| | |
| | | text-indent: 80px; |
| | | letter-spacing: 2px; |
| | | } |
| | | |
| | | .left-content { |
| | | margin-top: 20px; |
| | | background: url("@/assets/img/left/leftbg.png"); |
| | |
| | | width: 100%; |
| | | height: calc(100% - 70px); |
| | | } |
| | | |
| | | .el-button { |
| | | background-color: #009688 !important; |
| | | border-color: #009688 !important; |
| | |
| | | border-color: #009688 !important; |
| | | color: #fff !important; |
| | | } |
| | | |
| | | .el-picker-panel__icon-btn { |
| | | color: #fff !important; |
| | | font-size: 18px; |
| | | } |
| | | .el-date-range-picker__header [class*="arrow-left"] { |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .el-select-dropdown__item.is-hovering { |
| | | background-color: #009688; |
| | | } |
| | | |
| | | .el-select__placeholder { |
| | | color: white; |
| | | } |
| | | .el-select-dropdown__item.hover, |
| | | .el-select-dropdown__item:hover { |
| | | color: white !important; |
| | | background-color: rgb(38, 124, 124, 0.5) !important; |
| | | } |
| | | .el-select__placeholder, |
| | | .el-form-item__label, |
| | | .el-input__inner { |
| | | color: #fff !important; |
| | | } |
| | | |
| | | .el-slider__bar { |
| | | background-color: #009688 !important; |
| | | border-color: #009688 !important; |
| | |
| | | .el-slider__button { |
| | | border-color: rgb(0, 150, 136) !important; |
| | | } |
| | | |
| | | .el-select-dropdown { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-picker-panel__body div { |
| | | background: #084b42 !important; |
| | | } |
| | | |
| | | .el-picker-panel { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item { |
| | | color: white !important; |
| | | font-size: 12px !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item.hover, |
| | | .el-select-dropdown__item:hover { |
| | | color: #409eff !important; |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .el-select__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .el-time-spinner__item:hover:not(.is-disabled):not(.is-active), |
| | | .el-date-table td.current:not(.disabled) .el-date-table-cell__text { |
| | | background: #009688 !important; |
| | | } |
| | | |
| | | .el-picker-panel__footer { |
| | | background-color: #084b42 !important; |
| | | } |
| | | |
| | | .el-date-table td.end-date .el-date-table-cell__text, |
| | | .el-date-table td.start-date .el-date-table-cell__text { |
| | | background-color: #61f7d4 !important; |
| | | } |
| | | |
| | | .el-date-table td.today .el-date-table-cell__text { |
| | | color: #61f7d4 !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item.hover, |
| | | .el-select-dropdown__item:hover, |
| | | .el-time-panel__btn.confirm, |
| | | .el-date-editor .el-range-separator, |
| | | .el-date-editor .el-range-input, |
| | | .el-time-panel__btn, |
| | | .el-time-spinner__item, |
| | | .el-date-table th, |
| | | .el-picker-panel__body, |
| | | .el-select__placeholder, |
| | | .el-form-item__label, |
| | | .el-input__inner, |
| | | .el-select__placeholder, |
| | | .el-date-range-picker__header [class*="arrow-left"] { |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-date-editor.el-input, |
| | | .el-date-editor.el-input__wrapper { |
| | | height: 100% !important; |
| | | width: 100% !important; |
| | | } |
| | |
| | | color: white !important; |
| | | } |
| | | </style> |
| | | <style> |
| | | .el-select-dropdown { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-picker-panel__body { |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-picker-panel__body div { |
| | | background: transparent !important; |
| | | } |
| | | |
| | | .el-picker-panel { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item { |
| | | color: white !important; |
| | | font-size: 12px !important; |
| | | } |
| | | |
| | | .el-date-table th { |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item.hover, |
| | | .el-select-dropdown__item:hover { |
| | | color: #409eff !important; |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .el-select__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | </style> |
| | |
| | | color: white !important; |
| | | } |
| | | </style> |
| | | <style> |
| | | .el-select-dropdown { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-picker-panel__body { |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-picker-panel__body div { |
| | | background: transparent !important; |
| | | } |
| | | |
| | | .el-picker-panel { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item { |
| | | color: white !important; |
| | | font-size: 12px !important; |
| | | } |
| | | |
| | | .el-date-table th { |
| | | color: white !important; |
| | | } |
| | | |
| | | .el-select-dropdown__item.hover, |
| | | .el-select-dropdown__item:hover { |
| | | color: #409eff !important; |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .el-select__wrapper { |
| | | background: rgba(8, 75, 66, 1) !important; |
| | | border: 2px solid #437a74 !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .level-list { |
| | | display: flex; |
| | | margin-top: 10px; |
| | | flex-wrap: wrap; |
| | | |
| | | .level-item { |
| | | width: 150px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | text-align: center; |
| | | background: rgba(8, 75, 66, 1); |
| | | color: white; |
| | | margin-right: 10px; |
| | | margin-bottom: 10px; |
| | | cursor: pointer; |
| | | border-radius: 5px; |
| | | |
| | | &.active { |
| | | background: #11b6a6; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | return timeOnly; |
| | | }; |
| | | |
| | | //初始化并配置第一个ECharts图表(降雨数据图表) |
| | | const setEcharts1 = () => { |
| | | // 获取DOM元素并初始化ECharts实例 |
| | | // 1. 初始化图表 |
| | | const chartDom = document.getElementById("echarts1"); |
| | | myChart1 = echarts.init(chartDom); |
| | | |
| | | // 响应式数据定义 |
| | | let rainfallData = ref([]); // 存储从JSON加载的原始降雨数据 |
| | | let data1 = ref([]); // 存储降雨数据(mm/min) |
| | | let data2 = ref([]); // 存储累计雨量数据(mm) |
| | | let xAxisData = ref([]); // 存储x轴时间数据 |
| | | let updateInterval = null; // 定时器ID |
| | | let dataIndex = ref(0); // 当前数据索引 |
| | | // 2. 数据定义(完全保持您的原始变量) |
| | | let rainfallData = ref([]); |
| | | let data1 = ref([]); |
| | | let data2 = ref([]); |
| | | let xAxisData = ref([]); |
| | | let updateInterval = null; |
| | | let dataIndex = ref(0); |
| | | |
| | | // 从JSON文件加载降雨数据 |
| | | |
| | | // 4. 动态计算Y轴(新增的核心逻辑) |
| | | const getDynamicYAxis = (dataArray) => { |
| | | const currentMax = Math.max(...dataArray, 1); // 确保最小显示范围 |
| | | const step = Math.ceil(currentMax / 3); |
| | | return { |
| | | max: step * 3, |
| | | interval: step, |
| | | }; |
| | | }; |
| | | |
| | | // 5. 加载数据(完全保持您的逻辑) |
| | | const loadJsonData = async () => { |
| | | try { |
| | | // 发起网络请求获取数据 |
| | | const response = await fetch("/json/rainfall.json"); |
| | | const result = await response.json(); |
| | | |
| | | // 验证数据格式 |
| | | if (result && result.data && Array.isArray(result.data)) { |
| | | if (result?.data?.length) { |
| | | rainfallData.value = result.data; |
| | | xAxisData.value = ["00:00"] || syncTimeWithTimeline(); // 初始时间点 |
| | | |
| | | // 计算数据的最大值用于y轴刻度 |
| | | const maxValue = Math.max( |
| | | ...rainfallData.value.map((item) => item.value) |
| | | ); |
| | | const maxTotal = Math.max( |
| | | ...rainfallData.value.map((item) => item.total) |
| | | ); |
| | | |
| | | // 初始化时间轴和第一个数据点 |
| | | xAxisData.value = ["00:00"]; // 起始时间 |
| | | if (rainfallData.value.length > 0) { |
| | | data1.value.push(rainfallData.value[0].value); // 添加第一个降雨数据 |
| | | data2.value.push(rainfallData.value[0].total); // 添加第一个累计雨量 |
| | | data1.value = [rainfallData.value[0].value]; |
| | | data2.value = [rainfallData.value[0].total]; |
| | | updateChart(); // 初始化图表 |
| | | } |
| | | |
| | | // 计算y轴参数并更新图表 |
| | | const yAxis1Params = calculateYAxisParams(maxValue); // 左侧y轴(降雨数据) |
| | | const yAxis2Params = calculateYAxisParams(maxTotal); // 右侧y轴(累计雨量) |
| | | updateChart(yAxis1Params, yAxis2Params); |
| | | } else { |
| | | console.error( |
| | | "Invalid JSON format: 'data' is missing or not an array!" |
| | | ); |
| | | } |
| | | } catch (error) { |
| | | console.error("Error fetching data:", error); |
| | | console.error("数据加载失败:", error); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * 计算y轴参数(生成均匀分布的刻度) |
| | | * @param {number} max - 数据最大值 |
| | | * @returns {Object} 包含max和interval的对象 |
| | | */ |
| | | const calculateYAxisParams = (max) => { |
| | | const step = Math.ceil(max / 3); // 将范围分成3等份(产生4个刻度点) |
| | | return { |
| | | max: step * 3, // 确保最大值是步长的整数倍 |
| | | interval: step, // 刻度间隔 |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * 更新图表配置 |
| | | * @param {Object} yAxis1Params - 左侧y轴参数 |
| | | * @param {Object} yAxis2Params - 右侧y轴参数 |
| | | */ |
| | | const updateChart = (yAxis1Params, yAxis2Params) => { |
| | | // 6. 图表配置(仅修改Y轴部分) |
| | | const updateChart = () => { |
| | | const option = { |
| | | animation: false, // 禁用动画提高性能 |
| | | |
| | | // 提示框配置 |
| | | tooltip: { |
| | | trigger: "axis", // 坐标轴触发 |
| | | axisPointer: { |
| | | // 指示器样式 |
| | | type: "cross", // 十字准星指示器 |
| | | crossStyle: { color: "#fff" }, // 白色线条 |
| | | }, |
| | | }, |
| | | |
| | | // 图表布局 |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", // 边距 |
| | | containLabel: true, // 包含坐标轴标签 |
| | | }, |
| | | |
| | | // 图例配置 |
| | | // >>> 保持您原有的所有配置 <<< |
| | | animation: false, |
| | | tooltip: { trigger: "axis" }, |
| | | grid: { left: "1%", right: "1%", bottom: "1%", containLabel: true }, |
| | | legend: { |
| | | data: ["降雨数据", "累计雨量"], // 系列名称 |
| | | textStyle: { color: "#fff" }, // 白色文字 |
| | | right: "10px", // 靠右对齐 |
| | | data: ["降雨数据", "累计雨量"], |
| | | textStyle: { color: "#fff" }, |
| | | }, |
| | | |
| | | // x轴配置(时间轴) |
| | | // >>> 您原来的xAxis配置(完全不变) <<< |
| | | xAxis: [ |
| | | { |
| | | type: "category", // 类目轴 |
| | | data: xAxisData.value, // 时间数据 |
| | | axisPointer: { type: "shadow" }, // 阴影指示器 |
| | | axisLabel: { |
| | | color: "#fff", // 白色标签 |
| | | rotate: 0, // 不旋转 |
| | | }, |
| | | type: "category", |
| | | data: xAxisData.value, // 您的时间数据 |
| | | axisLabel: { color: "#fff", rotate: 0 }, |
| | | }, |
| | | ], |
| | | |
| | | // y轴配置(双y轴) |
| | | // >>> 修改的Y轴配置(动态范围) <<< |
| | | yAxis: [ |
| | | // 左侧y轴(降雨数据) |
| | | { |
| | | type: "value", |
| | | name: "单位:mm", |
| | | min: 0, // 最小值为0 |
| | | max: yAxis1Params.max, // 动态计算的最大值 |
| | | interval: yAxis1Params.interval, // 动态计算的间隔 |
| | | axisLabel: { |
| | | formatter: "{value}", |
| | | color: "#fff", |
| | | align: "right", // 标签右对齐 |
| | | }, |
| | | nameTextStyle: { |
| | | padding: [0, 0, 0, 30], // 名称右侧内边距 |
| | | color: "#fff", |
| | | }, |
| | | splitLine: { show: false }, // 不显示网格线 |
| | | }, |
| | | // 右侧y轴(累计雨量) |
| | | { |
| | | // 左侧Y轴(降雨) |
| | | type: "value", |
| | | name: "单位:mm", |
| | | min: 0, |
| | | max: yAxis2Params.max, |
| | | interval: yAxis2Params.interval, |
| | | axisLabel: { |
| | | formatter: "{value}", |
| | | color: "#fff", |
| | | align: "left", // 标签左对齐 |
| | | }, |
| | | nameTextStyle: { |
| | | padding: [0, 10, 0, 0], // 名称左侧内边距 |
| | | color: "#fff", |
| | | }, |
| | | splitLine: { show: true }, // 显示网格线 |
| | | ...getDynamicYAxis(data1.value), // 动态范围 |
| | | axisLabel: { color: "#fff" }, |
| | | splitLine: { show: false }, |
| | | }, |
| | | { |
| | | // 右侧Y轴(累计) |
| | | type: "value", |
| | | name: "单位:mm", |
| | | min: 0, |
| | | ...getDynamicYAxis(data2.value), // 动态范围 |
| | | axisLabel: { color: "#fff" }, |
| | | splitLine: { show: true }, |
| | | }, |
| | | ], |
| | | |
| | | // 数据系列配置 |
| | | // >>> 保持您原有的series配置 <<< |
| | | series: [ |
| | | // 柱状图(降雨数据) |
| | | { |
| | | name: "降雨数据", |
| | | type: "bar", // 柱状图 |
| | | tooltip: { |
| | | valueFormatter: (value) => value + " mm/min", // 提示框单位 |
| | | }, |
| | | data: data1.value, // 绑定数据 |
| | | itemStyle: { color: "#3268fe" }, // 蓝色柱状图 |
| | | label: { show: false, color: "#fff" }, // 不显示数据标签 |
| | | type: "bar", |
| | | data: data1.value, |
| | | itemStyle: { color: "#3268fe" }, |
| | | }, |
| | | // 折线图(累计雨量) |
| | | { |
| | | name: "累计雨量", |
| | | type: "line", // 折线图 |
| | | yAxisIndex: 1, // 使用第二个y轴 |
| | | tooltip: { |
| | | valueFormatter: (value) => value + " mm", // 提示框单位 |
| | | }, |
| | | data: data2.value, // 绑定数据 |
| | | lineStyle: { color: "#ffb637" }, // 黄色线条 |
| | | label: { show: false, color: "#fff" }, // 不显示数据标签 |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | data: data2.value, |
| | | lineStyle: { color: "#ffb637" }, |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | // 应用配置到图表 |
| | | myChart1.setOption(option); |
| | | myChart1.setOption(option, true); |
| | | }; |
| | | |
| | | // 定时更新图表数据 |
| | | // 7. 数据更新(保持您的时间逻辑) |
| | | const updateData = () => { |
| | | // 检查是否还有数据需要显示 |
| | | if (dataIndex.value < rainfallData.value.length) { |
| | | const newItem = rainfallData.value[dataIndex.value]; |
| | | |
| | | // 添加新数据 |
| | | data1.value.push(newItem.value); // 添加降雨数据 |
| | | data2.value.push(newItem.total); // 添加累计雨量 |
| | | xAxisData.value.push(syncTimeWithTimeline()); // 添加时间点 |
| | | |
| | | dataIndex.value++; // 递增索引 |
| | | |
| | | // 更新图表(保持原有y轴范围) |
| | | updateChart( |
| | | { |
| | | max: myChart1.getOption().yAxis[0].max, |
| | | interval: myChart1.getOption().yAxis[0].interval, |
| | | }, |
| | | { |
| | | max: myChart1.getOption().yAxis[1].max, |
| | | interval: myChart1.getOption().yAxis[1].interval, |
| | | } |
| | | ); |
| | | const item = rainfallData.value[dataIndex.value]; |
| | | data1.value.push(item.value); |
| | | data2.value.push(item.total); |
| | | xAxisData.value.push(syncTimeWithTimeline()); // 您的时间生成方法 |
| | | dataIndex.value++; |
| | | updateChart(); // 动态调整Y轴 |
| | | } else { |
| | | console.log("All data has been displayed."); |
| | | stopUpdating(); // 数据全部显示完成后停止更新 |
| | | stopUpdating(); |
| | | } |
| | | }; |
| | | |
| | | //启动定时更新 |
| | | // 8. 控制方法(完全不变) |
| | | const startUpdating = (interval = 1000) => { |
| | | if (!updateInterval) { |
| | | updateInterval = setInterval(updateData, interval); |
| | | console.log("Started updating..."); |
| | | } |
| | | }; |
| | | |
| | | //停止定时更新 |
| | | const stopUpdating = () => { |
| | | if (updateInterval) { |
| | | clearInterval(updateInterval); |
| | | updateInterval = null; |
| | | console.log("Stopped updating..."); |
| | | } |
| | | }; |
| | | |
| | | //重置图表数据和状态 |
| | | const resetLoading = () => { |
| | | stopUpdating(); // 停止当前更新 |
| | | |
| | | // 重置状态 |
| | | stopUpdating(); |
| | | dataIndex.value = 0; |
| | | data1.value = []; |
| | | data2.value = []; |
| | | xAxisData.value = ["00:00"]; |
| | | |
| | | // 重新加载第一个数据点(如果有数据) |
| | | if (rainfallData.value.length > 0) { |
| | | data1.value.push(rainfallData.value[0].value); |
| | | data2.value.push(rainfallData.value[0].total); |
| | | if (rainfallData.value.length) { |
| | | data1.value = [rainfallData.value[0].value]; |
| | | data2.value = [rainfallData.value[0].total]; |
| | | } |
| | | |
| | | // 重新绘制图表(保持原有y轴范围) |
| | | updateChart( |
| | | { |
| | | max: myChart1.getOption().yAxis[0].max, |
| | | interval: myChart1.getOption().yAxis[0].interval, |
| | | }, |
| | | { |
| | | max: myChart1.getOption().yAxis[1].max, |
| | | interval: myChart1.getOption().yAxis[1].interval, |
| | | } |
| | | ); |
| | | |
| | | console.log("Reset loading..."); |
| | | updateChart(); |
| | | }; |
| | | |
| | | // 初始化:加载数据 |
| | | // 9. 初始化 |
| | | loadJsonData(); |
| | | |
| | | // 返回公共接口 |
| | | return { |
| | | myChart1, // 图表实例 |
| | | startUpdating, // 启动更新方法 |
| | | stopUpdating, // 停止更新方法 |
| | | resetLoading, // 重置方法 |
| | | myChart1, |
| | | startUpdating, |
| | | stopUpdating, |
| | | resetLoading, |
| | | }; |
| | | }; |
| | | |
| | |
| | | const chartDom = document.getElementById("echarts2"); |
| | | myChart2 = echarts.init(chartDom); |
| | | |
| | | let jsonData = ref([]); // 存储从 JSON 文件中加载的数据 |
| | | let data1 = ref([]); // 实时流量数据 |
| | | let data2 = ref([]); // 累计流量数据 |
| | | let xAxisData = ref([]); // 动态时间轴 |
| | | let updateInterval = null; // 定时器变量 |
| | | let dataIndex = ref(0); // 当前数据索引,用于按顺序更新 |
| | | let jsonData = ref([]); |
| | | let data1 = ref([]); |
| | | let data2 = ref([]); |
| | | let xAxisData = ref([]); |
| | | let updateInterval = null; |
| | | let dataIndex = ref(0); |
| | | |
| | | // 加载 JSON 数据 |
| | | // 加载 JSON 数据(完全保持原有逻辑) |
| | | const loadJsonData = async () => { |
| | | try { |
| | | const response = await fetch("/json/于家西沟断面下数据.json"); |
| | | const result = await response.json(); |
| | | if (result && result.data && Array.isArray(result.data)) { |
| | | jsonData.value = result.data; |
| | | |
| | | // 计算 value 和 total 的最大值 |
| | | const maxValue = Math.max(...jsonData.value.map((item) => item.value)); |
| | | const maxTotal = Math.max(...jsonData.value.map((item) => item.total)); |
| | | |
| | | // 初始化时间轴(从00:00开始) |
| | | xAxisData.value = ["00:00"] || syncTimeWithTimeline(); // 初始时间点 |
| | | |
| | | // 初始化图表(仅加载第一个数据点) |
| | | xAxisData.value = ["00:00"] || syncTimeWithTimeline(); // 保持您的时间初始化 |
| | | |
| | | if (jsonData.value.length > 0) { |
| | | data1.value.push(jsonData.value[0].value); // 实时流量 |
| | | data2.value.push(jsonData.value[0].total); // 累计流量 |
| | | data1.value.push(jsonData.value[0].value); |
| | | data2.value.push(jsonData.value[0].total); |
| | | } |
| | | |
| | | // 根据最大值设置 y 轴参数并初始化图表 |
| | | const yAxis1Params = calculateYAxisParams(maxValue); |
| | | const yAxis2Params = calculateYAxisParams(maxTotal); |
| | | updateChart(yAxis1Params, yAxis2Params); |
| | | } else { |
| | | console.error( |
| | | "Invalid JSON format: 'data' is missing or not an array!" |
| | | ); |
| | | updateChart(); // 初始化时自动计算Y轴范围 |
| | | } |
| | | } catch (error) { |
| | | console.error("Error fetching data:", error); |
| | | console.error("数据加载失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 计算 y 轴参数(最多有 4 个点) |
| | | const calculateYAxisParams = (max) => { |
| | | const step = Math.ceil(max / 3); // 最多有 4 个点(包括 0),所以分成 3 份 |
| | | // 动态计算Y轴参数(新增核心功能) |
| | | const calculateDynamicYAxis = (dataArray) => { |
| | | const currentMax = Math.max(...dataArray, 1); // 确保最小显示范围 |
| | | const step = Math.ceil(currentMax / 3); |
| | | return { |
| | | max: step * 3, // 确保最大值是步长的整数倍 |
| | | interval: step, |
| | | max: step * 3, |
| | | interval: step |
| | | }; |
| | | }; |
| | | |
| | | // 更新图表配置 |
| | | const updateChart = (yAxis1Params, yAxis2Params) => { |
| | | // 更新图表配置(仅修改Y轴部分) |
| | | const updateChart = () => { |
| | | const option = { |
| | | animation: false, // 禁用动画 |
| | | // >>> 保持您原有的所有配置 <<< |
| | | animation: false, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "cross", |
| | | crossStyle: { |
| | | color: "#fff", |
| | | }, |
| | | }, |
| | | axisPointer: { type: "cross" } |
| | | }, |
| | | grid: { |
| | | left: "1%", |
| | | right: "1%", |
| | | bottom: "1%", |
| | | containLabel: true, |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | data: ["实时流量", "累计流量"], |
| | | textStyle: { |
| | | color: "#fff", |
| | | }, |
| | | right: "10px", // 将图例靠右贴边 |
| | | textStyle: { color: "#fff" }, |
| | | right: "10px" |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: "category", |
| | | data: xAxisData.value, // 使用动态时间轴 |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | axisLabel: { |
| | | color: "#fff", |
| | | rotate: 0, // 将旋转角度设置为0,取消倾斜 |
| | | }, |
| | | }, |
| | | ], |
| | | |
| | | // >>> 您原来的xAxis配置(完全不变) <<< |
| | | xAxis: [{ |
| | | type: "category", |
| | | data: xAxisData.value, |
| | | axisLabel: { color: "#fff", rotate: 0 } |
| | | }], |
| | | |
| | | // >>> 修改的Y轴配置(动态范围) <<< |
| | | yAxis: [ |
| | | { |
| | | { // 左侧Y轴(实时流量) |
| | | type: "value", |
| | | name: "单位:m³/min", |
| | | min: 0, |
| | | max: yAxis1Params.max, |
| | | interval: yAxis1Params.interval, |
| | | axisLabel: { |
| | | ...calculateDynamicYAxis(data1.value), |
| | | axisLabel: { |
| | | formatter: "{value}", |
| | | color: "#fff", |
| | | align: "right", // 将标签右对齐 |
| | | align: "right" |
| | | }, |
| | | nameTextStyle: { |
| | | padding: [0, 0, 0, 20], // 在右侧添加一些内边距 |
| | | color: "#fff", |
| | | padding: [0, 0, 0, 20], |
| | | color: "#fff" |
| | | }, |
| | | splitLine: { |
| | | show: false, // 关闭左侧 y 轴的横线 |
| | | }, |
| | | splitLine: { show: false } |
| | | }, |
| | | { |
| | | { // 右侧Y轴(累计流量) |
| | | type: "value", |
| | | name: "单位:m³", |
| | | min: 0, |
| | | max: yAxis2Params.max, |
| | | interval: yAxis2Params.interval, |
| | | axisLabel: { |
| | | ...calculateDynamicYAxis(data2.value), |
| | | axisLabel: { |
| | | formatter: "{value}", |
| | | color: "#fff", |
| | | align: "left", // 将标签右对齐 |
| | | align: "left" |
| | | }, |
| | | nameTextStyle: { |
| | | padding: [0, 10, 0, 0], // 在右侧添加一些内边距 |
| | | color: "#fff", |
| | | padding: [0, 10, 0, 0], |
| | | color: "#fff" |
| | | }, |
| | | splitLine: { |
| | | show: true, // 保留右侧 y 轴的横线 |
| | | }, |
| | | }, |
| | | splitLine: { show: true } |
| | | } |
| | | ], |
| | | |
| | | // >>> 保持您原有的series配置 <<< |
| | | series: [ |
| | | { |
| | | name: "实时流量", |
| | | type: "bar", |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value + " m³/min"; |
| | | }, |
| | | }, |
| | | tooltip: { valueFormatter: value => value + " m³/min" }, |
| | | data: data1.value, |
| | | itemStyle: { |
| | | color: "blue", // 设置柱状图颜色为蓝色 |
| | | }, |
| | | label: { |
| | | show: false, |
| | | color: "#fff", |
| | | }, |
| | | itemStyle: { color: "blue" } |
| | | }, |
| | | { |
| | | name: "累计流量", |
| | | type: "line", |
| | | yAxisIndex: 1, |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value + " m³"; |
| | | }, |
| | | }, |
| | | tooltip: { valueFormatter: value => value + " m³" }, |
| | | data: data2.value, |
| | | lineStyle: { |
| | | color: "#ffb637", // 设置折线图线条颜色为黄色 |
| | | }, |
| | | label: { |
| | | show: false, // 确保标签不显示 |
| | | color: "#fff", |
| | | }, |
| | | }, |
| | | ], |
| | | lineStyle: { color: "#ffb637" } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | myChart2.setOption(option); |
| | | myChart2.setOption(option, true); // 强制刷新 |
| | | }; |
| | | |
| | | // 定义按顺序更新数据的方法 |
| | | // 数据更新(保持您的时间逻辑) |
| | | const updateData = () => { |
| | | if (dataIndex.value < jsonData.value.length) { |
| | | // 获取当前索引的数据项 |
| | | const newItem = jsonData.value[dataIndex.value]; |
| | | data1.value.push(newItem.value); // 添加实时流量 |
| | | data2.value.push(newItem.total); // 添加累计流量 |
| | | |
| | | const nextTime = syncTimeWithTimeline(); |
| | | xAxisData.value.push(nextTime); |
| | | |
| | | // 更新当前索引 |
| | | dataIndex.value += 2; |
| | | |
| | | // 更新图表 |
| | | updateChart( |
| | | { |
| | | max: myChart2.getOption().yAxis[0].max, |
| | | interval: myChart2.getOption().yAxis[0].interval, |
| | | }, // 左侧 y 轴保持不变 |
| | | { |
| | | max: myChart2.getOption().yAxis[1].max, |
| | | interval: myChart2.getOption().yAxis[1].interval, |
| | | } // 右侧 y 轴保持不变 |
| | | ); |
| | | data1.value.push(newItem.value); |
| | | data2.value.push(newItem.total); |
| | | xAxisData.value.push(syncTimeWithTimeline()); // 您的时间生成方法 |
| | | dataIndex.value += 2; // 保持您的索引步长 |
| | | updateChart(); // 自动调整Y轴 |
| | | } else { |
| | | console.log("All data has been displayed."); |
| | | stopUpdating(); // 停止定时更新 |
| | | stopUpdating(); |
| | | } |
| | | }; |
| | | |
| | | // 启动定时更新 |
| | | // 控制方法(完全不变) |
| | | const startUpdating = (interval = 1000) => { |
| | | if (!updateInterval) { |
| | | updateInterval = setInterval(updateData, interval); // 每隔 interval 毫秒更新一次数据 |
| | | console.log("Started updating..."); |
| | | updateInterval = setInterval(updateData, interval); |
| | | } |
| | | }; |
| | | |
| | | // 停止定时更新 |
| | | const stopUpdating = () => { |
| | | if (updateInterval) { |
| | | clearInterval(updateInterval); |
| | | updateInterval = null; |
| | | console.log("Stopped updating..."); |
| | | } |
| | | }; |
| | | |
| | | // 重置加载 |
| | | const resetLoading = () => { |
| | | stopUpdating(); // 停止定时器 |
| | | dataIndex.value = 0; // 重置数据索引 |
| | | data1.value = []; // 清空实时流量数据 |
| | | data2.value = []; // 清空累计流量数据 |
| | | xAxisData.value = ["00:00"]; // 重置时间轴 |
| | | |
| | | // 重新加载第一个数据点 |
| | | if (jsonData.value.length > 0) { |
| | | data1.value.push(jsonData.value[0].value); // 实时流量 |
| | | data2.value.push(jsonData.value[0].total); // 累计流量 |
| | | stopUpdating(); |
| | | dataIndex.value = 0; |
| | | data1.value = []; |
| | | data2.value = []; |
| | | xAxisData.value = ["00:00"]; |
| | | if (jsonData.value.length) { |
| | | data1.value.push(jsonData.value[0].value); |
| | | data2.value.push(jsonData.value[0].total); |
| | | } |
| | | |
| | | // 重新绘制图表 |
| | | updateChart( |
| | | { |
| | | max: myChart2.getOption().yAxis[0].max, |
| | | interval: myChart2.getOption().yAxis[0].interval, |
| | | }, // 左侧 y 轴保持不变 |
| | | { |
| | | max: myChart2.getOption().yAxis[1].max, |
| | | interval: myChart2.getOption().yAxis[1].interval, |
| | | } // 右侧 y 轴保持不变 |
| | | ); |
| | | |
| | | console.log("Reset loading..."); |
| | | updateChart(); |
| | | }; |
| | | |
| | | // 初始化加载 JSON 数据 |
| | | // 初始化 |
| | | loadJsonData(); |
| | | |
| | | return { |
| | | myChart2, |
| | | startUpdating, |
| | | stopUpdating, |
| | | resetLoading, |
| | | resetLoading |
| | | }; |
| | | }; |
| | | |
| | |
| | | |
| | | // 保存方案逻辑 |
| | | const saveScheme = async (forms) => { |
| | | // forms.hours = dayjs(val[0]).format("YYYY-MM-DD HH:mm:ss"); |
| | | if (isLoading.value) { |
| | | ElMessage.warning('正在保存,请稍候...') |
| | | return |
| | |
| | | type: forms.type, |
| | | status: 0, |
| | | data: JSON.stringify({ |
| | | startTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), |
| | | startTime: Array.isArray(forms.hours) |
| | | ? dayjs(forms.hours[0]).format("YYYY-MM-DD HH:mm:ss") |
| | | : dayjs(forms.hours).format("YYYY-MM-DD HH:mm:ss"), |
| | | type: forms.type, |
| | | total: forms.rainfall, |
| | | duration: forms.duration, |
| | |
| | | }) |
| | | // 用户确认后执行保存 |
| | | await saveScheme(forms) |
| | | console.log(forms, 'ffffffffff') |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('保存出错:', error) |
| | |
| | | // import Device from "@/components/menu/Device.vue"; |
| | | import Detail from "@/components/tools/Detail.vue"; |
| | | // 不可以删除,否则全局样式会丢掉,不知道原因 |
| | | import ResultAssess from "@/components/monifangzhen/ResultAssess.vue"; |
| | | // import ResultAssess from "@/components/monifangzhen/ResultAssess.vue"; |
| | | // import DangerAssess from "@/components/monifangzhen/DangerAssess.vue"; |
| | | import { showDeviceDetail } from "@/store"; |
| | | import { setupTokenRefresh } from "@/api/hpApi.js" |
| | |
| | | <template #append>mm</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="选择时间:"> |
| | | <el-date-picker |
| | | v-if="forms.fileList.length !== 0" |
| | | v-model="forms.hours" |
| | | type="datetime" |
| | | placeholder="Select date and time" |
| | | /> |
| | | <el-date-picker |
| | | v-if="forms.fileList.length == 0" |
| | | v-model="forms.hours" |
| | | type="datetimerange" |
| | | start-placeholder="开始时间" |
| | | end-placeholder="结束时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | date-format="YYYY/MM/DD ddd" |
| | | time-format="A hh:mm:ss" |
| | | @change="change" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="降雨时长:"> |
| | | <el-input |
| | | disabled |
| | | v-model="forms.duration" |
| | | style="max-width: 600px" |
| | | placeholder="Please input" |
| | |
| | | import { SimAPIStore } from "@/store/simAPI"; |
| | | import { getRegionData } from "@/api/trApi"; |
| | | import { storeToRefs } from "pinia"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const simStore = SimAPIStore(); |
| | | const { selectTab } = storeToRefs(simStore); |
| | |
| | | fileList: [], |
| | | type: 3, |
| | | rainFallList: [], |
| | | hours: "", |
| | | }); |
| | | |
| | | // 计算累计时长 |
| | | const calculateHoursDifference = (val) => { |
| | | if (!val || val.length !== 2) return 0; |
| | | const [startDate, endDate] = val; |
| | | const diffInHours = dayjs(endDate).diff(dayjs(startDate), "hour", true); // true 表示返回浮点数 |
| | | return diffInHours; |
| | | }; |
| | | |
| | | const change = (val) => { |
| | | forms.duration = calculateHoursDifference(val); |
| | | }; |
| | | |
| | | const addSimCheme = async () => { |
| | | await simStore.addSimCheme(forms); |
| | |
| | | forms.intensity = ""; |
| | | forms.fileList = []; |
| | | forms.rainFallList = []; |
| | | forms.hours = ""; |
| | | }; |
| | | |
| | | // 计算属性:获取上传文件的名称列表 |
| | |
| | | ><template #append>h</template></el-input |
| | | > |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="openPlan">打开方案</el-button> |
| | | <el-button type="primary" @click="openSaveDialog">保存方案</el-button> |
| | | <el-button type="success" @click="startPlay">开始模拟</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="buttons"> |
| | | <el-button type="primary" @click="openPlan">打开方案</el-button> |
| | | <el-button type="primary" @click="openSaveDialog">保存方案</el-button> |
| | | <el-button type="success" @click="startPlay">开始模拟</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <script setup> |