map/ui/dasadmin/src/views/backend/realData/index.vue
2024-11-26 11:08:07 +08:00

776 lines
26 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="default-main">
<el-dialog v-model="visible" title="测点选择" width="1000" :before-close="handleClose" :show-close="false">
<el-row :gutter="20">
<el-col :span="14">
<div class="transferLeft">
<div class="transferHeader">
<span class="transferTitle">可添加的测点</span>
<el-radio-group v-model="radioActiveName" @change="handleradioChange">
<el-radio value="138">模拟量</el-radio>
<el-radio value="199">计算量</el-radio>
<el-radio value="140">状态量</el-radio>
</el-radio-group>
</div>
<el-main class="mainPart">
<el-table class="tablePart"
ref="RealtableRef"
:data="modalTbleData"
@selectionChange="selectTable"
:row-key="getRowKey">
<!-- <el-table-column type="selection" width="55" :reserve-selection="true"/>-->
<el-table-column type="selection" width="55"/>
<el-table-column prop="porder" label="序号" width="60" />
<el-table-column prop="attributeCode" sortable label="名称" />
<el-table-column prop="attributeName" sortable label="描述" />
</el-table>
<div class="mainFooter" style="display: flex; justify-content: left">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="currentPageSize"
:total="pageTotal"
:page-sizes="pagePagination"
background
:pager-count="5"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="prev, pager, next,sizes"
></el-pagination>
</div>
</el-main>
</div>
</el-col>
<el-col :span="10">
<div class="transferRight">
<div class="transferHeader">
<span class="transferTitle">已选择<span>{{Statistic}}</span>项</span>
<div @click="clearList" style="color: rgb(0, 100, 170);cursor: pointer;">清空</div>
</div>
<el-main class="transferMain">
<el-scrollbar>
<div class="selectItem" v-for="(item, index) in multipleSelection"
:key="item.attributeCode">
{{item.attributeName}}
<div>
<el-icon :size="20" @click="moveUp(index)"><Top /></el-icon>
<el-icon :size="20" @click="moveDown(index)"><Bottom /></el-icon>
<el-icon :size="20" @click="removeremove(index, item)"><Close /></el-icon>
</div>
</div>
</el-scrollbar>
</el-main>
<!-- <div class="mainFooter" style="display: flex; justify-content: left">
<el-pagination
v-model:current-page="selectcurrentPage"
v-model:page-size="selectcurrentPageSize"
:total="selectpageTotal"
background
:pager-count="4"
@size-change="selecthandleSizeChange"
@current-change="selecthandleCurrentChange"
layout="prev, pager, next"
></el-pagination>
</div>-->
</div>
</el-col>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="sureBtn">保存</el-button>
<el-button @click="visible = false">取消</el-button>
</div>
</template>
</el-dialog>
<div class="realConter">
<div class="header">
<el-button type="primary" :icon="Crop" class="defaultBtn" @click="openMeasure">测点选择</el-button>
<el-button style="color: rgb(0, 100, 170);" :icon="Download" class="defaultBtn" @click="downFun(tableColumn,tableData)">数据导出</el-button>
<div class="selectPart">
<span>自动更新:</span>
<el-switch
v-model="autoUpdate"
class="ml-2"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
></el-switch>
</div>
</div>
<div class="realTable">
<el-table height="100%" :data="tableData">
<template v-for="item in tableColumn">
<el-table-column :prop="item.prop" :label="item.label" :align="item.align" />
<!-- <el-table-column v-if="item.custom === 'default'" :prop="item.prop" :label="item.label" :align="item.align" />
<el-table-column v-if="item.custom === 'header'" :prop="item.prop" :label="item.label+item.unit" :align="item.align" />-->
</template>
</el-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {Crop,Download,Top,Bottom,Close} from '@element-plus/icons-vue'
import {onMounted, onUnmounted, reactive, ref, watch,computed,nextTick} from 'vue'
import {ElMessage} from 'element-plus'
import {equipList,getModelAttributeList,getsnapshotData} from "/@/api/backend/realData/request.ts";
import {getAllEnumData} from "/@/api/backend/Enumeration/request";
import { useEnumStore } from '/@/stores/enums'
const enumStore = useEnumStore()
const tableData = ref()
const tableItem0: any = [
{
label: '风机列表',
unit:' ',
prop: 'name',
align: 'center',
custom: 'default',
name:'name',
title: '风机列表'
}]
const tableItem1: any = [
{
label: '机组运行状态',
unit: ' ',
prop: 'iturbineoperationmode',
align: 'center',
custom: 'header',
name: 'iTurbineOperationMode',
title: '机组运行状态'
},
{
label: '风速 (m/s)',
unit: ' (m/s)',
prop: 'iwindspeed',
align: 'center',
custom: 'header',
name:'iWindSpeed',
title: '风速'
},
{
label: '风向',
unit: '',
prop: 'iwinddirection',
align: 'center',
custom: 'header',
name:'iWindDirection',
title: '风向'
},
{
label: '发电机转速 (rmp)',
unit:' (rmp)',
prop: 'igenspeed',
align: 'center',
custom: 'header',
name:'iGenSpeed',
title: '发电机转速'
},
{
label: '有功功率 (kW)',
unit:' (kW)',
prop: 'igenpower',
align: 'center',
custom: 'header',
name:'iGenPower',
title: '有功功率'
},
{
label: '给定有功功率 (kW)',
unit:' (kW)',
prop: 'iactivepowersetpointvalue',
align: 'center',
custom: 'header',
name:'iActivePowerSetPointValue',
title: '给定有功功率'
},
{
label: '无功功率 (kvar)',
unit:' (kvar)',
prop: 'ireactivepower',
align: 'center',
custom: 'header',
name:'iReactivePower',
title: '无功功率'
},
{
label: '给定无功功率 (kvar)',
unit:' (kvar)',
prop: 'ireactivepowersetpointvalue',
align: 'center',
custom: 'header',
name:'iReactivePowerSetPointValue',
title: '给定无功功率'
},
{
label: '桨叶1角度',
unit: ' ',
prop: 'ipitchangle1',
align: 'center',
custom: 'header',
name:'iPitchAngle1',
title: '桨叶1角度'
},
{
label: '桨叶2角度',
unit: ' ',
prop: 'ipitchangle2',
align: 'center',
custom: 'header',
name:'iPitchAngle2',
title: '桨叶2角度'
},
{
label: '桨叶3角度',
unit: ' ',
prop: 'ipitchangle3',
align: 'center',
custom: 'header',
name:'iPitchAngle3',
title: '桨叶1角度'
},
{
label: '限电原因',
unit: ' ',
prop: 'powerlimitsource',
align: 'center',
custom: 'header',
name:'PowerLimitSource',
title: '限电原因'
},
{
label: '机舱位置',
unit: ' ',
prop: 'ivanedirection',
align: 'center',
custom: 'header',
name:'iVaneDirection',
title: '机舱位置'
},
{
label: '日发电量 (kWh)',
unit:' (kWh)',
prop: 'ikwhthisday',
align: 'center',
custom: 'header',
name:'iKWhThisDay',
title: '日发电量'
}
]
const tableColumn=ref(
[...tableItem0,...tableItem1]
)
const deviceList = ref()
const tableList=ref()
const modalTbleData=ref<any[]>([])
const devicelistData = reactive({
objectType: 10002,
})
const objectType= ref(10002);
const iotModelId=ref()
const radioActiveName=ref('138')
const selectedIndex=ref(0)
const newtableData=ref()
const deviceQuery = (data: any) => {
equipList(data).then((res) => {
deviceList.value = res.data
tableData.value = res.data.map((item) => {
return {
id:item.id,
name: item.name ?? '-',
}
})
newtableData.value = res.data.map((item) => {
return {
id:item.id,
name: item.name ?? '-',
}
})
iotModelId.value=res.data[0].iotModelId
defaultdeviceQuery()
})
}
const defaultdeviceQuery = () => {
const deviceId=deviceList.value.map((item) => item.id);
let attributesCode:any[]=[]
deviceId.forEach((item,index) => {
objparms.deviceId=item
attributesCode=tableColumn.value.map((item1)=>item1.prop)
objparms.attributes=attributesCode
snapshotParms.push({...objparms})
})
getsnapshotData(snapshotParms).then((res) => {
if (res.code == 200) {
const tsnapshotVoObject: any = res.data;
const tsnapshotVoMap = new Map(Object.entries(tsnapshotVoObject));
const updatedTableData = tableColumn.value.reduce((acc, item1) => {
acc.forEach((item, i) => {
const itemKey = item.id;
if (tsnapshotVoMap.has(itemKey)) {
const tsnapshotVoItem = tsnapshotVoMap.get(itemKey);
//const attributeCodeLower = item1.attributeCode?.toLowerCase();
const attributeCodeLower = item1.prop;
if(attributeCodeLower!='name'){
if (attributeCodeLower) {
const value=tsnapshotVoItem[attributeCodeLower];
let formattedValue = value !== undefined ? (value % 1 === 0 ? value : value.toFixed(1)) : '-';
if (enumStore.keys.includes(item1.name)) {
formattedValue = enumStore.data[item1.name][formattedValue]?enumStore.data[item1.name][formattedValue]:'-'
}
acc[i] = { ...item, [attributeCodeLower]: formattedValue};
}
}
}
});
return acc;
}, [...tableData.value]);
tableData.value = updatedTableData;
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
}
const queryListData = reactive({
pageSize: 20,
pageNum: 1,
iotModelId: '',
attributeType: '138'
})
const modelAttributeList=(data: any) =>{
getModelAttributeList(data).then((res) => {
if (res.code == 200) {
modalTbleData.value = res.rows
pageTotal.value = res.total;
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
}
interface TableType {
attributeCode:string
attributeName:string
attributeType:number
dataType:string
highSpeed:number
id:string
iotModelId:string
porder:number
revision:number
subSystem:string
unit:string
visible:number | null
}
const selectList=ref([])
const getSel = () => {
selectList.value=[]
try {
if (tableColumn.value && Array.isArray(tableColumn.value)) {
for (const item of tableColumn.value) {
if (item && item.prop && item.prop !== 'name') {
if(item.title!==undefined){
selectList.value.push({
attributeName: item.title || '',
attributeCode: item.name || '',
unit: item.unit || '',
});
}
}
}
}
} catch (error) {
console.error('Error in tableColumn processing:', error);
}
multipleSelection.value=selectList.value
};
let isCheckRow = false;
const RealtableRef=ref<any>()
const multipleSelection = ref<TableType[]>([])
const Statistic = computed(() => multipleSelection.value.length)
const selectTable = (selected: TableType[] | null) => {
if (!selected) {
console.error('Selected is null or undefined')
return
}
debugger
selected.forEach((item, index) => {
if (!multipleSelection.value.some(item1 => item1.attributeCode === item.attributeCode)) {
multipleSelection.value.push(item);
}
});
}
const getRowKey = (row) => row.attributeCode;
const visible = ref(false)
const openMeasure=() =>{
visible.value=true
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
nextTick(() => {
getSel()
})
}
const moveUp = (index:number) => {
if (index > 0) {
const temp = multipleSelection.value[index];
multipleSelection.value[index] = multipleSelection.value[index - 1];
multipleSelection.value[index - 1] = temp;
selectedIndex.value = index - 1;
}
};
const moveDown = (index:number) => {
if (index < multipleSelection.value.length - 1) {
const temp = multipleSelection.value[index];
multipleSelection.value[index] = multipleSelection.value[index + 1];
multipleSelection.value[index + 1] = temp;
selectedIndex.value = index + 1;
}
};
const removeremove=(index:number, row:any)=>{
multipleSelection.value.splice(index, 1);
nextTick(() => {
isCheckRow = true;
const finIindexNum = modalTbleData.value.findIndex((item: any) => item.attributeCode === row.attributeCode);
if (finIindexNum !== -1) {
RealtableRef.value.toggleRowSelection(modalTbleData.value[finIindexNum], false, false);
ElMessage.success('删除成功')
}
})
}
const clearList=() => {
Statistic.value=0
multipleSelection.value = [];
RealtableRef.value.clearSelection()
//tableData.value=[]
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const handleradioChange=() => {
//multipleSelection.value = [];
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const autoUpdate = ref(false)
const autoUpdateInterval = ref<any>(null)
watch(autoUpdate, (newVal: boolean) => {
if (newVal) {
if (autoUpdateInterval.value) return
ElMessage.success('开启自动刷新')
autoUpdateInterval.value = setInterval(() => {
defaultdeviceQuery()
//getTableData()
}, 2000)
} else {
ElMessage.warning('关闭自动刷新')
clearInterval(autoUpdateInterval.value)
autoUpdateInterval.value = null
}
})
const currentPage = ref(1)
//const currentPageSize = ref(20)
const currentPageSize = ref(20)
const pageTotal = ref(0)
const pagePagination = ref([20, 50, 100])
const handleSizeChange = (val: number) => {
queryListData.pageSize = val
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const handleCurrentChange = (val: number) => {
queryListData.pageNum = val
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const selectcurrentPage = ref(1)
const selectcurrentPageSize = ref(10)
const selectpageTotal = ref(0)
const selecthandleSizeChange = (val: number) => {
}
const selecthandleCurrentChange = (val: number) => {
}
const handleClose = (done: () => void) => {
visible.value = false
}
const snapshotParms = reactive([])
const objparms = reactive({
deviceId: '',
attributes: [],
})
const getTableData = () => {
const deviceId=deviceList.value.map((item) => item.id);
const tableColumnEnds = ref([]);
if(multipleSelection.value.length === 0){
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
}else{
multipleSelection.value.forEach(item => {
if (item.attributeCode) {
const attributeCodeLower = item.attributeCode.toLowerCase();
if(item.unit==""||item.unit==undefined){
tableColumnEnds.value.push({
label: item.attributeName,
unit:item.unit,
prop: attributeCodeLower,
align: 'center',
custom: 'header',
name: item.attributeCode,
title: item.attributeName,
});
}else{
tableColumnEnds.value.push({
label: item.attributeName+'\n'+item.unit,
unit:item.unit,
prop: attributeCodeLower,
align: 'center',
custom: 'header',
name: item.attributeCode,
title: item.attributeName,
});
}
}
});
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
}
tableData.value = []
const deviceNameList=deviceList.value.map((item) => {
return {
id:item.id,
name: item.name ?? '-',
}
});
deviceId.forEach((item,index) => {
objparms.deviceId=item
objparms.attributes=multipleSelection.value.map((item) => item.attributeCode)
snapshotParms.push({...objparms})
})
deviceNameList.forEach((item1,index) => {
const NameItem={
id:item1.id,
name: item1.name,
}
tableData.value.push({...NameItem})
})
getsnapshotData(snapshotParms).then((res) => {
if (res.code == 200) {
const tsnapshotVoObject: any = res.data;
multipleSelection.value.map((item1: any) => {
//tableData.value = [];
tableData.value.forEach((item: any, i: number, arr: any) => {
for (const itemKey in tsnapshotVoObject) {
if (item.id === itemKey) {
const attributeCodeLower = item1.attributeCode?.toLowerCase();
const value = tsnapshotVoObject[itemKey]?.[attributeCodeLower];
let formattedValue = value !== undefined ? (value % 1 === 0 ? value : value.toFixed(1)) : '-';
if (enumStore.keys.includes(item1.attributeCode)) {
formattedValue = enumStore.data[item1.attributeCode][formattedValue]?enumStore.data[item1.attributeCode][formattedValue]:'-'
}
arr[i] = { ...item, [attributeCodeLower]: formattedValue};
}
}
});
})
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
}
const sureBtn = (done: () => void) => {
getTableData()
visible.value = false
}
const downFun=(tableColumn,tableData)=>{
const itemsWithoutAge = tableData.map(item => {
const { id, ...rest } = item;
return rest;
});
if (!tableColumn.length || !itemsWithoutAge.length) {
return [];
}
const columnSet = new Set(tableColumn.map(item => item.prop));
const result = [];
itemsWithoutAge.forEach((item) => {
const newItem = {};
for (const itemKey in item) {
if (columnSet.has(itemKey)) {
newItem[itemKey] = item[itemKey];
}
}
if (Object.keys(newItem).length > 0) {
result.push(newItem);
}
});
let addobj = {}
tableColumn.map((v, i) => {
addobj['rowData' + i] = v.label
})
let tableDatadown = JSON.parse(JSON.stringify(result))
tableDatadown.unshift(addobj)
let str = ``;
for(let i = 0; i < tableDatadown.length; i++) {
for(let item in tableDatadown[i]) {
if (typeof tableDatadown[i][item] === 'string') {
tableDatadown[i][item] = tableDatadown[i][item].replace(/[\n,]/g, match => match === '\n' ? ' ' : '');
} else {
console.warn(`tableDatadown[${i}][${item}] is not a string`);
}
str += `${tableDatadown[i][item] + '\t'},`;
}
str += '\n';
}
let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
let link = document.createElement('a');
link.href = uri;
link.download = '实时数据'+Date.now() + ".csv";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
onUnmounted(() => {
autoUpdateInterval.value && clearInterval(autoUpdateInterval.value)
autoUpdateInterval.value = null
})
onMounted(() => {
deviceQuery(devicelistData)
modelAttributeList(queryListData)
})
</script>
<style scoped lang="scss">
$paginationHeight: 32px;
.default-main {
/* width: 100%;*/
height: 100%;
.realConter {
width: 100%;
height: 100%;
/* height: calc(100% - 20px);*/
.header {
display: flex;
.el-button{
width: 140px;
height: 40px;
}
.selectPart{
display: flex;
align-items: center;
margin-left: 20px;
}
}
.realTable{
margin-top: 20px;
height: calc(100% - 60px);
}
}
.el-dialog{
.transferHeader{
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
color: #333333;
background: #F7F9FC;
border-bottom: 1px solid #E1EDF6;
border-radius: 6px 6px 0 0;
}
.transferLeft{
width: 550px;
height: 700px;
border: 1px solid #E1EDF6;
border-radius: 6px;
.mainPart{
padding: 10px;
height: 625px;
overflow: hidden;
.tablePart {
height: calc(100% - $paginationHeight);
}
.mainFooter{
margin-top: 10px;
}
}
}
.transferRight{
height: 700px;
border: 1px solid #E1EDF6;
border-radius: 6px;
.transferMain{
height: 655px;
/*padding: 10px;*/
padding:0;
::v-deep .el-table__row{
height: 40px;
padding: 0 20px;
background: #EFF0F1;
border-radius: 4px;
}
.selectItem{
height: 40px;
padding: 0 20px;
background: #EFF0F1;
border-radius: 4px;
margin: 10px;
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
.el-icon{
cursor: pointer;
}
}
}
.mainFooter{
padding: 10px;
}
}
.dialog-footer{
text-align: center;
.el-button{
width: 120px;
height: 40px;
}
}
}
}
</style>