exhibition.blade.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. <!DOCTYPE html>
  2. <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. <link rel="icon" href="{{asset('icon/faviconc.ico')}}" type="image/x-icon"/>
  7. <!-- CSRF Token -->
  8. <meta name="csrf-token" content="{{ csrf_token() }}">
  9. <title>入库区终端-入库预约</title>
  10. <link href="{{ mix('css/app.css') }}" rel="stylesheet">
  11. <style>
  12. html{
  13. background: white;
  14. height: 100%;
  15. width: 100%;
  16. }
  17. .h-90{
  18. height: 90%;
  19. }
  20. .h-10{
  21. height: 10%;
  22. }
  23. #msg{
  24. width:266px;
  25. position: fixed;
  26. z-index:999;
  27. top: 49%;
  28. margin-top:-80px;
  29. left:50%;
  30. margin-left:-133px;
  31. background:#fff;
  32. box-shadow:5px 5px 8px #999;
  33. font-size:17px;
  34. color:#666;
  35. border:1px solid #f8f8f8;
  36. text-align: center;
  37. line-height: 2rem;
  38. display:inline-block;
  39. padding-bottom:20px;
  40. border-radius:5px;
  41. }
  42. #msg_top {
  43. background: #f8f8f8;
  44. padding: 5px 15px 5px 20px;
  45. text-align: left;
  46. }
  47. #msg_top span{
  48. font-size:22px;
  49. float:right;
  50. cursor:pointer;
  51. }
  52. #msg_cont{
  53. padding:15px 20px 20px;
  54. text-align:left;
  55. }
  56. #msg_clear{
  57. background:#8fc31f;
  58. float:right;
  59. }
  60. #msg_success{
  61. background:#2a9055;
  62. float:right;
  63. }
  64. .msg_btn{
  65. display:inline-block;
  66. color:#fff;
  67. padding:1px 15px;
  68. border-radius:2px;
  69. margin-right:15px;
  70. cursor:pointer;
  71. }
  72. hr{
  73. border: 2px solid #1b1e21;
  74. border-radius: 2px;
  75. }
  76. .modal-body-div{
  77. width: 30%;
  78. display: inline-block;
  79. }
  80. .modal-body-item{
  81. margin: 10px;
  82. border: 2px solid #aaaaaa;
  83. border-radius: 5px;
  84. height:100px;
  85. text-align: center;
  86. display: flex;
  87. align-items: center;
  88. justify-content: center;
  89. flex-direction: column
  90. }
  91. .modal-body-item-text{
  92. margin-left:10%;
  93. width: 80%;
  94. }
  95. .br-1{
  96. border-right:2px solid #aaaaaa;
  97. }
  98. table{
  99. border-top: 3px solid #1b1e21;
  100. }
  101. </style>
  102. </head>
  103. <body onload="initLoad()" class="h-100">
  104. <div class="container-fluid h-100 d-none" id="container">
  105. <div class="ml-5 h1 font-weight-bold mt-2 mb-0 h-10">
  106. <div class="h-5"></div>
  107. <div class="h-5 h6">
  108. <div class="font-weight-bold row">
  109. <div class="col-2"><span class="fa fa-diamond text-info"></span>&nbsp;当天预约车辆:</div>
  110. <div class="col-8 m-0">
  111. <div class="progress">
  112. <div class="progress-bar bg-info progress-bar-striped" :style="{width:(count.total>0 ? (count.work/count.total)*100 : 0)+'%'}">作业中:@{{ count.work }}</div>
  113. <div class="progress-bar bg-secondary progress-bar-striped" :style="{width:(count.total>0 ? (count.notReached/count.total)*100 : 0)+'%'}">待送达:@{{ count.notReached }}</div>
  114. <div class="progress-bar bg-success progress-bar-striped" :style="{width:(count.total>0 ? (count.success/count.total)*100 : 100)+'%'}">已完成:@{{ count.success }}</div>
  115. </div>
  116. </div>
  117. </div>
  118. <hr class="font-weight-bold">
  119. </div>
  120. </div>
  121. <div class="row h-90 mt-0">
  122. <div class="col-8 br-1">
  123. <div class="w-100 text-center">
  124. <h1 class="font-weight-bold">当日预约</h1>
  125. </div>
  126. <table class="table w-100 h3">
  127. <tr>
  128. <th>货主</th>
  129. <th>车牌/预约号</th>
  130. <th>吨位/立方</th>
  131. <th>特殊要求</th>
  132. <th>预约时间</th>
  133. <th>到场时间</th>
  134. <th>状态</th>
  135. </tr>
  136. <tr v-for="data in list">
  137. <td class="text-secondary">@{{ data.owner_name }}</td>
  138. <td class="text-danger">@{{ data.license_plate_number }}</td>
  139. <td class="text-secondary"><i v-if="data.tonne">@{{ data.tonne }}吨</i><br><i v-if="data.cubic_meter">@{{ data.cubic_meter }}立方</i></td>
  140. <td class="text-primary">@{{ data.type }}</td>
  141. <td class="text-secondary">@{{ data.period }}</td>
  142. <td class="text-secondary">@{{ data.delivery_time }}</td>
  143. <td :class="data.status == '未送达' ? 'text-dark' : (data.status=='作业中' ? 'text-primary' : 'text-success')">@{{ data.status }}</td>
  144. </tr>
  145. </table>
  146. </div>
  147. <div class="col-4">
  148. <div class="w-100 text-center">
  149. <h2 class="font-weight-bold">后续预约</h2>
  150. </div>
  151. <table class="table w-100 h4">
  152. <tr>
  153. <th>货主</th>
  154. <th>车牌/预约号</th>
  155. <th>吨位/立方</th>
  156. <th>特殊要求</th>
  157. <th>预约时间</th>
  158. </tr>
  159. <tr v-for="data in nextList">
  160. <td class="text-secondary">@{{ data.owner_name }}</td>
  161. <td class="text-danger">@{{ data.license_plate_number }}</td>
  162. <td class="text-secondary"><i v-if="data.tonne">@{{ data.tonne }}吨</i><br><i v-if="data.cubic_meter">@{{ data.cubic_meter }}立方</i></td>
  163. <td class="text-primary">@{{ data.type }}</td>
  164. <td class="text-secondary">@{{ data.period }}</td>
  165. <td class="text-secondary">@{{ data.delivery_time }}</td>
  166. <td :class="data.status == '未送达' ? 'text-dark' : (data.status=='作业中' ? 'text-primary' : 'text-success')">@{{ data.status }}</td>
  167. </tr>
  168. </table>
  169. </div>
  170. </div>
  171. <div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static">
  172. <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
  173. <div class="modal-content">
  174. <div class="modal-header">
  175. <div class="text-center font-weight-bold">选择仓库</div>
  176. </div>
  177. <div class="modal-body" id="modal-body"></div>
  178. <div class="modal-footer">
  179. <button class="btn btn-success" onclick="selectedWarehouse()"> 确 定 </button>
  180. </div>
  181. </div>
  182. </div>
  183. </div>
  184. </div>
  185. </body>
  186. <script src="{{ mix('js/app.js') }}"></script>
  187. <script src="{{ mix('js/utilities/qrcode.js') }}"></script>
  188. <script type="text/javascript">
  189. var warehouses = [@foreach($warehouses as $warehouse)@json($warehouse),@endforeach];
  190. var warehouse = "{{$id}}";
  191. var selected = "";
  192. //初始化询问
  193. function initLoad() {
  194. if (!warehouse){
  195. let dom = document.getElementById("modal-body");
  196. for (let i=0;i<warehouses.length;i++){
  197. let div = document.createElement("div");
  198. div.className="modal-body-div";
  199. let div1 = document.createElement("div");
  200. div1.className="modal-body-item";
  201. div1.style.cursor = "pointer";
  202. div1.dataset.id = warehouses[i].id;
  203. div1.id = "warehouse-"+warehouses[i].id;
  204. if (i===0){
  205. div1.className += " box-shadow-dark";
  206. selected = "warehouse-"+warehouses[i].id;
  207. }
  208. div1.onclick = function(){
  209. let dom = event.target;
  210. while (!dom.id)dom = dom.parentElement;
  211. if (dom.id===selected)return;
  212. document.getElementById(selected).className = "modal-body-item";
  213. document.getElementById(dom.id).className = "modal-body-item box-shadow-dark";
  214. selected = dom.id;
  215. };
  216. let div2 = document.createElement("div");
  217. div2.className="modal-body-item-text";
  218. div2.innerText = warehouses[i].name;
  219. div1.appendChild(div2);
  220. div.appendChild(div1);
  221. dom.appendChild(div);
  222. }
  223. $("#modal").modal('show');
  224. }else alert("是否需要开启全屏?");
  225. }
  226. function selectedWarehouse() {
  227. if (!selected) return;
  228. warehouse = document.getElementById(selected).dataset.id;
  229. vue._initData();
  230. history.pushState(null,null,window.location.href+"?warehouse="+warehouse);
  231. $("#modal").modal('hide');
  232. alert("是否需要开启全屏?");
  233. }
  234. //重绘弹窗样式
  235. function alert(e){
  236. $("body").append('<div id="msg"><div id="msg_top">设置<span class="msg_close">×</span></div><div id="msg_cont">'+e+
  237. '</div><div class="msg_close msg_btn" id="msg_clear">取消</div><div class="msg_close msg_btn" id="msg_success" onclick="launchFullScreen()">确定</div></div>');
  238. $(".msg_close").click(function (){
  239. $("#msg").remove();
  240. });
  241. }
  242. //全屏
  243. function launchFullScreen() {
  244. let element = window.document.body;
  245. if (element.requestFullscreen) {
  246. element.requestFullscreen();
  247. } else if (element.mozRequestFullScreen) {
  248. element.mozRequestFullScreen();
  249. } else if (element.webkitRequestFullscreen) {
  250. element.webkitRequestFullscreen();
  251. } else if (element.msRequestFullscreen) {
  252. element.msRequestFullscreen();
  253. }
  254. }
  255. let vue = new Vue({
  256. el:"#container",
  257. data:{
  258. list:[],
  259. nextList:[],
  260. key:"",
  261. baseUrl:"{{url('store/deliveryAppointment/delivery?k=')}}",
  262. QrCode : null,
  263. count : {
  264. total : 0,
  265. success : 0,
  266. notReached : 0,
  267. work : 0,
  268. },
  269. },
  270. mounted(){
  271. $("#container").removeClass("d-none");
  272. if (warehouse) this._initData();
  273. this._broadcast();
  274. /*this._getKey();
  275. setTimeout(()=>{
  276. //刷新密匙
  277. this._getKey()
  278. },this._getDiffDate());
  279. setInterval(()=>{
  280. this._createQrCode(this.baseUrl+this.base64());
  281. },60000);*/
  282. },
  283. methods:{
  284. _broadcast(){
  285. initEcho();
  286. window.Echo.channel('{{config('database.redis.options.prefix')}}delivery').listen('.car',(res)=>{this._sortData(res.delivery)})
  287. },
  288. _countChange(oldStatus,newStatus){
  289. switch (oldStatus) {
  290. case '未送达':
  291. this.count.notReached--;
  292. break;
  293. case '作业中':
  294. this.count.work--;
  295. break;
  296. }
  297. if (!oldStatus && newStatus)this.count.total++;
  298. switch (newStatus) {
  299. case '未送达':
  300. this.count.notReached++;
  301. break;
  302. case '作业中':
  303. this.count.work++;
  304. break;
  305. case '已完成':
  306. this.count.success++;
  307. break;
  308. }
  309. },
  310. _formatObj(res){
  311. return {
  312. "id" : res.id,
  313. "license_plate_number" : res.license_plate_number,
  314. "driver_name" : res.driver_name,
  315. "driver_phone" : res.driver_phone,
  316. "cubic_meter" : res.cubic_meter,
  317. "tonne" : res.tonne,
  318. "owner_name" : res.owner_name,
  319. "type" : res.type,
  320. "period" : res.period,
  321. "delivery_time" : res.delivery_time,
  322. "status" : res.status,
  323. };
  324. },
  325. _sortData(res){
  326. if (res.warehouse!=warehouse)return;
  327. if (res.change){
  328. let continueMark = true;
  329. switch (Number(res.old)) {
  330. case 0:
  331. switch (Number(res.new)) {
  332. case 0:
  333. continueMark = false;
  334. break;
  335. default:
  336. this.list.some((data,i)=>{
  337. if (data.id==res.id){
  338. this.$delete(this.list,i);
  339. return true;
  340. }
  341. });
  342. if (Number(res.old)===1) continueMark = false;
  343. break;
  344. }
  345. break;
  346. case 1:
  347. this.nextList.some((data,i)=>{
  348. if (data.id==res.id){
  349. if (res.new!=1)this.$delete(this.nextList,i);
  350. else this.$set(this.nextList,i,this._formatObj(res));
  351. return true;
  352. }
  353. });
  354. if (res.new==0) continueMark = false;
  355. break;
  356. case 2:
  357. continueMark = false;
  358. break;
  359. }
  360. if (continueMark) return;
  361. }
  362. if (res.morrow){
  363. if (this.nextList.length>=10) this.nextList = this.nextList.splice(0,9);
  364. this.nextList.push(this._formatObj(res));
  365. return;
  366. }
  367. if (this.list.every((data,i)=>{
  368. if (data.id === res.id){
  369. this._countChange(data.status,res.status);
  370. data = this._formatObj(res);
  371. this.list.splice(i,1);
  372. if (data.status=='1'){
  373. if (this.list.every((car,j)=>{
  374. if (car.status!=data.status){
  375. this.list.splice(j,0,data);
  376. return false;
  377. }
  378. return true;
  379. }))this.list.push(data);
  380. }else this.list.push(data);
  381. return false;
  382. }
  383. return true;
  384. })){
  385. this._countChange(null,res.status);
  386. if (this.list.length>=10) this.list = this.list.splice(0,9);
  387. let obj = this._formatObj(res);
  388. if (res.status=='1'){
  389. if (this.list.every((car,j)=>{
  390. if (car.status!=res.status){
  391. this.list.splice(j,0,obj);
  392. return false;
  393. }
  394. return true;
  395. }))this.list.push(obj);
  396. }else this.list.push(obj);
  397. }
  398. /*setTimeout(()=>{
  399. this.list.some((data,i)=>{
  400. if (data.license_plate_number === res.license_plate_number) {
  401. this.$set(this.list[i],"is_delivery",false);
  402. return true;
  403. }
  404. });
  405. },1800000);*/
  406. },
  407. //初始化数据
  408. _initData(){
  409. let url = "{{url('store/deliveryAppointment/getExhibitionList')}}";
  410. window.tempTip.postBasicRequest(url,{warehouse:warehouse},res=>{
  411. if (!res)return;
  412. if (res.list){
  413. /*let data = res.list;
  414. data.forEach((item,i)=>{
  415. if (item.diff){
  416. data[i].is_delivery = true;
  417. setTimeout(()=>{
  418. this.list.some((data,i)=>{
  419. if (data.license_plate_number === item.license_plate_number) {
  420. this.$set(this.list[i],"is_delivery",false);
  421. return true;
  422. }
  423. });
  424. },item.diff);
  425. }
  426. });*/
  427. this.list = res.list;
  428. this.nextList = res.nextDay;
  429. this.count.notReached = res.notReached;
  430. this.count.success = res.success;
  431. this.count.work = res.work;
  432. this.count.total = res.notReached+res.success+res.work;
  433. }
  434. //判断下次刷新数据的时间
  435. let refreshVal = res.refresh ? res.refresh : this._getDiffDate();
  436. setTimeout(()=>{
  437. this._initData();
  438. },refreshVal);
  439. });
  440. },
  441. /*//获取密匙
  442. _getKey(){
  443. let url = "{{--{{url('store/deliveryAppointment/getKey')}}--}}";
  444. window.tempTip.postBasicRequest(url,{},res=>{
  445. this.key = res;
  446. this._createQrCode(this.baseUrl+this.base64());
  447. });
  448. },
  449. //生成二维码
  450. _createQrCode(text){
  451. if (!this.QrCode){
  452. let dom = document.getElementById("code");
  453. let height = dom.parentNode.offsetHeight<dom.parentNode.offsetWidth ? dom.parentNode.offsetHeight : dom.parentNode.offsetWidth;
  454. this.QrCode = new QRCode(dom,{
  455. text: text,
  456. width: height*1.4,
  457. height: height,
  458. colorDark : "#000000",
  459. colorLight : "#ffffff",
  460. }
  461. );
  462. }else{
  463. this.QrCode.clear();
  464. this.QrCode.makeCode(text);
  465. }
  466. },*/
  467. //获取当前时间距离明天0点的时间差 毫秒
  468. _getDiffDate(){
  469. let now = new Date();
  470. let dateTime = now.getTime();
  471. let yy = now.getFullYear();
  472. let mm = now.getMonth() + 1;
  473. let dd = now.getDate();
  474. let clock = yy + "-";
  475. if(mm < 10) clock += "0";
  476. clock += mm + "-";
  477. if(dd < 10) clock += "0";
  478. clock += dd+" 00:00:00";
  479. let timestamp = new Date(clock).getTime()+(24*60*60*1000);
  480. return timestamp-dateTime;
  481. },
  482. /*//加密
  483. base64(){
  484. let _keyStr= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  485. let output = "";
  486. let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  487. let i = 0;
  488. let str = Math.floor(new Date().getTime()/1000).toString();
  489. str = str.slice(str.length-8);
  490. let input = this._utf8_encode(this.key+str);
  491. while (i < input.length) {
  492. chr1 = input.charCodeAt(i++);
  493. chr2 = input.charCodeAt(i++);
  494. chr3 = input.charCodeAt(i++);
  495. enc1 = chr1 >> 2;
  496. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  497. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  498. enc4 = chr3 & 63;
  499. if (isNaN(chr2)) {
  500. enc3 = enc4 = 64;
  501. } else if (isNaN(chr3)) {
  502. enc4 = 64;
  503. }
  504. output = output +
  505. _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
  506. _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
  507. }
  508. return output;
  509. },
  510. _utf8_encode (string) {
  511. string = string.replace(/\r\n/g,"\n");
  512. let utftext = "";
  513. for (let n = 0; n < string.length; n++) {
  514. let c = string.charCodeAt(n);
  515. if (c < 128) {
  516. utftext += String.fromCharCode(c);
  517. } else if((c > 127) && (c < 2048)) {
  518. utftext += String.fromCharCode((c >> 6) | 192);
  519. utftext += String.fromCharCode((c & 63) | 128);
  520. } else {
  521. utftext += String.fromCharCode((c >> 12) | 224);
  522. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  523. utftext += String.fromCharCode((c & 63) | 128);
  524. }
  525. }
  526. return utftext;
  527. }*/
  528. },
  529. });
  530. </script>
  531. </html>