index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. <template>
  2. <div class="screen-container">
  3. <common-header title="质量统计" />
  4. <div class="screen-content">
  5. <div class="infoItem">
  6. <div class="infoItemHeader itemBackgroud">
  7. <TitleHeader title="报故统计" />
  8. <div class="chartsBox">
  9. <div id="charts1"></div>
  10. </div>
  11. </div>
  12. <div class="infoItemBody itemBackgroud">
  13. <TitleHeader title="报故缺陷项分布" />
  14. <div class="chartsBox">
  15. <div id="charts3"></div>
  16. </div>
  17. </div>
  18. </div>
  19. <div class="infoItem">
  20. <div class="infoItemHeader itemBackgroud">
  21. <TitleHeader title="不合格品统计" />
  22. <div class="chartsBox">
  23. <div id="charts2"></div>
  24. </div>
  25. </div>
  26. <div class="infoItemBody itemBackgroud">
  27. <TitleHeader title="报故处理跟踪" />
  28. <div class="chartsCarouselBox">
  29. <div class="carouselHeader tableStyle">
  30. <div class="left center1Text">产品名称</div>
  31. <div class="middle center1Text">状态</div>
  32. <div class="right center1Text">报故数量</div>
  33. </div>
  34. <div class="carouselBody">
  35. <TransitionGroup name="list" tag="ul">
  36. <li
  37. class="carouselItem tableStyle"
  38. :key="item"
  39. style="height: 4.3vh"
  40. v-for="item in showData1"
  41. >
  42. <div class="left infoBackgroud centerText textComent">
  43. {{ item.materialName }}
  44. </div>
  45. <div class="middle infoBackgroud centerText textComent">
  46. {{ item.currentState }}
  47. </div>
  48. <div
  49. class="right infoBackgroud centerText textComent"
  50. style="font-weight: bolder"
  51. >
  52. {{ item.unqualifiedNum }}
  53. </div>
  54. </li>
  55. </TransitionGroup>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <div
  61. class="infoItem itemBackgroud"
  62. style="justify-content: flex-start; padding: 0.8vw"
  63. >
  64. <TitleHeader title="产品合格率" />
  65. <div class="chartsCarouselBox">
  66. <div class="carouselBody" style="padding: 2vh 0">
  67. <TransitionGroup name="list" tag="ul">
  68. <li
  69. class="carouselItem table1Style"
  70. :key="item"
  71. v-for="item in showData2"
  72. style="height: 8vh"
  73. >
  74. <div class="left infoBackgroud centerText">
  75. <div class="line">
  76. <div class="box">
  77. <div class="box1"></div>
  78. </div>
  79. <div class="titleTextBox textComent">
  80. {{ item.materialName }}
  81. </div>
  82. </div>
  83. <div class="line">
  84. <div class="title1TextBox textComent">
  85. {{ item.materialModel }}
  86. </div>
  87. </div>
  88. </div>
  89. <div class="middle infoBackgroud centerText textComent">
  90. {{ item.rate }}
  91. </div>
  92. </li>
  93. </TransitionGroup>
  94. </div>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </template>
  100. <script setup>
  101. import CommonHeader from "@/views/report/statistics/screens/common-header.vue";
  102. import TitleHeader from "../titleHeader.vue";
  103. import {
  104. getFaultBug,
  105. getFaultCount,
  106. getFaultTrack,
  107. getCensusNonconforming,
  108. getQualifiedRate,
  109. } from "@/api/bigScreen";
  110. import * as echarts from "echarts";
  111. const charts1 = shallowRef(null);
  112. const charts2 = shallowRef(null);
  113. const charts3 = shallowRef(null);
  114. //存放接口数据
  115. //报故统计
  116. const chartsData1 = ref({});
  117. //不合格品统计
  118. const chartsData2 = ref([]);
  119. //报故缺陷分布
  120. const chartsData3 = ref({});
  121. //报故处理跟踪
  122. const data1 = ref([]);
  123. const showData1 = ref([]);
  124. const sum1 = ref(1);
  125. const interval1 = ref(null);
  126. const setShowData1 = (num, time) => {
  127. sum1.value = num;
  128. if (data1.value.length > num) {
  129. const dataA = JSON.parse(JSON.stringify(data1.value));
  130. showData1.value = dataA.splice(0, num);
  131. interval1.value = setInterval(async () => {
  132. await showData1.value.push(data1.value[sum1.value % data1.value.length]);
  133. showData1.value.splice(0, 1);
  134. sum1.value = sum1.value + 1;
  135. }, time);
  136. } else {
  137. showData1.value = data1.value;
  138. }
  139. };
  140. //产品合格率
  141. const data2 = ref([]);
  142. const showData2 = ref([]);
  143. const sum2 = ref(1);
  144. const interval2 = ref(null);
  145. const fontSize = ref(0);
  146. const setFontSize = () => {
  147. fontSize.value = (window.innerHeight / 100) * 1.55;
  148. };
  149. const setShowData2 = (num, time) => {
  150. sum2.value = num;
  151. if (data2.value.length > num) {
  152. const dataA = JSON.parse(JSON.stringify(data2.value));
  153. showData2.value = dataA.splice(0, num);
  154. interval2.value = setInterval(async () => {
  155. await showData2.value.push(data2.value[sum2.value % data2.value.length]);
  156. showData2.value.splice(0, 1);
  157. sum2.value = sum2.value + 1;
  158. }, time);
  159. } else {
  160. showData2.value = data2.value;
  161. }
  162. };
  163. const getData1 = async () => {
  164. //报故缺陷项分布
  165. const { data } = await getFaultBug();
  166. chartsData3.value = data;
  167. };
  168. const getData2 = async () => {
  169. //报故统计
  170. const { data } = await getFaultCount();
  171. chartsData1.value = data;
  172. };
  173. const getData3 = async () => {
  174. //报故处理跟踪
  175. const { data } = await getFaultTrack();
  176. data1.value = data;
  177. setShowData1(9, 2500);
  178. };
  179. const getData4 = async () => {
  180. //不合格品统计
  181. const { data } = await getCensusNonconforming();
  182. chartsData2.value = data;
  183. };
  184. const getData5 = async () => {
  185. //产品合格率
  186. const { data } = await getQualifiedRate();
  187. data2.value = data;
  188. setShowData2(8, 4000);
  189. };
  190. const getData = async () => {
  191. await getData1();
  192. await getData2();
  193. await getData3();
  194. await getData4();
  195. await getData5();
  196. };
  197. const option1 = {
  198. xAxis: {
  199. type: "category",
  200. data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  201. axisLabel: {
  202. fontSize: 12,
  203. },
  204. },
  205. grid: {
  206. left: "8%",
  207. right: "3%",
  208. top: "10%",
  209. bottom: "10%",
  210. },
  211. yAxis: {
  212. type: "value",
  213. axisLabel: {
  214. fontSize: 12,
  215. },
  216. },
  217. series: [
  218. {
  219. data: [820, 932, 901, 934, 1290, 1330, 1320],
  220. type: "line",
  221. symbol: "none",
  222. itemStyle: {
  223. color: "#BCB62E80",
  224. },
  225. areaStyle: {
  226. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  227. {
  228. offset: 0,
  229. color: "#BCB62E80",
  230. },
  231. {
  232. offset: 1,
  233. color: "#BCB62E20",
  234. },
  235. ]),
  236. },
  237. },
  238. ],
  239. textStyle: {
  240. fontSize: 999,
  241. },
  242. };
  243. const option2 = {
  244. xAxis: {
  245. type: "category",
  246. data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  247. axisLabel: {
  248. fontSize: 12,
  249. },
  250. },
  251. grid: {
  252. left: "8%",
  253. right: "3%",
  254. top: "10%",
  255. bottom: "10%",
  256. },
  257. yAxis: {
  258. type: "value",
  259. axisLabel: {
  260. fontSize: 12,
  261. },
  262. },
  263. textStyle: {
  264. fontSize: 999,
  265. },
  266. series: [
  267. {
  268. data: [820, 932, 901, 934, 1290, 0, 700],
  269. type: "line",
  270. symbol: "none",
  271. itemStyle: {
  272. color: "#D7565680",
  273. },
  274. areaStyle: {
  275. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  276. {
  277. offset: 0,
  278. color: "#D7565680",
  279. },
  280. {
  281. offset: 1,
  282. color: "#D7565620",
  283. },
  284. ]),
  285. },
  286. },
  287. ],
  288. };
  289. const option3 = {
  290. textStyle: {
  291. fontSize: 99,
  292. },
  293. yAxis: {
  294. type: "category",
  295. data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  296. axisLabel: {
  297. fontSize: 12,
  298. },
  299. },
  300. grid: {
  301. left: "18%",
  302. right: "7%",
  303. top: "10%",
  304. bottom: "10%",
  305. },
  306. xAxis: {
  307. type: "value",
  308. axisLabel: {
  309. fontSize: 12,
  310. },
  311. },
  312. series: [
  313. {
  314. data: [120, 200, 150, 80, 70, 110, 130],
  315. type: "bar",
  316. itemStyle: {
  317. color: "#daf4ff",
  318. },
  319. barWidth: "15%",
  320. },
  321. ],
  322. };
  323. const setChart3Option = () => {
  324. const op3 = { ...option3 };
  325. if (chartsData3.value && charts3.value) {
  326. op3.series[0].data = chartsData3.value.countList;
  327. op3.yAxis.data = chartsData3.value.bugNameList;
  328. op3.yAxis.axisLabel.fontSize = fontSize.value;
  329. op3.xAxis.axisLabel.fontSize = fontSize.value;
  330. charts3.value.setOption(op3, true);
  331. }
  332. };
  333. const setChart2Option = () => {
  334. const op2 = { ...option2 };
  335. if (chartsData1.value && charts1.value) {
  336. op2.series[0].data = chartsData1.value.countList;
  337. op2.xAxis.data = chartsData1.value.monthList;
  338. op2.yAxis.axisLabel.fontSize = fontSize.value;
  339. op2.xAxis.axisLabel.fontSize = fontSize.value;
  340. charts1.value.setOption(op2, true);
  341. }
  342. };
  343. const setChart1Option = () => {
  344. const op1 = { ...option1 };
  345. if (chartsData2.value && charts2.value) {
  346. op1.series[0].data = chartsData2.value.countList;
  347. op1.xAxis.data = chartsData2.value.monthList;
  348. op1.yAxis.axisLabel.fontSize = fontSize.value;
  349. op1.xAxis.axisLabel.fontSize = fontSize.value;
  350. charts2.value.setOption(op1, true);
  351. }
  352. };
  353. onMounted(async () => {
  354. setFontSize();
  355. charts1.value = echarts.init(document.getElementById("charts1"));
  356. charts2.value = echarts.init(document.getElementById("charts2"));
  357. charts3.value = echarts.init(document.getElementById("charts3"));
  358. await getData();
  359. });
  360. onUnmounted(() => {
  361. if (interval1.value) {
  362. clearInterval(interval1.value);
  363. }
  364. if (interval2.value) {
  365. clearInterval(interval2.value);
  366. }
  367. });
  368. watch(
  369. [() => chartsData3.value, () => chartsData1.value, () => chartsData2.value],
  370. () => {
  371. setChart3Option();
  372. setChart2Option();
  373. setChart1Option();
  374. },
  375. { deep: true }
  376. );
  377. </script>
  378. <style lang="scss" scoped>
  379. #charts1 {
  380. width: 100%;
  381. height: 100%;
  382. transform-origin: center center; /* 设置变换的原点为元素中心 */
  383. position: absolute;
  384. }
  385. #charts2 {
  386. width: 100%;
  387. height: 100%;
  388. position: absolute;
  389. }
  390. #charts3 {
  391. width: 100%;
  392. height: 100%;
  393. position: absolute;
  394. transform-origin: center center; /* 设置变换的原点为元素中心 */
  395. transform: scale(1.1); /* 放大1.5倍 */
  396. }
  397. .list-move,
  398. .list-enter-active,
  399. .list-leave-active {
  400. transition: all 0.5s ease;
  401. }
  402. .list-enter-from,
  403. .list-leave-to {
  404. opacity: 0;
  405. transform: translateY(-4.6vh);
  406. }
  407. .list-leave-active {
  408. position: absolute;
  409. }
  410. .list1-leave-active {
  411. transition: all 0.5s ease;
  412. }
  413. .list1-leave-to {
  414. opacity: 0;
  415. transform: translateY(-8vh);
  416. }
  417. .list1-leave-active {
  418. position: absolute;
  419. }
  420. .screen-container {
  421. width: 100vw;
  422. height: 100vh;
  423. background-image: url("@/assets/images/screen_bg_task.png");
  424. background-size: cover;
  425. background-position: center;
  426. }
  427. .itemBackgroud {
  428. background-color: rgba(0, 0, 0, 0.6);
  429. }
  430. .infoBackgroud {
  431. background-color: rgba(255, 255, 255, 0.05);
  432. }
  433. .screen-content {
  434. width: 100vw;
  435. height: calc(100vh - 96px - 18px);
  436. margin-top: 18px;
  437. display: flex;
  438. justify-content: space-evenly;
  439. .infoItem {
  440. width: 31vw;
  441. height: 100%;
  442. display: flex;
  443. flex-direction: column;
  444. justify-content: space-between;
  445. .infoItemHeader {
  446. height: 36%;
  447. display: flex;
  448. flex-direction: column;
  449. padding: 0.8vw;
  450. width: 100%;
  451. .chartsBox {
  452. flex: 1;
  453. position: relative;
  454. }
  455. }
  456. .infoItemBody {
  457. width: 100%;
  458. height: 60%;
  459. display: flex;
  460. flex-direction: column;
  461. padding: 0.8vw;
  462. .chartsBox {
  463. flex: 1;
  464. position: relative;
  465. }
  466. }
  467. }
  468. }
  469. .chartsCarouselBox {
  470. flex: 1;
  471. display: flex;
  472. flex-direction: column;
  473. .carouselHeader {
  474. height: calc(2vh);
  475. line-height: 2vh;
  476. margin-bottom: 0.5vh;
  477. }
  478. .carouselBody {
  479. flex: 1;
  480. display: flex;
  481. flex-direction: column;
  482. overflow: hidden;
  483. .carouselItem {
  484. margin-bottom: 0.5vh;
  485. width: calc(31vw - 1.6vw);
  486. }
  487. }
  488. }
  489. .centerText {
  490. color: rgba(255, 255, 255, 0.8);
  491. font-size: 1.8vh;
  492. display: flex;
  493. align-items: center;
  494. justify-content: center;
  495. padding: 0 0.3vh;
  496. }
  497. .center1Text {
  498. color: rgba(255, 255, 255, 0.8);
  499. font-size: 1.4vh;
  500. display: flex;
  501. align-items: center;
  502. justify-content: center;
  503. padding: 0 0.3vh;
  504. }
  505. .tableStyle {
  506. display: flex;
  507. justify-content: space-between;
  508. width: 100%;
  509. .left {
  510. width: 66%;
  511. }
  512. .middle {
  513. width: 19%;
  514. }
  515. .right {
  516. width: 13%;
  517. }
  518. }
  519. .table1Style {
  520. display: flex;
  521. justify-content: space-between;
  522. width: 100%;
  523. margin-bottom: 2vh !important;
  524. .left {
  525. width: calc(80% - 0.5vh);
  526. padding: 1vh 2vh 1vh 3vh;
  527. display: flex;
  528. flex-direction: column;
  529. .line {
  530. width: 100%;
  531. flex: 1;
  532. display: flex;
  533. align-items: center;
  534. .box {
  535. height: 1.8vh;
  536. width: 1.8vh;
  537. display: flex;
  538. justify-content: center;
  539. align-items: center;
  540. background-color: rgba(255, 255, 255, 0.1);
  541. .box1 {
  542. height: 0.8vh;
  543. width: 0.8vh;
  544. background-color: rgba(255, 255, 255, 1);
  545. }
  546. }
  547. .titleTextBox {
  548. font-size: 2vh;
  549. color: white;
  550. font-weight: bold;
  551. flex: 1;
  552. margin-left: 0.5vh;
  553. }
  554. .title1TextBox {
  555. font-size: 1.4vh;
  556. color: #ffffff60;
  557. flex: 1;
  558. margin-left: calc(1.8vh + 2px);
  559. }
  560. }
  561. }
  562. .middle {
  563. width: 20%;
  564. }
  565. }
  566. .textComent {
  567. white-space: nowrap; /* 不允许换行 */
  568. overflow: hidden; /* 超出长度时隐藏 */
  569. text-overflow: ellipsis; /* 超出部分显示省略号 */
  570. }
  571. </style>