Files
bigscreenWeb/src/views/SagTraceResult_WX/components/eventStatistics/index.vue

1384 lines
37 KiB
Vue
Raw Normal View History

2025-09-25 13:32:47 +08:00
<template>
<!--右中 暂降事件聚合成功后数量的统计 -->
<div class="plan">
<div class="titleBox_1">
<div class="titleBox_1">
<div style="display: flex">
<div class="titles" style="margin-left: 0px">
<!-- 暂降溯源 -->
<div
class="react-right"
:class="flag == 0 ? 'titleClick' : ''"
@click="flag = 0"
>
<span class="text">
暂降溯源<el-icon style="top: 2px; left: 2px"
><Lightning
/></el-icon>
</span>
</div>
<!-- 谐波溯源 -->
<div
class="react-right"
:class="flag == 1 ? 'titleClick' : ''"
@click="flag = 1"
>
<span class="text">
谐波溯源<el-icon style="top: 2px; left: 2px"
><DataLine
/></el-icon>
</span>
</div>
<!-- 谐波放大 -->
<div
class="react-right"
style="margin-left: 10px"
:class="flag == 2 ? 'titleClick' : ''"
@click="flag = 2"
>
<span class="text">
谐波放大<el-icon style="top: 2px; left: 2px"
><ZoomIn
/></el-icon>
</span>
</div>
</div>
</div>
</div>
</div>
<!-- 暂降聚合 -->
<div v-if="flag == 0">
<div class="titleBox" style="margin-top: 10px">暂降事件</div>
<div
style="
margin-left: 84%;
height: 34px;
line-height: 20px;
margin-top: -30px;
"
>
<el-button
size="small"
:icon="HelpFilled"
type="primary"
@click="polymerizationClick(1)"
>溯源
</el-button>
</div>
<div
style="display: flex"
v-loading="loading"
element-loading-background="#343849c7"
>
<div class="polymerization" style="width: 24%; height: 230px">
<div
style="background-color: #f8ff4470; cursor: pointer"
@click="polymerizationClick(2)"
>
<span class="text">{{ numRecords.eventCount }}</span>
<span style="font-size: 14px">暂降事件</span>
</div>
</div>
<dv-scroll-ranking-board
ref="rankingBoardRef"
:config="config"
style="width: 70%; height: 215px; margin: 10px 0 0 10px"
/>
</div>
<el-divider />
<div v-loading="loading" element-loading-background="#343849c7">
<div class="titleBox" style="margin-top: 10px">暂降溯源</div>
<div style="display: flex; margin-top: 10px">
<div class="polymerization" style="width: 24%; height: 240px">
<div style="background-color: #0a73ff70">
<span class="text">{{ numAggregation.eventCount }}</span>
<span style="font-size: 14px">暂降溯源</span>
</div>
</div>
<div
style="width: 73%; height: 260px; margin: 0px 0px 10px 10px"
class="eventList"
>
<div v-for="(item, i) in tableData">
<div class="eventListDiv">
<div>{{ i + 1 }}</div>
<div>{{ item.name }}</div>
<div>
<el-button
size="small"
type="primary"
link
@click="analysisClick(item)"
>溯源
</el-button>
</div>
</div>
<el-divider />
</div>
</div>
</div>
</div>
</div>
<!-- 谐波溯源 -->
<div v-if="flag == 1">
<div class="titles title_1">
<el-button type="primary" size="small" @click="calculation" :icon="Aim"
>谐波责任度计算
</el-button>
<el-button type="primary" size="small" @click="collecting" :icon="Memo"
>用采数据管理
</el-button>
</div>
<div class="tableBox">
<el-table
:scrollbar-always-on="true"
:data="traceabilityTableData"
height="555px"
size="small"
:header-cell-style="{ textAlign: 'center' }"
border
v-loading="loading"
element-loading-background="#343849c7"
@row-click="handleTraceabilityRow"
:row-style="{ cursor: 'pointer' }"
highlight-current-row
:current-row-key="defaultCurrentRowKey"
row-key="id"
>
<el-table-column
type="index"
align="center"
label="序号"
width="50"
/>
<el-table-column
prop="updateTime"
align="center"
label="时间"
show-overflow-tooltip
width="140"
/>
<el-table-column prop="content" label="事件内容" />
<el-table-column fixed="right" label="操作" width="70">
<template #default="{ row }">
<el-button
link
type="primary"
size="small"
@click.stop="handleDetail(row)"
style="margin-left: 12px"
>详情
</el-button>
<el-button
link
type="danger"
size="small"
@click.stop="handleDelete(row)"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 谐波放大 -->
<div v-if="flag == 2">
<div style="display: flex">
<div
class="eacharts2"
ref="eacharts2"
style="width: 100%; height: 609px"
v-loading="loading"
element-loading-background="#343849c7"
></div>
</div>
<!-- <div class="tableBox">
<el-table
:scrollbar-always-on="true"
:data="amplifyTableData"
height="319px"
size="small"
:header-cell-style="{ textAlign: 'center' }"
border
v-loading="loading"
element-loading-background="#343849c7"
>
<el-table-column
type="index"
align="center"
label="序号"
width="50"
/>
<el-table-column
prop="time"
align="center"
label="谐波放大时间范围"
width="160"
/>
<el-table-column prop="content" align="center" label="事件内容" />
<el-table-column
prop="address"
align="center"
label="操作"
width="70"
>
<template #default="scope">
<el-button
size="small"
type="primary"
link
@click="arendChart(scope.row)"
>趋势图</el-button
>
</template>
</el-table-column>
</el-table>
</div> -->
</div>
<dropOffTable ref="dropOffTableRef" />
<Collecting ref="collectingRef" />
<Calculation
ref="calculationRef"
v-if="showCalculation"
@show-calculation="handleShowCalculation"
@close-dialog="handleChildClose"
/>
<TraceabilityDetail
ref="traceabilityDetailRef"
:detailsQuery="detailsQuery"
/>
<!-- 暂降溯源 暂降事件单行点击事件 -->
<DipDetail ref="dipDetail"></DipDetail>
<!-- 暂降溯源 暂降事件总点击事件 -->
<DipDetailTotal
ref="dipDetailTotalRef"
@aggregation-success="handleAggregationSuccess"
></DipDetailTotal>
<!-- 谐波放大表格详情 -->
<AmplifyDeatil ref="amplifyDeatilRef"></AmplifyDeatil>
<!-- 谐波放大表格趋势图 -->
<TrendChart ref="trendChartRef"></TrendChart>
<!-- 谐波溯源表格点击事件选择次数弹框 -->
<el-dialog
v-model="visibleTimes"
:close-on-click-modal="false"
title="谐波次数"
draggable
width="500px"
@close="handleCloseDialog"
style="height: 170px"
v-if="dataTimes && dataTimes.length > 0"
>
<div style="display: flex; margin-top: 10px">
<div style="margin-right: 10px">谐波次数</div>
<el-select
v-model="timeValue"
placeholder="请选择"
size="small"
style="width: 200px"
@change="handleTimeChange"
>
<el-option
v-for="item in dataTimes"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { Lightning, DataLine, ZoomIn } from "@element-plus/icons-vue";
import {
ref,
reactive,
onMounted,
getCurrentInstance,
watch,
nextTick,
onBeforeUnmount,
} from "vue";
2025-10-11 10:53:46 +08:00
import { ElMessage,ElMessageBox } from "element-plus";
2025-09-25 13:32:47 +08:00
import {
eventSource,
eventAggregation,
hasEventList,
processEvents,
getEventList,
responsibilityList,
deleteByIds,
getInfoList,
tableInfo,
harmOneImage,
hasUpEventList,
} from "@/api/manage_wx/index";
import { HelpFilled, Aim, Memo } from "@element-plus/icons-vue";
const flag = ref(0); // 0 for 暂降, 1 for 谐波, 2 for 谐波放大
const time = ref(0); // 0 for 周, 1 for 月
const { proxy }: any = getCurrentInstance();
import dropOffTable from "./dropOffTable.vue";
import { useStore } from "vuex";
import Collecting from "./collecting.vue";
import Calculation from "./calculation.vue";
import TraceabilityDetail from "./traceabilityDetail.vue";
import DipDetail from "./dipDetail.vue";
import AmplifyDeatil from "./amplifyDeatil.vue";
import TrendChart from "./trendChart.vue";
import DipDetailTotal from "./dipDetailTotal.vue";
const store = useStore();
const eacharts1 = ref(null);
const eacharts2 = ref(null);
const dropOffTableRef = ref();
const loading = ref(false);
const showCollecting = ref(false);
const showCalculation = ref(false);
const numRecords = ref({
eventCount: 0,
// innerList: [],
}); //暂降记录个数
const numAggregation = ref({
eventCount: 0,
});
const eventList = ref([]); //闪烁点
const iframeEventLists = ref([]); //iframeDia页面需要的数据
const collectingRef = ref();
const calculationRef = ref();
const traceabilityDetailRef = ref();
const dipDetail = ref();
const amplifyDeatilRef = ref();
const trendChartRef = ref();
const dipDetailTotalRef = ref();
let pointX = ref();
let pointY = ref();
// 添加用于存储热力图数据的响应式变量
const pointData = ref([]);
const detailsQuery = reactive({
id: "",
time: "",
name: "",
});
const amplifyTableData = ref([]); //谐波放大表格
const tableData = reactive<any[]>([]);
const traceabilityTableData = ref([]);
// 添加用于存储默认高亮行key的响应式变量
const defaultCurrentRowKey = ref();
const config = reactive({
data: [],
waitTime: 5000,
unit: "次",
rowNum: 6,
carousel: "page",
color: "rgba(248, 255, 68, .7)",
});
const rankingBoardRef = ref();
// 监听 config.data 变化,动态设置 title 属性
watch(
() => config.data,
(newData) => {
setTimeout(() => {
if (rankingBoardRef.value && newData.length > 0) {
const nameElements = document.querySelectorAll(
".dv-scroll-ranking-board .info-name"
);
nameElements.forEach((el, index) => {
if (newData[index]) {
el.setAttribute("title", newData[index].name);
}
});
}
}, 100);
},
{ deep: true }
);
const renderChart2 = () => {
var myChar2 = proxy.$echarts.init(eacharts2.value);
var hours = pointX.value;
var days = pointY.value;
var data = [];
if (pointData.value && Array.isArray(pointData.value)) {
data = pointData.value.map((item) => [
item.date || 0, // x轴索引
item.monitorName || 0, // y轴索引
item.count || 0, // 值
]);
} else {
data = [];
}
// 判断是否需要纵向滚动条y轴数据超过7条
const needYScroll = days && days.length > 15;
// 计算滚动比例
const scrollRatio = needYScroll ? (7 / days.length) * 100 : 100;
myChar2.setOption({
tooltip: {
position: "top",
formatter: function (params: any) {
let tips = ``;
tips += params.name + "<br/>";
tips +=
params.marker + params.value[1] + " " + params.value[2] + "次";
return tips;
},
},
animation: false,
grid: {
right: needYScroll ? "30" : "20", // 为滚动条留出空间
left: "90",
bottom: "60px",
top: "20",
},
xAxis: {
type: "category",
data: hours,
splitArea: {
show: true,
},
axisLabel: {
textStyle: {
color: "#ffffff",
fontSize: 10,
},
formatter: function (value) {
let time = "";
if (value.slice(-2) == "01") {
time = value;
} else {
time = value.slice(5, 10);
}
return time;
},
},
},
yAxis: {
type: "category",
data: days,
inverse: true, // 反转 y 轴,使第一条数据在顶部
axisLabel: {
textStyle: {
color: "#ffffff",
fontSize: 12,
},
// 只显示前6个字符多余部分用省略号表示
formatter: function (value: string) {
if (value && value.length > 6) {
return value.substring(0, 6) + "...";
}
return value;
},
},
},
dataZoom: [
// 纵向滚动条y轴
...(needYScroll
? [
{
type: "slider",
show: true,
orient: "vertical",
start: 0,
end: scrollRatio,
right: "5",
top: "20",
bottom: "40",
width: 10,
},
{
type: "inside",
orient: "vertical",
start: 0,
end: scrollRatio,
},
]
: []),
// 横向滚动条x轴
{
type: "inside",
height: 10,
start: hours && hours.length > 12 ? 70 : 0,
bottom: "25px",
end: 100,
},
{
type: "slider",
start: hours && hours.length > 12 ? 70 : 0,
height: 10,
bottom: "25px",
end: 100,
},
],
visualMap: {
show: false,
min: 0,
max: 20,
calculable: true,
orient: "horizontal",
left: "center",
bottom: "15%",
type: "piecewise", // 必须设置为分段模式
pieces: [
{ min: 15, max: 20, color: "rgba(236,143,21,0.92)" }, // 第4段绿色
{ min: 5, max: 15, color: "rgba(236,218,21,0.92)" }, // 第3段蓝色
{ min: 1, max: 5, color: "#1d83ce60" }, // 第2段黄色
{ min: 0, max: 0, color: "#008000" }, // 第1段橙色
],
},
series: [
{
name: "",
type: "heatmap",
data: data,
label: {
show: true,
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
});
// 注册图表点击事件
myChar2.on("click", handleChartClick);
};
const handleChartClick = (params: any) => {
// console.log("Clicked params:", params);
if (params.componentType === "series") {
// // 通过数据索引直接获取原始数据
const dataIndex = params.dataIndex;
// 从 pointData 中获取对应的原始数据
const originalData =
pointData.value && pointData.value[dataIndex]
? pointData.value[dataIndex]
: null;
// 获取 lineId
const lineId = originalData ? originalData.lineId || null : null;
dropOffTableRef.value.open(
flag.value == 2 ? "暂降事件" : "谐波放大事件",
params.name,
lineId
);
}
};
// 定义 emit
const emit = defineEmits(["flag-changed", "expand-detail"]);
watch(flag, (newVal) => {
// 向父组件发送 flag 变化事件
emit("flag-changed", newVal);
setTimeout(() => {
if (flag.value == 0) {
initHasEventList();
// flag 变化后重新绑定事件
bindRankingClickEvent();
}
if (flag.value == 2) {
renderChart2();
initHasUpEventList();
}
if (flag.value == 1) {
callHarmOneImageApi(getFirstTableData.value, getTimes.value);
}
}, 100);
});
// 暂降记录个数
const initialData = () => {
loading.value = true;
eventSource({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
}).then((res: any) => {
if (res.code == "A0000") {
numRecords.value.eventCount = res.data.eventCount;
// numRecords.value.innerList = res.data.innerList;
// 将 innerList 数据转换并赋值给 config.data
if (res.data.innerList && Array.isArray(res.data.innerList)) {
config.data = res.data.innerList.map((item: any) => ({
name: item.name || item.stationName || "未知站点", // 根据实际字段名调整
value: item.value || item.count || 0, // 根据实际字段名调整
id: item.id, // 根据实际字段名调整
}));
} else {
config.data = [];
}
loading.value = false;
}
});
};
// 暂降聚合个数
const initialAggregation = () => {
loading.value = true;
eventAggregation({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
})
.then((res: any) => {
if (res.code == "A0000") {
numAggregation.value.eventCount = res.data.eventCount;
// 直接将 innerList 赋值给 tableData
if (res.data.innerList && Array.isArray(res.data.innerList)) {
tableData.splice(0, tableData.length, ...res.data.innerList);
} else {
tableData.splice(0, tableData.length);
}
loading.value = false;
}
})
.catch((error) => {
console.error("获取聚合数据失败:", error);
tableData.splice(0, tableData.length);
});
};
// 提取发送消息到iframe的公共方法
const sendMessageToIframe = (type: string, payload: any) => {
window.parent.postMessage(
{
type,
payload,
},
"*"
);
};
// 闪烁点
const initHasEventList = () => {
hasEventList({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
})
.then((res: any) => {
if (res.code == "A0000") {
// 从返回的数据中提取所有lineId并存入eventList
if (res.data && Array.isArray(res.data)) {
// iframeEventLists.value = res.data;
// 如果返回的数据本身就是数组
eventList.value = res.data
.filter((item) => item.lineId) // 过滤掉没有lineId的项
.map((item) => item.lineId);
}
const dataObject = {
eventList: [...eventList.value],
color: "#7ac1f9",
};
// 发送eventList数据到iframe注意发送的是.value而不是响应式对象本身
sendMessageToIframe("SEND_KEYS_TO_IFRAME", dataObject);
}
})
.catch((error) => {
console.error("获取闪烁点失败:", error);
eventList.value = []; // 出错时清空eventList
// 出错时也发送空数组到iframe
sendMessageToIframe("SEND_KEYS_TO_IFRAME", {});
});
};
// 谐波放大闪烁点
const initHasUpEventList = () => {
hasUpEventList({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
})
.then((res: any) => {
if (res.code == "A0000") {
// 从返回的数据中提取所有lineId并存入eventList
if (res.data && Array.isArray(res.data)) {
// iframeEventLists.value = res.data;
// 如果返回的数据本身就是数组
eventList.value = res.data
.filter((item) => item.lineId) // 过滤掉没有lineId的项
.map((item) => item.lineId);
}
const dataObject = {
eventList: [...eventList.value],
color: "#fcfc57",
flagValue: '2',
};
// 发送eventList数据到iframe注意发送的是.value而不是响应式对象本身
sendMessageToIframe("SEND_KEYS_TO_IFRAME", dataObject);
}
})
.catch((error) => {
console.error("获取闪烁点失败:", error);
eventList.value = []; // 出错时清空eventList
// 出错时也发送空数组到iframe
sendMessageToIframe("SEND_KEYS_TO_IFRAME", {});
});
};
// 聚合
const handleAggregation = (row: any) => {
ElMessageBox.confirm(
`是否确认对当前用户部门${store.state.timeValue[0]}${store.state.timeValue[1]}之间的暂降事件进行溯源?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
processEvents({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
}).then((res: any) => {
if (res.code == "A0000") {
ElMessage({
type: "success",
message: res.message,
});
initialAggregation();
} else {
ElMessage({
type: "warning",
message: res.message,
});
}
});
})
.catch((error) => {});
};
// 范围分析 溯源
const analysisClick = (row: any) => {
hasEventList({
eventAssId: row.id,
})
.then((res: any) => {
if (res.code == "A0000") {
// 从返回的数据中提取所有lineId并存入eventList
if (res.data && Array.isArray(res.data)) {
// iframeEventLists.value = res.data;
// 如果返回的数据本身就是数组
eventList.value = res.data
.filter((item) => item.lineId) // 过滤掉没有lineId的项
.map((item) => item.lineId);
maxResponsibilityMonitorId.value = res.data
.filter((item) => item.isImport == 1)
.map((item) => item.lineId); // 筛选 isImport 为 1
console.log(maxResponsibilityMonitorId.value, "890jhuj");
}
const dataObject = {
eventList: [...eventList.value],
color: "#fcfc57",
maxResponsibilityMonitorId: [...maxResponsibilityMonitorId.value],
maxColor: "#ff0000",
};
// 发送eventList数据到iframe注意发送的是.value而不是响应式对象本身
sendMessageToIframe("SEND_KEYS_TO_IFRAME", dataObject);
// 发送消息通知父组件展开详情面板
emit("expand-detail", 0); // 0 表示暂降溯源
}
})
.catch((error) => {
console.error("获取闪烁点失败:", error);
eventList.value = []; // 出错时清空eventList
// 出错时也发送空数组到iframe
sendMessageToIframe("SEND_KEYS_TO_IFRAME", {});
});
getEventList({
eventAssId: row.id,
}).then((res: any) => {
if (res.code == "A0000") {
// 通过 Vuex 更新 realData
store.dispatch("updateRealData", res.data.records);
}
});
};
const handleShowCalculation = (value) => {
showCalculation.value = value;
};
const handleShowCollecting = (value) => {
showCollecting.value = value;
};
// 谐波贡献度计算
const calculation = () => {
showCalculation.value = true;
nextTick(() => {
calculationRef.value.openDialog();
});
};
// 用采数据列表
const collecting = () => {
showCollecting.value = true;
nextTick(() => {
collectingRef.value.openDialog();
});
};
// 获取谐波溯源第一行数据和次数
const getFirstTableData = ref([]);
const getTimes = ref();
// 谐波溯源表格
const initialResponsibilityList = () => {
loading.value = true;
responsibilityList({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
})
.then((res: any) => {
if (res.code == "A0000") {
// 直接将 records 赋值给 tableData
if (res.data.records && Array.isArray(res.data.records)) {
getFirstTableData.value = res.data.records[0];
if (res.data.records[0].dataTimes) {
if (res.data.records[0].dataTimes.includes(",")) {
getTimes.value = res.data.records[0].dataTimes.split(",")[0];
} else {
getTimes.value = res.data.records[0].dataTimes;
}
}
const processedData = res.data.records.map((item: any) => {
// 根据实际字段进行拼接,示例:
const content = `${item.lineName || ""}进行${
item.dataTimes || ""
}次谐波电压溯源,溯源对象:${item.userDataName || ""}`.trim();
return {
...item,
content: content,
};
});
traceabilityTableData.value = processedData;
// 设置默认高亮第一行使用唯一标识字段如id
if (processedData.length > 0) {
defaultCurrentRowKey.value = processedData[0].id || 0;
}
} else {
traceabilityTableData.value = [];
defaultCurrentRowKey.value = null;
}
loading.value = false;
}
})
.catch((error) => {
traceabilityTableData.value = [];
defaultCurrentRowKey.value = null;
});
};
// 谐波溯源详情
const handleDetail = (row: any) => {
detailsQuery.id = row.id;
detailsQuery.time = row.dataTimes;
detailsQuery.name = `${row.gdName}>${row.subName}>${row.devName}>${row.lineName}`;
nextTick(() => {
traceabilityDetailRef.value.openDialog();
});
};
// 删除
const handleDelete = (row: any) => {
ElMessageBox.confirm("确定删除该数据项?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
deleteByIds([row.id])
.then((res: any) => {
ElMessage.success("删除成功");
initialResponsibilityList();
})
.catch((err: any) => {
ElMessage.error(err.message);
});
});
};
// 点击事件处理器
let clickHandler = null;
const handleRankingClick = (name: any) => {
let eventList = config.data.filter((item) => item.name == name);
dipDetail.value.open(eventList[0].id);
};
// 谐波放大表格
// const getInfoListAmplify = () => {
// loading.value = true;
// getInfoList({
// deptId: store.state.deptId,
// searchBeginTime: store.state.timeValue[0],
// searchEndTime: store.state.timeValue[1],
// }).then((res: any) => {
// if (res.code == "A0000") {
// // 对返回的数据进行处理,拼接字段
// amplifyTableData.value = res.data.map((item: any) => {
// return {
// ...item,
// // 拼接新的字段用于展示
// time: `${item.startTime || ""}至${item.endTime || ""}`,
// content: `${item.monitorName || ""}(${
// item.objName.replace("无锡市", "").replace("无锡", "") || ""
// })谐波放大: ${item.harmonicCount || ""}次谐波${
// item.phase || ""
// }相,持续时间${Math.floor(item.duration / 60) || ""}分钟`,
// };
// });
// } else {
// amplifyTableData.value = [];
// }
// loading.value = false;
// });
// };
// 谐波放大测点
const tableInfoAmplify = () => {
loading.value = true;
tableInfo({
deptId: store.state.deptId,
searchBeginTime: store.state.timeValue[0],
searchEndTime: store.state.timeValue[1],
}).then((res: any) => {
if (res.code == "A0000") {
if (res.data.date) {
pointX.value = res.data.date;
}
if (res.data.monitorList) {
pointY.value = res.data.monitorList;
}
if (res.data.inner) {
pointData.value = res.data.inner;
}
nextTick(() => {
if (flag.value == 2) {
renderChart2();
}
});
} else {
pointX.value = [];
pointY.value = [];
pointData.value = [];
}
loading.value = false;
});
};
// 谐波放大表格详情
const amplifyDeatil = (row: any) => {
amplifyDeatilRef.value.open();
};
// 谐波放大表格趋势图
const arendChart = (row: any) => {
trendChartRef.value.open(row);
};
const visibleTimes = ref(false);
// 选择的次数
const timeValue = ref("");
const dataTimes = ref();
// 谐波溯源表格点击事件
// 添加用于存储最大 responsibilityData 对应的 monitorId 的响应式变量
const maxResponsibilityMonitorId = ref([]);
//谐波溯源背景测点数据
const backgroundPoint = ref([]);
const handleTraceabilityRow = (row: any, column: any) => {
if (column.label === "操作") return; // 如果是操作列,不执行行点击逻辑
if (row.dataTimes) {
if (row.dataTimes.includes(",")) {
// 包含逗号时,分割成数组并转换为下拉框所需格式
const timesArray = row.dataTimes
.split(",")
.map((item: string, index: number) => {
const trimmedItem = item.trim();
return {
value: trimmedItem,
label: trimmedItem,
};
});
dataTimes.value = timesArray;
// 设置默认选中第一个选项
// if (dataTimes.value && dataTimes.value.length > 0) {
// timeValue.value = dataTimes.value[0].value;
// }
// 保存当前行数据,用于后续调用接口
currentRow.value = row;
// 打开弹框
visibleTimes.value = true;
// 注意:这里不立即调用接口,等待用户选择后再调用
return;
} else {
// 不包含逗号时,直接调用接口
callHarmOneImageApi(row, row.dataTimes);
}
} else {
// 没有 dataTimes 时,直接调用接口
callHarmOneImageApi(row, "");
}
};
// 保存当前行数据的响应式变量
const currentRow = ref(null);
// 新增:处理下拉框值变化的函数
const handleTimeChange = (value: string) => {
// 当用户在下拉框中选择了一个值后,调用接口
if (currentRow.value) {
callHarmOneImageApi(currentRow.value, value);
visibleTimes.value = false;
}
};
// 谐溯源点击行的全部数据
const eventListAll = ref([]);
// 抽取接口调用逻辑到独立函数
const callHarmOneImageApi = (row: any, selectedTime: string) => {
//谐波溯源背景测点数据
if (row && row.lineId) {
backgroundPoint.value = [row.lineId];
} else {
backgroundPoint.value = [];
}
harmOneImage({
id: row.id,
time: selectedTime,
}).then((res: any) => {
if (res.code == "A0000") {
// 从返回的数据中提取所有monitorId并存入eventList
if (res.data && Array.isArray(res.data)) {
// 全部数据
eventListAll.value = res.data;
// 原有逻辑:提取所有 monitorId
eventList.value = res.data
.filter((item) => item.monitorId) // 过滤掉没有monitorId的项
.map((item) => item.monitorId);
// 新逻辑:使用 reduce 方法找到 responsibilityData 最大值对应的项
const validData = res.data.filter(
(item) =>
item.responsibilityData &&
!isNaN(item.responsibilityData) &&
item.monitorId
);
if (validData.length > 0) {
const maxResponsibilityItem = validData.reduce(
(maxItem, currentItem) => {
const currentValue = parseFloat(currentItem.responsibilityData);
const maxValue = parseFloat(maxItem.responsibilityData);
return currentValue > maxValue ? currentItem : maxItem;
}
);
// 存储最大 responsibilityData 对应的 monitorId
maxResponsibilityMonitorId.value = [maxResponsibilityItem.monitorId];
} else {
maxResponsibilityMonitorId.value = [];
}
}
const dataObject = {
eventListAll: [JSON.parse(JSON.stringify(eventListAll.value))],
eventList: [...eventList.value],
color: "#fcfc57",
maxResponsibilityMonitorId: [...maxResponsibilityMonitorId.value],
maxColor: "#ff0000",
backgroundPointId: [...backgroundPoint.value],
backgroundPointColor: "#03df6d",
};
// 发送所有 monitorId 数据到 iframe
sendMessageToIframe("SEND_KEYS_TO_IFRAME", dataObject);
}
});
};
// 暂降溯源,暂降总事件
const polymerizationClick = (val) => {
dipDetailTotalRef.value.open(val);
};
// 修改 handleCloseDialog 函数
const handleCloseDialog = () => {
visibleTimes.value = false;
timeValue.value = "";
// 清空当前行数据
currentRow.value = null;
};
// 处理聚合成功的回调
const handleAggregationSuccess = () => {
// 调用 initialAggregation 函数
initialAggregation();
};
onMounted(() => {
// 获取组件DOM
bindRankingClickEvent();
});
// 重新绑定点击事件的函数
const bindRankingClickEvent = () => {
// 先移除之前的事件监听器
const oldRankingEl = rankingBoardRef.value?.$el;
if (oldRankingEl && clickHandler) {
oldRankingEl.removeEventListener("click", clickHandler);
}
// 获取新的组件DOM
const rankingEl = rankingBoardRef.value?.$el;
if (rankingEl) {
clickHandler = (e) => {
// 查找点击的行元素类名为row-item
const rowEl = e.target.closest(".row-item");
if (rowEl) {
// 查找行内的名称元素类名为info-name
const nameEl = rowEl.querySelector(".info-name");
if (nameEl) {
// 获取并传递名称文本
handleRankingClick(nameEl.textContent.trim());
}
}
};
// 添加事件监听
rankingEl.addEventListener("click", clickHandler);
}
};
onBeforeUnmount(() => {
const rankingEl = rankingBoardRef.value?.$el;
if (rankingEl && clickHandler) {
rankingEl.removeEventListener("click", clickHandler);
}
});
const handleChildClose = () => {
// 在这里执行父组件需要的逻辑
initialResponsibilityList();
};
const init = () => {
initialData();
initialAggregation();
initHasEventList();
initialResponsibilityList();
// getInfoListAmplify();
tableInfoAmplify();
if (flag.value == 2) {
initHasUpEventList();
}
};
defineExpose({
init,
initHasEventList,
//getEventList: () => [...iframeEventLists.value], // 提供获取 eventList 数据的方法 提供给iframeDia.vue
});
</script>
<style lang="scss" scoped>
@use "@/assets/scss/index.scss";
@import "@/assets/scss/element.scss";
.plan {
width: 100%;
.titles {
margin-right: 10px;
.react-right {
// width: 60px !important;
// line-height: 20px !important;
// font-size: 14px !important;
width: 110px !important;
line-height: 30px !important;
font-size: 16px !important;
}
.time {
width: 40px !important;
}
}
}
.imputation {
position: absolute;
right: 10px;
top: 40px;
z-index: 999;
}
.polymerization {
padding: 20px 10px;
display: flex;
flex-direction: column;
justify-content: center;
div {
height: 80px;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
.text {
font-size: 22px;
font-weight: 700;
color: #fff;
margin-bottom: 10px;
}
}
// display: grid;
// gap: 5px;
// grid-template-rows: repeat(2, 1fr);
}
.eventList {
overflow-y: auto;
/* 可以添加一些内边距来让内容和滚动条之间有间距 */
padding-right: 8px;
}
:deep(.el-divider--horizontal) {
margin: 10px 0;
}
.eventListDiv {
color: #fff;
display: flex;
div:nth-child(1) {
width: 30px;
display: flex;
align-items: center;
color: var(--el-color-primary);
font-size: 14px;
font-weight: 600;
}
div:nth-child(2) {
flex: 1;
font-size: 13px;
}
div:nth-child(3) {
width: 30px;
display: flex;
align-items: center;
}
}
.title_1 {
display: flex;
float: right;
margin: 10px;
font-size: 16px;
}
/* 添加以下样式来处理文字省略 */
:deep(.dv-scroll-ranking-board) {
.row-item {
cursor: pointer;
.ranking-info {
.info-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// 添加 title 属性显示完整内容
&[title] {
cursor: pointer;
}
}
}
}
}
.titleBox_1 {
display: flex;
justify-content: space-between;
width: 100%;
line-height: 32px;
font-size: 18px;
padding-left: 20px;
margin: 0 auto;
}
:deep(.el-table__body tr.current-row > td.el-table__cell) {
background-color: #456a91de !important;
}
</style>