detail.vue 22 KB

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