|
|
@@ -1,142 +1,129 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <div class="TopBox">
|
|
|
- <div class="rightdiv">
|
|
|
- <el-table
|
|
|
- ref="multipleTable"
|
|
|
- :data="tableData"
|
|
|
- tooltip-effect="dark"
|
|
|
- style="width: 100%"
|
|
|
- height="250"
|
|
|
- stripe
|
|
|
- border
|
|
|
- >
|
|
|
- <!-- <el-table-column fixed type="selection" width="55"> </el-table-column> -->
|
|
|
- <el-table-column
|
|
|
- type="index"
|
|
|
- label="序号"
|
|
|
- align="center"
|
|
|
- width="100"
|
|
|
- :index="bearingTableIndex"
|
|
|
- >
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="brandType" label="型号" align="left">
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="detectionPointCn" label="名称" align="left">
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="状态" width="150" align="center">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-tag
|
|
|
- size="mini"
|
|
|
- :type="statusTagType(scope.row.status)"
|
|
|
- effect="dark"
|
|
|
- >
|
|
|
- {{ formatStatusText(scope.row.status) }}
|
|
|
- </el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <!-- <el-table-column prop="timeStamp" label="时间" align="center">
|
|
|
- </el-table-column> -->
|
|
|
- <el-table-column prop="brand" width="150" label="品牌" align="left">
|
|
|
- </el-table-column>
|
|
|
-
|
|
|
- <!-- <el-table-column prop="" label="操作" align="center">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-button
|
|
|
- type="text"
|
|
|
- size="small"
|
|
|
- @click="handleDetail(scope.row)"
|
|
|
- >查看振动分析</el-button
|
|
|
- >
|
|
|
- </template>
|
|
|
- </el-table-column> -->
|
|
|
- </el-table>
|
|
|
- <div class="fenye">
|
|
|
- <p></p>
|
|
|
- <!-- <p><span>状态码说明:</span>0正常,1报警,2危险</p> -->
|
|
|
- <el-pagination
|
|
|
- @current-change="handleCurrentChange"
|
|
|
- :current-page="currentPage"
|
|
|
- layout="total, prev, pager, next"
|
|
|
- :total="totalCount"
|
|
|
- :page-size="pageSize"
|
|
|
- small
|
|
|
- ></el-pagination>
|
|
|
- </div>
|
|
|
+ <div class="gear-container">
|
|
|
+ <div class="gear-header">
|
|
|
+ <div class="header-title">
|
|
|
+ <p class="title">轴承诊断状态总览</p>
|
|
|
+ <p class="sub-title">共 {{ statusSummary.total }} 个监测点</p>
|
|
|
</div>
|
|
|
- <!-- <div class="leftdiv">
|
|
|
- <div class="stateBox">
|
|
|
- <h4>轴承状态</h4>
|
|
|
- <div class="state">
|
|
|
- <p :style="{ backgroundColor: bearingStateColors.innerRing }">
|
|
|
- 轴承内圈状态
|
|
|
- </p>
|
|
|
- <p :style="{ backgroundColor: bearingStateColors.outerRing }">
|
|
|
- 轴承外圈状态
|
|
|
- </p>
|
|
|
- <p :style="{ backgroundColor: bearingStateColors.rollingElement }">
|
|
|
- 轴承滚动体状态
|
|
|
- </p>
|
|
|
- <p :style="{ backgroundColor: bearingStateColors.cage }">
|
|
|
- 轴承保持架状态
|
|
|
- </p>
|
|
|
+ <div class="header-stat">
|
|
|
+ <div
|
|
|
+ v-for="item in statusCards"
|
|
|
+ :key="item.key"
|
|
|
+ class="stat-item"
|
|
|
+ :class="`is-${item.key}`"
|
|
|
+ >
|
|
|
+ <el-divider direction="vertical" class="header-divider"></el-divider>
|
|
|
+ <div class="stat-item-content">
|
|
|
+ <div class="icon-wrap">
|
|
|
+ <i :class="item.icon"></i>
|
|
|
+ </div>
|
|
|
+ <div class="stat-content">
|
|
|
+ <p class="label">{{ item.label }}</p>
|
|
|
+ <p class="count">{{ item.count }}</p>
|
|
|
+ <p class="ratio">占比 {{ item.ratio }}</p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- size="small"
|
|
|
- @click="automaticDiagnosis"
|
|
|
- class="btn-auto"
|
|
|
- :loading="loading"
|
|
|
- >诊断</el-button
|
|
|
- >
|
|
|
+ <div class="stat-nobox"></div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div class="Btn">
|
|
|
- <div style="height: 200px">
|
|
|
- <bingTwo :statistics="statistics"> </bingTwo>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="gear">
|
|
|
+ <div class="TopBox">
|
|
|
+ <div class="rightdiv">
|
|
|
+ <div class="monitor-panel">
|
|
|
+ <h4>轴承监测点列表</h4>
|
|
|
+ <div v-if="!tableData.length" class="monitor-empty">
|
|
|
+ <el-empty description="暂无监测点数据"></el-empty>
|
|
|
+ </div>
|
|
|
+ <div v-else class="monitor-list">
|
|
|
+ <div
|
|
|
+ v-for="(row, index) in tableData"
|
|
|
+ :key="row.id || `${row.functionTypeName}-${index}`"
|
|
|
+ class="monitor-item"
|
|
|
+ :class="{
|
|
|
+ 'is-active':
|
|
|
+ selectedFunctionTypeName &&
|
|
|
+ selectedFunctionTypeName === rowFunctionTypeName(row),
|
|
|
+ }"
|
|
|
+ @click="selectMonitorPoint(row)"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="index-badge"
|
|
|
+ :class="`is-${statusTagType(row.status)}`"
|
|
|
+ >
|
|
|
+ {{ bearingTableIndex(index) }}
|
|
|
+ </div>
|
|
|
+ <div class="item-main">
|
|
|
+ <p class="item-name">
|
|
|
+ {{ monitorDisplayName(row) }}
|
|
|
+ </p>
|
|
|
+ <p class="item-line">监测类型:{{ monitorTypeText(row) }}</p>
|
|
|
+ <p class="item-line">型号:{{ row.brandType }}</p>
|
|
|
+ <p class="item-line">品牌:{{ row.brand }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="item-right">
|
|
|
+ <span
|
|
|
+ class="status-pill"
|
|
|
+ :class="`is-${statusTagType(row.status)}`"
|
|
|
+ >
|
|
|
+ <i class="status-dot"></i>
|
|
|
+ {{ formatStatusText(row.status) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div class="minp">
|
|
|
- <p class="PText">
|
|
|
- <span><i class="color1"></i>正常</span
|
|
|
- ><span><i class="color2"></i>报警</span
|
|
|
- ><span><i class="color3"></i>危险</span>
|
|
|
- </p>
|
|
|
-
|
|
|
- <h4>诊断步骤:</h4>
|
|
|
- <p>1、选择振动测点与起止时间,点击“查询”;</p>
|
|
|
-
|
|
|
- <p>2、点击“诊断”输出最终轴承状态结果。</p>
|
|
|
+ <div class="fenye">
|
|
|
+ <p></p>
|
|
|
+ <el-pagination
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ :current-page="currentPage"
|
|
|
+ layout="total, prev, pager, next"
|
|
|
+ :total="totalCount"
|
|
|
+ :page-size="pageSize"
|
|
|
+ small
|
|
|
+ ></el-pagination>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div> -->
|
|
|
- </div>
|
|
|
- <div class="bottomBox">
|
|
|
- <div class="BtLeft">
|
|
|
- <h4>轴承状态趋势图</h4>
|
|
|
- <p style="font-size: 12px; color: #999">
|
|
|
- <span>状态码说明:</span>0正常,1报警,2危险
|
|
|
- </p>
|
|
|
- <el-empty
|
|
|
- v-if="!trendChartList.length"
|
|
|
- description="暂无数据"
|
|
|
- style="padding: 46px 0"
|
|
|
- ></el-empty>
|
|
|
- <div v-else class="mpoint-charts">
|
|
|
- <div
|
|
|
- v-for="(chart, index) in trendChartList"
|
|
|
- :key="`${chart.title}-${index}`"
|
|
|
- class="mpoint-chart-item"
|
|
|
- >
|
|
|
- <!-- <p class="mpoint-chart-title">{{ chart.title }}</p> -->
|
|
|
- <Eecharts
|
|
|
- style="height: 260px"
|
|
|
- :xData="chart.xData"
|
|
|
- :yData="chart.yData"
|
|
|
- :yNames="chart.yNames"
|
|
|
- yAxisName="故障状态"
|
|
|
- :jumpContext="chart.jumpContext"
|
|
|
- ></Eecharts>
|
|
|
+ </div>
|
|
|
+ <div class="bottomBox">
|
|
|
+ <div class="BtLeft">
|
|
|
+ <h4>轴承状态趋势图:</h4>
|
|
|
+ <p class="status-legend">
|
|
|
+ <span class="legend-label">状态码说明:</span>
|
|
|
+ <span class="legend-item is-normal"
|
|
|
+ ><i class="legend-dot"></i>0 正常</span
|
|
|
+ >
|
|
|
+ <span class="legend-item is-warning"
|
|
|
+ ><i class="legend-dot"></i>1 报警</span
|
|
|
+ >
|
|
|
+ <span class="legend-item is-danger"
|
|
|
+ ><i class="legend-dot"></i>2 危险</span
|
|
|
+ >
|
|
|
+ </p>
|
|
|
+ <el-empty
|
|
|
+ v-if="!filteredTrendChartList.length"
|
|
|
+ description="暂无数据"
|
|
|
+ style="padding: 46px 0"
|
|
|
+ ></el-empty>
|
|
|
+ <div v-else class="mpoint-charts">
|
|
|
+ <el-carousel :key="trendCarouselKey">
|
|
|
+ <el-carousel-item
|
|
|
+ v-for="(chart, index) in filteredTrendChartList"
|
|
|
+ :key="`${chart.title}-${index}`"
|
|
|
+ >
|
|
|
+ <div class="mpoint-chart-item">
|
|
|
+ <Eecharts
|
|
|
+ style="height: 260px"
|
|
|
+ :xData="chart.xData"
|
|
|
+ :yData="chart.yData"
|
|
|
+ :yNames="chart.yNames"
|
|
|
+ yAxisName="故障状态"
|
|
|
+ :jumpContext="chart.jumpContext"
|
|
|
+ ></Eecharts>
|
|
|
+ </div>
|
|
|
+ </el-carousel-item>
|
|
|
+ </el-carousel>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -146,9 +133,8 @@
|
|
|
|
|
|
<script>
|
|
|
import Eecharts from "./mpointEecharts.vue";
|
|
|
-import bingTwo from "./bingTwo.vue";
|
|
|
export default {
|
|
|
- components: { Eecharts, bingTwo },
|
|
|
+ components: { Eecharts },
|
|
|
props: {
|
|
|
codedata: {
|
|
|
type: Array,
|
|
|
@@ -188,10 +174,9 @@ export default {
|
|
|
vibrationSpeedDangerThreshold: "",
|
|
|
envelopeTotalAlarmThreshold: "",
|
|
|
envelopeTotalDangerThreshold: "",
|
|
|
- // 分页
|
|
|
- pageSize: 10,
|
|
|
currentPage: 1,
|
|
|
total: 1,
|
|
|
+ pageSize: 10,
|
|
|
xData: [],
|
|
|
yData: [],
|
|
|
// 颜色判断
|
|
|
@@ -207,6 +192,8 @@ export default {
|
|
|
loading: false, // 控制加载状态
|
|
|
statistics: {},
|
|
|
trendChartList: [],
|
|
|
+ selectedFunctionTypeName: "",
|
|
|
+ selectedMonitorId: "",
|
|
|
};
|
|
|
},
|
|
|
created() {},
|
|
|
@@ -214,6 +201,24 @@ export default {
|
|
|
codedata: {
|
|
|
handler(newVal) {
|
|
|
this.tableData = newVal;
|
|
|
+ const exists = this.tableData.some(
|
|
|
+ (row) =>
|
|
|
+ this.resolveFunctionTypeNameByRow(row) ===
|
|
|
+ this.selectedFunctionTypeName,
|
|
|
+ );
|
|
|
+ if (!exists) {
|
|
|
+ if (this.tableData.length) {
|
|
|
+ this.selectedFunctionTypeName = this.resolveFunctionTypeNameByRow(
|
|
|
+ this.tableData[0],
|
|
|
+ );
|
|
|
+ this.selectedMonitorId = this.tableData[0]?.id
|
|
|
+ ? String(this.tableData[0].id)
|
|
|
+ : "";
|
|
|
+ } else {
|
|
|
+ this.selectedFunctionTypeName = "";
|
|
|
+ this.selectedMonitorId = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
immediate: true, // 组件创建时立刻执行一次
|
|
|
deep: true, // 如果 codedata 是复杂对象,建议加上
|
|
|
@@ -235,16 +240,34 @@ export default {
|
|
|
: Number(v);
|
|
|
});
|
|
|
const pointIds = inner.map((d) => d?.id);
|
|
|
+ const pointRows = inner.map((d) => {
|
|
|
+ const pid = d?.id;
|
|
|
+ return (
|
|
|
+ this.tableData.find((r) => String(r?.id) === String(pid)) ||
|
|
|
+ null
|
|
|
+ );
|
|
|
+ });
|
|
|
+ const normalizedFunctionTypeName = this.normalizeFunctionTypeName(
|
|
|
+ item?.functionTypeName ||
|
|
|
+ inner.find((d) => d?.functionTypeName)?.functionTypeName ||
|
|
|
+ pointRows.find((r) => r?.functionTypeName)?.functionTypeName ||
|
|
|
+ item?.functionTypeNameCn ||
|
|
|
+ item?.pointNameCn ||
|
|
|
+ item?.mesurePointName ||
|
|
|
+ "",
|
|
|
+ );
|
|
|
return {
|
|
|
title,
|
|
|
xData,
|
|
|
yData: [seriesY],
|
|
|
yNames: [title],
|
|
|
+ functionTypeName: normalizedFunctionTypeName,
|
|
|
jumpContext: {
|
|
|
companyCode: this.fieldCode,
|
|
|
windCode: this.fieldCode,
|
|
|
windTurbineNumber: this.windTurbineNumber,
|
|
|
itemKey: item?.itemKey ?? item?.item_key,
|
|
|
+ functionTypeName: normalizedFunctionTypeName,
|
|
|
id: item?.id,
|
|
|
mesurePointName: item?.mesurePointName || title,
|
|
|
detectionPointCn: item?.pointNameCn || title,
|
|
|
@@ -255,17 +278,111 @@ export default {
|
|
|
? { ...item.otherData }
|
|
|
: undefined,
|
|
|
pointIds,
|
|
|
+ pointRows,
|
|
|
},
|
|
|
};
|
|
|
})
|
|
|
.filter((it) => it.xData.length);
|
|
|
+ if (!this.selectedFunctionTypeName && this.tableData.length) {
|
|
|
+ this.selectedFunctionTypeName = this.resolveFunctionTypeNameByRow(
|
|
|
+ this.tableData[0],
|
|
|
+ );
|
|
|
+ this.selectedMonitorId = this.tableData[0]?.id
|
|
|
+ ? String(this.tableData[0].id)
|
|
|
+ : "";
|
|
|
+ }
|
|
|
},
|
|
|
immediate: true,
|
|
|
deep: true,
|
|
|
},
|
|
|
},
|
|
|
- mounted() {},
|
|
|
+ computed: {
|
|
|
+ statusSummary() {
|
|
|
+ const rows = Array.isArray(this.tableData) ? this.tableData : [];
|
|
|
+ const total = rows.length;
|
|
|
+ const summary = { total, normal: 0, warning: 0, danger: 0 };
|
|
|
+ rows.forEach((row) => {
|
|
|
+ const code = Number(row?.status);
|
|
|
+ if (code === 0) summary.normal += 1;
|
|
|
+ else if (code === 1) summary.warning += 1;
|
|
|
+ else if (code === 2) summary.danger += 1;
|
|
|
+ });
|
|
|
+ return summary;
|
|
|
+ },
|
|
|
+ statusCards() {
|
|
|
+ const { total, normal, warning, danger } = this.statusSummary;
|
|
|
+ const toRatio = (count) =>
|
|
|
+ total > 0 ? `${((count / total) * 100).toFixed(0)}%` : "0%";
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ key: "normal",
|
|
|
+ label: "正常",
|
|
|
+ count: normal,
|
|
|
+ ratio: toRatio(normal),
|
|
|
+ icon: "el-icon-check",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: "warning",
|
|
|
+ label: "报警",
|
|
|
+ count: warning,
|
|
|
+ ratio: toRatio(warning),
|
|
|
+ icon: "el-icon-warning-outline",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: "danger",
|
|
|
+ label: "危险",
|
|
|
+ count: danger,
|
|
|
+ ratio: toRatio(danger),
|
|
|
+ icon: "el-icon-warning",
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ filteredTrendChartList() {
|
|
|
+ const selected = this.selectedFunctionTypeName;
|
|
|
+ if (!selected) return this.trendChartList;
|
|
|
+ return this.trendChartList.filter(
|
|
|
+ (chart) => this.chartFunctionTypeName(chart) === selected,
|
|
|
+ );
|
|
|
+ },
|
|
|
+ trendCarouselKey() {
|
|
|
+ return `trend-${this.selectedFunctionTypeName || "all"}`;
|
|
|
+ },
|
|
|
+ },
|
|
|
methods: {
|
|
|
+ normalizeFunctionTypeName(name) {
|
|
|
+ return typeof name === "string" ? name.trim() : "";
|
|
|
+ },
|
|
|
+ rowFunctionTypeName(row) {
|
|
|
+ return this.normalizeFunctionTypeName(
|
|
|
+ row?.functionTypeName ? String(row.functionTypeName) : "",
|
|
|
+ );
|
|
|
+ },
|
|
|
+ resolveFunctionTypeNameByRow(row) {
|
|
|
+ const direct = this.rowFunctionTypeName(row);
|
|
|
+ if (direct) return direct;
|
|
|
+ const rowId =
|
|
|
+ row?.id !== undefined && row?.id !== null ? String(row.id) : "";
|
|
|
+ if (!rowId) return "";
|
|
|
+ const chart = this.trendChartList.find((item) => {
|
|
|
+ const rows = item?.jumpContext?.pointRows;
|
|
|
+ if (!Array.isArray(rows)) return false;
|
|
|
+ return rows.some(
|
|
|
+ (r) =>
|
|
|
+ r?.id !== undefined && r?.id !== null && String(r.id) === rowId,
|
|
|
+ );
|
|
|
+ });
|
|
|
+ return chart ? this.chartFunctionTypeName(chart) : "";
|
|
|
+ },
|
|
|
+ monitorDisplayName(row) {
|
|
|
+ return row?.functionTypeName || row?.detectionPointCn || "-";
|
|
|
+ },
|
|
|
+ chartFunctionTypeName(chart) {
|
|
|
+ return this.normalizeFunctionTypeName(
|
|
|
+ chart?.jumpContext?.functionTypeName
|
|
|
+ ? String(chart.jumpContext.functionTypeName)
|
|
|
+ : "",
|
|
|
+ );
|
|
|
+ },
|
|
|
statusTagType(status) {
|
|
|
const code = Number(status);
|
|
|
if (code === 0) return "success";
|
|
|
@@ -282,6 +399,14 @@ export default {
|
|
|
if (code === -1) return "未定义";
|
|
|
return String(status);
|
|
|
},
|
|
|
+ monitorTypeText(row) {
|
|
|
+ return "振动-加速度包络";
|
|
|
+ },
|
|
|
+ selectMonitorPoint(row) {
|
|
|
+ this.selectedMonitorId =
|
|
|
+ row?.id !== undefined && row?.id !== null ? String(row.id) : "";
|
|
|
+ this.selectedFunctionTypeName = this.resolveFunctionTypeNameByRow(row);
|
|
|
+ },
|
|
|
handleDetail(row) {
|
|
|
const itemKey = row.itemKey ?? row.item_key;
|
|
|
const payload = {
|
|
|
@@ -336,126 +461,285 @@ export default {
|
|
|
this.$emit("updatePage", this.currentPage); // 通知父组件,把当前页传出去
|
|
|
},
|
|
|
reset() {
|
|
|
- // 重置状态
|
|
|
+ this.tableData = [];
|
|
|
this.xData = [];
|
|
|
this.yData = [];
|
|
|
this.statistics = {};
|
|
|
+ this.result = {};
|
|
|
this.trendChartList = [];
|
|
|
+ this.selectedFunctionTypeName = "";
|
|
|
+ this.selectedMonitorId = "";
|
|
|
this.bearingStateColors = {
|
|
|
innerRing: "#80808057",
|
|
|
outerRing: "#80808057",
|
|
|
rollingElement: "#80808057",
|
|
|
cage: "#80808057",
|
|
|
};
|
|
|
- this.tableData = [];
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-h4 {
|
|
|
- margin-bottom: 5px;
|
|
|
- font-weight: 600;
|
|
|
+.gear-container {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+ margin-top: -10px;
|
|
|
}
|
|
|
|
|
|
-.TopBox {
|
|
|
- // height: 280px;
|
|
|
+.gear-header {
|
|
|
display: flex;
|
|
|
- justify-content: space-around;
|
|
|
-
|
|
|
- .leftdiv {
|
|
|
- width: 50%;
|
|
|
+ align-items: stretch;
|
|
|
+ border-radius: 12px;
|
|
|
+ background: #f5f7fa5e;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
|
+
|
|
|
+ .header-title {
|
|
|
+ width: 230px;
|
|
|
+ padding: 16px 18px;
|
|
|
display: flex;
|
|
|
- justify-content: space-around;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ .title {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ .sub-title {
|
|
|
+ margin: 6px 0 0;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .stateBox {
|
|
|
- .state {
|
|
|
+ .header-stat {
|
|
|
+ flex: 1;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
+ ::v-deep .header-divider.el-divider--vertical {
|
|
|
+ height: 48px;
|
|
|
+ margin: 0 8px 0 0;
|
|
|
+ width: 1px;
|
|
|
+ background-color: #dcdfe65e;
|
|
|
+ }
|
|
|
+ .stat-item {
|
|
|
+ padding: 10px 18px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 10px;
|
|
|
+ &:last-child {
|
|
|
+ border-right: 0;
|
|
|
+ }
|
|
|
+ .icon-wrap {
|
|
|
+ width: 42px;
|
|
|
+ height: 42px;
|
|
|
+ border-radius: 50%;
|
|
|
+ color: #fff;
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
justify-content: center;
|
|
|
- /* 整体居中 */
|
|
|
+ font-size: 22px;
|
|
|
+ }
|
|
|
+ .stat-item-content {
|
|
|
+ display: flex;
|
|
|
align-items: center;
|
|
|
- height: 200px;
|
|
|
- gap: 20px;
|
|
|
-
|
|
|
- /* 控制间距 */
|
|
|
- p {
|
|
|
- width: 150px;
|
|
|
- height: 40px;
|
|
|
- background: rgb(227, 227, 227);
|
|
|
- color: rgb(50, 50, 50);
|
|
|
- text-align: center;
|
|
|
- align-content: center;
|
|
|
- font-weight: 600;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+ .stat-content {
|
|
|
+ .label,
|
|
|
+ .count,
|
|
|
+ .ratio {
|
|
|
+ margin: 0;
|
|
|
+ line-height: 1.2;
|
|
|
+ }
|
|
|
+ .label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #303133;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ .count {
|
|
|
+ margin-top: 2px;
|
|
|
+ font-size: 30px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ .ratio {
|
|
|
+ margin-top: 2px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .btn-auto {
|
|
|
- margin-top: 10px;
|
|
|
- width: 100%;
|
|
|
+ &.is-normal .icon-wrap {
|
|
|
+ background: #008080;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- .Btn {
|
|
|
- width: 50%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- /* 垂直排列 */
|
|
|
- justify-content: space-between;
|
|
|
- /* 顶部和底部对齐 */
|
|
|
- min-height: 100px;
|
|
|
- /* 确保容器有足够高度 */
|
|
|
- margin: 10px 0;
|
|
|
-
|
|
|
- .PText {
|
|
|
- display: flex;
|
|
|
- justify-content: space-around;
|
|
|
-
|
|
|
- span {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- i {
|
|
|
- width: 30px;
|
|
|
- height: 15px;
|
|
|
- margin-right: 5px;
|
|
|
- }
|
|
|
-
|
|
|
- .color1 {
|
|
|
- background-color: #8ae359;
|
|
|
- }
|
|
|
-
|
|
|
- .color2 {
|
|
|
- background-color: #eecb5f;
|
|
|
- }
|
|
|
-
|
|
|
- .color3 {
|
|
|
- background-color: #f7715f;
|
|
|
- }
|
|
|
- }
|
|
|
+ &.is-warning .icon-wrap {
|
|
|
+ background: #e6a23c;
|
|
|
}
|
|
|
-
|
|
|
- margin: 10px 0;
|
|
|
-
|
|
|
- .minp {
|
|
|
- font-size: 12px;
|
|
|
- margin-top: auto;
|
|
|
- /* 自动推到最底部 */
|
|
|
+ &.is-danger .icon-wrap {
|
|
|
+ background: #f56c6c;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+.gear {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 10px;
|
|
|
+ .TopBox {
|
|
|
+ width: 40%;
|
|
|
+ }
|
|
|
+ .bottomBox {
|
|
|
+ width: 59%;
|
|
|
+ height: 360px;
|
|
|
+ }
|
|
|
+}
|
|
|
+h4 {
|
|
|
+ margin-bottom: 5px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
|
|
|
+.TopBox {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
.rightdiv {
|
|
|
width: 100%;
|
|
|
-
|
|
|
+ .monitor-panel {
|
|
|
+ border-radius: 14px;
|
|
|
+ padding: 14px;
|
|
|
+ min-height: 360px;
|
|
|
+ box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
|
+ height: 360px;
|
|
|
+ overflow-y: auto;
|
|
|
+ }
|
|
|
+ .monitor-empty {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 260px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ }
|
|
|
+ .monitor-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+ .monitor-item {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 14px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 10px;
|
|
|
+ background: #fff;
|
|
|
+ padding: 14px 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ &.is-active {
|
|
|
+ background: #f0f5f7;
|
|
|
+ }
|
|
|
+ &.is-active::before {
|
|
|
+ content: "";
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 10px;
|
|
|
+ bottom: 10px;
|
|
|
+ width: 4px;
|
|
|
+ background: #74727224;
|
|
|
+ box-shadow: 0 0 0 2px #24a16600 inset;
|
|
|
+ border-radius: 0 4px 4px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .index-badge {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ border-radius: 50%;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ flex-shrink: 0;
|
|
|
+ &.is-success {
|
|
|
+ background: #008080;
|
|
|
+ }
|
|
|
+ &.is-warning {
|
|
|
+ background: #e6a23c;
|
|
|
+ }
|
|
|
+ &.is-danger {
|
|
|
+ background: #f56c6c;
|
|
|
+ }
|
|
|
+ &.is-info {
|
|
|
+ background: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .item-main {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ .item-name {
|
|
|
+ margin: 0 0 8px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1f2d3d;
|
|
|
+ }
|
|
|
+ .item-line {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 1.5;
|
|
|
+ color: #6b7280;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .item-right {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ }
|
|
|
+ .status-pill {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 10px 16px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1;
|
|
|
+ .status-dot {
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: currentColor;
|
|
|
+ }
|
|
|
+ &.is-success {
|
|
|
+ color: #21a366;
|
|
|
+ background: #e7f6ee;
|
|
|
+ }
|
|
|
+ &.is-warning {
|
|
|
+ color: #d48806;
|
|
|
+ background: #fff6e5;
|
|
|
+ }
|
|
|
+ &.is-danger {
|
|
|
+ color: #f04438;
|
|
|
+ background: #ffebee;
|
|
|
+ }
|
|
|
+ &.is-info {
|
|
|
+ color: #606266;
|
|
|
+ background: #f4f4f5;
|
|
|
+ }
|
|
|
+ }
|
|
|
.fenye {
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- margin: 5px 0;
|
|
|
- font-size: 11px;
|
|
|
+ justify-content: flex-end;
|
|
|
+ margin: 10px 0 0;
|
|
|
+ font-size: 12px;
|
|
|
line-height: 30px;
|
|
|
-
|
|
|
span {
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
@@ -466,63 +750,16 @@ h4 {
|
|
|
.bottomBox {
|
|
|
display: flex;
|
|
|
justify-content: space-around;
|
|
|
- margin-top: 10px;
|
|
|
-
|
|
|
+ box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
|
+ border-radius: 12px;
|
|
|
.BtLeft {
|
|
|
- border: 1px solid rgb(231, 231, 231);
|
|
|
width: 100%;
|
|
|
- padding: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .BtRight {
|
|
|
- border: 1px solid rgb(231, 231, 231);
|
|
|
- padding: 10px;
|
|
|
-
|
|
|
- .BtRightDiv {
|
|
|
- padding: 0 10px;
|
|
|
-
|
|
|
- h4 {
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
-
|
|
|
- .BtRightP {
|
|
|
- line-height: 30px;
|
|
|
- font-size: 12px;
|
|
|
- display: flex;
|
|
|
- margin-bottom: 5px;
|
|
|
- width: 50%;
|
|
|
-
|
|
|
- span {
|
|
|
- margin-left: 10px;
|
|
|
-
|
|
|
- .el-input {
|
|
|
- width: 100px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .label-text {
|
|
|
- width: 140px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .canshu {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- justify-content: space-between;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .dialog-footer {
|
|
|
- margin-top: 20px;
|
|
|
- text-align: right;
|
|
|
+ padding: 10px 20px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.mpoint-charts {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
- gap: 16px;
|
|
|
+ display: block;
|
|
|
}
|
|
|
|
|
|
.mpoint-chart-item {
|
|
|
@@ -531,18 +768,51 @@ h4 {
|
|
|
padding: 8px 10px;
|
|
|
}
|
|
|
|
|
|
-.mpoint-chart-title {
|
|
|
- margin: 0 0 6px;
|
|
|
- font-size: 13px;
|
|
|
- color: #303133;
|
|
|
-}
|
|
|
-
|
|
|
-@media (max-width: 1200px) {
|
|
|
- .mpoint-charts {
|
|
|
- grid-template-columns: 1fr;
|
|
|
+.status-legend {
|
|
|
+ margin: 4px 0 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ .legend-label {
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ .legend-item {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ .legend-dot {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: currentColor;
|
|
|
+ }
|
|
|
+ &.is-normal {
|
|
|
+ color: #008080;
|
|
|
+ }
|
|
|
+ &.is-warning {
|
|
|
+ color: #e6a23c;
|
|
|
+ }
|
|
|
+ &.is-danger {
|
|
|
+ color: #f56c6c;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+::v-deep .el-carousel__indicator .el-carousel__button {
|
|
|
+ background-color: rgba(144, 147, 153, 0.45);
|
|
|
+ opacity: 1;
|
|
|
+}
|
|
|
+::v-deep .el-carousel__indicator.is-active .el-carousel__button {
|
|
|
+ background-color: #24a166;
|
|
|
+}
|
|
|
+::v-deep .el-carousel__indicator:hover .el-carousel__button {
|
|
|
+ background-color: #24a166aa;
|
|
|
+}
|
|
|
+::v-deep .el-carousel__indicators--horizontal {
|
|
|
+ bottom: -10px !important;
|
|
|
+}
|
|
|
::v-deep .el-table__cell {
|
|
|
padding: 2px 0;
|
|
|
font-size: 12px;
|