index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. <template>
  2. <view class="mainBox">
  3. <uni-nav-bar background-color="#157A2C" color="#fff" fixed="true" statusBar="true" left-icon="back" title="售后工单"
  4. @clickLeft="back">
  5. </uni-nav-bar>
  6. <view class="top-wrapper">
  7. <uni-section>
  8. <uni-easyinput @clear="clearSearch" prefixIcon="search" style="width: 460rpx" v-model="searchVal"
  9. placeholder="名称">
  10. </uni-easyinput>
  11. </uni-section>
  12. <button class="search_btn" @click="doSearch">搜索</button>
  13. <image class="menu_icon" src="~@/static/pda/menu.svg" @click="showSearch"></image>
  14. </view>
  15. <view class="">
  16. <view class="tab_box rx-sc">
  17. <view class="tab_item" v-for="(item,index) in tabList" :key="index"
  18. :class="{active: pickTabIndex == item.value}">
  19. <view @click="changeChartsTab(item.value)">
  20. {{item.label}}
  21. </view>
  22. </view>
  23. </view>
  24. </view>
  25. <view class="wrapper">
  26. <u-list @scrolltolower="scrolltolower" class="listContent" style="height: auto;">
  27. <view v-for="(item, index) in tableList" :key="index" style="position: relative;">
  28. <myCard @addSpareItems="addSpareItems(item.id)" @report="edit('report',item.id)"
  29. @handleDetail="handleDetail(item)" @edit="edit('edit',item.id)" @details="edit('view',item.id)"
  30. @handleAudit="handleAudit(item)" @checkAndAccept="checkAndAccept(item)"
  31. @evaluate="evaluate(item)" :item="item" :index="index+1" @receive="receive(item)"
  32. :columns="columns" :btnList="btnList">
  33. </myCard>
  34. <u-empty v-show="emptyShow && tableList.length==0" width="300" height="300" textSize="30"></u-empty>
  35. </view>
  36. </u-list>
  37. </view>
  38. <CheckAndAccept ref="acceptRef" @getList='doSearch' />
  39. <Evaluate ref="evaluateRef" @getList='doSearch' />
  40. <u-toast ref="uToast"></u-toast>
  41. <MySearch :show.sync="searchShow" :formItems="formItems" @search="confirmSearch"></MySearch>
  42. </view>
  43. </template>
  44. <script>
  45. import {
  46. getByCode
  47. } from '@/api/pda/common.js'
  48. import {
  49. initDict
  50. } from '@/utils/utils.js'
  51. import {
  52. getSalesWorkOrder,
  53. receiveSalesWorkOrder,
  54. checkByWorkId
  55. } from '@/api/salesServiceManagement/workOrder/index.js'
  56. import myCard from '@/pages/saleManage/components/myCard.vue'
  57. import CheckAndAccept from './components/forWork/checkAndAccept.vue'
  58. import Evaluate from './components/forWork/evaluate.vue'
  59. import {
  60. getBpmCustomFormList,
  61. } from '@/api/wt/index.js'
  62. export default {
  63. components: {
  64. myCard,
  65. CheckAndAccept,
  66. Evaluate,
  67. },
  68. watch: {
  69. fault_level_arr: {
  70. handler(val) {
  71. console.log(val);
  72. this.formItems.find(item => item.prop === 'faultLevel').props.localdata = val
  73. },
  74. deep: true
  75. }
  76. },
  77. data() {
  78. return {
  79. searchForm: {},
  80. emptyShow: false,
  81. searchShow: false,
  82. fault_level_obj: {},
  83. fault_level_arr: [],
  84. formItems: [{
  85. label: '工单编号:',
  86. prop: 'code',
  87. component: 'MyInput',
  88. props: {
  89. placeholder: '请输入内容',
  90. }
  91. },
  92. {
  93. label: '客户名称:',
  94. prop: 'contactName',
  95. component: 'MyInput',
  96. props: {
  97. placeholder: '请输入内容',
  98. }
  99. },
  100. {
  101. label: '设备名称:',
  102. prop: 'deviceName',
  103. component: 'MyInput',
  104. props: {
  105. placeholder: '请输入内容',
  106. }
  107. },
  108. {
  109. label: '故障等级:',
  110. prop: 'faultLevel',
  111. component: 'MySelect',
  112. props: {
  113. localdata: [],
  114. dataKey: 'label',
  115. dataValue: 'value'
  116. }
  117. },
  118. {
  119. label: '计划单号:',
  120. prop: 'planCode',
  121. component: 'MyInput',
  122. props: {
  123. placeholder: '请输入内容',
  124. }
  125. },
  126. {
  127. label: '计划名称:',
  128. prop: 'planName',
  129. component: 'MyInput',
  130. props: {
  131. placeholder: '请输入内容',
  132. }
  133. },
  134. {
  135. label: '报工人:',
  136. prop: 'executeUserName',
  137. component: 'MyInput',
  138. props: {
  139. placeholder: '请输入内容',
  140. }
  141. },
  142. {
  143. label: '验收人:',
  144. prop: 'accepterUserName',
  145. component: 'MyInput',
  146. props: {
  147. placeholder: '请输入内容',
  148. }
  149. },
  150. ],
  151. tabList: [{
  152. value: 'all',
  153. label: '全部',
  154. },
  155. {
  156. value: '0',
  157. label: '待执行',
  158. },
  159. {
  160. value: '1',
  161. label: '执行中',
  162. },
  163. {
  164. value: '3',
  165. label: '待验收',
  166. },
  167. {
  168. value: '5',
  169. label: '已完成',
  170. },
  171. ],
  172. workOrderStatus: [
  173. // { code: 0, label: '待接收' },
  174. {
  175. code: 0,
  176. label: '待执行'
  177. },
  178. {
  179. code: 1,
  180. label: '已接收'
  181. },
  182. {
  183. code: 2,
  184. label: '执行中'
  185. },
  186. {
  187. code: 3,
  188. label: '待验收'
  189. },
  190. {
  191. code: 4,
  192. label: '待评价'
  193. },
  194. {
  195. code: 5,
  196. label: '已完成'
  197. },
  198. {
  199. code: 6,
  200. label: '验收不通过'
  201. }
  202. ],
  203. pickTabIndex: 'all',
  204. searchVal: '',
  205. isEnd: false,
  206. page: 1,
  207. size: 10,
  208. tableList: [],
  209. columns: [
  210. [{
  211. label: '工单编号:',
  212. prop: 'code',
  213. type: 'title',
  214. className: 'perce100',
  215. }],
  216. [{
  217. label: '计划单号:',
  218. prop: 'planCode'
  219. }],
  220. [{
  221. label: '计划名称:',
  222. prop: 'planName',
  223. }],
  224. [{
  225. label: '报工人:',
  226. prop: 'executeUserName'
  227. }, {
  228. label: '验收人:',
  229. prop: 'accepterUserName',
  230. }],
  231. [{
  232. label: '故障等级:',
  233. prop: 'faultLevel',
  234. formatter: (row) => {
  235. console.log(this.fault_level_obj);
  236. return this.fault_level_obj[row.faultLevel]
  237. }
  238. }, {
  239. label: '客户名称:',
  240. prop: 'contactName',
  241. }],
  242. [{
  243. label: '设备名称:',
  244. prop: 'categoryName',
  245. formatter: (row) => {
  246. if (!row.deviceDetails) return '';
  247. let str = '';
  248. row.deviceDetails.map((el, idx) => {
  249. if (idx + 1 == row.deviceDetails.length) {
  250. str += el.categoryName;
  251. } else {
  252. str = str + '' + el.categoryName + ',';
  253. }
  254. });
  255. return str;
  256. }
  257. }],
  258. [{
  259. label: '验收时间:',
  260. prop: 'accepterTime'
  261. }, {
  262. label: '开始时间:',
  263. prop: 'acceptTime',
  264. }],
  265. [{
  266. label: '结束时间:',
  267. prop: 'finishTime'
  268. }, {
  269. label: '计划完成时间:',
  270. prop: 'planFinishTime',
  271. }],
  272. [{
  273. label: '实际售后时长:',
  274. prop: 'inFactDuration',
  275. formatter: (row) => {
  276. if (row.inFactDuration || row.inFactDuration == 0) {
  277. let str = ((row.inFactDuration - 0) / 60).toFixed(1);
  278. return str + ' 小时';
  279. }
  280. }
  281. }, {
  282. label: '状态:',
  283. prop: 'orderStatus',
  284. formatter: (row) => {
  285. return this.workOrderStatus.find(
  286. (item) => item.code == row.orderStatus
  287. )?.label;
  288. }
  289. }],
  290. [{
  291. label: '操作:',
  292. prop: 'action',
  293. type: 'action',
  294. className: 'perce100',
  295. }],
  296. ],
  297. btnList: [{
  298. name: '详情',
  299. apiName: 'details',
  300. btnType: 'primary',
  301. type: '2',
  302. pageUrl: '',
  303. },
  304. // {
  305. // name: '修改',
  306. // apiName: 'edit',
  307. // btnType: 'primary',
  308. // type: '2',
  309. // pageUrl: '',
  310. // judge: [{
  311. // authorities: '',
  312. // }, {
  313. // key: 'orderStatus',
  314. // value: [1, 6],
  315. // }],
  316. // },
  317. {
  318. name: '报工',
  319. apiName: 'report',
  320. btnType: 'error ',
  321. type: '2',
  322. pageUrl: '',
  323. judge: [{
  324. authorities: '',
  325. }, {
  326. key: 'orderStatus',
  327. value: [1, 6],
  328. }],
  329. }, {
  330. name: '接收',
  331. apiName: 'receive',
  332. btnType: 'error ',
  333. type: '2',
  334. pageUrl: '',
  335. judge: [{
  336. authorities: '',
  337. }, {
  338. key: 'orderStatus',
  339. value: [0],
  340. }],
  341. }, {
  342. name: '转派',
  343. apiName: 'handleAudit',
  344. btnType: 'primary',
  345. type: '2',
  346. pageUrl: '',
  347. judge: [{
  348. authorities: '',
  349. }, {
  350. key: 'orderStatus',
  351. value: [0, 1],
  352. }],
  353. },
  354. {
  355. name: '验收',
  356. apiName: 'checkAndAccept',
  357. btnType: 'primary',
  358. type: '2',
  359. pageUrl: '',
  360. judge: [{
  361. authorities: '',
  362. }, {
  363. key: 'orderStatus',
  364. value: [3, 6],
  365. }],
  366. },
  367. {
  368. name: '评价',
  369. apiName: 'evaluate',
  370. btnType: 'primary',
  371. type: '2',
  372. pageUrl: '',
  373. judge: [{
  374. authorities: '',
  375. }, {
  376. key: 'orderStatus',
  377. value: [4],
  378. }],
  379. },
  380. {
  381. name: '申请配件',
  382. apiName: 'addSpareItems',
  383. btnType: 'primary',
  384. type: '2',
  385. pageUrl: '',
  386. judge: [{
  387. authorities: '',
  388. }, {
  389. key: 'orderStatus',
  390. value: [1, 2],
  391. }],
  392. },
  393. {
  394. name: '用车申请',
  395. apiName: 'handleDetail',
  396. btnType: 'primary',
  397. type: '2',
  398. pageUrl: '',
  399. judge: [{
  400. authorities: '',
  401. }, {
  402. key: 'pieCarType',
  403. value: [1, 2],
  404. }],
  405. },
  406. ],
  407. }
  408. },
  409. onLoad() {
  410. this.getDict()
  411. },
  412. onShow() {
  413. this.doSearch();
  414. },
  415. created() {
  416. },
  417. onReachBottom() {
  418. this.getList()
  419. },
  420. methods: {
  421. async getDict() {
  422. let res = await getByCode('fault_level')
  423. let [arr, obj] = initDict(res)
  424. this.fault_level_obj = obj
  425. this.fault_level_arr = arr
  426. console.log(arr, obj);
  427. },
  428. async handleDetail(row) {
  429. const list = await getBpmCustomFormList({
  430. status: 1
  431. })
  432. const data = list.find(
  433. (item) => item?.code === 'carBy'
  434. );
  435. console.log(data, 'data')
  436. // return
  437. let params = JSON.stringify({
  438. id: data.id,
  439. processInstanceId: data.processInstance?.id || data.processDefinitionId || '',
  440. type: 'add',
  441. isEdit: true,
  442. manage_workorder: {
  443. id: row.id, // 列表工单ID
  444. code: row.code, // 列表工单编号(要显示的code)
  445. name: row.planName // 列表工单名称(可选,根据弹窗需求传递)
  446. }
  447. })
  448. let queryParams = `params=${params}`
  449. let url = '/pages/home/wt/components/formParser/routerView'
  450. uni.navigateTo({
  451. url: `${url}?${queryParams}`
  452. })
  453. },
  454. changeChartsTab(value) {
  455. this.pickTabIndex = value;
  456. this.doSearch();
  457. },
  458. doSearch() {
  459. this.isEnd = false;
  460. this.page = 1;
  461. this.getList();
  462. },
  463. //获取列表信息
  464. getList() {
  465. this.emptyShow = false
  466. if (this.isEnd) {
  467. this.$refs.uToast.show({
  468. message: "暂无更多数据",
  469. duration: 1000
  470. })
  471. return
  472. }
  473. uni.showLoading({
  474. title: '加载中'
  475. })
  476. let data = {
  477. pageNum: this.page,
  478. size: this.size,
  479. keyWord: this.searchVal,
  480. ...this.searchForm
  481. }
  482. if (this.pickTabIndex != 'all') {
  483. data.orderStatus = this.pickTabIndex;
  484. }
  485. getSalesWorkOrder(data).then(res => {
  486. if (this.page === 1) {
  487. this.tableList = res.list
  488. if (this.tableList.length === 0) {
  489. this.emptyShow = true
  490. }
  491. } else {
  492. this.tableList.push(...res.list)
  493. }
  494. this.page += 1
  495. this.isEnd = this.tableList.length >= res.count;
  496. uni.hideLoading();
  497. }).catch((e) => {
  498. uni.hideLoading();
  499. })
  500. },
  501. scrolltolower() {
  502. if (this.isEnd) {
  503. return
  504. }
  505. this.getList();
  506. },
  507. // 申请配件
  508. async addSpareItems(id) {
  509. const result = await this.checkId(id)
  510. if (result) {
  511. uni.navigateTo({
  512. url: `/pages/salesServiceManagement/workOrder/components/accessory?id=${id}`
  513. })
  514. }
  515. },
  516. // 验收
  517. checkAndAccept(item) {
  518. this.$refs.acceptRef.open(item.id);
  519. },
  520. // 评价
  521. evaluate(item) {
  522. this.$refs.evaluateRef.open(item.id);
  523. },
  524. // 转派
  525. handleAudit(item) {
  526. console.log(item, 'item ---')
  527. uni.navigateTo({
  528. url: `/pages/salesServiceManagement/workOrder/components/forWork/transfer?id=${item.id}`
  529. })
  530. },
  531. // 报工
  532. async edit(type, id) {
  533. // 判断报工是否可执行
  534. if (type == 'report') {
  535. const result = await this.checkId(id)
  536. if (!result) return
  537. }
  538. uni.navigateTo({
  539. url: `/pages/salesServiceManagement/workOrder/components/editPlan?type=${type}&id=${id}`
  540. })
  541. },
  542. // 接收
  543. async receive(item) {
  544. const data = await uni.showModal({
  545. title: '确认接收',
  546. content: '确定要接收这条数据吗?',
  547. confirmText: '接收',
  548. confirmColor: '#157a2c',
  549. });
  550. if (data[1].confirm) {
  551. const res = await receiveSalesWorkOrder(item);
  552. if (!res) return;
  553. this.$refs.uToast.show({
  554. type: "success",
  555. message: "操作成功",
  556. })
  557. this.doSearch();
  558. }
  559. },
  560. clearSearch() {
  561. this.searchVal = ''
  562. this.doSearch()
  563. },
  564. showSearch() {
  565. this.searchShow = true
  566. },
  567. confirmSearch(e) {
  568. console.log(e);
  569. let data = JSON.parse(JSON.stringify(e))
  570. this.searchForm = data
  571. this.doSearch()
  572. },
  573. async checkId(id) {
  574. try {
  575. await checkByWorkId(id)
  576. return true
  577. } catch (error) {
  578. console.log(error);
  579. return false
  580. }
  581. }
  582. }
  583. }
  584. </script>
  585. <style lang="scss" scoped>
  586. .top-wrapper {
  587. background-color: #fff;
  588. display: flex;
  589. width: 750rpx;
  590. height: 88rpx;
  591. padding: 16rpx 32rpx;
  592. align-items: center;
  593. gap: 16rpx;
  594. /deep/.uni-section {
  595. margin-top: 0px;
  596. }
  597. /deep/.uni-section-header {
  598. padding: 0px;
  599. }
  600. .search_btn {
  601. width: 120rpx;
  602. height: 70rpx;
  603. line-height: 70rpx;
  604. padding: 0 24rpx;
  605. background: $theme-color;
  606. font-size: 32rpx;
  607. color: #fff;
  608. margin: 0;
  609. margin-left: 26rpx;
  610. }
  611. .menu_icon {
  612. width: 44rpx;
  613. height: 44rpx;
  614. margin-left: 14rpx;
  615. }
  616. }
  617. .tab_box {
  618. width: 100%;
  619. height: 68rpx;
  620. border-bottom: 1rpx solid #E1E1E1;
  621. .tab_item {
  622. height: 68rpx;
  623. line-height: 68rpx;
  624. padding: 0 20rpx;
  625. font-size: 32rpx;
  626. color: #979C9E;
  627. }
  628. .active {
  629. box-sizing: border-box;
  630. border-bottom: 6rpx solid $theme-color;
  631. color: $theme-color;
  632. }
  633. }
  634. /deep/ .u-empty {
  635. margin-top: 200px !important;
  636. }
  637. </style>