index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. <template>
  2. <div class="app-container" style="background-color: #F7F7F7;height: 100%;overflow: auto;">
  3. <div class="gw-statistic-row" style="height: 12vh;">
  4. <gw-statistic v-for="item in statisticData" :key="item.name" :name="item.name" :value="item.value"
  5. :color="item.color">
  6. </gw-statistic>
  7. </div>
  8. <div class="gw-statistic-row" style="height: 30vh;">
  9. <gw-card style="width: 50%;">
  10. <template v-slot:title>
  11. <span>模型服务接口统计</span>
  12. </template>
  13. <gw-echart ref="top9Ref"></gw-echart>
  14. </gw-card>
  15. <!-- <gw-card style="width: 33%;">-->
  16. <!-- <template v-slot:title>-->
  17. <!-- <span>模型计算结果统计</span>-->
  18. <!-- </template>-->
  19. <!-- <gw-echart ref="top10Ref"></gw-echart>-->
  20. <!-- </gw-card>-->
  21. <gw-card style="width: 50%;">
  22. <template v-slot:title>
  23. <div style="display: flex;align-items: center;justify-content: space-between;">
  24. <div>
  25. <span>模型计算成功统计</span>
  26. </div>
  27. <el-segmented v-model="dateType" :options="dateTypeOptions" @change="initChartTop11"/>
  28. </div>
  29. </template>
  30. <gw-echart ref="top11Ref"></gw-echart>
  31. </gw-card>
  32. </div>
  33. <div class="gw-statistic-row" style="height: 30vh;">
  34. <gw-card style="width: 50%;">
  35. <template v-slot:title>
  36. <div style="display: flex;align-items: center;justify-content: space-between;">
  37. <div>模型调用次数</div>
  38. <el-segmented v-model="dateType" :options="dateTypeOptions" @change="initChartTop3"/>
  39. </div>
  40. </template>
  41. <gw-echart ref="top3Ref"></gw-echart>
  42. </gw-card>
  43. <gw-card style="width: 50%;">
  44. <template v-slot:title>
  45. <div style="display: flex;align-items: center;justify-content: space-between;">
  46. <div>
  47. <span>应用调用统计</span>
  48. <span style="color: #79bbff;">&nbsp;{{ todayModelCallCount }}&nbsp;</span>
  49. <span>次</span>
  50. </div>
  51. <el-segmented v-model="dateType" :options="dateTypeOptions" @change="initChartTop1"/>
  52. </div>
  53. </template>
  54. <gw-echart ref="top1Ref"></gw-echart>
  55. </gw-card>
  56. <!-- <gw-card style="width: 30%;">-->
  57. <!-- <template v-slot:title>-->
  58. <!-- <div style="display: flex;align-items: center;font-weight: bold;width: 100%;">-->
  59. <!-- <div style="">模型服务调用次数</div>-->
  60. <!-- <div style="width: 50%;margin-left: 20%;">-->
  61. <!-- <el-select v-model="userId" class="m-2" placeholder="选则用户" style="width: 100%;"-->
  62. <!-- @change="initChartTop2">-->
  63. <!-- <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value"/>-->
  64. <!-- </el-select>-->
  65. <!-- </div>-->
  66. <!-- </div>-->
  67. <!-- </template>-->
  68. <!-- <gw-echart ref="top2Ref"></gw-echart>-->
  69. <!-- </gw-card>-->
  70. </div>
  71. <div class="gw-statistic-row" style="height: 30vh;">
  72. <gw-card style="width: 50%;">
  73. <template v-slot:title>
  74. <div style="display: flex;align-items: center;justify-content: space-between;">
  75. <div>
  76. <span>任务统计</span>
  77. </div>
  78. <el-segmented v-model="task" :options="taskOptions" @change="initChartTop5"/>
  79. </div>
  80. </template>
  81. <gw-echart ref="top5Ref"></gw-echart>
  82. </gw-card>
  83. <gw-card style="width: 50%;">
  84. <template v-slot:title>
  85. <div style="display:flex;align-items: center;">
  86. <span style="margin-right: 5px;">报警信息</span>
  87. <el-tag type="danger" effect="dark" size="small">{{ alarmTableData.length }}</el-tag>
  88. </div>
  89. </template>
  90. <el-table stripe :data="alarmTableData" size="small" height="100%">
  91. <el-table-column align="center" width="120" prop="tm" label="报警时间">
  92. <template #default="scope">
  93. {{ scope.row.alertTime ? scope.row.alertTime.substring(5, 16) : '' }}
  94. </template>
  95. </el-table-column>
  96. <el-table-column align="center" width="100" prop="alertType" label="报警类型">
  97. <template #default="scope">
  98. <el-tag size="small" v-if="scope.row.alertType == '1'" type="danger">
  99. {{ alertTypeConversion(scope.row.alertType) }}
  100. </el-tag>
  101. <el-tag size="small" v-else-if="scope.row.alertType == '2'" type="warning">
  102. {{ alertTypeConversion(scope.row.alertType) }}
  103. </el-tag>
  104. <el-tag size="small" v-else type="info">{{ alertTypeConversion(scope.row.alertType) }}</el-tag>
  105. </template>
  106. </el-table-column>
  107. <el-table-column align="center" width="150" prop="modelName" label="模型名称"/>
  108. <el-table-column align="center" prop="alertContent" label="报警内容"/>
  109. </el-table>
  110. </gw-card>
  111. </div>
  112. <!-- <div class="gw-statistic-row" style="height: 30vh;">-->
  113. <!-- <gw-card>-->
  114. <!-- <template v-slot:title>-->
  115. <!-- <div style="width: 100%;display: flex;justify-content: flex-end;">-->
  116. <!-- <el-select-->
  117. <!-- v-model="dateType"-->
  118. <!-- class="m-2"-->
  119. <!-- style="width: 20%;"-->
  120. <!-- @change="initChartBottom1"-->
  121. <!-- <el-option-->
  122. <!-- v-for="item in dateTypeOptions"-->
  123. <!-- :key="item.value"-->
  124. <!-- :label="item.label"-->
  125. <!-- :value="item.value"-->
  126. <!-- />-->
  127. <!-- </el-select>-->
  128. <!-- </div>-->
  129. <!-- </template>-->
  130. <!-- <gw-echart ref="bt1Ref"></gw-echart>-->
  131. <!-- </gw-card>-->
  132. <!-- </div>-->
  133. <!-- <div class="gw-statistic-row" style="height: 40vh;">-->
  134. <!-- <div class="gw-statistic-body">-->
  135. <!-- <el-row :gutter="10" style="height: 100%;">-->
  136. <!-- <el-col :span="15" style="height: 100%;position: relative;">-->
  137. <!-- <div class="title">访问来源追溯</div>-->
  138. <!-- <div style="height: calc(100% - 20px)">-->
  139. <!-- <div id="visit_source_chart" class="chart_container"></div>-->
  140. <!-- </div>-->
  141. <!-- </el-col>-->
  142. <!-- <el-col :span="9" class="visit_number" style="height: 100%;">-->
  143. <!-- <div class="title">访问次数排行</div>-->
  144. <!-- <div style="height: calc(100% - 20px)">-->
  145. <!-- <div id="visit_number_chart" class="chart_container"></div>-->
  146. <!-- </div>-->
  147. <!-- </el-col>-->
  148. <!-- </el-row>-->
  149. <!-- </div>-->
  150. <!-- </div>-->
  151. </div>
  152. </template>
  153. <script setup>
  154. import {onMounted} from 'vue';
  155. import * as echarts from 'echarts';
  156. import GwStatistic from "@/views/monitor/service/GwStatistic.vue";
  157. import {
  158. getModelCallCount,
  159. getModelServiceCount,
  160. getModelServiceSuccessCount,
  161. getModelTypeCallCount,
  162. getStatisticData,
  163. getUserModelCallCount,
  164. getViewNumByCity
  165. } from "@/api/monitor/server.js";
  166. import {initEchartMap} from "@/utils/echarts/chinaMap.js";
  167. import GwCard from "@/views/monitor/service/GwCard.vue";
  168. import GwEchart from "@/components/chart/GwEchart.vue";
  169. import {listUser} from "@/api/system/user.js";
  170. import {parseTime} from "@/utils/ruoyi.js";
  171. import {getAlarmList} from "@/api/service/alarm.js";
  172. const statisticData = ref([
  173. {name: '当前服务总数', value: 0, color: '#477ACF'},
  174. {name: '服务在线比率', value: '0%', color: '#40B0D7'},
  175. {name: '模型服务支撑健康指数', value: '无', color: '#2DBEA2'},
  176. {name: '当月热点服务', value: '无', color: '#487ACF'},
  177. {name: '累计调用次数', value: '0', color: '#4BBA9B'},
  178. ])
  179. const todayModelCallCount = ref(0)
  180. const userId = ref(null)
  181. const userOptions = ref([])
  182. listUser().then(res => {
  183. userOptions.value = res.rows.map(item => {
  184. return {
  185. label: item.nickName,
  186. value: item.userId
  187. }
  188. })
  189. })
  190. const top1Ref = ref(null)
  191. const top2Ref = ref(null)
  192. const top3Ref = ref(null)
  193. const top5Ref = ref(null)
  194. const top9Ref = ref(null)
  195. const top10Ref = ref(null)
  196. const top11Ref = ref(null)
  197. const modelTypeCallCount = ref(0)
  198. const dateType = ref('5')
  199. const dateTypeOptions = ref([
  200. {label: '今日', value: '1'},
  201. {label: '近三日', value: '2'},
  202. {label: '近一周', value: '3'},
  203. {label: '近一个月', value: '4'},
  204. {label: '全部', value: '5'},
  205. ])
  206. const task = ref('1')
  207. const taskOptions = ref([
  208. {label: '日执行量', value: '1'},
  209. {label: '月执行量', value: '2'},
  210. ])
  211. const bt1Ref = ref(null)
  212. const echartMapData = ref([])
  213. const alarmTableData = ref([
  214. {tm: '09-12 11:12', type: '格式异常', modelName: '上海沿海风暴潮预报模型', content: '调用返回异常'},
  215. {tm: '09-11 11:12', type: '请求异常', modelName: '上海沿海风暴潮预报模型', content: '模型连接失败'},
  216. {tm: '09-10 11:12', type: '服务器未响应', modelName: '上海沿海风暴潮预报模型', content: '服务器报错'},
  217. ])
  218. function getTimes(dateType) {
  219. let startTime = null, endTime = null
  220. const date = new Date()
  221. switch (dateType) {
  222. case '1':
  223. startTime = parseTime(new Date(), '{y}-{m}-{d}') + ' 00:00:00'
  224. date.setDate(date.getDate() + 1)
  225. endTime = parseTime(date, '{y}-{m}-{d}') + ' 00:00:00'
  226. break;
  227. case '2':
  228. endTime = parseTime(new Date())
  229. date.setDate(date.getDate() - 3)
  230. startTime = parseTime(date)
  231. break;
  232. case '3':
  233. endTime = parseTime(new Date())
  234. date.setDate(date.getDate() - 7)
  235. startTime = parseTime(date)
  236. break;
  237. case '4':
  238. endTime = parseTime(new Date())
  239. date.setDate(date.getDate() - 30)
  240. startTime = parseTime(date)
  241. break;
  242. default:
  243. }
  244. return {startTime, endTime}
  245. }
  246. function initChartTop1() {
  247. const params = {}
  248. const {startTime, endTime} = getTimes(dateType.value)
  249. params.startTime = startTime
  250. params.endTime = endTime
  251. getModelCallCount(params).then(res => {
  252. let chartData = res.data
  253. todayModelCallCount.value = chartData.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  254. const option = {
  255. tooltip: {
  256. trigger: 'item',
  257. formatter: '{a} <br/>{b} : {c} ({d}%)'
  258. },
  259. grid: {
  260. left: '5%',
  261. right: '5%',
  262. bottom: '0%',
  263. top: '10%',
  264. containLabel: true
  265. },
  266. xAxis: {
  267. // splitLine: {show: false},
  268. axisLabel: {
  269. rotate: 10 // 设置标签旋转45度
  270. },
  271. data: chartData.map(item => item.APPNAME),
  272. },
  273. yAxis: {
  274. type: 'value',
  275. name: '次',
  276. // splitLine: {show: false}
  277. },
  278. series: [
  279. {
  280. data: chartData.map(item => item.TOTAL),
  281. type: 'bar',
  282. itemStyle: {
  283. normal: {
  284. // 这里就可以实现,配置柱状图的颜色
  285. color: function (params) {
  286. const colorList = ['#477ACF', '#40B0D7', '#2DBEA2', '#487ACF', '#4BBA9B', '#529b2e', '#95d475', '#b3e19d', '#d1edc4'];
  287. return colorList[params.dataIndex]
  288. },
  289. }
  290. },
  291. label: {
  292. show: true, // 启用标签
  293. position: 'top' // 位置:顶部(可选 'inside'、'bottom' 等)
  294. }
  295. }
  296. ]
  297. };
  298. top1Ref.value.loadChart(option);
  299. })
  300. }
  301. function initChartTop2() {
  302. getUserModelCallCount(userId.value).then(res => {
  303. let chartData = res.data.map(item => {
  304. return {
  305. name: item.serviceName,
  306. value: item.TOTAL
  307. }
  308. })
  309. const option = {
  310. tooltip: {
  311. trigger: 'item'
  312. },
  313. legend: {
  314. top: '90%',
  315. left: 'center'
  316. },
  317. series: [
  318. {
  319. type: 'pie',
  320. radius: ['50%', '70%'],
  321. avoidLabelOverlap: false,
  322. label: {
  323. show: true,
  324. position: 'outside',
  325. formatter: '{c}',
  326. },
  327. labelLine: {
  328. show: true
  329. },
  330. color: ['#80D0F8', '#3384C2', '#14D3D4', '#69F3C0'],
  331. data: chartData
  332. }
  333. ]
  334. }
  335. top2Ref.value.loadChart(option)
  336. })
  337. }
  338. function initChartTop3() {
  339. const params = {}
  340. const {startTime, endTime} = getTimes(dateType.value)
  341. params.startTime = startTime
  342. params.endTime = endTime
  343. getModelTypeCallCount(params).then(res => {
  344. modelTypeCallCount.value = res.data.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  345. let chartData = res.data.map(item => {
  346. return {
  347. name: item.NAME,
  348. value: item.TOTAL
  349. }
  350. })
  351. const option = {
  352. tooltip: {
  353. trigger: 'item',
  354. formatter: '{a} <br/>{b} : {c} ({d}%)'
  355. },
  356. grid: {
  357. left: '5%',
  358. right: '5%',
  359. bottom: '0%',
  360. top: '10%',
  361. containLabel: true
  362. },
  363. legend: {
  364. type: "scroll",
  365. top: '90%',
  366. left: 'center'
  367. },
  368. series: [
  369. {
  370. name: '调用次数',
  371. type: 'pie',
  372. radius: ['50%', '70%'],
  373. avoidLabelOverlap: false,
  374. label: {
  375. show: true,
  376. position: 'outside',
  377. formatter: '{b} : {c} ({d}%)',
  378. },
  379. labelLine: {
  380. show: true
  381. },
  382. // color: ['#529b2e', '#95d475', '#b3e19d', '#d1edc4'],
  383. data: chartData
  384. }
  385. ]
  386. };
  387. top3Ref.value.loadChart(option)
  388. })
  389. }
  390. function initChartTop9() {
  391. getModelServiceCount().then(res => {
  392. modelTypeCallCount.value = res.data.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  393. let chartData = res.data.map(item => {
  394. return {
  395. name: item.NAME,
  396. value: item.TOTAL
  397. }
  398. })
  399. const option = {
  400. tooltip: {
  401. trigger: 'item',
  402. formatter: '{a} <br/>{b} : {c} ({d}%)'
  403. },
  404. grid: {
  405. left: '5%',
  406. right: '5%',
  407. bottom: '0%',
  408. top: '10%',
  409. containLabel: true
  410. },
  411. legend: {
  412. type: "scroll",
  413. top: '90%',
  414. left: 'center'
  415. },
  416. series: [
  417. {
  418. name: '接口个数',
  419. type: 'pie',
  420. radius: ['50%', '70%'],
  421. avoidLabelOverlap: false,
  422. label: {
  423. show: true,
  424. position: 'outside',
  425. formatter: '{b} : {c} ({d}%)',
  426. },
  427. labelLine: {
  428. show: true
  429. },
  430. // color: ['#529b2e', '#95d475', '#b3e19d', '#d1edc4'],
  431. data: chartData
  432. }
  433. ]
  434. };
  435. top9Ref.value.loadChart(option)
  436. })
  437. }
  438. function initChartTop11() {
  439. const params = {}
  440. const {startTime, endTime} = getTimes(dateType.value)
  441. params.startTime = startTime
  442. params.endTime = endTime
  443. getModelServiceSuccessCount(params).then(res => {
  444. let rawData = [
  445. res.data.map(item => item.SUCCESS),
  446. res.data.map(item => item.FAIL)
  447. ]
  448. const totalData = [];
  449. for (let i = 0; i < rawData[0].length; ++i) {
  450. let sum = 0;
  451. for (let j = 0; j < rawData.length; ++j) {
  452. sum += rawData[j][i];
  453. }
  454. totalData.push(sum);
  455. }
  456. const series = ['成功', '失败'].map((name, sid) => {
  457. return {
  458. name,
  459. type: 'bar',
  460. stack: 'total',
  461. barWidth: '60%',
  462. label: {
  463. show: true,
  464. formatter: (params) => Math.round(params.value * 1000) / 10 + '%'
  465. },
  466. data: rawData[sid].map((d, did) =>
  467. totalData[did] <= 0 ? 0 : d / totalData[did]
  468. )
  469. };
  470. });
  471. const option = {
  472. legend: {
  473. selectedMode: false
  474. },
  475. tooltip: {
  476. trigger: 'item'
  477. },
  478. grid: {
  479. left: '5%',
  480. right: '5%',
  481. bottom: '0%',
  482. top: '20%',
  483. containLabel: true
  484. },
  485. yAxis: {
  486. type: 'value'
  487. },
  488. xAxis: {
  489. type: 'category',
  490. axisLabel: {
  491. interval: 0,
  492. rotate: 10 // 设置标签旋转45度
  493. },
  494. data: res.data.map(item => item.NAME)
  495. },
  496. series
  497. };
  498. top11Ref.value.loadChart(option)
  499. })
  500. }
  501. function initChartBottom1() {
  502. const params = {}
  503. const {startTime, endTime} = getTimes(dateType.value)
  504. params.startTime = startTime
  505. params.endTime = endTime
  506. getModelCallCount(params).then(res => {
  507. const chartData = res.data
  508. const option = {
  509. tooltip: {},
  510. grid: {
  511. left: '5%',
  512. right: '5%',
  513. bottom: '10%',
  514. top: '18%',
  515. containLabel: true
  516. },
  517. xAxis: {
  518. data: chartData.map(item => item.name),
  519. },
  520. yAxis: {
  521. type: 'value',
  522. name: '次',
  523. // splitLine: {show: false}
  524. },
  525. series: [
  526. {
  527. name: 'Access From',
  528. data: chartData.map(item => item.TOTAL),
  529. type: 'bar',
  530. label: {
  531. show: true, // 启用标签
  532. position: 'top' // 位置:顶部(可选 'inside'、'bottom' 等)
  533. }
  534. }
  535. ]
  536. };
  537. bt1Ref.value.loadChart(option)
  538. })
  539. }
  540. function initChartBottom2() {
  541. var chartDom = document.getElementById('bt2');
  542. var myChart = echarts.init(chartDom);
  543. var option;
  544. option = {
  545. radar: {
  546. // shape: 'circle',
  547. indicator: [
  548. {name: 'Sales', max: 6500},
  549. {name: 'Administration', max: 16000},
  550. {name: 'Information Technology', max: 30000},
  551. {name: 'Customer Support', max: 38000},
  552. {name: 'Development', max: 52000},
  553. {name: 'Marketing', max: 25000}
  554. ]
  555. },
  556. series: [
  557. {
  558. name: 'Budget vs spending',
  559. type: 'radar',
  560. data: [
  561. {
  562. value: [4200, 3000, 20000, 35000, 50000, 18000],
  563. name: 'Allocated Budget'
  564. },
  565. {
  566. value: [5000, 14000, 28000, 26000, 42000, 21000],
  567. name: 'Actual Spending'
  568. }
  569. ]
  570. }
  571. ]
  572. };
  573. option && myChart.setOption(option);
  574. }
  575. function initChartTop5() {
  576. const option = {
  577. legend: {},
  578. grid: {
  579. left: '5%',
  580. right: '5%',
  581. bottom: '10%',
  582. top: '15%',
  583. containLabel: true
  584. },
  585. tooltip: {
  586. trigger: 'axis',
  587. showContent: false
  588. },
  589. dataset: {
  590. source: [
  591. ['模型', '09-07', '09-08', '09-09', '09-10', '09-11', '09-12'],
  592. ['上海沿海风暴潮预报模型', 56.5, 82.1, 88.7, 70.1, 53.4, 85.1],
  593. ['马斯京根法', 51.1, 51.4, 55.1, 53.3, 73.8, 68.7],
  594. ['三水源新安江产流模型', 40.1, 62.2, 69.5, 36.4, 45.2, 32.5],
  595. ['上海市中心城区排水系统模型', 25.2, 37.1, 41.2, 18, 33.9, 49.1]
  596. ]
  597. },
  598. xAxis: {type: 'category'},
  599. yAxis: {gridIndex: 0},
  600. series: [
  601. {
  602. type: 'line',
  603. smooth: true,
  604. seriesLayoutBy: 'row',
  605. emphasis: {focus: 'series'}
  606. },
  607. {
  608. type: 'line',
  609. smooth: true,
  610. seriesLayoutBy: 'row',
  611. emphasis: {focus: 'series'}
  612. },
  613. {
  614. type: 'line',
  615. smooth: true,
  616. seriesLayoutBy: 'row',
  617. emphasis: {focus: 'series'}
  618. },
  619. {
  620. type: 'line',
  621. smooth: true,
  622. seriesLayoutBy: 'row',
  623. emphasis: {focus: 'series'}
  624. }
  625. ]
  626. };
  627. top5Ref.value.loadChart(option);
  628. }
  629. function initVisitNumberChart(name, data) {
  630. data.sort((a, b) => b.value - a.value)
  631. let d = data.slice(0, 9)
  632. let yAxisData = []
  633. let seriesData = []
  634. for (let i in d) {
  635. yAxisData.push(d[i].name)
  636. seriesData.push(d[i].value)
  637. }
  638. // 初始化echarts实例
  639. let chart = echarts.init(document.getElementById(name))
  640. // 绘制图表
  641. let option = {
  642. tooltip: {
  643. trigger: 'axis',
  644. axisPointer: {
  645. type: 'shadow',
  646. },
  647. },
  648. grid: {
  649. left: '3%',
  650. right: '4%',
  651. bottom: '3%',
  652. top: '3%',
  653. containLabel: true,
  654. },
  655. xAxis: {
  656. type: 'value',
  657. boundaryGap: [0, 0.01],
  658. },
  659. yAxis: {
  660. type: 'category',
  661. data: yAxisData,
  662. },
  663. series: [
  664. {
  665. name: '访问次数',
  666. type: 'bar',
  667. data: seriesData,
  668. },
  669. ],
  670. }
  671. chart.setOption(option)
  672. }
  673. /** 获取统计数据 */
  674. function initStatisticData() {
  675. getStatisticData().then((r) => {
  676. statisticData.value = r.data
  677. })
  678. }
  679. /** 访问来源追溯 */
  680. function initViewNumByCity() {
  681. getViewNumByCity().then((r) => {
  682. echartMapData.value = r.data
  683. // 初始化地图
  684. initEchartMap('visit_source_chart', echartMapData.value)
  685. initVisitNumberChart('visit_number_chart', echartMapData.value)
  686. })
  687. }
  688. /** 获取模型服务调用次数 */
  689. function getAlarmData() {
  690. getAlarmList().then(res => {
  691. alarmTableData.value = res.data
  692. })
  693. }
  694. function alertTypeConversion(alertType) {
  695. switch (alertType) {
  696. case '1':
  697. return '服务器异常'
  698. case '2':
  699. return '接口异常'
  700. case '3':
  701. return '返回信息异常'
  702. default:
  703. return ''
  704. }
  705. }
  706. onMounted(() => {
  707. initStatisticData()
  708. initChartTop1()
  709. // initChartTop2()
  710. initChartTop3()
  711. initChartTop5()
  712. initChartTop9()
  713. initChartTop11()
  714. // initChartBottom1()
  715. // initChartBottom2()
  716. // initViewNumByCity()
  717. getAlarmData()
  718. });
  719. </script>
  720. <style scoped lang="scss">
  721. .boxShadow {
  722. box-shadow: -8px 0 15px -10px rgba(0, 0, 0, 0.1), /* 左侧阴影 */
  723. 8px 0 15px -10px rgba(0, 0, 0, 0.1); /* 右侧阴影 */
  724. transition: box-shadow 0.3s ease;
  725. }
  726. .gw-statistic-row {
  727. display: flex;
  728. align-content: center;
  729. gap: 10px;
  730. margin-bottom: 10px;
  731. .gw-statistic-body {
  732. box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
  733. width: 100%;
  734. height: 100%;
  735. border-radius: 8px;
  736. background: #fff;
  737. padding: 15px 20px;
  738. .title {
  739. font-weight: bold;
  740. margin: 0;
  741. }
  742. }
  743. }
  744. .chart_container {
  745. width: 100%;
  746. height: 100%;
  747. overflow: hidden;
  748. }
  749. </style>