dashboard.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. <!-- 物联网卡-详情 -->
  2. <template>
  3. <div class="page">
  4. <el-card shadow="nover" class="page-full-part">
  5. <div shadow="nover" class="top-wrap">
  6. <div class="title flex">
  7. 数据统计
  8. <div class="select-wrap">
  9. <el-select v-model="types" placeholder="请选择" style="width: 320px" @change="typeChange()">
  10. <!-- 1电信,2联通,3移动 -->
  11. <el-option label="电信" :value="1" />
  12. <el-option label="联通" :value="2" />
  13. <el-option label="移动" :value="3" />
  14. </el-select>
  15. </div>
  16. </div>
  17. <div class="top-inner-wrap">
  18. <div class="line-wrap flow-line-wrap">
  19. <div class="text-wrap">
  20. <div class="text">昨日流量消耗</div>
  21. <div>{{formatSize(statisticsData.yesterdayTotal * 1024 * 1024)}}</div>
  22. </div>
  23. <div class="line-inner-wrap" ref="yesterdayLine"></div>
  24. </div>
  25. <div class="line-wrap flow-line-wrap">
  26. <div class="text-wrap">
  27. <div class="text">当月流量消耗</div>
  28. <div>{{formatSize(statisticsData.realMonthTotal * 1024 * 1024)}}</div>
  29. </div>
  30. <div class="line-inner-wrap" ref="monthLine"></div>
  31. </div>
  32. <div class="line-wrap flow-line-wrap">
  33. <div class="text-wrap">
  34. <div class="text">本年流量消耗</div>
  35. <div>{{formatSize(statisticsData.yearTotal * 1024 * 1024)}}</div>
  36. </div>
  37. <div class="line-inner-wrap" ref="yearLine"></div>
  38. </div>
  39. </div>
  40. </div>
  41. <div class="statistics-wrap gap-3">
  42. <el-card shadow="nover" class="left-wrap">
  43. <div class="top-title-wrap">
  44. <div class="title">流量统计</div>
  45. <div class="operate-wrap">
  46. <el-button-group>
  47. <el-button @click="changeDate(1)" :type="activeIndex == 1 ? 'primary' : ''">昨日</el-button>
  48. <el-button @click="changeDate(2)" :type="activeIndex == 2 ? 'primary' : ''">近一周</el-button>
  49. <el-button @click="changeDate(3)" :type="activeIndex == 3 ? 'primary' : ''">近一月</el-button>
  50. <el-button @click="changeDate(4)" :type="activeIndex == 4 ? 'primary' : ''">近一年</el-button>
  51. </el-button-group>
  52. <el-date-picker
  53. class="date-picker-wrap"
  54. v-model="dateTimeRange"
  55. :disabled-date="disabledDate"
  56. type="datetimerange"
  57. range-separator="至"
  58. start-placeholder="开始时间"
  59. end-placeholder="结束时间"
  60. format="YYYY-MM-DD HH:mm:ss"
  61. date-format="YYYY/MM/DD"
  62. time-format="hh:mm:ss"
  63. />
  64. </div>
  65. </div>
  66. <div style="height: 508px;" ref="flowLine"></div>
  67. </el-card>
  68. <el-card shadow="nover" class="right-wrap">
  69. <div class="top-title-wrap">
  70. <div class="title">流量使用TOP10</div>
  71. <el-date-picker
  72. class="date-picker-wrap"
  73. v-model="dateRange"
  74. :disabled-date="disabledDate"
  75. type="daterange"
  76. range-separator="至"
  77. start-placeholder="开始日期"
  78. end-placeholder="结束日期"
  79. format="YYYY-MM-DD"
  80. date-format="YYYY/MM/DD"
  81. />
  82. </div>
  83. <div class="ranking-list">
  84. <div class="rank-item" v-for="(item, index) in rankList" :key="index">
  85. <div :class="`number-item-${++index}`" class="number">{{index++}}</div>
  86. <div class="card-num">{{item.accessNumber}}</div>
  87. <el-progress class="progress-wrap" :text-inside="true" :stroke-width="16" :percentage="totalNum ? (item.value / totalNum * 100).toFixed(2) : 0" />
  88. <div class="flow-num">{{formatSize(item.value * 1024 * 1024)}}</div>
  89. </div>
  90. </div>
  91. </el-card>
  92. </div>
  93. </el-card>
  94. </div>
  95. </template>
  96. <script lang="ts" setup>
  97. import { ref, reactive, nextTick, watch, markRaw } from "vue"
  98. import { formatSize } from "/@/utils/common";
  99. import api from '/@/api/iotCard';
  100. import { useSearch } from "/@/hooks/useCommon";
  101. import { useStore } from '/@/store/index';
  102. import { useRoute } from 'vue-router';
  103. import * as echarts from 'echarts';
  104. import dayjs from 'dayjs';
  105. const store = useStore();
  106. const route = useRoute();
  107. const sim = ref({
  108. accNumber: "",// 卡号
  109. iccid: "",// ICCID
  110. bindDeviceName: "",// 绑定设备
  111. platName: "",// 平台对接
  112. types: "",// 运营商
  113. simTypes: "",// 类型
  114. totalFlow: "",// 总流量
  115. usedFlow: "",// 使用流量
  116. leaveFlow: "",// 剩余流量
  117. activationTime: "",// 激活日期
  118. updatedAt: "",// 更新时间
  119. simStatus: "",// 状态
  120. remark: ""// 说明
  121. })
  122. const types = ref(1);
  123. const statisticsData = ref({
  124. realMonthTotal: 0,
  125. yearTotal: 0,
  126. yesterdayTotal: 0
  127. })
  128. const flowLine = ref();
  129. const yesterdayLine = ref();
  130. const monthLine = ref();
  131. const yearLine = ref();
  132. const dateRange = ref<any>([
  133. dayjs(new Date()).subtract(1, 'month'),
  134. dayjs(new Date()),
  135. ])
  136. const dateTimeRange = ref<any>([
  137. dayjs(new Date()).subtract(6, 'day'),
  138. dayjs(new Date()),
  139. ])
  140. const totalNum = ref(0);
  141. const activeIndex= ref(2);
  142. const rankList = ref([]);
  143. const flowLineXAxisData = ref<any>([]);
  144. const flowLineData = ref<any>([]);
  145. const yearLineXAxisData = ref<any>([]);
  146. const yearLineData = ref<any>([]);
  147. const monthLineXAxisData = ref<any>([]);
  148. const monthLineData = ref<any>([]);
  149. const yesterdayLineXAxisData = ref<any>([dayjs(new Date()).subtract(1, 'day').format('YYYY-MM-DD')]);
  150. const yesterdayLineData = ref<any>([]);
  151. const state = reactive({
  152. global: {
  153. yesterdayLine: null,
  154. monthLine: null,
  155. yearLine: null,
  156. dispose: [null, '', undefined],
  157. } as any,
  158. myCharts: [],
  159. charts: {
  160. theme: '',
  161. bgColor: '',
  162. color: '#303133',
  163. },
  164. });
  165. const disabledDate = (time: Date) => {
  166. return time.getTime() > Date.now()
  167. }
  168. const getFlowDataByDateRange = async (dateRangeData:any) => {
  169. const simFlowRes = await api.dashboard.getFlowDataByDateRange({
  170. sdate: dayjs(dateRangeData[0]).format('YYYY-MM-DD HH:mm:ss'),
  171. edate: dayjs(dateRangeData[1]).format('YYYY-MM-DD HH:mm:ss'),
  172. types: types.value
  173. })
  174. return simFlowRes.data;
  175. }
  176. const getYesterdayFlowData = async () => {
  177. const yesterday = dayjs(new Date()).subtract(1, 'day').format('YYYY-MM-DD')
  178. const res = await getFlowDataByDateRange([
  179. yesterday + " 00:00:00",
  180. yesterday + " 23:59:59"
  181. ])
  182. yesterdayLineData.value = [res[0].value];
  183. initYesterdayLineChart();
  184. }
  185. const getMonthFlowData = async () => {
  186. monthLineXAxisData.value = [];
  187. monthLineData.value = [];
  188. const monthDay1 = dayjs(new Date()).startOf('month').format('YYYY-MM-DD');
  189. const monthDay2 = dayjs(new Date()).endOf('month').format('YYYY-MM-DD');
  190. const res = await getFlowDataByDateRange([monthDay1, monthDay2])
  191. res.reverse().forEach((item:any) => {
  192. monthLineXAxisData.value.push(item.date);
  193. monthLineData.value.push(item.value);
  194. })
  195. initMonthLineChart();
  196. }
  197. const getYearFlowData = async () => {
  198. yearLineXAxisData.value = [];
  199. yearLineData.value = [];
  200. const year = dayjs(new Date()).startOf('year').format('YYYY');
  201. const res = await getFlowDataByDateRange([
  202. year + '-01-01',
  203. year + '-12-31'
  204. ])
  205. res.reverse().forEach((item:any) => {
  206. yearLineXAxisData.value.push(item.date);
  207. yearLineData.value.push(item.value);
  208. })
  209. initYearLineChart();
  210. }
  211. const getFlowData = async () => {
  212. flowLineXAxisData.value = [];
  213. flowLineData.value = [];
  214. const res = await getFlowDataByDateRange(dateTimeRange.value)
  215. res.reverse().forEach((item:any) => {
  216. flowLineXAxisData.value.push(item.date);
  217. flowLineData.value.push(item.value);
  218. })
  219. iniFlowLineChart();
  220. }
  221. const changeDate = (key:number) => {
  222. // 1 昨天 2近一周 3近一月 4近一年
  223. activeIndex.value = key;
  224. if(key === 1) {
  225. // 昨天
  226. const yesterday = dayjs(new Date()).subtract(1, 'day').format('YYYY-MM-DD')
  227. dateTimeRange.value = [
  228. yesterday + " 00:00:00",
  229. yesterday + " 23:59:59"
  230. ]
  231. }else if(key === 2) {
  232. // 近一周
  233. dateTimeRange.value = [
  234. dayjs(new Date()).subtract(6, 'day'),
  235. dayjs(new Date()),
  236. ]
  237. }else if(key === 3) {
  238. // 近一月
  239. dateTimeRange.value = [
  240. dayjs(new Date()).subtract(1, 'month'),
  241. dayjs(new Date()),
  242. ]
  243. }else if(key === 4) {
  244. // 近一年
  245. dateTimeRange.value = [
  246. dayjs(new Date()).subtract(1, 'year'),
  247. dayjs(new Date()),
  248. ]
  249. }
  250. getFlowData();
  251. }
  252. const typeChange = (value:any) => {
  253. getYesterdayFlowData();
  254. getMonthFlowData();
  255. getYearFlowData();
  256. getFlowData();
  257. getTop10Data();
  258. }
  259. const getTop10Data = async () => {
  260. const top10Res = await api.dashboard.getTop10Data({
  261. sdate: dayjs(dateRange.value[0]).format('YYYY-MM-DD'),
  262. edate: dayjs(dateRange.value[1]).format('YYYY-MM-DD'),
  263. types: types.value
  264. })
  265. // if(!top10Res.data) return;
  266. rankList.value = top10Res.data || [];
  267. totalNum.value = top10Res.data ? top10Res.data[0].value : 0;
  268. }
  269. const getFlowAllData = async () => {
  270. const res = await api.dashboard.getFlowData({
  271. types: types.value
  272. })
  273. statisticsData.value = res
  274. }
  275. const formatOperator = (val:any) => {
  276. // 1电信,2联通,3移动
  277. if(val == 1) {
  278. return "电信"
  279. }else if(val == 2) {
  280. return "联通"
  281. }else if(val == 3) {
  282. return "移动"
  283. }
  284. }
  285. const formatType = (val:any) => {
  286. // 1月卡,2季卡,3年卡,4其他
  287. if(val == 1) {
  288. return "月卡"
  289. }else if(val == 2) {
  290. return "季卡"
  291. }else if(val == 3) {
  292. return "年卡"
  293. }else if(val == 4) {
  294. return "其他"
  295. }
  296. }
  297. const formatStatus = (val:any) => {
  298. // 1:可激活 2:测试激活 3:测试去激活 4:在用5:停机6:运营商管理状态
  299. if(val == 1) {
  300. return "可激活"
  301. }else if(val == 2) {
  302. return "测试激活"
  303. }else if(val == 3) {
  304. return "测试去激活"
  305. }else if(val == 4) {
  306. return "在用"
  307. }else if(val == 5) {
  308. return "停机"
  309. }else if(val == 6) {
  310. return "运营商管理状态"
  311. }
  312. }
  313. // 折线图 - 昨日流量消耗
  314. const initYesterdayLineChart = () => {
  315. if (!state.global.dispose.some((b: any) => b === state.global.yesterdayLine)) state.global.yesterdayLine.dispose();
  316. state.global.yesterdayLine = markRaw(echarts.init(yesterdayLine.value, state.charts.theme));
  317. const option = {
  318. backgroundColor: state.charts.bgColor,
  319. xAxis: {
  320. data: yesterdayLineXAxisData.value,
  321. show: false,
  322. },
  323. yAxis: [
  324. {
  325. type: 'value',
  326. name: '',
  327. show: false,
  328. splitLine: { show: false, lineStyle: { type: 'dashed', color: '#f5f5f5' } },
  329. },
  330. ],
  331. tooltip: {
  332. trigger: 'axis',
  333. formatter: function (params:any) {
  334. var relVal = params[0].name
  335. let circle = `<i style="margin-right:4px;display: inline-block;width: 10px;height: 10px;border-radius: 50%;background-color:${params[0].color}"></i>`
  336. relVal += '<br/>' + circle + ' 流量: ' + formatSize(params[0].value*1024*1024)
  337. return relVal;
  338. }
  339. },
  340. grid: { top: 10, right: 10, bottom: 10, left: 10 },
  341. series: [
  342. {
  343. name: '流量',
  344. type: 'line',
  345. smooth: true,
  346. data: yesterdayLineData.value,
  347. lineStyle: { color: '#fe9a8b' },
  348. itemStyle: { color: '#fe9a8b', borderColor: '#fe9a8b' },
  349. areaStyle: {
  350. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  351. { offset: 0, color: '#fe9a8bb3' },
  352. { offset: 1, color: '#fe9a8b03' },
  353. ]),
  354. },
  355. }
  356. ],
  357. };
  358. (<any>state.global.yesterdayLine).setOption(option);
  359. (<any>state.myCharts).push(state.global.yesterdayLine);
  360. };
  361. // 折线图 - 当月流量消耗
  362. const initMonthLineChart = () => {
  363. if (!state.global.dispose.some((b: any) => b === state.global.monthLine)) state.global.monthLine.dispose();
  364. state.global.monthLine = markRaw(echarts.init(monthLine.value, state.charts.theme));
  365. const option = {
  366. backgroundColor: state.charts.bgColor,
  367. xAxis: {
  368. data: monthLineXAxisData.value,
  369. show: false,
  370. },
  371. yAxis: [
  372. {
  373. type: 'value',
  374. name: '',
  375. show: false,
  376. },
  377. ],
  378. tooltip: {
  379. trigger: 'axis',
  380. formatter: function (params:any) {
  381. var relVal = params[0].name
  382. let circle = `<i style="margin-right:4px;display: inline-block;width: 10px;height: 10px;border-radius: 50%;background-color:${params[0].color}"></i>`
  383. relVal += '<br/>' + circle + ' 流量: ' + formatSize(params[0].value*1024*1024)
  384. return relVal;
  385. }
  386. },
  387. grid: { top: 10, right: 10, bottom: 10, left: 10 },
  388. series: [
  389. {
  390. name: '流量',
  391. type: 'line',
  392. smooth: true,
  393. data: monthLineData.value,
  394. lineStyle: { color: '#9E87FF' },
  395. itemStyle: { color: '#9E87FF', borderColor: '#9E87FF' },
  396. areaStyle: {
  397. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  398. { offset: 0, color: '#9E87FFb3' },
  399. { offset: 1, color: '#9E87FF03' },
  400. ]),
  401. },
  402. }
  403. ],
  404. };
  405. (<any>state.global.monthLine).setOption(option);
  406. (<any>state.myCharts).push(state.global.monthLine);
  407. };
  408. // 折线图 - 本年流量消耗
  409. const initYearLineChart = () => {
  410. if (!state.global.dispose.some((b: any) => b === state.global.yearLine)) state.global.yearLine.dispose();
  411. state.global.yearLine = markRaw(echarts.init(yearLine.value, state.charts.theme));
  412. const option = {
  413. backgroundColor: state.charts.bgColor,
  414. xAxis: {
  415. data: yearLineXAxisData.value,
  416. show: false,
  417. },
  418. yAxis: [
  419. {
  420. type: 'value',
  421. name: '',
  422. show: false,
  423. splitLine: { show: false, lineStyle: { type: 'dashed', color: '#f5f5f5' } }
  424. }
  425. ],
  426. tooltip: {
  427. trigger: 'axis',
  428. formatter: function (params:any) {
  429. var relVal = params[0].name
  430. let circle = `<i style="margin-right:4px;display: inline-block;width: 10px;height: 10px;border-radius: 50%;background-color:${params[0].color}"></i>`
  431. relVal += '<br/>' + circle + ' 流量: ' + formatSize(params[0].value*1024*1024)
  432. return relVal;
  433. }
  434. },
  435. grid: { top: 10, right: 10, bottom: 10, left: 10 },
  436. series: [
  437. {
  438. name: '流量',
  439. type: 'line',
  440. smooth: true,
  441. data: yearLineData.value,
  442. lineStyle: { color: '#fe9a8b' },
  443. itemStyle: { color: '#fe9a8b', borderColor: '#fe9a8b' },
  444. areaStyle: {
  445. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  446. { offset: 0, color: '#fe9a8bb3' },
  447. { offset: 1, color: '#fe9a8b03' },
  448. ]),
  449. },
  450. }
  451. ],
  452. };
  453. (<any>state.global.yearLine).setOption(option);
  454. (<any>state.myCharts).push(state.global.yearLine);
  455. };
  456. // 折线图 - 流量统计
  457. const iniFlowLineChart = async () => {
  458. if (!state.global.dispose.some((b: any) => b === state.global.flowLine)) state.global.flowLine.dispose();
  459. state.global.flowLine = markRaw(echarts.init(flowLine.value, state.charts.theme));
  460. const option = {
  461. backgroundColor: state.charts.bgColor,
  462. grid: { top: 70, right: 20, bottom: 30, left: 30 },
  463. tooltip: {
  464. trigger: 'axis',
  465. formatter: function (params:any) {
  466. var relVal = params[0].name
  467. let circle = `<i style="margin-right:4px;display: inline-block;width: 10px;height: 10px;border-radius: 50%;background-color:${params[0].color}"></i>`
  468. relVal += '<br/>' + circle + ' 流量: ' + params[0].value + 'MB'
  469. return relVal;
  470. }
  471. },
  472. xAxis: {
  473. data: flowLineXAxisData.value,
  474. },
  475. yAxis: [
  476. {
  477. type: 'value',
  478. name: '',
  479. splitLine: { show: true, lineStyle: { type: 'dashed', color: '#f5f5f5' } },
  480. axisLabel: {
  481. margin: 2,
  482. formatter: function (value:any, index:any) {
  483. if (value >= 10000 && value < 10000000) {
  484. value = value / 10000 + "W";
  485. } else if (value >= 10000000) {
  486. value = value / 10000000 + "KW";
  487. }
  488. return value;
  489. }
  490. },
  491. },
  492. ],
  493. series: [
  494. {
  495. name: '流量',
  496. type: 'line',
  497. symbolSize: 6,
  498. symbol: 'circle',
  499. smooth: true,
  500. data: flowLineData.value,
  501. lineStyle: { color: '#9E87FF' },
  502. itemStyle: { color: '#9E87FF', borderColor: '#9E87FF' },
  503. areaStyle: {
  504. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  505. { offset: 0, color: '#9E87FFb3' },
  506. { offset: 1, color: '#9E87FF03' },
  507. ]),
  508. },
  509. emphasis: {
  510. itemStyle: {
  511. color: {
  512. type: 'radial',
  513. x: 0.5,
  514. y: 0.5,
  515. r: 0.5,
  516. colorStops: [
  517. { offset: 0, color: '#9E87FF' },
  518. { offset: 0.4, color: '#9E87FF' },
  519. { offset: 0.5, color: '#fff' },
  520. { offset: 0.7, color: '#fff' },
  521. { offset: 0.8, color: '#fff' },
  522. { offset: 1, color: '#fff' },
  523. ],
  524. },
  525. borderColor: '#9E87FF',
  526. borderWidth: 2,
  527. },
  528. },
  529. },
  530. ],
  531. };
  532. (<any>state.global.flowLine).setOption(option);
  533. (<any>state.myCharts).push(state.global.flowLine);
  534. };
  535. getFlowAllData();
  536. getYesterdayFlowData();
  537. getMonthFlowData();
  538. getYearFlowData();
  539. getFlowData();
  540. getTop10Data();
  541. // 监听 vuex 中是否开启深色主题
  542. watch(
  543. () => store.state.themeConfig.themeConfig.isIsDark,
  544. (isIsDark) => {
  545. nextTick(() => {
  546. state.charts.theme = isIsDark ? 'dark' : '';
  547. state.charts.bgColor = isIsDark ? 'transparent' : '';
  548. state.charts.color = isIsDark ? '#dadada' : '#303133';
  549. setTimeout(() => {
  550. iniFlowLineChart();
  551. initYesterdayLineChart();
  552. initMonthLineChart();
  553. initYearLineChart();
  554. }, 500);
  555. });
  556. },
  557. {
  558. deep: true,
  559. immediate: true,
  560. }
  561. );
  562. </script>
  563. <style lang="scss" scoped>
  564. .select-wrap {
  565. text-align: right;
  566. }
  567. .top-wrap {
  568. width: 100%;
  569. .flex {
  570. justify-content: space-between;
  571. }
  572. .top-inner-wrap {
  573. display: flex;
  574. margin-top: 10px;
  575. }
  576. .line-wrap {
  577. flex: 1;
  578. background-color: #fff;
  579. background: #fcfcfc;
  580. border: 1px solid #e0e4e8;
  581. display: flex;
  582. justify-content: space-between;
  583. align-items: center;
  584. padding: 20px;
  585. position: relative;
  586. .text-wrap {
  587. position: absolute;
  588. left: 20px;
  589. top: 40px;
  590. .text {
  591. font-size: 14px;
  592. color: #000000a3;
  593. }
  594. div:nth-child(2) {
  595. font-size: 32px;
  596. font-weight: 700;
  597. overflow: hidden;
  598. white-space: nowrap;
  599. text-overflow: ellipsis;
  600. }
  601. }
  602. .line-inner-wrap {
  603. height: 100px;
  604. width: calc(100% - 150px);
  605. margin-left: 150px;
  606. }
  607. }
  608. .line-wrap:not(:nth-child(1)) {
  609. margin-left: 20px;
  610. }
  611. }
  612. .title {
  613. color: var(--el-text-color-primary);
  614. font-size: 16px;
  615. font-weight: 700;
  616. }
  617. .statistics-wrap {
  618. display: flex;
  619. justify-content: space-between;
  620. align-items: normal;
  621. margin-top: 20px;
  622. .left-wrap {
  623. width: 67%;
  624. .top-title-wrap {
  625. display: flex;
  626. justify-content: space-between;
  627. align-items: center;
  628. margin-bottom: 16px;
  629. ::v-deep .el-date-editor.el-input__wrapper {
  630. width: 360px!important;
  631. margin-left: 12px;
  632. }
  633. .operate-wrap {
  634. display: flex;
  635. justify-content: center;
  636. align-items: center;
  637. }
  638. }
  639. }
  640. .right-wrap {
  641. width: 33%;
  642. .top-title-wrap {
  643. display: flex;
  644. justify-content: space-between;
  645. align-items: center;
  646. margin-bottom: 16px;
  647. ::v-deep .el-date-editor.el-input__wrapper {
  648. max-width: 220px!important;
  649. }
  650. }
  651. .ranking-list {
  652. width: 100%;
  653. .rank-item {
  654. width: 100%;
  655. display: flex;
  656. justify-content: space-between;
  657. align-items: center;
  658. margin-bottom: 24px;
  659. .number {
  660. flex: 0 0 24px;
  661. height: 24px;
  662. color: #fff;
  663. font-weight: 700;
  664. line-height: 24px;
  665. text-align: center;
  666. background-color: #d1d1d1;
  667. }
  668. .number-item-1 {
  669. color: #e50012;
  670. background-color: #e500121a;
  671. }
  672. .number-item-2 {
  673. color: #fba500;
  674. background-color: #fba5001a;
  675. }
  676. .number-item-3 {
  677. color: #597ef7;
  678. background-color: #597ef71a;
  679. }
  680. .card-num {
  681. width: 110px;
  682. }
  683. .progress-wrap {
  684. width: 32%;
  685. }
  686. .flow-num {
  687. width: 90px;
  688. text-align: right;
  689. }
  690. }
  691. }
  692. }
  693. }
  694. </style>