index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. <template>
  2. <div class="system-user-container">
  3. <div class="flex-row gap-3">
  4. <el-col :xs="24" :sm="12" :md="8" class="marg-b-15">
  5. <el-card class="box-card-meter">
  6. <div class="el-table--enable-row-hover el-table--medium">
  7. <el-row :gutter="30">
  8. <el-col :xs="24" :sm="24" :md="12">
  9. <table cellspacing="0" style="width: 100%">
  10. <tbody>
  11. <tr>
  12. <td>
  13. <div class="cell-card">CPU数: </div>
  14. </td>
  15. <td>
  16. <div class="cell-card">{{ sysInfo.cpuNum }}</div>
  17. </td>
  18. </tr>
  19. <tr>
  20. <td>
  21. <div class="cell-card">核心数: </div>
  22. </td>
  23. <td>
  24. <div class="cell-card">{{ sysInfo.cpuCores }}</div>
  25. </td>
  26. </tr>
  27. <tr>
  28. <td>
  29. <div class="cell-card">使用率:</div>
  30. </td>
  31. <td>
  32. <div class="cell-card">{{ sysInfo.cpuUsed }}%</div>
  33. </td>
  34. </tr>
  35. <tr>
  36. <td>
  37. <div class="cell-card">LA5:</div>
  38. </td>
  39. <td>
  40. <div class="cell-card">{{ sysInfo.cpuAvg5 }}%</div>
  41. </td>
  42. </tr>
  43. <tr>
  44. <td>
  45. <div class="cell-card">LA15:</div>
  46. </td>
  47. <td>
  48. <div class="cell-card">{{ sysInfo.cpuAvg15 }}%</div>
  49. </td>
  50. </tr>
  51. </tbody>
  52. </table>
  53. </el-col>
  54. <el-col :xs="24" :sm="24" :md="12">
  55. <div style="min-height: 180px" ref="chartsWarningRef1"></div>
  56. </el-col>
  57. </el-row>
  58. </div>
  59. </el-card>
  60. </el-col>
  61. <el-col :xs="24" :sm="12" :md="8" class="marg-b-15">
  62. <el-card class="box-card-meter">
  63. <div class="el-table--enable-row-hover el-table--medium">
  64. <el-row :gutter="30">
  65. <el-col :xs="24" :sm="24" :md="12">
  66. <table cellspacing="0" style="width: 100%">
  67. <tbody>
  68. <tr>
  69. <td>
  70. <div class="cell-card">内存总数:</div>
  71. </td>
  72. <td>
  73. <div class="cell-card">{{ memorySizeFormat(sysInfo.memTotal) }}</div>
  74. </td>
  75. </tr>
  76. <tr>
  77. <td>
  78. <div class="cell-card">已使用:</div>
  79. </td>
  80. <td>
  81. <div class="cell-card">{{ memorySizeFormat(sysInfo.memUsed) }}</div>
  82. </td>
  83. </tr>
  84. <tr>
  85. <td>
  86. <div class="cell-card">剩余:</div>
  87. </td>
  88. <td>
  89. <div class="cell-card">{{ memorySizeFormat(sysInfo.memFree) }}</div>
  90. </td>
  91. </tr>
  92. <tr>
  93. <td>
  94. <div class="cell-card">系统使用:</div>
  95. </td>
  96. <td>
  97. <div class="cell-card">{{ memorySizeFormat(sysInfo.goUsed) }}</div>
  98. </td>
  99. </tr>
  100. <tr>
  101. <td>
  102. <div class="cell-card">使用率:</div>
  103. </td>
  104. <td>
  105. <div class="cell-card">{{ sysInfo.memUsage }}%</div>
  106. </td>
  107. </tr>
  108. </tbody>
  109. </table>
  110. </el-col>
  111. <el-col :xs="24" :sm="24" :md="12">
  112. <div style="min-height: 180px" ref="chartsWarningRef2"></div>
  113. </el-col>
  114. </el-row>
  115. </div>
  116. </el-card>
  117. </el-col>
  118. <el-col :xs="24" :sm="12" :md="8" class="marg-b-15">
  119. <el-card class="box-card-meter">
  120. <div class="el-table--enable-row-hover el-table--medium">
  121. <el-row :gutter="30">
  122. <el-col :xs="24" :sm="24" :md="12">
  123. <table cellspacing="0" style="width: 100%">
  124. <tbody>
  125. <tr>
  126. <td>
  127. <div class="cell-card">磁盘容量:</div>
  128. </td>
  129. <td>
  130. <div class="cell-card">{{ memorySizeFormat(sysInfo.diskTotal) }}</div>
  131. </td>
  132. </tr>
  133. <tr>
  134. <td>
  135. <div class="cell-card">已使用:</div>
  136. </td>
  137. <td>
  138. <div class="cell-card">{{ memorySizeFormat(sysInfo.diskUsed) }}</div>
  139. </td>
  140. </tr>
  141. <tr>
  142. <td>
  143. <div class="cell-card">使用率:</div>
  144. </td>
  145. <td>
  146. <div class="cell-card">{{ sysInfo.diskUsedPercent }}%</div>
  147. </td>
  148. </tr>
  149. </tbody>
  150. </table>
  151. </el-col>
  152. <el-col :xs="24" :sm="24" :md="12">
  153. <div style="min-height: 180px" ref="chartsWarningRef3"></div>
  154. </el-col>
  155. </el-row>
  156. </div>
  157. </el-card>
  158. </el-col>
  159. </div>
  160. <div class="flex-row gap-3">
  161. <el-col :xs="24" :sm="12" :md="12" class="marg-b-15">
  162. <el-card class="box-card">
  163. <template #header>
  164. <div class="card-header">
  165. <span>运行资源</span>
  166. </div>
  167. </template>
  168. <div class="el-table--enable-row-hover el-table--medium">
  169. <table cellspacing="0" style="width: 100%">
  170. <tbody>
  171. <tr>
  172. <td>
  173. <div class="cell">操作系统:</div>
  174. </td>
  175. <td>
  176. <div class="cell">{{ sysInfo.sysOsName }}</div>
  177. </td>
  178. </tr>
  179. <tr>
  180. <td>
  181. <div class="cell">系统架构:</div>
  182. </td>
  183. <td>
  184. <div class="cell">{{ sysInfo.sysOsArch }}</div>
  185. </td>
  186. </tr>
  187. <tr>
  188. <td>
  189. <div class="cell">服务器名称:</div>
  190. </td>
  191. <td>
  192. <div class="cell">{{ sysInfo.sysComputerName }}</div>
  193. </td>
  194. </tr>
  195. <tr>
  196. <td>
  197. <div class="cell">服务器IP:</div>
  198. </td>
  199. <td>
  200. <div class="cell">{{ sysInfo.sysComputerIp }}</div>
  201. </td>
  202. </tr>
  203. <tr>
  204. <td>
  205. <div class="cell">Go语言版本</div>
  206. </td>
  207. <td>
  208. <div class="cell">{{ sysInfo.goVersion }}</div>
  209. </td>
  210. </tr>
  211. <tr>
  212. <td>
  213. <div class="cell">启动时间</div>
  214. </td>
  215. <td>
  216. <div class="cell">{{ sysInfo.goStartTime }}</div>
  217. </td>
  218. </tr>
  219. <tr>
  220. <td>
  221. <div class="cell">运行时长:</div>
  222. </td>
  223. <td>
  224. <div class="cell">{{ timeFormat(sysInfo.goRunTime) }}</div>
  225. </td>
  226. </tr>
  227. </tbody>
  228. </table>
  229. </div>
  230. </el-card>
  231. </el-col>
  232. <el-col :xs="24" :sm="12" :md="12" class="marg-b-15">
  233. <el-card class="box-card">
  234. <template #header>
  235. <div class="card-header">
  236. <span>硬盘资源</span>
  237. </div>
  238. </template>
  239. <div class="el-table--enable-row-hover el-table--medium" style="height: 280px; overflow: auto">
  240. <table cellspacing="0" style="width: 100%">
  241. <tbody>
  242. <tr>
  243. <td>
  244. <div class="cell">盘符路径</div>
  245. </td>
  246. <td>
  247. <div class="cell">文件系统</div>
  248. </td>
  249. <td>
  250. <div class="cell">总大小</div>
  251. </td>
  252. <td>
  253. <div class="cell">可用大小</div>
  254. </td>
  255. <td>
  256. <div class="cell">已用大小</div>
  257. </td>
  258. <td>
  259. <div class="cell">已用百分比</div>
  260. </td>
  261. </tr>
  262. <tr v-for="(sysFile, index) in sysInfo.diskList" :key="index">
  263. <td>
  264. <div class="cell">{{ sysFile.path }}</div>
  265. </td>
  266. <td>
  267. <div class="cell">{{ sysFile.fstype }}</div>
  268. </td>
  269. <td>
  270. <div class="cell">{{ memorySizeFormat(sysFile.total) }}</div>
  271. </td>
  272. <td>
  273. <div class="cell">{{ memorySizeFormat(sysFile.free) }}</div>
  274. </td>
  275. <td>
  276. <div class="cell">{{ memorySizeFormat(sysFile.used) }}</div>
  277. </td>
  278. <td>
  279. <div class="cell">{{ sysFile.usedPercent }}%</div>
  280. </td>
  281. </tr>
  282. </tbody>
  283. </table>
  284. </div>
  285. </el-card>
  286. </el-col>
  287. </div>
  288. </div>
  289. </template>
  290. <script lang="ts">
  291. import { toRefs, reactive, onMounted, getCurrentInstance, defineComponent } from 'vue';
  292. import * as echarts from 'echarts';
  293. import 'echarts-wordcloud';
  294. import api from '/@/api/system';
  295. let interval: any = null;
  296. export default defineComponent({
  297. name: 'monitor',
  298. components: {},
  299. setup() {
  300. const { proxy } = getCurrentInstance() as any;
  301. const state: any = reactive({
  302. myCharts: [],
  303. sysInfo: {},
  304. });
  305. let myChart1: any;
  306. let myChart2: any;
  307. let myChart3: any;
  308. function setOptChart1(value: number) {
  309. myChart1.setOption({
  310. series: [
  311. {
  312. data: [
  313. {
  314. value: value,
  315. name: '',//cpu
  316. },
  317. ],
  318. },
  319. ],
  320. });
  321. }
  322. function setOptChart2(value: number) {
  323. myChart2.setOption({
  324. series: [
  325. {
  326. data: [
  327. {
  328. value: value,
  329. name: '',//内存
  330. },
  331. ],
  332. },
  333. ],
  334. });
  335. }
  336. function setOptChart3(value: number) {
  337. myChart3.setOption({
  338. series: [
  339. {
  340. data: [
  341. {
  342. value: value,
  343. name: '',//磁盘
  344. },
  345. ],
  346. },
  347. ],
  348. });
  349. }
  350. //CPU
  351. const initChartCPU = () => {
  352. myChart1 = echarts.init(proxy.$refs.chartsWarningRef1);
  353. const option = {
  354. tooltip: {
  355. formatter: '{a} <br/>{b} : {c}%',
  356. },
  357. series: [
  358. {
  359. type: 'gauge',
  360. name: 'CPU',
  361. radius: '90%', //修改表盘大小
  362. title: {
  363. show: true, //控制表盘title(今日预计用电量)字体是否显示
  364. fontSize: 12, //控制表盘title(今日预计用电量)字体大小
  365. 'color': 'green', //控制表盘title(今日预计用电量)字体颜色
  366. offsetCenter: [-2, '30%'], //设置表盘title(今日预计用电量)位置
  367. },
  368. axisLine: {
  369. show: true,
  370. lineStyle: {
  371. // 属性lineStyle控制线条样式
  372. color: [
  373. [0.3, '#4dabf7'],
  374. [0.6, '#69db7c'],
  375. [0.8, '#ffa94d'],
  376. [1, '#ff6b6b'],
  377. ],
  378. },
  379. },
  380. splitNumber: 5, //分割线之间的刻度
  381. detail: {
  382. valueAnimation: true,
  383. formatter: '{value}%',
  384. textStyle: {
  385. fontSize: 20,
  386. color: 'red',
  387. },
  388. offsetCenter: ['0', '80%'], //表盘数据(30%)位置
  389. },
  390. // data: [
  391. // {
  392. // value: 15,
  393. // name: 'CPU使用率',
  394. // },
  395. // ],
  396. },
  397. ],
  398. };
  399. myChart1.setOption(option);
  400. state.myCharts.push(myChart1);
  401. };
  402. //内存
  403. const initChartRAM = () => {
  404. myChart2 = echarts.init(proxy.$refs.chartsWarningRef2);
  405. const option = {
  406. tooltip: {
  407. formatter: '{a} <br/>{b} : {c}%',
  408. },
  409. series: [
  410. {
  411. type: 'gauge',
  412. name: '内存',
  413. radius: '90%', //修改表盘大小
  414. title: {
  415. show: true, //控制表盘title(今日预计用电量)字体是否显示
  416. fontSize: 12, //控制表盘title(今日预计用电量)字体大小
  417. 'color': 'green', //控制表盘title(今日预计用电量)字体颜色
  418. offsetCenter: [-2, '30%'], //设置表盘title(今日预计用电量)位置
  419. },
  420. axisLine: {
  421. show: true,
  422. lineStyle: {
  423. // 属性lineStyle控制线条样式
  424. color: [
  425. [0.3, '#4dabf7'],
  426. [0.6, '#69db7c'],
  427. [0.8, '#ffa94d'],
  428. [1, '#ff6b6b'],
  429. ],
  430. },
  431. },
  432. splitNumber: 5, //分割线之间的刻度
  433. detail: {
  434. valueAnimation: true,
  435. formatter: '{value}%',
  436. textStyle: {
  437. fontSize: 20,
  438. color: 'red',
  439. },
  440. offsetCenter: ['0', '80%'], //表盘数据(30%)位置
  441. },
  442. // data: [
  443. // {
  444. // value: 30,
  445. // name: '内存使用率',
  446. // },
  447. // ],
  448. },
  449. ],
  450. };
  451. myChart2.setOption(option);
  452. state.myCharts.push(myChart2);
  453. };
  454. //磁盘
  455. const initChartDISK = () => {
  456. myChart3 = echarts.init(proxy.$refs.chartsWarningRef3);
  457. const option = {
  458. tooltip: {
  459. formatter: '{a} <br/>{b} : {c}%',
  460. },
  461. series: [
  462. {
  463. type: 'gauge',
  464. name: '磁盘',
  465. radius: '90%', //修改表盘大小
  466. title: {
  467. show: true, //控制表盘title(今日预计用电量)字体是否显示
  468. fontSize: 12, //控制表盘title(今日预计用电量)字体大小
  469. 'color': 'green', //控制表盘title(今日预计用电量)字体颜色
  470. offsetCenter: [-2, '30%'], //设置表盘title(今日预计用电量)位置
  471. },
  472. axisLine: {
  473. show: true,
  474. lineStyle: {
  475. // 属性lineStyle控制线条样式
  476. color: [
  477. [0.3, '#4dabf7'],
  478. [0.6, '#69db7c'],
  479. [0.8, '#ffa94d'],
  480. [1, '#ff6b6b'],
  481. ],
  482. },
  483. },
  484. splitNumber: 5, //分割线之间的刻度
  485. detail: {
  486. valueAnimation: true,
  487. formatter: '{value}%',
  488. textStyle: {
  489. fontSize: 20,
  490. color: 'red',
  491. },
  492. offsetCenter: ['0', '80%'], //表盘数据(30%)位置
  493. },
  494. // data: [
  495. // {
  496. // value: 30,
  497. // name: '内存使用率',
  498. // },
  499. // ],
  500. },
  501. ],
  502. };
  503. myChart3.setOption(option);
  504. state.myCharts.push(myChart3);
  505. };
  506. // 页面加载时
  507. onMounted(() => {
  508. initChartCPU();
  509. initChartRAM();
  510. initChartDISK();
  511. });
  512. function startWs() {
  513. // ws = null;
  514. // ws = new WebSocket(import.meta.env.VITE_WS_URL + '/monitorServer/ws');
  515. // ws.onopen = () => {};
  516. // ws.onmessage = ({ data: dataStr }) => {
  517. // const data = JSON.parse(dataStr);
  518. // state.sysInfo = data;
  519. // setOptChart1(data.cpuUsed);
  520. // setOptChart2(data.memUsage);
  521. // setOptChart3(data.diskUsedPercent);
  522. // };
  523. const es = new EventSource(import.meta.env.VITE_SERVER_URL+"/subscribe/sysenv");
  524. es.addEventListener("host", displayHost);
  525. es.addEventListener("mem", displayMem);
  526. es.addEventListener("cpu", displayCpu);
  527. es.addEventListener("sysLoad", displaySysLoad);
  528. es.addEventListener("disk", displayDisk);
  529. }
  530. startWs();
  531. function displayHost(event: { data: any; }) {
  532. const data=JSON.parse(event.data);
  533. state.sysInfo.sysOsName = data.os
  534. state.sysInfo.sysOsArch = data.kernelArch
  535. state.sysInfo.sysComputerName = data.hostname
  536. state.sysInfo.goStartTime = data.bootTime
  537. state.sysInfo.goRunTime = data.uptime
  538. }
  539. function displayMem(event: { data: any; }) {
  540. const data=JSON.parse(event.data);
  541. setOptChart2(data.usedPercent.toFixed(2));
  542. state.sysInfo.memTotal = data.total
  543. state.sysInfo.memUsed = data.used
  544. state.sysInfo.memFree = data.free
  545. state.sysInfo.goUsed = data.goUsed
  546. state.sysInfo.memUsage = data.usedPercent.toFixed(2)
  547. }
  548. function displayCpu(event: { data: any; }) {
  549. const data=JSON.parse(event.data);
  550. state.sysInfo.cpuNum = data.Number
  551. state.sysInfo.cpuCores = data.Cores
  552. state.sysInfo.cpuUsed = data.UsedPercent[0].toFixed(2)
  553. setOptChart1(data.UsedPercent[0].toFixed(2));
  554. };
  555. function displaySysLoad(event: { data: any; }) {
  556. const data=JSON.parse(event.data)
  557. state.sysInfo.cpuAvg5 = data.load5.toFixed(2)
  558. state.sysInfo.cpuAvg15 = data.load15.toFixed(2)
  559. };
  560. function displayDisk(event: { data: any; }) {
  561. const data=JSON.parse(event.data)
  562. state.sysInfo.diskTotal = data.total
  563. state.sysInfo.diskUsed = data.used
  564. state.sysInfo.diskUsedPercent = data.usedPercent.toFixed(2)
  565. setOptChart3(data.usedPercent.toFixed(2));
  566. };
  567. // function getSystemInfo() {
  568. // api.getSysInfo().then((res: any) => {
  569. // state.sysInfo = res;
  570. // setOptChart1(res.cpuUsed);
  571. // setOptChart2(res.memUsage);
  572. // setOptChart3(res.diskUsedPercent);
  573. //
  574. // });
  575. // }
  576. return {
  577. ...toRefs(state),
  578. // getSystemInfo,
  579. setOptChart1,
  580. setOptChart2,
  581. setOptChart3,
  582. // ws,
  583. };
  584. },
  585. created() {
  586. // this.getSystemInfo();
  587. // if (interval === null) {
  588. // interval = setInterval(() => {
  589. // this.getSystemInfo();
  590. // }, 5000);
  591. // }
  592. },
  593. unmounted() {
  594. // if (this.ws) {
  595. // (this.ws as WebSocket).close();
  596. // }
  597. if (interval) {
  598. clearInterval(interval);
  599. interval = null;
  600. }
  601. },
  602. data() {
  603. return {};
  604. },
  605. methods: {
  606. memorySizeFormat(size: any) {
  607. size = parseFloat(size);
  608. let rank = 0;
  609. let rankchar = 'Bytes';
  610. while (size > 1024 && rankchar != 'TB') {
  611. size = size / 1024;
  612. rank++;
  613. if (rank == 1) {
  614. rankchar = 'KB';
  615. } else if (rank == 2) {
  616. rankchar = 'MB';
  617. } else if (rank == 3) {
  618. rankchar = 'GB';
  619. } else if (rank == 4) {
  620. rankchar = 'TB';
  621. }
  622. }
  623. return size.toFixed(2) + ' ' + rankchar;
  624. },
  625. timeFormat(second: any) {
  626. second = parseFloat(second);
  627. let rank = 0;
  628. let rankchar = '秒';
  629. while ((second > 60 && rankchar != '小时' && rankchar != '天') || (second > 24 && rankchar == '小时')) {
  630. if (rankchar == '小时') {
  631. second = second / 24;
  632. } else {
  633. second = second / 60;
  634. }
  635. rank++;
  636. if (rank == 1) {
  637. rankchar = '分';
  638. } else if (rank == 2) {
  639. rankchar = '小时';
  640. } else if (rank == 3) {
  641. rankchar = '天';
  642. }
  643. }
  644. return second.toFixed(2) + ' ' + rankchar;
  645. },
  646. },
  647. });
  648. </script>
  649. <style scoped lang="scss">
  650. .el-card {
  651. height: 300px;
  652. overflow-y: auto;
  653. }
  654. .marg-b-15 {
  655. margin-bottom: 15px;
  656. }
  657. .cell {
  658. box-sizing: border-box;
  659. overflow: hidden;
  660. text-overflow: ellipsis;
  661. white-space: normal;
  662. word-break: break-all;
  663. line-height: 36px;
  664. padding-left: 10px;
  665. padding-right: 10px;
  666. }
  667. .cell-card {
  668. box-sizing: border-box;
  669. overflow: hidden;
  670. text-overflow: ellipsis;
  671. white-space: normal;
  672. word-break: break-all;
  673. line-height: 36px;
  674. }
  675. .box-card {
  676. min-height: 380px;
  677. }
  678. .box-card-meter{
  679. height: 230px;
  680. min-height: 180px;
  681. }
  682. </style>