index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  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" 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. import {snailJobLine} from "@/api/service/timing.js";
  173. const statisticData = ref([
  174. {name: '模型总数', value: 0, color: '#477ACF'},
  175. {name: '当前服务总数', value: 0, color: '#40B0D7'},
  176. {name: '服务在线比率', value: '0%', color: '#2DBEA2'},
  177. {name: '当月热点服务', value: '无', color: '#487ACF'},
  178. {name: '累计调用次数', value: '0', color: '#4BBA9B'},
  179. ])
  180. const todayModelCallCount = ref(0)
  181. const userId = ref(null)
  182. const userOptions = ref([])
  183. listUser().then(res => {
  184. userOptions.value = res.rows.map(item => {
  185. return {
  186. label: item.nickName,
  187. value: item.userId
  188. }
  189. })
  190. })
  191. const top1Ref = ref(null)
  192. const top2Ref = ref(null)
  193. const top3Ref = ref(null)
  194. const top5Ref = ref(null)
  195. const top9Ref = ref(null)
  196. const top10Ref = ref(null)
  197. const top11Ref = ref(null)
  198. const modelTypeCallCount = ref(0)
  199. const dateType = ref('5')
  200. const dateTypeOptions = ref([
  201. {label: '今日', value: '1'},
  202. {label: '近三日', value: '2'},
  203. {label: '近一周', value: '3'},
  204. {label: '近一个月', value: '4'},
  205. {label: '全部', value: '5'},
  206. ])
  207. const task = ref('MONTH')
  208. const taskOptions = ref([
  209. {label: '今日', value: 'DAY'},
  210. {label: '最近一周', value: 'WEEK'},
  211. {label: '最近一月', value: 'MONTH'},
  212. {label: '全年', value: 'YEAR'},
  213. ])
  214. const bt1Ref = ref(null)
  215. const echartMapData = ref([])
  216. const alarmTableData = ref([
  217. {tm: '09-12 11:12', type: '格式异常', modelName: '上海沿海风暴潮预报模型', content: '调用返回异常'},
  218. {tm: '09-11 11:12', type: '请求异常', modelName: '上海沿海风暴潮预报模型', content: '模型连接失败'},
  219. {tm: '09-10 11:12', type: '服务器未响应', modelName: '上海沿海风暴潮预报模型', content: '服务器报错'},
  220. ])
  221. function getTimes(dateType) {
  222. let startTime = null, endTime = null
  223. const date = new Date()
  224. switch (dateType) {
  225. case '1':
  226. startTime = parseTime(new Date(), '{y}-{m}-{d}') + ' 00:00:00'
  227. date.setDate(date.getDate() + 1)
  228. endTime = parseTime(date, '{y}-{m}-{d}') + ' 00:00:00'
  229. break;
  230. case '2':
  231. endTime = parseTime(new Date())
  232. date.setDate(date.getDate() - 3)
  233. startTime = parseTime(date)
  234. break;
  235. case '3':
  236. endTime = parseTime(new Date())
  237. date.setDate(date.getDate() - 7)
  238. startTime = parseTime(date)
  239. break;
  240. case '4':
  241. endTime = parseTime(new Date())
  242. date.setDate(date.getDate() - 30)
  243. startTime = parseTime(date)
  244. break;
  245. default:
  246. }
  247. return {startTime, endTime}
  248. }
  249. function initChartTop1() {
  250. const params = {}
  251. const {startTime, endTime} = getTimes(dateType.value)
  252. params.startTime = startTime
  253. params.endTime = endTime
  254. getModelCallCount(params).then(res => {
  255. let chartData = res.data
  256. todayModelCallCount.value = chartData.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  257. const option = {
  258. tooltip: {
  259. trigger: 'item',
  260. formatter: '{a} <br/>{b} : {c} ({d}%)'
  261. },
  262. grid: {
  263. left: '5%',
  264. right: '5%',
  265. bottom: '0%',
  266. top: '10%',
  267. containLabel: true
  268. },
  269. xAxis: {
  270. // splitLine: {show: false},
  271. axisLabel: {
  272. rotate: 10 // 设置标签旋转45度
  273. },
  274. data: chartData.map(item => item.APPNAME),
  275. },
  276. yAxis: {
  277. type: 'value',
  278. name: '次',
  279. // splitLine: {show: false}
  280. },
  281. series: [
  282. {
  283. data: chartData.map(item => item.TOTAL),
  284. type: 'bar',
  285. itemStyle: {
  286. normal: {
  287. // 这里就可以实现,配置柱状图的颜色
  288. color: function (params) {
  289. const colorList = ['#477ACF', '#40B0D7', '#2DBEA2', '#487ACF', '#4BBA9B', '#529b2e', '#95d475', '#b3e19d', '#d1edc4'];
  290. return colorList[params.dataIndex]
  291. },
  292. }
  293. },
  294. label: {
  295. show: true, // 启用标签
  296. position: 'top' // 位置:顶部(可选 'inside'、'bottom' 等)
  297. }
  298. }
  299. ]
  300. };
  301. top1Ref.value.loadChart(option);
  302. })
  303. }
  304. function initChartTop2() {
  305. getUserModelCallCount(userId.value).then(res => {
  306. let chartData = res.data.map(item => {
  307. return {
  308. name: item.serviceName,
  309. value: item.TOTAL
  310. }
  311. })
  312. const option = {
  313. tooltip: {
  314. trigger: 'item'
  315. },
  316. legend: {
  317. top: '90%',
  318. left: 'center',
  319. textStyle: {
  320. fontSize: 12 // 提示框字体大小
  321. }
  322. },
  323. series: [
  324. {
  325. type: 'pie',
  326. radius: ['50%', '70%'],
  327. avoidLabelOverlap: false,
  328. label: {
  329. show: true,
  330. position: 'outside',
  331. formatter: '{c}',
  332. },
  333. labelLine: {
  334. show: true
  335. },
  336. color: ['#80D0F8', '#3384C2', '#14D3D4', '#69F3C0'],
  337. data: chartData
  338. }
  339. ]
  340. }
  341. top2Ref.value.loadChart(option)
  342. })
  343. }
  344. function initChartTop3() {
  345. const params = {}
  346. const {startTime, endTime} = getTimes(dateType.value)
  347. params.startTime = startTime
  348. params.endTime = endTime
  349. getModelTypeCallCount(params).then(res => {
  350. modelTypeCallCount.value = res.data.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  351. let chartData = res.data.map(item => {
  352. return {
  353. name: item.NAME,
  354. value: item.TOTAL
  355. }
  356. })
  357. const option = {
  358. tooltip: {
  359. trigger: 'item',
  360. formatter: '{a} <br/>{b} : {c} ({d}%)'
  361. },
  362. grid: {
  363. left: '5%',
  364. right: '5%',
  365. bottom: '0%',
  366. top: '10%',
  367. containLabel: true
  368. },
  369. legend: {
  370. type: "scroll",
  371. top: '90%',
  372. left: 'center',
  373. textStyle: {
  374. fontSize: 12 // 提示框字体大小
  375. }
  376. },
  377. series: [
  378. {
  379. name: '调用次数',
  380. type: 'pie',
  381. radius: ['50%', '70%'],
  382. avoidLabelOverlap: false,
  383. label: {
  384. show: true,
  385. fontSize: 14,
  386. position: 'outside',
  387. formatter: '{b} : {c} ({d}%)',
  388. },
  389. labelLine: {
  390. show: true
  391. },
  392. // color: ['#529b2e', '#95d475', '#b3e19d', '#d1edc4'],
  393. data: chartData
  394. }
  395. ]
  396. };
  397. top3Ref.value.loadChart(option)
  398. })
  399. }
  400. function initChartTop9() {
  401. getModelServiceCount().then(res => {
  402. modelTypeCallCount.value = res.data.map(item => item.TOTAL).reduce((acc, current) => acc + current, 0);
  403. let chartData = res.data.map(item => {
  404. return {
  405. name: item.NAME,
  406. value: item.TOTAL
  407. }
  408. })
  409. const option = {
  410. tooltip: {
  411. trigger: 'item',
  412. formatter: '{a} <br/>{b} : {c} ({d}%)'
  413. },
  414. grid: {
  415. left: '5%',
  416. right: '5%',
  417. bottom: '0%',
  418. top: '10%',
  419. containLabel: true
  420. },
  421. legend: {
  422. type: "scroll",
  423. top: '90%',
  424. left: 'center',
  425. textStyle: {
  426. fontSize: 12 // 提示框字体大小
  427. }
  428. },
  429. series: [
  430. {
  431. name: '接口个数',
  432. type: 'pie',
  433. radius: ['50%', '70%'],
  434. avoidLabelOverlap: false,
  435. label: {
  436. show: true,
  437. position: 'outside',
  438. fontSize: 14,
  439. formatter: '{b} : {c} ({d}%)',
  440. },
  441. labelLine: {
  442. show: true
  443. },
  444. // color: ['#529b2e', '#95d475', '#b3e19d', '#d1edc4'],
  445. data: chartData
  446. }
  447. ]
  448. };
  449. top9Ref.value.loadChart(option)
  450. })
  451. }
  452. function initChartTop11() {
  453. const params = {}
  454. const {startTime, endTime} = getTimes(dateType.value)
  455. params.startTime = startTime
  456. params.endTime = endTime
  457. getModelServiceSuccessCount(params).then(res => {
  458. let rawData = [
  459. res.data.map(item => item.SUCCESS),
  460. res.data.map(item => item.FAIL)
  461. ]
  462. const totalData = [];
  463. for (let i = 0; i < rawData[0].length; ++i) {
  464. let sum = 0;
  465. for (let j = 0; j < rawData.length; ++j) {
  466. sum += rawData[j][i];
  467. }
  468. totalData.push(sum);
  469. }
  470. const series = ['成功', '失败'].map((name, sid) => {
  471. return {
  472. name,
  473. type: 'bar',
  474. stack: 'total',
  475. barWidth: '60%',
  476. label: {
  477. show: true,
  478. formatter: (params) => Math.round(params.value * 1000) / 10 + '%'
  479. },
  480. data: rawData[sid].map((d, did) =>
  481. totalData[did] <= 0 ? 0 : d / totalData[did]
  482. )
  483. };
  484. });
  485. const option = {
  486. legend: {
  487. selectedMode: false,
  488. textStyle: {
  489. fontSize: 12 // 提示框字体大小
  490. }
  491. },
  492. tooltip: {
  493. trigger: 'item'
  494. },
  495. grid: {
  496. left: '5%',
  497. right: '5%',
  498. bottom: '0%',
  499. top: '20%',
  500. containLabel: true
  501. },
  502. yAxis: {
  503. type: 'value',
  504. axisLabel: {
  505. interval: 0,
  506. fontSize: 14,
  507. rotate: 10, // 设置标签旋转45度
  508. formatter: (params) => Math.round(params * 100) + '%'
  509. },
  510. },
  511. xAxis: {
  512. type: 'category',
  513. axisLabel: {
  514. interval: 0,
  515. fontSize: 14,
  516. rotate: 10 // 设置标签旋转45度
  517. },
  518. data: res.data.map(item => item.NAME)
  519. },
  520. series
  521. };
  522. top11Ref.value.loadChart(option)
  523. })
  524. }
  525. function initChartBottom1() {
  526. const params = {}
  527. const {startTime, endTime} = getTimes(dateType.value)
  528. params.startTime = startTime
  529. params.endTime = endTime
  530. getModelCallCount(params).then(res => {
  531. const chartData = res.data
  532. const option = {
  533. tooltip: {},
  534. grid: {
  535. left: '5%',
  536. right: '5%',
  537. bottom: '10%',
  538. top: '18%',
  539. containLabel: true
  540. },
  541. xAxis: {
  542. data: chartData.map(item => item.name),
  543. },
  544. yAxis: {
  545. type: 'value',
  546. name: '次',
  547. // splitLine: {show: false}
  548. },
  549. series: [
  550. {
  551. name: 'Access From',
  552. data: chartData.map(item => item.TOTAL),
  553. type: 'bar',
  554. label: {
  555. show: true, // 启用标签
  556. position: 'top' // 位置:顶部(可选 'inside'、'bottom' 等)
  557. }
  558. }
  559. ]
  560. };
  561. bt1Ref.value.loadChart(option)
  562. })
  563. }
  564. function initChartBottom2() {
  565. var chartDom = document.getElementById('bt2');
  566. var myChart = echarts.init(chartDom);
  567. var option;
  568. option = {
  569. radar: {
  570. // shape: 'circle',
  571. indicator: [
  572. {name: 'Sales', max: 6500},
  573. {name: 'Administration', max: 16000},
  574. {name: 'Information Technology', max: 30000},
  575. {name: 'Customer Support', max: 38000},
  576. {name: 'Development', max: 52000},
  577. {name: 'Marketing', max: 25000}
  578. ]
  579. },
  580. series: [
  581. {
  582. name: 'Budget vs spending',
  583. type: 'radar',
  584. data: [
  585. {
  586. value: [4200, 3000, 20000, 35000, 50000, 18000],
  587. name: 'Allocated Budget'
  588. },
  589. {
  590. value: [5000, 14000, 28000, 26000, 42000, 21000],
  591. name: 'Actual Spending'
  592. }
  593. ]
  594. }
  595. ]
  596. };
  597. option && myChart.setOption(option);
  598. }
  599. function initChartTop5() {
  600. snailJobLine({type: task.value}).then(res => {
  601. const chartData = res.data
  602. const option = {
  603. color: ['#2dbea2', '#f56c6c', '#b686d4', '#e6a23c'],
  604. legend: {
  605. textStyle: {
  606. fontSize: 12 // 提示框字体大小
  607. }
  608. },
  609. grid: {
  610. left: '5%',
  611. right: '5%',
  612. bottom: '10%',
  613. top: '15%',
  614. containLabel: true
  615. },
  616. // tooltip: {
  617. // trigger: 'axis'
  618. // },
  619. tooltip: {
  620. trigger: "item",
  621. // formatter: "{a} <br/>{b} : {c}"
  622. },
  623. xAxis: {
  624. type: 'category',
  625. data: chartData.map(item => item.createDt)
  626. },
  627. yAxis: {gridIndex: 0},
  628. series: [
  629. {
  630. type: 'line',
  631. name: '成功',
  632. smooth: true,
  633. seriesLayoutBy: 'row',
  634. emphasis: {focus: 'series'},
  635. data: chartData.map(item => item.success)
  636. },
  637. {
  638. type: 'line',
  639. name: '失败',
  640. smooth: true,
  641. seriesLayoutBy: 'row',
  642. emphasis: {focus: 'series'},
  643. data: chartData.map(item => item.failNum)
  644. },
  645. {
  646. type: 'line',
  647. name: '停止',
  648. smooth: true,
  649. seriesLayoutBy: 'row',
  650. emphasis: {focus: 'series'},
  651. data: chartData.map(item => item.stop)
  652. },
  653. {
  654. type: 'line',
  655. name: '取消',
  656. smooth: true,
  657. seriesLayoutBy: 'row',
  658. emphasis: {focus: 'series'},
  659. data: chartData.map(item => item.cancel)
  660. }
  661. ]
  662. };
  663. top5Ref.value.loadChart(option);
  664. })
  665. }
  666. function initVisitNumberChart(name, data) {
  667. data.sort((a, b) => b.value - a.value)
  668. let d = data.slice(0, 9)
  669. let yAxisData = []
  670. let seriesData = []
  671. for (let i in d) {
  672. yAxisData.push(d[i].name)
  673. seriesData.push(d[i].value)
  674. }
  675. // 初始化echarts实例
  676. let chart = echarts.init(document.getElementById(name))
  677. // 绘制图表
  678. let option = {
  679. tooltip: {
  680. trigger: 'axis',
  681. axisPointer: {
  682. type: 'shadow',
  683. },
  684. },
  685. grid: {
  686. left: '3%',
  687. right: '4%',
  688. bottom: '3%',
  689. top: '3%',
  690. containLabel: true,
  691. },
  692. xAxis: {
  693. type: 'value',
  694. boundaryGap: [0, 0.01],
  695. axisLabel: {
  696. fontSize: 14, // x轴标签字体大小
  697. },
  698. },
  699. yAxis: {
  700. type: 'category',
  701. data: yAxisData,
  702. axisLabel: {
  703. fontSize: 14, // x轴标签字体大小
  704. },
  705. },
  706. series: [
  707. {
  708. name: '访问次数',
  709. type: 'bar',
  710. data: seriesData,
  711. },
  712. ],
  713. }
  714. chart.setOption(option)
  715. }
  716. /** 获取统计数据 */
  717. function initStatisticData() {
  718. getStatisticData().then((r) => {
  719. statisticData.value = r.data
  720. })
  721. }
  722. /** 访问来源追溯 */
  723. function initViewNumByCity() {
  724. getViewNumByCity().then((r) => {
  725. echartMapData.value = r.data
  726. // 初始化地图
  727. initEchartMap('visit_source_chart', echartMapData.value)
  728. initVisitNumberChart('visit_number_chart', echartMapData.value)
  729. })
  730. }
  731. /** 获取模型服务调用次数 */
  732. function getAlarmData() {
  733. getAlarmList().then(res => {
  734. alarmTableData.value = res.data
  735. })
  736. }
  737. function alertTypeConversion(alertType) {
  738. switch (alertType) {
  739. case '1':
  740. return '服务器异常'
  741. case '2':
  742. return '接口异常'
  743. case '3':
  744. return '返回信息异常'
  745. default:
  746. return ''
  747. }
  748. }
  749. onMounted(() => {
  750. initStatisticData()
  751. initChartTop1()
  752. // initChartTop2()
  753. initChartTop3()
  754. initChartTop5()
  755. initChartTop9()
  756. initChartTop11()
  757. // initChartBottom1()
  758. // initChartBottom2()
  759. // initViewNumByCity()
  760. getAlarmData()
  761. });
  762. </script>
  763. <style scoped lang="scss">
  764. .boxShadow {
  765. box-shadow: -8px 0 15px -10px rgba(0, 0, 0, 0.1), /* 左侧阴影 */
  766. 8px 0 15px -10px rgba(0, 0, 0, 0.1); /* 右侧阴影 */
  767. transition: box-shadow 0.3s ease;
  768. }
  769. .gw-statistic-row {
  770. display: flex;
  771. align-content: center;
  772. gap: 10px;
  773. margin-bottom: 10px;
  774. .gw-statistic-body {
  775. box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
  776. width: 100%;
  777. height: 100%;
  778. border-radius: 8px;
  779. background: #fff;
  780. padding: 15px 20px;
  781. .title {
  782. font-weight: bold;
  783. margin: 0;
  784. }
  785. }
  786. }
  787. .chart_container {
  788. width: 100%;
  789. height: 100%;
  790. overflow: hidden;
  791. }
  792. </style>