index.blade.php 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. @extends("layouts.app")
  2. @section('title','处理工单')
  3. @section("content")
  4. <div class="container-fluid d-none" id="list">
  5. <div>
  6. <div class="">
  7. <div id="form_div" style="min-width: 1220px;"></div>
  8. <div class="form-inline mt-1" id="btn">
  9. @can('订单管理-订单问题件生成')
  10. <button type="button"
  11. class="ml-1 btn btn-outline-dark btn-sm form-control-sm tooltipTarget"
  12. @click="createOrderIssue(null,false)" style="background: #dad7e8;">生成问题件
  13. </button>
  14. @endcan
  15. @can('订单管理-订单问题件生成')
  16. <button type="button"
  17. class="ml-1 btn btn-outline-primary btn-sm form-control-sm tooltipTarget"
  18. @click="exportText()">导出文本
  19. </button>
  20. @endcan
  21. @can('订单管理-工单处理-审核')
  22. @endcan
  23. <button type="button"
  24. class="ml-1 btn btn-outline-dark btn-sm form-control-sm tooltipTarget"
  25. @click="copyLogisticNumber()" style="background: #dad7e8;">批量复制单号
  26. </button>
  27. @can('订单管理-工单处理-审核')
  28. <button type="button"
  29. class="ml-1 btn btn-outline-success btn-sm form-control-sm tooltipTarget"
  30. @click="showEditIssueType">批量修改问题件类型
  31. </button>
  32. @endcan
  33. </div>
  34. <div>
  35. <table class="table table-sm table-striped table-hover table-bordered td-min-width-80 " id="table">
  36. <tbody>
  37. <template v-for="(item,i) in workOrders">
  38. <tr @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
  39. <td>
  40. <label><input type="checkbox" :value="item.id"></label>
  41. </td>
  42. <td>
  43. <span v-text="item.id"></span>
  44. <a :href="'{{url("order/issue/index")}}'+'?orderCode='+item.orderno"
  45. target="order/issue/index?addtime=15">
  46. <span v-show="item.is_issue_order" class="badge badge-primary">问题件</span>
  47. </a>
  48. </td>
  49. <td>
  50. @can('订单管理-订单问题件生成')
  51. <button class="btn btn-sm btn-outline-primary"
  52. v-show="!item.is_issue_order "
  53. @click="createOrderIssue(item,true)">生成问题件
  54. </button>
  55. @endcan
  56. @can('订单管理-工单处理-货主编辑')
  57. <button class="btn btn-sm"
  58. style="background-color: #42a887;color: #FFFFFF;border-color: #378d72"
  59. v-if="item.issue_type_name === '快递丢件' && item.status === '货主处理'"
  60. @click="ownerFillWorkOrder(item,i)">
  61. 商家处理
  62. </button>
  63. @endcan
  64. @can('订单管理-工单处理-承运商编辑')
  65. <button class="btn btn-sm"
  66. style="background-color:#e06538;color: #FFFFFF;border-color: #9a3d23"
  67. v-if="['破损','快递异常'].includes(item.issue_type_name) && item.status ==='承运商处理'"
  68. @click="logisticFillWorkOrder(item,i)">
  69. 快递处理
  70. </button>
  71. <button class="btn btn-sm"
  72. style="background-color:#e06538;color: #FFFFFF;border-color: #9a3d23"
  73. v-if="['拦截','信息更改'].includes(item.issue_type_name) && item.status ==='承运商处理'"
  74. @click="logisticEndWorkOrder(item,i)">
  75. 快递处理
  76. </button>
  77. @endcan
  78. @can('订单管理-工单处理-宝时编辑')
  79. <button class="btn btn-sm"
  80. style="background-color: #38b1e0;color: #FFFFFF;border-color:#90acb6;"
  81. v-if="['错漏发','快递丢件','破损'].includes(item.issue_type_name) && item.status ==='宝时处理'"
  82. @click="baoShiFillWorkOrder(item,i)">
  83. 宝时处理
  84. </button>
  85. <button class="btn btn-sm "
  86. style="background-color: #54c337;color: #FFFFFF;border-color:#90acb6;"
  87. v-if="'宝时终审' === item.status"
  88. @click="baoShiReview(item,i)">
  89. 终审
  90. </button>
  91. @endcan
  92. </td>
  93. <td>
  94. @can('订单管理-工单处理-审核')
  95. <select class="form-control form-control-sm"
  96. :disabled="item.status === '完成'"
  97. :value="item.order_issue_type_id"
  98. @change="changeIssueType(item,$event)">
  99. <option value="0"></option>
  100. <option v-for="type in orderIssueTypes"
  101. :value="type.name"
  102. v-text="type.value">
  103. </option>
  104. </select>
  105. @else
  106. <span v-text="item.issue_type_name"></span>
  107. @endcan
  108. </td>
  109. <td>
  110. <span v-text="item.created_at"></span>
  111. </td>
  112. <td>
  113. <span v-text="item.status"></span>
  114. </td>
  115. <td>
  116. <span v-text="item.owner? item.owner.name : ''"></span>
  117. </td>
  118. <td>
  119. <span v-text="item.order? item.order.client_code : ''"></span>
  120. </td>
  121. <td>
  122. <div v-for="data in (item.order? item.order.packages : [])">
  123. <span v-text="data.logistic_number"></span>
  124. </div>
  125. </td>
  126. <td>
  127. <span v-text="item.logistic ? item.logistic.name : ''"></span>
  128. </td>
  129. <td>
  130. <span v-text="item.creator ? item.creator.name : ''"></span>
  131. </td>
  132. <td>
  133. <span v-text="item.result_explain ? item.result_explain: item.remark"></span>
  134. </td>
  135. <td>
  136. @include('order.workOrder._issue_logs')
  137. </td>
  138. <td class="container">
  139. <div class="row">
  140. @can('订单管理-工单处理-删除')
  141. <div class="col-1 ">
  142. <div class="header-alert">
  143. <button type="button"
  144. class="btn btn-sm btn-outline-danger"
  145. @click="destroy(item,i)">
  146. 删除
  147. </button>
  148. </div>
  149. </div>
  150. @endcan
  151. <div class="col-6 m-0 ">
  152. @include('order.workOrder._work_order_details')
  153. </div>
  154. <div @can('订单管理-工单处理-删除') class="col-5 m-0"
  155. @else class="col-6 p-0" @endcan>
  156. <div class="alert alert-light mb-0">
  157. <button type="button" class="btn btn-sm btn-outline-primary float-left"
  158. v-show="selectLog !== item.id && item.logs && item.logs.length > 0"
  159. @click="selectLog=item.id">
  160. 显示
  161. </button>
  162. <button type="button" class="btn btn-sm btn-outline-primary float-left"
  163. v-show="selectLog === item.id && item.logs && item.logs.length > 0"
  164. @click="selectLog=null">
  165. 收起
  166. </button>
  167. <span>&nbsp;</span>
  168. </div>
  169. <transition-group name="fade">
  170. <div class="alert alert-light mb-0 border-top"
  171. v-show="selectLog === item.id"
  172. v-for="(log,index) in item.logs" v-bind:key="item.id+':'+index">
  173. <div class="card-body col-12 p-0">
  174. <div>
  175. <span class="text-monospace">创建人:</span>
  176. <span v-text="log.creator? log.creator.name : ''"></span>
  177. </div>
  178. <div>
  179. <span class="text-monospace">创建时间:</span>
  180. <span v-text="log.created_at"></span>
  181. </div>
  182. <div>
  183. <span class="text-monospace">内容:</span>
  184. <span v-text="log.content"></span>
  185. </div>
  186. </div>
  187. </div>
  188. </transition-group>
  189. </div>
  190. </div>
  191. </td>
  192. </template>
  193. </tbody>
  194. </table>
  195. {{ $workOrders->withQueryString()->links() }}
  196. </div>
  197. </div>
  198. @can('订单管理-工单处理-审核')
  199. {{-- @include('order.workOrder._edit_issue_type')--}}
  200. @endcan
  201. @include('order.workOrder._bao_shi_review_modal')
  202. @include('order.workOrder._bao_shi_fill_work_order_modal')
  203. @include('order.workOrder._logistic_fill_work_order_modal')
  204. @include('order.workOrder._owner_fill_work_order_modal')
  205. </div>
  206. </div>
  207. @endsection()
  208. @section("lastScript")
  209. <script type="text/javascript" src="{{asset('js/queryForm/queryForm.js')}}"></script>
  210. <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
  211. <style>
  212. .fade-enter-active {
  213. transition: opacity .3s;
  214. }
  215. .fade-leave-active {
  216. transition: opacity .1s;
  217. }
  218. .fade-enter, .fade-leave-to {
  219. opacity: 0;
  220. }
  221. .image-div {
  222. }
  223. .image-w {
  224. width: 100%;
  225. }
  226. </style>
  227. <script>
  228. let list = new Vue({
  229. el: "#list",
  230. data: {
  231. workOrders: {!! $workOrders->toJson() !!}['data'],
  232. form: null,
  233. logistics: [
  234. @foreach($logistics as $logistic)
  235. {
  236. name: {{$logistic->id}}, value: '{{$logistic->name}}'
  237. },
  238. @endforeach
  239. ],
  240. orderIssueTypes: [
  241. @foreach($orderIssueTypes as $type)
  242. {
  243. name: '{{$type->id}}', value: "{{$type->name}}"
  244. },
  245. @endforeach
  246. ],
  247. owners: [
  248. @foreach($owners as $owner)
  249. {
  250. name: '{{$owner->id}}', value: '{{$owner->name}}'
  251. },
  252. @endforeach
  253. ],
  254. workOrder: {
  255. id: null,
  256. detail_id:null,
  257. reissue_logistic_number: null, // 补发单号
  258. logistic_number: null, // 丢件快递单号
  259. refundImages: [], // 退款图
  260. dealImages: [], // 交易图
  261. },
  262. fillWorkOrder: {
  263. id: null,
  264. detail_id:null,
  265. reissue_logistic_number: null, // 补发单号
  266. logistic_number: null, // 丢件快递单号
  267. refundImages: [], // 退款图
  268. dealImages: [], // 交易图
  269. commodities: [],
  270. },
  271. workOrderStatus: ['创建', '信息已填写', '快递已处理', '工单完成'],
  272. reviewWorkOrder: {
  273. id: null,
  274. detail_id:null,
  275. commodities: [],
  276. issue_type_name: null,
  277. },
  278. selectTr: null, // table 行
  279. selectDetailId: null, // 详情
  280. selectCreateOrderIssueLog: null,// 创建问题件处理信息
  281. selectOrderIssueLog: null, // 问题件处理信息
  282. selectOrderIssue: null, // 问题件
  283. selectIssueType: '',
  284. selectLog: null, // 工单日志
  285. selectIndex: null, // 选中工单
  286. filePrefix: "{{asset("/storage")}}",
  287. damagedResults: ['核实破损', '核实未破损'],
  288. mistakeResults: ['核实少发', '核实多发', '核实未错漏发'],
  289. processResults: ['核实破损', '核实未破损'],
  290. mistakeProcessResults: ['少发', '多发,客户买下', '多发,客户退回', '少发,不补发', '核实未错漏发'],
  291. damagedProcessResults: ['赔偿', '不赔偿'],
  292. expressAbnormalLogisticProcessResults: ['已拦截', '已催件'],
  293. processResultInfo: {
  294. "少发": {'0': '宝时补发(商家不做单)'},
  295. "多发,客户买下": {'0': '商家做出库单(物流选自提,宝时不发货)'},
  296. "多发,客户退回": {'0': '客户自行退回(提供退回单号)', '1': '宝时上门取件(提供寄件信息,地址,联系人,电话)'},
  297. '少发,不补发': {'0': '商家做入库单,选择明细和数量'},
  298. '核实未错漏发': {'0': ''},
  299. },
  300. },
  301. mounted() {
  302. let data = [[
  303. {name: 'created_at_start', type: 'time', tip: ['工单创建开始日期', '时间']},
  304. {name: 'created_at_end', type: 'time', tip: ['工单创建结束日期', '时间']},
  305. {
  306. name: 'logistic',
  307. type: 'select_multiple_select',
  308. data: this.logistics,
  309. tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的承运商'],
  310. placeholder: ['承运商', '定位或多选承运商']
  311. },
  312. @can('订单管理-订单问题件生成')
  313. {
  314. name: 'owner',
  315. type: 'select_multiple_select',
  316. data: this.owners,
  317. tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的货主'],
  318. placeholder: ['货主', '定位或多选货主']
  319. },
  320. @endcan
  321. {
  322. name: 'logistic_number', type: 'input', placeholder: '快递单号'
  323. },
  324. {
  325. name: 'is_issue_order',
  326. type: 'select',
  327. placeholder: '问题件',
  328. data: [{name: 'true', value: '有'}, {name: 'false', value: '无'}]
  329. },
  330. {name: 'creator', type: 'input', placeholder: '创建人'},
  331. ], [
  332. {name: 'review_at_start', type: 'time', tip: ['终审开始日期', '时间']},
  333. {name: 'review_at_end', type: 'time', tip: ['终审结束日期', '时间']},
  334. {name: 'order_issue_type', type: 'select', placeholder: '问题件类型', data: this.orderIssueTypes},
  335. {name: 'client_code', type: 'input', placeholder: '客户订单号'},
  336. {
  337. name: 'status', type: 'select', placeholder: '工单当前处理人',
  338. data: [{name: '宝时处理', value: '宝时处理'},
  339. {name: '货主处理', value: '货主处理'},
  340. {name: '承运商处理', value: '承运商处理'},]
  341. },
  342. {name: 'is_end', type: 'checkbox', tip: '是否已拦截', data: [{name: 'ture', value: '已完成'}]},
  343. ]];
  344. this.form = new query({
  345. el: '#form_div',
  346. condition: data,
  347. });
  348. this.form.init();
  349. let column = [
  350. {name: 'id', value: '工单号', neglect: true},
  351. {name: 'operation', value: '操作', neglect: true},
  352. {name: 'work_type', value: '工单类型', neglect: true},
  353. {name: 'created_at', value: '创建时间', neglect: true},
  354. {name: 'status', value: '当前处理人', neglect: true},
  355. {name: 'owner', value: '货主', neglect: true},
  356. {name: 'order_code', value: '订单号', neglect: true},
  357. {name: 'logistic_numbers', value: '快递单号'},
  358. {name: 'logistic', value: '承运商'},
  359. {name: 'creator', value: '创建人'},
  360. {name: 'remark', value: '情况说明'},
  361. {name: 'order_issue_log', value: '处理结果'},
  362. {
  363. name: 'ab_operation', type: 'multi', title: "其他操作", rows: [
  364. @can('订单管理-工单处理-删除')
  365. {
  366. value: "删除", col: "1"
  367. },
  368. {value: "查看资料", col: "6"},
  369. {value: "处理日志", col: "5"},
  370. @else
  371. {
  372. value: "查看资料", col: "6"
  373. },
  374. {value: "处理日志", col: "6"},
  375. @endcan
  376. ], neglect: true
  377. },
  378. ];
  379. new Header({
  380. el: "table",
  381. name: "workOrders",
  382. column: column,
  383. data: this.workOrders,
  384. fixedTop: ($('#form_div').height()) + 2,
  385. }).init();
  386. $("#list").removeClass("d-none");
  387. },
  388. created() {
  389. this.workOrders.forEach(item => {
  390. if (!item.order) return;
  391. if (!item.order.packages) return;
  392. this.sortOrder(item);
  393. });
  394. },
  395. filters: {
  396. dataTime: function (value) {
  397. if (value !== null) {
  398. return moment(value).format('yyyy-MM-DD');
  399. }
  400. return value
  401. },
  402. },
  403. methods: {
  404. sortOrder(workOrder) {
  405. workOrder.detail_infos = this.groupDetails(workOrder); // 工单详情
  406. workOrder.package_images = this.groupImages(workOrder, '外包装图片'); // 外包装图片
  407. workOrder.commodity_images = this.groupImages(workOrder, '内物破碎图片'); // 内物破碎图片
  408. workOrder.deal_images = this.groupImages(workOrder, '交易截图'); // 交易截图
  409. workOrder.refund_images = this.groupImages(workOrder, '退款成功截图'); //退款成功截图
  410. workOrder.issue_logs = this.groupOrderIssueLogs(workOrder); // 问题件日志
  411. workOrder.logs = this.groupLogs(workOrder); // 工单日志
  412. workOrder.commodities = this.groupCommodities(workOrder);
  413. workOrder.issue_type_name = workOrder.issue_type ? workOrder.issue_type.name : ''; // 工单类型
  414. workOrder.pending_detail =this.groupPendingDetail(workOrder);
  415. },
  416. groupPendingDetail(workOrder){
  417. let detail = workOrder.details.find(item=>{
  418. return !['完成','标记'].includes(item.tag);
  419. });
  420. if (!detail) return null;
  421. return {
  422. id:workOrder.id,
  423. detail_id:detail.id,
  424. commodities:detail.commodities,
  425. issue_type_name:detail.issue_type ? detail.issue_type.name : '',
  426. status:detail.status,
  427. reissue_logistic_number:detail.reissue_logistic_number,
  428. logistic_number:detail.logistic_number,
  429. price:detail.price,
  430. return_logistic_number:detail.return_logistic_number,
  431. remark:detail.remark,
  432. tag:detail.tag,
  433. };
  434. },
  435. groupCommodities(workOrder,isCurrent = true){
  436. let commodities = [];
  437. workOrder.details.forEach(detail=>{
  438. commodities.push(...(detail.commodities ?? []))
  439. });
  440. commodities = commodities.filter(item=>{
  441. if (!isCurrent){
  442. return !['完成','标记'].includes(item.tag);
  443. } else {
  444. return ['完成','标记'].includes(item.tag);
  445. }
  446. })
  447. return commodities;
  448. },
  449. groupOrderIssueLogs(workOrder) {
  450. workOrder.current_issue_type = workOrder.issue_type ? workOrder.issue_type.name : '';
  451. let logs = workOrder.order_issue ? (workOrder.order_issue.logs ? workOrder.order_issue.logs : []) : [];
  452. return logs.sort((perv, cur) => {
  453. let prevT = new Date(perv.created_at), curT = new Date(cur.created_at);
  454. if (prevT > curT) {
  455. return -1;
  456. } else if (prevT === curT) {
  457. return 0;
  458. } else if (prevT < curT) {
  459. return 1;
  460. }
  461. });
  462. },
  463. groupDetails(workOrder) {
  464. return workOrder.details.map(item => {
  465. return {
  466. id: item.id,
  467. issue_type: item.issue_type ? item.issue_type.name : '', // 工单类型
  468. price: item.price, // 商品价值总价
  469. reissue_logistic_number: item.reissue_logistic_number, // 补发单号
  470. return_logistic_number: item.return_logistic_number, // 退回单号
  471. logistic_number: item.logistic_number, // 快递单号
  472. status: item.status, // 工单状态
  473. created_at: item.created_at, // 创建时间
  474. };
  475. });
  476. },
  477. groupDetailCommodities(detail) {
  478. return detail.commodities.map(item => {
  479. item.commodity_name = item.commodity ? item.commodity.name : '';
  480. return item;
  481. });
  482. },
  483. groupImages(workOrder, type) {
  484. let images = [];
  485. workOrder.details.forEach(detail => {
  486. let imageList = detail.images.filter(item => {
  487. return item.type === type;
  488. })
  489. images.push(...imageList);
  490. });
  491. return images;
  492. },
  493. groupLogs(workOrder) {
  494. let logs = [];
  495. workOrder.details.forEach(detail => {
  496. let logList = detail.logs.map(item => {
  497. return {
  498. id: item.id, // id
  499. created_at: item.created_at, // 创建时间
  500. creator: item.creator, // 创建人
  501. type: item.type, // 类型
  502. content: item.content, // 内容
  503. };
  504. });
  505. logs.push(...logList);
  506. });
  507. return logs;
  508. },
  509. sortTransfer(item) {
  510. if (!("transfer_status" in item)) return;
  511. if (item.transfer_status == null || !(item.transfer_status instanceof Array)) return;
  512. item.transfer_status.sort(function (item1, item2) {
  513. let date1 = new Date(item1['accept_time']);
  514. let date2 = new Date(item2['accept_time']);
  515. if (date1 - date2 > 0) return -1;
  516. if (date1 - date2 < 0) return 1;
  517. return 0;
  518. });
  519. },
  520. createOrderIssue(item, tag) { // 生成问题件
  521. let url = '{{route('workOrder.buildOrderIssueApi')}}';
  522. let data = {};
  523. if (tag) data.ids = [item.id];
  524. else data.ids = checkData;
  525. window.tempTip.confirm('是否生成对应的问题件', () => {
  526. window.tempTip.waitingTip('生成中........');
  527. window.axios.post(url, data).then(res => {
  528. if (res.data.success) {
  529. this.replaceWorkOrder(res.data.data);
  530. this.$forceUpdate();
  531. window.tempTip.cancelWaitingTip();
  532. window.tempTip.showSuccess('已生成对应的问题件');
  533. } else {
  534. window.tempTip.cancelWaitingTip();
  535. window.tempTip.show(res.data.message ? res.data.message : '生成问题件异常');
  536. }
  537. }).catch(err => {
  538. window.tempTip.cancelWaitingTip();
  539. window.tempTip.show(err)
  540. });
  541. })
  542. },
  543. replaceWorkOrder(workOrders) {
  544. let data = [];
  545. workOrders.forEach(item => {
  546. data[item.id] = item;
  547. });
  548. this.workOrders.forEach((e, i) => {
  549. if (data[e.id]) {
  550. let item = data[e.id];
  551. this.sortOrder(item);
  552. this.$set(this.workOrders, i, item);
  553. }
  554. });
  555. this.$forceUpdate();
  556. },
  557. getMessageWorkOrder() {
  558. let selected = checkData;
  559. if (!selected) {
  560. window.tempTip.show('未选中任何信息');
  561. return null;
  562. }
  563. return this.workOrders.filter((item) => {
  564. if (!item.order || !item.order.packages) return false;
  565. return selected.includes(item.id + '');
  566. });
  567. },
  568. exportText() {
  569. let items = this.getMessageWorkOrder();
  570. if (items == null) return;
  571. let text = '';
  572. items.forEach(item => {
  573. if (item.order) text += this.getExportText(item);
  574. });
  575. this.copyText(text);
  576. },
  577. getExportText(item) {
  578. if (!item.order || !item.order.packages) return '';
  579. let message = '';
  580. let issue_type = item['issue_type'] ? item['issue_type'].name : '';
  581. switch (issue_type) {
  582. case '拦截':
  583. message = this.interceptMessage(item);
  584. break;
  585. case '信息更改':
  586. message = this.modificationMessage(item);
  587. break;
  588. default:
  589. message = this.getMessage(item);
  590. break;
  591. }
  592. return message;
  593. },
  594. interceptMessage(item) {
  595. let message = '';
  596. let order = item.order;
  597. let order_packages = item.order ? item.order.packages : [];
  598. let logistic_code = item.order ? (item.order['logistic'] ? item.order['logistic'].code : '') : ''; // 承运商编码
  599. let logistic_name = item.order ? (item.order['logistic'] ? item.order['logistic'].name : '') : ''; // 承运商名称
  600. let {consignee_name, consignee_phone, address} = order;
  601. let order_adder = `${consignee_name} ${consignee_phone} ${address}`;
  602. order_packages.forEach(item => {
  603. let logistic_number = item.logistic_number;
  604. if (logistic_code.includes('SF') || logistic_code.includes('ZTO')) {
  605. message += `${logistic_number}\n`;
  606. } else {
  607. if (item) message += `${logistic_name} ${logistic_number} ${order_adder}\n`;
  608. }
  609. });
  610. message = message.trim() + ' ——拦截\n';
  611. return message;
  612. },
  613. modificationMessage(item) {
  614. let message = '';
  615. let {remark, order} = item;
  616. let order_packages = item.order ? item.order.packages : [];
  617. let logistic_code = item.order ? (item.order['logistic'] ? item.order['logistic'].code : '') : '';
  618. const {consignee_name, consignee_phone, province, city, district, address} = order;
  619. let adder = `${consignee_name} ${consignee_phone} ${province} ${city} ${district} ${address}`;
  620. order_packages.forEach(node => {
  621. let logistic_number = node.logistic_number;
  622. if (logistic_code.includes('SF')) { // 顺丰订单
  623. message += `${logistic_number} ——改信息:${remark},运费到付或月结\n`;
  624. } else {
  625. message += `${logistic_number} ${adder} ——改地址 ${remark}\n`;
  626. }
  627. });
  628. return message;
  629. },
  630. getMessage(item) {
  631. let message = '';
  632. if (!item.order.packages) return message;
  633. let {order, remark} = item.order;
  634. let {consignee_name, consignee_phone, province, city, district, address} = order;
  635. let adder = `${consignee_name} ${consignee_phone} ${province} ${city} ${district} ${address}`;
  636. order.packages.forEach(p => {
  637. message += `${p.logistic_number} ${adder} ——描述 ${remark}\n`;
  638. });
  639. return message;
  640. },
  641. copyText(text) {
  642. let ele = document.querySelector('#copy_text');
  643. if (ele == null) {
  644. ele = document.createElement("textarea");
  645. ele.setAttribute('id', 'copy_text')
  646. ele.style.opacity = 0;
  647. document.querySelector('body').append(ele);
  648. }
  649. try {
  650. $("#copy_text").text(text).select().focus();
  651. document.execCommand("Copy");
  652. tempTip.showSuccess('复制成功')
  653. } catch (e) {
  654. tempTip.showSuccess('复制失败:' + e)
  655. }
  656. },
  657. batchReview() {
  658. let url = '{{route('workOrder.batchReviewApi')}}';
  659. let data = {ids: checkData};
  660. window.tempTip.setIndex('1999');
  661. if (!confirm('是否对当前选中订单进行审核')) return;
  662. window.tempTip.waitingTip('审核中........');
  663. window.axios.post(url, data).then(res => {
  664. if (res.data.success) {
  665. this.replaceWorkOrder(res.data.data);
  666. this.$forceUpdate();
  667. window.tempTip.cancelWaitingTip();
  668. window.tempTip.showSuccess('审核完成');
  669. } else {
  670. window.tempTip.cancelWaitingTip();
  671. window.tempTip.show(res.data.message ? res.data.message : '审核出现异常');
  672. }
  673. }).catch(err => {
  674. window.tempTip.cancelWaitingTip();
  675. window.tempTip.show(err);
  676. })
  677. },
  678. changeIssueType(item, e) {
  679. let url = '{{route('workOrder.updateIssueTypeApi')}}';
  680. let data = {
  681. id: item.id,
  682. type_id: $(e.target).val()
  683. };
  684. window.tempTip.waitingTip('修改中.........');
  685. window.axios.post(url, data).then(res => {
  686. if (res.data.success) {
  687. window.tempTip.cancelWaitingTip();
  688. window.tempTip.showSuccess('修改成功');
  689. item.order_issue_type_id = data.type_id;
  690. } else {
  691. window.tempTip.cancelWaitingTip();
  692. window.tempTip.show(res.data.message ? res.data.message : '修改异常');
  693. }
  694. }).catch(err => {
  695. window.tempTip.cancelWaitingTip();
  696. window.tempTip.show(err);
  697. });
  698. },
  699. copyLogisticNumber() {
  700. let items = this.getMessageWorkOrder();
  701. let logistic_numbers = '';
  702. items.forEach(item => {
  703. item.order.packages.forEach(node => {
  704. logistic_numbers += `${node.logistic_number}\n`;
  705. });
  706. })
  707. this.copyText(logistic_numbers);
  708. },
  709. showEditIssueType() {
  710. this.selectIssueType = 0;
  711. $("edit-issue-type-modal").modal('show');
  712. },
  713. editOrderIssueType() {
  714. let url = '{{route('workOrder.batchUpdateIssueTypeApi')}}'
  715. let data = {ids: checkData, type: this.selectIssueType};
  716. window.tempTip.setIndex(1999);
  717. window.axios.post(url, data).then(res => {
  718. if (res.data.success) {
  719. window.tempTip.showSuccess('修改问题件类型成功');
  720. this.replaceWorkOrder(res.data.data);
  721. $("#edit-issue-type-type-modal").modal('hide');
  722. return;
  723. }
  724. window.tempTip.show(res.data.message ? res.data.message : '修改异常');
  725. }).catch(err => {
  726. window.tempTip.show(err)
  727. })
  728. },
  729. destroy(item, i) {
  730. window.tempTip.confirm('是否删除当前工单', () => {
  731. let url = '{{url('apiLocal/workOrder/')}}' + '/' + item.id;
  732. window.tempTip.waitingTip('删除.........');
  733. window.axios.delete(url).then(res => {
  734. if (res.data.success) {
  735. window.tempTip.cancelWaitingTip();
  736. window.tempTip.showSuccess('删除成功');
  737. this.$delete(this.workOrders, i);
  738. } else {
  739. window.tempTip.cancelWaitingTip();
  740. window.tempTip.show(res.data.message ? res.data.message : '');
  741. }
  742. }).catch(err => {
  743. window.tempTip.cancelWaitingTip();
  744. window.tempTip.show(err);
  745. })
  746. })
  747. },
  748. spliceImage(i, images) {
  749. window.tempTip.setIndex(1999);
  750. window.tempTip.confirm('是否取消选择该图片', () => {
  751. images.splice(i, 1);
  752. });
  753. },
  754. clearWorkOrder(item = null, index = null) {
  755. this.fillWorkOrder.id = item ? item.id : null;
  756. this.fillWorkOrder.detail_id = item ? this.getCurrentWorkOrderDetailId(item) : null;
  757. this.selectIndex = index ? index : null;
  758. this.fillWorkOrder.reissue_logistic_number = null; // 补发单号
  759. this.fillWorkOrder.logistic_number = null; // 补发单号
  760. this.fillWorkOrder.dealImages = []; // 交易图
  761. this.fillWorkOrder.refundImages = []; // 退款图
  762. this.fillWorkOrder.commodities = [];
  763. },
  764. setFormDataImagePrefix(formData, prefix, images) {
  765. images.forEach((item, i) => {
  766. formData.append(`${prefix}[]`, item);
  767. });
  768. },
  769. getImages(images) {
  770. return images.map((item) => {
  771. return item.file;
  772. })
  773. },
  774. pasteImage(event, imageArray) {
  775. for (let i = 0; i < event.clipboardData.items.length; i++) {
  776. let item = event.clipboardData.items[i];
  777. if (item.kind === 'string') continue;
  778. if (item.type.indexOf('image') === -1) continue;
  779. if (item.kind === 'file') {
  780. let blob = item.getAsFile();
  781. let src = null;
  782. this.blobToBase64(blob).then(res => {
  783. src = res;
  784. imageArray.push({src: src, file: blob});
  785. });
  786. }
  787. }
  788. event.preventDefault();
  789. },
  790. blobToBase64(blob) {
  791. return new Promise((resolve, reject) => {
  792. const fileReader = new FileReader();
  793. fileReader.onload = (e) => {
  794. resolve(e.target.result);
  795. };
  796. fileReader.readAsDataURL(blob);
  797. fileReader.onerror = () => {
  798. reject(new Error('blobToBase64 error'));
  799. };
  800. });
  801. },
  802. logisticFillWorkOrder(item, index) {
  803. this.fillWorkOrder = JSON.parse(JSON.stringify(item.pending_detail));
  804. this.selectIndex = index;
  805. $("#logistic-fill-work-order-modal").modal('show');
  806. },
  807. logisticUpdateCommodities() {
  808. let url = "{{route("workOrder.commodity.logisticUpdateApi")}}";
  809. let formData = new FormData();
  810. formData.append('id', this.fillWorkOrder.id);
  811. formData.append('detail_id', this.fillWorkOrder.detail_id);
  812. this.fillWorkOrderCommodity(formData);
  813. window.tempTip.setIndex(1999);
  814. window.axios.post(url, formData, {'Content-Type': 'multipart/form-data'})
  815. .then(res => {
  816. if (res.data.success) {
  817. this.sortOrder(res.data.data);
  818. this.$set(this.workOrders, this.selectIndex, res.data.data);
  819. window.tempTip.showSuccess('修改成功');
  820. $("#logistic-fill-work-order-modal").modal('hide');
  821. } else {
  822. window.tempTip.show(res.data.message ? res.data.message : '修改异常');
  823. }
  824. }).catch(err => {
  825. window.tempTip.show(err);
  826. });
  827. },
  828. logisticEndWorkOrder(item, index) {
  829. let url = "{{route("workOrder.logistic.endApi")}}";
  830. let data = {
  831. id:item.id,
  832. detail_id:this.getCurrentWorkOrderDetailId(item),
  833. };
  834. window.axios.post(url, data).then(res => {
  835. if (res.data.success) {
  836. window.tempTip.showSuccess('工单已处理');
  837. this.sortOrder(res.data.data);
  838. this.$set(this.workOrders, index, res.data.data);
  839. } else {
  840. window.tempTip.show(res.data.message ? res.data.message : '工单处理异常刷新后重试');
  841. }
  842. }).catch(err => {
  843. window.tempTip.show(err || '工单处理异常刷新后重试');
  844. });
  845. },
  846. baoShiFillWorkOrder(item, index) {
  847. this.fillWorkOrder = JSON.parse(JSON.stringify(item.pending_detail));
  848. this.selectIndex = index;
  849. $('#bao-shi-fill-work-order-modal').modal('show');
  850. },
  851. baoShiUpdateCommodities() {
  852. let url = "{{route("workOrder.commodity.baoShiUpdateApi")}}";
  853. let formData = new FormData();
  854. formData.append('id', this.fillWorkOrder.id);
  855. formData.append('detail_id', this.fillWorkOrder.detail_id);
  856. this.fillWorkOrderCommodity(formData)
  857. window.tempTip.setIndex(1999);
  858. window.axios.post(url, formData, {'Content-Type': 'multipart/form-data'})
  859. .then(res => {
  860. if (res.data.success) {
  861. this.sortOrder(res.data.data);
  862. this.$set(this.workOrders, this.selectIndex, res.data.data);
  863. window.tempTip.showSuccess('修改成功');
  864. $("#bao-shi-fill-work-order-modal").modal('hide');
  865. } else {
  866. window.tempTip.show(res.data.message ? res.data.message : '修改异常');
  867. }
  868. }).catch(err => {
  869. window.tempTip.show(err);
  870. })
  871. },
  872. ownerFillWorkOrder(item, index) {
  873. window.tempTip.waitingTip('获取数据中');
  874. this.getOrderCommodity(item).then(res => {
  875. window.tempTip.cancelWaitingTip();
  876. this.clearWorkOrderWith(item, index);
  877. this.fillWorkOrder.commodities = res.map(item => {
  878. item.abnormal_amount = item.amount;
  879. item.tag = 0;
  880. return item;
  881. });
  882. $("#owner-fill-work-order-modal").modal('show');
  883. }).catch(err => {
  884. window.tempTip.cancelWaitingTip();
  885. window.tempTip.show('获取数据异常');
  886. });
  887. },
  888. clearWorkOrderWith(item, index) {
  889. this.fillWorkOrder.id = item.id;
  890. this.fillWorkOrder.detail_id = this.getCurrentWorkOrderDetailId(item);
  891. this.selectIndex = index;
  892. this.fillWorkOrder.reissue_logistic_number = null; // 补发单号
  893. this.fillWorkOrder.logistic_number = null; // 补发单号
  894. this.fillWorkOrder.dealImages = []; // 交易图
  895. this.fillWorkOrder.refundImages = []; // 退款图
  896. },
  897. getOrderCommodity(item) {
  898. return new Promise((resolve, reject) => {
  899. let url = '{{route('order.commodity.getCommoditiesApi')}}';
  900. let data = {orderNo: item ? (item.order ? item.order.code : '') : ''};
  901. window.axios.post(url, data).then(res => {
  902. if (res.data.success) {
  903. resolve(res.data.data);
  904. }
  905. }).catch(err => {
  906. });
  907. });
  908. },
  909. ownerUpdateWorkOrder() {
  910. if (!this.checkFillLossWorkOrder()) return;
  911. let formData = new FormData();
  912. formData.append('id', this.fillWorkOrder.id);
  913. formData.append('detail_id', this.fillWorkOrder.detail_id);
  914. formData.append('reissue_logistic_number', this.fillWorkOrder.reissue_logistic_number);
  915. formData.append('logistic_number', this.fillWorkOrder.logistic_number);
  916. formData.append('price', this.fillWorkOrder.price);
  917. let dealImages = this.getImages(this.fillWorkOrder.dealImages);
  918. let refundImages = this.getImages(this.fillWorkOrder.refundImages);
  919. this.setFormDataImagePrefix(formData, 'dealImages', dealImages);
  920. this.setFormDataImagePrefix(formData, 'refundImages', refundImages);
  921. this.fillWorkOrderCommodity(formData);
  922. this.ownerFillLossWorkOrder(formData);
  923. },
  924. checkFillLossWorkOrder() {
  925. window.tempTip.setIndex(2000);
  926. window.tempTip.setDuration(1500);
  927. let message = null;
  928. let abnormal_amount_is_null = this.fillWorkOrder.commodities.filter(item => {
  929. return Number(item.abnormal_amount) === 0;
  930. }).length > 0;
  931. if (abnormal_amount_is_null) message = '异常数量不能为空';
  932. if (this.fillWorkOrder.refundImages.length === 0) message = '退款截图为必需项!';
  933. if (this.fillWorkOrder.reissue_logistic_number !== null) {
  934. } else if (this.fillWorkOrder.dealImages.length === 0) {
  935. message = '交易截图为必需项!';
  936. }
  937. if (message) {
  938. window.tempTip.show(message);
  939. return false;
  940. }
  941. return true;
  942. },
  943. fillWorkOrderCommodity(formData) {
  944. this.fillWorkOrder.commodities.forEach(e => {
  945. formData.append("commodities[]", JSON.stringify(e));
  946. });
  947. },
  948. ownerFillLossWorkOrder(data) {
  949. let url = "{{route('workOrder.updateLossApi')}}";
  950. window.tempTip.setIndex(1999);
  951. window.axios.post(url, data, {'Content-Type': 'multipart/form-data'}).then(res => {
  952. if (res.data.success) {
  953. this.sortOrder(res.data.data);
  954. this.$set(this.workOrders, this.selectIndex, res.data.data);
  955. window.tempTip.showSuccess('工单信息填充成功');
  956. this.clearWorkOrder();
  957. $("#owner-fill-work-order-modal").modal('hide');
  958. } else {
  959. window.tempTip.show(res.data.message);
  960. }
  961. }).catch(err => {
  962. window.tempTip.show(err);
  963. });
  964. },
  965. baoShiReview(item, i) { // 宝时终审
  966. this.reviewWorkOrder = JSON.parse(JSON.stringify(item.pending_detail));
  967. this.selectIndex = i;
  968. $('#bao-shi-review-modal').modal('show');
  969. },
  970. getCurrentWorkOrderDetailId(workOrder){
  971. let items = workOrder.details.filter(item=>{
  972. return !['标记','完成'].includes(item.tag);
  973. });
  974. if (items.length === 0) return null;
  975. let item = items.shift();
  976. return item.id;
  977. },
  978. review() {
  979. let formData = new FormData();
  980. formData.append('id', this.reviewWorkOrder.id);
  981. formData.append('detail_id', this.reviewWorkOrder.detail_id);
  982. this.reviewWorkOrderCommodity(formData);
  983. let url = "{{route('workOrder.baoShi.reviewApi')}}";
  984. window.tempTip.setIndex(1999);
  985. window.tempTip.waitingTip('审核中');
  986. window.axios.post(url, formData).then(res => {
  987. window.tempTip.cancelWaitingTip();
  988. if (res.data.success) {
  989. this.sortOrder(res.data.data);
  990. this.$set(this.workOrders, this.selectIndex, res.data.data);
  991. window.tempTip.setIndex(1999);
  992. window.tempTip.showSuccess('审核完成');
  993. } else {
  994. window.tempTip.setIndex(1999);
  995. window.tempTip.show(res.data.message ? res.data.message : '审核异常刷新后重试');
  996. }
  997. $('#bao-shi-review-modal').modal('hide');
  998. }).catch(err => {
  999. window.tempTip.cancelWaitingTip();
  1000. window.tempTip.setIndex(1999);
  1001. window.tempTip.show(err);
  1002. })
  1003. },
  1004. reviewWorkOrderCommodity(formData) {
  1005. this.reviewWorkOrder.commodities.forEach(e => {
  1006. formData.append("commodities[]", JSON.stringify(e));
  1007. });
  1008. },
  1009. computeBaoShiCheckResult(item) {
  1010. let amount = Number(item.amount);
  1011. let bao_shi_check_amount = Number(item['bao_shi_check_amount']);
  1012. item.check_result = amount === bao_shi_check_amount ? '核实未错漏发' : (amount < bao_shi_check_amount ? '核实多发' : '核实少发')
  1013. },
  1014. sumPrice(workOrder) {
  1015. workOrder.price = workOrder.commodities.reduce((prev, cur) => {
  1016. return Number(prev) + Number(cur.price);
  1017. }, 0);
  1018. },
  1019. createOrderIssueLog(orderIssueId,item){
  1020. let log_text = document.getElementById(orderIssueId+'_log_text');
  1021. let log_check = document.getElementById(orderIssueId+'_log_check');
  1022. let data = {
  1023. id:item.order_issue.id,
  1024. order_issue_id:orderIssueId,
  1025. content:log_text.value,
  1026. tag:log_check.checked ? 1 : 0,
  1027. };
  1028. let url = "{{route("order.issue.log.storeApi")}}";
  1029. window.tempTip.waitingTip("创建中");
  1030. window.tempTip.setDuration(1500);
  1031. window.axios.post(url,data).then(res=>{
  1032. window.tempTip.cancelWaitingTip();
  1033. if (res.data.success){
  1034. item.issue_logs.unshift(res.data.data);
  1035. window.tempTip.showSuccess('添加成功');
  1036. this.selectCreateOrderIssueLog = null;
  1037. log_text.value = null;
  1038. log_check.checked = false;
  1039. } else {
  1040. window.tempTip.setDuration(2000);
  1041. window.tempTip.show(res.data.fail_info);
  1042. }
  1043. }).catch(err=>{
  1044. window.tempTip.cancelWaitingTip();
  1045. tempTip.setDuration(4000);
  1046. tempTip.show('网络异常:' + err);
  1047. });
  1048. },
  1049. destroyLog(log,index,i){
  1050. if (!confirm('是否删除当前记录')) return;
  1051. if (log.type === '创建') {
  1052. tempTip.show('创建记录不能删除');
  1053. return;
  1054. }
  1055. let url = "{{route("order.issue.log.destroyApi")}}";
  1056. let data = {id:log.id};
  1057. window.tempTip.setIndex('1999');
  1058. window.axios.post(url,data).then(res=>{
  1059. if (res.data.success){
  1060. this.$delete(this.workOrders[i].issue_logs,index);
  1061. tempTip.setDuration(1500);
  1062. tempTip.showSuccess('删除成功');
  1063. } else {
  1064. tempTip.setDuration(2000);
  1065. tempTip.show('删除失败:' + res.data.fail_info);
  1066. }
  1067. }).catch(err=>{
  1068. tempTip.setDuration(2500);
  1069. tempTip.show('网络异常:' + err);
  1070. });
  1071. },
  1072. tagIssueLog(log){
  1073. let url = '{{route('order.issue.log.tagApi')}}';
  1074. let data = {id: log.id};
  1075. if (!confirm('是否标记当前记录客户不可见')) return;
  1076. window.axios.post(url, data).then(res => {
  1077. if (res.data.success) {
  1078. window.tempTip.showSuccess('标记成功');
  1079. log.tag = 1;
  1080. } else {
  1081. window.tempTip.show(res.data.message ? res.data.message : '标记出现异常');
  1082. }
  1083. }).catch(err => {
  1084. window.tempTip.show(err);
  1085. });
  1086. }
  1087. },
  1088. });
  1089. </script>
  1090. @endsection