You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
maotu-webtopo/src/components/vue-xq-test/vue-synthesize-table.vue

582 lines
13 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="table-container">
<el-card class="card" shadow="hover" :body-style="{ padding: '10px' }">
<h2 class="cardHead">运行信息</h2>
<div class="table-wrapper" v-loading="arr.length === 0">
<el-table
:data="arr"
:span-method="objectSpanMethods"
style="width: 100%"
class="full-height-table"
@cell-click="handleCellClick"
>
<el-table-column prop="floorName" label="楼层" />
<el-table-column prop="id" label="设备ID" />
<el-table-column prop="name" label="设备名称" />
<el-table-column label="绑定">
<template #default="{ row }">
<el-tag :type="row.isBinding ? 'primary' : 'info'">
{{ row.isBinding ? '绑定' : '待绑' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="设备状态">
<template #default="{ row }">
<el-tag :type="row.eState === 0 ? 'success' : 'warning'">
{{ row.eState === 0 ? '正常' : '故障' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="当前状态">
<template #default="{ row }">
<el-tag v-if="row.currentState === 0" type="success">运行</el-tag>
<el-tag v-else-if="row.currentState === 1" type="info">停止</el-tag>
<el-tag v-else type="error">报警</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" class="operation-btn" v-if="row.operation">
</el-button>
<el-button type="primary" class="operation-btn" v-else> </el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import type { TableColumnCtx } from 'element-plus';
import { ElMessage } from 'element-plus';
import { computed, onMounted, onUnmounted, ref, watch, reactive } from 'vue';
import { modelApi } from '@/utils/request';
import emitter from '@/utils/emitter';
import { type DataItem } from '@/components/mt-edit/store/types';
const loading = ref(false);
// 导入全局类型定义
/// <reference path="../../../global.d.ts" />
interface RecRuntimeData {
double: number;
node: {
name: string;
};
}
interface RecServiceType {
service: {
node: {
runtimes: Record<string, RecRuntimeData>;
};
};
}
// interface ExtendedParentWindow extends Window {
// Rec?: RecServiceType;
// }
interface ExtendedParentWindow extends Window {
globalData: Map<string, DataItem> | Record<string, DataItem>;
}
interface User {
id: string;
name: string;
amount1: string;
amount2: string;
amount3: number;
}
interface Equipment {
id: string; //设备ID
address?: string; //设备地址
name: string; //设备名称
eState: number; //设备状态 0正常 1故障
currentState: number; //当前状态 0运行 1停止 2报警
operation: boolean; //操作 true屏蔽 false取消屏蔽
}
interface FloorObj {
floorName: string; //地址
equipments: Equipment[];
}
// node楼层节点
interface FloorNode {
roomId: string;
floorName: string;
eqpList: EquipmentNode[];
}
//node
interface EquipmentNode {
id: string; //设备ID
name: string; //设备名称
isBinding: boolean; //是否绑定
eState: number; //设备状态 0正常 1故障
currentState: number; //当前状态 0运行 1停止 2报警
operation: boolean; //操作 true屏蔽 false取消屏蔽
}
function handleCellClick(obj: any) {
console.log('点击:', obj);
emitter.emit('binding-obj-facility-move', obj.id);
}
emitter.on('binding-data-update', () => {
console.log('@@binding-data-update');
dataInit();
});
const props = defineProps({
fontFamily: {
type: String,
default: '黑体'
},
fontSize: {
type: Number,
default: 12
},
testColor: {
type: String,
default: '#ffffff'
},
definitionItemJson: {
type: Object,
default: () => ({})
}
});
console.log('父传子itemjson:', props.definitionItemJson);
// 计算属性——既读取又修改
let computedSize = computed({
// 读取
get() {
return props.fontSize + 'px';
}, // 修改
set(val) {}
});
const arr = ref<any[]>([]);
let targetDataTable: FloorNode[] = [];
let initArrs: any = {};
//数据初始化
async function dataInit() {
// 从 window 获取 globalData可能是 Map 或对象)
const globalDataRaw = (window as unknown as ExtendedParentWindow).globalData;
// 清空数组
arr.value = [];
targetDataTable = [];
loading.value = true;
const response = await modelApi.oneRoomFor_Equipment_get();
if (response.code == 200 && response.data && response.data.length > 0) {
// console.log('公共:', window.parent.Rec.service.node.runtimes);
response.data.forEach((floor: any) => {
let targetData: FloorNode = {
roomId: floor.roomId,
floorName: floor.roomName,
eqpList: []
};
let eqpList: EquipmentNode[] = [];
floor.eqpList.forEach((eqp: any) => {
let currentState = 1;
// 根据 globalData 类型选择访问方式
const getNodeData = (key: string) => {
if (globalDataRaw instanceof Map) {
return globalDataRaw.get(key);
} else {
return (globalDataRaw as Record<string, any>)[key];
}
};
//故障
if (getNodeData(eqp.nodes[1])?.double != 1) currentState = 1;
else if (getNodeData(eqp.nodes[2])?.double == 1) currentState = 2;
else if (getNodeData(eqp.nodes[1])?.double == 1) currentState = 0;
let eqpNode: EquipmentNode = {
id: eqp.id,
name: getNodeData(eqp.nodes[0])?.node?.name || '',
eState: getNodeData(eqp.nodes[0])?.double || 0,
currentState: currentState,
isBinding: eqp.isBinding,
operation: getNodeData(eqp.nodes[3])?.double == 1
};
eqpList.push(eqpNode);
});
targetData.eqpList = eqpList;
targetDataTable.push(targetData);
});
ElMessage.success('获取接口数据成功');
arr.value = targetDataTable.flatMap((floor) =>
floor.eqpList.map((equipment) => ({
...equipment,
floorName: floor.floorName,
roomId: floor.roomId
}))
);
} else {
ElMessage.error('获取接口数据失败');
}
}
// 将嵌套数据展开为表格数据
const tableDatas = computed(() => {
return targetDataTable.flatMap((floor) =>
floor.eqpList.map((equipment) => ({
...equipment,
floorName: floor.floorName, // 添加楼层信息到每行
roomId: floor.roomId // 添加设备地址到每行
}))
);
});
// 在 onMounted 中
onMounted(async () => {
await dataInit();
});
onUnmounted(() => {
emitter.off('binding-data-update');
});
// 数据源头
const floorData: FloorObj[] = [
{
floorName: '安全工器具室',
equipments: [
{
id: 'smokeDetector01',
name: '1号感烟探头',
eState: 0,
currentState: 0,
operation: true
},
{
id: 'smokeDetector02',
name: '2号感烟探头',
eState: 0,
currentState: 0,
operation: true
}
]
},
{
floorName: '蓄电池室',
equipments: [
{
id: 'smokeDetector03',
name: '3号感烟探头',
eState: 1,
currentState: 1,
operation: false
},
{
id: 'smokeDetector04',
name: '4号感烟探头',
eState: 0,
currentState: 0,
operation: true
}
]
},
{
floorName: '220kV保护室',
equipments: [
{
id: 'smokeDetector05',
name: '5号感烟探头',
eState: 0,
currentState: 2,
operation: false
},
{
id: 'smokeDetector06',
name: '6号感烟探头',
eState: 1,
currentState: 1,
operation: true
}
]
},
{
floorName: '380kV配电室',
equipments: [
{
id: 'smokeDetector07',
name: '7号感烟探头',
eState: 0,
currentState: 0,
operation: false
},
{
id: 'smokeDetector08',
name: '8号感烟探头',
eState: 0,
currentState: 2,
operation: true
}
]
},
{
floorName: '35kV高压室',
equipments: [
{
id: 'smokeDetector09',
name: '9号感烟探头',
eState: 1,
currentState: 1,
operation: false
},
{
id: 'smokeDetector10',
name: '10号感烟探头',
eState: 0,
currentState: 0,
operation: true
}
]
},
{
floorName: '2号接地变室',
equipments: [
{
id: 'smokeDetector11',
name: '11号感烟探头',
eState: 0,
currentState: 2,
operation: false
},
{
id: 'smokeDetector12',
name: '12号感烟探头',
eState: 1,
currentState: 1,
operation: true
}
]
},
{
floorName: '110kV电缆室',
equipments: [
{
id: 'smokeDetector13',
name: '13号感烟探头',
eState: 0,
currentState: 0,
operation: false
},
{
id: 'smokeDetector14',
name: '14号感烟探头',
eState: 0,
currentState: 0,
operation: true
}
]
},
{
floorName: '2号站用变室',
equipments: [
{
id: 'smokeDetector15',
name: '15号感烟探头',
eState: 0,
currentState: 0,
operation: false
},
{
id: 'smokeDetector16',
name: '16号感烟探头',
eState: 0,
currentState: 0,
operation: true
}
]
},
{
floorName: '生产综合楼1楼走廊',
equipments: [
{
id: 'smokeDetector17',
name: '17号感烟探头',
eState: 0,
currentState: 0,
operation: false
},
{
id: 'smokeDetector18',
name: '18号感烟探头',
eState: 0,
currentState: 0,
operation: true
},
{
id: '10028',
name: '1号声光报警器',
eState: 0,
currentState: 0,
operation: false
},
{
id: '10029',
name: '2号声光报警器',
eState: 0,
currentState: 0,
operation: true
},
{
id: '10030',
name: '1号手报',
eState: 0,
currentState: 0,
operation: false
},
{
id: '10031',
name: '2号手报',
eState: 0,
currentState: 0,
operation: true
}
]
}
];
interface SpanMethodProps {
row: any;
column: TableColumnCtx<User>;
rowIndex: number;
columnIndex: number;
}
const objectSpanMethods = ({ row, columnIndex }: SpanMethodProps) => {
if (columnIndex === 0) {
// 查找当前行对应的楼层数据
const floor = targetDataTable.find((f) => f.floorName === row.floorName);
if (floor) {
// 找到该楼层下第一个设备的索引
const firstEquipmentIndex = floor.eqpList.findIndex((e) => e.id === row.id);
if (firstEquipmentIndex === 0) {
// 如果是第一个设备,合并该楼层的所有行
return {
rowspan: floor.eqpList.length,
colspan: 1
};
} else {
// 如果不是第一个设备,不显示(被合并)
return {
rowspan: 0,
colspan: 0
};
}
}
}
// 其他列不合并
return {
rowspan: 1,
colspan: 1
};
};
// 将嵌套数据展开为表格数据
const tableData = computed(() => {
return floorData.flatMap((floor) =>
floor.equipments.map((equipment) => ({
...equipment,
floorName: floor.floorName, // 添加楼层信息到每行
// 如果有设备地址就显示,没有就显示楼层作为地址
address: equipment.address || floor.floorName
}))
);
});
</script>
<style scoped>
.table-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.card {
flex: 1;
display: flex;
flex-direction: column;
height: 100%;
}
.card :deep(.el-card__body) {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 10px;
}
.table-wrapper {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
.full-height-table {
flex: 1;
height: 100%;
}
.full-height-table :deep(.el-table__body-wrapper) {
flex: 1;
overflow-y: auto;
}
.cardHead {
margin: 0 0 15px 0;
padding: 0;
font-size: 16px;
font-weight: bold;
text-align: center;
color: #ffffff;
flex-shrink: 0;
}
.operation-btn {
width: 60px;
min-width: 50px;
padding: 8px 12px;
height: 30px;
}
/* 控制表头文字大小 */
.full-height-table :deep(.el-table__header th) {
font-size: 13px;
font-weight: bold;
}
/* 控制表格内容文字大小 */
.full-height-table :deep(.el-table__body td) {
font-size: v-bind('computedSize');
color: v-bind('props.testColor');
}
/* 控制标签文字大小 */
.full-height-table :deep(.el-tag) {
font-size: v-bind('computedSize'); /* 标签内的文字可以稍小一些 */
}
/* 控制按钮文字大小 */
.full-height-table :deep(.el-button) {
font-size: v-bind('computedSize');
color: v-bind('props.testColor');
}
</style>