list.blade.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. @extends('layouts.app')
  2. @section('title')预约管理-入库预约@endsection
  3. @section('content')
  4. <span id="nav2">
  5. @component('store.menu')@endcomponent
  6. @component('store.deliveryAppointment.menu')@endcomponent
  7. </span>
  8. <div class="container-fluid d-none" id="container">
  9. <div id="form"></div>
  10. <div class="mt-1">
  11. <button type="button" class="btn btn-outline-dark btn-sm form-control-sm dropdown-toggle tooltipTarget" :class="[checkData.length>0?'btn-dark text-light':'']"
  12. data-toggle="dropdown" title="导出所有页将会以搜索条件得到的筛选结果,将其全部记录(每一页)导出">
  13. 导出Excel
  14. </button>
  15. <div class="dropdown-menu">
  16. <a class="dropdown-item" @click="executeExport(false)" href="javascript:">导出勾选内容</a>
  17. <a class="dropdown-item" @click="executeExport(true)" href="javascript:">导出所有页</a>
  18. </div>
  19. @can("入库管理-入库预约-质检")<button type="button" class="btn btn-outline-primary" @click="qualityInspectionMark()">质检</button>@endcan
  20. </div>
  21. <table class="table table-striped table-hover text-nowrap td-min-width-80" id="table">
  22. <tr class="text-center">
  23. <th>
  24. <label for="all" id="cloneCheckAll">
  25. <input id="all" type="checkbox" @click="checkAll($event)">全选
  26. </label>
  27. </th>
  28. <th>序号</th>
  29. <th>操作</th>
  30. <th>状态</th>
  31. <th>货主</th>
  32. <th>预约时间</th>
  33. <th>仓库</th>
  34. <th>
  35. <div class="row" style="min-width: 800px">
  36. <div class="col-12">车辆信息</div>
  37. </div>
  38. <div class="row">
  39. <div class="col-2">预约号</div>
  40. <div class="col-2">车牌号</div>
  41. <div class="col-2">车型</div>
  42. <div class="col-1">司机姓名</div>
  43. <div class="col-2">司机电话</div>
  44. <div class="col-3">操作/送达时间</div>
  45. </div>
  46. </th>
  47. <th>吨</th>
  48. <th>立方</th>
  49. <th>箱数</th>
  50. <th>快递公司</th>
  51. <th>快递单号</th>
  52. <th>采购单号</th>
  53. <th>ASN单号</th>
  54. <th>
  55. <div class="row">
  56. <div class="col-12 text-center">明细单</div>
  57. </div>
  58. <div class="row" style="min-width: 500px">
  59. <div class="col-5 text-center">商品名称</div>
  60. <div class="col-4 text-center">条码</div>
  61. <div class="col-2 text-center">数量</div>
  62. </div>
  63. </th>
  64. <th>预约备注</th>
  65. <th>创建时间</th>
  66. </tr>
  67. <tr v-for="(info,i) in list">
  68. <td>
  69. <label>
  70. <input class="checkItem" type="checkbox" :value="info.id" v-model="checkData">
  71. </label>
  72. </td>
  73. <td>@{{ i+1 }}</td>
  74. <td>
  75. <span v-if="info.status==0">
  76. <button type="button" @click="cancel(info.id,i)" class="btn btn-sm btn-outline-danger">取消预约</button><br>
  77. <button type="button" @click="updateDeliveryDate(info,i)" class="btn btn-sm btn-outline-primary">修改预约</button>
  78. </span>
  79. <span v-if="info.status==2">
  80. <button type="button" @click="printReceipt(info)" class="btn btn-sm btn-outline-success"><i class="fa fa-print"></i>&nbsp;打印</button>
  81. </span>
  82. </td>
  83. <td>
  84. <span v-if="info.status==0 && info.cars.length>0 && info.cars[0].status==1">
  85. <span class="fa fa-circle text-primary">作业中</span>
  86. </span>
  87. <span v-else>
  88. <label v-if="!poolMapping.status">
  89. <span class="fa fa-circle text-secondary">未知</span>
  90. </label>
  91. <label v-else>
  92. <small><span class="fa fa-circle" :class="info.status==0 ? 'text-info' : (info.status==2 ? 'text-success' : 'text-danger')"></span></small>
  93. @{{ poolMapping.status[info.status] }}
  94. <span v-if="info.type_mark==0" class="badge badge-primary">质检单</span>
  95. </label>
  96. </span>
  97. </td>
  98. <td>
  99. <label v-if="!poolMapping.owners"></label>
  100. <label v-else>@{{ poolMapping.owners[info.owner_id] }}</label>
  101. </td>
  102. <td class="text-primary">@{{ info.appointment_date }}&nbsp;&nbsp;@{{ info.period }}</td>
  103. <td>
  104. <label v-if="!poolMapping.warehouses"></label>
  105. <label v-else>@{{ poolMapping.warehouses[info.warehouse_id] }}</label>
  106. </td>
  107. <td>
  108. <div v-if="info.cars.length>0" class="text-center">
  109. <div class="row">
  110. <div class="col-2 font-weight-bold">@{{ info.cars[0].appointment_number }}</div>
  111. <div class="col-2 text-secondary">@{{ info.cars[0].license_plate_number }}</div>
  112. <div class="col-2 text-secondary">@{{ info.cars[0].car ? info.cars[0].car.name : '' }}</div>
  113. <div class="col-1 text-secondary">@{{ info.cars[0].driver_name }}</div>
  114. <div class="col-2 text-secondary">@{{ info.cars[0].driver_phone }}</div>
  115. <div class="col-3">
  116. @can("入库管理-入库预约-预约管理-卸货完成")<button class="btn btn-sm btn-outline-success" @click="unloading(i,0)" v-if="info.cars[0].status==1">卸货完成</button>@endcan
  117. <div v-if="info.cars[0].status==2">@{{ info.cars[0].delivery_time }}</div>
  118. </div>
  119. </div>
  120. <div class="up" :id="'item-'+info.id" v-show="info.cars.length>1">
  121. <div class="row" v-for="(car,j) in info.cars" v-if="j!==0">
  122. <div class="col-2 font-weight-bold">@{{ car.appointment_number }}</div>
  123. <div class="col-2 text-secondary">@{{ car.license_plate_number }}</div>
  124. <div class="col-2 text-secondary">@{{ car.car ? car.car.name : '' }}</div>
  125. <div class="col-1 text-secondary">@{{ car.driver_name }}</div>
  126. <div class="col-2 text-secondary">@{{ car.driver_phone }}</div>
  127. <div class="col-3">
  128. @can("入库管理-入库预约-预约管理-卸货完成")<button class="btn btn-sm btn-outline-success" @click="unloading(i,j)" v-if="car.status==1">卸货完成</button>@endcan
  129. <div v-if="car.status==2">@{{ car.delivery_time }}</div>
  130. </div>
  131. </div>
  132. </div>
  133. <div class="text-center m-auto small cursor-pointer" v-if="info.cars.length>1" @click="upAll(info.id)">
  134. <span class="fa" :class="upList[info.id] ? 'fa-angle-double-down' : 'fa-angle-double-right'" style="margin-top: 2px;"></span>&nbsp;
  135. <span v-if="upList[info.id]">收起其余@{{ info.cars.length-1 }}条</span>
  136. <span v-else>展开其余@{{ info.cars.length-1 }}条</span>
  137. </div>
  138. </div>
  139. </td>
  140. <td>@{{ info.tonne>0 ? info.tonne : '-' }}</td>
  141. <td>@{{ info.cubic_meter>0 ? info.cubic_meter : '-' }}</td>
  142. <td>@{{ info.box_amount>0 ? info.box_amount : '-' }}</td>
  143. <td>@{{ info.logistic ? info.logistic.name : '' }}</td>
  144. <td>@{{ info.logistic_number }}</td>
  145. <td><span v-html="warpText(info.procurement_number)"></span></td>
  146. <td><span v-html="warpText(info.asn_number)"></span></td>
  147. <td>
  148. <div v-if="info.details.length>0">
  149. <div class="row">
  150. <div class="col-5 font-weight-bold text-overflow-warp">@{{ info.details[0].commodity_id ? (info.details[0].commodity ? info.details[0].commodity.name : '') : info.details[0].name }}</div>
  151. <div class="col-4 text-secondary text-overflow-warp">@{{ info.details[0] | getCommodity }}</div>
  152. <div class="col-2 text-secondary">@{{ info.details[0].amount }}</div>
  153. </div>
  154. <div class="up" :id="'detail-'+info.id" v-show="info.details.length>1">
  155. <div class="row" v-for="(detail,i) in info.details" v-if="i!==0">
  156. <div class="col-5 font-weight-bold text-overflow-warp">@{{ detail.commodity_id ? (detail.commodity ? detail.commodity.name : '') : detail.name }}</div>
  157. <div class="col-4 text-secondary text-overflow-warp">@{{ detail | getCommodity }}</div>
  158. <div class="col-2 text-secondary">@{{ detail.amount }}</div>
  159. </div>
  160. </div>
  161. <div class="text-center m-auto small cursor-pointer" v-if="info.details.length>1" @click="upAllDetail(info.id)">
  162. <span class="fa" :class="upListDetail[info.id] ? 'fa-angle-double-down' : 'fa-angle-double-right'" style="margin-top: 2px;"></span>&nbsp;
  163. <span v-if="upListDetail[info.id]">收起其余@{{ info.details.length-1 }}条</span>
  164. <span v-else>展开其余@{{ info.details.length-1 }}条</span>
  165. </div>
  166. </div>
  167. </td>
  168. <td>@{{ info.remark }}</td>
  169. <td>@{{ info.created_at }}</td>
  170. </tr>
  171. </table>
  172. @include("store.deliveryAppointment._selectDate")
  173. @include("store.deliveryAppointment._printBody")
  174. @include("store.deliveryAppointment._printInfo")
  175. </div>
  176. @stop
  177. @section("lastScript")
  178. <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
  179. <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
  180. <script>
  181. new Vue({
  182. el:"#container",
  183. data:{
  184. list:[@foreach($list as $data)@json($data),@endforeach],
  185. status:[],
  186. warehouses:[],
  187. owners:[@foreach($owners as $owner){name:"{{$owner->id}}",value:"{{$owner->name}}"},@endforeach],
  188. checkData:[],
  189. poolMapping:{},
  190. upList:{},
  191. upListDetail:{},
  192. sum:Number("{{$list->total()}}"),
  193. capacities:[],
  194. btnName:"确定修改预约",
  195. index:"",
  196. selectDate:{},
  197. periods:@json(\App\DeliveryAppointment::PERIOD),
  198. printInfo:{},
  199. infoShow:false,
  200. },
  201. mounted(){
  202. let status = [];
  203. let statusMap = {};
  204. let warehouses = [];
  205. let warehouseMap = {};
  206. let owners = [];
  207. let ownerMap = [];
  208. @foreach(\App\DeliveryAppointment::STATUS as $index=>$status)
  209. status.push({name:"{{$index}}",value:"{{$status}}"});
  210. statusMap["{{$index}}"] = "{{$status}}";
  211. @endforeach
  212. this.status = status;
  213. this.$set(this.poolMapping,"status",statusMap);
  214. @foreach($warehouses as $warehouse)
  215. warehouses.push({name:"{{$warehouse->id}}",value:"{{$warehouse->name}}"});
  216. warehouseMap["{{$warehouse->id}}"] = "{{$warehouse->name}}";
  217. @endforeach
  218. this.warehouses = warehouses;
  219. this.poolMapping.warehouses = warehouseMap;
  220. @foreach($owners as $owner)
  221. owners.push({name:"{{$owner->id}}",value:"{{$owner->name}}"});
  222. ownerMap["{{$owner->id}}"] = "{{$owner->name}}";
  223. @endforeach
  224. this.owners = owners;
  225. this.poolMapping.owners = ownerMap;
  226. $(".up").slideUp();
  227. $("#container").removeClass("d-none");
  228. this._renderingForm();
  229. },
  230. watch:{
  231. checkData:{
  232. handler(){
  233. document.querySelector('#all').checked = this.checkData.length === this.list.length;
  234. },
  235. deep:true
  236. },
  237. },
  238. methods: {
  239. exePrint(){
  240. this.infoShow = true;
  241. if (!this.printInfo.signer){
  242. window.tempTip.setIndex(1099);
  243. window.tempTip.show("请填写签收人");
  244. return;
  245. }
  246. $("#printModal").modal('hide');
  247. let iframe=document.getElementById("print-iframe");
  248. if(!iframe){
  249. let el = document.getElementById("printContent");
  250. iframe = document.createElement('IFRAME');
  251. iframe.setAttribute("id", "print-iframe");
  252. iframe.setAttribute('style', 'position:absolute;width:0;height:0;left:-500px;top:-500px;');
  253. document.body.appendChild(iframe);
  254. let doc = iframe.contentWindow.document;
  255. doc.write('<LINK rel="stylesheet" type="text/css" href="{{ asset(mix("css/app.css")) }}">');
  256. doc.write('<div>' + el.innerHTML + '</div>');
  257. doc.close();
  258. iframe.contentWindow.focus();
  259. }
  260. this.infoShow = false;
  261. setTimeout(function () {
  262. iframe.contentWindow.print();
  263. if (navigator.userAgent.indexOf("MSIE") > 0){
  264. document.body.removeChild(iframe);
  265. }
  266. },200);
  267. },
  268. _renderingForm(){
  269. let data=[
  270. [
  271. {name:'created_at_start',type:'dateTime',tip:"选择显示创建日期的结束时间"},
  272. {name:'appointment_date_start',type:'dateTime',tip:"选择显示预约日期的结束时间"},
  273. {name:'owner_id',type:'select_multiple_select',tip:['输入关键词快速定位下拉列表,回车确定','选择要显示的客户'],
  274. placeholder:['货主','定位或多选货主'],data:this.owners},
  275. {name:'status',type:'select',placeholder: '状态',data:this.status},
  276. ],
  277. [
  278. {name:'created_at_end',type:'dateTime',tip:"选择显示创建日期的结束时间"},
  279. {name:'appointment_date_end',type:'dateTime',tip:"选择显示预约日期的结束时间"},
  280. {name:'warehouse_id',type:'select',placeholder: '仓库',data:this.warehouses},
  281. ],
  282. ];
  283. let form = new query({
  284. el:"#form",
  285. condition:data,
  286. });
  287. form.init();
  288. },
  289. upAll(id){
  290. let dom = "#item-"+id;
  291. if (this.upList[id]) $(dom).slideUp();
  292. else $(dom).slideDown();
  293. this.$set(this.upList,id,!this.upList[id]);
  294. },
  295. upAllDetail(id){
  296. let dom = "#detail-"+id;
  297. if (this.upListDetail[id]) $(dom).slideUp();
  298. else $(dom).slideDown();
  299. this.$set(this.upListDetail,id,!this.upListDetail[id]);
  300. },
  301. unloading(i,j){
  302. window.tempTip.confirm("确定已经完成卸货?",()=>{
  303. window.tempTip.postBasicRequest("{{url('store/deliveryAppointment/unloading')}}",{id:this.list[i].cars[j].id},res=>{
  304. this.list[i].cars[j].status = 2;
  305. if (this.list[i].cars.every(car=>{
  306. if (car.status!=2)return false;
  307. return true
  308. }))this.list[i].status = 2;
  309. return "成功确认";
  310. })
  311. })
  312. },
  313. cancel(id,index){
  314. window.tempTip.confirm("确定要取消该次预约吗?此操作不可逆,请谨慎选择",()=>{
  315. window.tempTip.postBasicRequest("{{url('store/deliveryAppointment/cancel')}}",{id:id},res=>{
  316. this.$set(this.list[index],"status",res);
  317. return "成功取消该单预约";
  318. })
  319. })
  320. },
  321. checkAll(e){
  322. if (e.target.checked){
  323. this.checkData = [];
  324. this.list.forEach((el)=>{
  325. this.checkData.push(el.id);
  326. });
  327. }else this.checkData = [];
  328. },
  329. executeExport(isAll){
  330. let url = '{{url('store/deliveryAppointment/export')}}';
  331. let token='{{ csrf_token() }}';
  332. excelExport(isAll,this.checkData,url,this.sum,token);
  333. },
  334. updateDeliveryDate(info,index){
  335. for (let i=0;i<info.cars.length;i++){
  336. if (info.cars[i].status!=0){
  337. window.tempTip.setDuration("3000");
  338. window.tempTip.show("车辆已达,无法修改预约");
  339. return;
  340. }
  341. this.index = index;
  342. let param = {
  343. model:info,
  344. detail_amount:info.details.length,
  345. };
  346. window.tempTip.postBasicRequest("{{url('store/deliveryAppointment/getCapacity')}}",param,res=>{
  347. this.capacities = res;
  348. $("#modal").modal("show");
  349. });
  350. }
  351. },
  352. submitAppointment(){
  353. window.tempTip.setDuration(3000);
  354. window.tempTip.setIndex(1099);
  355. if (!this.selectDate.date){
  356. window.tempTip.show("尚未选择预约时间");
  357. return;
  358. }
  359. let url = "{{url('store/deliveryAppointment/updateAppointment')}}";
  360. let param = {
  361. id:this.list[this.index].id,
  362. date:this.selectDate,
  363. };
  364. window.tempTip.postBasicRequest(url,param,res=>{
  365. if (res && res.isFail){
  366. this.capacities.some(capacity=>{
  367. if (capacity.date === this.selectDate.date){
  368. capacity.period.some(p=>{
  369. if (p.index === this.selectDate.time){
  370. p.isAvailable = false;
  371. return true;
  372. }
  373. });
  374. return true;
  375. }
  376. });
  377. this.selectDate={};
  378. window.tempTip.show("该预约时段已经被抢占了,请选择其他时段");
  379. return;
  380. }
  381. this.list[this.index].appointment_date = this.selectDate.date;
  382. this.list[this.index].date_period = this.selectDate.time;
  383. this.list[this.index].period = this.periods[this.selectDate.time];
  384. $("#modal").modal("hide");
  385. return "修改预约时间成功";
  386. },true);
  387. },
  388. selectPeriod(date,time,isSelect){
  389. if (isSelect) this.selectDate = {date:date,time:time};
  390. },
  391. qualityInspectionMark(){
  392. if (this.checkData.length<1){
  393. window.tempTip.setDuration("3000");
  394. window.tempTip.show("未勾选记录");
  395. return;
  396. }
  397. let url = "{{url('store/deliveryAppointment/qualityInspectionMark')}}";
  398. window.tempTip.postBasicRequest(url,{ids:this.checkData},()=>{
  399. this.list.forEach(data=>{
  400. if (this.checkData.indexOf(data.id)!==-1){
  401. data.type_mark = 0;
  402. }
  403. });
  404. return "标记质检成功";
  405. });
  406. },
  407. printReceipt(info){
  408. let d = new Date();
  409. let str = '';
  410. str += d.getFullYear() + '年';
  411. str += d.getMonth() + 1 + '月';
  412. str += d.getDate() + '日';
  413. str += d.getHours() + '时';
  414. str += d.getMinutes() + '分';
  415. str += d.getSeconds() + '秒';
  416. this.printInfo = info;
  417. this.printInfo.print_date = str;
  418. $("#printModal").modal("show");
  419. },
  420. warpText(code){
  421. if (!code)return code;
  422. code = code.split(/[,, ]+/is);
  423. let str = "";
  424. for (let i=0;i<code.length;i++){
  425. str += code[i]+"<br>";
  426. }
  427. return str;
  428. }
  429. },
  430. filters:{
  431. getCommodity(detail){
  432. if (!detail.commodity_id)return detail.name;
  433. if (detail.commodity && detail.commodity.barcodes.length>0)return detail.commodity.barcodes[0].code;
  434. return "";
  435. },
  436. },
  437. });
  438. </script>
  439. @stop