warehouseOne.html 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=1920" />
  6. <title>无人线边仓库看板</title>
  7. <link rel="stylesheet" href="./css/common.css" />
  8. <link rel="stylesheet" href="./css/board1.css" />
  9. <script type="text/javascript" src="./plugin/jquery.min.js"></script>
  10. <script type="text/javascript" src="./plugin/echarts.min.js"></script>
  11. <script type="text/javascript" src="./plugin/vue.min.js"></script>
  12. <script type="text/javascript" src="./js/util.js"></script>
  13. <script type="text/javascript" src="./js/common.js"></script>
  14. <script src="./plugin/datav.min.js"></script>
  15. <script type="text/javascript" src="./js/chart.js"></script>
  16. </head>
  17. <script>
  18. $(window).load(function () {
  19. $(".loading").fadeOut();
  20. });
  21. //动态设置视口
  22. const setSize = () => {
  23. // 获取html元素
  24. const html = document.getElementsByTagName("html")[0];
  25. // 获取屏幕宽度
  26. const pageWidth = html.getBoundingClientRect().width;
  27. // 动态计算字体大小(rem)
  28. html.style.fontSize = pageWidth / 20 + "px";
  29. };
  30. setSize();
  31. window.addEventListener("resize", setSize, false);
  32. </script>
  33. <body>
  34. <div class="loading">
  35. <div class="load_box">
  36. <img src="./images/loading.gif" /> 看板加载中,请稍等...
  37. </div>
  38. </div>
  39. <div id="app" class="container">
  40. <div class="head">
  41. <h1>无人线边仓库看板</h1>
  42. <span id="showTime"></span>
  43. </div>
  44. <div class="box">
  45. <span class="title day-title">近七日出入库数据</span>
  46. <div
  47. style="
  48. height: 4rem;
  49. position: absolute;
  50. width: 4.6rem;
  51. top: 1rem;
  52. left: 0.4rem;
  53. "
  54. id="daysChart"
  55. ></div>
  56. </div>
  57. <div class="box">
  58. <span class="title position-title">今日出入库货位</span>
  59. <div
  60. style="
  61. height: 4.5rem;
  62. position: absolute;
  63. width: 4.6rem;
  64. top: 5.4rem;
  65. left: 0.4rem;
  66. "
  67. id="positionChart"
  68. ></div>
  69. </div>
  70. <div class="box">
  71. <!-- <span class="title count frock-title">工装库存</span> -->
  72. <span class="count-number clamp-quantity">{{clampQuantity}}</span>
  73. </div>
  74. <div class="box">
  75. <!-- <span class="title count total-title">总库存</span> -->
  76. <span class="count-number inventory-quantity"
  77. >{{inventoryQuantity}}</span
  78. >
  79. </div>
  80. <div class="box">
  81. <!-- <span class="title count device-title">设备库存</span> -->
  82. <span class="count-number instrument-quantity"
  83. >{{instrumentQuantity}}</span
  84. >
  85. </div>
  86. <div class="box">
  87. <span class="title year-title">年领用数据统计</span>
  88. <div
  89. style="
  90. height: 3rem;
  91. position: absolute;
  92. width: 9.2rem;
  93. top: 3.1rem;
  94. left: 5.2rem;
  95. "
  96. id="yearChart"
  97. ></div>
  98. </div>
  99. <div class="box">
  100. <span class="title goIn-title">出入库记录</span>
  101. <div>
  102. <dv-scroll-board
  103. ref="scrollBoard"
  104. style="
  105. height: 2.8rem;
  106. position: absolute;
  107. width: 8.8rem;
  108. top: 6.86rem;
  109. left: 5.5rem;
  110. "
  111. :config="recordConfig"
  112. />
  113. </div>
  114. </div>
  115. <div class="box">
  116. <span class="title type-title">今日出入库类型</span>
  117. <div
  118. style="
  119. height: 4.2rem;
  120. position: absolute;
  121. width: 5rem;
  122. top: 0.4rem;
  123. right: 0.3rem;
  124. "
  125. id="typeChart"
  126. ></div>
  127. </div>
  128. <div class="box">
  129. <span class="title hot-title">热门使用Top5</span>
  130. <div
  131. style="
  132. height: 2.6rem;
  133. position: absolute;
  134. width: 5rem;
  135. top: 4.4rem;
  136. right: 0.2rem;
  137. "
  138. id="hotChart"
  139. ></div>
  140. </div>
  141. <div class="box">
  142. <span class="title use-title">领用排行Top5</span>
  143. <div
  144. style="
  145. height: 2.6rem;
  146. position: absolute;
  147. width: 5rem;
  148. top: 7.2rem;
  149. right: 0.2rem;
  150. "
  151. id="useChart"
  152. ></div>
  153. </div>
  154. </div>
  155. <div class="back"></div>
  156. <script>
  157. var app = new Vue({
  158. el: "#app",
  159. data() {
  160. return {
  161. timer: null,
  162. clampQuantity: null,
  163. inventoryQuantity: null,
  164. instrumentQuantity: null,
  165. daysChart: null,
  166. positionChart: null,
  167. yearChart: null,
  168. typeChart: null,
  169. hotChart: null,
  170. useChart: null,
  171. recordConfig: {
  172. header: [
  173. '<span style="color:#3ac7e9;font-size:0.16rem">序号</span>',
  174. '<span style="color:#3ac7e9;font-size:0.16rem">名称</span>',
  175. '<span style="color:#3ac7e9;font-size:0.16rem">图号</span>',
  176. '<span style="color:#3ac7e9;font-size:0.16rem">类型</span>',
  177. '<span style="color:#3ac7e9;font-size:0.16rem">规格</span>',
  178. '<span style="color:#3ac7e9;font-size:0.16rem">操作时间</span>',
  179. '<span style="color:#3ac7e9;font-size:0.16rem">操作人</span>',
  180. ],
  181. columnWidth: [60, 140, 160, 90, 120, 160, 120],
  182. data: [],
  183. align: [
  184. "center",
  185. "center",
  186. "center",
  187. "center",
  188. "center",
  189. "center",
  190. "center",
  191. ],
  192. headerBGC: "transparent",
  193. oddRowBGC: "transparent",
  194. evenRowBGC: "transparent",
  195. },
  196. tableDatas: [],
  197. dayDatas: [],
  198. outStockDatas: [],
  199. inStockDatas: [],
  200. yearDatas: [],
  201. inTypeDatas: {},
  202. outTypeDatas: {},
  203. hotDatas: [],
  204. useDatas: [],
  205. outDatas: {},
  206. inDatas: {},
  207. };
  208. },
  209. methods: {
  210. // 获取当前展示的仓库id
  211. getWarehouseId() {
  212. const _self = this;
  213. const params = getQueryString();
  214. _self.warehouseId = params.warehouseId;
  215. },
  216. // 创建出入库柱状图
  217. createDaysChart() {
  218. const _self = this;
  219. const daysOption = drawDaysChart();
  220. initChart(_self.daysChart, daysOption);
  221. },
  222. createPositionChart() {
  223. const _self = this;
  224. const positionOption = drawPositionChart();
  225. initChart(_self.positionChart, positionOption);
  226. },
  227. createYearChart() {
  228. const _self = this;
  229. const yearOption = drawYearChart();
  230. initChart(_self.yearChart, yearOption);
  231. },
  232. createTypeChart() {
  233. const _self = this;
  234. const typeOption = drawTypeChart();
  235. initChart(_self.typeChart, typeOption);
  236. },
  237. createHotChart() {
  238. const _self = this;
  239. const hotOption = drawTopChart();
  240. initChart(_self.hotChart, hotOption);
  241. },
  242. createUseChart() {
  243. const _self = this;
  244. const useOption = drawTopChart();
  245. initChart(_self.useChart, useOption);
  246. },
  247. // 获取看板信息
  248. getWarehouseInfo() {
  249. const _self = this;
  250. const url = "/api/WmsResource/queryBoardStatistic";
  251. const params = [["warehouseId", _self.warehouseId]];
  252. // const success = {
  253. // errorCode: 0,
  254. // errorMessage: null,
  255. // data: {
  256. // todayStockIn: 0,
  257. // todayStockOut: 0,
  258. // stockInCategory: {
  259. // clampQuantity: 0,
  260. // instrumentQuantity: 0,
  261. // productQuantity: 0,
  262. // },
  263. // stockOutCategory: {
  264. // clampQuantity: 0,
  265. // instrumentQuantity: 0,
  266. // productQuantity: 0,
  267. // },
  268. // stockInPosition: {
  269. // stereoscopicQuantity: 0,
  270. // groundQuantity: 0,
  271. // toolQuantity: 0,
  272. // equipmentQuantity: 0,
  273. // finishedQuantity: 0,
  274. // },
  275. // stockOutPosition: {
  276. // stereoscopicQuantity: 0,
  277. // groundQuantity: 0,
  278. // toolQuantity: 0,
  279. // equipmentQuantity: 0,
  280. // finishedQuantity: 0,
  281. // },
  282. // weekStatisticList: [
  283. // {
  284. // day: "2026-01-17",
  285. // inCount: 0,
  286. // outCount: 0,
  287. // },
  288. // {
  289. // day: "2026-01-18",
  290. // inCount: 0,
  291. // outCount: 0,
  292. // },
  293. // {
  294. // day: "2026-01-19",
  295. // inCount: 1,
  296. // outCount: 1,
  297. // },
  298. // {
  299. // day: "2026-01-20",
  300. // inCount: 12,
  301. // outCount: 12,
  302. // },
  303. // {
  304. // day: "2026-01-21",
  305. // inCount: 0,
  306. // outCount: 0,
  307. // },
  308. // {
  309. // day: "2026-01-22",
  310. // inCount: 0,
  311. // outCount: 0,
  312. // },
  313. // {
  314. // day: "2026-01-23",
  315. // inCount: 0,
  316. // outCount: 0,
  317. // },
  318. // ],
  319. // popularInvList: [
  320. // {
  321. // invName: "工装101",
  322. // count: 81,
  323. // },
  324. // {
  325. // invName: "测试设备01501",
  326. // count: 60,
  327. // },
  328. // {
  329. // invName: "工装-1",
  330. // count: 47,
  331. // },
  332. // {
  333. // invName: "测试设备101",
  334. // count: 21,
  335. // },
  336. // {
  337. // invName: "设备-3",
  338. // count: 17,
  339. // },
  340. // {
  341. // invName: "设备-2",
  342. // count: 6,
  343. // },
  344. // {
  345. // invName: "设备-4",
  346. // count: 5,
  347. // },
  348. // {
  349. // invName: "测试工装00015",
  350. // count: 5,
  351. // },
  352. // {
  353. // invName: "设备-1",
  354. // count: 3,
  355. // },
  356. // {
  357. // invName: "测试工装00005",
  358. // count: 2,
  359. // },
  360. // ],
  361. // popularUserList: [
  362. // {
  363. // userName: "admin",
  364. // count: 138,
  365. // },
  366. // {
  367. // userName: "测试用户甲",
  368. // count: 100,
  369. // },
  370. // {
  371. // userName: "操作员",
  372. // count: 13,
  373. // },
  374. // {
  375. // userName: "测试用户丁",
  376. // count: 3,
  377. // },
  378. // ],
  379. // inventoryQuantity: 2998,
  380. // clampQuantity: 1498,
  381. // instrumentQuantity: 1500,
  382. // invUseTimeList: null,
  383. // agvTaskList: null,
  384. // cfInAndOutResponses: [],
  385. // monthPickList: [
  386. // {
  387. // month: "2025-02",
  388. // pickCount: 0,
  389. // clampCount: 0,
  390. // instrumentCount: 0,
  391. // },
  392. // {
  393. // month: "2025-03",
  394. // pickCount: 0,
  395. // clampCount: 0,
  396. // instrumentCount: 0,
  397. // },
  398. // {
  399. // month: "2025-04",
  400. // pickCount: 0,
  401. // clampCount: 0,
  402. // instrumentCount: 0,
  403. // },
  404. // {
  405. // month: "2025-05",
  406. // pickCount: 0,
  407. // clampCount: 0,
  408. // instrumentCount: 0,
  409. // },
  410. // {
  411. // month: "2025-06",
  412. // pickCount: 0,
  413. // clampCount: 0,
  414. // instrumentCount: 0,
  415. // },
  416. // {
  417. // month: "2025-07",
  418. // pickCount: 0,
  419. // clampCount: 0,
  420. // instrumentCount: 0,
  421. // },
  422. // {
  423. // month: "2025-08",
  424. // pickCount: 0,
  425. // clampCount: 0,
  426. // instrumentCount: 0,
  427. // },
  428. // {
  429. // month: "2025-09",
  430. // pickCount: 0,
  431. // clampCount: 0,
  432. // instrumentCount: 0,
  433. // },
  434. // {
  435. // month: "2025-10",
  436. // pickCount: 0,
  437. // clampCount: 0,
  438. // instrumentCount: 0,
  439. // },
  440. // {
  441. // month: "2025-11",
  442. // pickCount: 0,
  443. // clampCount: 0,
  444. // instrumentCount: 0,
  445. // },
  446. // {
  447. // month: "2025-12",
  448. // pickCount: 0,
  449. // clampCount: 0,
  450. // instrumentCount: 0,
  451. // },
  452. // {
  453. // month: "2026-01",
  454. // pickCount: 190,
  455. // clampCount: 112,
  456. // instrumentCount: 78,
  457. // },
  458. // ],
  459. // },
  460. // };
  461. ajaxGet(url, params).then((success) => {
  462. if (success.errorCode === 0) {
  463. const { weekStatisticList, stockOutPosition } = success.data;
  464. const { stockInPosition, monthPickList } = success.data;
  465. const { inventoryQuantity, clampQuantity, instrumentQuantity } =
  466. success.data;
  467. const { stockInCategory, stockOutCategory } = success.data;
  468. const { popularInvList, popularUserList } = success.data;
  469. const { cfInAndOutResponses } = success.data;
  470. _self.clampQuantity = clampQuantity;
  471. _self.inventoryQuantity = inventoryQuantity;
  472. _self.instrumentQuantity = instrumentQuantity;
  473. _self.updateDaysChart(weekStatisticList);
  474. _self.updatePositionChart(stockOutPosition, stockInPosition);
  475. _self.updateYearChart(monthPickList);
  476. _self.updateTypeChart(stockInCategory, stockOutCategory);
  477. _self.updateHotChart(popularInvList);
  478. _self.updateInOutChart(cfInAndOutResponses);
  479. _self.updateUseChart(popularUserList);
  480. } else {
  481. console.log(success.errorMessage);
  482. }
  483. });
  484. },
  485. // 更新近七日出入库数据
  486. updateDaysChart(dto) {
  487. const _self = this;
  488. if (!isObjectEqual(dto, _self.dayDatas)) {
  489. const xDatas = dto.map((item) => {
  490. const date = new Date(item.day);
  491. const month = (date.getMonth() + 1).toString().padStart(2, "0");
  492. const day = date.getDate().toString().padStart(2, "0");
  493. return `${month}.${day}`;
  494. });
  495. const inDatas = dto.map((item) => item.inCount);
  496. const outDatas = dto.map((item) => item.outCount);
  497. _self.daysChart.setOption({
  498. xAxis: {
  499. data: xDatas,
  500. },
  501. series: [
  502. { name: "入库", data: inDatas },
  503. { name: "出库", data: outDatas },
  504. ],
  505. });
  506. _self.dayDatas = dto;
  507. }
  508. },
  509. // 更新货位数据
  510. updatePositionChart(outDto, inDto) {
  511. const _self = this;
  512. if (
  513. !isObjectEqual(outDto, _self.outDatas) ||
  514. !isObjectEqual(inDto, _self.inDatas)
  515. ) {
  516. const inDatas = [
  517. inDto.toolQuantity,
  518. inDto.equipmentQuantity,
  519. inDto.finishedQuantity,
  520. inDto.stereoscopicQuantity,
  521. inDto.groundQuantity,
  522. ];
  523. const outDatas = [
  524. outDto.toolQuantity,
  525. outDto.equipmentQuantity,
  526. outDto.finishedQuantity,
  527. outDto.stereoscopicQuantity,
  528. outDto.groundQuantity,
  529. ];
  530. _self.positionChart.setOption({
  531. series: [
  532. { name: "入库", data: inDatas },
  533. { name: "出库", data: outDatas },
  534. ],
  535. });
  536. _self.outStockDatas = outDto;
  537. _self.inStockDatas = inDto;
  538. }
  539. },
  540. // 更新年领用数据
  541. updateYearChart(dto) {
  542. const _self = this;
  543. if (!isObjectEqual(dto, _self.yearDatas)) {
  544. const xDatas = dto.map((item) => item.month);
  545. const pickCount = dto.map((item) => item.pickCount);
  546. const clampCount = dto.map((item) => item.clampCount);
  547. const instrumentCount = dto.map((item) => item.instrumentCount);
  548. _self.yearChart.setOption({
  549. xAxis: { data: xDatas },
  550. series: [
  551. { name: "总领用", data: pickCount },
  552. { name: "设备领用", data: clampCount },
  553. { name: "工装领用", data: instrumentCount },
  554. ],
  555. });
  556. _self.yearDatas = dto;
  557. }
  558. },
  559. // 更新出入库类型数据
  560. updateTypeChart(inDto, outDto) {
  561. const _self = this;
  562. if (
  563. !isObjectEqual(inDto, _self.inTypeDatas) ||
  564. !isObjectEqual(outDto, _self.outTypeDatas)
  565. ) {
  566. const seriesData = [
  567. {
  568. name: "工装入库数",
  569. value: inDto.instrumentQuantity,
  570. },
  571. {
  572. name: "工装出库数",
  573. value: outDto.instrumentQuantity,
  574. },
  575. {
  576. name: "设备入库数",
  577. value: inDto.instrumentQuantity,
  578. },
  579. {
  580. name: "设备出库数",
  581. value: outDto.instrumentQuantity,
  582. },
  583. {
  584. name: "成品入库数",
  585. value: inDto.productQuantity,
  586. },
  587. {
  588. name: "成品出库数",
  589. value: outDto.productQuantity,
  590. },
  591. ];
  592. _self.typeChart.setOption({
  593. series: [{ name: "类型", data: seriesData }],
  594. });
  595. _self.inTypeDatas = inDto;
  596. _self.outTypeDatas = outDto;
  597. }
  598. },
  599. // 更新热门数据
  600. updateHotChart(dto) {
  601. const _self = this;
  602. if (!isObjectEqual(dto, _self.hotDatas)) {
  603. const datas = dto.slice(0, 5);
  604. const names = datas.map((item) => item.invName || "");
  605. const values = datas.map((item) => Number(item.count) || 0);
  606. while (names.length < 5) names.push("");
  607. while (values.length < 5) values.push(0);
  608. _self.hotChart.setOption({
  609. yAxis: [{ name: "", data: names }],
  610. series: [{ name: "值", data: values }],
  611. });
  612. _self.hotDatas = dto;
  613. }
  614. },
  615. // 更新领用排行数据
  616. updateUseChart(dto) {
  617. const _self = this;
  618. if (!isObjectEqual(dto, _self.useDatas)) {
  619. const datas = dto.slice(0, 5);
  620. const names = datas.map((item) => item.userName || "");
  621. const values = datas.map((item) => Number(item.count) || 0);
  622. while (names.length < 5) names.push("");
  623. while (values.length < 5) values.push(0);
  624. _self.useChart.setOption({
  625. yAxis: [{ name: "", data: names }],
  626. series: [{ name: "值", data: values }],
  627. });
  628. _self.useDatas = dto;
  629. }
  630. },
  631. // 更新出入库数据
  632. updateInOutChart(dtos) {
  633. const _self = this;
  634. if (!dtos || dtos.length === 0) {
  635. _self.recordConfig.data = [];
  636. return;
  637. }
  638. if (!isArrayEqual(dtos, _self.tableDatas)) {
  639. const processedData = dtos.map((item, index) => {
  640. return [
  641. index + 1,
  642. item.name || "",
  643. item.drawNo || "",
  644. item.type || "",
  645. item.inventoryType || "",
  646. item.time || "",
  647. item.userName || "",
  648. ];
  649. });
  650. _self.tableDatas = dtos;
  651. _self.recordConfig.data = JSON.parse(
  652. JSON.stringify(processedData),
  653. );
  654. // 强制更新组件
  655. _self.$nextTick(() => {
  656. if (_self.$refs.scrollBoard) {
  657. _self.$refs.scrollBoard.updateRows(_self.recordConfig.data);
  658. }
  659. });
  660. }
  661. },
  662. // 屏幕自适应
  663. resizeChart() {
  664. const _self = this;
  665. _self.daysChart && _self.daysChart.resize();
  666. _self.positionChart && _self.positionChart.resize();
  667. _self.yearChart && _self.yearChart.resize();
  668. _self.typeChart && _self.typeChart.resize();
  669. _self.hotChart && _self.hotChart.resize();
  670. _self.useChart && _self.useChart.resize();
  671. },
  672. cancalDebounce: debounce(function () {
  673. this.resizeChart();
  674. }, 200),
  675. },
  676. mounted() {
  677. const _self = this;
  678. _self.getWarehouseId();
  679. _self.daysChart = getElement("daysChart");
  680. _self.positionChart = getElement("positionChart");
  681. _self.yearChart = getElement("yearChart");
  682. _self.typeChart = getElement("typeChart");
  683. _self.hotChart = getElement("hotChart");
  684. _self.useChart = getElement("useChart");
  685. _self.$nextTick(() => {
  686. _self.createDaysChart();
  687. _self.createPositionChart();
  688. _self.createYearChart();
  689. _self.createTypeChart();
  690. _self.createHotChart();
  691. _self.createUseChart();
  692. _self.getWarehouseInfo();
  693. window.addEventListener("resize", _self.cancalDebounce);
  694. });
  695. _self.timer = setInterval(() => {
  696. _self.getWarehouseInfo();
  697. }, 3000);
  698. },
  699. beforeUnmount() {
  700. const _self = this;
  701. clearInterval(_self.timer);
  702. _self.timer = null;
  703. },
  704. });
  705. </script>
  706. </body>
  707. </html>