index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <!-- 维修工单 -->
  2. <template>
  3. <div class="ele-body">
  4. <el-card shadow="never">
  5. <div class="filter-container">
  6. <seekPage
  7. :seekList="seekList"
  8. :formLength="3"
  9. @search="search"
  10. ></seekPage>
  11. </div>
  12. <ele-pro-table
  13. ref="table"
  14. :columns="columns"
  15. :datasource="datasource"
  16. :pageSize="20"
  17. >
  18. <!-- 操作列 -->
  19. <template v-slot:action="{ row }">
  20. <el-link
  21. v-if="row.orderStatus == 0"
  22. type="primary"
  23. :underline="false"
  24. icon="el-icon-edit"
  25. @click="handleNotice(row)"
  26. >
  27. 接收
  28. </el-link>
  29. <el-link
  30. v-if="row.orderStatus == 3 && row.requestUserId == $store.state.user.info.userId"
  31. type="primary"
  32. :underline="false"
  33. icon="el-icon-edit"
  34. @click="goDetail(row)"
  35. >
  36. 验收
  37. </el-link>
  38. <el-link
  39. v-if="
  40. row.orderStatus !== 3 &&
  41. row.orderStatus !== 0 &&
  42. row.orderStatus !== 4 &&
  43. $store.state.user.info.userId == row.executeUserId
  44. "
  45. type="primary"
  46. :underline="false"
  47. icon="el-icon-edit"
  48. @click="toSigningUpWork(row)"
  49. >
  50. 报工
  51. </el-link>
  52. <el-link
  53. v-if="
  54. row.orderStatus !== 3 &&
  55. row.orderStatus !== 4 &&
  56. $store.state.user.info.userId== row.executeUserId
  57. "
  58. type="primary"
  59. :underline="false"
  60. icon="el-icon-edit"
  61. @click="toRedeploy(row)"
  62. >
  63. 转派
  64. </el-link>
  65. <el-link
  66. type="primary"
  67. :underline="false"
  68. icon="el-icon-edit"
  69. @click="openDetail(row)"
  70. >
  71. 详情
  72. </el-link>
  73. </template>
  74. </ele-pro-table>
  75. </el-card>
  76. <!-- 验收 -->
  77. <RepairDetailsDialog ref="detailsDialogRef" @refesh="getData" />
  78. <!-- 非完成报工接收 注意事项-->
  79. <Notice ref="noticeShow" :repairInfo="repairInfo" @agree="agree" />
  80. <!-- 转派弹窗 -->
  81. <redeployOther ref="redeployOtherRef" @refresh="getData" />
  82. <!-- 报工弹框 -->
  83. <signingUpWork ref="signingUpWorkRef" @refresh="getData" />
  84. </div>
  85. </template>
  86. <script>
  87. import RepairDetailsDialog from '../components/RepairDetailsDialog.vue';
  88. import redeployOther from '../components/redeployOther.vue';
  89. import signingUpWork from '../components/signingUpWork.vue';
  90. import { workorderStatus, resultStatus } from '@/utils/dict/tickets';
  91. import {
  92. getWorkOrderList,
  93. getRule,
  94. startExecuting,
  95. getWorkOrderDetail
  96. } from '@/api/tickets';
  97. import pagenation from '@/components/Pagination';
  98. import Notice from '../components/notice.vue';
  99. // 修改
  100. import {
  101. notifyMessagePageAPI,
  102. updateNotifyMessageReadByIdAPI
  103. } from '@/api/bpm/task';
  104. import { mapGetters } from 'vuex';
  105. export default {
  106. components: {
  107. pagenation,
  108. redeployOther,
  109. signingUpWork,
  110. Notice,
  111. RepairDetailsDialog
  112. },
  113. data() {
  114. return {
  115. ruleNameList: [],
  116. userId: '',
  117. workorderStatus: [],
  118. resultStatus,
  119. repairInfo: {},
  120. //
  121. addOrEditDialogFlag: false,
  122. columns: [
  123. {
  124. columnKey: 'index',
  125. label: '序号',
  126. type: 'index',
  127. width: 60,
  128. align: 'center',
  129. showOverflowTooltip: true,
  130. fixed: 'left'
  131. },
  132. {
  133. prop: 'code',
  134. label: '工单编号',
  135. minWidth: '200',
  136. align: 'center',
  137. showOverflowTooltip: true
  138. },
  139. {
  140. prop: 'planCode',
  141. label: '计划单号',
  142. width: '200',
  143. align: 'center',
  144. showOverflowTooltip: true
  145. },
  146. {
  147. prop: 'planName',
  148. label: '维修名称',
  149. align: 'center',
  150. minWidth: '180',
  151. showOverflowTooltip: true
  152. },
  153. {
  154. prop: 'ruleName',
  155. label: '规则名称',
  156. align: 'center',
  157. minWidth: '180',
  158. showOverflowTooltip: true
  159. },
  160. {
  161. prop: 'equiCode',
  162. label: '设备编号',
  163. align: 'center',
  164. minWidth: '180',
  165. showOverflowTooltip: true
  166. },
  167. {
  168. prop: 'equiName',
  169. label: '设备名称',
  170. align: 'center',
  171. minWidth: '180',
  172. showOverflowTooltip: true
  173. },
  174. {
  175. prop: 'requestUserName',
  176. label: '报修人',
  177. align: 'center',
  178. minWidth: '180',
  179. showOverflowTooltip: true
  180. },
  181. {
  182. prop: 'executeUserName',
  183. label: '执行人',
  184. align: 'center',
  185. minWidth: '180',
  186. showOverflowTooltip: true
  187. },
  188. {
  189. prop: 'acceptTime',
  190. label: '开始时间',
  191. align: 'center',
  192. minWidth: '180',
  193. showOverflowTooltip: true
  194. },
  195. {
  196. prop: 'finishTime',
  197. label: '结束时间',
  198. align: 'center',
  199. minWidth: '180',
  200. showOverflowTooltip: true
  201. },
  202. {
  203. prop: 'planFinishTime',
  204. label: '计划完成时间',
  205. align: 'center',
  206. minWidth: '180',
  207. showOverflowTooltip: true
  208. },
  209. {
  210. prop: 'acceptanceStatus',
  211. label: '执行结果',
  212. align: 'center',
  213. showOverflowTooltip: true,
  214. formatter: (_row, _column, cellValue) => {
  215. return _row.acceptanceStatus
  216. ? resultStatus.filter(
  217. (item) => item.code == _row.acceptanceStatus
  218. )[0].label
  219. : '';
  220. }
  221. },
  222. {
  223. prop: 'orderStatus',
  224. label: '状态',
  225. align: 'center',
  226. showOverflowTooltip: true,
  227. formatter: (_row, _column, cellValue) => {
  228. return workorderStatus.filter(
  229. (item) => item.id == _row.orderStatus
  230. )[0]?.label;
  231. }
  232. },
  233. {
  234. prop: 'practicalTime',
  235. label: '实际工时',
  236. align: 'center',
  237. showOverflowTooltip: true,
  238. formatter: (_row, _column, cellValue) => {
  239. let _this = this;
  240. return _this.time_interval(_row.acceptTime, _row.finishTime);
  241. }
  242. },
  243. {
  244. columnKey: 'action',
  245. label: '操作',
  246. minWidth: 250,
  247. align: 'center',
  248. slot: 'action',
  249. fixed: 'right'
  250. }
  251. ],
  252. searchForm: {
  253. code: '',
  254. status: '',
  255. ruleId: '',
  256. date: '',
  257. startTime: '',
  258. endTime: '',
  259. executeUserId: '',
  260. statusType: 0,
  261. type: 3,
  262. isQueryTodo: 1,
  263. executeUserId: ''
  264. },
  265. tableData: [],
  266. size: 20,
  267. page: 1,
  268. total: 0
  269. };
  270. },
  271. computed: {
  272. ...mapGetters(['user']),
  273. // 是否开启响应式布局
  274. styleResponsive() {
  275. return this.$store.state.theme.styleResponsive;
  276. },
  277. seekList() {
  278. return [
  279. {
  280. label: '工单编号',
  281. value: 'code',
  282. type: 'input',
  283. placeholder: ' '
  284. },
  285. {
  286. label: '规则名称:',
  287. value: 'ruleId',
  288. type: 'select',
  289. placeholder: ' ',
  290. planList: this.ruleNameList.map((item) => {
  291. return { label: item.name, value: item.id };
  292. })
  293. },
  294. {
  295. label: '状态',
  296. value: 'status',
  297. type: 'select',
  298. planList: workorderStatus.map((item) => {
  299. return { label: item.label, value: item.id };
  300. }),
  301. placeholder: ' '
  302. },
  303. {
  304. label: '创建时间',
  305. value: 'createTime',
  306. type: 'date',
  307. dateType: 'datetimerange',
  308. placeholder: '',
  309. width: 380,
  310. labelWidth: '130px',
  311. valueAr: ['startTime', 'endTime']
  312. }
  313. ];
  314. }
  315. },
  316. methods: {
  317. //新增或修改模板
  318. async handleAddOrEdit(row) {
  319. await updateNotifyMessageReadByIdAPI([row.id]);
  320. this.$refs.table.reload();
  321. },
  322. search(e) {
  323. this.searchForm = e;
  324. this.$refs.table.reload({ page: 1, where: e });
  325. },
  326. // 获取table数据
  327. async datasource({ page, where, limit, ...row }) {
  328. const res = await getWorkOrderList({
  329. ...where,
  330. pageNum: page,
  331. size: limit,
  332. executeUserId: this.userId,
  333. userId: this.user.info.userId,
  334. type: 3,
  335. isQueryTodo: 1,
  336. statusType: 1
  337. });
  338. this.total = res.total;
  339. this.$emit('recount');
  340. return res;
  341. },
  342. // 获取规则名列表(设备维修)
  343. async getRuleNameList() {
  344. const res = await getRule({
  345. status: 1,
  346. type: 3,
  347. pageNum: 1,
  348. size: -1
  349. });
  350. if (res.list) {
  351. this.ruleNameList = res.list || [];
  352. }
  353. },
  354. async handleNotice(row) {
  355. this.id = row.id;
  356. const res = await getWorkOrderDetail(row.code);
  357. console.log(res, 'resresresresres');
  358. this.repairInfo = res.repairRequestResponse;
  359. this.$refs.noticeShow.open(row);
  360. },
  361. agree() {
  362. this.$refs.noticeShow.close();
  363. this.handleExecute();
  364. },
  365. // 执行工单
  366. handleExecute() {
  367. startExecuting({
  368. id: this.id
  369. }).then(() => {
  370. this.reload();
  371. });
  372. },
  373. // 验收
  374. goDetail(row) {
  375. row.title = '工单详情';
  376. row.tabLabel = '工单信息';
  377. this.$refs.detailsDialogRef.init(row);
  378. },
  379. // 转派
  380. toRedeploy(row) {
  381. this.$refs.redeployOtherRef.open(row);
  382. },
  383. // 报工
  384. toSigningUpWork(row) {
  385. this.$refs.signingUpWorkRef.open(row);
  386. },
  387. openDetail(row) {
  388. row.title = '工单详情';
  389. row.tabLabel = '工单信息';
  390. this.$refs.detailsDialogRef.init(row, true);
  391. },
  392. getData() {
  393. this.search(this.searchForm);
  394. },
  395. // 计算实际工时
  396. time_interval(dt1, dt2) {
  397. if (!dt1 || !dt2) {
  398. return '';
  399. }
  400. if (typeof dt1 == 'string') {
  401. dt1 = new Date(dt1.replace(/-/, '/'));
  402. dt2 = new Date(dt2.replace(/-/, '/'));
  403. }
  404. var res = dt2 - dt1;
  405. if (isNaN(res)) throw Error('invalid dates arguments');
  406. let re = res / (1000 * 60 * 60);
  407. var h = parseInt(re);
  408. var m = parseInt((re - h) * 60);
  409. let result = '';
  410. if (h) {
  411. result += `${h} 小时`;
  412. }
  413. if (m) {
  414. result += `${m} 分钟`;
  415. }
  416. return result;
  417. },
  418. changeDate(val) {
  419. if (val === null) {
  420. this.searchForm.startTime = '';
  421. this.searchForm.endTime = '';
  422. return;
  423. }
  424. this.searchForm.startTime = val[0];
  425. this.searchForm.endTime = val[1];
  426. }
  427. },
  428. created() {
  429. this.userId = localStorage.getItem('userId');
  430. this.searchForm.executeUserId = this.userId;
  431. this.getRuleNameList();
  432. this.workorderStatus = workorderStatus.filter((item) => {
  433. return [0, 2, 3].includes(item.id);
  434. });
  435. }
  436. };
  437. </script>
  438. <style lang="scss" scoped>
  439. // 步骤条边线显示
  440. // ::v-deep .el-step__head.is-process .el-step__icon.is-text {
  441. // border: none !important;
  442. // background: none !important;
  443. // }
  444. // ::v-deep .el-step:last-of-type .el-step__line {
  445. // display: block !important;
  446. // width: 3px !important;
  447. // }
  448. // ::v-deep .el-steps:last-child .el-step__line {
  449. // display: none !important;
  450. // }
  451. // .patrolInspection {
  452. // height: 100%;
  453. // width: 100%;
  454. // display: flex;
  455. // flex-direction: column;
  456. // .search {
  457. // flex: 0 0 50px;
  458. // }
  459. // .table {
  460. // flex: 1;
  461. // .el-table {
  462. // width: 100%;
  463. // display: flex;
  464. // flex-direction: column;
  465. // }
  466. // }
  467. // .table-footer {
  468. // flex: 0 0 30px;
  469. // display: flex;
  470. // justify-content: flex-end;
  471. // }
  472. // }
  473. // 修改
  474. // ::v-deep .el-card__body {
  475. // padding: 0;
  476. // }
  477. // .app-container {
  478. // background: #f0f3f3;
  479. // min-height: calc(100vh - 84px);
  480. // }
  481. // .zw-page-table {
  482. // background: #ffffff;
  483. // padding-top: 20px;
  484. // }
  485. // .pagination-wrap {
  486. // display: flex;
  487. // justify-content: flex-end;
  488. // padding: 10px 0;
  489. // }
  490. // .table {
  491. // width: 100%;
  492. // margin-top: 10px;
  493. // }
  494. </style>