index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <template>
  2. <ele-page flex-table v-loading="loading">
  3. <ele-card flex-table>
  4. <date-search
  5. class="mb-4"
  6. v-model="mapDateRange"
  7. @search="fetchProvinceData"
  8. position="left"
  9. />
  10. <map-card class="flex-1" :province-data="provinceData" />
  11. <div class="flex gap-10">
  12. <div class="flex-1 stat-card">
  13. <el-statistic
  14. title="总扫描次数"
  15. :value="realTimeData.scanTimesTotal"
  16. value-style="font-size:30px;color:#409eef"
  17. />
  18. </div>
  19. <div class="flex-1 stat-card">
  20. <el-statistic
  21. title="总审核单量"
  22. :value="realTimeData.auditNumTotal"
  23. value-style="font-size:30px;color:#409eef"
  24. />
  25. </div>
  26. <div class="flex-1 stat-card">
  27. <el-statistic
  28. title="总审核本数"
  29. :value="realTimeData.auditBookNumTotal"
  30. value-style="font-size:30px;color:#409eef"
  31. />
  32. </div>
  33. <div class="flex-1 stat-card">
  34. <el-statistic
  35. title="总审核金额"
  36. :value="realTimeData.auditMoneyTotal"
  37. value-style="font-size:30px;color:#409eef"
  38. :precision="2"
  39. />
  40. </div>
  41. <div class="flex-1 stat-card">
  42. <el-statistic
  43. title="总用户人数"
  44. :value="realTimeData.userNumTotal"
  45. value-style="font-size:30px;color:#409eef"
  46. />
  47. </div>
  48. </div>
  49. <el-divider />
  50. <div class="flex justify-end mb-2" @click="fetchRealTimeData">
  51. <div class="flex items-center gap-2 cursor-pointer">
  52. <el-icon><Refresh /></el-icon>
  53. <span>更新时间:{{ nowTime }}</span>
  54. </div>
  55. </div>
  56. <div class="flex gap-4">
  57. <div class="flex-1 stat-card">
  58. <stat-card
  59. title="回收订单数"
  60. :value="realTimeData.orderNum"
  61. :data="realTimeData.orderNumTodayCharts"
  62. :yesterday-data="realTimeData.orderNumYestodayCharts"
  63. :chatAxis="realTimeData.chatAxis"
  64. />
  65. </div>
  66. <div class="flex-1 stat-card">
  67. <stat-card
  68. title="回收数量(本)"
  69. :value="realTimeData.bookNum"
  70. :data="realTimeData.bookNumTodayCharts"
  71. :yesterday-data="realTimeData.bookNumYestodayCharts"
  72. :chatAxis="realTimeData.chatAxis"
  73. />
  74. </div>
  75. <div class="flex-1 stat-card">
  76. <stat-card
  77. title="回收单本均价"
  78. :precision="2"
  79. :value="realTimeData.recycleAveragePrice"
  80. :data="realTimeData.recycleAveragePriceTodayCharts"
  81. :yesterday-data="
  82. realTimeData.recycleAveragePriceYestodayCharts
  83. "
  84. :chatAxis="realTimeData.chatAxis"
  85. />
  86. </div>
  87. <div class="flex-1 stat-card">
  88. <stat-card
  89. title="待审核订单数"
  90. :value="realTimeData.waitAuditOrderNum"
  91. :data="realTimeData.waitAuditOrderNumTodayCharts"
  92. :yesterday-data="
  93. realTimeData.waitAuditOrderNumYestodayCharts
  94. "
  95. :chatAxis="realTimeData.chatAxis"
  96. />
  97. </div>
  98. <div class="flex-1 stat-card">
  99. <stat-card
  100. title="待签收订单数"
  101. :value="realTimeData.waitSignOrderNum"
  102. :data="realTimeData.waitSignOrderNumTodayCharts"
  103. :yesterday-data="
  104. realTimeData.waitSignOrderNumYestodayCharts
  105. "
  106. :chatAxis="realTimeData.chatAxis"
  107. />
  108. </div>
  109. </div>
  110. <div class="flex gap-4 mt-4">
  111. <div class="flex-1 stat-card">
  112. <stat-card
  113. title="今日扫描次数"
  114. :value="realTimeData.scanTimes"
  115. :data="realTimeData.scanTimesTodayCharts"
  116. :yesterday-data="realTimeData.scanTimesYestodayCharts"
  117. :chatAxis="realTimeData.chatAxis"
  118. />
  119. </div>
  120. <div class="flex-1 stat-card">
  121. <stat-card
  122. title="今日扫描人数"
  123. :value="realTimeData.scanUserNum"
  124. :data="realTimeData.scanUserNumTodayCharts"
  125. :yesterday-data="realTimeData.scanUserNumYestodayCharts"
  126. :chatAxis="realTimeData.chatAxis"
  127. />
  128. </div>
  129. <div class="flex-1 stat-card">
  130. <stat-card
  131. title="用户增长数"
  132. :value="realTimeData.userRegNum"
  133. :data="realTimeData.userRegNumTodayCharts"
  134. :yesterday-data="realTimeData.userRegNumYestodayCharts"
  135. :chatAxis="realTimeData.chatAxis"
  136. />
  137. </div>
  138. <div class="flex-1 stat-card">
  139. <stat-card
  140. title="待审核金额"
  141. :precision="2"
  142. :value="realTimeData.waitAuditMoney"
  143. :data="realTimeData.waitAuditMoneyTodayCharts"
  144. :yesterday-data="
  145. realTimeData.waitAuditMoneyYestodayCharts
  146. "
  147. :chatAxis="realTimeData.chatAxis"
  148. />
  149. </div>
  150. <div class="flex-1 stat-card">
  151. <stat-card
  152. title="待打款金额"
  153. :precision="2"
  154. :value="realTimeData.waitPayoutMoney"
  155. :data="realTimeData.waitPayoutMoneyTodayCharts"
  156. :yesterday-data="
  157. realTimeData.waitPayoutMoneyYestodayCharts
  158. "
  159. :chatAxis="realTimeData.chatAxis"
  160. />
  161. </div>
  162. </div>
  163. <el-divider />
  164. <div class="flex-col">
  165. <date-search
  166. class="mb-4"
  167. v-model="dateRange"
  168. @search="fetchHistoryData"
  169. />
  170. <div class="gap-4 flex">
  171. <div style="flex: 4" class="flex flex-col">
  172. <div class="flex gap-4">
  173. <div class="flex-1 stat-card">
  174. <stat-card
  175. title="回收订单数"
  176. :data="historyData.orderNumCharts"
  177. :chatAxis="historyData.chatAxis"
  178. :value="historyData.orderNum"
  179. />
  180. </div>
  181. <div class="flex-1 stat-card">
  182. <stat-card
  183. title="回收数量(本)"
  184. :value="historyData.bookNum"
  185. :data="historyData.bookNumCharts"
  186. :chatAxis="historyData.chatAxis"
  187. />
  188. </div>
  189. <div class="flex-1 stat-card">
  190. <stat-card
  191. title="回收单本均价"
  192. :value="historyData.recycleAveragePrice"
  193. :data="
  194. historyData.recycleAveragePriceCharts
  195. "
  196. :chatAxis="historyData.chatAxis"
  197. :precision="2"
  198. />
  199. </div>
  200. <div class="flex-1 stat-card">
  201. <stat-card
  202. title="审核订单数"
  203. :value="historyData.auditNum"
  204. :data="historyData.auditNumCharts"
  205. :chatAxis="historyData.chatAxis"
  206. />
  207. </div>
  208. </div>
  209. <div class="flex gap-4 mt-4">
  210. <div class="flex-1 stat-card">
  211. <stat-card
  212. title="签收订单数"
  213. :value="historyData.signOrderNum"
  214. :data="historyData.signOrderNumCharts"
  215. :chatAxis="historyData.chatAxis"
  216. />
  217. </div>
  218. <div class="flex-1 stat-card">
  219. <stat-card
  220. title="扫描次数"
  221. :value="historyData.scanTimes"
  222. :data="historyData.scanTimesCharts"
  223. :chatAxis="historyData.chatAxis"
  224. />
  225. </div>
  226. <div class="flex-1 stat-card">
  227. <stat-card
  228. title="扫描人数"
  229. :value="historyData.scanUserNum"
  230. :data="historyData.scanUserNumCharts"
  231. :chatAxis="historyData.chatAxis"
  232. />
  233. </div>
  234. <div class="flex-1 stat-card">
  235. <stat-card
  236. title="用户增长数"
  237. :value="historyData.userRegNum"
  238. :data="historyData.userRegNumCharts"
  239. :chatAxis="historyData.chatAxis"
  240. />
  241. </div>
  242. </div>
  243. </div>
  244. <div class="flex-1 flex flex-col stat-card">
  245. <pie-chart
  246. title="回收折扣占比"
  247. :data="recycleDiscountData"
  248. />
  249. <pie-chart
  250. title="审核品相比例分析"
  251. :data="auditRatioData"
  252. />
  253. </div>
  254. </div>
  255. </div>
  256. </ele-card>
  257. </ele-page>
  258. </template>
  259. <script setup>
  260. import mapCard from '@/views/statistic/overview/components/map-card.vue';
  261. import statCard from '@/views/statistic/overview/components/stat-card.vue';
  262. import pieChart from '@/views/statistic/overview/components/pie-chart.vue';
  263. import DateSearch from '@/components/DateSearch/index.vue';
  264. import { Refresh } from '@element-plus/icons-vue';
  265. import dayjs from 'dayjs';
  266. import request from '@/utils/request';
  267. import { onMounted, ref } from 'vue';
  268. const provinceData = ref([]);
  269. const dateRange = ref([
  270. dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
  271. dayjs().subtract(1, 'day').format('YYYY-MM-DD')
  272. ]);
  273. // 地图数据时间范围
  274. const mapDateRange = ref([
  275. dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
  276. dayjs().subtract(1, 'day').format('YYYY-MM-DD')
  277. ]);
  278. // 组织回收折扣比例数据
  279. const recycleDiscountData = ref([
  280. { value: 0, name: '≥2折', key: 'discount2' },
  281. { value: 0, name: '2<至≥1', key: 'discount12' },
  282. { value: 0, name: '1<至≥0.5', key: 'discount051' },
  283. { value: 0, name: '<0.5', key: 'discount05' }
  284. ]);
  285. // 组织审核品相比例分析数据
  286. const auditRatioData = ref([
  287. { value: 0, name: '良好', key: 'auditGoodNum' },
  288. { value: 0, name: '一般', key: 'auditGeneralNum' },
  289. { value: 0, name: '较差', key: 'auditBadNum' }
  290. ]);
  291. //获取历史数据汇总
  292. const historyData = ref({
  293. orderNumCharts: [],
  294. chatAxis: []
  295. });
  296. const fetchHistoryData = async () => {
  297. let params = {
  298. statisticDateStart: dateRange.value[0],
  299. statisticDateEnd: dateRange.value[1]
  300. };
  301. request
  302. .get('/order/recycleStatisticOverview/history', { params })
  303. .then((res) => {
  304. if (res.data.code === 200) {
  305. recycleDiscountData.value.forEach((item) => {
  306. item.value = res.data.data[item.key] || 0;
  307. });
  308. auditRatioData.value.forEach((item) => {
  309. item.value = res.data.data[item.key] || 0;
  310. });
  311. historyData.value = res.data.data;
  312. }
  313. });
  314. };
  315. // 获取省份排名数据 //传入的时间是近7天,结束时间就是今天,使用 dayjs
  316. const fetchProvinceData = async () => {
  317. const params = {
  318. statisticDateStart: mapDateRange.value[0],
  319. statisticDateEnd: mapDateRange.value[1]
  320. };
  321. request
  322. .get('/order/recycleStatisticOverview/provinceRankList', {
  323. params
  324. })
  325. .then((res) => {
  326. if (res.data.code === 200) {
  327. provinceData.value = res.data.data;
  328. }
  329. });
  330. };
  331. // 获取实时数据
  332. const realTimeData = ref({});
  333. const loading = ref(false);
  334. const nowTime = ref('');
  335. const fetchRealTimeData = async () => {
  336. loading.value = true;
  337. request
  338. .get('/order/recycleStatisticOverview/realtime')
  339. .then((res) => {
  340. if (res.data.code === 200) {
  341. loading.value = false;
  342. realTimeData.value = res.data.data;
  343. nowTime.value =
  344. res.data.data.nowTime ||
  345. dayjs().format('YYYY-MM-DD HH:mm:ss');
  346. // realTimeData.value.chatAxis = res.data.data.chatAxis.map(v=>`${v}点`);
  347. }
  348. })
  349. .finally(() => {
  350. loading.value = false;
  351. });
  352. };
  353. 2254;
  354. onMounted(() => {
  355. fetchProvinceData();
  356. fetchHistoryData();
  357. fetchRealTimeData();
  358. });
  359. </script>
  360. <style lang="scss">
  361. .stat-card {
  362. border-radius: 10px;
  363. background: #f8f7f6;
  364. padding: 20px;
  365. display: flex;
  366. flex-direction: column;
  367. justify-content: center;
  368. align-items: center;
  369. .el-statistic__head {
  370. text-align: center;
  371. }
  372. }
  373. </style>