Files
bigscreenWeb/src/views/SagTraceResult_WX/components/eventStatistics/index.vue
2025-10-27 13:34:34 +08:00

1420 lines
38 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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";
import { ElMessage, ElMessageBox } from "element-plus";
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",
"refresh-security-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) => {
// console.log(123,store.state.iframeLoad);
// window.parent.postMessage(
// {
// type,
// payload,
// },
// "*"
// );
// 如果 iframe 已加载完成,直接发送消息
if (store.state.iframeLoad) {
window.parent.postMessage(
{
type,
payload,
},
"*" // 建议替换为具体域名,如 'https://父页面域名'
);
return;
}
// 如果未加载完成,每 1 秒尝试发送一次
const interval = setInterval(() => {
console.log("等待 iframe 加载1 秒后重试...");
if (store.state.iframeLoad) {
// 加载完成后发送消息并清除定时器
window.parent.postMessage(
{
type,
payload,
},
"*" // 建议替换为具体域名
);
clearInterval(interval);
}
}, 1000);
};
// 闪烁点
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: "#375db4",
};
// 发送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: "#f08a0a",
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
}
const dataObject = {
eventList: [...eventList.value],
color: "#03de6d",
maxResponsibilityMonitorId: [...maxResponsibilityMonitorId.value],
maxColor: "#f9065b",
};
// 发送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;
}
// 通知父组件刷新 manage/securityDetail.vue 中的数据
emit("refresh-security-detail");
})
.catch((error) => {
traceabilityTableData.value = [];
defaultCurrentRowKey.value = null;
loading.value = false;
});
};
// 谐波溯源详情
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: "#cf552d",
maxResponsibilityMonitorId: [...maxResponsibilityMonitorId.value],
maxColor: "#c708fe",
backgroundPointId: [...backgroundPoint.value],
backgroundPointColor: "#0936f4",
};
// 发送所有 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>