SeizeDetails.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <template>
  2. <div class="chartsContainer">
  3. <div class="chartsContainer-title">查获明细</div>
  4. <div class="chartsContainer-list">
  5. <div class="chartsContainer-content">
  6. <div class="chartsContainer-content-top">
  7. <div class="chartsContainer-content-name">违禁品类别</div>
  8. </div>
  9. <div class="chartsContainer-content-content" ref="pieCategory" />
  10. </div>
  11. <div class="chartsContainer-content">
  12. <div class="chartsContainer-content-top">
  13. <div class="chartsContainer-content-name">查获部位</div>
  14. </div>
  15. <div class="chartsContainer-content-content" ref="pieAppPosition" />
  16. </div>
  17. <div class="chartsContainer-content">
  18. <div class="chartsContainer-content-top">
  19. <div class="chartsContainer-content-name">安检岗位</div>
  20. </div>
  21. <div class="chartsContainer-content-content" ref="pieLargeScreenPost" />
  22. </div>
  23. <div class="chartsContainer-content">
  24. <div class="chartsContainer-content-top">
  25. <div class="chartsContainer-content-name">查获时间分布</div>
  26. </div>
  27. <div class="chartsContainer-content-content" ref="lineChart" />
  28. </div>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup>
  33. import { category, appPosition, largeScreenPost, appTimeSpan } from '@/api/item/items'
  34. import { useTimeOut } from './useTimeOut';
  35. import { useECharts } from '@/hooks/useEcharts.js';
  36. import { ref, computed, inject } from 'vue'
  37. const provideParams = inject('provideParams')
  38. const pieCategory = ref(null)
  39. const pieCategoryData = ref([])
  40. const setChartsOptions = computed(() => {
  41. return {
  42. tooltip: {
  43. trigger: 'item',
  44. formatter: '{a} <br/>{b}: {c} ({d}%)'
  45. },
  46. legend: {
  47. show: false
  48. },
  49. series: [
  50. {
  51. name: '违禁品类别',
  52. type: 'pie',
  53. radius: [ '0%', '50%' ], // 环形图设置
  54. center: [ '50%', '50%' ],
  55. data: pieCategoryData.value.map(item => {
  56. return {
  57. name: item.name,
  58. value: item.total
  59. }
  60. }),
  61. label: {
  62. show: true,
  63. formatter: function (params) {
  64. return params.name + '\n' + params.percent + '%'
  65. },
  66. color: '#fff',
  67. fontSize: 14,
  68. },
  69. labelLine: {
  70. length: 15
  71. },
  72. emphasis: {
  73. itemStyle: {
  74. shadowBlur: 10,
  75. shadowOffsetX: 0,
  76. shadowColor: 'rgba(0, 0, 0, 0.5)'
  77. }
  78. }
  79. }
  80. ]
  81. }
  82. })
  83. useECharts(pieCategory, setChartsOptions);
  84. const pieAppPosition = ref(null)
  85. const pieAppPositionData = ref([])
  86. const setpieAppPositionOptions = computed(() => {
  87. return {
  88. tooltip: {
  89. trigger: 'item',
  90. formatter: '{a} <br/>{b}: {c} ({d}%)'
  91. },
  92. legend: {
  93. show: false
  94. },
  95. series: [
  96. {
  97. name: '查获部位',
  98. type: 'pie',
  99. radius: [ '0%', '50%' ], // 环形图设置
  100. center: [ '50%', '50%' ],
  101. data: pieAppPositionData.value.map(item => {
  102. return {
  103. name: item.name,
  104. value: item.total
  105. }
  106. }),
  107. label: {
  108. show: true,
  109. formatter: function (params) {
  110. return params.name + '\n' + params.percent + '%'
  111. },
  112. color: '#fff',
  113. fontSize: 14,
  114. },
  115. labelLine: {
  116. length: 15
  117. },
  118. emphasis: {
  119. itemStyle: {
  120. shadowBlur: 10,
  121. shadowOffsetX: 0,
  122. shadowColor: 'rgba(0, 0, 0, 0.5)'
  123. }
  124. }
  125. }
  126. ]
  127. }
  128. })
  129. useECharts(pieAppPosition, setpieAppPositionOptions);
  130. const pieLargeScreenPost = ref(null)
  131. const pieLargeScreenPostData = ref([])
  132. const setpieLargeScreenPostOptions = computed(() => {
  133. return {
  134. tooltip: {
  135. trigger: 'item',
  136. formatter: '{a} <br/>{b}: {c} ({d}%)'
  137. },
  138. legend: {
  139. show: false
  140. },
  141. series: [
  142. {
  143. name: '安检岗位',
  144. type: 'pie',
  145. radius: [ '0%', '50%' ], // 环形图设置
  146. center: [ '50%', '50%' ],
  147. data: pieLargeScreenPostData.value.map(item => {
  148. return {
  149. name: item.name,
  150. value: item.total
  151. }
  152. }),
  153. label: {
  154. show: true,
  155. formatter: function (params) {
  156. return params.name + '\n' + params.percent + '%'
  157. },
  158. color: '#fff',
  159. fontSize: 14,
  160. },
  161. labelLine: {
  162. length: 15
  163. },
  164. emphasis: {
  165. itemStyle: {
  166. shadowBlur: 10,
  167. shadowOffsetX: 0,
  168. shadowColor: 'rgba(0, 0, 0, 0.5)'
  169. }
  170. }
  171. }
  172. ]
  173. }
  174. })
  175. useECharts(pieLargeScreenPost, setpieLargeScreenPostOptions);
  176. const lineChart = ref(null)
  177. const lineChartData = ref([])
  178. const setlineChartOptions = computed(() => {
  179. return {
  180. tooltip: {
  181. trigger: 'axis'
  182. },
  183. xAxis: {
  184. type: 'category',
  185. boundaryGap: false,
  186. data: lineChartData.value.map(item => item.hourOfDay),
  187. axisLabel: {
  188. color: '#fff',
  189. rotate: 25,
  190. fontSize: 12,
  191. }
  192. },
  193. yAxis: {
  194. type: 'value',
  195. minInterval: 1,
  196. max: Math.max(...lineChartData.value.map(item => item.total)) * 2,
  197. axisLabel: {
  198. color: '#fff',
  199. }
  200. },
  201. series: {
  202. data: lineChartData.value.map(item => item.total),
  203. type: 'line',
  204. smooth: true,
  205. },
  206. grid: {
  207. left: '5%',
  208. right: '0%',
  209. bottom: '10%',
  210. top: '5%',
  211. containLabel: true
  212. }
  213. };
  214. })
  215. useECharts(lineChart, setlineChartOptions);
  216. useTimeOut(() => {
  217. provideParams.value.inspectDepartmentId && category({
  218. startDate: provideParams.value.startDate,
  219. endDate: provideParams.value.endDate,
  220. inspectDepartmentId: provideParams.value.inspectDepartmentId === 'ALL' ? '' : provideParams.value.inspectDepartmentId
  221. }).then(res => {
  222. pieCategoryData.value = (res.data || [])
  223. })
  224. provideParams.value.inspectDepartmentId && appPosition({
  225. startDate: provideParams.value.startDate,
  226. endDate: provideParams.value.endDate,
  227. inspectDepartmentId: provideParams.value.inspectDepartmentId === 'ALL' ? '' : provideParams.value.inspectDepartmentId
  228. }).then(res => {
  229. pieAppPositionData.value = (res.data || [])
  230. })
  231. provideParams.value.inspectDepartmentId && largeScreenPost({
  232. startDate: provideParams.value.startDate,
  233. endDate: provideParams.value.endDate,
  234. inspectDepartmentId: provideParams.value.inspectDepartmentId === 'ALL' ? '' : provideParams.value.inspectDepartmentId
  235. }).then(res => {
  236. pieLargeScreenPostData.value = (res.data || [])
  237. })
  238. provideParams.value.inspectDepartmentId && appTimeSpan({
  239. startDate: provideParams.value.startDate,
  240. endDate: provideParams.value.endDate,
  241. inspectDepartmentId: provideParams.value.inspectDepartmentId === 'ALL' ? '' : provideParams.value.inspectDepartmentId
  242. }).then(res => {
  243. lineChartData.value = Array.isArray(res.data) ? Array.from({length: 24}, (_, index) => {
  244. const item = res.data.find(item => Number(item.hourOfDay) === index)
  245. if (item) {
  246. return {
  247. total: item.total,
  248. hourOfDay: `${index}:00`
  249. }
  250. } else {
  251. return {
  252. total: 0,
  253. hourOfDay: `${index}:00`
  254. }
  255. }
  256. }) : []
  257. })
  258. }, [provideParams])
  259. </script>
  260. <style lang="scss" scoped>
  261. .chartsContainer {
  262. width: 100%;
  263. height: 100%;
  264. position: relative;
  265. background: linear-gradient(to bottom, rgba(8, 97, 117, 0) 0%, #13a2d6 200%);
  266. border-radius: 4px;
  267. overflow: hidden;
  268. display: flex;
  269. flex-direction: column;
  270. .chartsContainer-title {
  271. height: 42px;
  272. width: 100%;
  273. background: linear-gradient(to right, #004387 0%, #090B18 100%);
  274. border-left: 1px solid #1892CE;
  275. line-height: 42px;
  276. color: #fff;
  277. font-weight: 900;
  278. font-size: 20px;
  279. text-indent: 1em;
  280. }
  281. .chartsContainer-list {
  282. padding: 20px 15px 10px;
  283. box-sizing: border-box;
  284. display: flex;
  285. column-gap: 20px;
  286. row-gap: 20px;
  287. flex: 1;
  288. overflow: hidden;
  289. flex-wrap: wrap;
  290. }
  291. .chartsContainer-content {
  292. display: flex;
  293. flex-direction: column;
  294. row-gap: 10px;
  295. width: calc(50% - 10px);
  296. height: calc(50% - 10px);
  297. overflow: hidden;
  298. .chartsContainer-content-top {
  299. display: flex;
  300. align-items: center;
  301. color: #78DEF5;
  302. .chartsContainer-content-name {
  303. color: #fff;
  304. font-weight: bold;
  305. font-size: 16px;
  306. display: flex;
  307. align-items: center;
  308. &::before {
  309. content: '';
  310. display: inline-block;
  311. border-left: 9px solid #1CB6FF;
  312. border-top: 8px solid transparent;
  313. border-right: 9px solid transparent;
  314. border-bottom: 8px solid transparent;
  315. }
  316. }
  317. }
  318. .chartsContainer-content-describe {
  319. color: #78DEF5;
  320. font-size: 12px;
  321. font-weight: bold;
  322. display: flex;
  323. align-items: center;
  324. }
  325. .chartsContainer-content-content {
  326. flex: 1;
  327. width: 100%;
  328. overflow: hidden;
  329. }
  330. }
  331. }
  332. </style>