index.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  1. <template>
  2. <div class="dashboard-container">
  3. <!-- 顶部横幅 -->
  4. <!-- <div class="server_title">
  5. <el-image
  6. style="width: 50%; height: calc(100vh - 120px)"
  7. src="static/images/wgn_title.png"
  8. fit="cover"
  9. />
  10. <div class="server_title_text">
  11. <div class="server_title_text_title">时空门户</div>
  12. <div class="server_title_text_content">
  13. 时空门户子系统为用户提供信息概览、导航入口及交互功能,帮助用户快速了解和使用平台服务。系统统计访问量(累计和日均)、用户使用时长及活跃时段;展示平台功能、核心能力及操作演示视频;统计并展示服务总数、分类占比及新上线服务;同时统计各委办平台的注册用户信息及用户总数。
  14. </div>
  15. </div>
  16. </div> -->
  17. <!-- 顶部横幅区域 -->
  18. <div class="banner">
  19. <div class="banner-content">
  20. <h1 class="banner-title">时空门户</h1>
  21. <p class="banner-description">
  22. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;时空门户子系统为用户提供信息概览、导航入口及交互功能,帮助用户快速了解和使用平台服务。系统统计访问量(累计和日均)、用户使用时长及活跃时段;展示平台功能、核心能力及操作演示视频;统计并展示服务总数、分类占比及新上线服务;同时统计各委办平台的注册用户信息及用户总数。
  23. </p>
  24. <!-- <div>
  25. <el-button type="primary" class="enter-button" @click="handleEnterClick">立即体验</el-button>
  26. </div> -->
  27. </div>
  28. </div>
  29. <div class="server_list_box">
  30. <div class="server_list_box_table">
  31. <div
  32. v-for="(item, index) in dataList[0].data"
  33. :key="item.index"
  34. class="server_list_box_table_item"
  35. :id="item.index + 'list'"
  36. >
  37. <div class="server_list_box_table_item_content">
  38. <div class="server_list_box_table_item_content_title">{{ item.title }}</div>
  39. <div class="server_list_box_table_item_content_text">{{ item.text }}</div>
  40. <div class="server_list_box_table_item_content_button_box">
  41. <div v-if="index < 3"
  42. class="server_list_box_table_item_content_button_box_item"
  43. @click.stop="handleOpenPage(item)"
  44. >
  45. 进入系统
  46. </div>
  47. <div v-else
  48. class="server_list_box_table_item_content_button_box_expect"
  49. >
  50. 敬请期待
  51. </div>
  52. </div>
  53. </div>
  54. <div class="server_list_box_table_item_image">
  55. <el-image
  56. style="width: 690px; height: 410px"
  57. :src="item.picture"
  58. fit="cover"
  59. />
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. <!-- 平台数据统计 -->
  65. <!-- <div class="stats-section">
  66. <div class="overview-header">
  67. <h2>平台数据统计</h2>
  68. </div>
  69. <div class="stats-grid">
  70. <div class="stat-card card-1">
  71. <div class="stat-label">平台服务总数
  72. <el-image
  73. style="width: 20px; height: 20px"
  74. src="static/images/skmh-1.png"
  75. fit="cover"
  76. />
  77. </div>
  78. <div class="stat-number"><NumberScroll :value="countData.total.service" :duration="2000" /></div>
  79. <div class="stat-label">较上月增长{{countData.grown}}%</div>
  80. </div>
  81. <div class="stat-card card-2">
  82. <div class="stat-label">新上线服务统计
  83. <el-image
  84. style="width: 20px; height: 20px"
  85. src="static/images/skmh-2.png"
  86. fit="cover"
  87. />
  88. </div>
  89. <div class="stat-number"><NumberScroll :value="countData.curMonth.service" :duration="2000" /></div>
  90. <div class="stat-label">本月新增服务</div>
  91. </div>
  92. <div class="stat-card card-3">
  93. <div class="stat-label">注册用户总数
  94. <el-image
  95. style="width: 20px; height: 20px"
  96. src="static/images/skmh-3.png"
  97. fit="cover"
  98. />
  99. </div>
  100. <div class="stat-number"><NumberScroll :value="countData.total.username" :duration="2000" /></div>
  101. <div class="stat-label">本周新增{{countData.curWeek.username}}人</div>
  102. </div>
  103. </div>
  104. </div> -->
  105. <!-- 数据概览 -->
  106. <!-- <div class="data-overview">
  107. <div class="overview-header">
  108. <h2>数据概览</h2>
  109. </div>
  110. <div class="time-section">
  111. <div class="time-card">
  112. <div class="time-content">
  113. <div style="">
  114. <el-date-picker
  115. class="el-date-picker"
  116. v-model="fromTime.date"
  117. :clearable="false"
  118. type="daterange"
  119. range-separator="到"
  120. start-placeholder="开始日期"
  121. end-placeholder="结束日期"
  122. format="YYYY-MM-DD"
  123. @change="changeTime"
  124. />
  125. </div>
  126. <div class="button-row">
  127. <el-button type="primary" @click="handleType(7)">最近7天</el-button>
  128. <el-button type="primary" @click="handleType(30)">最近30天</el-button>
  129. <el-button type="primary" @click="handleType(90)">最近90天</el-button>
  130. <el-button type="primary" @click="handleType(365)">最近1年</el-button>
  131. </div>
  132. </div>
  133. </div>
  134. </div> -->
  135. <!-- <div class="charts-grid"> -->
  136. <!-- 访问量统计柱状图 -->
  137. <!-- <div class="chart-card">
  138. <div class="chart-title">访问量统计</div>
  139. <div ref="deviceChart" class="chart-container"></div>
  140. </div> -->
  141. <!-- 服务分类占比饼图 -->
  142. <!-- <div class="chart-card">
  143. <div class="chart-title">服务分类占比</div>
  144. <div ref="statusChart" class="chart-container"></div>
  145. </div> -->
  146. <!-- 用户活跃度分析折线图 -->
  147. <!-- <div class="chart-card">
  148. <div class="chart-title">用户活跃度分析</div>
  149. <div ref="activityChart" class="chart-container"></div>
  150. </div> -->
  151. <!-- 数据量柱状图 -->
  152. <!-- <div class="chart-card">
  153. <div class="chart-title">数据量</div>
  154. <div ref="dataVolumeChart" class="chart-container"></div>
  155. </div> -->
  156. <!-- </div>
  157. </div> -->
  158. <!-- 设备综合分析比较 -->
  159. <!-- <div class="comparison-section">
  160. <div class="chart-card full-width">
  161. <div class="chart-title">用户分布</div>
  162. <el-table :data="tableData" style="width: 100%;"
  163. height="530"
  164. :header-cell-style="headerCellStyle"
  165. :row-style="rowStyle"
  166. :cell-style="cellStyle"
  167. stripe
  168. border>
  169. <el-table-column prop="unit" label="委办单位" />
  170. <el-table-column prop="user" label="用户数量" />
  171. <el-table-column prop="active" label="活跃天数" />
  172. <el-table-column prop="count" label="服务使用量" />
  173. </el-table>
  174. </div>
  175. </div> -->
  176. <!-- 功能演示 -->
  177. <!-- <div class="demo-section">
  178. <div class="overview-header">
  179. <h2>功能演示</h2>
  180. </div>
  181. <div class="demo-grid">
  182. <div class="demo-card" v-for="item in applications" :key="item.id">
  183. <div class="demo-thumbnail" :style="{ backgroundImage: 'url(' + item.backImg + ')',backgroundSize: 'cover' }">
  184. <div class="play-btn" @click="openVideo(item)">▶</div>
  185. </div>
  186. <div class="demo-title">
  187. <div class="demo-label">{{item.title}}</div>
  188. <div class="demo-text">{{item.content}}</div>
  189. </div>
  190. </div>
  191. </div>
  192. </div> -->
  193. <div>
  194. <el-dialog
  195. v-model="centerDialogVisible"
  196. title="预览"
  197. width="60%"
  198. center
  199. :before-close="closeDialog"
  200. >
  201. <video :src="videoUrl" controls style="width: 100%" />
  202. </el-dialog>
  203. </div>
  204. </div>
  205. </template>
  206. <script>
  207. import * as echarts from 'echarts'
  208. import { ElNotification } from "element-plus";
  209. import appCenter from "@/api/appCenter";
  210. import { countUserList,coutService,totalCountGroupByTime,countUserDataByAutoTime } from "@/api/count";
  211. import moment from "moment";
  212. import NumberScroll from '@/components/AppVue/numberScroll.vue'
  213. export default {
  214. name: 'SpatialTemporalPortal',
  215. components: {
  216. NumberScroll
  217. },
  218. data() {
  219. return {
  220. deviceChart: null,
  221. statusChart: null,
  222. activityChart: null,
  223. dataVolumeChart: null,
  224. comparisonChart: null,
  225. centerDialogVisible: false,
  226. videoUrl: "",
  227. imageUrl: "static/images/wgn_title.png",
  228. dataList:systemConfig.examplelist,
  229. countData:{
  230. total:{
  231. service:0,
  232. username:0,
  233. },
  234. curWeek:{
  235. service:0,
  236. username:0,
  237. },
  238. curMonth:{
  239. service:0,
  240. username:0,
  241. },
  242. lastMonth:{
  243. service:0,
  244. username:0,
  245. },
  246. grown:0,
  247. },
  248. fromTime:{
  249. date:[new Date(new Date().setMonth(new Date().getMonth() - 1)),new Date()],// 默认显示最近一个月
  250. },
  251. tableData:[],
  252. applications:[],
  253. }
  254. },
  255. computed: {
  256. headerCellStyle() {
  257. return {
  258. backgroundColor: "rgba(24, 144, 255, 0.25)",
  259. color: "#0071e3",
  260. fontWeight: "bold",
  261. borderBottom: "2px solid rgba(24, 144, 255, 0.3)",
  262. padding: "12px 8px",
  263. };
  264. },
  265. rowStyle() {
  266. return {
  267. // 调整行背景色为更浅的黑色,增加透明度
  268. backgroundColor: "rgba(0, 0, 0, 0.05)",
  269. borderBottom: "1px solid rgba(255, 255, 255, 0.05)",
  270. transition: "all 0.3s ease",
  271. };
  272. },
  273. cellStyle() {
  274. return {
  275. color: "#e0e0e0",
  276. padding: "12px 8px",
  277. borderRight: "1px solid rgba(255, 255, 255, 0.05)",
  278. };
  279. },
  280. },
  281. mounted() {
  282. // this.initData()
  283. // window.addEventListener('resize', this.handleResize)
  284. },
  285. beforeUnmount() {
  286. // window.removeEventListener('resize', this.handleResize)
  287. // this.destroyCharts()
  288. },
  289. methods: {
  290. initData(){
  291. this.getTimeRange();
  292. this.getCountUserDataByAutoTime();
  293. this.getDmsDataList();
  294. },
  295. getTimeRange(){
  296. this.getTotalCountGroupByTime();
  297. this.getCountUserList();
  298. this.getCoutService();
  299. },
  300. openVideo(param) {
  301. console.log(param)
  302. this.videoUrl = param.url;
  303. this.centerDialogVisible = true;
  304. },
  305. closeDialog() {
  306. this.videoUrl = "";
  307. this.centerDialogVisible = false;
  308. },
  309. handleOpenPage(item){
  310. if(item.url){
  311. window.open(item.url, '_blank');
  312. }else{
  313. ElNotification.success({
  314. title: "提示",
  315. message: "暂未开放服务",
  316. offset: 80,
  317. });
  318. }
  319. },
  320. getDmsDataList() {
  321. let requestParams = {
  322. columnId: systemConfig.columnIds[2], // 应用中心栏目id(示范应用)
  323. states: 0,
  324. orderBy: JSON.stringify([{"field":"update_time","orderByType":2}]),
  325. pageSize: 9999,
  326. page: 0,
  327. };
  328. this.applications = [];
  329. appCenter.getDmsDataList(requestParams).then((res) => {
  330. if (res.code === 200) {
  331. this.applications = res.content.data.map((item) => ({
  332. ...item,
  333. status:
  334. item.status === 0
  335. ? "待审核"
  336. : item.status === 1
  337. ? "待发布"
  338. : item.status === 2
  339. ? "未完成"
  340. : "已完成",
  341. createTime: moment(item.create_time).format("YYYY-MM-DD HH:mm:ss"),
  342. backImg: systemConfig.dmsDataProxy + item.c_picture,
  343. url: item.c_url,
  344. }));
  345. }
  346. });
  347. },
  348. getCountUserDataByAutoTime(){
  349. let param = JSON.stringify([
  350. {
  351. name: "total",
  352. start: '2000-01-01 00:00:00', // 从2000年1月1日开始
  353. end: moment(new Date()).format("YYYY-MM-DD 23:59:59") // 到当前一天结束时间
  354. },
  355. {
  356. name: "curWeek",
  357. start: moment().weekday(1).format("YYYY-MM-DD 00:00:00"), //本周一00:00:00
  358. end: moment(new Date()).format("YYYY-MM-DD 23:59:59") // 到当前一天结束时间
  359. },
  360. {
  361. name: "curMonth",
  362. start: moment().startOf('month').format('YYYY-MM-DD 00:00:00'), //本月1日00:00:00
  363. end: moment(new Date()).format("YYYY-MM-DD 23:59:59") // 到当前一天结束时间
  364. },
  365. {
  366. name: "lastMonth",
  367. start: moment().subtract(1, 'month').startOf('month').format('YYYY-MM-DD 00:00:00'), //上月1日00:00:00
  368. end: moment().subtract(1, 'month').endOf('month').format("YYYY-MM-DD 23:59:59") //上月最后一天23:59:59
  369. },
  370. ])
  371. // console.log(param)
  372. countUserDataByAutoTime(param).then(res => {
  373. // console.log(res)
  374. this.countData = res;
  375. this.countData.grown = (res.curMonth.service/res.lastMonth.service)*100;
  376. this.countData.grown = this.countData.grown.toFixed(2)
  377. })
  378. },
  379. getTotalCountGroupByTime(){
  380. let start = this.fromTime.date[0], end = this.fromTime.date[1];
  381. start = moment(start).format("YYYY-MM-DD 00:00:00");
  382. end = moment(end).format("YYYY-MM-DD 23:59:59");
  383. totalCountGroupByTime(start,end).then(res => {
  384. this.drawLineChart(res)
  385. })
  386. },
  387. drawLineChart(data){
  388. let that = this;
  389. let times = []
  390. let values = []
  391. data.sort((a, b) => a.time - b.time)
  392. data.forEach((item,index) => {
  393. times.push(moment(item.time).format("YYYY-MM-DD"))
  394. values.push(item.count)
  395. })
  396. // 基于准备好的dom,初始化echarts实例
  397. let lineChart = echarts.init(this.$refs.deviceChart)
  398. const option = {
  399. tooltip: {
  400. trigger: "axis",
  401. axisPointer: { type: "shadow" },
  402. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  403. borderColor: '#1E90FF',
  404. textStyle: {
  405. color: '#fff'
  406. },
  407. formatter: function (params) {
  408. let str = '';
  409. params.forEach(item => {
  410. str += `${item.name} <br/> ${item.seriesName}: ${item.value}次<br/>`;
  411. });
  412. return str;
  413. }
  414. },
  415. grid: {
  416. left: '3%',
  417. right: '4%',
  418. bottom: '3%',
  419. containLabel: true
  420. },
  421. xAxis: {
  422. type: 'category',
  423. data: times,
  424. axisLabel: {
  425. color: '#a3b6c7',
  426. formatter: function (params) {
  427. let str = '';
  428. let arr = params.split("-")
  429. str = `${arr[1]}/${arr[2]}`
  430. return str;
  431. }
  432. },
  433. axisLine: {
  434. lineStyle: {
  435. color: '#1E90FF'
  436. }
  437. }
  438. },
  439. yAxis: {
  440. type: 'value',
  441. axisLabel: {
  442. color: '#a3b6c7'
  443. },
  444. axisLine: {
  445. lineStyle: {
  446. color: '#1E90FF'
  447. }
  448. },
  449. splitLine: {
  450. lineStyle: {
  451. color: 'rgba(30, 144, 255, 0.2)'
  452. }
  453. }
  454. },
  455. series: [
  456. {
  457. name: "访问次数",
  458. type: 'line',
  459. data: values,
  460. itemStyle: {
  461. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  462. { offset: 0, color: '#1E90FF' },
  463. { offset: 1, color: '#00BFFF' }
  464. ])
  465. }
  466. }
  467. ]
  468. }
  469. // 绘制图表
  470. lineChart.setOption(option);
  471. that.deviceChart = lineChart;
  472. },
  473. getCoutService(){
  474. let start = this.fromTime.date[0], end = this.fromTime.date[1];
  475. start = moment(start).format("YYYY-MM-DD 00:00:00");
  476. end = moment(end).format("YYYY-MM-DD 23:59:59");
  477. coutService(new Date(start),new Date(end)).then(res => {
  478. // console.log('[ res ] >', res)
  479. let arr = [];
  480. if(res != undefined){
  481. res.sort((a, b) => b.count - a.count)
  482. res.forEach(item => {
  483. // let str = { value: item.count, name: item.service_name, itemStyle: { color: '#52C41A' } }
  484. let str = { value: item.count, name: item.service_name }
  485. arr.push(str)
  486. })
  487. }
  488. this.initStatusChart(arr)
  489. })
  490. },
  491. getCountUserList(){
  492. let that = this
  493. let start = this.fromTime.date[0], end = this.fromTime.date[1];
  494. start = moment(start).format("YYYY-MM-DD 00:00:00");
  495. end = moment(end).format("YYYY-MM-DD 23:59:59");
  496. countUserList(start,end).then(res => {
  497. res.sort((a, b) => b.count - a.count)
  498. that.tableData = res;
  499. })
  500. },
  501. handleType(param){
  502. const end = new Date()
  503. const start = new Date()
  504. start.setDate(start.getDate() - (param - 1))
  505. console.log(start,end)
  506. this.fromTime.date = [start,end];
  507. this.getTimeRange();
  508. },
  509. changeTime(v){
  510. this.fromTime.date=v
  511. this.getTimeRange();
  512. },
  513. initDeviceChart() {
  514. this.deviceChart = echarts.init(this.$refs.deviceChart)
  515. const option = {
  516. tooltip: {
  517. trigger: 'item',
  518. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  519. borderColor: '#1E90FF',
  520. textStyle: {
  521. color: '#fff'
  522. }
  523. },
  524. legend: {
  525. orient: 'horizontal',
  526. // bottom: 0,
  527. top:0,
  528. textStyle: {
  529. color: '#a3b6c7'
  530. }
  531. },
  532. grid: {
  533. left: '3%',
  534. right: '4%',
  535. bottom: '3%',
  536. containLabel: true
  537. },
  538. xAxis: {
  539. type: 'category',
  540. data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
  541. axisLabel: {
  542. color: '#a3b6c7'
  543. },
  544. axisLine: {
  545. lineStyle: {
  546. color: '#1E90FF'
  547. }
  548. }
  549. },
  550. yAxis: {
  551. type: 'value',
  552. axisLabel: {
  553. color: '#a3b6c7'
  554. },
  555. axisLine: {
  556. lineStyle: {
  557. color: '#1E90FF'
  558. }
  559. },
  560. splitLine: {
  561. lineStyle: {
  562. color: 'rgba(30, 144, 255, 0.2)'
  563. }
  564. }
  565. },
  566. series: [
  567. {
  568. data: [120, 200, 150, 80, 70, 110],
  569. type: 'bar',
  570. barWidth: '60%',
  571. itemStyle: {
  572. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  573. { offset: 0, color: '#1E90FF' },
  574. { offset: 1, color: '#00BFFF' }
  575. ])
  576. }
  577. }
  578. ]
  579. }
  580. this.deviceChart.setOption(option)
  581. },
  582. initStatusChart(seriesData) {
  583. this.statusChart = echarts.init(this.$refs.statusChart)
  584. const option = {
  585. tooltip: {
  586. trigger: 'item',
  587. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  588. borderColor: '#1E90FF',
  589. textStyle: {
  590. color: '#fff'
  591. }
  592. },
  593. legend: {
  594. orient: 'horizontal',
  595. bottom: 0,
  596. textStyle: {
  597. color: '#a3b6c7'
  598. }
  599. },
  600. series: [
  601. {
  602. name: '服务分类占比',
  603. type: 'pie',
  604. radius: ['40%', '70%'],
  605. avoidLabelOverlap: false,
  606. itemStyle: {
  607. borderRadius: 10,
  608. borderColor: '#0A192F',
  609. borderWidth: 2
  610. },
  611. label: {
  612. show: false,
  613. position: 'center'
  614. },
  615. emphasis: {
  616. label: {
  617. show: true,
  618. fontSize: 20,
  619. fontWeight: 'bold',
  620. color: '#fff'
  621. }
  622. },
  623. labelLine: {
  624. show: false
  625. },
  626. data: seriesData
  627. }
  628. ]
  629. }
  630. this.statusChart.setOption(option)
  631. },
  632. initActivityChart() {
  633. this.activityChart = echarts.init(this.$refs.activityChart)
  634. const option = {
  635. tooltip: {
  636. trigger: 'axis',
  637. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  638. borderColor: '#1E90FF',
  639. textStyle: {
  640. color: '#fff'
  641. }
  642. },
  643. grid: {
  644. left: '3%',
  645. right: '4%',
  646. bottom: '3%',
  647. containLabel: true
  648. },
  649. xAxis: {
  650. type: 'category',
  651. boundaryGap: false,
  652. data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
  653. axisLabel: {
  654. color: '#a3b6c7'
  655. },
  656. axisLine: {
  657. lineStyle: {
  658. color: '#1E90FF'
  659. }
  660. }
  661. },
  662. yAxis: {
  663. type: 'value',
  664. axisLabel: {
  665. color: '#a3b6c7'
  666. },
  667. axisLine: {
  668. lineStyle: {
  669. color: '#1E90FF'
  670. }
  671. },
  672. splitLine: {
  673. lineStyle: {
  674. color: 'rgba(30, 144, 255, 0.2)'
  675. }
  676. }
  677. },
  678. series: [
  679. {
  680. name: '活跃度',
  681. type: 'line',
  682. stack: 'Total',
  683. smooth: true,
  684. lineStyle: {
  685. color: '#1E90FF'
  686. },
  687. areaStyle: {
  688. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  689. { offset: 0, color: 'rgba(30, 144, 255, 0.6)' },
  690. { offset: 1, color: 'rgba(30, 144, 255, 0.1)' }
  691. ])
  692. },
  693. emphasis: {
  694. focus: 'series'
  695. },
  696. data: [120, 132, 101, 134, 90, 230]
  697. }
  698. ]
  699. }
  700. this.activityChart.setOption(option)
  701. },
  702. initDataVolumeChart() {
  703. this.dataVolumeChart = echarts.init(this.$refs.dataVolumeChart)
  704. const option = {
  705. tooltip: {
  706. trigger: 'axis',
  707. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  708. borderColor: '#1E90FF',
  709. textStyle: {
  710. color: '#fff'
  711. }
  712. },
  713. grid: {
  714. left: '3%',
  715. right: '4%',
  716. bottom: '3%',
  717. containLabel: true
  718. },
  719. xAxis: {
  720. type: 'category',
  721. data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
  722. axisLabel: {
  723. color: '#a3b6c7'
  724. },
  725. axisLine: {
  726. lineStyle: {
  727. color: '#1E90FF'
  728. }
  729. }
  730. },
  731. yAxis: {
  732. type: 'value',
  733. axisLabel: {
  734. color: '#a3b6c7'
  735. },
  736. axisLine: {
  737. lineStyle: {
  738. color: '#1E90FF'
  739. }
  740. },
  741. splitLine: {
  742. lineStyle: {
  743. color: 'rgba(30, 144, 255, 0.2)'
  744. }
  745. }
  746. },
  747. series: [
  748. {
  749. data: [1200, 2000, 1500, 800, 700, 1100, 1300],
  750. type: 'bar',
  751. barWidth: '60%',
  752. itemStyle: {
  753. color: '#FF7F50'
  754. }
  755. }
  756. ]
  757. }
  758. this.dataVolumeChart.setOption(option)
  759. },
  760. initComparisonChart() {
  761. this.comparisonChart = echarts.init(this.$refs.comparisonChart)
  762. const option = {
  763. tooltip: {
  764. trigger: 'axis',
  765. backgroundColor: 'rgba(0, 25, 50, 0.8)',
  766. borderColor: '#1E90FF',
  767. textStyle: {
  768. color: '#fff'
  769. }
  770. },
  771. legend: {
  772. data: ['设备A', '设备B', '设备C'],
  773. textStyle: {
  774. color: '#a3b6c7'
  775. }
  776. },
  777. grid: {
  778. left: '3%',
  779. right: '4%',
  780. bottom: '3%',
  781. containLabel: true
  782. },
  783. xAxis: {
  784. type: 'category',
  785. boundaryGap: false,
  786. data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
  787. axisLabel: {
  788. color: '#a3b6c7'
  789. },
  790. axisLine: {
  791. lineStyle: {
  792. color: '#1E90FF'
  793. }
  794. }
  795. },
  796. yAxis: {
  797. type: 'value',
  798. axisLabel: {
  799. color: '#a3b6c7'
  800. },
  801. axisLine: {
  802. lineStyle: {
  803. color: '#1E90FF'
  804. }
  805. },
  806. splitLine: {
  807. lineStyle: {
  808. color: 'rgba(30, 144, 255, 0.2)'
  809. }
  810. }
  811. },
  812. series: [
  813. {
  814. name: '设备A',
  815. type: 'line',
  816. stack: 'Total',
  817. smooth: true,
  818. lineStyle: {
  819. color: '#1E90FF'
  820. },
  821. areaStyle: {
  822. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  823. { offset: 0, color: 'rgba(30, 144, 255, 0.6)' },
  824. { offset: 1, color: 'rgba(30, 144, 255, 0.1)' }
  825. ])
  826. },
  827. data: [120, 132, 101, 134, 90, 230]
  828. },
  829. {
  830. name: '设备B',
  831. type: 'line',
  832. stack: 'Total',
  833. smooth: true,
  834. lineStyle: {
  835. color: '#52C41A'
  836. },
  837. areaStyle: {
  838. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  839. { offset: 0, color: 'rgba(82, 196, 26, 0.6)' },
  840. { offset: 1, color: 'rgba(82, 196, 26, 0.1)' }
  841. ])
  842. },
  843. data: [220, 182, 191, 234, 290, 330]
  844. },
  845. {
  846. name: '设备C',
  847. type: 'line',
  848. stack: 'Total',
  849. smooth: true,
  850. lineStyle: {
  851. color: '#FF7F50'
  852. },
  853. areaStyle: {
  854. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  855. { offset: 0, color: 'rgba(255, 127, 80, 0.6)' },
  856. { offset: 1, color: 'rgba(255, 127, 80, 0.1)' }
  857. ])
  858. },
  859. data: [150, 232, 201, 154, 190, 330]
  860. }
  861. ]
  862. }
  863. this.comparisonChart.setOption(option)
  864. },
  865. handleResize() {
  866. if (this.deviceChart) this.deviceChart.resize()
  867. if (this.statusChart) this.statusChart.resize()
  868. if (this.activityChart) this.activityChart.resize()
  869. if (this.dataVolumeChart) this.dataVolumeChart.resize()
  870. if (this.comparisonChart) this.comparisonChart.resize()
  871. },
  872. destroyCharts() {
  873. if (this.deviceChart) {
  874. this.deviceChart.dispose()
  875. this.deviceChart = null
  876. }
  877. if (this.statusChart) {
  878. this.statusChart.dispose()
  879. this.statusChart = null
  880. }
  881. if (this.activityChart) {
  882. this.activityChart.dispose()
  883. this.activityChart = null
  884. }
  885. if (this.dataVolumeChart) {
  886. this.dataVolumeChart.dispose()
  887. this.dataVolumeChart = null
  888. }
  889. if (this.comparisonChart) {
  890. this.comparisonChart.dispose()
  891. this.comparisonChart = null
  892. }
  893. }
  894. }
  895. }
  896. </script>
  897. <style lang="less" scoped>
  898. /* 顶部横幅样式 */
  899. .banner {
  900. width: 100%;
  901. // height: calc(100vh - 120px);
  902. height: 552px;
  903. background: url('@static/images/skmh/bg.png');
  904. background-size: cover;
  905. display: flex;
  906. justify-content: right;
  907. align-items: start;
  908. position: relative;
  909. overflow: hidden;
  910. .banner-content {
  911. position: relative;
  912. z-index: 2;
  913. text-align: right;
  914. max-width: 500px;
  915. padding: 0 10%;
  916. justify-content: right;
  917. display: grid;
  918. padding-top: 100px;
  919. }
  920. .banner-title {
  921. font-size: 56px;
  922. font-weight: bold;
  923. // letter-spacing: 0.5rem;
  924. // margin-bottom: 20px;
  925. color: #ffffff;
  926. text-align: right;
  927. text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  928. }
  929. .banner-description {
  930. font-size: 16px;
  931. // line-height: 1.8;
  932. margin: 20px 0px;
  933. text-align: left;
  934. color: rgba(255, 255, 255, 0.9);
  935. }
  936. .enter-button {
  937. padding: 12px 36px;
  938. font-size: 18px;
  939. border-radius: 10px;
  940. background-color: #1890ff;
  941. border: none;
  942. transition: all 0.3s ease;
  943. &:hover {
  944. background-color: #40a9ff;
  945. transform: translateY(-2px);
  946. box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
  947. }
  948. }
  949. }
  950. /* 确保你的自定义样式优先级更高 */
  951. .el-date-picker {
  952. /* 重置为期望的样式 */
  953. color: initial !important; /* 使用 !important 来确保优先级 */
  954. background-color: white !important; /* 确保背景色正确 */
  955. }
  956. .dashboard-container {
  957. // background-color: #0A192F;
  958. // min-height: 100vh;
  959. // color: #fff;
  960. width: 100%;
  961. min-height: 100vh;
  962. background-color: #01012f;
  963. color: #ffffff;
  964. overflow-x: hidden;
  965. }
  966. .server_title {
  967. display: flex;
  968. justify-content: center;
  969. align-items: center;
  970. }
  971. .server_title_text {
  972. width: calc(100vw - 824px);
  973. height: calc(100vh - 120px);
  974. background-color: #1c2631;
  975. color: #fff;
  976. padding: 0 160px 0 60px;
  977. display: flex;
  978. flex-direction: column;
  979. justify-content: center;
  980. overflow: hidden;
  981. &_title {
  982. font-size: 64px;
  983. font-weight: bold;
  984. // letter-spacing: 0.5rem;
  985. }
  986. &_content {
  987. margin-top: 77px;
  988. font-size: 22px;
  989. }
  990. }
  991. /* 平台数据统计 */
  992. .stats-section {
  993. padding: 40px 10%;
  994. margin-top: 100px;
  995. .overview-header {
  996. display: flex;
  997. justify-content: space-between;
  998. align-items: center;
  999. margin-bottom: 30px;
  1000. h2 {
  1001. font-size: 24px;
  1002. color: #fff;
  1003. margin: 0;
  1004. }
  1005. }
  1006. .stats-grid {
  1007. display: flex;
  1008. justify-content: space-between;
  1009. gap: 30px;
  1010. flex-wrap: wrap;
  1011. .stat-card {
  1012. width: 400px;
  1013. height: 150px;
  1014. border-radius: 12px;
  1015. padding: 20px;
  1016. display: flex;
  1017. flex-direction: column;
  1018. justify-content: center;
  1019. align-items: flex-start;
  1020. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  1021. transition: transform 0.3s ease;
  1022. &:hover {
  1023. transform: translateY(-5px);
  1024. }
  1025. .stat-number {
  1026. font-size: 36px;
  1027. font-weight: bold;
  1028. margin-top: 10px;
  1029. margin-bottom: 10px;
  1030. color: #fff;
  1031. }
  1032. .stat-label {
  1033. font-size: 16px;
  1034. color: rgba(255, 255, 255, 0.8);
  1035. width: 100%;
  1036. justify-content: space-between;
  1037. display: flex;
  1038. }
  1039. }
  1040. .card-1 {
  1041. background: linear-gradient(135deg, #3B82F6 0%, #4F46E5 100%);
  1042. }
  1043. .card-2 {
  1044. background: linear-gradient(135deg, #22C55E 0%, #059669 100%);
  1045. }
  1046. .card-3 {
  1047. background: linear-gradient(135deg, #A855F7 0%, #7C3AED 100%);
  1048. }
  1049. }
  1050. }
  1051. /* 数据概览 */
  1052. .data-overview {
  1053. padding: 0 10% 40px;
  1054. .overview-header {
  1055. display: flex;
  1056. justify-content: space-between;
  1057. align-items: center;
  1058. margin-bottom: 30px;
  1059. h2 {
  1060. font-size: 24px;
  1061. color: #fff;
  1062. margin: 0;
  1063. }
  1064. .time-tabs {
  1065. display: flex;
  1066. gap: 20px;
  1067. .tab {
  1068. padding: 8px 16px;
  1069. cursor: pointer;
  1070. color: #a3b6c7;
  1071. border-radius: 20px;
  1072. transition: all 0.3s ease;
  1073. &:hover {
  1074. color: #409eff;
  1075. }
  1076. &.active {
  1077. background-color: #409eff;
  1078. color: #fff;
  1079. }
  1080. }
  1081. }
  1082. }
  1083. .charts-grid {
  1084. display: grid;
  1085. grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  1086. gap: 30px;
  1087. .chart-card {
  1088. background-color: rgba(30, 41, 59, 0.6);
  1089. border-radius: 12px;
  1090. padding: 20px;
  1091. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  1092. .chart-title {
  1093. font-size: 18px;
  1094. color: #fff;
  1095. margin-bottom: 20px;
  1096. text-align: left;
  1097. }
  1098. .chart-container {
  1099. height: 300px;
  1100. width: 100%;
  1101. }
  1102. }
  1103. }
  1104. }
  1105. // 时间筛选
  1106. .time-section{
  1107. padding: 0 0px 10px;
  1108. .time-card {
  1109. // background-color: rgba(30, 41, 59, 0.6);
  1110. // border-radius: 12px;
  1111. padding: 10px;
  1112. // box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  1113. }
  1114. .time-content{
  1115. display: flex;
  1116. justify-content: space-between;
  1117. width: 100%;
  1118. }
  1119. }
  1120. /* 设备综合分析比较 */
  1121. .comparison-section {
  1122. padding: 0 10% 40px;
  1123. .chart-card {
  1124. background-color: rgba(30, 41, 59, 0.6);
  1125. border-radius: 12px;
  1126. padding: 20px;
  1127. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  1128. &.full-width {
  1129. max-width: 100%;
  1130. }
  1131. .chart-title {
  1132. font-size: 18px;
  1133. color: #fff;
  1134. margin-bottom: 20px;
  1135. text-align: left;
  1136. }
  1137. .chart-container {
  1138. height: 400px;
  1139. width: 100%;
  1140. }
  1141. }
  1142. }
  1143. /* 功能演示 */
  1144. .demo-section {
  1145. padding: 0 10% 100px;
  1146. .overview-header {
  1147. display: flex;
  1148. justify-content: space-between;
  1149. align-items: center;
  1150. margin-bottom: 30px;
  1151. h2 {
  1152. font-size: 24px;
  1153. color: #fff;
  1154. margin: 0;
  1155. }
  1156. }
  1157. .demo-grid {
  1158. display: flex;
  1159. justify-content: space-between;
  1160. gap: 30px;
  1161. flex-wrap: wrap;
  1162. .demo-card {
  1163. width: 350px;
  1164. background-color: rgba(30, 41, 59, 0.6);
  1165. border-radius: 12px;
  1166. overflow: hidden;
  1167. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  1168. transition: transform 0.3s ease;
  1169. &:hover {
  1170. transform: translateY(-5px);
  1171. box-shadow: 0 10px 30px rgba(24, 144, 255, 0.3);
  1172. border-color: rgba(24, 144, 255, 0.6);
  1173. }
  1174. .demo-thumbnail {
  1175. height: 200px;
  1176. background-color: #1E90FF;
  1177. position: relative;
  1178. display: flex;
  1179. justify-content: center;
  1180. align-items: center;
  1181. .play-btn {
  1182. width: 60px;
  1183. height: 60px;
  1184. border-radius: 50%;
  1185. background-color: rgba(255, 255, 255, 0.8);
  1186. color: #1E90FF;
  1187. font-size: 30px;
  1188. display: flex;
  1189. justify-content: center;
  1190. align-items: center;
  1191. cursor: pointer;
  1192. transition: all 0.3s ease;
  1193. &:hover {
  1194. background-color: #fff;
  1195. transform: scale(1.1);
  1196. }
  1197. }
  1198. }
  1199. .demo-title {
  1200. padding: 15px;
  1201. color: #fff;
  1202. text-align: left;
  1203. }
  1204. .demo-label {
  1205. font-size: 16px;
  1206. color: #fff;
  1207. padding-bottom: 10px;
  1208. text-align: left;
  1209. }
  1210. .demo-text {
  1211. font-size: 12px;
  1212. color: #fff;
  1213. text-align: left;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. /* 响应式设计 */
  1219. @media (max-width: 768px) {
  1220. .banner {
  1221. padding-right: 5%;
  1222. .banner-content {
  1223. h1 {
  1224. font-size: 32px;
  1225. }
  1226. }
  1227. }
  1228. .stats-section {
  1229. .stats-grid {
  1230. gap: 20px;
  1231. .stat-card {
  1232. width: 100%;
  1233. max-width: 300px;
  1234. }
  1235. }
  1236. }
  1237. .data-overview {
  1238. .overview-header {
  1239. flex-direction: column;
  1240. gap: 20px;
  1241. h2 {
  1242. text-align: center;
  1243. }
  1244. }
  1245. .charts-grid {
  1246. grid-template-columns: 1fr;
  1247. .chart-card {
  1248. .chart-container {
  1249. height: 250px;
  1250. }
  1251. }
  1252. }
  1253. }
  1254. .comparison-section {
  1255. .chart-card {
  1256. .chart-container {
  1257. height: 300px;
  1258. }
  1259. }
  1260. }
  1261. .demo-section {
  1262. .demo-grid {
  1263. gap: 20px;
  1264. .demo-card {
  1265. width: 100%;
  1266. max-width: 350px;
  1267. }
  1268. }
  1269. }
  1270. }
  1271. // 美化表格行悬停效果
  1272. :deep(.el-table__body tr:hover > td) {
  1273. background-color: rgba(24, 144, 255, 0.1) !important;
  1274. }
  1275. // 美化表格边框
  1276. :deep(.el-table__inner-wrapper) {
  1277. border-radius: 6px;
  1278. overflow: hidden;
  1279. }
  1280. :deep(.el-table__cell) {
  1281. border-right: 1px solid rgba(255, 255, 255, 0.05);
  1282. }
  1283. :deep(.el-table__row) {
  1284. border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  1285. }
  1286. // 调整奇偶行背景色,使其更明亮
  1287. :deep(.el-table--striped .el-table__body tr.el-table__row--striped) {
  1288. background-color: rgba(255, 255, 255, 0.02) !important;
  1289. }
  1290. // 调整表格主体背景色
  1291. :deep(.el-table__body) {
  1292. background-color: rgba(0, 0, 0, 0.05);
  1293. }
  1294. :deep(.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell) {
  1295. background-color: rgba(255, 255, 255, 0.02);
  1296. }
  1297. .server_list_box {
  1298. width: 100vw;
  1299. background-color: #00002e;
  1300. display: flex;
  1301. flex-direction: column;
  1302. align-items: center;
  1303. color: #fff;
  1304. position: relative;
  1305. padding-bottom: 100px;
  1306. &_menu {
  1307. position: absolute;
  1308. top: 100px;
  1309. left: 10px;
  1310. z-index: 1;
  1311. }
  1312. &_title {
  1313. margin: 100px 0;
  1314. font-size: 35px;
  1315. font-weight: bold;
  1316. position: relative;
  1317. &::after {
  1318. content: "";
  1319. position: absolute;
  1320. bottom: -12px;
  1321. left: 50%;
  1322. transform: translateX(-50%);
  1323. width: 100px;
  1324. height: 4px;
  1325. background-image: linear-gradient(to right, #1d88f0, #00bfff);
  1326. }
  1327. }
  1328. &_search {
  1329. // margin-top: 100px;
  1330. font-size: 25px;
  1331. display: flex;
  1332. flex-wrap: nowrap;
  1333. align-items: center;
  1334. width: -webkit-fill-available;
  1335. justify-content: center;
  1336. .input-with-select {
  1337. background: #08224a;
  1338. }
  1339. }
  1340. &_table {
  1341. // margin-top: 50px;
  1342. width: 100vw;
  1343. &_item {
  1344. display: flex;
  1345. justify-content: space-evenly;
  1346. align-items: center;
  1347. padding: 50px 0;
  1348. &:nth-child(odd) {
  1349. flex-direction: row;
  1350. }
  1351. &:nth-child(even) {
  1352. flex-direction: row-reverse;
  1353. }
  1354. &_content {
  1355. width: 760px;
  1356. height: 100px;
  1357. display: flex;
  1358. flex-direction: column;
  1359. justify-content: center;
  1360. align-items: center;
  1361. &_title {
  1362. font-size: 35px;
  1363. font-weight: bold;
  1364. color: #fff;
  1365. text-align: left;
  1366. width: 100%;
  1367. }
  1368. &_text {
  1369. margin-top: 35px;
  1370. font-size: 18px;
  1371. text-align: left;
  1372. width: 100%;
  1373. }
  1374. &_button_box {
  1375. display: flex;
  1376. // justify-content: space-evenly;
  1377. text-align: left;
  1378. width: 100%;
  1379. &_item {
  1380. margin-top: 35px;
  1381. font-size: 20px;
  1382. // letter-spacing: 0.2rem;
  1383. // color: #4095e5;
  1384. // border: 1px solid #4095e5;
  1385. background: linear-gradient(97.31deg, #1586FF 12.71%, #0E5AF4 91.55%);
  1386. color: #fff;
  1387. border-radius: 10px;
  1388. padding: 10px 36px;
  1389. cursor: pointer;
  1390. &:hover {
  1391. // background-color: #077ae6;
  1392. background: linear-gradient(97.31deg, #067cfa 12.71%, #0047d4 91.55%);
  1393. color: #fff;
  1394. }
  1395. }
  1396. &_expect {
  1397. margin-top: 35px;
  1398. font-size: 20px;
  1399. // letter-spacing: 0.2rem;
  1400. // color: #4095e5;
  1401. // border: 1px solid #4095e5;
  1402. background: linear-gradient(97.31deg, #2f2f30 12.71%, #202020 91.55%);
  1403. color: #ccc;
  1404. border-radius: 10px;
  1405. padding: 10px 36px;
  1406. cursor: pointer;
  1407. &:hover {
  1408. // background-color: #077ae6;
  1409. background: linear-gradient(97.31deg, #424242 12.71%, #212122 91.55%);
  1410. color: #ccc;
  1411. }
  1412. }
  1413. }
  1414. }
  1415. &_image {
  1416. width: 690px;
  1417. display: flex;
  1418. justify-content: center;
  1419. align-items: center;
  1420. border-radius: 30px;
  1421. overflow: hidden;
  1422. }
  1423. }
  1424. }
  1425. }
  1426. </style>