index.blade.php 59 KB

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