1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005 |
- <template>
- <div class="bootstrap-scope">
- <div class="widget-chart">
- <!-- 主容器 -->
- <div class="pcoded-main-container">
- <div class="pcoded-wrapper">
- <div class="pcoded-content">
- <div class="pcoded-inner-content">
- <div class="main-body">
- <div class="page-wrapper">
- <!-- 主要内容区域 -->
- <div class="row">
- <!-- 云计算存储卡片 -->
- <!-- <div class="col-xl-4 col-md-12">
- <div class="card">
- <div class="card-body pb-0">
- <div class="row">
- <div class="col-auto">
- <h6>云计算</h6>
- </div>
- </div>
- <div class="row mt-2">
- <div class="col-auto">
- <span class="d-block">
- 存储
- </span>
- <h6 class="ms-3 mt-1">10.5 GB</h6>
- </div>
- <div class="col">
- <span class="d-block">
- 带宽
- </span>
- <h6 class="ms-3 mt-1">50 GB</h6>
- </div>
- </div>
- </div>
- <div ref="storageChart" style="height: 100px"></div>
- </div>
- </div> -->
- <div class="col-xl-6">
- <div class="card">
- <div class="card-header">
- <div class="row">
- <div class="col">
- <h5>C/GPU使用率</h5>
- </div>
- <!-- <div class="col-auto text-end">
- <span>This Month</span>
- </div> -->
- </div>
- </div>
- <div class="card-body">
- <div class="row mb-2">
- <div class="col-auto">
- <h2 class="m-0">
- <strong>{{ cpuValue + "%"
- }}</strong>
- <i
- class="feather icon-arrow-up text-c-green"
- ></i>
- </h2>
- <span>CPU使用率</span>
- </div>
- <div class="col-auto">
- <h2 class="m-0">
- <strong>{{ GpuValue + "%"
- }}</strong><i
- class="feather icon-arrow-down text-c-red"
- ></i>
- </h2>
- <span>GPU使用率</span>
- </div>
- <!-- <div class="col">
- <h4 class="m-0">
- 40.05%<i
- class="feather icon-arrow-up text-c-green"
- ></i>
- </h4>
- <span>Bounce Rate</span>
- </div> -->
- </div>
- <div
- ref="siteVisitorChart"
- style="height: 245px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <div class="col-xl-3">
- <div class="row">
- <!-- GPU温度 -->
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div
- class="row"
- style="display: flex; align-items: center"
- >
- <div class="col-auto">
- <h6>温度监控</h6>
- </div>
- </div>
- <div class="row">
- <!-- CPU温度 -->
- <div class="col-6">
- <h2 class="mb-0" style="margin-top: 20px !important">
- {{ cpuTemperature }}°C
- </h2>
- <span>CPU温度</span>
- <div class="temperature-select-wrapper" style="margin-top: 15px">
- <select
- class="temperature-select"
- :value="Math.round(cpuTemperature / temperatureData.cpu.critical)"
- disabled
- >
- <option v-for="n in 24" :key="`cpu-${n}`" :value="n"></option>
- </select>
- <div
- class="temperature-progress"
- :style="{
- width: `${(cpuTemperature / temperatureData.cpu.critical) * 100}%`,
- backgroundColor: getTemperatureColor(cpuTemperature, 'cpu'),
- }"
- ></div>
- </div>
- </div>
- <!-- GPU温度 -->
- <div class="col-6">
- <h2 class="mb-0" style="margin-top: 20px !important">
- {{ gpuTemperature }}°C
- </h2>
- <span>GPU温度</span>
- <div class="temperature-select-wrapper" style="margin-top: 15px">
- <select
- class="temperature-select"
- :value="Math.round(gpuTemperature / temperatureData.gpu.critical)"
- disabled
- >
- <option v-for="n in 24" :key="`gpu-${n}`" :value="n"></option>
- </select>
- <div
- class="temperature-progress"
- :style="{
- width: `${(gpuTemperature / temperatureData.gpu.critical) * 100}%`,
- backgroundColor: getTemperatureColor(gpuTemperature, 'gpu'),
- }"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 磁盘信息 -->
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div class="row">
- <div class="col-6">
- <h6>磁盘信息</h6>
- </div>
- </div>
- <div class="row">
- <div class="col-12">
- <div
- ref="diskChart"
- style="height: 110px"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <h6>Traffic tracker</h6>
- <div class="row mt-2">
- <div class="col-6">
- <span class="d-block text-uppercase"
- >Inbound</span
- >
- <h3 class="mt-1">180 GB</h3>
- <div
- ref="transactions1"
- style="
- height: 50px;
- width: 100%;
- margin: 0 auto;
- "
- ></div>
- </div>
- <div class="col-6">
- <span class="d-block text-uppercase"
- >Outbound</span
- >
- <h3 class="mt-1">597.1 GB</h3>
- <div
- ref="transactions2"
- style="
- height: 50px;
- width: 100%;
- margin: 0 auto;
- "
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div class="row d-flex align-items-center">
- <div class="col-6 p-r-0">
- <span class="d-block mb-1"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #a367dc"
- ></i
- >Desktop [66.6%]</span
- >
- <span class="d-block mb-1"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #67b7dc"
- ></i
- >Mobile [29.7%]</span
- >
- <span class="d-block"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #6771dc"
- ></i
- >Tablet [38.6%]</span
- >
- </div>
- <div class="col-6">
- <div
- ref="deviceChart"
- id="device-chart"
- style="height: 140px"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div> -->
- </div>
- </div>
- <div class="col-xl-3">
- <div class="row">
- <!-- 支持分析卡片 -->
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div class="row">
- <div class="col-6">
- <h6>Memory</h6>
- </div>
- <!-- <div class="col">
- <div class="dropdown float-end">
- <a
- class="dropdown-toggle text-c-blue"
- href="#"
- data-bs-toggle="dropdown"
- >
- 最近5个月
- </a>
- <div class="dropdown-menu dropdown-menu-end">
- <a class="dropdown-item" href="#">1周</a>
- <a class="dropdown-item" href="#">2年</a>
- <a class="dropdown-item" href="#">3个月</a>
- </div>
- </div>
- </div> -->
- </div>
- <div class="row">
- <div class="col-6">
- <h2 class="mt-2 mb-0">
- {{ currentPercentage.total + "GB" }}
- </h2>
- <span>总内存</span>
- <h6 class="mb-0 mt-3">
- 空闲内存:
- <span class="text-primary">{{
- currentPercentage.available + "GB"
- }}</span>
- </h6>
- <h6>
- 已使用:
- <span class="text-danger">{{
- currentPercentage.used + "GB"
- }}</span>
- </h6>
- </div>
- <div class="col">
- <!-- 支持工单完成图表 -->
- <div
- ref="hdComplitedTicket"
- style="height: 100px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 知识库统计卡片 -->
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div
- class="row"
- style="display: flex; align-items: center"
- >
- <div class="col-auto">
- <h6>知识库统计</h6>
- </div>
- <div
- class="col"
- style="
- display: flex;
- justify-content: flex-end;
- "
- >
- <el-select
- v-model="kenValue"
- @change="kenChange"
- placeholder="请选择"
- >
- <el-option
- v-for="item in kenList"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- >
- </el-option>
- </el-select>
- <!-- <div class="dropdown float-end">
- <a
- class="dropdown-toggle text-c-blue"
- href="#"
- data-bs-toggle="dropdown"
- >
- 最近30天
- </a>
- <div
- class="dropdown-menu dropdown-menu-end"
- >
- <a class="dropdown-item" href="#">1周</a>
- <a class="dropdown-item" href="#">2年</a>
- <a class="dropdown-item" href="#"
- >3个月</a
- >
- </div>
- </div> -->
- </div>
- </div>
- <div class="row">
- <div class="col-6 p-r-0">
- <template
- v-for="(count, type) in fileTypeCounts"
- >
- <h6
- :key="type"
- class="my-3"
- v-if="
- ['pdf', 'docx', 'xlsx'].includes(
- type.toLowerCase()
- )
- "
- >
- <i
- class="feather"
- :class="getFileTypeIcon(type)"
- style="
- font-size: 20px;
- margin-right: 8px;
- "
- :style="{
- color: getFileTypeColor(type),
- }"
- ></i>
- {{ type.toUpperCase() }}
- <span class="ms-2"> </span>
- <span
- :class="getChangeClass(type)"
- class="ms-2 f-14"
- >
- <i
- class="feather"
- :class="getChangeIcon(type)"
- ></i>
- {{ count }}
- <!-- {{ getChangePercentage(type) }} -->
- </span>
- </h6>
- </template>
- </div>
- <div class="col-6">
- <!-- 设备占比饼图 -->
- <div
- ref="chartPercent"
- style="height: 100px"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <h6>Traffic tracker</h6>
- <div class="row mt-2">
- <div class="col-6">
- <span class="d-block text-uppercase"
- >Inbound</span
- >
- <h3 class="mt-1">180 GB</h3>
- <div
- ref="transactions1"
- style="
- height: 50px;
- width: 100%;
- margin: 0 auto;
- "
- ></div>
- </div>
- <div class="col-6">
- <span class="d-block text-uppercase"
- >Outbound</span
- >
- <h3 class="mt-1">597.1 GB</h3>
- <div
- ref="transactions2"
- style="
- height: 50px;
- width: 100%;
- margin: 0 auto;
- "
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="col-xl-12 col-md-6">
- <div class="card">
- <div class="card-body">
- <div class="row d-flex align-items-center">
- <div class="col-6 p-r-0">
- <span class="d-block mb-1"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #a367dc"
- ></i
- >Desktop [66.6%]</span
- >
- <span class="d-block mb-1"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #67b7dc"
- ></i
- >Mobile [29.7%]</span
- >
- <span class="d-block"
- ><i
- class="fas fa-circle f-10 m-r-5"
- style="color: #6771dc"
- ></i
- >Tablet [38.6%]</span
- >
- </div>
- <div class="col-6">
- <div
- ref="deviceChart"
- id="device-chart"
- style="height: 140px"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div> -->
- </div>
- </div>
- <!-- 其他统计卡片组 -->
- <div class="col-sm-12">
- <div class="row g-0">
- <!-- 交易量卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>知识库数量</span>
- <h2><strong>{{ kenList.length }}</strong></h2>
- <div
- ref="real4Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <!-- 当前库存卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>文件已解析数量</span>
- <h2><strong>{{ docList.run_3 }}</strong></h2>
- <div
- ref="real6Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <!-- 跳出率卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>文件未解析数量</span>
- <h2><strong>{{ docList.run_0 }}</strong></h2>
- <div
- ref="real1Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <!-- 订单总额卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>文档数量</span>
- <h2><strong>{{ docTotal }}</strong></h2>
- <div
- ref="real5Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <!-- 收入卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>模版数量</span>
- <h2><strong>{{ temTotal }}</strong></h2>
- <div
- ref="real2Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- <!-- 新购买卡片 -->
- <div class="col-md-4 col-xl-2 col-sm-6">
- <div class="card">
- <div class="card-body">
- <span>模块数量</span>
- <h2><strong>{{ pageTotal }}</strong></h2>
- <div
- ref="real3Chart"
- style="height: 20px; width: 100%"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- import * as am4core from "@amcharts/amcharts4/core";
- import * as am4charts from "@amcharts/amcharts4/charts";
- import am4themes_animated from "@amcharts/amcharts4/themes/animated";
- import BootstrapWrapper from "@/components/BootstrapWrapper/index.vue";
- import { searchlistDoc, searchList } from "@/api/document";
- import { pageTemplate } from "@/api/template";
- import {
- listBuckets,
- structure_count,
- GET_Rbq,
- gpu_info,
- doc_status,
- } from "@/api/knowledge";
- export default {
- name: "WidgetChart",
- components: {
- BootstrapWrapper,
- },
- data() {
- return {
- charts: {
- diskChart: null,
- // 其他图表...
- },
- chartData: {},
- currentPercentage: {},
- cpuValue: 0,
- GpuValue: 0,
- kenValue: null, //知识库
- kenList: [],
- previousCounts: {}, // 用于存储上一次的数量,计算变化率
- fileTypeCounts: {}, // 用于存储上一次的数量,计算变化率
- docTotal: 0,
- temTotal: 0,
- pageTotal: 0,
- docList: {},
- chartUpdateInterval: null, // 添加新的数据属性用于存储定时器
- isPageVisible: !document.hidden, // 添加新的数据属性
- cpuTemperature: 0,
- gpuTemperature: 0,
- temperatureData: {
- cpu: {
- current: 0,
- high: 95, // 默认CPU高温阈值
- critical: 100 // 默认CPU临界温度
- },
- gpu: {
- current: 0,
- high: 85, // 默认GPU高温阈值
- critical: 90 // 默认GPU临界温度
- }
- },
- isCurrentPage: false, // 添加标记当前页面状态的变量
- };
- },
- watch: {
- $route: {
- immediate: true,
- handler(newRoute) {
- const isDashboard = newRoute.path === "/dashboard";
- if (isDashboard && !this.isCurrentPage) {
- // 进入dashboard页面
- this.isCurrentPage = true;
- this.initWebSocket();
- } else if (!isDashboard && this.isCurrentPage) {
- // 离开dashboard页面
- this.isCurrentPage = false;
- this.closeWebSocket();
- }
- },
- },
- // 监听页面可见性
- isPageVisible: {
- immediate: true,
- handler(newValue) {
- console.log(newValue);
- if (newValue) {
- // 页面变为可见时
- console.log("Page became visible");
- this.initSiteVisitorChart();
- } else {
- // 页面变为不可见时
- console.log("Page became hidden");
- this.cleanupCharts();
- }
- },
- },
- },
- mounted() {
- document.addEventListener("visibilitychange", this.handleVisibilityChange);
- // 使用动画主题
- am4core.useTheme(am4themes_animated);
- this.init();
- // 初始化各个图表
- this.initHdComplitedTicket();
- this.initChartPercent();
- this.initStorageChart();
- this.initRealTimeCharts();
- this.initSiteVisitorChart(); // 添加这行
- this.initTransactionCharts();
- this.initDeviceChart(); // 添加这行
- this.initDiskChart();
-
- },
- // 修改生命周期钩子
- activated() {
- console.log(1123);
- // 当组件被激活时重新初始化图表
- this.initSiteVisitorChart();
- },
- deactivated() {
- // 当组件被停用时清理资源
- this.cleanupCharts();
- },
- beforeDestroy() {
- // 组件销毁前清理所有资源
- this.cleanupCharts();
- this.closeWebSocket();
- // 清理其他图表实例
- Object.values(this.charts).forEach((chart) => {
- if (chart) {
- if (typeof chart.dispose === "function") {
- chart.dispose();
- } else if (typeof chart === "number") {
- clearInterval(chart);
- }
- }
- });
- },
- methods: {
- // 处理页面可见性变化
- handleVisibilityChange() {
- this.isPageVisible = !document.hidden;
- },
- closeWebSocket() {
- if (this.ws) {
- this.ws.close();
- this.ws = null;
- }
- // 清除重连定时器
- if (this.wsReconnectTimer) {
- clearTimeout(this.wsReconnectTimer);
- this.wsReconnectTimer = null;
- }
- },
- handleRouteChange() {
- if (this.isOnDashboard) {
- this.initWebSocket(); // 初始化 WebSocket
- } else {
- this.closeWebSocket();
- }
- },
- /* websocket 请求 */
- initWebSocket() {
- // 如果不是当前页面或已经存在连接,则不建立新连接
- if (!this.isCurrentPage || this.ws) {
- return;
- }
- const wsUrl = process.env.VUE_APP_BASE_API.replace(/^http/, "ws");
- this.ws = new WebSocket(`${wsUrl}/ws/monitoring`);
- this.ws.onopen = () => {
- console.log("WebSocket连接成功");
- };
- this.ws.onmessage = (event) => {
- if (!this.isCurrentPage) return; // 如果不是当前页面,不处理消息
- try {
- const data = JSON.parse(event.data);
- // 检查数据结构是否完整
- /* console.log("gpuTemperature", this.gpuTemperature); */
- if (
- data &&
- data.data &&
- data.data.system &&
- data.data.system.cpu &&
- data.data.system.cpu.memory
- ) {
- // 更新图表数据
- this.chartData = data;
- this.cpuValue = data.data.system.cpu.total_usage;
- this.GpuValue = data.data.system.gpu.devices[0]?.power || 0;
- // 更新 GPU 温度
- /* this.gpuTemperature =
- data.data.system.gpu.devices[0]?.temperature || 0; */
- this.currentPercentage = data.data.system.cpu.memory;
- this.handleWebSocketMessage(data)
- } else {
- console.warn("Received incomplete data structure:", data);
- }
- } catch (error) {
- console.error("Error processing WebSocket message:", error);
- }
- };
- this.ws.onclose = () => {
- console.log("WebSocket连接关闭");
- // 只在当前页面时进行重连
- if (this.isCurrentPage && !this.wsReconnectTimer) {
- this.wsReconnectTimer = setTimeout(() => {
- this.initWebSocket();
- }, 3000);
- }
- };
- this.ws.onerror = (error) => {
- console.error("WebSocket连接错误:", error);
- // 连接错误时关闭连接,触发重连
- this.closeWebSocket();
- };
- },
- // 添加一个用于检查 WebSocket 连接状态的方法
- checkWebSocketConnection() {
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
- console.log("WebSocket disconnected, attempting to reconnect...");
- this.initWebSocket();
- }
- },
- // 初始化支持工单完成率图表
- initHdComplitedTicket() {
- const chart = am4core.create(
- this.$refs.hdComplitedTicket,
- am4charts.GaugeChart
- );
- chart.logo.disabled = true;
- chart.innerRadius = am4core.percent(82);
- // 修改主配置
- const axis = chart.xAxes.push(new am4charts.ValueAxis());
- axis.min = 0;
- axis.max = 100;
- axis.strictMinMax = true;
- // 设置固定的半径
- axis.renderer.radius = 80; // 使用固定像素值而不是百分比
- axis.renderer.inside = true;
- axis.renderer.line.strokeOpacity = 0;
- axis.renderer.ticks.template.strokeOpacity = 1;
- axis.renderer.ticks.template.length = 10;
- axis.renderer.grid.template.disabled = true;
- axis.renderer.labels.template.radius = 40;
- axis.renderer.labels.template.adapter.add("text", () => "");
- // 修改第二轴配置
- const axis2 = chart.xAxes.push(new am4charts.ValueAxis());
- axis2.min = 0;
- axis2.max = 100;
- // 设置固定的内半径
- axis2.renderer.innerRadius = 65; // 使用固定像素值
- axis2.renderer.radius = 80; // 设置固定的外半径
- axis2.strictMinMax = true;
- axis2.renderer.labels.template.disabled = true;
- axis2.renderer.ticks.template.disabled = true;
- axis2.renderer.grid.template.disabled = true;
- // 配置填充范围
- const range0 = axis2.axisRanges.create();
- range0.value = 0;
- range0.endValue = 50;
- range0.axisFill.fillOpacity = 1;
- range0.axisFill.fill = am4core.color("#19BCBF");
- const range1 = axis2.axisRanges.create();
- range1.value = 50;
- range1.endValue = 100;
- range1.axisFill.fillOpacity = 1;
- range1.axisFill.fill = am4core.color("#eff3f6");
- // 添加标签
- const label = chart.radarContainer.createChild(am4core.Label);
- label.isMeasured = false;
- label.fontSize = 18;
- label.x = am4core.percent(50);
- label.y = am4core.percent(100);
- label.horizontalCenter = "middle";
- label.verticalCenter = "bottom";
- label.text = "50%";
- const label2 = chart.radarContainer.createChild(am4core.Label);
- label2.isMeasured = false;
- label2.fontSize = 12;
- label2.x = am4core.percent(50);
- label2.y = am4core.percent(100);
- label2.horizontalCenter = "middle";
- label2.verticalCenter = "top";
- label2.text = "Complited Ticket";
- // 配置指针
- const hand = chart.hands.push(new am4charts.ClockHand());
- hand.axis = axis2;
- hand.innerRadius = am4core.percent(20);
- hand.startWidth = 0;
- hand.pin.disabled = true;
- hand.value = 50;
- hand.disabled = true;
- // 更新事件处理
- hand.events.on("propertychanged", (ev) => {
- range0.endValue = ev.target.value;
- range1.value = ev.target.value;
- axis2.invalidate();
- });
- // 设置图表容器的固定大小
- //chart.width = 160; // 设置固定宽度
- // 定时更新数据
- const interval = setInterval(() => {
- const value = this.currentPercentage.percent; // Math.round(Math.random() * 100);
- label.text = value + "%";
- new am4core.Animation(
- hand,
- {
- property: "value",
- to: value,
- },
- 1000,
- am4core.ease.cubicOut
- ).start();
- }, 2000);
- chart.padding(0, 0, 0, 0);
- // 保存表实例和定时器
- this.charts.hdComplitedTicket = {
- chart: chart,
- interval: interval,
- };
- },
- // 初始化设备占比饼图
- initChartPercent() {
- const chart = am4core.create(this.$refs.chartPercent, am4charts.PieChart);
- chart.logo.disabled = true;
- chart.innerRadius = 30;
- // 配置系列
- const pieSeries = chart.series.push(new am4charts.PieSeries());
- pieSeries.dataFields.value = "size";
- pieSeries.dataFields.category = "sector";
- pieSeries.labels.template.disabled = true;
- pieSeries.ticks.template.disabled = true;
- pieSeries.colors.step = 3;
- this.charts.chartPercent = chart;
- },
- // 初始化存储使用趋势图
- initStorageChart() {
- const chart = am4core.create(this.$refs.storageChart, am4charts.XYChart);
- // 添加数据
- chart.data = [
- {
- date: "2012-03-01",
- price: 180,
- price1: 50,
- },
- {
- date: "2012-03-02",
- price: 252,
- price1: 40,
- },
- {
- date: "2012-03-03",
- price: 185,
- price1: 55,
- },
- {
- date: "2012-03-04",
- price: 110,
- price1: 38,
- },
- {
- date: "2012-03-05",
- price: 158,
- price1: 87,
- },
- {
- date: "2012-03-06",
- price: 200,
- price1: 67,
- },
- {
- date: "2012-03-07",
- price: 187,
- price1: 100,
- },
- ];
- // 配置X轴
- const dateAxis = chart.xAxes.push(new am4charts.DateAxis());
- dateAxis.renderer.grid.template.location = 0;
- dateAxis.renderer.grid.template.disabled = true;
- dateAxis.startLocation = 0.6;
- dateAxis.endLocation = 0.4;
- dateAxis.renderer.inside = true;
- dateAxis.renderer.labels.template.fill = am4core.color("#463699");
- // 配置Y轴
- const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
- valueAxis.logarithmic = true;
- valueAxis.renderer.minGridDistance = 0;
- valueAxis.renderer.inside = true;
- valueAxis.renderer.labels.template.disabled = true;
- // 配置第一个数据系列
- const series = chart.series.push(new am4charts.LineSeries());
- series.dataFields.valueY = "price";
- series.dataFields.dateX = "date";
- series.tensionX = 0.77;
- series.strokeWidth = 2;
- series.fillOpacity = 0.1;
- series.tooltipText = "{valueY.value}";
- series.fill = am4core.color("#19BCBF");
- series.stroke = am4core.color("#19BCBF");
- // 配置第二个数据系列
- const series1 = chart.series.push(new am4charts.LineSeries());
- series1.dataFields.valueY = "price1";
- series1.dataFields.dateX = "date";
- series1.tensionX = 0.77;
- series1.strokeWidth = 2;
- series1.fillOpacity = 0.1;
- series1.tooltipText = "{valueY.value}";
- series1.fill = am4core.color("#463699");
- series1.stroke = am4core.color("#463699");
- // 添加第一个系列的圆点
- const bullet = series.bullets.push(new am4charts.CircleBullet());
- bullet.circle.fill = am4core.color("#fff");
- bullet.circle.strokeWidth = 3;
- // 添加第二个系列的圆点
- const bullet1 = series1.bullets.push(new am4charts.CircleBullet());
- bullet1.circle.fill = am4core.color("#fff");
- bullet1.circle.strokeWidth = 3;
- // 添加光标
- chart.cursor = new am4charts.XYCursor();
- chart.cursor.fullWidthLineX = true;
- chart.cursor.xAxis = dateAxis;
- chart.cursor.lineX.strokeWidth = 0;
- chart.cursor.lineX.fill = am4core.color("#fff");
- chart.cursor.lineX.fillOpacity = 0;
- chart.padding(0, 0, 0, 0);
- this.charts.storageChart = chart;
- },
- // 修改initSiteVisitorChart方法
- initSiteVisitorChart() {
- // 如果已存在图表实例,先销毁它
- if (this.charts.siteVisitorChart) {
- this.charts.siteVisitorChart.dispose();
- }
- const chart = am4core.create(
- this.$refs.siteVisitorChart,
- am4charts.XYChart
- );
- chart.logo.disabled = true;
- chart.hiddenState.properties.opacity = 0;
- chart.padding(0, 0, 0, 0);
- chart.zoomOutButton.disabled = true;
- // 初始化数据
- const data = [];
- let visits = 10;
- for (let i = 0; i <= 30; i++) {
- visits -= Math.round(
- (Math.random() < 0.5 ? 1 : -1) * Math.random() * 10
- );
- data.push({
- date: new Date().setSeconds(i - 30),
- cpuValue: this.cpuValue || 0, //Math.abs(visits),
- gpuValue: this.GpuValue || 0,
- });
- }
- chart.data = data;
- // 配置X轴
- const dateAxis = chart.xAxes.push(new am4charts.DateAxis());
- dateAxis.renderer.grid.template.location = 0;
- dateAxis.renderer.minGridDistance = 30;
- dateAxis.dateFormats.setKey("second", "ss");
- dateAxis.periodChangeDateFormats.setKey("second", "[bold]h:mm a");
- dateAxis.periodChangeDateFormats.setKey("minute", "[bold]h:mm a");
- dateAxis.periodChangeDateFormats.setKey("hour", "[bold]h:mm a");
- dateAxis.renderer.inside = true;
- dateAxis.renderer.axisFills.template.disabled = true;
- dateAxis.renderer.ticks.template.disabled = true;
- dateAxis.interpolationDuration = 500;
- dateAxis.rangeChangeDuration = 500;
- // 配置Y轴
- const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
- valueAxis.tooltip.disabled = true;
- valueAxis.interpolationDuration = 500;
- valueAxis.rangeChangeDuration = 500;
- valueAxis.renderer.inside = true;
- valueAxis.renderer.minLabelPosition = 0.05;
- valueAxis.renderer.maxLabelPosition = 0.95;
- valueAxis.renderer.axisFills.template.disabled = true;
- valueAxis.renderer.ticks.template.disabled = true;
- // CPU 数据系列(红色)
- const cpuSeries = chart.series.push(new am4charts.LineSeries());
- cpuSeries.dataFields.dateX = "date";
- cpuSeries.dataFields.valueY = "cpuValue";
- cpuSeries.interpolationDuration = 500;
- cpuSeries.defaultState.transitionDuration = 0;
- cpuSeries.tensionX = 0.8;
- cpuSeries.stroke = am4core.color("#FF425C"); // 红色
- cpuSeries.strokeWidth = 2;
- // CPU 系列渐变
- cpuSeries.fillOpacity = 1;
- const cpuGradient = new am4core.LinearGradient();
- cpuGradient.addColor(am4core.color("#FF425C"), 0.2);
- cpuGradient.addColor(am4core.color("#FF425C"), 0);
- cpuSeries.fill = cpuGradient;
- // GPU 数据系列(蓝色)
- const gpuSeries = chart.series.push(new am4charts.LineSeries());
- gpuSeries.dataFields.dateX = "date";
- gpuSeries.dataFields.valueY = "gpuValue";
- gpuSeries.interpolationDuration = 500;
- gpuSeries.defaultState.transitionDuration = 0;
- gpuSeries.tensionX = 0.8;
- gpuSeries.stroke = am4core.color("#19BCBF"); // 蓝色
- gpuSeries.strokeWidth = 2;
- // GPU 系列渐变
- gpuSeries.fillOpacity = 1;
- const gpuGradient = new am4core.LinearGradient();
- gpuGradient.addColor(am4core.color("#19BCBF"), 0.2);
- gpuGradient.addColor(am4core.color("#19BCBF"), 0);
- gpuSeries.fill = gpuGradient;
- // CPU 圆点
- const cpuBullet = cpuSeries.createChild(am4charts.CircleBullet);
- cpuBullet.circle.radius = 5;
- cpuBullet.fillOpacity = 1;
- cpuBullet.fill = am4core.color("#FF425C");
- cpuBullet.isMeasured = false;
- // GPU 圆点
- const gpuBullet = gpuSeries.createChild(am4charts.CircleBullet);
- gpuBullet.circle.radius = 5;
- gpuBullet.fillOpacity = 1;
- gpuBullet.fill = am4core.color("#19BCBF");
- gpuBullet.isMeasured = false;
- // 更新两个系列圆点位置
- cpuSeries.events.on("validated", () => {
- cpuBullet.moveTo(cpuSeries.dataItems.last.point);
- cpuBullet.validatePosition();
- });
- gpuSeries.events.on("validated", () => {
- gpuBullet.moveTo(gpuSeries.dataItems.last.point);
- gpuBullet.validatePosition();
- });
- // 设置初始缩放
- chart.events.on("datavalidated", () => {
- dateAxis.zoom({ start: 1 / 15, end: 1.2 }, false, true);
- });
- // 存储图表实例
- this.charts.siteVisitorChart = chart;
- /* // 启动数据更新
- setTimeout(() => {
- this.startVisitorDataInterval(cpuSeries, gpuSeries);
- }, 100); */
- // 修改数据更新逻辑
- this.startVisitorDataInterval(cpuSeries, gpuSeries);
- },
- // 修改 startVisitorDataInterval 方法
- startVisitorDataInterval(cpuSeries, gpuSeries) {
- // 清除已存在的定时器
- if (this.chartUpdateInterval) {
- clearInterval(this.chartUpdateInterval);
- }
- this.chartUpdateInterval = setInterval(() => {
- const lastDataItem = cpuSeries.dataItems.getIndex(
- cpuSeries.dataItems.length - 1
- );
- if (lastDataItem && lastDataItem.dateX) {
- cpuSeries.chart.addData(
- {
- date: new Date(lastDataItem.dateX.getTime() + 1000),
- cpuValue: this.cpuValue || 0,
- gpuValue: this.GpuValue || 0,
- },
- 1
- );
- }
- }, 1000);
- },
- // 添加清理方法
- cleanupCharts() {
- // 清除定时器
- if (this.chartUpdateInterval) {
- clearInterval(this.chartUpdateInterval);
- this.chartUpdateInterval = null;
- }
- // 清除图表实例
- if (this.charts.siteVisitorChart) {
- this.charts.siteVisitorChart.dispose();
- this.charts.siteVisitorChart = null;
- }
- },
- handleVisitorChartVisibility() {
- if (document.hidden) {
- if (this.charts.siteVisitorInterval) {
- clearInterval(this.charts.siteVisitorInterval);
- }
- } else {
- const series = this.charts.siteVisitorChart.series.getIndex(0);
- this.startVisitorDataInterval(series);
- }
- },
- // 初始化实时数据小图表
- initRealTimeCharts() {
- // 交易量图表
- const real4Chart = am4core.create(
- this.$refs.real4Chart,
- am4charts.XYChart
- );
- // ... 配置real4Chart
- this.charts.real4Chart = real4Chart;
- // 库存图表
- const real6Chart = am4core.create(
- this.$refs.real6Chart,
- am4charts.XYChart
- );
- // ... 配置real6Chart
- this.charts.real6Chart = real6Chart;
- // 跳出率图表
- const real1Chart = am4core.create(
- this.$refs.real1Chart,
- am4charts.XYChart
- );
- // ... 配置real1Chart
- this.charts.real1Chart = real1Chart;
- // 订单总额图表
- const real5Chart = am4core.create(
- this.$refs.real5Chart,
- am4charts.XYChart
- );
- // ... 配置real5Chart
- this.charts.real5Chart = real5Chart;
- // 收入图表
- const real2Chart = am4core.create(
- this.$refs.real2Chart,
- am4charts.XYChart
- );
- // ... 配置real2Chart
- this.charts.real2Chart = real2Chart;
- // 新购买图表
- const real3Chart = am4core.create(
- this.$refs.real3Chart,
- am4charts.XYChart
- );
- // ... 配置real3Chart
- this.charts.real3Chart = real3Chart;
- },
- initTransactionCharts() {
- // Transactions 1 Chart
- const transactions1 = am4core.create(
- this.$refs.transactions1,
- am4charts.XYChart
- );
- transactions1.data = this.generateTransactionData("#19BCBF");
- this.configureTransactionChart(transactions1);
- this.charts.transactions1 = transactions1;
- // Transactions 2 Chart
- const transactions2 = am4core.create(
- this.$refs.transactions2,
- am4charts.XYChart
- );
- transactions2.data = this.generateTransactionData("#FF425C");
- this.configureTransactionChart(transactions2);
- this.charts.transactions2 = transactions2;
- },
- generateTransactionData(color) {
- const data = [];
- for (let i = 0; i <= 12; i++) {
- data.push({
- category: i,
- value: Math.random() * 30 + 10,
- color: color,
- });
- }
- return data;
- },
- configureTransactionChart(chart) {
- // Create axes
- const categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
- categoryAxis.dataFields.category = "category";
- categoryAxis.renderer.grid.template.disabled = true;
- categoryAxis.renderer.labels.template.disabled = true;
- categoryAxis.renderer.minGridDistance = 10;
- const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
- valueAxis.renderer.grid.template.disabled = true;
- valueAxis.renderer.labels.template.disabled = true;
- valueAxis.min = 0;
- valueAxis.max = 50;
- // Create series
- const series = chart.series.push(new am4charts.ColumnSeries());
- series.dataFields.valueY = "value";
- series.dataFields.categoryX = "category";
- series.columns.template.propertyFields.fill = "color";
- series.columns.template.propertyFields.stroke = "color";
- series.columns.template.width = am4core.percent(40);
- // Add tooltip
- series.tooltipText = "{valueY}";
- chart.cursor = new am4charts.XYCursor();
- chart.cursor.behavior = "none";
- // Remove padding
- chart.paddingBottom = 0;
- chart.paddingTop = 0;
- chart.paddingLeft = 0;
- chart.paddingRight = 0;
- },
- initDeviceChart() {
- const chart = am4core.create(this.$refs.deviceChart, am4charts.PieChart);
- // 添加数据
- chart.data = [
- { sector: "Mobile", size: 14.6 },
- { sector: "Tablet", size: 9.3 },
- { sector: "Desktop", size: 22.5 },
- ];
- // 设置内圆半径
- chart.innerRadius = 30;
- // 添加并配置饼图系列
- const pieSeries = chart.series.push(new am4charts.PieSeries());
- pieSeries.dataFields.value = "size";
- pieSeries.dataFields.category = "sector";
- pieSeries.labels.template.disabled = true;
- pieSeries.ticks.template.disabled = true;
- pieSeries.colors.step = 2;
- // 保存图表实例
- this.charts.deviceChart = chart;
- },
- /* 初始化 */
- init() {
- structure_count().then((res) => {
- if (res.status !== 200) return;
- this.kenList = res.data;
- if (this.kenList.length > 0) {
- this.kenValue = this.kenList[0].id;
- this.kenVal = this.kenList[0];
- // 处理文件类型统计数据
- this.updateChartPercentData(this.kenList[0]);
- }
- });
- /* 获取文档数量 */
- searchlistDoc({ page: 1, pageSize: 9999 }).then((res) => {
- this.docTotal = res.data.dataList.length;
- });
- searchList({ page: 1, pageSize: 9999 }).then((res) => {
- if (!res) return;
- this.temTotal = res.data.dataList.length;
- });
- pageTemplate({ page: 1, pageSize: 9999 }).then((res) => {
- if (!res) return;
- this.pageTotal = res.data.dataList.length;
- });
- /* 获取文件解析数量 */
- doc_status().then((res) => {
- this.docList = res.data.data.run_stats;
- console.log(this.docList.run_3);
- });
- },
- /* 选择知识库 */
- kenChange(val) {
- this.kenVal = this.kenList.find((el) => el.id === val);
- // 更新图表数据
- this.updateChartPercentData(this.kenVal);
- },
- // 更新文件类型统计数据
- updateChartPercentData(kenData) {
- if (!kenData) return;
- // 获取所有的 file_type_stats
- const allFileStats = this.getAllFileTypeStats(kenData);
- // 合并所有的文件统计数据
- const mergedFileStats = this.mergeFileStats(allFileStats);
- // 保存上一次的数据用于计算变化率
- this.previousCounts = { ...this.fileTypeCounts };
- // 更新当前数据
- this.fileTypeCounts = mergedFileStats;
- // 计算总文件数和百分比
- const totalFiles = Object.values(mergedFileStats).reduce(
- (a, b) => a + b,
- 0
- );
- // 转换数据格式
- const chartData = Object.entries(mergedFileStats).map(
- ([type, count]) => ({
- sector: type.toUpperCase(),
- size: count /* Number(((count / totalFiles) * 100).toFixed(1)) */,
- count: count,
- })
- );
- // 更新图表数据
- if (this.charts.chartPercent) {
- this.charts.chartPercent.data = chartData;
- }
- },
- // 获取文件类型对应的图标
- getFileTypeIcon(type) {
- const icons = {
- pdf: "icon-file-text",
- docx: "icon-file",
- xlsx: "icon-file",
- };
- return icons[type.toLowerCase()] || "icon-file";
- },
- // 获取文件类型对应的颜色
- getFileTypeColor(type) {
- const colors = {
- pdf: "#dc67ce",
- docx: "#8067dc",
- xlsx: "#67b7dc",
- };
- return colors[type.toLowerCase()] || "#666666";
- },
- // 计算化率
- getChangePercentage(type) {
- const currentCount = this.fileTypeCounts[type] || 0;
- const previousCount = this.previousCounts[type] || currentCount;
- if (previousCount === 0) return "0%";
- const change = ((currentCount - previousCount) / previousCount) * 100;
- return `${Math.abs(change).toFixed(1)}%`;
- },
- // 获取变化率的图标
- getChangeIcon(type) {
- const currentCount = this.fileTypeCounts[type] || 0;
- const previousCount = this.previousCounts[type] || currentCount;
- return currentCount >= previousCount
- ? "icon-arrow-up"
- : "icon-arrow-down";
- },
- // 获取变化率的样式类
- getChangeClass(type) {
- const currentCount = this.fileTypeCounts[type] || 0;
- const previousCount = this.previousCounts[type] || currentCount;
- return currentCount >= previousCount ? "text-c-green" : "text-c-red";
- },
- // 递归获取所有的 file_type_stats
- getAllFileTypeStats(data) {
- let results = [];
- // 处理当前层级的 file_type_stats
- if (data.file_type_stats) {
- results.push(data.file_type_stats);
- }
- // 处理 directories 中的 file_type_stats
- if (data.directories && Array.isArray(data.directories)) {
- data.directories.forEach((dir) => {
- results = results.concat(this.getAllFileTypeStats(dir));
- });
- }
- return results;
- },
- // 合并多个 file_type_stats 对象
- mergeFileStats(fileStatsList) {
- return fileStatsList.reduce((merged, current) => {
- Object.entries(current).forEach(([type, count]) => {
- merged[type] = (merged[type] || 0) + count;
- });
- return merged;
- }, {});
- },
- // 处理WebSocket消息的方法修改
- handleWebSocketMessage(data) {
- try {
- if (data?.data?.system?.temperature) {
- this.updateTemperatures(data.data.system.temperature);
- }
- } catch (error) {
- console.error("Error processing WebSocket message:", error);
- }
- },
- updateTemperatures(temperatureData) {
- // 更新CPU温度
- if (temperatureData.cpu && Array.isArray(temperatureData.cpu)) {
- // 获取Package温度作为主要CPU温度
- const packageTemp = temperatureData.cpu.find(temp => temp.label === 'Package id 0');
- if (packageTemp) {
- this.temperatureData.cpu = {
- current: packageTemp.current,
- high: packageTemp.high || this.temperatureData.cpu.high,
- critical: packageTemp.critical || this.temperatureData.cpu.critical
- };
- this.cpuTemperature = packageTemp.current;
- }
- // 记录最高核心温度用于告警
- const maxCoreTemp = Math.max(
- ...temperatureData.cpu
- .filter(temp => temp.label.startsWith('Core'))
- .map(temp => temp.current)
- );
- if (maxCoreTemp > this.temperatureData.cpu.high) {
- console.warn(`CPU temperature warning: ${maxCoreTemp}°C`);
- }
- }
- // 更新GPU温度
- if (temperatureData.gpu && temperatureData.gpu.length > 0) {
- const gpuTemp = temperatureData.gpu[0];
- this.temperatureData.gpu.current = gpuTemp.temperature;
- this.gpuTemperature = gpuTemp.temperature;
-
- if (gpuTemp.temperature > this.temperatureData.gpu.high) {
- console.warn(`GPU temperature warning: ${gpuTemp.temperature}°C`);
- }
- }
- },
- getTemperatureColor(temp, type = 'cpu') {
- const thresholds = this.temperatureData[type];
- const percentage = (temp / thresholds.critical) * 100;
- if (percentage >= 90) return "#FF425C"; // 危险温度 - 红色
- if (percentage >= 70) return "#FFA726"; // 警告温度 - 橙色
- return "#19BCBF"; // 正常温度 - 蓝色
- },
- // 初始化磁盘图表
- initDiskChart() {
- try {
- // 创建环形图实例
- const chart = am4core.create(this.$refs.diskChart, am4charts.PieChart);
- if (!chart) return;
- // 禁用 logo
- if (chart.logo) {
- chart.logo.disabled = true;
- }
- // 设置内半径创建环形效果
- chart.innerRadius = am4core.percent(65);
- // 添加数据
- chart.data = this.formatDiskData();
- // 创建饼图系列
- const series = chart.series.push(new am4charts.PieSeries());
- if (series) {
- // 配置数据字段
- series.dataFields.value = "used";
- series.dataFields.category = "diskName";
- // 禁用标签和刻度
- series.labels.template.disabled = true;
- series.ticks.template.disabled = true;
- // 配置切片样式
- if (series.slices.template) {
- series.slices.template.strokeWidth = 2;
- series.slices.template.strokeOpacity = 1;
- series.slices.template.stroke = am4core.color("#fff");
- // 设置切片颜色
- series.slices.template.adapter.add("fill", (fill, target) => {
- const dataItem = target.dataItem;
- if (dataItem) {
- const percentUsed = (dataItem.values.value.value / dataItem.dataContext.total) * 100;
- if (percentUsed > 80) return am4core.color("#FF425C"); // 危险
- if (percentUsed > 60) return am4core.color("#FFA726"); // 警告
- return am4core.color("#19BCBF"); // 正常
- }
- return fill;
- });
- // 配置悬浮提示
- series.slices.template.tooltipHTML = `
- <div style="padding: 10px;">
- <div style="margin-bottom: 5px;color:#333;"><strong>{diskName}</strong></div>
- <div style="color: #666;">总容量: {total.formatNumber('#.##')} GB</div>
- <div style="color: #FF425C;">已使用: {used.formatNumber('#.##')} GB</div>
- <div style="color: #19BCBF;">可用空间: {free.formatNumber('#.##')} GB</div>
- <div style="color: #666;">使用率: {percent.formatNumber('#.##')}%</div>
- </div>
- `;
- // 设置悬浮提示样式
- if (series.tooltip) {
- series.tooltip.getFillFromObject = false;
- series.tooltip.pointerOrientation = "vertical";
- series.tooltip.dy = -5;
- series.tooltip.dx = 0;
- if (series.tooltip.background) {
- series.tooltip.background.fill = am4core.color("#ffffff");
- series.tooltip.background.stroke = am4core.color("#19BCBF");
- series.tooltip.background.strokeWidth = 1;
- series.tooltip.background.cornerRadius = 4;
- }
- }
- }
- // 添加中心标签
- const label = chart.seriesContainer.createChild(am4core.Label);
- label.text = "{percent.formatNumber('#.#')}%";
- label.horizontalCenter = "middle";
- label.verticalCenter = "middle";
- label.fontSize = 20;
- label.fontWeight = "600";
- // 更新中心标签的值
- series.events.on("validated", () => {
- const total = series.dataItems.getIndex(0).dataContext.total;
- const used = series.dataItems.getIndex(0).dataContext.used;
- const percent = (used / total) * 100;
- label.text = `${percent.toFixed(1)}%`;
- });
- }
- // 保存图表实例
- this.charts.diskChart = chart;
- // 设置自动更新
- this.startDiskDataInterval();
- } catch (error) {
- console.error("初始化磁盘图表失败:", error);
- }
- },
- // 格式化磁盘数据
- formatDiskData() {
- if (!this.chartData?.data?.system?.cpu?.disk?.partitions) {
- return [];
- }
- const diskNameMap = {
- C: "系统盘",
- D: "数据盘",
- E: "扩展盘",
- };
- return this.chartData.data.system.cpu.disk.partitions
- .filter(partition => partition.mountpoint === "/")
- .map(partition => {
- const driveLetter = partition.device.replace(":\\", "");
- const diskName = diskNameMap[driveLetter] || `${driveLetter}盘`;
- return {
- device: driveLetter,
- diskName: diskName,
- used: partition.used,
- free: partition.free,
- total: partition.total,
- percent: partition.percent
- };
- });
- },
- // 启动磁盘数据更新定时器
- startDiskDataInterval() {
- if (this.diskUpdateInterval) {
- clearInterval(this.diskUpdateInterval);
- }
- this.diskUpdateInterval = setInterval(() => {
- if (this.charts.diskChart) {
- this.charts.diskChart.data = this.formatDiskData();
- }
- }, 2000); // 每2秒更新一次
- },
- /* // 在 WebSocket 消息处理中添加磁盘数据更新
- handleWebSocketMessage(event) {
- try {
- const data = JSON.parse(event.data);
- if (data?.data?.system?.cpu?.disk) {
- this.chartData = data;
- if (this.charts.diskChart) {
- this.charts.diskChart.data = this.formatDiskData();
- }
- }
- } catch (error) {
- console.error("Error processing WebSocket message:", error);
- }
- }, */
- },
- // 修改beforeDestroy钩子
- beforeDestroy() {
- this.isCurrentPage = false;
- this.closeWebSocket();
- // 清理所有图表实例
- Object.values(this.charts).forEach((chart) => {
- if (chart) {
- if (typeof chart.dispose === "function") {
- chart.dispose();
- } else if (typeof chart === "number") {
- clearInterval(chart);
- }
- }
- });
- // 移除事件监听器
- document.removeEventListener(
- "visibilitychange",
- this.handleVisitorChartVisibility
- );
- },
- };
- </script>
- <style lang="scss" scoped>
- .widget-chart {
- height: calc(100vh - 85px);
- padding: 15px;
- font-family: "Roboto", sans-serif;
- font-size: 14px;
- color: #686c71;
- font-weight: 400;
- background: #f8f9fa;
- a {
- text-decoration: none;
- }
- // 卡片基础样式
- .card {
- border-radius: 2px;
- box-shadow: 0 0px 0 1px #e2e5e8;
- border: none;
- margin-bottom: 17px;
- background: #fff;
- .card-body {
- padding: 1.5rem;
- h6 {
- color: #111;
- font-size: 16px;
- .text-primary {
- color: #19bcbf !important;
- }
- .text-danger {
- color: #ff425c !important;
- }
- }
- }
- }
- // 文字样式
- h2 {
- font-size: 28px;
- font-weight: 600;
- color: #333;
- margin: 0;
- }
- h6 {
- font-size: 14px;
- color: #6c757d;
- margin-bottom: 0.5rem;
- }
- // 图标样式
- .feather {
- width: 20px;
- height: 20px;
- vertical-align: text-bottom;
- }
- // 颜色方案
- .text-c-blue {
- color: #19bcbf;
- }
- .text-c-green {
- color: #2ed8b6;
- }
- .text-c-red {
- color: #ff5370;
- }
- .text-c-purple {
- color: #8067dc;
- }
- // 下拉菜单样式
- .dropdown-toggle {
- &:after {
- margin-left: 0.5em;
- }
- }
- .dropdown-menu {
- border-radius: 4px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
- .dropdown-item {
- padding: 0.5rem 1rem;
- &:hover {
- background-color: #f8f9fa;
- }
- }
- }
- // 图表容器样式
- [ref="hdComplitedTicket"],
- [ref="chartPercent"],
- [ref="storageChart"] {
- margin: 1rem 0;
- }
- // 小型图表样式
- [ref^="real"] {
- height: 20px;
- width: 100%;
- margin-top: 0.5rem;
- }
- // 统计数字样式
- .mt-2 {
- h3 {
- font-size: 24px;
- font-weight: 600;
- color: #333;
- margin: 0.5rem 0;
- }
- }
- // 图标指标样式
- .fas.fa-circle {
- font-size: 10px;
- margin-right: 8px;
- &.text-c-blue {
- color: #19bcbf;
- }
- &.text-c-purple {
- color: #8067dc;
- }
- }
- }
- // 响应式布局调整
- @media (max-width: 768px) {
- .widget-chart {
- .card {
- margin-bottom: 16px;
- }
- }
- }
- .progress {
- background-color: #f0f0f0;
- border-radius: 3px;
- overflow: hidden;
- }
- .progress-bar {
- transition: width 0.3s ease;
- }
- .temperature-select-wrapper {
- position: relative;
- width: 100%;
- height: 20px;
- .temperature-select {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- appearance: none;
- background: transparent;
- border: none;
- pointer-events: none;
- z-index: 1;
- &::-ms-expand {
- display: none;
- }
- option {
- background: transparent;
- }
- }
- .temperature-progress {
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- background-color: #19bcbf;
- transition: width 0.3s ease;
- border-radius: 3px;
- &::after {
- content: "";
- position: absolute;
- top: 0;
- right: 0;
- width: 100%;
- height: 100%;
- background: repeating-linear-gradient(
- 90deg,
- currentColor,
- currentColor 4px,
- transparent 4px,
- transparent 8px
- );
- opacity: 0.2;
- }
- }
- }
- // 添加条纹背景
- .temperature-select-wrapper::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: repeating-linear-gradient(
- 90deg,
- #e0e0e0,
- #e0e0e0 4px,
- #f0f0f0 4px,
- #f0f0f0 8px
- );
- border-radius: 3px;
- }
- // 更新温度进度条样式
- .temperature-select-wrapper {
- margin-bottom: 10px;
-
- .temperature-progress {
- transition: all 0.3s ease;
-
- &::after {
- opacity: 0.15;
- }
- }
- }
- // 添加新的温度显示样式
- .col-6 {
- h2 {
- font-size: 24px;
- font-weight: 600;
- }
-
- span {
- color: #666;
- font-size: 14px;
- }
- }
- </style>
- <style src="./css/bootstrap.min.css" scoped></style>
|