Index.vue 23 KB

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