StatisticalAnalysis.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. <template>
  2. <div class="mainBox">
  3. <!-- 搜索区域 -->
  4. <div class="searchBox">
  5. <div>
  6. <!-- 添加一个按钮触发事件 -->
  7. <!-- <el-button type="primary" @click="playTTS()">请求音频</el-button> -->
  8. <!-- 对比时间:
  9. <el-date-picker
  10. v-model="lastTimes"
  11. type="daterange"
  12. unlink-panels
  13. range-separator="到"
  14. start-placeholder="开始时间"
  15. end-placeholder="结束时间"
  16. disabled
  17. size="large"
  18. style="margin-right: 30px"
  19. /> -->
  20. 搜索时间:
  21. <el-date-picker
  22. v-model="nowTimes"
  23. type="daterange"
  24. unlink-panels
  25. range-separator="到"
  26. start-placeholder="开始时间"
  27. end-placeholder="结束时间"
  28. :shortcuts="shortcutsFun"
  29. size="large"
  30. />
  31. </div>
  32. </div>
  33. <!-- 服务调用card -->
  34. <div class="flex">
  35. <card
  36. v-for="item in TopCardDatas"
  37. :key="item.name"
  38. class="card flex"
  39. :title="item.name"
  40. :value="item.value"
  41. :growth="item.growth"
  42. :iconColor="item.iconColor"
  43. :upStatus="item.upStatus"
  44. />
  45. </div>
  46. <!-- 服务类信息统计 -->
  47. <div class="bigCard">
  48. <div class="bigCard_title">服务类信息统计</div>
  49. <div class="tools">
  50. <el-button>
  51. <el-icon><Upload /></el-icon> 导出数据
  52. </el-button>
  53. <el-button type="primary">
  54. <el-icon><TrendCharts /></el-icon>
  55. 详细报告
  56. </el-button>
  57. </div>
  58. <div class="flex">
  59. <div style="width: 48%; height: 400px">
  60. <EchartsDome :chartOption="chartOptions['服务调用趋势']" title="服务调用趋势" />
  61. </div>
  62. <div style="width: 48%; height: 400px">
  63. <EchartsDome title="服务类别分布" :chartOption="chartOptions['服务类别分布']" />
  64. </div>
  65. </div>
  66. <div style="width: 100%; height: 400px">
  67. <Table title="服务调用TOP10" :tableData="tableDatas" />
  68. </div>
  69. </div>
  70. <!-- 委办信息统计 -->
  71. <div class="bigCard">
  72. <div class="bigCard_title">委办信息统计</div>
  73. <div class="flex">
  74. <div style="width: 28%; height: 400px">
  75. <EchartsDome :chartOption="chartOptions['委办分布']" title="委办分布" />
  76. </div>
  77. <div style="width: 68%; height: 400px">
  78. <EchartsDome
  79. :chartOption="chartOptions['委办活跃度趋势']"
  80. title="委办活跃度趋势"
  81. />
  82. </div>
  83. </div>
  84. <!-- <div style="width: 100%; height: 400px">
  85. <EchartsDome :chartOption="chartOptions['用户部门分布']" title="用户部门分布" />
  86. </div> -->
  87. </div>
  88. <!-- 应用类信息统计 -->
  89. <div class="bigCard">
  90. <div class="bigCard_title">应用类信息统计</div>
  91. <div class="flex">
  92. <div style="width: 58%; height: 400px">
  93. <EchartsDome
  94. :chartOption="chartOptions['热点应用TOP10排名']"
  95. title="热点应用TOP10排名"
  96. />
  97. </div>
  98. <div style="width: 38%; height: 400px">
  99. <EchartsDome :chartOption="chartOptions['应用状态分布']" title="应用状态分布" />
  100. </div>
  101. </div>
  102. </div>
  103. <!-- 数据类信息统计 -->
  104. <div class="bigCard">
  105. <div class="bigCard_title">数据类信息统计</div>
  106. <div class="flex">
  107. <div style="width: 50%; height: 400px">
  108. <EchartsDome :chartOption="chartOptions['数据类别分布']" title="数据类别分布" />
  109. </div>
  110. <div style="width: 50%; height: 400px">
  111. <EchartsDome :chartOption="chartOptions['数据质量评分']" title="数据质量评分" />
  112. </div>
  113. </div>
  114. </div>
  115. <!-- 区级特色信息统计 -->
  116. <div class="bigCard">
  117. <div class="bigCard_title">区级特色信息统计</div>
  118. <div class="flex" style="margin-top: 20px">
  119. <div class="flex_column" style="width: 28%; height: 420px">
  120. <card
  121. class="card2 flex"
  122. :title="'服务机构总数'"
  123. value="8"
  124. :growth="'较上个月增长了12%'"
  125. iconColor="#2563db"
  126. :upStatus="1"
  127. />
  128. <card
  129. class="card2 flex"
  130. :title="'服务总数'"
  131. value="100"
  132. :growth="'较上个月下降了12%'"
  133. iconColor="#16a34a"
  134. :upStatus="-1"
  135. />
  136. <card
  137. class="card2 flex"
  138. :title="'服务调用总次数'"
  139. value="1000"
  140. :growth="'较上个月增长了12%'"
  141. iconColor="#9333ea"
  142. :upStatus="1"
  143. />
  144. </div>
  145. <div style="width: 68%; height: 420px">
  146. <EchartsDome :chartOption="chartOptions['服务调用趋势']" title="服务调用趋势" />
  147. </div>
  148. </div>
  149. </div>
  150. </div>
  151. </template>
  152. <script>
  153. import card from "@/components/yxgl/card.vue";
  154. import EchartsDome from "@/components/yxgl/EchartsDome.vue";
  155. import Table from "@/components/yxgl/table.vue";
  156. import appCenter from "@/api/appCenter";
  157. import { color } from "echarts";
  158. export default {
  159. name: "",
  160. components: {
  161. card,
  162. EchartsDome,
  163. Table,
  164. },
  165. data() {
  166. return {
  167. // 比较的时间范围(默认60天到30天前,主要跟nowTimes有关系)
  168. lastTimes: [],
  169. // 当前选中的时间范围
  170. nowTimes: [],
  171. TopCardDatas: [
  172. {
  173. name: "委办总数",
  174. value: "-",
  175. growth: "--",
  176. iconColor: "#2563db",
  177. iconName: "OfficeBuilding",
  178. upStatus: 0,
  179. },
  180. {
  181. name: "系统总数",
  182. value: "-",
  183. growth: "--",
  184. iconColor: "#16a34a",
  185. iconName: "WalletFilled",
  186. upStatus: 0,
  187. },
  188. {
  189. name: "服务总数",
  190. value: "-",
  191. growth: "--",
  192. iconColor: "#9333ea",
  193. iconName: "TrendCharts",
  194. upStatus: 0,
  195. },
  196. {
  197. name: "服务调用总数",
  198. value: "-",
  199. growth: "--",
  200. iconColor: "#ca8a04",
  201. iconName: "TrendCharts",
  202. upStatus: 0,
  203. },
  204. ],
  205. shortcutsFun: this.shortcuts(),
  206. chartOptions: {},
  207. tableDatas: [],
  208. };
  209. },
  210. watch: {
  211. nowTimes: {
  212. handler(newVal, oldVal) {
  213. if (newVal !== oldVal && newVal.length > 0) {
  214. // 计算出比较的时间范围
  215. this.lastTimes = [
  216. this.$moment(
  217. new Date(
  218. new Date(newVal[0]).setTime(
  219. new Date(newVal[0]).getTime() -
  220. (newVal[1] - newVal[0]) -
  221. 24 * 60 * 60 * 1000
  222. )
  223. )
  224. ).format("YYYY-MM-DD 00:00:00"),
  225. this.$moment(new Date(newVal[0])).format("YYYY-MM-DD 00:00:00"),
  226. ];
  227. this.initChart();
  228. }
  229. },
  230. deep: true,
  231. // immediate: true,
  232. },
  233. },
  234. mounted() {
  235. this.$nextTick(() => {
  236. this.nowTimes = [
  237. new Date(new Date().setTime(new Date() - 3600 * 1000 * 24 * 30)),
  238. new Date(),
  239. ];
  240. });
  241. },
  242. methods: {
  243. playTTS() {
  244. const url = "http://192.168.2.8:8008/api/tts/audio";
  245. fetch(url, {
  246. method: "POST",
  247. headers: {
  248. "Content-Type": "application/json",
  249. },
  250. body: JSON.stringify({
  251. text: `纸扎铺的灯笼
  252. 深巷尽头的纸扎铺,夜半总飘出灯笼光。
  253. 我加班晚归,撞见铺门虚掩,昏黄的灯笼悬在檐下,穗子无风自动。老板低头扎纸人,指尖翻飞,纸人眉眼竟和巷口失踪的外卖员一模一样。
  254. “要灯笼吗?” 他头也不抬,声音像揉皱的黄纸。
  255. 我拔腿就跑,身后传来细碎的脚步声。回头看,那盏灯笼悠悠跟着,灯笼里的烛火,映出一张纸糊的脸。
  256. 次日清晨,巷口多了一盏新灯笼,上面贴着我的名字。`,
  257. }),
  258. })
  259. .then((response) => response.blob()) // 转换为Blob对象
  260. .then((blob) => {
  261. const audio = new Audio();
  262. const blobUrl = window.URL.createObjectURL(blob);
  263. audio.src = blobUrl;
  264. audio.play();
  265. audio.onended = () => {
  266. window.URL.revokeObjectURL(blobUrl);
  267. };
  268. })
  269. .catch((error) => {
  270. console.error("TTS请求失败:", error);
  271. });
  272. },
  273. initChart() {
  274. // 获取运行管理页面数据
  275. appCenter
  276. .getAllYxglDatas({
  277. nowTimes: [
  278. this.$moment(new Date(this.nowTimes[0])).format("YYYY-MM-DD 00:00:00"),
  279. this.$moment(new Date(this.nowTimes[1])).format("YYYY-MM-DD 23:59:59"),
  280. ],
  281. lastTimes: this.lastTimes,
  282. })
  283. .then((res) => {
  284. if (res && res.code == 200) {
  285. this.TopCardDatas = res.content.TopCardDatas;
  286. this.dataToOption(
  287. "服务调用趋势",
  288. "line",
  289. [...res.content.serviceCountTrend],
  290. {
  291. legend: { data: ["调用次数"] },
  292. xData: [],
  293. xKey: "key",
  294. xFormart: "YYYY-MM-DD",
  295. yAxis: {
  296. type: "value",
  297. name: "调用次数",
  298. axisLine: { lineStyle: { color: "#42a5f5" } }, // 区分样式
  299. },
  300. yData: {
  301. key: "value",
  302. name: "调用次数",
  303. color: "#42a5f5",
  304. data: [],
  305. yAxisIndex: 0,
  306. },
  307. }
  308. );
  309. // 初始化服务类别分布,这个地方需要先根据serviceType进行groupBy统计调用次数
  310. this.dataToOption("服务类别分布", "pie", [...res.content.serviceCountType], {
  311. pieKey: { value: "value", name: "key" },
  312. pieData: [],
  313. });
  314. // 服务调用TOP10《cPathComment+cUnit,调用次数》
  315. let serviceDatas = [];
  316. serviceDatas = res.content.serviceCountTop;
  317. // 排序
  318. serviceDatas.sort((a, b) => b.c_count - a.c_count);
  319. this.initTableDatas(serviceDatas.slice(0, 10));
  320. // 委办分布
  321. this.dataToOption("委办分布", "pie", [...res.content.serviceCountUnit], {
  322. pieKey: { value: "value", name: "key" },
  323. pieData: [],
  324. legend: {
  325. bottom: 10,
  326. },
  327. radius: "60%",
  328. padAngle: 0,
  329. borderRadius: 0,
  330. label: {},
  331. });
  332. // 先清洗一下res.content.serviceCountUnitTrend
  333. let serviceCountUnitTrend = [];
  334. serviceCountUnitTrend = res.content.serviceCountUnitTrend;
  335. let serviceCountUnitTrendLegend = [];
  336. let itemData = serviceCountUnitTrend[0];
  337. for (let key in itemData) {
  338. if (key !== "key") {
  339. serviceCountUnitTrendLegend.push(key);
  340. }
  341. }
  342. this.dataToOption(
  343. "委办活跃度趋势",
  344. "line",
  345. [...res.content.serviceCountUnitTrend],
  346. {
  347. legend: { data: serviceCountUnitTrendLegend },
  348. xData: [],
  349. xKey: "key",
  350. xFormart: "YYYY-MM-DD",
  351. yAxis: {
  352. type: "value",
  353. axisLine: { lineStyle: { color: "#42a5f5" } }, // 区分样式
  354. },
  355. yDatas: { auto: true },
  356. }
  357. );
  358. let serviceDatas2 = [];
  359. serviceDatas2 = res.content.serviceCountApplicationTop;
  360. // 排序
  361. serviceDatas2.sort((a, b) => a.c_count - b.c_count);
  362. // 用户部门分布
  363. this.dataToOption("热点应用TOP10排名", "bar", serviceDatas2.slice(0, 10), {
  364. showLegend: false,
  365. xData: [],
  366. xKey: "c_application",
  367. yData: {
  368. key: "c_count",
  369. name: "调用次数",
  370. color: "#42a5f5",
  371. data: [],
  372. },
  373. });
  374. // 数据类别分布
  375. if (res.content.dataTypes && res.content.dataTypes.length > 0) {
  376. this.dataToOption("数据类别分布", "pie", [...res.content.dataTypes], {
  377. pieKey: { value: "count", name: "service_name" },
  378. pieData: [],
  379. legend: {
  380. bottom: 10,
  381. },
  382. radius: "60%",
  383. padAngle: 0,
  384. borderRadius: 0,
  385. label: {},
  386. });
  387. }
  388. // console.log("getAllYxglDatas", res);
  389. }
  390. });
  391. // 应用状态分布,cloumnId:1659
  392. appCenter
  393. .getDmsDataList({
  394. columnId: 1659,
  395. pageSize: 1000,
  396. page: 0,
  397. })
  398. .then((res) => {
  399. if (res.code == 200) {
  400. let dmsDatas = res.content.data;
  401. let tableDatas = [];
  402. // 根据状态进行groupBy统计个数
  403. let statusMap = {};
  404. dmsDatas.forEach((item) => {
  405. if (statusMap[item.appstauts + ""]) {
  406. statusMap[item.appstauts + ""] += 1;
  407. } else {
  408. statusMap[item.appstauts + ""] = 1;
  409. }
  410. });
  411. // 转换为数组
  412. for (let key in statusMap) {
  413. if (statusMap[key] && key) {
  414. tableDatas.push({
  415. name: this.$getDmsTypes("appstatus", key),
  416. value: statusMap[key],
  417. });
  418. }
  419. }
  420. this.dataToOption("应用状态分布", "pie", tableDatas, {
  421. pieKey: { value: "value", name: "name" },
  422. pieData: [],
  423. });
  424. } else {
  425. this.$message({
  426. type: "error",
  427. message: "服务器忙碌,请稍后重试!",
  428. });
  429. }
  430. });
  431. this.dataToOption("数据质量评分", "radar", null, null);
  432. },
  433. /**
  434. * 数据转换为图表选项
  435. * @param title 图表标题
  436. * @param type 图表类型
  437. * @param datas 原始数据
  438. * @param keyRule 解析规则
  439. */
  440. async dataToOption(title, type, datas, keyRule) {
  441. // 根据规则解析数据
  442. if (keyRule) {
  443. datas.forEach((item) => {
  444. // 有的图表没有X轴
  445. if (keyRule.xKey) {
  446. if (keyRule.xFormart) {
  447. item[keyRule.xKey] = this.$moment(item[keyRule.xKey]).format(
  448. keyRule.xFormart
  449. );
  450. }
  451. keyRule.xData.push(item[keyRule.xKey]);
  452. }
  453. if (keyRule.yData) {
  454. keyRule.yData.data.push(item[keyRule.yData.key]);
  455. keyRule.series = [
  456. {
  457. name: keyRule.yData.name,
  458. type: "line",
  459. smooth: true,
  460. data: keyRule.yData.data,
  461. lineStyle: {
  462. color: keyRule.yData.color ? keyRule.yData.color : "",
  463. type: keyRule.yData.ifDashed ? "dashed" : "",
  464. }, // 蓝色线条
  465. itemStyle: keyRule.yData.color,
  466. symbol: "circle", // 节点形状
  467. symbolSize: 6, // 节点大小
  468. },
  469. ];
  470. }
  471. if (keyRule.yDatas) {
  472. // 先根据lenged得到data集合
  473. for (let name of keyRule.legend.data) {
  474. if (keyRule.yDatas[name]) {
  475. keyRule.yDatas[name].data.push(item[name]);
  476. } else {
  477. keyRule.yDatas[name] = {
  478. name: name,
  479. data: [item[name]],
  480. };
  481. }
  482. }
  483. }
  484. if (keyRule.pieKey) {
  485. keyRule.pieData.push({
  486. value: item[keyRule.pieKey.value],
  487. name: item[keyRule.pieKey.name],
  488. });
  489. }
  490. });
  491. // 专门用来处理多y数据的series
  492. if (keyRule.yDatas) {
  493. keyRule.series = [];
  494. for (let name of keyRule.legend.data) {
  495. keyRule.series.push({
  496. name: name,
  497. type: "line",
  498. smooth: true,
  499. data: keyRule.yDatas[name].data,
  500. symbol: "circle", // 节点形状
  501. symbolSize: 6, // 节点大小
  502. });
  503. }
  504. }
  505. }
  506. let _option = {};
  507. switch (type) {
  508. case "line":
  509. // 折线图基础
  510. _option = {
  511. legend: {
  512. data: keyRule.legend.data,
  513. },
  514. tooltip: {
  515. show: true,
  516. trigger: "axis",
  517. axisPointer: { type: "shadow" },
  518. },
  519. // 默认样式
  520. xAxis: {
  521. type: "category",
  522. data: keyRule.xData,
  523. axisTick: { show: false }, // 隐藏刻度
  524. splitLine: { show: false }, // 隐藏分割线
  525. axisLabel: {
  526. color: "#F2F3F5cc", // 字体颜色(支持十六进制、RGB、颜色名)
  527. fontSize: 14, // 可选:字体大小
  528. fontWeight: "normal", // 可选:字体粗细
  529. },
  530. },
  531. yAxis: {
  532. type: "value",
  533. axisLabel: {
  534. color: "#42a5f5cc", // 字体颜色(支持十六进制、RGB、颜色名)
  535. fontSize: 14, // 可选:字体大小
  536. fontWeight: "normal", // 可选:字体粗细
  537. },
  538. splitLine: { lineStyle: { color: "#42a5f532" } },
  539. },
  540. series: keyRule.series,
  541. };
  542. break;
  543. case "pie":
  544. // 饼状图
  545. _option = {
  546. tooltip: {
  547. trigger: "item",
  548. },
  549. legend: keyRule.legend
  550. ? keyRule.legend
  551. : {
  552. orient: "vertical",
  553. top: "50%",
  554. right: 10,
  555. },
  556. series: [
  557. {
  558. name: title,
  559. type: "pie",
  560. radius: keyRule.radius ? keyRule.radius : ["40%", "70%"],
  561. avoidLabelOverlap: false,
  562. padAngle: keyRule.padAngle != undefined ? keyRule.padAngle : 5,
  563. itemStyle: {
  564. borderRadius:
  565. keyRule.borderRadius != undefined ? keyRule.borderRadius : 10,
  566. },
  567. label:
  568. keyRule.label != undefined
  569. ? keyRule.label
  570. : {
  571. show: false,
  572. position: "center",
  573. },
  574. emphasis: {
  575. label: {
  576. show: true,
  577. fontSize: 20,
  578. fontWeight: "bold",
  579. },
  580. },
  581. labelLine: {
  582. show: true,
  583. },
  584. data: keyRule.pieData,
  585. },
  586. ],
  587. };
  588. break;
  589. case "bar":
  590. // 柱状图
  591. _option = {
  592. tooltip: {
  593. trigger: "axis",
  594. axisPointer: {
  595. type: "shadow",
  596. },
  597. },
  598. legend: {
  599. show: keyRule.showLegend ? keyRule.showLegend : false,
  600. data: keyRule.legend,
  601. },
  602. xAxis: {
  603. type: "value",
  604. axisLabel: {
  605. color: "#42a5f5cc", // 字体颜色(支持十六进制、RGB、颜色名)
  606. fontSize: 14, // 可选:字体大小
  607. fontWeight: "normal", // 可选:字体粗细
  608. },
  609. splitLine: { lineStyle: { color: "#42a5f532" } },
  610. },
  611. yAxis: {
  612. type: "category",
  613. data: keyRule.xData,
  614. axisLabel: {
  615. color: "#F2F3F5cc", // 字体颜色(支持十六进制、RGB、颜色名)
  616. fontSize: 14, // 可选:字体大小
  617. fontWeight: "normal", // 可选:字体粗细
  618. },
  619. },
  620. series: [
  621. {
  622. name: keyRule.yData.name,
  623. type: "bar",
  624. label: {
  625. show: true,
  626. },
  627. emphasis: {
  628. focus: "series",
  629. },
  630. data: keyRule.yData.data,
  631. },
  632. ],
  633. };
  634. break;
  635. default:
  636. // 雷达图
  637. _option = {
  638. tooltip: {
  639. trigger: "axis",
  640. },
  641. legend: {
  642. show: false,
  643. left: "center",
  644. },
  645. radar: [
  646. {
  647. indicator: [
  648. { name: "健壮性", max: 100 },
  649. { name: "完整性", max: 100 },
  650. { name: "一致性", max: 100 },
  651. { name: "及时性", max: 100 },
  652. { name: "准确性", max: 100 },
  653. ],
  654. },
  655. ],
  656. series: [
  657. {
  658. type: "radar",
  659. areaStyle: {},
  660. data: [
  661. {
  662. value: [93, 85, 92, 95, 93],
  663. name: "",
  664. },
  665. ],
  666. },
  667. ],
  668. };
  669. break;
  670. }
  671. this.chartOptions[title] = _option;
  672. },
  673. // 服务调用列表
  674. initTableDatas(serviceTypeDatas2) {
  675. this.tableDatas = serviceTypeDatas2;
  676. },
  677. // 时间范围自定义时间
  678. shortcuts() {
  679. return [
  680. {
  681. text: "当天",
  682. value: () => {
  683. const end = new Date();
  684. const start = new Date();
  685. return [start, end];
  686. },
  687. },
  688. {
  689. text: "最近7天",
  690. value: () => {
  691. const end = new Date();
  692. const start = new Date();
  693. start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
  694. return [start, end];
  695. },
  696. },
  697. {
  698. text: "最近30天",
  699. value: () => {
  700. const end = new Date();
  701. const start = new Date();
  702. start.setTime(start.getTime() - 3600 * 1000 * 24 * 29);
  703. return [start, end];
  704. },
  705. },
  706. {
  707. text: "最近90天",
  708. value: () => {
  709. const end = new Date();
  710. const start = new Date();
  711. start.setTime(start.getTime() - 3600 * 1000 * 24 * 89);
  712. return [start, end];
  713. },
  714. },
  715. {
  716. text: "最近1年",
  717. value: () => {
  718. const end = new Date();
  719. const start = new Date();
  720. start.setTime(start.getTime() - 3600 * 1000 * 24 * 364);
  721. return [start, end];
  722. },
  723. },
  724. ];
  725. },
  726. },
  727. };
  728. </script>
  729. <style lang="less" scoped>
  730. .mainBox {
  731. width: calc(100% - 60px);
  732. margin: 30px;
  733. & > div {
  734. margin: 20px 0;
  735. display: flex;
  736. }
  737. .card {
  738. width: calc(25% - 56px);
  739. border-radius: 5px;
  740. padding: 20px 18px;
  741. // background: #00000032;
  742. background: rgba(255, 255, 255, 0.1);
  743. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
  744. }
  745. .card2 {
  746. width: 100%;
  747. border-radius: 5px;
  748. padding: 20px 18px;
  749. // background: rgba(255, 255, 255, 0.1);
  750. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
  751. }
  752. .bigCard {
  753. width: calc(100% - 36px);
  754. border-radius: 5px;
  755. padding: 20px 18px;
  756. // background: #00000032;
  757. position: relative;
  758. flex-direction: column;
  759. background: rgba(255, 255, 255, 0.1);
  760. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
  761. .tools {
  762. position: absolute;
  763. top: 20px;
  764. right: 20px;
  765. display: flex;
  766. flex-direction: row;
  767. justify-content: flex-end;
  768. }
  769. &_title {
  770. font-size: 20px;
  771. font-weight: bold;
  772. }
  773. }
  774. .flex {
  775. display: flex;
  776. flex-direction: row;
  777. justify-content: space-between;
  778. }
  779. .flex_column {
  780. display: flex;
  781. flex-direction: column;
  782. justify-content: space-between;
  783. align-items: flex-start;
  784. box-sizing: border-box;
  785. }
  786. .searchBox {
  787. width: 100%;
  788. height: 50px;
  789. line-height: 50px;
  790. text-align: center;
  791. font-size: 20px;
  792. font-weight: bold;
  793. flex-direction: row-reverse;
  794. display: flex;
  795. }
  796. }
  797. // 日期选择框样式
  798. .demo-date-picker {
  799. display: flex;
  800. width: 100%;
  801. padding: 0;
  802. flex-wrap: wrap;
  803. }
  804. .demo-date-picker .block {
  805. padding: 1.5rem 0;
  806. text-align: center;
  807. border-right: solid 1px var(--el-border-color);
  808. flex: 1;
  809. min-width: 400px;
  810. display: flex;
  811. flex-direction: column;
  812. align-items: center;
  813. }
  814. .demo-date-picker .block:last-child {
  815. border-right: none;
  816. }
  817. .demo-date-picker .demonstration {
  818. display: block;
  819. color: var(--el-text-color-secondary);
  820. font-size: 14px;
  821. margin-bottom: 1rem;
  822. }
  823. @media screen and (max-width: 1200px) {
  824. .demo-date-picker .block {
  825. flex: 0 0 100%;
  826. padding: 1rem 0;
  827. min-width: auto;
  828. border-right: none;
  829. border-bottom: solid 1px var(--el-border-color);
  830. }
  831. .demo-date-picker .block:last-child {
  832. border-bottom: none;
  833. }
  834. }
  835. </style>