index.vue 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  1. <template>
  2. <vue-fullscreen
  3. class="box-container"
  4. v-cloak
  5. v-model="isFullscreen"
  6. fullscreenClass="box-container"
  7. :exit-on-click-wrapper="false"
  8. >
  9. <div class="box-container" v-cloak>
  10. <!-- 中间内容区域 - 可左右滚动,头部跟随 -->
  11. <div class="box-content">
  12. <div class="scroll-wrapper">
  13. <!-- 头部区域 - 跟随滚动 -->
  14. <div class="header-section">
  15. <div class="box-header-scroll">
  16. <div class="logo">
  17. <el-select
  18. v-model="stationId"
  19. placeholder="请选择"
  20. class="custom-select"
  21. popper-class="custom-select-dropdown"
  22. :popper-append-to-body="false"
  23. @change="init"
  24. >
  25. <el-option
  26. v-for="item in selectOptions"
  27. :key="item.value"
  28. :label="item.label"
  29. :value="item.value"
  30. />
  31. </el-select>
  32. </div>
  33. <div class="header-center">
  34. <div class="title">克拉玛依宇信工业科技股份有限公司</div>
  35. </div>
  36. <div class="time">
  37. <div class="time-display">
  38. <span class="date-text">{{ date }}</span>
  39. <span class="time-text">{{ time }}</span>
  40. </div>
  41. <span class="fullscreen-toggle" @click.passive="onFullscreen">
  42. <i
  43. v-if="isFullscreen"
  44. title="取消全屏"
  45. class="el-icon-_screen-restore"
  46. />
  47. <i v-else title="全屏" class="el-icon-_screen-full" />
  48. </span>
  49. </div>
  50. </div>
  51. </div>
  52. <!-- 三栏布局区域 -->
  53. <div class="three-column-layout">
  54. <!-- 左侧区域 -->
  55. <div class="left-section">
  56. <!-- 综合数据 -->
  57. <div class="panel data-panel">
  58. <div class="panel-title" style="cursor: pointer" @click="handelRouterTo('/page-pcs/productionRecords')">
  59. <div class="panel-icon"></div>
  60. 综合数据
  61. </div>
  62. <div
  63. style="
  64. display: flex;
  65. flex: 1;
  66. align-items: center;
  67. justify-content: center;
  68. "
  69. >
  70. <div class="data-grid">
  71. <div
  72. class="data-item"
  73. v-for="(item, index) in comprehensiveList"
  74. :key="index"
  75. >
  76. <div class="img"></div>
  77. <div class="data-item_value">
  78. <span class="data-label">{{ item.label }}</span>
  79. <span class="data-value">{{ item.value }}</span></div
  80. >
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <!-- 区域用能对比 -->
  86. <div class="panel chart-panel" style="position: relative">
  87. <div class="panel-title energy-title">
  88. <div class="title-left">
  89. <div class="panel-icon"></div>
  90. 用水用煤趋势图
  91. </div>
  92. </div>
  93. <div class="energy-tabs">
  94. <span
  95. v-for="tab in energyTabs"
  96. :key="tab.value"
  97. :class="[
  98. 'tab-item',
  99. { active: activeEnergyTab === tab.value }
  100. ]"
  101. @click="energyTabsCahnge(tab.value)"
  102. >
  103. {{ tab.label }}
  104. </span>
  105. </div>
  106. <div class="chart-container" ref="waterChart"></div>
  107. </div>
  108. <!-- 区域能耗对比 -->
  109. <div class="panel chart-panel">
  110. <div class="panel-title energy-title">
  111. <div class="title-left">
  112. <div class="panel-icon"></div>
  113. 注汽量趋势图
  114. </div>
  115. </div>
  116. <div class="chart-container" ref="returnChart"></div>
  117. </div>
  118. </div>
  119. <!-- 中间区域 -->
  120. <div class="center-section">
  121. <!-- 锅炉运行参数 -->
  122. <div
  123. :class="'param-card param-card' + (index + 1)"
  124. v-for="(boiler, index) in boilerData"
  125. :key="index"
  126. >
  127. <div class="param-title" style="cursor: pointer" @click="handelRouterTo('', boiler.title)">{{ boiler.title }}</div>
  128. <div class="param-list">
  129. <div
  130. class="param-item"
  131. v-for="(param, pIndex) in boiler.params"
  132. :key="pIndex"
  133. >
  134. <span class="param-name">{{ param.name }}</span>
  135. <span class="param-value">{{ param.value }}</span>
  136. </div>
  137. </div>
  138. </div>
  139. <!-- 管道流程图 -->
  140. <div class="pipeline-container">
  141. <!-- 管道流程图内容 -->
  142. </div>
  143. </div>
  144. <!-- 右侧区域 -->
  145. <div class="right-section">
  146. <!-- 告警数据统计 -->
  147. <div class="panel alert-panel">
  148. <div class="panel-title">
  149. <div class="panel-icon"></div>
  150. 告警数据概览
  151. </div>
  152. <div class="alert-stats">
  153. <!-- 左侧数据卡片 -->
  154. <div class="alert-cards">
  155. <div
  156. class="alert-card-item"
  157. v-for="(item, index) in alertStatsData"
  158. :key="index"
  159. >
  160. <div class="img"></div>
  161. <div class="data-item_value">
  162. <span class="data-label">{{ item.label }}</span>
  163. <span class="data-value">{{ item.value }}</span></div
  164. >
  165. </div>
  166. </div>
  167. <!-- 右侧环形图 -->
  168. <div class="alert-pie-chart">
  169. <div class="alert-pie" ref="alertPieChart"></div>
  170. </div>
  171. </div>
  172. </div>
  173. <!-- 告警列表 -->
  174. <!-- <div class="panel alert-list-panel">
  175. <div class="panel-title">
  176. <div class="panel-icon"></div>
  177. 告警列表
  178. </div>
  179. <div class="alert-table">
  180. <dv-scroll-board
  181. :config="alertConfig"
  182. style="width: 100%; height: calc(100% - 2.5rem)"
  183. />
  184. </div>
  185. </div> -->
  186. <!-- 设备告警趋势图 -->
  187. <div class="panel chart-panel">
  188. <div class="panel-title">
  189. <div class="panel-icon"></div>
  190. 设备告警趋势图
  191. </div>
  192. <div class="chart-container" ref="alertTrendChart"></div>
  193. </div>
  194. <div class="panel chart-panel">
  195. <div class="panel-title">
  196. <div class="panel-icon"></div>
  197. 用电趋势图
  198. </div>
  199. <div class="chart-container" ref="electricityTrendChart"></div>
  200. </div>
  201. </div>
  202. </div>
  203. </div>
  204. </div>
  205. </div>
  206. </vue-fullscreen>
  207. </template>
  208. <script>
  209. import { component } from 'vue-fullscreen';
  210. import * as echarts from 'echarts';
  211. import {
  212. alarmOverview,
  213. queryAlarmList,
  214. deviceAlarmTrend,
  215. comprehensiveData,
  216. waterCoalTrend,
  217. wasteTrend,
  218. listFactoryLine,
  219. electricityTrend
  220. } from '@/api/pcsData/index.js';
  221. export default {
  222. name: 'PcsDataDashboard',
  223. components: {
  224. VueFullscreen: component
  225. },
  226. data() {
  227. return {
  228. isFullscreen: false,
  229. isFlag: false,
  230. date: '',
  231. time: '',
  232. week: '',
  233. selectedValue: '',
  234. selectOptions: [],
  235. comprehensiveList: [],
  236. boilerData: [
  237. {
  238. title: '锅炉运行参数',
  239. params: []
  240. },
  241. {
  242. title: '生产记录',
  243. params: []
  244. },
  245. {
  246. title: '蒸汽质量检查记录',
  247. params: []
  248. }
  249. ],
  250. alertStatsData: [],
  251. alertLegend: [
  252. { name: '一般告警', percent: 45.2, color: '#3b82f6' },
  253. { name: '警告告警', percent: 35.3, color: '#f59e0b' },
  254. { name: '严重告警', percent: 4.7, color: '#ef4444', value: 58 },
  255. { name: '紧急告警', percent: 15.2, color: '#ef4444' }
  256. ],
  257. alertConfig: {},
  258. unitValue: '',
  259. unitOptions: [
  260. { label: '1#机组', value: '1' },
  261. { label: '2#机组', value: '2' },
  262. { label: '3#机组', value: '3' },
  263. { label: '4#机组', value: '4' }
  264. ],
  265. energyTabs: [
  266. { label: '水', value: '1' },
  267. { label: '煤', value: '2' }
  268. ],
  269. activeEnergyTab: '1',
  270. charts: {},
  271. stationId: ''
  272. };
  273. },
  274. watch: {
  275. isFullscreen: {
  276. handler() {
  277. this.handleResize();
  278. },
  279. immediate: true
  280. }
  281. },
  282. created() {
  283. this.init();
  284. listFactoryLine({
  285. pageNum: 1,
  286. size: 999,
  287. type: 4
  288. }).then((res) => {
  289. this.selectOptions = res.list.map((item) => {
  290. return {
  291. label: item.name,
  292. value: item.id
  293. };
  294. });
  295. console.log(res);
  296. });
  297. },
  298. mounted() {
  299. this.updateTimer = setInterval(this.updateTime, 1000);
  300. window.addEventListener('resize', this.handleResize);
  301. // 初始化时同步头部宽度
  302. this.$nextTick(() => {
  303. this.syncHeaderWidth();
  304. });
  305. },
  306. beforeDestroy() {
  307. clearInterval(this.updateTimer);
  308. window.removeEventListener('resize', this.handleResize);
  309. Object.values(this.charts).forEach((chart) => chart && chart.dispose());
  310. },
  311. methods: {
  312. handelRouterTo(path, item) {
  313. let url = path;
  314. if(!url) {
  315. if(item == '锅炉运行参数') {
  316. url = '/page-pcs/boilerOperationRecord'
  317. } else if(item == '生产记录') {
  318. url = '/page-pcs/productionRecords'
  319. } else if(item == '蒸汽质量检查记录') {
  320. url = '/page-pcs/qualityTestRecords'
  321. }
  322. }
  323. window.history.pushState(null, '', url);
  324. },
  325. energyTabsCahnge(val) {
  326. this.activeEnergyTab = val;
  327. this.waterCoalTrend();
  328. },
  329. init() {
  330. this.alarmOverview();
  331. // this.queryAlarmList();
  332. this.deviceAlarmTrend();
  333. this.waterCoalTrend();
  334. this.wasteTrend();
  335. this.electricityTrend();
  336. this.comprehensiveData();
  337. },
  338. //告警数据概览
  339. alarmOverview() {
  340. alarmOverview({
  341. stationId: this.stationId
  342. }).then((res) => {
  343. this.$nextTick(() => {
  344. this.initAlertPieChart(res);
  345. });
  346. });
  347. },
  348. //设备告警趋势图
  349. deviceAlarmTrend() {
  350. deviceAlarmTrend({ stationId: this.stationId }).then((res) => {
  351. this.$nextTick(() => {
  352. this.initAlertTrendChart(res);
  353. });
  354. });
  355. },
  356. //综合数据
  357. comprehensiveData() {
  358. comprehensiveData({ stationId: this.stationId }).then((res) => {
  359. this.comprehensiveList = [
  360. { label: '年度总注气量(M³)', value: res.yearTotalGasInjection },
  361. { label: '年度总水量(T)', value: res.yearTotalWater },
  362. { label: '年度用煤总量(T)', value: res.yearTotalCoal },
  363. { label: '年度用电量(kWh)', value: res.yearTotalElectricity },
  364. { label: '本月注气量(M³)', value: res.monthTotalGasInjection },
  365. { label: '本月水量(T)', value: res.monthTotalWater },
  366. { label: '本月用煤量(T)', value: res.monthTotalCoal },
  367. { label: '本月用电量(kWh)', value: res.monthTotalElectricity }
  368. ];
  369. this.$set(
  370. this.boilerData[0],
  371. 'params',
  372. this.getParams(res['dailyReportOnBoilerOperation'] || {})
  373. );
  374. this.$set(
  375. this.boilerData[1],
  376. 'params',
  377. this.getParams(res['productionRecord'] || {})
  378. );
  379. this.$set(
  380. this.boilerData[2],
  381. 'params',
  382. this.getParams(res['steamQualityInspectionRecord'] || {})
  383. );
  384. });
  385. },
  386. getParams(data = {}) {
  387. let list = [
  388. {
  389. name: '报工人:',
  390. value: data?.executeUsers?.map((item) => item.userName).toString()
  391. },
  392. { name: '报工时间:', value: data.checkFinishTime }
  393. ];
  394. data.detailList?.forEach((item) => {
  395. list.push({
  396. name: item.paramValue,
  397. value: item.num,
  398. unit: item.unitName
  399. });
  400. });
  401. return list;
  402. },
  403. //用煤用水
  404. waterCoalTrend() {
  405. waterCoalTrend({
  406. trendType: this.activeEnergyTab,
  407. stationId: this.stationId
  408. }).then((res) => {
  409. this.$nextTick(() => {
  410. this.initWaterChart(res);
  411. });
  412. });
  413. },
  414. //固废趋势图
  415. wasteTrend() {
  416. wasteTrend({ stationId: this.stationId }).then((res) => {
  417. this.$nextTick(() => {
  418. this.initReturnChart(res);
  419. });
  420. });
  421. },
  422. //用电趋势图
  423. electricityTrend() {
  424. electricityTrend({ stationId: this.stationId }).then((res) => {
  425. this.$nextTick(() => {
  426. this.initElectricityTrend(res);
  427. });
  428. });
  429. },
  430. // //告警列表
  431. // queryAlarmList() {
  432. // let dataKey = [
  433. // 'name',
  434. // 'deviceLocation',
  435. // 'alertLevel',
  436. // 'ruleName',
  437. // 'alarmTime',
  438. // 'handleStatus'
  439. // ];
  440. // queryAlarmList({ stationId: this.stationId }).then((res) => {
  441. // let dataArr = [];
  442. // res.forEach((item, index) => {
  443. // let data = [index + 1];
  444. // dataKey.forEach((key, index) => {
  445. // if (key == 'alertLevel') {
  446. // item[key] =
  447. // item[key] == 1
  448. // ? '紧急'
  449. // : item[key] == 2
  450. // ? '严重'
  451. // : item[key] == 3
  452. // ? '一般'
  453. // : '告警';
  454. // }
  455. // if (key == 'handleStatus') {
  456. // item[key] =
  457. // item[key] == 1
  458. // ? '处理中'
  459. // : item[key] == 2
  460. // ? '已处理'
  461. // : '未处理';
  462. // }
  463. // data.push(item[key]);
  464. // });
  465. // dataArr.push(data);
  466. // });
  467. // this.alertConfig = {
  468. // header: [
  469. // '序号',
  470. // '设备名称',
  471. // '设备位置',
  472. // '告警级别',
  473. // '告警内容描述',
  474. // '告警时间',
  475. // '处理状态'
  476. // ].map(
  477. // (item) =>
  478. // `<div style="color: #38fdf8;font-size: 0.9rem;font-weight: bold">${item}</div>`
  479. // ),
  480. // data: dataArr.map((data) =>
  481. // data.map((item, index) => {
  482. // return `<div style="color: ${
  483. // index == 3 ? this.getClolr(item) : '#fff'
  484. // };font-size: 0.9rem;">${item}</div>`;
  485. // })
  486. // ),
  487. // rowNum: 4,
  488. // headerBGC: 'transparent',
  489. // oddRowBGC: 'rgba(13, 41, 96, 0.3)',
  490. // evenRowBGC: 'rgba(13, 41, 96, 0.1)',
  491. // headerHeight: 30,
  492. // waitTime: 3000,
  493. // align: [
  494. // 'center',
  495. // 'center',
  496. // 'center',
  497. // 'center',
  498. // 'center',
  499. // 'center',
  500. // 'center'
  501. // ],
  502. // columnWidth: []
  503. // };
  504. // });
  505. // },
  506. onFullscreen() {
  507. this.isFullscreen = !this.isFullscreen;
  508. },
  509. getClolr(item) {
  510. return item == '严重'
  511. ? '#FF0000'
  512. : item == '紧急'
  513. ? '#FF7070'
  514. : item == '警告'
  515. ? '#FFD337'
  516. : '#fff';
  517. },
  518. updateTime() {
  519. const now = new Date();
  520. const hours = now.getHours().toString().padStart(2, '0');
  521. const minutes = now.getMinutes().toString().padStart(2, '0');
  522. const seconds = now.getSeconds().toString().padStart(2, '0');
  523. this.time = `${hours}:${minutes}:${seconds}`;
  524. const year = now.getFullYear();
  525. const month = (now.getMonth() + 1).toString().padStart(2, '0');
  526. const day = now.getDate().toString().padStart(2, '0');
  527. this.date = `${year}-${month}-${day}`;
  528. },
  529. syncHeaderWidth() {
  530. this.$nextTick(() => {
  531. const threeColumnLayout = document.querySelector(
  532. '.three-column-layout'
  533. );
  534. const headerSection = document.querySelector('.header-section');
  535. if (threeColumnLayout && headerSection) {
  536. const layoutWidth = threeColumnLayout.scrollWidth;
  537. headerSection.style.width = layoutWidth + 'px';
  538. }
  539. });
  540. },
  541. handleResize() {
  542. this.$nextTick(() => {
  543. // 同步头部宽度
  544. this.syncHeaderWidth();
  545. const { clientWidth, clientHeight } = document.documentElement;
  546. const containers = document.getElementsByClassName('box-container');
  547. Array.from(containers).forEach((item) => {
  548. if (this.isFullscreen) {
  549. item.style.height = clientHeight + 'px';
  550. item.style.width = clientWidth + 'px';
  551. } else {
  552. item.style.height = clientHeight - 100 + 'px';
  553. item.style.width = clientWidth - 240 + 'px';
  554. }
  555. });
  556. Object.values(this.charts).forEach(
  557. (chart) => chart && chart.resize()
  558. );
  559. });
  560. },
  561. initWaterChart(res) {
  562. if (!this.$refs.waterChart) return;
  563. console.log(res);
  564. const chart = echarts.init(this.$refs.waterChart);
  565. const option = {
  566. tooltip: {
  567. trigger: 'axis',
  568. backgroundColor: '#fff',
  569. borderColor: '#e0e0e0',
  570. borderWidth: 1,
  571. textStyle: {
  572. color: '#333'
  573. },
  574. axisPointer: {
  575. type: 'line',
  576. lineStyle: {
  577. color: 'rgba(255, 255, 255, 0.5)'
  578. }
  579. }
  580. },
  581. grid: {
  582. top: '1.875rem',
  583. right: '1.25rem',
  584. bottom: '1.875rem',
  585. left: '3.125rem'
  586. },
  587. xAxis: {
  588. type: 'category',
  589. data: res.map((item) => item.time),
  590. axisLine: { lineStyle: { color: '#4a6fa5' } },
  591. axisLabel: { color: '#8ba3c7' }
  592. },
  593. yAxis: {
  594. type: 'value',
  595. axisLine: { lineStyle: { color: '#4a6fa5' } },
  596. axisLabel: { color: '#8ba3c7' },
  597. splitLine: { lineStyle: { color: 'rgba(74, 111, 165, 0.2)' } }
  598. },
  599. series: [
  600. {
  601. data: res.map((item) => item.value),
  602. type: 'line',
  603. smooth: true,
  604. areaStyle: {
  605. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  606. { offset: 0, color: 'rgba(59, 130, 246, 0.5)' },
  607. { offset: 1, color: 'rgba(59, 130, 246, 0.05)' }
  608. ])
  609. },
  610. lineStyle: { color: '#3b82f6', width: 2 },
  611. itemStyle: { color: '#3b82f6' }
  612. }
  613. ]
  614. };
  615. chart.setOption(option);
  616. this.charts.water = chart;
  617. },
  618. initReturnChart(res) {
  619. if (!this.$refs.returnChart) return;
  620. const chart = echarts.init(this.$refs.returnChart);
  621. const option = {
  622. tooltip: {
  623. trigger: 'axis',
  624. backgroundColor: '#fff',
  625. borderColor: '#e0e0e0',
  626. borderWidth: 1,
  627. textStyle: {
  628. color: '#333'
  629. },
  630. axisPointer: {
  631. type: 'line',
  632. lineStyle: {
  633. color: 'rgba(255, 255, 255, 0.5)'
  634. }
  635. }
  636. },
  637. grid: {
  638. top: '1.875rem',
  639. right: '1.25rem',
  640. bottom: '1.875rem',
  641. left: '3.125rem'
  642. },
  643. xAxis: {
  644. type: 'category',
  645. data: res.map((item) => item.time),
  646. axisLine: { lineStyle: { color: '#4a6fa5' } },
  647. axisLabel: { color: '#8ba3c7' }
  648. },
  649. yAxis: {
  650. type: 'value',
  651. axisLine: { lineStyle: { color: '#4a6fa5' } },
  652. axisLabel: { color: '#8ba3c7' },
  653. splitLine: { lineStyle: { color: 'rgba(74, 111, 165, 0.2)' } }
  654. },
  655. series: [
  656. {
  657. data: res.map((item) => item.value),
  658. type: 'line',
  659. smooth: true,
  660. areaStyle: {
  661. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  662. { offset: 0, color: 'rgba(59, 130, 246, 0.5)' },
  663. { offset: 1, color: 'rgba(59, 130, 246, 0.05)' }
  664. ])
  665. },
  666. lineStyle: { color: '#3b82f6', width: 2 },
  667. itemStyle: { color: '#3b82f6' }
  668. }
  669. ]
  670. };
  671. chart.setOption(option);
  672. this.charts.return = chart;
  673. },
  674. initAlertPieChart(res) {
  675. this.alertStatsData = [
  676. {
  677. label: '系统告警总数',
  678. value: res.yearTotalCount,
  679. icon: 'el-icon-_alert'
  680. },
  681. {
  682. label: '本月告警数',
  683. value: res.monthTotalCount,
  684. icon: 'el-icon-_month'
  685. },
  686. {
  687. label: '本年已处理数',
  688. value: res.yearHandledCount,
  689. icon: 'el-icon-_check'
  690. },
  691. {
  692. label: '本月已处理数',
  693. value: res.monthHandledCount,
  694. icon: 'el-icon-_check'
  695. },
  696. {
  697. label: '年度未处理数',
  698. value: res.yearUnhandledCount,
  699. icon: 'el-icon-_warning'
  700. },
  701. {
  702. label: '本月未处理数',
  703. value: res.monthUnhandledCount,
  704. icon: 'el-icon-_warning'
  705. }
  706. ];
  707. if (!this.$refs.alertPieChart) return;
  708. const chart = echarts.init(this.$refs.alertPieChart);
  709. // 计算总数
  710. const total =
  711. res?.levelStats?.reduce((sum, item) => sum + item.count, 0) || 1247;
  712. const option = {
  713. tooltip: {
  714. trigger: 'item',
  715. formatter: '{b}: {c} ({d}%)'
  716. },
  717. series: [
  718. {
  719. type: 'pie',
  720. radius: ['45%', '65%'],
  721. center: ['50%', '50%'],
  722. avoidLabelOverlap: true,
  723. itemStyle: {
  724. borderRadius: 4,
  725. borderColor: '#0d1f4a',
  726. borderWidth: 2
  727. },
  728. data: res?.levelStats?.map((item) => {
  729. return {
  730. value: item.count,
  731. name: item.levelName,
  732. itemStyle: {
  733. color:
  734. item.level == 1
  735. ? '#ef4444'
  736. : item.level == 2
  737. ? '#dc2626'
  738. : item.level == 3
  739. ? '#3b82f6'
  740. : '#f59e0b'
  741. }
  742. };
  743. }) || [
  744. {
  745. value: 564,
  746. name: '一般告警',
  747. itemStyle: { color: '#3b82f6' }
  748. },
  749. {
  750. value: 440,
  751. name: '警告告警',
  752. itemStyle: { color: '#f59e0b' }
  753. },
  754. {
  755. value: 58,
  756. name: '严重告警',
  757. itemStyle: { color: '#dc2626' }
  758. },
  759. {
  760. value: 185,
  761. name: '紧急告警',
  762. itemStyle: { color: '#ef4444' }
  763. }
  764. ],
  765. label: {
  766. show: true,
  767. position: 'outside',
  768. formatter: '{per|{d}%}\n{name|{b}}',
  769. rich: {
  770. per: {
  771. fontSize: 14,
  772. fontWeight: 'bold',
  773. color: '#fff',
  774. padding: [0, 0, 4, 0]
  775. },
  776. name: {
  777. fontSize: 12,
  778. color: '#8ba3c7'
  779. }
  780. }
  781. },
  782. labelLine: {
  783. show: true,
  784. length: 10,
  785. length2: 10,
  786. lineStyle: {
  787. color: 'rgba(138, 163, 199, 0.5)'
  788. }
  789. },
  790. emphasis: {
  791. scale: true,
  792. scaleSize: 5,
  793. label: {
  794. show: true,
  795. fontWeight: 'bold'
  796. }
  797. }
  798. }
  799. ],
  800. graphic: [
  801. {
  802. type: 'text',
  803. left: 'center',
  804. top: '45%',
  805. style: {
  806. text: String(total),
  807. textAlign: 'center',
  808. fill: '#fff',
  809. fontSize: 24,
  810. fontWeight: 'bold'
  811. }
  812. },
  813. {
  814. type: 'text',
  815. left: 'center',
  816. top: '60%',
  817. style: {
  818. text: '告警总数',
  819. textAlign: 'center',
  820. fill: '#8ba3c7',
  821. fontSize: 11
  822. }
  823. }
  824. ]
  825. };
  826. chart.setOption(option);
  827. this.charts.alertPie = chart;
  828. },
  829. initAlertTrendChart(res) {
  830. if (!this.$refs.alertTrendChart) return;
  831. const chart = echarts.init(this.$refs.alertTrendChart);
  832. const option = {
  833. tooltip: {
  834. trigger: 'axis',
  835. backgroundColor: '#fff',
  836. borderColor: '#e0e0e0',
  837. borderWidth: 1,
  838. textStyle: {
  839. color: '#333'
  840. },
  841. axisPointer: {
  842. type: 'line',
  843. lineStyle: {
  844. color: 'rgba(255, 255, 255, 0.5)'
  845. }
  846. }
  847. },
  848. grid: {
  849. top: '1.875rem',
  850. right: '1.25rem',
  851. bottom: '1.875rem',
  852. left: '3.125rem'
  853. },
  854. xAxis: {
  855. type: 'category',
  856. data: res.map((item) => item.time),
  857. axisLine: { lineStyle: { color: '#4a6fa5' } },
  858. axisLabel: { color: '#8ba3c7' }
  859. },
  860. yAxis: {
  861. type: 'value',
  862. axisLine: { lineStyle: { color: '#4a6fa5' } },
  863. axisLabel: { color: '#8ba3c7' },
  864. splitLine: { lineStyle: { color: 'rgba(74, 111, 165, 0.2)' } }
  865. },
  866. series: [
  867. {
  868. data: res.map((item) => item.value),
  869. type: 'line',
  870. smooth: true,
  871. areaStyle: {
  872. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  873. { offset: 0, color: 'rgba(59, 130, 246, 0.5)' },
  874. { offset: 1, color: 'rgba(59, 130, 246, 0.05)' }
  875. ])
  876. },
  877. lineStyle: { color: '#3b82f6', width: 2 },
  878. itemStyle: { color: '#3b82f6' }
  879. }
  880. ]
  881. };
  882. chart.setOption(option);
  883. this.charts.alertTrend = chart;
  884. },
  885. initElectricityTrend(res) {
  886. if (!this.$refs.electricityTrendChart) return;
  887. const chart = echarts.init(this.$refs.electricityTrendChart);
  888. const option = {
  889. tooltip: {
  890. trigger: 'axis',
  891. backgroundColor: '#fff',
  892. borderColor: '#e0e0e0',
  893. borderWidth: 1,
  894. textStyle: {
  895. color: '#333'
  896. },
  897. axisPointer: {
  898. type: 'line',
  899. lineStyle: {
  900. color: 'rgba(255, 255, 255, 0.5)'
  901. }
  902. }
  903. },
  904. grid: { top: 30, right: 20, bottom: 30, left: 50 },
  905. xAxis: {
  906. type: 'category',
  907. data: res.map((item) => item.time),
  908. axisLine: { lineStyle: { color: '#4a6fa5' } },
  909. axisLabel: { color: '#8ba3c7' }
  910. },
  911. yAxis: {
  912. type: 'value',
  913. axisLine: { lineStyle: { color: '#4a6fa5' } },
  914. axisLabel: { color: '#8ba3c7' },
  915. splitLine: { lineStyle: { color: 'rgba(74, 111, 165, 0.2)' } }
  916. },
  917. series: [
  918. {
  919. data: res.map((item) => item.value),
  920. type: 'line',
  921. smooth: true,
  922. areaStyle: {
  923. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  924. { offset: 0, color: 'rgba(59, 130, 246, 0.5)' },
  925. { offset: 1, color: 'rgba(59, 130, 246, 0.05)' }
  926. ])
  927. },
  928. lineStyle: { color: '#3b82f6', width: 2 },
  929. itemStyle: { color: '#3b82f6' }
  930. }
  931. ]
  932. };
  933. chart.setOption(option);
  934. this.charts.electricityTrendChart = chart;
  935. }
  936. }
  937. };
  938. </script>
  939. <style lang="scss" scoped>
  940. .box-container {
  941. width: 100vw;
  942. height: 100vh;
  943. .box-header-scroll {
  944. height: 5rem;
  945. background: url('~@/assets/pcs/header.png') no-repeat center top;
  946. background-size: 100% 100%;
  947. display: flex;
  948. align-items: center;
  949. justify-content: center;
  950. padding: 0 1.25rem;
  951. position: relative;
  952. z-index: 10;
  953. min-width: 137.5rem;
  954. .logo {
  955. // width: 12.5rem;
  956. padding-top: 0.625rem;
  957. position: absolute;
  958. left: 5rem;
  959. ::v-deep .custom-select {
  960. .el-input__inner {
  961. background: #0d2960;
  962. border: 1px solid #1a4a8a;
  963. color: #fff;
  964. height: 2.25rem;
  965. line-height: 2.25rem;
  966. &::placeholder {
  967. color: #8ba3c7;
  968. }
  969. }
  970. .el-input__suffix {
  971. .el-input__icon {
  972. color: #8ba3c7;
  973. }
  974. }
  975. }
  976. }
  977. .title {
  978. flex: 1;
  979. text-align: center;
  980. font-size: 1.75rem;
  981. font-weight: bold;
  982. color: #fff;
  983. text-shadow: 0 0 0.625rem rgba(59, 130, 246, 0.5);
  984. letter-spacing: 0.25rem;
  985. }
  986. .time {
  987. position: absolute;
  988. right: 1.875rem;
  989. width: 17.5rem;
  990. display: flex;
  991. align-items: center;
  992. justify-content: flex-end;
  993. gap: 0.9375rem;
  994. .time-display {
  995. display: flex;
  996. flex-direction: column;
  997. align-items: flex-end;
  998. .date-text {
  999. font-size: 0.875rem;
  1000. color: #8ba3c7;
  1001. }
  1002. .time-text {
  1003. font-size: 1.25rem;
  1004. font-weight: bold;
  1005. color: #fff;
  1006. }
  1007. }
  1008. .fullscreen-toggle {
  1009. cursor: pointer;
  1010. font-size: 1.25rem;
  1011. color: #8ba3c7;
  1012. transition: color 0.3s;
  1013. &:hover {
  1014. color: #3b82f6;
  1015. }
  1016. }
  1017. }
  1018. }
  1019. .box-content {
  1020. height: calc(100%);
  1021. background: radial-gradient(
  1022. ellipse at top,
  1023. rgba(13, 45, 110, 0.3) 0%,
  1024. transparent 50%
  1025. ),
  1026. radial-gradient(
  1027. ellipse at bottom,
  1028. rgba(8, 25, 65, 0.5) 0%,
  1029. transparent 50%
  1030. ),
  1031. linear-gradient(180deg, #0a1630 0%, #0d1f4a 50%, #08152e 100%);
  1032. overflow: auto;
  1033. font-family: 'Microsoft YaHei', sans-serif;
  1034. flex: 1;
  1035. // overflow-x: auto;
  1036. // overflow-y: hidden;
  1037. &::-webkit-scrollbar {
  1038. height: 0.375rem;
  1039. }
  1040. &::-webkit-scrollbar-track {
  1041. background: rgba(12, 32, 70, 0.4);
  1042. }
  1043. &::-webkit-scrollbar-thumb {
  1044. background: linear-gradient(180deg, #1a4a8a, #0d2a5a);
  1045. border-radius: 0.1875rem;
  1046. }
  1047. .scroll-wrapper {
  1048. // display: flex;
  1049. display: inline-block;
  1050. height: 100%;
  1051. // flex-direction: column;
  1052. // gap: 1.25rem;
  1053. // padding: 0 1.25rem 1.25rem 1.25rem;
  1054. width: 100%;
  1055. .header-section {
  1056. width: auto;
  1057. flex-shrink: 0;
  1058. padding-top: 0.625rem;
  1059. min-width: 100%;
  1060. }
  1061. .three-column-layout {
  1062. display: inline-block;
  1063. white-space: nowrap;
  1064. flex: 1;
  1065. min-height: 53.125rem;
  1066. // min-width: 137.5rem;
  1067. height: calc(100% - 8.125rem);
  1068. min-width: 100%;
  1069. margin-top: 1.25rem;
  1070. font-size: 0;
  1071. background: url('~@/assets/pcs/back.png') no-repeat center top;
  1072. background-size: 100% 100%;
  1073. }
  1074. }
  1075. .left-section,
  1076. .right-section,
  1077. .center-section {
  1078. display: inline-block;
  1079. vertical-align: top;
  1080. height: 100%;
  1081. font-size: 0.875rem;
  1082. white-space: normal;
  1083. }
  1084. .left-section,
  1085. .right-section {
  1086. min-width: 50rem;
  1087. margin-right: 1.25rem;
  1088. width: 29%;
  1089. }
  1090. .center-section {
  1091. width: 40%;
  1092. // width: calc(100% - 77.5rem);
  1093. min-width: 78.125rem;
  1094. margin-right: 1.25rem;
  1095. position: relative;
  1096. }
  1097. .left-section,
  1098. .right-section {
  1099. display: inline-flex;
  1100. flex-direction: column;
  1101. gap: 0.9375rem;
  1102. overflow: hidden;
  1103. }
  1104. .panel {
  1105. // background: linear-gradient(
  1106. // 135deg,
  1107. // rgba(16, 42, 88, 0.9) 0%,
  1108. // rgba(10, 28, 65, 0.85) 100%
  1109. // );
  1110. // border: 1px solid rgba(42, 90, 170, 0.4);
  1111. // border-radius: 0.5rem;
  1112. padding: 0.9375rem;
  1113. min-height: 0;
  1114. // box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
  1115. // 0 4px 20px rgba(0, 0, 0, 0.3);
  1116. .panel-title {
  1117. font-size: 1.75rem;
  1118. // font-weight: bold;
  1119. // font-style: italic;
  1120. font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei', sans-serif;
  1121. color: #fff;
  1122. margin-bottom: 0.9375rem;
  1123. height: 2.625rem;
  1124. padding-left: 2.5rem;
  1125. position: relative;
  1126. display: flex;
  1127. align-items: center;
  1128. background: url('~@/assets/pcs/titleb.png') no-repeat center top;
  1129. background-size: 100% 100%;
  1130. &.energy-title {
  1131. display: flex;
  1132. justify-content: space-between;
  1133. padding-right: 0.9375rem;
  1134. .title-left {
  1135. display: flex;
  1136. align-items: center;
  1137. gap: 0.5rem;
  1138. }
  1139. }
  1140. .panel-icon {
  1141. position: absolute;
  1142. left: 0.9375rem;
  1143. width: 1.25rem;
  1144. height: 1.5625rem;
  1145. background: url('~@/assets/pcs/titleIcon.png') no-repeat center top;
  1146. background-size: 100% 100%;
  1147. }
  1148. }
  1149. .energy-tabs {
  1150. position: absolute;
  1151. top: 4.0625rem;
  1152. right: 2.5rem;
  1153. z-index: 999;
  1154. display: flex;
  1155. gap: 0;
  1156. background: rgba(13, 41, 96, 0.5);
  1157. border-radius: 0.25rem;
  1158. padding: 0.125rem;
  1159. .tab-item {
  1160. padding: 0.25rem 0.75rem;
  1161. font-size: 0.75rem;
  1162. color: #8ba3c7;
  1163. cursor: pointer;
  1164. border-radius: 0.1875rem;
  1165. transition: all 0.3s;
  1166. &:hover {
  1167. color: #fff;
  1168. }
  1169. &.active {
  1170. background: linear-gradient(135deg, #3b82f6, #1a6fd9);
  1171. color: #fff;
  1172. }
  1173. }
  1174. }
  1175. }
  1176. .data-panel {
  1177. min-height: 13.75rem;
  1178. flex-shrink: 0;
  1179. display: flex;
  1180. flex-direction: column;
  1181. flex: 0.7;
  1182. .panel-title {
  1183. flex-shrink: 0;
  1184. }
  1185. .data-grid {
  1186. display: flex;
  1187. gap: 0.75rem;
  1188. // padding: 0.625rem 0;
  1189. align-items: center;
  1190. justify-content: space-around;
  1191. flex-wrap: wrap;
  1192. overflow: hidden;
  1193. height: 100%;
  1194. .data-item {
  1195. // background: linear-gradient(
  1196. // 135deg,
  1197. // rgba(20, 50, 105, 0.9) 0%,
  1198. // rgba(14, 38, 82, 0.85) 100%
  1199. // );
  1200. // border: 1px solid rgba(45, 95, 180, 0.5);
  1201. .img {
  1202. width: 2.1875rem;
  1203. height: 2.1875rem;
  1204. background: url('~@/assets/pcs/icon.png') no-repeat center top;
  1205. background-size: 100% 100%;
  1206. }
  1207. border-radius: 0.375rem;
  1208. display: flex;
  1209. .data-item_value {
  1210. display: flex;
  1211. flex-direction: column;
  1212. // align-items: center;
  1213. }
  1214. // flex-direction: column;
  1215. align-items: center;
  1216. // justify-content: center;
  1217. padding-left: 0.9375rem;
  1218. gap: 0.5rem;
  1219. position: relative;
  1220. overflow: hidden;
  1221. width: 18%;
  1222. height: 3.75rem;
  1223. background: url('~@/assets/pcs/leftItem.png') no-repeat center top;
  1224. background-size: 100% 100%;
  1225. // &::before {
  1226. // content: '';
  1227. // position: absolute;
  1228. // top: 0;
  1229. // left: 0;
  1230. // right: 0;
  1231. // height: 0.125rem;
  1232. // background: linear-gradient(
  1233. // 90deg,
  1234. // transparent,
  1235. // #00d4ff,
  1236. // transparent
  1237. // );
  1238. // box-shadow: 0 0 0.5rem rgba(0, 212, 255, 0.6);
  1239. // }
  1240. .data-label {
  1241. font-size: 0.75rem;
  1242. color: #8ba3c7;
  1243. text-align: center;
  1244. line-height: 1.3;
  1245. }
  1246. .data-value {
  1247. font-size: 1.125rem;
  1248. font-weight: bold;
  1249. color: #b6ceff;
  1250. text-shadow: 0 0 0.625rem rgba(0, 212, 255, 0.5);
  1251. }
  1252. }
  1253. }
  1254. }
  1255. .chart-panel {
  1256. flex: 1;
  1257. min-height: 15.625rem;
  1258. display: flex;
  1259. flex-direction: column;
  1260. .chart-container {
  1261. width: 100%;
  1262. flex: 1;
  1263. min-height: 0;
  1264. }
  1265. }
  1266. .param-card3 {
  1267. right: 0.625rem;
  1268. }
  1269. .param-card2 {
  1270. left: 30%;
  1271. }
  1272. .param-card {
  1273. width: 23%;
  1274. top: 3.125rem;
  1275. position: absolute;
  1276. background: rgba(39, 88, 233, 0.1);
  1277. border: 1px solid #3373d4;
  1278. border-radius: 0.5rem;
  1279. &::before {
  1280. content: '';
  1281. position: absolute;
  1282. top: 0;
  1283. left: 0;
  1284. right: 0;
  1285. height: 0.125rem;
  1286. background: linear-gradient(90deg, transparent, #00d4ff, transparent);
  1287. box-shadow: 0 0 0.5rem rgba(0, 212, 255, 0.5);
  1288. }
  1289. .param-title {
  1290. font-size: 0.875rem;
  1291. font-weight: bold;
  1292. color: #fff;
  1293. padding-bottom: 0.75rem;
  1294. padding-top: 0.75rem;
  1295. text-align: center;
  1296. text-shadow: 0 0 0.625rem rgba(0, 212, 255, 0.3);
  1297. border-bottom: 1px solid rgba(0, 212, 255, 0.5);
  1298. background: rgba(39, 88, 233, 0.1);
  1299. }
  1300. .param-list {
  1301. padding: 0.9375rem;
  1302. display: flex;
  1303. flex-direction: column;
  1304. gap: 0.625rem;
  1305. .param-item {
  1306. display: flex;
  1307. // justify-content: space-between;
  1308. font-size: 0.75rem;
  1309. padding: 0.25rem 0;
  1310. // border-bottom: 1px dashed rgba(138, 163, 199, 0.2);
  1311. &:last-child {
  1312. border-bottom: none;
  1313. }
  1314. .param-name {
  1315. color: #8ba3c7;
  1316. min-width: 4rem;
  1317. }
  1318. .param-value {
  1319. color: #fff;
  1320. font-weight: 500;
  1321. }
  1322. }
  1323. }
  1324. }
  1325. .pipeline-container {
  1326. flex: 1;
  1327. min-height: 0;
  1328. position: absolute;
  1329. bottom: 0.9375rem;
  1330. left: 0;
  1331. height: 60%;
  1332. width: 100%;
  1333. // background: linear-gradient(
  1334. // 135deg,
  1335. // rgba(14, 40, 85, 0.6) 0%,
  1336. // rgba(10, 28, 60, 0.5) 100%
  1337. // );
  1338. // border: 1px solid rgba(45, 95, 180, 0.3);
  1339. // border-radius: 0.5rem;
  1340. background: url('~@/assets/pcs/home.png') no-repeat center top;
  1341. background-size: 100% 100%;
  1342. // max-height: 42.5rem;
  1343. }
  1344. .alert-panel {
  1345. min-height: 13.75rem;
  1346. flex-shrink: 0;
  1347. display: flex;
  1348. flex-direction: column;
  1349. flex: 0.7;
  1350. .panel-title {
  1351. flex-shrink: 0;
  1352. }
  1353. .alert-stats {
  1354. flex: 1;
  1355. min-height: 0;
  1356. display: flex;
  1357. align-items: center;
  1358. height: calc(100% - 2.1875rem);
  1359. gap: 1.25rem;
  1360. // 左侧数据卡片区域
  1361. .alert-cards {
  1362. width: 50%;
  1363. height: 100%;
  1364. display: flex;
  1365. flex-wrap: wrap;
  1366. justify-content: space-around;
  1367. gap: 0.75rem;
  1368. .alert-card-item {
  1369. width: 40%;
  1370. // background: linear-gradient(
  1371. // 135deg,
  1372. // rgba(20, 50, 105, 0.9) 0%,
  1373. // rgba(14, 38, 82, 0.85) 100%
  1374. // );
  1375. // border: 1px solid rgba(45, 95, 180, 0.5);
  1376. .img {
  1377. width: 2.1875rem;
  1378. height: 2.1875rem;
  1379. background: url('~@/assets/pcs/icon.png') no-repeat center top;
  1380. background-size: 100% 100%;
  1381. }
  1382. border-radius: 0.375rem;
  1383. display: flex;
  1384. .data-item_value {
  1385. display: flex;
  1386. flex-direction: column;
  1387. // align-items: center;
  1388. }
  1389. // flex-direction: column;
  1390. align-items: center;
  1391. // justify-content: center;
  1392. padding-left: 0.9375rem;
  1393. gap: 0.5rem;
  1394. position: relative;
  1395. overflow: hidden;
  1396. height: 3.75rem;
  1397. background: url('~@/assets/pcs/leftItem.png') no-repeat center top;
  1398. background-size: 100% 100%;
  1399. // &::before {
  1400. // content: '';
  1401. // position: absolute;
  1402. // top: 0;
  1403. // left: 0;
  1404. // right: 0;
  1405. // height: 0.125rem;
  1406. // background: linear-gradient(
  1407. // 90deg,
  1408. // transparent,
  1409. // #00d4ff,
  1410. // transparent
  1411. // );
  1412. // box-shadow: 0 0 0.5rem rgba(0, 212, 255, 0.6);
  1413. // }
  1414. .data-label {
  1415. font-size: 0.75rem;
  1416. color: #8ba3c7;
  1417. text-align: center;
  1418. line-height: 1.3;
  1419. }
  1420. .data-value {
  1421. font-size: 1.125rem;
  1422. font-weight: bold;
  1423. color: #b6ceff;
  1424. text-shadow: 0 0 0.625rem rgba(0, 212, 255, 0.5);
  1425. }
  1426. }
  1427. }
  1428. // 右侧环形图区域
  1429. .alert-pie-chart {
  1430. width: 50%;
  1431. height: 100%;
  1432. position: relative;
  1433. display: flex;
  1434. align-items: center;
  1435. justify-content: center;
  1436. .alert-pie {
  1437. width: 100%;
  1438. height: 100%;
  1439. min-height: 11.25rem;
  1440. }
  1441. }
  1442. }
  1443. }
  1444. .alert-list-panel {
  1445. flex: 1;
  1446. min-height: 0;
  1447. display: flex;
  1448. flex-direction: column;
  1449. min-height: 15.625rem;
  1450. .alert-table {
  1451. flex: 1;
  1452. min-height: 0;
  1453. overflow: hidden;
  1454. .table-header {
  1455. display: grid;
  1456. grid-template-columns: 3.125rem 5.625rem 6.25rem 4.375rem 1fr 8.125rem 4.375rem;
  1457. gap: 0.375rem;
  1458. padding: 0.625rem 0.375rem;
  1459. background: linear-gradient(
  1460. 90deg,
  1461. rgba(16, 45, 95, 0.9) 0%,
  1462. rgba(12, 35, 75, 0.85) 100%
  1463. );
  1464. font-size: 0.75rem;
  1465. color: #00d4ff;
  1466. text-align: center;
  1467. font-weight: 500;
  1468. border-bottom: 1px solid rgba(45, 95, 180, 0.4);
  1469. }
  1470. }
  1471. }
  1472. }
  1473. }
  1474. [v-cloak] {
  1475. display: none;
  1476. }
  1477. </style>