diff --git a/src/assets/icons/svg/cgq.svg b/src/assets/icons/svg/cgq.svg
new file mode 100644
index 0000000..f651888
--- /dev/null
+++ b/src/assets/icons/svg/cgq.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/fan.svg b/src/assets/icons/svg/fan.svg
new file mode 100644
index 0000000..fc2be17
--- /dev/null
+++ b/src/assets/icons/svg/fan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/gjdj.svg b/src/assets/icons/svg/gjdj.svg
new file mode 100644
index 0000000..7fdf89a
--- /dev/null
+++ b/src/assets/icons/svg/gjdj.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/pump.svg b/src/assets/icons/svg/pump.svg
new file mode 100644
index 0000000..ed8c917
--- /dev/null
+++ b/src/assets/icons/svg/pump.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
index dbbdc00..7f30e90 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -76,8 +76,8 @@ export const constantRoutes = [
path: 'index',
component: () => import('@/views/index'),
name: 'Index',
- meta: { title: '工作台', icon: 'index', affix: true }
- // meta: { title: '首页', icon: '@/assets/treeIcons/index.png', affix: true }
+ meta: { title: '工作台', icon: 'index' }
+ // meta: { title: '首页', icon: '@/assets/treeIcons/index.png', affix: true } affix 是否常驻
},
]
},
@@ -90,7 +90,7 @@ export const constantRoutes = [
path: 'plan',
component: () => import('@/views/plan'),
name: 'Plan',
- meta: { title: '平面图', icon: 'plan', affix: true }
+ meta: { title: '平面图', icon: 'plan' }
},
]
@@ -234,6 +234,71 @@ export const constantRoutes = [
},
]
},
+ {
+ name: "linkConfig",
+ alwaysShow: true,
+ component: Layout,
+ hidden: false,
+ name: "linkConfig",
+ path: "/linkConfig",
+ redirect: "noRedirect",
+ meta: {
+ icon: "link",
+ link: null,
+ noCache: false,
+ title: "联动配置管理",
+ },
+ children: [
+ {
+ component: () => import('@/views/linkConfig/alarmConfig'),
+ hidden: false,
+ name: "alarmConfig",
+ path: "alarmConfig",
+ meta: {
+ icon: "gjdj",
+ link: null,
+ noCache: false,
+ title: "报警等级配置",
+ },
+ },
+ {
+ component: () => import('@/views/linkConfig/fanLinkConfig'),
+ hidden: false,
+ name: "fanLinkConfig",
+ path: "fanLinkConfig",
+ meta: {
+ icon: "fan",
+ link: null,
+ noCache: false,
+ title: "风机联动阈值配置",
+ },
+ },
+ {
+ component: () => import('@/views/linkConfig/pumpLinkConfig'),
+ hidden: false,
+ name: "pumpLinkConfig",
+ path: "pumpLinkConfig",
+ meta: {
+ icon: "pump",
+ link: null,
+ noCache: false,
+ title: "水泵联动阈值配置",
+ },
+ },
+ {
+ component: () => import('@/views/linkConfig/sensorConfig'),
+ hidden: false,
+ name: "sensorConfig",
+ path: "sensorConfig",
+ meta: {
+ icon: "cgq",
+ link: null,
+ noCache: false,
+ title: "传感器报警阈值",
+ },
+ },
+ ]
+ },
{
name: "Equipment",
diff --git a/src/views/linkConfig/alarmConfig.vue b/src/views/linkConfig/alarmConfig.vue
new file mode 100644
index 0000000..203db83
--- /dev/null
+++ b/src/views/linkConfig/alarmConfig.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存等级配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存时间配置
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/linkConfig/fanLinkConfig.vue b/src/views/linkConfig/fanLinkConfig.vue
new file mode 100644
index 0000000..16ff658
--- /dev/null
+++ b/src/views/linkConfig/fanLinkConfig.vue
@@ -0,0 +1,1222 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 温度
+
+
+ {{ zone.thresholds.temperature.start }}℃
+ /
+ {{ zone.thresholds.temperature.stop }}℃
+
+
+
+
+
+
+ 湿度
+
+
+ {{ zone.thresholds.humidity.start }}%
+ /
+ {{ zone.thresholds.humidity.stop }}%
+
+
+
+
+
+
+ 氧气
+
+
+ {{ zone.thresholds.oxygen.start }}%
+ /
+ {{ zone.thresholds.oxygen.stop }}%
+
+
+
+
+
+
+ 硫化氢
+
+
+ {{ zone.thresholds.h2s.start }}ppm
+ /
+ {{ zone.thresholds.h2s.stop }}ppm
+
+
+
+
+
+
+ 甲烷
+
+
+ {{ zone.thresholds.methane.start }}LEL
+ /
+ {{ zone.thresholds.methane.stop }}LEL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.temperature }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.humidity }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.oxygen }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.h2s }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.methane }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.temperature }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.humidity }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.oxygen }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.h2s }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.methane }}
+
+
+
+
+
+
+
+
+ • 请至少选择一个分区进行配置
+ • 请至少设置一个参数的阈值(开启或停止阈值不为0)
+ • 只有设置了阈值的参数才会被保存
+ • 氧气参数:开启阈值应小于停止阈值
+ • 其他参数:开启阈值应大于停止阈值
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/linkConfig/pumpLinkConfig.vue b/src/views/linkConfig/pumpLinkConfig.vue
new file mode 100644
index 0000000..32d1225
--- /dev/null
+++ b/src/views/linkConfig/pumpLinkConfig.vue
@@ -0,0 +1,830 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 基于1分区液位
+
+
+ {{ zone.thresholds.self.start }}cm
+ /
+ {{ zone.thresholds.self.stop }}cm
+
+
+
+
+
+
+ 基于2分区液位
+
+
+ {{ zone.thresholds.zone2.start }}cm
+ /
+ {{ zone.thresholds.zone2.stop }}cm
+
+
+
+
+
+
+
+
+
+ 液位高度
+
+
+ {{ zone.thresholds.self.start }}cm
+ /
+ {{ zone.thresholds.self.stop }}cm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.self }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.zone2 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentZone.errors.self }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ batchErrors.self }}
+
+
+
+
+
+
+
+
+ • 请至少选择一个分区进行配置
+ • 启动水泵阈值应大于停止水泵阈值
+ • 批量配置只会设置各分区基于自身液位的阈值
+ • 1分区的基于2分区液位配置需要单独设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/linkConfig/sensorConfig.vue b/src/views/linkConfig/sensorConfig.vue
new file mode 100644
index 0000000..db75c2c
--- /dev/null
+++ b/src/views/linkConfig/sensorConfig.vue
@@ -0,0 +1,356 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存配置
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/plan.vue b/src/views/plan.vue
index 39cab86..4796a93 100644
--- a/src/views/plan.vue
+++ b/src/views/plan.vue
@@ -70,10 +70,7 @@
-
+
+
@@ -158,6 +158,7 @@ import {
import typesDictionary from "../utils/equipmentType"; //设备类型字典
import videoEle from "./components/videoEle.vue";
import tableEle from "./components/tableEle.vue";
+import * as echarts from "echarts";
const tableModelValue = ref(false);
// 新增:底层背景Canvas引用
@@ -248,7 +249,7 @@ const MOUSE_CURRENT_Y = ref(0);
const activeMarker = ref({ target: "" });
const Shrink = ref(false);
-const SELECT_ACTION_TYPE = ref('');
+const SELECT_ACTION_TYPE = ref("");
//背景图片/标记图片等(保持不变)
const backgroundImage = new URL("../assets/gl.png", import.meta.url).href;
@@ -276,7 +277,10 @@ const icons = {
};
icons.baiye.src = new URL("../assets/icon/baiye.png", import.meta.url).href;
-icons.dianbiao.src = new URL("../assets/icon/dianbiao.png", import.meta.url).href;
+icons.dianbiao.src = new URL(
+ "../assets/icon/dianbiao.png",
+ import.meta.url
+).href;
icons.hongwai.src = new URL("../assets/icon/hongwai.png", import.meta.url).href;
icons.jiawan.src = new URL("../assets/icon/jiawan.png", import.meta.url).href;
icons.jingai.src = new URL("../assets/icon/jingai.png", import.meta.url).href;
@@ -303,6 +307,170 @@ const updateTableModelValue = (value) => {
tableModelValue.value = value;
};
+// 图表引用和实例
+const chartRef = ref(null);
+let chartInstance = null;
+
+// 状态变量
+const darkMode = ref(true);
+const chartData = ref({
+ xAxis: [
+ "1月",
+ "2月",
+ "3月",
+ "4月",
+ "5月",
+ "6月",
+ "7月",
+ "8月",
+ "9月",
+ "10月",
+ "11月",
+ "12月",
+ ],
+ series: [
+ {
+ name: "产品A",
+ data: [120, 132, 101, 134, 90, 230, 210, 230, 180, 230, 210, 250],
+ color: "#42b983", // 柔和的绿色
+ },
+ {
+ name: "产品B",
+ data: [220, 182, 191, 234, 290, 330, 310, 330, 380, 330, 310, 350],
+ color: "#3498db", // 柔和的蓝色
+ },
+ {
+ name: "产品C",
+ data: [150, 232, 201, 154, 190, 330, 410, 330, 380, 430, 410, 450],
+ color: "#f39c12", // 柔和的橙色
+ },
+ ],
+});
+
+// 初始化图表
+const initChart = () => {
+ // 销毁已有实例
+ if (chartInstance) {
+ chartInstance.dispose();
+ }
+
+ // 创建新实例
+ chartInstance = echarts.init(chartRef.value);
+
+ // 设置图表选项
+ const option = {
+ backgroundColor: darkMode.value
+ ? "rgba(30, 30, 30, 0.7)"
+ : "rgba(255, 255, 255, 0.7)",
+ tooltip: {
+ trigger: "axis",
+ backgroundColor: darkMode.value
+ ? "rgba(40, 40, 40, 0.9)"
+ : "rgba(255, 255, 255, 0.9)",
+ borderColor: darkMode.value ? "#555" : "#ddd",
+ textStyle: {
+ color: darkMode.value ? "#fff" : "#333",
+ },
+ padding: 10,
+ borderRadius: 6,
+ },
+ legend: {
+ data: chartData.value.series.map((item) => item.name),
+ top: 10,
+ textStyle: {
+ color: darkMode.value ? "#eee" : "#555",
+ },
+ },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "3%",
+ containLabel: true,
+ },
+ xAxis: {
+ type: "category",
+ boundaryGap: false,
+ data: chartData.value.xAxis,
+ axisLine: {
+ lineStyle: {
+ color: darkMode.value ? "#555" : "#ddd",
+ },
+ },
+ axisLabel: {
+ color: darkMode.value ? "#bbb" : "#666",
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: darkMode.value
+ ? "rgba(255, 255, 255, 0.05)"
+ : "rgba(0, 0, 0, 0.05)",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLine: {
+ lineStyle: {
+ color: darkMode.value ? "#555" : "#ddd",
+ },
+ },
+ axisLabel: {
+ color: darkMode.value ? "#bbb" : "#666",
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: darkMode.value
+ ? "rgba(255, 255, 255, 0.05)"
+ : "rgba(0, 0, 0, 0.05)",
+ },
+ },
+ },
+ series: chartData.value.series.map((item) => ({
+ name: item.name,
+ type: "line",
+ data: item.data,
+ symbol: "circle",
+ symbolSize: 6,
+ emphasis: {
+ symbolSize: 8,
+ },
+ lineStyle: {
+ width: 2,
+ color: item.color,
+ },
+ itemStyle: {
+ color: item.color,
+ borderWidth: 2,
+ borderColor: darkMode.value ? "#333" : "#fff",
+ },
+ areaStyle: {
+ color: {
+ type: "linear",
+ x: 0,
+ y: 0,
+ x2: 0,
+ y2: 1,
+ colorStops: [
+ {
+ offset: 0,
+ color: item.color + "80", // 透明度80%
+ },
+ {
+ offset: 1,
+ color: item.color + "00", // 透明度0%
+ },
+ ],
+ },
+ },
+ })),
+ };
+
+ // 设置选项
+ chartInstance.setOption(option);
+};
+
const pointsToPartiData = (data) => {
let _partiData = {};
let areaId = 0;
@@ -327,7 +495,7 @@ const handleTabbar = (e) => {
d.isSelected = false;
}
});
- if(e.isSelected) {
+ if (e.isSelected) {
SELECT_ACTION_TYPE.value = e.value;
} else {
SELECT_ACTION_TYPE.value = "";
@@ -401,15 +569,15 @@ const drawBackground = () => {
// 初始化Canvas(修改:同时初始化两层Canvas)
const initCanvas = () => {
- nextTick(()=> {
+ nextTick(() => {
// 初始化上层主Canvas
ctx.value = canvasRef.value.getContext("2d");
// 初始化底层背景Canvas
bgCtx.value = bgCanvasRef.value.getContext("2d");
-
+
// 加载背景图(加载完成后绘制底层背景)
loadImage();
- })
+ });
};
const getIcon = (id) => {
@@ -444,18 +612,18 @@ const resizeCanvas = () => {
// 同时设置两层Canvas的大小(保持一致)
const clientWidth = canvasRef.value.clientWidth;
const clientHeight = canvasRef.value.clientHeight;
-
+
canvasRef.value.width = clientWidth;
canvasRef.value.height = clientHeight;
bgCanvasRef.value.width = clientWidth;
bgCanvasRef.value.height = clientHeight;
-
+
canvasWidthNum.value = clientWidth;
canvasHeightNum.value = clientHeight;
-
+
BL.value = clientHeight / StandardC;
getCurrentArea();
-
+
// 窗口 resize 时需要重新绘制背景
drawBackground();
// 同时重绘上层内容
@@ -481,7 +649,14 @@ const getCurrentArea = () => {
};
const isCGQ = (type) => {
- if (type == 26 || type == 30 || type == 31 || type == 32 || type == 34 || type == 35) {
+ if (
+ type == 26 ||
+ type == 30 ||
+ type == 31 ||
+ type == 32 ||
+ type == 34 ||
+ type == 35
+ ) {
return true;
}
return false;
@@ -516,7 +691,7 @@ const drawTooltip = () => {
const canvasY = activeMarker.value.y * BL.value * scale.value + offsetY.value;
let x = canvasX - tooltipWidth / 2;
- let y = canvasY - tooltipHeight - (20 * scale.value);
+ let y = canvasY - tooltipHeight - 20 * scale.value;
const canvasWidth = canvasRef.value.width;
const canvasHeight = canvasRef.value.height;
@@ -536,7 +711,13 @@ const drawTooltip = () => {
ctxTooltip.lineTo(x + tooltipWidth - radius, y);
ctxTooltip.arcTo(x + tooltipWidth, y, x + tooltipWidth, y + radius, radius);
ctxTooltip.lineTo(x + tooltipWidth, y + tooltipHeight - radius);
- ctxTooltip.arcTo(x + tooltipWidth, y + tooltipHeight, x + tooltipWidth - radius, y + tooltipHeight, radius);
+ ctxTooltip.arcTo(
+ x + tooltipWidth,
+ y + tooltipHeight,
+ x + tooltipWidth - radius,
+ y + tooltipHeight,
+ radius
+ );
ctxTooltip.lineTo(x + radius, y + tooltipHeight);
ctxTooltip.arcTo(x, y + tooltipHeight, x, y + tooltipHeight - radius, radius);
ctxTooltip.lineTo(x, y + radius);
@@ -580,7 +761,7 @@ const draw = (alpha = 1) => {
const canvasHeight = canvasRef.value.height;
BL.value = canvasHeight / StandardC;
-
+
// 清除上层画布(只清除动态内容)
ctx.value.clearRect(0, 0, canvasWidth, canvasHeight);
@@ -613,8 +794,11 @@ const draw = (alpha = 1) => {
for (const key in points) {
let _points = points[key];
_points.forEach((point) => {
- if(SELECT_ACTION_TYPE.value && point.TypeId !== SELECT_ACTION_TYPE.value) {
- return
+ if (
+ SELECT_ACTION_TYPE.value &&
+ point.TypeId !== SELECT_ACTION_TYPE.value
+ ) {
+ return;
}
let status = getIconStatus(point.TypeId);
@@ -655,19 +839,78 @@ const draw = (alpha = 1) => {
);
}
- // 添加文字传感器数值
- if(point.TypeId == 26) {
+ // 辅助函数:绘制圆角矩形
+ function roundedRect(ctx, x, y, width, height, radius, isStroke = false) {
+ ctx.beginPath();
+ ctx.moveTo(x + radius, y);
+ ctx.lineTo(x + width - radius, y);
+ ctx.arcTo(x + width, y, x + width, y + radius, radius);
+ ctx.lineTo(x + width, y + height - radius);
+ ctx.arcTo(
+ x + width,
+ y + height,
+ x + width - radius,
+ y + height,
+ radius
+ );
+ ctx.lineTo(x + radius, y + height);
+ ctx.arcTo(x, y + height, x, y + height - radius, radius);
+ ctx.lineTo(x, y + radius);
+ ctx.arcTo(x, y, x + radius, y, radius);
+ ctx.closePath();
+
+ if (isStroke) {
+ ctx.stroke();
+ } else {
+ ctx.fill();
+ }
+ }
+
+ // 添加文字传感器数值(带圆角边框和半透明背景)
+ if (point.TypeId == 26) {
+ // 设置字体样式
+ ctx.value.font = `10px Arial`;
+ const textColor = "#FFF"; // 白色字体
+ const borderColor = "rgba(100, 180, 255, 0.9)"; // 浅蓝色边框
+ const bgColor = "rgba(100, 180, 255, 0.4)"; // 同色系半透明背景
+
+ let _value = point.Data[0].Value; // 传感器数值value
- ctx.value.font = `10px Arial`; // 设置字体和大小
- ctx.value.fillStyle = "#FFF"; // 设置文字颜色
// 计算文字位置(图标右侧10px处,垂直居中对齐)
+ const textX = point.x * BL.value;
+ const textY = point.y * BL.value + 20; // 垂直居中调整
- let _value = point.Data[0].Value; //传感器数值value
+ // 测量文本宽度,用于计算背景框大小
+ const textMetrics = ctx.value.measureText(_value);
+ const padding = 3; // 文字周围的内边距
+ const borderRadius = 3; // 圆角半径
- const textX = point.x * BL.value + (iSize * BL.value) / scale.value / 2 + 1;
- const textY = point.y * BL.value + 15; // +5是为了视觉上垂直居中
- ctx.value.fillText(_value, textX, textY); // 绘制文字
+ // 计算背景框的位置和大小
+ const bgX = textX - padding - textMetrics.width / 2;
+ const bgY = textY - 10; // 基于10px字体的位置调整
+ const bgWidth = textMetrics.width + padding * 2;
+ const bgHeight = 14; // 适合10px字体的高度
+ // 绘制圆角背景
+ ctx.value.fillStyle = bgColor;
+ roundedRect(ctx.value, bgX, bgY + 10, bgWidth, bgHeight, borderRadius);
+
+ // 绘制圆角边框
+ ctx.value.strokeStyle = borderColor;
+ ctx.value.lineWidth = 1;
+ roundedRect(
+ ctx.value,
+ bgX,
+ bgY + 10,
+ bgWidth,
+ bgHeight,
+ borderRadius,
+ true
+ );
+
+ // 绘制文字(确保在最上层)
+ ctx.value.fillStyle = textColor;
+ ctx.value.fillText(_value, textX - textMetrics.width / 2, textY + 10);
}
if (point.target == "device" && point.IsOpen) {
@@ -682,7 +925,11 @@ const draw = (alpha = 1) => {
ctx.value.strokeStyle = window.customConfigUrl.faultColor;
ctx.value.lineWidth = (4 / scale.value) * BL.value;
ctx.value.stroke();
- } else if (point.target == "device" && !isCGQ(point.TypeId) && point.TypeId != 66) {
+ } else if (
+ point.target == "device" &&
+ !isCGQ(point.TypeId) &&
+ point.TypeId != 66
+ ) {
ctx.value.strokeStyle = window.customConfigUrl.closeColor;
ctx.value.lineWidth = (4 / scale.value) * BL.value;
ctx.value.stroke();
@@ -716,7 +963,7 @@ const animate = () => {
let mouseMoveTimeout = null;
const MOUSE_MOVE_DELAY = 16;
const onMouseMove = (e) => {
- if(!BL.value) return;
+ if (!BL.value) return;
if (dragging.value === null) {
if (mouseMoveTimeout) {
cancelAnimationFrame(mouseMoveTimeout);
@@ -763,7 +1010,8 @@ const onMouseMove = (e) => {
activeReferenceLine.value = closestLine;
if (closestLine !== null) {
const easingFactor = 0.2;
- currentPoint.y = currentPoint.y + (closestLine - currentPoint.y) * easingFactor;
+ currentPoint.y =
+ currentPoint.y + (closestLine - currentPoint.y) * easingFactor;
if (Math.abs(currentPoint.y - closestLine) < 10) {
currentPoint.y = closestLine;
}
@@ -934,7 +1182,10 @@ const handleWheel = (e) => {
const zoomIntensity = 0.1;
const wheel = e.deltaY < 0 ? 1 : -1;
- const newScale = Math.max(0.75, Math.min(2, scale.value + wheel * zoomIntensity));
+ const newScale = Math.max(
+ 0.75,
+ Math.min(2, scale.value + wheel * zoomIntensity)
+ );
scalePercent.value = Math.round(newScale * 100);
@@ -942,7 +1193,7 @@ const handleWheel = (e) => {
offsetY.value = mouseY - imgY * newScale;
scale.value = newScale;
-
+
// 缩放时需要重新绘制背景
drawBackground();
// 同时重绘上层内容
@@ -960,7 +1211,9 @@ const handleCanvasClick = (e) => {
const originalY = (y - offsetY.value) / scale.value;
console.log(
- `点击坐标: (${(originalX / BL.value).toFixed(1)}, ${(originalY / BL.value).toFixed(1)})`
+ `点击坐标: (${(originalX / BL.value).toFixed(1)}, ${(
+ originalY / BL.value
+ ).toFixed(1)})`
);
let clickedPoint = false;
@@ -1008,7 +1261,7 @@ const resetView = () => {
selectedPointId.value = null;
progress.value = 0;
selectAreaId.value = 1;
-
+
// 重置背景
drawBackground();
// 重置上层内容
@@ -1137,6 +1390,7 @@ const upDialogZindex = (e) => {
// 初始化
onMounted(() => {
getJson();
+ initChart();
window.addEventListener("resize", resizeCanvas);
initCanvas();
// animate(); // 根据原代码注释,按需启用
@@ -1282,7 +1536,8 @@ body {
}
/* 新增:两层Canvas样式,确保完全重叠 */
-.bg-canvas, .main-canvas {
+.bg-canvas,
+.main-canvas {
display: block;
width: 100%;
height: 100%;
@@ -1383,9 +1638,8 @@ button:active {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(4px);
border-radius: 4px;
- margin-top: 15px;
position: absolute;
- bottom: 30px;
+ top: 30px;
left: 50%;
transform: translateX(-50%);
box-shadow: 0 4px 10px rgba(255, 255, 255, 0.1);
@@ -1407,6 +1661,24 @@ button:active {
width: 100%;
}
+.charts-content {
+ width: 800px;
+ height: 240px;
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(4px);
+ border-radius: 4px;
+ position: absolute;
+ bottom: 30px;
+ left: 50%;
+ transform: translateX(-50%);
+ box-shadow: 0 4px 10px rgba(255, 255, 255, 0.1);
+ display: flex;
+ .line-chart {
+ width: 100%;
+ height: 100%;
+ }
+}
+
/deep/ .el-slider__button {
height: 10px !important;
width: 10px !important;
diff --git a/src/views/system/log/index.vue b/src/views/system/log/index.vue
index 8dacc4d..8e01b11 100644
--- a/src/views/system/log/index.vue
+++ b/src/views/system/log/index.vue
@@ -55,6 +55,9 @@
查询
+
+ 导出
+