Index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. <template>
  2. <el-affix :offset="0">
  3. <div style="height: 44px; width: 100vw; background: #00002a"></div>
  4. </el-affix>
  5. <el-affix :offset="44">
  6. <div class="blue-background">
  7. <div style="padding: 0px 20px;margin: 0px 15px;">
  8. <div class="left-row">
  9. <div>
  10. <span>状态:</span>
  11. <el-tag
  12. size="large"
  13. :effect="focusTaskStatus.includes('all') ? 'dark' : ''"
  14. type="primary"
  15. @click="changeTaskStatus()"
  16. style="cursor: pointer; margin: 10px 5px"
  17. >
  18. 全部
  19. </el-tag>
  20. <template v-for="status in taskStatus" :key="status.index">
  21. <el-tag
  22. size="large"
  23. :effect="focusTaskStatus.includes(status.index) ? 'dark' : ''"
  24. type="primary"
  25. @click="changeTaskStatus(status)"
  26. style="cursor: pointer; margin: 10px 5px"
  27. >
  28. {{ status.name }}
  29. </el-tag>
  30. </template>
  31. </div>
  32. <div>
  33. <span>类别:</span>
  34. <el-tag
  35. size="large"
  36. :effect="focusTaskType.includes('all') ? 'dark' : ''"
  37. type="primary"
  38. @click="changeTaskType()"
  39. style="cursor: pointer; margin: 10px 5px"
  40. >
  41. 全部
  42. </el-tag>
  43. <template v-for="type in taskType" :key="type.index">
  44. <el-tag
  45. size="large"
  46. :effect="focusTaskType.includes(type.index) ? 'dark' : ''"
  47. type="primary"
  48. @click="changeTaskType(type)"
  49. style="cursor: pointer; margin: 10px 5px"
  50. >
  51. {{ type.name }}
  52. </el-tag>
  53. </template>
  54. </div>
  55. <div class="row-search">
  56. <el-input
  57. size="mini"
  58. class="searcher"
  59. v-model="searcher"
  60. placeholder="请输入任务名称相关关键字"
  61. />
  62. <el-button type="primary" @click="pullTaskData(1)">搜索</el-button>
  63. <el-button class="reset-btn" @click="reset(), pullTaskData(1)">重置</el-button>
  64. </div>
  65. </div>
  66. <!-- <div class="row">
  67. <el-input
  68. class="searcher"
  69. v-model="searcher"
  70. placeholder="请输入任务名称相关关键字"
  71. />
  72. <el-button type="primary" @click="pullTaskData(1)">搜索</el-button>
  73. <el-button type="primary" @click="reset(), pullTaskData(1)">重置</el-button>
  74. </div> -->
  75. </div>
  76. <div class="lighter-container">
  77. <!-- <div style="padding-bottom: 10px">检索出{{ taskNum }}条任务</div> -->
  78. <el-table table-layout="fixed" row-key="main_id" :data="taskData" class="table"
  79. :header-cell-style="headerCellStyle"
  80. :row-style="rowStyle"
  81. :cell-style="cellStyle"
  82. stripe
  83. border>
  84. <el-table-column prop="main_c_name" label="名称" />
  85. <el-table-column prop="main_c_user_name" label="用户" />
  86. <el-table-column prop="main_c_state" label="类型">
  87. <template #default="scope">
  88. <el-tag
  89. effect="dark"
  90. v-show="getType(scope.row.main_c_type) != null"
  91. disable-transitions
  92. >{{ getType(scope.row.main_c_type)?.name ?? "" }}
  93. </el-tag>
  94. </template>
  95. </el-table-column>
  96. <el-table-column prop="main_c_state" label="状态">
  97. <template #default="scope">
  98. <el-tag
  99. effect="dark"
  100. v-show="getStatus(scope.row.main_c_state) != null"
  101. :type="statusStaticInfo[scope.row.main_c_state]?.tagType ?? ''"
  102. disable-transitions
  103. >{{ getStatus(scope.row.main_c_state)?.name ?? "" }}</el-tag
  104. >
  105. </template>
  106. </el-table-column>
  107. <el-table-column prop="main_c_start_time" label="任务开始时间">
  108. <template #default="scope">
  109. {{ timeFormatter(scope.row.main_c_start_time) }}
  110. </template>
  111. </el-table-column>
  112. <el-table-column prop="main_c_end_time" label="任务结束时间">
  113. <template #default="scope">
  114. {{ timeFormatter(scope.row.main_c_end_time) }}
  115. </template>
  116. </el-table-column>
  117. <el-table-column prop="main_c_file_name" label="结果">
  118. <template #default="scope">
  119. <span
  120. class="link"
  121. v-if="scope.row.main_c_file != null && scope.row.main_c_file_name != null"
  122. @click="
  123. downloadWithBlob(scope.row.main_c_file, scope.row.main_c_file_name)
  124. "
  125. >
  126. {{ scope.row.main_c_file_name }}
  127. </span>
  128. </template>
  129. </el-table-column>
  130. <el-table-column label="操作" width="420">
  131. <template #default="scope">
  132. <el-button
  133. type="primary"
  134. @click="
  135. () => {
  136. dialog = true;
  137. focusTask = scope.row;
  138. }
  139. "
  140. >
  141. 查看详情
  142. </el-button>
  143. <el-button
  144. v-if="scope.row.main_c_state == 0"
  145. type="success"
  146. @click="runTask(scope.row.main_id)"
  147. >
  148. 运行
  149. </el-button>
  150. <template
  151. v-if="scope.row.main_c_file != null && scope.row.main_c_file_name != null"
  152. >
  153. <el-button
  154. type="primary"
  155. @click="
  156. downloadWithBlob(scope.row.main_c_file, scope.row.main_c_file_name)
  157. "
  158. >
  159. 下载结果
  160. </el-button>
  161. <el-button type="primary" v-if="scope.row.main_c_file.includes('.json') || scope.row.main_c_file.includes('.geojson') || scope.row.main_c_file.includes('.xlsx') || scope.row.main_c_file.includes('.xls')" @click="preView(scope.row.main_c_file)">
  162. 预览结果
  163. </el-button>
  164. </template>
  165. </template>
  166. </el-table-column>
  167. </el-table>
  168. <!-- <div class="between-row pagination-container">
  169. <div></div>
  170. <el-pagination
  171. layout="prev, pager, next"
  172. :total="taskNum"
  173. @change="(page) => pullTaskData(page)"
  174. />
  175. </div> -->
  176. <div class="between-row pagination-container">
  177. <span class="total-text">检索出{{ taskNum }}条任务</span>
  178. <el-pagination
  179. layout="prev, pager, next, jumper, total"
  180. :total="taskNum"
  181. :current-page="page"
  182. :page-size="pageSize"
  183. @current-change="pullTaskData(page)"
  184. >
  185. </el-pagination>
  186. </div>
  187. </div>
  188. <el-dialog v-model="dialog" :show-close="true" width="750">
  189. <template #header>
  190. <div class="my-header">
  191. <span class="second-title">{{ focusTask.main_c_name }}</span>
  192. </div>
  193. </template>
  194. <el-descriptions class="margin-top" label-width="128" :column="1" border>
  195. <el-descriptions-item label="任务名称">
  196. {{ focusTask.main_c_name }}
  197. </el-descriptions-item>
  198. <el-descriptions-item label="任务描述">
  199. {{ focusTask.main_c_comment }}
  200. </el-descriptions-item>
  201. <el-descriptions-item label="任务类型">
  202. <el-tag
  203. effect="dark"
  204. v-show="getType(focusTask.main_c_type) != null"
  205. disable-transitions
  206. >{{ getType(focusTask.main_c_type)?.name ?? "" }}
  207. </el-tag>
  208. </el-descriptions-item>
  209. <el-descriptions-item label="用户名">
  210. {{ focusTask.main_c_user_name }}
  211. </el-descriptions-item>
  212. <el-descriptions-item label="用户id">
  213. {{ focusTask.main_c_user_id }}
  214. </el-descriptions-item>
  215. <el-descriptions-item label="状态">
  216. <el-tag
  217. effect="dark"
  218. :type="statusStaticInfo[focusTask.main_c_state]?.tagType ?? ''"
  219. disable-transitions
  220. >{{ getStatus(focusTask.main_c_state)?.name ?? "" }}
  221. </el-tag>
  222. </el-descriptions-item>
  223. <el-descriptions-item label="任务开始时间">
  224. {{ timeFormatter(focusTask.main_c_start_time) }}
  225. </el-descriptions-item>
  226. <el-descriptions-item label="任务结束时间">
  227. {{ timeFormatter(focusTask.main_c_end_time) }}
  228. </el-descriptions-item>
  229. <el-descriptions-item label="结果文件">
  230. {{ focusTask.main_c_file_name }}
  231. <template
  232. v-if="focusTask.main_c_file != null && focusTask.main_c_file_name != null"
  233. >
  234. <el-button
  235. type="primary"
  236. size="small"
  237. @click="
  238. downloadWithBlob(focusTask.main_c_file, focusTask.main_c_file_name)
  239. "
  240. >
  241. 下载结果
  242. </el-button>
  243. <el-button
  244. type="primary"
  245. size="small"
  246. @click="preView(focusTask.main_c_file)"
  247. >
  248. 预览结果
  249. </el-button>
  250. </template>
  251. </el-descriptions-item>
  252. <el-descriptions-item label="原始数据">
  253. <template
  254. v-if="
  255. focusTask.main_c_source_file_name != null &&
  256. focusTask.main_c_source_file != null
  257. "
  258. >
  259. {{ focusTask.main_c_source_file_name }}
  260. <br />
  261. </template>
  262. <template v-if="focusTask.main_c_source_data != null">
  263. <div class="hide-scrollbar long-text">
  264. {{ truncateText(focusTask.main_c_source_data, 10000) }}
  265. </div>
  266. </template>
  267. </el-descriptions-item>
  268. </el-descriptions>
  269. </el-dialog>
  270. </div>
  271. </el-affix>
  272. </template>
  273. <script>
  274. import { getTasks, getCName, executeTask } from "@/api/rwgl";
  275. export default {
  276. data() {
  277. return {
  278. searcher: "",
  279. taskStatus: [],
  280. focusTaskStatus: ["all"],
  281. statusStaticInfo: {
  282. 0: {
  283. tagType: "primary",
  284. },
  285. 1: {
  286. tagType: "primary",
  287. },
  288. 2: {
  289. tagType: "success",
  290. },
  291. 3: {
  292. tagType: "danger",
  293. },
  294. },
  295. taskType: [],
  296. focusTaskType: ["all"],
  297. taskData: [],
  298. taskNum: 0,
  299. focusTask: {},
  300. dialog: false,
  301. page: 1,
  302. pageSize: 10,
  303. tableHeight: 0,
  304. };
  305. },
  306. computed: {
  307. headerCellStyle() {
  308. return {
  309. // backgroundColor: "rgba(24, 144, 255, 0.25)",
  310. color: "#fff",
  311. fontWeight: "bold",
  312. // borderBottom: "2px solid rgba(24, 144, 255, 0.3)",
  313. padding: "12px 8px",
  314. };
  315. },
  316. rowStyle() {
  317. return {
  318. // 调整行背景色为更浅的黑色,增加透明度
  319. backgroundColor: "rgba(0, 0, 0, 0.05)",
  320. borderBottom: "1px solid rgba(255, 255, 255, 0.05)",
  321. transition: "all 0.3s ease",
  322. };
  323. },
  324. cellStyle() {
  325. return {
  326. color: "#e0e0e0",
  327. padding: "12px 8px",
  328. borderRight: "1px solid rgba(255, 255, 255, 0.05)",
  329. };
  330. },
  331. },
  332. mounted() {
  333. this.pullTaskStatus();
  334. this.pullTaskType();
  335. this.pullTaskData(1);
  336. this.calculateTableHeight();
  337. window.addEventListener("resize", this.calculateTableHeight);
  338. },
  339. beforeUnmount() {
  340. window.removeEventListener("resize", this.calculateTableHeight);
  341. },
  342. methods: {
  343. async pullTaskStatus() {
  344. let oData = this.$getDmsTypes("task_status");
  345. let newData = [];
  346. for (const key of Object.keys(oData)) {
  347. newData.push({
  348. index: Number(key),
  349. name: oData[key],
  350. });
  351. }
  352. this.taskStatus = newData.sort((a, b) => a.index - b.index);
  353. },
  354. changeTaskStatus(status) {
  355. if (status == null) {
  356. this.focusTaskStatus = ["all"];
  357. } else {
  358. let set = new Set(this.focusTaskStatus);
  359. set.delete("all");
  360. let index = status.index;
  361. if (this.focusTaskStatus.includes(index)) {
  362. set.delete(index);
  363. } else {
  364. set.add(index);
  365. }
  366. this.focusTaskStatus = Array.from(set);
  367. }
  368. // if(this.taskStatus.length==this.focusTaskStatus.length){
  369. // this.focusTaskStatus = ["all"]
  370. // }
  371. },
  372. getCheckedStatus() {
  373. if (this.focusTaskStatus.includes("all")) {
  374. return null;
  375. } else {
  376. return this.focusTaskStatus;
  377. }
  378. },
  379. getStatus(index) {
  380. for (let i = 0; i < this.taskStatus.length; i++) {
  381. const e = this.taskStatus[i];
  382. if (e.index == index) {
  383. return e;
  384. }
  385. }
  386. },
  387. async pullTaskType() {
  388. let oData = this.$getDmsTypes("yzt_task_type");
  389. let newData = [];
  390. for (const key of Object.keys(oData)) {
  391. newData.push({
  392. index: Number(key),
  393. name: oData[key],
  394. });
  395. }
  396. let taskType = newData.sort((a, b) => a.index - b.index);
  397. for (let i = 0; i < taskType.length; i++) {
  398. const e = taskType[i];
  399. if (e.index === 100) {
  400. const otherItem = taskType.splice(i, 1)[0];
  401. taskType.push(otherItem);
  402. break;
  403. }
  404. }
  405. this.taskType = taskType;
  406. },
  407. changeTaskType(types) {
  408. if (types == null) {
  409. this.focusTaskType = ["all"];
  410. } else {
  411. let set = new Set(this.focusTaskType);
  412. set.delete("all");
  413. let index = types.index;
  414. if (this.focusTaskType.includes(index)) {
  415. set.delete(index);
  416. } else {
  417. set.add(index);
  418. }
  419. this.focusTaskType = Array.from(set);
  420. }
  421. },
  422. getCheckedType() {
  423. if (this.focusTaskType.includes("all")) {
  424. return null;
  425. } else {
  426. return this.focusTaskType;
  427. }
  428. },
  429. getType(index) {
  430. for (let i = 0; i < this.taskType.length; i++) {
  431. const e = this.taskType[i];
  432. if (e.index == index) {
  433. return e;
  434. }
  435. }
  436. },
  437. async pullTaskData(page) {
  438. if (page != null) this.page = page;
  439. let res = await getTasks(
  440. this.page,
  441. this.pageSize,
  442. this.searcher,
  443. this.getCheckedStatus(),
  444. this.getCheckedType()
  445. );
  446. this.taskNum = res.count;
  447. this.taskData = res.data;
  448. },
  449. timeFormatter(time) {
  450. if (time == null) return "";
  451. let date = new Date(time);
  452. return date.toLocaleString();
  453. },
  454. async downloadWithBlob(url, filename) {
  455. try {
  456. const response = await fetch(systemConfig.dmsDataProxy + url);
  457. const blob = await response.blob();
  458. const blobUrl = window.URL.createObjectURL(blob);
  459. const link = document.createElement("a");
  460. link.href = blobUrl;
  461. link.download = filename || "file";
  462. link.click();
  463. // 清理URL对象
  464. window.URL.revokeObjectURL(blobUrl);
  465. } catch (error) {
  466. console.error("下载失败:", error);
  467. }
  468. },
  469. reset() {
  470. this.focusTaskStatus = ["all"];
  471. this.searcher = "";
  472. },
  473. preView(url) {
  474. window.open("fileView?url=" + systemConfig.dmsDataProxy + url, "_blank");
  475. },
  476. async runTask(taskId) {
  477. try {
  478. const res = await executeTask(taskId);
  479. if (res.code === 200) {
  480. this.$message({
  481. type: "success",
  482. message: res.content || "任务已提交,正在后台执行",
  483. });
  484. // 先禁用按钮,防止重复点击
  485. this.$refs.runTaskBtn.disabled = true;
  486. // 刷新任务列表
  487. setTimeout(() => {
  488. // 执行成功后,刷新任务列表
  489. this.pullTaskData(this.page);
  490. }, 300);
  491. } else {
  492. this.$message({
  493. type: "error",
  494. message: res.message || "执行任务失败",
  495. });
  496. }
  497. } catch (error) {
  498. console.error("执行任务失败:", error);
  499. this.$message({
  500. type: "error",
  501. message: "执行任务失败,请稍后重试",
  502. });
  503. }
  504. },
  505. truncateText(text, maxLength = 40) {
  506. if (typeof text !== "string" || text.length <= maxLength) {
  507. return text;
  508. }
  509. return text.substring(0, maxLength) + "…";
  510. },
  511. calculateTableHeight() {
  512. // 计算表格高度:窗口高度 - header高度 - footer高度 - 页面padding - 其他元素高度
  513. const windowHeight = window.innerHeight;
  514. const headerHeight = 70; // Header组件高度
  515. const footerHeight = 50; // Footer组件高度
  516. const pagePadding = 40 * 2; // 页面上下padding
  517. const filterAreaHeight = 120; // 筛选条件区域高度
  518. const taskCountHeight = 30; // 任务数量文字高度
  519. const paginationHeight = 50; // 分页区域高度
  520. const containerMargin = 15 * 2; // 容器上下margin
  521. this.tableHeight =
  522. windowHeight -
  523. headerHeight -
  524. footerHeight -
  525. pagePadding -
  526. filterAreaHeight -
  527. taskCountHeight -
  528. paginationHeight -
  529. containerMargin;
  530. },
  531. },
  532. };
  533. </script>
  534. <style lang="less" scoped>
  535. // * {
  536. // --el-table-bg-color: #eeeeee0b;
  537. // /* 表格背景 */
  538. // --el-table-header-bg-color: #eeeeee0b;
  539. // /* 表头背景 */
  540. // --el-table-tr-bg-color: #eeeeee0b;
  541. // /* 行背景 */
  542. // --el-table-row-hover-bg-color: #eeeeee0b;
  543. // /* 行悬浮背景 */
  544. // --el-table-header-text-color: #ededed;
  545. // /* 表头文字颜色 */
  546. // }
  547. // 美化表格行悬停效果
  548. :deep(.el-table__body tr:hover > td) {
  549. background-color: rgba(24, 144, 255, 0.1) !important;
  550. }
  551. // 美化表格边框
  552. :deep(.el-table__inner-wrapper) {
  553. border-radius: 6px;
  554. overflow: hidden;
  555. }
  556. :deep(.el-table__cell) {
  557. border-right: 1px solid rgba(255, 255, 255, 0.05);
  558. }
  559. :deep(.el-table__row) {
  560. border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  561. }
  562. // 调整奇偶行背景色,使其更明亮
  563. :deep(.el-table--striped .el-table__body tr.el-table__row--striped) {
  564. background-color: rgba(255, 255, 255, 0.02) !important;
  565. }
  566. // 调整表格主体背景色
  567. :deep(.el-table__body) {
  568. background-color: rgba(0, 0, 0, 0.05);
  569. }
  570. :deep(.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell) {
  571. background-color: rgba(255, 255, 255, 0.02);
  572. }
  573. :deep(.el-tag--primary){
  574. background-color: rgba(0, 0, 0, 0);
  575. color: #fff;
  576. }
  577. :deep(.el-tag--dark){
  578. background-color: var(--el-color-primary);
  579. }
  580. .font,
  581. .title,
  582. .super-title,
  583. .title-sub,
  584. .second-title,
  585. .third-title,
  586. .strong-data,
  587. link {
  588. color: #fff;
  589. }
  590. .hide-scrollbar {
  591. -ms-overflow-style: none;
  592. /* IE和Edge */
  593. scrollbar-width: none;
  594. /* Firefox */
  595. }
  596. .hide-scrollbar::-webkit-scrollbar {
  597. display: none;
  598. /* Chrome, Safari和Opera */
  599. }
  600. .long-text {
  601. width: 100%;
  602. height: 200px;
  603. overflow: scroll;
  604. }
  605. .icon {
  606. color: #fff;
  607. fill: currentColor;
  608. }
  609. .middle {
  610. text-align: center;
  611. }
  612. .darkblue-background,
  613. .dark-background,
  614. .bluedark-background,
  615. .blue-background,
  616. .image-background {
  617. padding-top: 40px;
  618. padding-bottom: 40px;
  619. margin-left: 0;
  620. padding-left: 90px;
  621. padding-right: 90px;
  622. // min-height: 80vh
  623. height: 100vh;
  624. }
  625. .darkblue-background {
  626. background: linear-gradient(to bottom, #02060c 0%, #0f3460 40%, #0f3460 100%);
  627. }
  628. .dark-background {
  629. background: #0a0a08;
  630. }
  631. .blue-background,
  632. body {
  633. background: #00002a;
  634. }
  635. .bluedark-background {
  636. background: linear-gradient(to bottom, #0f3460 0%, #0f3460 60%, #02060c 100%);
  637. }
  638. .image-background {
  639. background-repeat: no-repeat;
  640. background-position: center;
  641. background-size: 100% auto;
  642. }
  643. .lighter-container {
  644. background-color: #eeeeee0b;
  645. padding: 20px;
  646. margin: 15px;
  647. vertical-align: middle;
  648. border-radius: 10px;
  649. }
  650. .task-count {
  651. margin-bottom: 10px;
  652. color: #fff;
  653. }
  654. .pagination-container {
  655. margin-top: 15px;
  656. }
  657. .lightblue-container {
  658. border-radius: 3%;
  659. padding: 20px;
  660. margin: 15px;
  661. background: linear-gradient(to bottom, #215476 0%, #28638b 66%, #337aac 100%);
  662. font-size: 20px;
  663. .third-title {
  664. font-size: 28px;
  665. padding: 0;
  666. }
  667. }
  668. .middle-container {
  669. display: flex !important;
  670. justify-content: center;
  671. flex-direction: column;
  672. padding: 0;
  673. align-items: stretch;
  674. }
  675. .row,
  676. .warp-row,
  677. .between-row,
  678. .left-row {
  679. display: flex !important;
  680. justify-content: space-between;
  681. padding: 0;
  682. align-items: stretch;
  683. }
  684. .row-search{
  685. display: flex !important;
  686. justify-content: space-between;
  687. align-items: center;
  688. }
  689. .warp-row {
  690. flex-wrap: wrap;
  691. }
  692. .between-row {
  693. justify-content: space-between;
  694. }
  695. .left-row {
  696. justify-content: space-between;
  697. }
  698. .left-row > * {
  699. // margin-right: 15px;
  700. }
  701. .col {
  702. display: flex !important;
  703. justify-content: space-around;
  704. flex-direction: column;
  705. }
  706. .dense-col {
  707. display: flex !important;
  708. justify-content: center;
  709. flex-direction: column;
  710. }
  711. .start-reverse-col {
  712. display: flex !important;
  713. justify-content: start;
  714. flex-direction: column-reverse;
  715. }
  716. .dense-col > *,
  717. .start-reverse-col > * {
  718. margin: 10px;
  719. }
  720. .grid-2x2 {
  721. display: grid !important;
  722. grid-template-columns: 1fr 1fr;
  723. gap: 12px;
  724. width: 100%;
  725. height: 80%;
  726. }
  727. .strong-data {
  728. font-size: 32px;
  729. font-weight: bold;
  730. text-align: center;
  731. }
  732. .title {
  733. font-size: 36px;
  734. margin-top: 10px;
  735. text-align: center;
  736. font-weight: bold;
  737. }
  738. .super-title {
  739. font-size: 44px;
  740. margin-top: 10px;
  741. text-align: center;
  742. font-weight: bold;
  743. }
  744. .title-sub {
  745. font-size: 16px;
  746. margin-top: 10px;
  747. color: rgb(192, 192, 192);
  748. text-align: center;
  749. }
  750. .second-title {
  751. font-size: 20px;
  752. margin-top: 10px;
  753. padding-left: 10px;
  754. border-left: 2px solid #3498db;
  755. font-weight: bold;
  756. }
  757. .third-title {
  758. font-size: 18px;
  759. margin-top: 10px;
  760. padding-left: 10px;
  761. display: flex;
  762. font-weight: bold;
  763. }
  764. .link {
  765. font-weight: bold;
  766. /* 字体加粗 */
  767. text-decoration: underline;
  768. /* 下划线 */
  769. cursor: pointer;
  770. /* 鼠标悬浮时变为手型(可点击形式) */
  771. }
  772. .searcher {
  773. background-color: #00002a;
  774. margin-right: 15px;
  775. width: 500px;
  776. height: 34px;
  777. }
  778. .blue {
  779. color: #3498db;
  780. }
  781. .grey {
  782. color: rgb(192, 192, 192);
  783. }
  784. .lightgrey {
  785. color: rgb(229, 229, 229);
  786. }
  787. #echart1 {
  788. width: 100%;
  789. height: 450px;
  790. }
  791. .container {
  792. width: 1920px;
  793. margin: 0 auto;
  794. }
  795. </style>