pendingOrder.uvue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. <template>
  2. <uni-navbar-lite :showLeft=true title="待处理工单"></uni-navbar-lite>
  3. <view class="list-page">
  4. <!-- 搜索栏 -->
  5. <view class="search-bar">
  6. <view class="search-box">
  7. <image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
  8. <input class="search-input" type="text" placeholder="搜索工单编码、风机编号" v-model="keyword" @confirm="handleSearch" @blur="handleSearch" />
  9. <text v-if="keyword.length > 0" class="clear-icon" @click="clearSearch">✕</text>
  10. </view>
  11. </view>
  12. <!-- 列表内容 -->
  13. <common-list
  14. :dataList="dataList"
  15. :loading="loading"
  16. :refreshing="refreshing"
  17. :hasMore="hasMore"
  18. @refresh="handleRefresh"
  19. @loadMore="loadMore"
  20. @itemClick="handleView"
  21. >
  22. <template #default="{ item, index }">
  23. <view class="list-item">
  24. <view class="item-container">
  25. <view class="item-header">
  26. <text class="item-title">{{ getWorkOrderProjectNo(item) }}-{{ (item as acceptOrderInfoExtend).pcsStationName }}{{ getPcsDeviceName(item) }}{{ getOrderType(item) }}</text>
  27. <text class="status-tag" :class="getStatusClass(item)">{{ getWorkOrderStatus(item) }}</text>
  28. </view>
  29. <view class="info-row">
  30. <view class="info-label">
  31. <text class="text-gray">{{ getDisplayTime(item) }}</text>
  32. </view>
  33. </view>
  34. <view class="btn-group">
  35. <view
  36. v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'accept')"
  37. class="btn-primary info-value"
  38. @click.stop="handleItemClick(item,'')"
  39. >
  40. <text class="btn-text">接单</text>
  41. </view>
  42. <view
  43. v-if="(getOrderStatus(item) == 'assigned' || getOrderStatus(item) == 'to_finish')
  44. && canHandleOrder(item,'shutdown') && (item as acceptOrderInfoExtend).pauseTime == null"
  45. class="btn-primary info-value"
  46. @click.stop="handleItemClick(item,'shutdown')"
  47. >
  48. <text class="btn-text">停机</text>
  49. </view>
  50. <view
  51. v-if="getOrderStatus(item) == 'to_approve' && canHandleOrder(item,'')"
  52. class="btn-primary info-value"
  53. @click.stop="handleItemClick(item,'')"
  54. >
  55. <text class="btn-text">审批</text>
  56. </view>
  57. <view
  58. v-if="getOrderStatus(item) == 'suspended' && canHandleOrder(item,'')"
  59. class="btn-primary info-value"
  60. @click.stop="handleItemClick(item,'')"
  61. >
  62. <text class="btn-text">恢复</text>
  63. </view>
  64. <view
  65. v-if="getOrderStatus(item) == 'return' && canHandleOrder(item,'acceptReturn')"
  66. class="btn-primary info-value"
  67. @click.stop="handleItemClick(item,'acceptReturn')"
  68. >
  69. <text class="btn-text">退回</text>
  70. </view>
  71. <view
  72. v-if="getOrderStatus(item) == 'assigned' && canHandleOrder(item,'acceptReturn')"
  73. class="btn-primary info-value"
  74. @click.stop="handleItemClick(item,'acceptReturn')"
  75. >
  76. <text class="btn-text">退回</text>
  77. </view>
  78. <!-- <view
  79. v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'return')"
  80. class="btn-primary info-value"
  81. @click.stop="handleItemClick(item, 'return')"
  82. >
  83. <text class="btn-text">退回</text>
  84. </view> -->
  85. <view
  86. v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'suspend')"
  87. class="btn-primary info-value"
  88. @click.stop="handleItemClick(item, 'suspend')"
  89. >
  90. <text class="btn-text">挂起</text>
  91. </view>
  92. <view
  93. v-if="getOrderStatus(item) == 'to_finish' && canHandleOrder(item, 'finalize')"
  94. class="btn-primary info-value"
  95. @click.stop="handleItemClick(item, 'finalize')"
  96. >
  97. <text class="btn-text">复启</text>
  98. </view>
  99. </view>
  100. </view>
  101. </view>
  102. </template>
  103. </common-list>
  104. </view>
  105. </template>
  106. <script setup lang="uts">
  107. import { ref, onBeforeUnmount, onMounted } from 'vue'
  108. import type { SysDictData } from '../../types/dict'
  109. import { pendingList } from '../../api/order/list'
  110. import { getDictDataByType } from '../../api/dict/index'
  111. import {checkPermi, getUserInfo} from '../../utils/storage'
  112. type acceptOrderInfoExtend = {
  113. orderType: Number
  114. id: Number
  115. teamLeaderId: Number
  116. acceptUserId: Number
  117. teamLeaderName: string | null
  118. acceptUserName: string | null
  119. acceptTime: string | null
  120. assignTime: string | null
  121. assignUserName: string | null
  122. status: Number
  123. workOrderProjectNo: string | null
  124. workOrderStatus: string | null
  125. gxtCenterId: Number
  126. gxtCenter: string | null
  127. pcsStationId: Number
  128. pcsStationName: string | null
  129. pcsDeviceId: Number
  130. pcsDeviceName: string | null
  131. brand: string | null
  132. model: string | null
  133. createTime: string | null
  134. suspendReason: string | null
  135. rejectionReason: string | null
  136. updateTime: string | null
  137. workEndTime: string | null
  138. orderEntryType: string | null
  139. pauseTime: string | null
  140. }
  141. const userId = ref<string>("")
  142. const roles = ref<string>('')
  143. // 列表数据
  144. const dataList = ref<acceptOrderInfoExtend[]>([])
  145. let keyword = ref<string>("")
  146. const page = ref<number>(1)
  147. const pageSize: number = 10
  148. const hasMore = ref<boolean>(true)
  149. const loading = ref<boolean>(false)
  150. const refreshing = ref<boolean>(false)
  151. const total = ref<number>(0)
  152. const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
  153. // 添加字典加载状态
  154. const dictLoaded = ref<boolean>(false)
  155. // 添加防重复请求的标志位
  156. const isSearching = ref<boolean>(false)
  157. // 添加防重复刷新的标志
  158. const isRefreshing = ref<boolean>(false)
  159. // 添加刷新时间戳,用于防抖
  160. const lastRefreshTime = ref<number>(0)
  161. const getOrderStatus = (item: any | null): string => {
  162. if (item == null) return ''
  163. const orderItem = item as acceptOrderInfoExtend
  164. return orderItem.workOrderStatus ?? ''
  165. }
  166. // 方法:判断当前工单是否显示操作按钮(基于 orderType)
  167. const canHandleOrder = (item: any | null, buttonType: string | ''): boolean => {
  168. if (item == null) return false
  169. let permit: string[] = []
  170. const orderItem = item as acceptOrderInfoExtend
  171. if(orderItem.workOrderStatus == 'assigned') {
  172. if(buttonType != '' && buttonType == "acceptReturn" && orderItem.orderType == 1) {
  173. // 接单退回
  174. permit = ['gxt:repairOrder:acceptReturn']
  175. } else if(buttonType != '' && buttonType == "accept") {
  176. // 接单
  177. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:accept'] : ['gxt:repairOrder:accept']
  178. } else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
  179. permit = ['gxt:maintenance:order:shutdown']
  180. }
  181. } else if(orderItem.workOrderStatus == 'to_finish') {
  182. if(buttonType != '' && buttonType == "suspend" && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
  183. // 挂起
  184. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:suspend'] : ['gxt:repairOrder:suspend']
  185. } else if(buttonType != '' && buttonType == "return" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
  186. // 退回
  187. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:return'] : ['gxt:repairOrder:return']
  188. } else if(buttonType != '' && buttonType == "finalize" && orderItem.orderType == 1 && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
  189. // 复启
  190. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
  191. } else if(buttonType != '' && buttonType == "shutdown" && orderItem.orderType == 2) {
  192. permit = ['gxt:maintenance:order:shutdown']
  193. }
  194. } else if(orderItem.workOrderStatus == 'to_approve') {
  195. // 审批
  196. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:approve'] : ['gxt:repairOrder:approve']
  197. } else if(orderItem.workOrderStatus == 'suspended' && (orderItem.teamLeaderId == parseInt(userId.value) || roles.value.includes("管理员"))) {
  198. // 恢复
  199. permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:resume'] : ['gxt:repairOrder:resume']
  200. } else if(orderItem.workOrderStatus == 'return') {
  201. // 接单退回
  202. permit = ['gxt:repairOrder:acceptReturn']
  203. }
  204. else {
  205. return false
  206. }
  207. // const orderType = (item as acceptOrderInfoExtend).orderType
  208. return checkPermi(permit)
  209. }
  210. // 获取工单状态字典列表
  211. const loadStatusDictList = async (): Promise<void> => {
  212. try {
  213. const result = await getDictDataByType('gxt_work_order_status')
  214. const resultObj = result as UTSJSONObject
  215. if (resultObj['code'] == 200) {
  216. const data = resultObj['data'] as any[]
  217. const dictData: SysDictData[] = []
  218. if (data.length > 0) {
  219. for (let i = 0; i < data.length; i++) {
  220. const item = data[i] as UTSJSONObject
  221. // 只提取需要的字段
  222. const dictItem: SysDictData = {
  223. dictValue: item['dictValue'] as string | null,
  224. dictLabel: item['dictLabel'] as string | null,
  225. dictCode: null,
  226. dictSort: null,
  227. dictType: null,
  228. cssClass: null,
  229. listClass: null,
  230. isDefault: null,
  231. status: null,
  232. default: null,
  233. createTime: null,
  234. remark: null
  235. }
  236. dictData.push(dictItem)
  237. }
  238. }
  239. statusDictList.value = dictData
  240. dictLoaded.value = true
  241. }
  242. } catch (e: any) {
  243. console.error('获取工单状态字典失败:', e.message)
  244. dictLoaded.value = true
  245. }
  246. }
  247. // 加载列表数据
  248. const loadData = async (isRefresh: boolean | null, disablePullDown: boolean | null): Promise<void> => {
  249. // 防止重复请求的核心机制
  250. if (loading.value) {
  251. // 确保刷新状态最终被重置,防止卡死
  252. if (isRefresh != true) {
  253. refreshing.value = false;
  254. }
  255. return
  256. }
  257. const shouldRefresh = isRefresh != null ? isRefresh : false
  258. const disablePull = disablePullDown != null ? disablePullDown : false
  259. loading.value = true
  260. let refreshTimeout: number | null = null;
  261. if (shouldRefresh && !disablePull) {
  262. page.value = 1
  263. refreshing.value = true
  264. // 添加超时机制,确保刷新动画不会一直显示
  265. refreshTimeout = setTimeout(() => {
  266. if (refreshing.value) {
  267. refreshing.value = false;
  268. isRefreshing.value = false;
  269. console.log("刷新超时,强制结束刷新状态");
  270. uni.showToast({
  271. title: '刷新超时',
  272. icon: 'none'
  273. });
  274. }
  275. }, 10000); // 10秒超时
  276. } else if (shouldRefresh && disablePull) {
  277. // 状态切换时,重置页码但不触发动画
  278. page.value = 1
  279. // 即使禁用下拉刷新,也要确保刷新状态最终被重置
  280. refreshing.value = false
  281. } else {
  282. // 对于加载更多操作,不需要显示下拉刷新状态
  283. refreshing.value = false;
  284. }
  285. try {
  286. // 处理默认值
  287. const searchKeyword = keyword.value.length > 0 ? keyword.value : null
  288. const result = await pendingList(page.value, pageSize, searchKeyword)
  289. // 提取响应数据
  290. const resultObj = result as UTSJSONObject
  291. const code = resultObj['code'] as number
  292. const responseData = resultObj['rows'] as any[]
  293. const responseTotal = resultObj['total'] as number
  294. if (code == 200) {
  295. // 将 any[] 转换为 acceptOrderInfoExtend[]
  296. const newData: acceptOrderInfoExtend[] = []
  297. for (let i = 0; i < responseData.length; i++) {
  298. const item = responseData[i] as UTSJSONObject
  299. const orderItem: acceptOrderInfoExtend = {
  300. orderType: item['orderType'] as Number,
  301. id: item['id'] as Number,
  302. teamLeaderId: item['teamLeaderId'] != null ? (item['teamLeaderId'] as Number) : 0,
  303. acceptUserId: item['acceptUserId'] != null ? (item['acceptUserId'] as Number) : 0,
  304. teamLeaderName: item['teamLeaderName'] as string | null,
  305. acceptUserName: item['acceptUserName'] as string | null,
  306. acceptTime: item['acceptTime'] as string | null,
  307. assignTime: item['assignTime'] as string | null,
  308. assignUserName: item['assignUserName'] as string | null,
  309. status: (item['status']==null)?0:item['status'] as Number,
  310. workOrderProjectNo: item['workOrderProjectNo'] as string | null,
  311. workOrderStatus: item['workOrderStatus'] as string | null,
  312. gxtCenterId: item['gxtCenterId'] as Number | 0,
  313. gxtCenter: item['gxtCenter'] as string | null,
  314. pcsStationId: item['pcsStationId'] as Number | 0,
  315. pcsStationName: item['pcsStationName'] as string | null,
  316. pcsDeviceId: item['pcsDeviceId'] as Number | 0,
  317. pcsDeviceName: item['pcsDeviceName'] as string | null,
  318. brand: item['brand'] as string | null,
  319. model: item['model'] as string | null,
  320. createTime: item['createTime'] as string | null,
  321. suspendReason: item['suspendReason'] as string | null,
  322. rejectionReason: item['rejectionReason'] as string | null,
  323. updateTime: item['updateTime'] as string | null, // 新增字段
  324. workEndTime: item['workEndTime'] as string | null, // 新增字段
  325. pauseTime: item['pauseTime'] as string | null
  326. }
  327. newData.push(orderItem)
  328. }
  329. if (shouldRefresh) {
  330. dataList.value = newData
  331. } else {
  332. dataList.value = [...dataList.value, ...newData]
  333. }
  334. total.value = responseTotal
  335. hasMore.value = dataList.value.length < responseTotal
  336. } else {
  337. const msg = resultObj['msg'] as string | null
  338. uni.showToast({
  339. title: msg ?? '加载失败',
  340. icon: 'none'
  341. })
  342. }
  343. } catch (e: any) {
  344. uni.showToast({
  345. title: e.message ?? '加载失败',
  346. icon: 'none'
  347. })
  348. } finally {
  349. loading.value = false
  350. // 清除超时定时器
  351. if (refreshTimeout != null) {
  352. clearTimeout(refreshTimeout);
  353. }
  354. // 确保刷新状态能结束
  355. if (shouldRefresh) {
  356. refreshing.value = false;
  357. // 使用setTimeout确保状态彻底重置
  358. setTimeout(() => {
  359. isRefreshing.value = false;
  360. refreshing.value = false; // 再次确保刷新状态被重置
  361. }, 50);
  362. }
  363. }
  364. }
  365. // 辅助函数:从 any 类型提取属性
  366. const getOrderType = (item: any | null): string => {
  367. if (item == null) return ''
  368. const orderInfoItem = item as acceptOrderInfoExtend
  369. return orderInfoItem.orderType == 1?"维修工单":"维保工单";
  370. }
  371. const getWorkOrderProjectNo = (item: any | null): string | null => {
  372. if (item == null) return ''
  373. const orderInfoItem = item as acceptOrderInfoExtend
  374. return orderInfoItem.workOrderProjectNo
  375. }
  376. const getPcsDeviceName = (item: any | null): string | null=> {
  377. if (item == null) return ''
  378. const orderInfoItem = item as acceptOrderInfoExtend
  379. return orderInfoItem.pcsDeviceName
  380. }
  381. // 根据状态显示不同的时间
  382. const getDisplayTime = (item: any | null): string|null => {
  383. if (item == null) return null
  384. const orderInfoItem = item as acceptOrderInfoExtend
  385. // 如果是"待接单"状态,显示派单时间
  386. if (orderInfoItem.workOrderStatus == 'assigned') {
  387. return '下发时间:' + orderInfoItem.assignTime
  388. } else if(orderInfoItem.workOrderStatus == 'to_finish') {
  389. if(orderInfoItem.workEndTime != null) {
  390. return '结束时间:' + orderInfoItem.workEndTime
  391. }
  392. return '接单时间:' + orderInfoItem.acceptTime
  393. } else if(orderInfoItem.workOrderStatus == 'to_approve') {
  394. return '申请挂起时间:' + orderInfoItem.updateTime
  395. } else if(orderInfoItem.workOrderStatus == 'suspended') {
  396. return '审批通过时间:' + orderInfoItem.updateTime
  397. } else if(orderInfoItem.workOrderStatus == 'return' || orderInfoItem.workOrderStatus == 'accept_return') {
  398. return '退回时间:' + orderInfoItem.updateTime
  399. } else if(orderInfoItem.workOrderStatus == 'completed') {
  400. return '结单时间:' + orderInfoItem.updateTime
  401. }
  402. // 默认显示创建时间
  403. return '创建时间:' + orderInfoItem.createTime
  404. }
  405. const getWorkOrderStatus = (item: any | null): string | null => {
  406. if (item == null) return ''
  407. const orderInfoItem = item as acceptOrderInfoExtend
  408. const rawStatus = orderInfoItem.workOrderStatus
  409. if (rawStatus==null) return ''
  410. // 如果字典尚未加载,返回原始值
  411. if (!dictLoaded.value) {
  412. return rawStatus
  413. }
  414. // 查找字典中对应的标签
  415. const dictItem = statusDictList.value.find(dict => dict.dictValue == rawStatus)
  416. return dictItem!=null ? dictItem.dictLabel : rawStatus
  417. }
  418. const getStatusClass = (item: any | null): string => {
  419. if (item == null) return ''
  420. const orderInfoItem = item as acceptOrderInfoExtend
  421. const rawStatus = orderInfoItem.workOrderStatus
  422. if (rawStatus==null) return ''
  423. // const status = rawStatus
  424. // 返回对应的状态类名
  425. return `status-${rawStatus}`
  426. }
  427. // 下拉刷新
  428. const handleRefresh = async (): Promise<void> => {
  429. console.log("handleRefresh被触发")
  430. console.log("loading.value===",loading.value)
  431. console.log("isRefreshing.value===",isRefreshing.value)
  432. // 防抖处理,避免频繁触发
  433. const now = Date.now();
  434. if (now - lastRefreshTime.value < 1000) {
  435. console.log("刷新操作过于频繁,忽略本次触发");
  436. refreshing.value = false;
  437. return;
  438. }
  439. lastRefreshTime.value = now;
  440. // 添加防重复调用检查
  441. if (loading.value || isRefreshing.value) {
  442. // 如果已经在加载或正在刷新,直接重置刷新状态
  443. refreshing.value = false;
  444. return;
  445. }
  446. console.log("loading.value1===",loading.value)
  447. console.log("isRefreshing.value1===",isRefreshing.value)
  448. // 设置刷新标志
  449. isRefreshing.value = true;
  450. refreshing.value = true; // 确保刷新状态被设置
  451. // 添加超时机制,确保刷新动画不会一直显示
  452. const refreshTimeout = setTimeout(() => {
  453. if (refreshing.value || isRefreshing.value) {
  454. refreshing.value = false;
  455. isRefreshing.value = false;
  456. console.log("刷新操作超时,重置刷新状态");
  457. uni.showToast({
  458. title: '刷新超时',
  459. icon: 'none'
  460. });
  461. }
  462. }, 10000);
  463. try {
  464. await loadData(true, false); // 使用默认的下拉刷新行为
  465. } catch (error) {
  466. console.error('刷新失败:', error);
  467. refreshing.value = false;
  468. isRefreshing.value = false;
  469. } finally {
  470. clearTimeout(refreshTimeout);
  471. // 确保刷新状态最终被重置
  472. refreshing.value = false;
  473. isRefreshing.value = false;
  474. }
  475. // 额外的保险机制,确保在一定时间后重置刷新标志
  476. setTimeout(() => {
  477. refreshing.value = false;
  478. isRefreshing.value = false;
  479. }, 200) // 延迟重置,确保状态完全更新
  480. }
  481. // 加载更多
  482. const loadMore = (): void => {
  483. if (!hasMore.value || loading.value) {
  484. return
  485. }
  486. page.value++
  487. loadData(false, false) // 加载更多时不涉及下拉刷新动画
  488. }
  489. // 搜索
  490. const handleSearch = (): void => {
  491. // 添加防重复调用检查
  492. if (loading.value) {
  493. return;
  494. }
  495. // 添加防重复请求检查
  496. if (isSearching.value) {
  497. return
  498. }
  499. isSearching.value = true
  500. page.value = 1
  501. loadData(true, true) // 状态切换时禁用下拉刷新动画
  502. // 延迟重置标志位,确保请求发送后才允许下一次搜索
  503. setTimeout(() => {
  504. isSearching.value = false
  505. }, 100)
  506. }
  507. // 点击列表查看
  508. const handleView = (item: any | null): void => {
  509. if (item == null) return
  510. const orderItem = item as acceptOrderInfoExtend
  511. uni.navigateTo({
  512. url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
  513. })
  514. }
  515. // 点击列表项
  516. const handleItemClick = (item: any | null, buttonType: string | ''): void => {
  517. if (item == null) return
  518. const orderItem = item as acceptOrderInfoExtend
  519. if(orderItem.workOrderStatus == 'assigned') {
  520. if(buttonType != '' && buttonType == "acceptReturn") {
  521. // 跳转到退回页面
  522. uni.navigateTo({
  523. url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  524. })
  525. } else if(buttonType != '' && buttonType == "shutdown") {
  526. // 跳转到停机页面
  527. uni.navigateTo({
  528. url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  529. })
  530. } else {
  531. // 跳转到接单页面
  532. uni.navigateTo({
  533. url: `/pages/order/detail/acceptIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  534. })
  535. }
  536. } else if(orderItem.workOrderStatus == 'to_finish') {
  537. if(buttonType != '' && buttonType == "suspend") {
  538. // 跳转到待结单页面
  539. uni.navigateTo({
  540. url: `/pages/order/detail/suspendIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  541. })
  542. } else if(buttonType != '' && buttonType == "return") {
  543. // 跳转到退回页面
  544. uni.navigateTo({
  545. url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  546. })
  547. } else if(buttonType != '' && buttonType == "finalize") {
  548. // 跳转到复启页面
  549. uni.navigateTo({
  550. url: `/pages/order/detail/resetIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  551. })
  552. } else if(buttonType != '' && buttonType == "shutdown") {
  553. // 跳转到停机页面
  554. uni.navigateTo({
  555. url: `/pages/order/detail/shutdownIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  556. })
  557. }
  558. } else if(orderItem.workOrderStatus == 'to_approve') {
  559. // 跳转到待审批页面
  560. uni.navigateTo({
  561. url: `/pages/order/detail/approveIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  562. })
  563. } else if(orderItem.workOrderStatus == 'suspended') {
  564. // 跳转到恢复页面
  565. uni.navigateTo({
  566. url: `/pages/order/detail/resumeIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  567. })
  568. } else if(orderItem.workOrderStatus == 'return') {
  569. // 跳转到退回页面
  570. uni.navigateTo({
  571. url: `/pages/order/detail/returnIndex?id=${orderItem.id}&orderType=${orderItem.orderType}`
  572. })
  573. } else {
  574. uni.navigateTo({
  575. url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
  576. })
  577. }
  578. }
  579. // 清空搜索
  580. const clearSearch = (): void => {
  581. // 添加防重复调用检查
  582. if (loading.value) {
  583. return;
  584. }
  585. // 添加防重复请求检查
  586. if (isSearching.value) {
  587. return
  588. }
  589. isSearching.value = true
  590. keyword.value = ""
  591. page.value = 1
  592. loadData(true, true) // 状态切换时禁用下拉刷新动画
  593. // 延迟重置标志位,确保请求发送后才允许下一次搜索
  594. setTimeout(() => {
  595. isSearching.value = false
  596. }, 100)
  597. }
  598. // 初始化
  599. onMounted(() => {
  600. const userInfo = getUserInfo()
  601. if (userInfo != null) {
  602. const userIdStr = userInfo['userId'].toString()
  603. userId.value = userIdStr
  604. roles.value = userInfo['roleNames'].toString()
  605. }
  606. loadStatusDictList()
  607. loadData(true, false)
  608. // 监听接单成功的事件,刷新列表
  609. uni.$on('refreshOrderList', () => {
  610. page.value = 1
  611. loadData(true, false)
  612. })
  613. })
  614. // 组件卸载前清理事件监听
  615. onBeforeUnmount(() => {
  616. // 确保所有状态都被重置
  617. refreshing.value = false
  618. loading.value = false
  619. isRefreshing.value = false
  620. // 移除事件监听
  621. uni.$off('refreshOrderList',{})
  622. })
  623. </script>
  624. <style lang="scss">
  625. .list-page {
  626. flex: 1;
  627. background-color: #e8f0f9;
  628. }
  629. .search-bar {
  630. padding: 20rpx 30rpx;
  631. background-color: #d7eafe;
  632. }
  633. .search-box {
  634. flex-direction: row;
  635. align-items: center;
  636. height: 72rpx;
  637. padding: 0 24rpx;
  638. background-color: #f5f5f5;
  639. border-radius: 36rpx;
  640. .search-icon {
  641. width: 32rpx;
  642. height: 32rpx;
  643. margin-right: 12rpx;
  644. }
  645. .search-input {
  646. flex: 1;
  647. font-size: 28rpx;
  648. color: #333333;
  649. }
  650. .clear-icon {
  651. margin-left: 12rpx;
  652. font-size: 28rpx;
  653. color: #999999;
  654. }
  655. }
  656. .list-item {
  657. margin: 24rpx 30rpx;
  658. background-color: #ffffff;
  659. border-radius: 16rpx;
  660. }
  661. .item-container {
  662. padding: 30rpx;
  663. }
  664. .item-header {
  665. flex-direction: row;
  666. align-items: flex-start;
  667. margin-bottom: 16rpx;
  668. justify-content: space-between;
  669. min-height: 55rpx;
  670. .item-title {
  671. font-size: 30rpx;
  672. color: #333333;
  673. font-weight: bold;
  674. flex-wrap: wrap;
  675. flex: 0 1 75%;
  676. min-width: 0;
  677. }
  678. .info-value {
  679. font-size: 28rpx;
  680. color: #999999;
  681. margin-left: auto;
  682. flex: 0 0 auto;
  683. white-space: nowrap;
  684. }
  685. }
  686. .info-row {
  687. flex-direction: row;
  688. justify-content: space-between;
  689. align-items: center;
  690. .info-label {
  691. font-size: 26rpx;
  692. color: #666;
  693. }
  694. .info-value {
  695. font-size: 26rpx;
  696. }
  697. }
  698. .text-gray{
  699. font-size: 26rpx;
  700. color: #666;
  701. }
  702. .status-tag {
  703. padding: 8rpx 20rpx;
  704. border-radius: 20rpx;
  705. font-size: 24rpx;
  706. white-space: nowrap;
  707. // margin-left: 20rpx;
  708. border: 1rpx solid;
  709. }
  710. /* 待接单 */
  711. .status-assigned {
  712. background-color: #ebf5ff;
  713. color: #409eff;
  714. border-color: #d8ebff;
  715. }
  716. /* 待结单 */
  717. .status-to_finish {
  718. background-color: #fff7e6;
  719. color: #fa8c16;
  720. border-color: #ffd591;
  721. }
  722. /* 待审批 */
  723. .status-to_approve {
  724. background-color: #fff7e6;
  725. color: #fa8c16;
  726. border-color: #ffd591;
  727. }
  728. /* 已挂起 */
  729. .status-suspended {
  730. background-color: #fff2f0;
  731. color: #ff4d4f;
  732. border-color: #ffccc7;
  733. }
  734. /* 已完成 */
  735. .status-completed {
  736. background-color: #f0f9eb;
  737. color: #5cb87a;
  738. border-color: #c2e7b0;
  739. }
  740. /* 待下发 */
  741. .status-to_issue {
  742. background-color: #f4f4f5;
  743. color: #909399;
  744. border-color: #e9e9eb;
  745. }
  746. /* 已归档 */
  747. .status-archived {
  748. background-color: #f0f9eb;
  749. color: #5cb87a;
  750. border-color: #c2e7b0;
  751. }
  752. /* 退回 */
  753. .status-return {
  754. background-color: #fff2f0;
  755. color: #ff4d4f;
  756. border-color: #ffccc7;
  757. }
  758. /* 退回 */
  759. .status-accept_return {
  760. background-color: #fff2f0;
  761. color: #ff4d4f;
  762. border-color: #ffccc7;
  763. }
  764. .btn-primary {
  765. z-index: 999;
  766. border-radius: 10rpx;
  767. font-size: 24rpx;
  768. // white-space: nowrap;
  769. margin-left: 20rpx;
  770. background-color: #165DFF;
  771. line-height: 45rpx;
  772. color: #ffffff;
  773. .btn-text{
  774. color: #ffffff;
  775. font-size: 24rpx;
  776. padding: 5px 15px;
  777. }
  778. }
  779. .btn-group {
  780. flex-direction: row;
  781. align-items: center;
  782. justify-content: flex-end;
  783. margin-top: 20rpx;
  784. }
  785. // /* 超时 */
  786. // .status-overdue {
  787. // background-color: #fff2f0;
  788. // color: #ff4d4f;
  789. // border-color: #ffccc7;
  790. // }
  791. </style>