修改预检测实时数据详情展示

This commit is contained in:
guanj
2025-08-27 14:55:00 +08:00
parent 772707ac42
commit 567201563d
17 changed files with 2513 additions and 2537 deletions

View File

@@ -1,84 +1,83 @@
<template>
<Maximize v-show="maximize" />
<Tabs v-if="tabs && showMenuFlag" />
<el-main>
<router-view v-slot="{ Component, route }" style="height:100%;">
<!-- {{ keepAliveName}} -->
<!-- <transition name="slide-right" mode="out-in"> -->
<keep-alive :include="tabsMenuList" >
<component :is="Component" :key="route.fullPath" />
</keep-alive>
<!-- </transition> -->
</router-view>
</el-main>
<el-footer>
<Footer />
</el-footer>
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount, provide, watch, computed } from "vue";
import { storeToRefs } from "pinia";
import { useDebounceFn } from "@vueuse/core";
import { useGlobalStore } from "@/stores/modules/global";
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
import Maximize from "./components/Maximize.vue";
import Tabs from "@/layouts/components/Tabs/index.vue";
import Footer from "@/layouts/components/Footer/index.vue";
import { useAuthStore } from "@/stores/modules/auth";
import { useTabsStore } from '@/stores/modules/tabs'
const tabStore = useTabsStore()
const globalStore = useGlobalStore();
const tabsMenuList = computed(() => tabStore.tabsMenuList.map(item => item.name))
const authStore = useAuthStore();
const { maximize, isCollapse, layout, tabs, footer } = storeToRefs(globalStore);
const keepAliveStore = useKeepAliveStore();
const { keepAliveName } = storeToRefs(keepAliveStore);
// console.log("🚀 ~ keepAliveName:", keepAliveName)
//是否显示导航栏
const showMenuFlag = computed(() => authStore.showMenuFlagGet);
// 注入刷新页面方法
const isRouterShow = ref(true);
const refreshCurrentPage = (val: boolean) => (isRouterShow.value = val);
provide("refresh", refreshCurrentPage);
// 监听当前页面是否最大化,动态添加 class
watch(
() => maximize.value,
() => {
const app = document.getElementById("app") as HTMLElement;
if (maximize.value) app.classList.add("main-maximize");
else app.classList.remove("main-maximize");
},
{ immediate: true }
);
// 监听布局变化,在 body 上添加相对应的 layout class
watch(
() => layout.value,
() => {
const body = document.body as HTMLElement;
body.setAttribute("class", layout.value);
},
{ immediate: true }
);
// 监听窗口大小变化,折叠侧边栏
const screenWidth = ref(0);
const listeningWindow = useDebounceFn(() => {
screenWidth.value = document.body.clientWidth;
if (!isCollapse.value && screenWidth.value < 1200)
globalStore.setGlobalState("isCollapse", true);
if (isCollapse.value && screenWidth.value > 1200)
globalStore.setGlobalState("isCollapse", false);
}, 100);
window.addEventListener("resize", listeningWindow, false);
onBeforeUnmount(() => {
window.removeEventListener("resize", listeningWindow);
});
</script>
<style scoped lang="scss">
@import "./index.scss";
</style>
<template>
<Maximize v-show="maximize" />
<Tabs v-if="tabs && showMenuFlag" />
<el-main>
<router-view v-slot="{ Component, route }" style="height:100%;">
<!-- {{ keepAliveName}} -->
<!-- <transition name="slide-right" mode="out-in"> -->
<keep-alive :include="tabsMenuList" >
<component :is="Component" :key="route.fullPath" />
</keep-alive>
<!-- </transition> -->
</router-view>
</el-main>
<el-footer>
<Footer />
</el-footer>
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount, provide, watch, computed } from "vue";
import { storeToRefs } from "pinia";
import { useDebounceFn } from "@vueuse/core";
import { useGlobalStore } from "@/stores/modules/global";
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
import Maximize from "./components/Maximize.vue";
import Tabs from "@/layouts/components/Tabs/index.vue";
import Footer from "@/layouts/components/Footer/index.vue";
import { useAuthStore } from "@/stores/modules/auth";
import { useTabsStore } from '@/stores/modules/tabs'
const tabStore = useTabsStore()
const globalStore = useGlobalStore();
const tabsMenuList = computed(() => tabStore.tabsMenuList.map(item => item.name))
const authStore = useAuthStore();
const { maximize, isCollapse, layout, tabs, footer } = storeToRefs(globalStore);
const keepAliveStore = useKeepAliveStore();
const { keepAliveName } = storeToRefs(keepAliveStore);
//是否显示导航栏
const showMenuFlag = computed(() => authStore.showMenuFlagGet);
// 注入刷新页面方法
const isRouterShow = ref(true);
const refreshCurrentPage = (val: boolean) => (isRouterShow.value = val);
provide("refresh", refreshCurrentPage);
// 监听当前页面是否最大化,动态添加 class
watch(
() => maximize.value,
() => {
const app = document.getElementById("app") as HTMLElement;
if (maximize.value) app.classList.add("main-maximize");
else app.classList.remove("main-maximize");
},
{ immediate: true }
);
// 监听布局变化,在 body 上添加相对应的 layout class
watch(
() => layout.value,
() => {
const body = document.body as HTMLElement;
body.setAttribute("class", layout.value);
},
{ immediate: true }
);
// 监听窗口大小变化,折叠侧边栏
const screenWidth = ref(0);
const listeningWindow = useDebounceFn(() => {
screenWidth.value = document.body.clientWidth;
if (!isCollapse.value && screenWidth.value < 1200)
globalStore.setGlobalState("isCollapse", true);
if (isCollapse.value && screenWidth.value > 1200)
globalStore.setGlobalState("isCollapse", false);
}, 100);
window.addEventListener("resize", listeningWindow, false);
onBeforeUnmount(() => {
window.removeEventListener("resize", listeningWindow);
});
</script>
<style scoped lang="scss">
@import "./index.scss";
</style>

View File

@@ -1,122 +1,121 @@
<template>
<div class="tabs-box">
<div class="tabs-menu">
<el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
<el-tab-pane
v-for="item in tabsMenuList"
:key="item.path"
:label="item.title"
:name="item.path"
:closable="item.close"
>
<template #label>
<el-icon v-show="item.icon && tabsIcon" class="tabs-icon">
<component :is="item.icon"></component>
</el-icon>
{{ item.title }}
</template>
</el-tab-pane>
</el-tabs>
<MoreButton />
</div>
</div>
</template>
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth'
import { TabsPaneContext, TabPaneName } from 'element-plus'
import MoreButton from './components/MoreButton.vue'
const route = useRoute()
const router = useRouter()
const tabStore = useTabsStore()
const authStore = useAuthStore()
const globalStore = useGlobalStore()
const tabsMenuValue = ref(route.fullPath)
const tabsMenuList = computed(() => tabStore.tabsMenuList)
const tabsIcon = computed(() => globalStore.tabsIcon)
onMounted(() => {
tabsDrop()
initTabs()
})
// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue
watch(
() => route.fullPath,
() => {
if (route.meta.isFull) return
if (route.meta.hideTab) {
tabsMenuValue.value = route.meta.parentPath as string
} else {
tabsMenuValue.value = route.fullPath
const tabsParams = {
icon: route.meta.icon as string,
title: route.meta.title as string,
path: route.fullPath,
name: route.name as string,
close: !route.meta.isAffix,
isKeepAlive: route.meta.isKeepAlive as boolean
}
tabStore.addTabs(tabsParams)
}
},
{ immediate: true }
)
// 初始化需要固定的 tabs
const initTabs = () => {
authStore.flatMenuListGet.forEach(item => {
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
const tabsParams = {
icon: item.meta.icon,
title: item.meta.title,
path: item.path,
name: item.name,
close: !item.meta.isAffix,
isKeepAlive: item.meta.isKeepAlive,
unshift: true
}
tabStore.addTabs(tabsParams)
}
})
}
// tabs 拖拽排序
const tabsDrop = () => {
Sortable.create(document.querySelector('.el-tabs__nav') as HTMLElement, {
draggable: '.el-tabs__item',
animation: 300,
onEnd({ newIndex, oldIndex }) {
const tabsList = [...tabStore.tabsMenuList]
const currRow = tabsList.splice(oldIndex as number, 1)[0]
tabsList.splice(newIndex as number, 0, currRow)
tabStore.setTabs(tabsList)
}
})
}
// Tab Click
const tabClick = (tabItem: TabsPaneContext) => {
const fullPath = tabItem.props.name as string
// console.log("🚀 ~ tabClick ~ fullPath:", tabItem)
router.push(fullPath)
}
// Remove Tab
const tabRemove = (fullPath: TabPaneName) => {
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath)
}
</script>
<style scoped lang="scss">
@import './index.scss';
</style>
<template>
<div class="tabs-box">
<div class="tabs-menu">
<el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
<el-tab-pane
v-for="item in tabsMenuList"
:key="item.path"
:label="item.title"
:name="item.path"
:closable="item.close"
>
<template #label>
<el-icon v-show="item.icon && tabsIcon" class="tabs-icon">
<component :is="item.icon"></component>
</el-icon>
{{ item.title }}
</template>
</el-tab-pane>
</el-tabs>
<MoreButton />
</div>
</div>
</template>
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth'
import { TabsPaneContext, TabPaneName } from 'element-plus'
import MoreButton from './components/MoreButton.vue'
const route = useRoute()
const router = useRouter()
const tabStore = useTabsStore()
const authStore = useAuthStore()
const globalStore = useGlobalStore()
const tabsMenuValue = ref(route.fullPath)
const tabsMenuList = computed(() => tabStore.tabsMenuList)
const tabsIcon = computed(() => globalStore.tabsIcon)
onMounted(() => {
tabsDrop()
initTabs()
})
// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue
watch(
() => route.fullPath,
() => {
if (route.meta.isFull) return
if (route.meta.hideTab) {
tabsMenuValue.value = route.meta.parentPath as string
} else {
tabsMenuValue.value = route.fullPath
const tabsParams = {
icon: route.meta.icon as string,
title: route.meta.title as string,
path: route.fullPath,
name: route.name as string,
close: !route.meta.isAffix,
isKeepAlive: route.meta.isKeepAlive as boolean
}
tabStore.addTabs(tabsParams)
}
},
{ immediate: true }
)
// 初始化需要固定的 tabs
const initTabs = () => {
authStore.flatMenuListGet.forEach(item => {
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
const tabsParams = {
icon: item.meta.icon,
title: item.meta.title,
path: item.path,
name: item.name,
close: !item.meta.isAffix,
isKeepAlive: item.meta.isKeepAlive,
unshift: true
}
tabStore.addTabs(tabsParams)
}
})
}
// tabs 拖拽排序
const tabsDrop = () => {
Sortable.create(document.querySelector('.el-tabs__nav') as HTMLElement, {
draggable: '.el-tabs__item',
animation: 300,
onEnd({ newIndex, oldIndex }) {
const tabsList = [...tabStore.tabsMenuList]
const currRow = tabsList.splice(oldIndex as number, 1)[0]
tabsList.splice(newIndex as number, 0, currRow)
tabStore.setTabs(tabsList)
}
})
}
// Tab Click
const tabClick = (tabItem: TabsPaneContext) => {
const fullPath = tabItem.props.name as string
router.push(fullPath)
}
// Remove Tab
const tabRemove = (fullPath: TabPaneName) => {
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath)
}
</script>
<style scoped lang="scss">
@import './index.scss';
</style>

View File

@@ -39,7 +39,6 @@ export const useCheckStore = defineStore(CHECK_STORE_KEY, {
this.selectTestItems.test = true
},
setSelectTestItems(selectTestItems: CheckData.SelectTestItem) {
console.log("🚀 ~ setSelectTestItems ~ selectTestItems:", selectTestItems)
this.selectTestItems = selectTestItems
},
setCheckType(checkType: number) {

View File

@@ -244,7 +244,7 @@ const handleNext = async () => {
},
{} as Record<string, string>
)
generateChannelMapping()
await generateChannelMapping()
await checkStore.setChnNum(chnNumList)
return {
title: dialogTitle.value,
@@ -308,12 +308,13 @@ const generateChannelMapping = () => {
// 查找对应的节点以获取显示名称
const sourceDeviceNode = nodes.value.find(node => node.id === sourceDeviceId)
const targetDeviceNode = nodes.value.find(node => node.id === targetDeviceId)
if (sourceDeviceNode && targetDeviceNode) {
// 提取设备显示文本
const sourceDeviceText = sourceDeviceNode.data.label.children[1].children
const targetDeviceText = targetDeviceNode.data.label.children[1].children
const sourceDeviceText = sourceDeviceNode.data.label.children[1].children[0].children
const targetDeviceText = targetDeviceNode.data.label.children[1].children[0].children
// 构造键名 - 现在以标准设备为键
const targetKey = `${targetDeviceText}`.replace('设备名称:', '')

View File

@@ -220,7 +220,6 @@ const checkResultView: ComputedRef<CheckData.ScriptChnViewItem[]> = computed(()
devices: []
}
item.devices.forEach(device => {
console.log('🚀 ~ item:', item, CheckData.ChnCheckResultEnum)
let tempChnBtnResult: CheckData.ButtonResult[] = []
if (chnSum.value <= MAX_CHN_SUM) {
@@ -299,7 +298,6 @@ let count = 0
watch(
webMsgSend,
function (newValue, oldValue) {
console.log('🚀 ~ newValue:', newValue)
if (checkStore.selectTestItems.preTest == false && newValue.requestId != 'formal_real') {
if (testLogList[0].log == '正在检测,请稍等...' || testLogList[0].log == '暂无数据,等待检测开始') {
testLogList.shift()

View File

@@ -450,7 +450,6 @@ watch(ActiveStatue, function (newValue, oldValue) {
if (newValue === 'success' && stepsActiveIndex.value === stepsTotalNum.value - 1) {
stepsActiveIndex.value += 2
nextStepText.value = '检测完成'
console.log('🚀 ~ nextStepText.value:', nextStepText.value)
}
if (newValue === 'test_init_fail') {
stepsActiveIndex.value += 2
@@ -581,7 +580,6 @@ const nextStep = () => {
}
const handleStepClick = (step: number) => {
console.log('🚀 ~ handleStepClick ~ step > stepsActive.value:', step, stepsActive.value)
if (step > stepsActive.value) {
return

View File

@@ -269,6 +269,7 @@ const openTestDialog = async () => {
generateChannelMapping()
setTimeout(() => {
testPopup.value?.open(
dialogTitle.value,
channelMapping.value,

View File

@@ -778,10 +778,7 @@ const handleTest2 = async () => {
const deviceNames = inconsistentPointDevices.map(d => d.name).join(', ')
ElMessage.warning(`以下设备存在通道未绑定监测点: ${deviceNames}`)
}
console.log("🚀 ~ handleTest2 ~ filteredChannelsSelection, pqStandardDevList.value, props.id:", filteredChannelsSelection, )
console.log("🚀 ~ handleTest2 ~ filteredChannelsSelection, pqStandardDevList.value, props.id:", pqStandardDevList.value, )
console.log("🚀 ~ handleTest2 ~ filteredChannelsSelection, pqStandardDevList.value, props.id:", props.id)
// 只传递有监测点的设备
deviceConnectionPopupRef.value?.open(filteredChannelsSelection, pqStandardDevList.value, props.id)
}

View File

@@ -1,166 +1,165 @@
<template>
<el-tree
node-key="id"
default-expand-all
:data="props.treeData"
:props="defaultProps"
style="width: 100%"
:expand-on-click-node="false"
:highlight-current="true"
@node-click="handleNodeClick"
show-checkbox
:check-strictly="true"
@check-change="handleCheckChange"
ref="treeRef"
>
<template #default="{ node, data }">
<el-tooltip effect="dark" :content="data.sourceDesc || data.scriptTypeName" placement="top" :hide-after="0">
<div class="custom-tree-node">
{{ data.scriptTypeName || data.sourceDesc }}
</div>
</el-tooltip>
</template>
</el-tree>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch, nextTick } from 'vue'
import { CheckData } from '@/api/check/interface'
import { da } from 'element-plus/es/locale'
import { on } from 'events'
const props = defineProps({
treeData: {
type: Array,
required: true
}
})
const emit = defineEmits(['setTab'])
const dataTree = ref<CheckData.TreeItem[]>([])
const defaultProps = {
children: 'children',
label: 'scriptTypeName',
pid: 'pid'
}
const activeName = ref('')
const childActiveName = ref('')
const activeIndex = ref()
const treeRef = ref()
const handleNodeClick = (data, node) => {
if(data.index!= null){
let code = ['Base', 'VOL', 'Freq', 'Harm', 'Base_0_10', 'Base_20_85', 'Base_110_200']
const parents = getParentNodes(node, [])
parents.pop()
parents.unshift(node.data)
parents.reverse()
let active = parents[0].scriptTypeCode
let childActive = findTargetCodes(parents, code)[0] || ''
// 获取当前节点的直接父节点
if (activeName.value != active || childActiveName.value != childActive || activeIndex.value != data.index) {
activeName.value = active
childActiveName.value = childActive
emit('setTab', {
activeName: active,
childActiveName: childActive,
activeIndex:data.index
})
}
}
}
// 返回父级
const getParentNodes = (node, parents) => {
if (node.parent) {
// 将父节点添加到数组中
parents.push(node.parent.data)
// 递归获取更高层级的父节点
getParentNodes(node.parent, parents)
}
return parents
}
// 判断childActiveName值
function findTargetCodes(data: any[], targetCodes: string[]) {
let result: string[] = []
data.forEach(item => {
if (item.scriptTypeCode != null) {
if (targetCodes.includes(item.scriptTypeCode)) {
result.push(item.scriptTypeCode)
}
}
})
return result
// for (let item of data) {
// // 判断当前项的 scriptTypeCode 是否包含目标值
// if (item.scriptTypeCode !=null && targetCodes.includes(item.scriptTypeCode)) {
// console.log("🚀 ~ findTargetCodes ~ targetCodes.includes(item.scriptTypeCode):",item.scriptTypeCode, targetCodes.includes(item.scriptTypeCode))
// result.push(item.scriptTypeCode)
// return result
// }
// // 如果存在 children递归检查
// if (item.children && item.children.length > 0) {
// result = result.concat(findTargetCodes(item.children, targetCodes))
// }
// }
// return result
}
function handleCheckChange(data,isChecked) {
if (isChecked)
{
// 如果没有子节点,允许勾选
const checked = [data.id]; // id为tree的node-key属性
treeRef.value?.setCheckedKeys(checked);
emit('setTab', {
activeName: data.scriptType,
childActiveName: data.scriptTypeCode,
activeIndex:data.index
})
}
}
// 递归查找第一个节点的最后一层子节点
function findFirstLeafNode(node: any): any {
if (node.children && node.children.length > 0) {
return findFirstLeafNode(node.children[0]);
}
return node;
}
const checkTree = () => {
console.log('checkTree11')
console.log('checkTree22',props.treeData.length)
console.log('checkTree33',treeRef.value)
if (props.treeData.length > 0 && treeRef.value) {
console.log('checkTree44')
const firstNode = props.treeData[0];
const firstLeafNode = findFirstLeafNode(firstNode);
const firstLeafNodeId = firstLeafNode.id;
treeRef.value.setCheckedKeys([firstLeafNodeId]);
}
}
// 确保在组件挂载后也执行一次
onMounted(() => {
console.log('onMounted',props.treeData);
nextTick(() => {
checkTree()
});
});
// // 对外映射
defineExpose({ checkTree })
</script>
<style lang="scss" scoped>
.custom-tree-node {
max-width: 230px;
overflow-x: hidden !important;
white-space: nowrap !important;
text-overflow: ellipsis !important;
}
</style>
<template>
<el-tree
node-key="id"
default-expand-all
:data="props.treeData"
:props="defaultProps"
style="width: 100%"
:expand-on-click-node="false"
:highlight-current="true"
@node-click="handleNodeClick"
show-checkbox
:check-strictly="true"
@check-change="handleCheckChange"
ref="treeRef"
>
<template #default="{ node, data }">
<el-tooltip effect="dark" :content="data.sourceDesc || data.scriptTypeName" placement="top" :hide-after="0">
<div class="custom-tree-node">
{{ data.scriptTypeName || data.sourceDesc }}
</div>
</el-tooltip>
</template>
</el-tree>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch, nextTick } from 'vue'
import { CheckData } from '@/api/check/interface'
import { da } from 'element-plus/es/locale'
import { on } from 'events'
const props = defineProps({
treeData: {
type: Array,
required: true
}
})
const emit = defineEmits(['setTab'])
const dataTree = ref<CheckData.TreeItem[]>([])
const defaultProps = {
children: 'children',
label: 'scriptTypeName',
pid: 'pid'
}
const activeName = ref('')
const childActiveName = ref('')
const activeIndex = ref()
const treeRef = ref()
const handleNodeClick = (data, node) => {
if(data.index!= null){
let code = ['Base', 'VOL', 'Freq', 'Harm', 'Base_0_10', 'Base_20_85', 'Base_110_200']
const parents = getParentNodes(node, [])
parents.pop()
parents.unshift(node.data)
parents.reverse()
let active = parents[0].scriptTypeCode
let childActive = findTargetCodes(parents, code)[0] || ''
// 获取当前节点的直接父节点
if (activeName.value != active || childActiveName.value != childActive || activeIndex.value != data.index) {
activeName.value = active
childActiveName.value = childActive
emit('setTab', {
activeName: active,
childActiveName: childActive,
activeIndex:data.index
})
}
}
}
// 返回父级
const getParentNodes = (node, parents) => {
if (node.parent) {
// 将父节点添加到数组中
parents.push(node.parent.data)
// 递归获取更高层级的父节点
getParentNodes(node.parent, parents)
}
return parents
}
// 判断childActiveName值
function findTargetCodes(data: any[], targetCodes: string[]) {
let result: string[] = []
data.forEach(item => {
if (item.scriptTypeCode != null) {
if (targetCodes.includes(item.scriptTypeCode)) {
result.push(item.scriptTypeCode)
}
}
})
return result
// for (let item of data) {
// // 判断当前项的 scriptTypeCode 是否包含目标值
// if (item.scriptTypeCode !=null && targetCodes.includes(item.scriptTypeCode)) {
// result.push(item.scriptTypeCode)
// return result
// }
// // 如果存在 children递归检查
// if (item.children && item.children.length > 0) {
// result = result.concat(findTargetCodes(item.children, targetCodes))
// }
// }
// return result
}
function handleCheckChange(data,isChecked) {
if (isChecked)
{
// 如果没有子节点,允许勾选
const checked = [data.id]; // id为tree的node-key属性
treeRef.value?.setCheckedKeys(checked);
emit('setTab', {
activeName: data.scriptType,
childActiveName: data.scriptTypeCode,
activeIndex:data.index
})
}
}
// 递归查找第一个节点的最后一层子节点
function findFirstLeafNode(node: any): any {
if (node.children && node.children.length > 0) {
return findFirstLeafNode(node.children[0]);
}
return node;
}
const checkTree = () => {
console.log('checkTree11')
console.log('checkTree22',props.treeData.length)
console.log('checkTree33',treeRef.value)
if (props.treeData.length > 0 && treeRef.value) {
console.log('checkTree44')
const firstNode = props.treeData[0];
const firstLeafNode = findFirstLeafNode(firstNode);
const firstLeafNodeId = firstLeafNode.id;
treeRef.value.setCheckedKeys([firstLeafNodeId]);
}
}
// 确保在组件挂载后也执行一次
onMounted(() => {
console.log('onMounted',props.treeData);
nextTick(() => {
checkTree()
});
});
// // 对外映射
defineExpose({ checkTree })
</script>
<style lang="scss" scoped>
.custom-tree-node {
max-width: 230px;
overflow-x: hidden !important;
white-space: nowrap !important;
text-overflow: ellipsis !important;
}
</style>

View File

@@ -1,185 +1,184 @@
<template>
<div>
<el-table
:data="tableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:height="`calc(100vh - ${props.shrink ? '535px' : '480px'})`"
:style="{ overflow: 'hidden' }"
row-key="id"
:expand-row-keys="[props.activeName]"
>
<el-table-column prop="name" label="指标" show-overflow-tooltip />
<el-table-column align="center" label="参与误差比较" width="110px">
<template #default="{ row }">
<el-switch
v-model="row.errorFlag"
v-if="row.show"
:active-value="1"
:inactive-value="0"
:disabled="row.disabled || disabled"
>
<template #active-action>
<span></span>
</template>
<template #inactive-action>
<span>×</span>
</template>
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" label="是否启用" width="85px">
<template #default="{ row }">
<el-switch
v-model="row.enable"
v-if="row.show"
:active-value="1"
:inactive-value="0"
:disabled="row.disabled || disabled"
>
<template #active-action>
<span></span>
</template>
<template #inactive-action>
<span>×</span>
</template>
</el-switch>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { Dict } from '@/api/system/dictionary/interface'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { checkDataList } from '@/api/device/testScript'
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: Object,
required: true
},
disabled: {
type: Boolean,
default: true
},
options: {
type: Array,
required: true
},
shrink: {
type: Boolean
}
})
const tableData = ref<any[]>([])
const info = async () => {
let checkData: any = []
let title = props.options.filter((i: any) => i.value == props.activeName)[0]
await checkDataList({
scriptId: props.formContent.id,
scriptType: props.activeName
}).then((res: any) => {
checkData = res.data
})
let { data } = await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
})
data[0].children.forEach((item: any, i: number) => {
tableData.value.push({
id: item.id,
name: item.name,
show: false,
children: []
})
item.children.forEach((k: any) => {
let childrenList: any = []
checkData.forEach((j: any) => {
if (j.valueType == k.id) {
childrenList.push(j)
}
})
if (childrenList.length > 0) {
tableData.value[i].children.push({
id: k.id,
pid: item.id,
name: k.name,
pname: item.name,
dataType:
item.name == '谐波有功功率'
? 'avg'
: item.name == '闪变'
? 'avg'
: item.name == '暂态'
? 'avg'
: 'real',
show: true,
errorFlag: childrenList[0].errorFlag,
enable: childrenList[0].enable
})
} else {
tableData.value[i].children.push({
id: k.id,
pid: item.id,
name: k.name,
disabled: false,
pname: item.name,
dataType: item.name =='谐波有功功率'
? 'avg'
: item.name == '闪变'
? 'avg'
: item.name == '暂态'
? 'avg'
: 'real',
show: true,
errorFlag: 0,
enable: 0
})
}
})
// 默认够选通讯脚本
if (item.name == title.label.replace(/准确度|检测/g, '')) {
if (item.name == '暂态') {
tableData.value[i].children.forEach((k: any) => {
k.disabled = true
k.enable = 1
k.errorFlag = 1
})
} else {
tableData.value[i].children[0].disabled = true
tableData.value[i].children[0].enable = 1
tableData.value[i].children[0].errorFlag = 1
}
}
})
//console.log('🚀 ~ item.children.forEach ~ tableData.value:', tableData.value)
}
const getData = () => {
return tableData.value
}
onMounted(() => {
info()
// tableData.value = data.data[0].children || []
})
// 对外映射
defineExpose({ getData })
</script>
<style lang="scss" scoped></style>
<template>
<div>
<el-table
:data="tableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:height="`calc(100vh - ${props.shrink ? '535px' : '480px'})`"
:style="{ overflow: 'hidden' }"
row-key="id"
:expand-row-keys="[props.activeName]"
>
<el-table-column prop="name" label="指标" show-overflow-tooltip />
<el-table-column align="center" label="参与误差比较" width="110px">
<template #default="{ row }">
<el-switch
v-model="row.errorFlag"
v-if="row.show"
:active-value="1"
:inactive-value="0"
:disabled="row.disabled || disabled"
>
<template #active-action>
<span></span>
</template>
<template #inactive-action>
<span>×</span>
</template>
</el-switch>
</template>
</el-table-column>
<el-table-column align="center" label="是否启用" width="85px">
<template #default="{ row }">
<el-switch
v-model="row.enable"
v-if="row.show"
:active-value="1"
:inactive-value="0"
:disabled="row.disabled || disabled"
>
<template #active-action>
<span></span>
</template>
<template #inactive-action>
<span>×</span>
</template>
</el-switch>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { Dict } from '@/api/system/dictionary/interface'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { checkDataList } from '@/api/device/testScript'
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: Object,
required: true
},
disabled: {
type: Boolean,
default: true
},
options: {
type: Array,
required: true
},
shrink: {
type: Boolean
}
})
const tableData = ref<any[]>([])
const info = async () => {
let checkData: any = []
let title = props.options.filter((i: any) => i.value == props.activeName)[0]
await checkDataList({
scriptId: props.formContent.id,
scriptType: props.activeName
}).then((res: any) => {
checkData = res.data
})
let { data } = await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
})
data[0].children.forEach((item: any, i: number) => {
tableData.value.push({
id: item.id,
name: item.name,
show: false,
children: []
})
item.children.forEach((k: any) => {
let childrenList: any = []
checkData.forEach((j: any) => {
if (j.valueType == k.id) {
childrenList.push(j)
}
})
if (childrenList.length > 0) {
tableData.value[i].children.push({
id: k.id,
pid: item.id,
name: k.name,
pname: item.name,
dataType:
item.name == '谐波有功功率'
? 'avg'
: item.name == '闪变'
? 'avg'
: item.name == '暂态'
? 'avg'
: 'real',
show: true,
errorFlag: childrenList[0].errorFlag,
enable: childrenList[0].enable
})
} else {
tableData.value[i].children.push({
id: k.id,
pid: item.id,
name: k.name,
disabled: false,
pname: item.name,
dataType: item.name =='谐波有功功率'
? 'avg'
: item.name == '闪变'
? 'avg'
: item.name == '暂态'
? 'avg'
: 'real',
show: true,
errorFlag: 0,
enable: 0
})
}
})
// 默认够选通讯脚本
if (item.name == title.label.replace(/准确度|检测/g, '')) {
if (item.name == '暂态') {
tableData.value[i].children.forEach((k: any) => {
k.disabled = true
k.enable = 1
k.errorFlag = 1
})
} else {
tableData.value[i].children[0].disabled = true
tableData.value[i].children[0].enable = 1
tableData.value[i].children[0].errorFlag = 1
}
}
})
}
const getData = () => {
return tableData.value
}
onMounted(() => {
info()
// tableData.value = data.data[0].children || []
})
// 对外映射
defineExpose({ getData })
</script>
<style lang="scss" scoped></style>

View File

@@ -1,351 +1,350 @@
<template>
<div class="table-container">
<div class="recalculation">
<el-button type="primary" :icon="Refresh" @click="recalculation">一键重算</el-button>
</div>
<el-table
:data="tableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="550px"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="pname" label="参考设定值类型" />
<el-table-column prop="name" label="参考设定值子类型" width="250">
<template #default="{ row }">{{ row.harmNum ? `(${row.harmNum}次)` : '' }} {{ row.name }}</template>
</el-table-column>
<!-- <el-table-column prop="dataType" label="值类型">
<template #default="{ row }">
<el-select v-model="row.dataType" v-if="!row.show">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span v-else>
{{ typeList.find(item => item.value == row.dataType)?.label || row.dataType }}
</span>
</template>
</el-table-column> -->
<el-table-column prop="phase" label="相别" />
<el-table-column prop="value" label="参考设定值">
<template #default="{ row }">
<span v-if="row.show">{{ parseFloat((row.value - 0).toFixed(4)) }}{{ setUnit(row) || '' }}</span>
<el-input type="number" v-else v-model="row.value" placeholder="请输入值" />
</template>
</el-table-column>
<el-table-column prop="value" label="参与误差比较">
<template #default="{ row }">
{{ row.errorFlag == 0 ? '否' : '是' }}
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" link :icon="EditPen" @click="row.show = !row.show" v-if="row.show">
编辑
</el-button>
<el-button type="primary" link :icon="Check" @click="row.show = !row.show" v-else>保存</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="dialogTitle" v-model="showForm" @close="close" width="500">
<el-form ref="form" :model="form" label-width="auto">
<el-form-item label="参考设定值类型" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="参考设定值子类型" prop="standardName">
<el-input v-model="form.standardName" />
</el-form-item>
<el-form-item label="参考设定值" prop="standardTime">
<el-input v-model="form.standardTime" />
</el-form-item>
</el-form>
<template #footer>
<div>
<el-button @click="close()"> </el-button>
<el-button type="primary" @click="save"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { Refresh, EditPen, Check, Share } from '@element-plus/icons-vue'
import { reactive, ref } from 'vue'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { dialogBig } from '@/utils/elementBind'
import { checkDataList, scriptDtlsCheckDataList } from '@/api/device/testScript/index'
const showForm = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('')
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: [Object, Array],
required: true
},
form: {
type: [Object, Array],
required: true
},
valueCode: {
type: String,
required: true
}
})
const emit = defineEmits(['recalculation'])
const tableData: any = ref([])
// 表格配置项
const typeList = [
{
label: '实时',
value: 'real'
},
{
label: 'CP95值',
value: 'cp95'
},
{
label: '平均值',
value: 'avg'
},
{
label: '最小值',
value: 'min'
},
{
label: '最大值',
value: 'max'
}
]
const form = ref({
name: 220,
standardName: 0,
standardTime: 0
})
// 打开弹窗,可能是新增,也可能是编辑
const open = async (row: any, copyRowList: any) => {
let treeData: any = []
await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
}).then((res: any) => {
treeData = res.data[0].children
})
let checkDataList: any = []
await row.forEach((item: any) => {
item.children.forEach((k: any) => {
if (k.enable != 0 || k.errorFlag != 0) {
checkDataList.push({
pid: k.pid,
valueType: k.id,
dataType: k.dataType,
enable: k.enable,
errorFlag: k.errorFlag
})
}
})
})
let form = handleHarmData(JSON.parse(JSON.stringify(props.form)))
let retryCompute = isEqual(form, copyRowList)
await scriptDtlsCheckDataList({
...form,
scriptId: props.formContent?.id,
scriptType: props.activeName,
checkDataList: checkDataList,
retryCompute: retryCompute
}).then((res: any) => {
res.data.forEach((item: any) => {
let pList = treeData.filter((i: any) => i.id == item.pid)[0]
item.pname = pList.name
item.name = pList.children.filter((i: any) => i.id == item.valueType)[0].name
item.show = true
})
tableData.value = res.data
})
}
// 重算
const recalculation = () => {
emit('recalculation')
}
// 处理多余数据
const handleHarmData = (row: any) => {
row.channelList.forEach((channel: any) => {
// 筛选出 famp 和 fphase 不同时为 0 的对象
channel.harmList = channel.harmList.filter((item: any) => item.famp != 0 || item.fphase != 0)
channel.inharmList = channel.inharmList.filter(
(item: any) => item.inharm !== '' || item.famp !== 0 || item.fphase !== 0
)
})
return row
}
// 判断数据是否变化
const isEqual = (obj1: any, obj2: any) => {
// 如果两个对象是同一个引用,直接返回 true
if (obj1 == obj2) return true
// 如果其中一个是 null 或者不是对象,返回 false
if (obj1 === null || typeof obj1 !== 'object' || obj2 === null || typeof obj2 !== 'object') {
return false
}
// 获取两个对象的键
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
// 如果键的数量不同,返回 false
if (keys1.length !== keys2.length) return false
// 遍历所有键,递归比较值
for (const key of keys1) {
if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
const unit = [
{
label: '频率',
unit: 'Hz'
},
{
label: '相电压有效值',
unit: 'V'
},
{
label: '电压偏差',
unit: '%'
},
{
label: '电压相角',
unit: '°'
},
{
label: '基波电压有效值',
unit: ''
},
{
label: '电流有效值',
unit: 'A'
},
{
label: '电流相角',
unit: '°'
},
{
label: '基波电流有效值',
unit: ''
},
{
label: '谐波电压',
unit: '%'
},
{
label: '谐波电流',
unit: '%'
},
{
label: '谐波电流幅值',
unit: 'A'
},
{
label: '谐波有功功率',
unit: 'W'
},
{
label: '间谐波电压',
unit: '%'
},
{
label: '间谐波电流',
unit: '%'
},
{
label: '电压幅值',
unit: '%'
},
{
label: '持续时间',
unit: '周波'
},
{
label: '三相电压不平衡度',
unit: '%'
},
{
label: '三相电流不平衡度',
unit: '%'
},
{
label: '闪变',
unit: ''
},
{
label: '电流',
unit: props.valueCode == 'Absolute' ? 'A' : '%'
},
]
// 参考设定值添加单位
const setUnit = (row: any) => {
console.log('🚀 ~ setUnit ~ row:', row)
let text = ''
if (row.pname == '暂态') {
row.name == '电压幅值' ? (text = '%') : ''
row.name == '持续时间' ? (text = '周波') : ''
} else if (row.pname == '电压') {
let o = props.valueCode == 'Absolute' ? 'V' : '%'
row.name == '电压有效值' ? (text = o) : ''
row.name == '电压偏差' ? (text = '%') : ''
row.name == '电压相角' ? (text = '°') : ''
}else if (row.pname == '电流') {
let o = props.valueCode == 'Absolute' ? 'A' : '%'
row.name == '电流有效值' ? (text = o) : ''
row.name == '电流相角' ? (text = '°') : ''
} else {
text = unit.filter(item => item.label == row.pname)[0]?.unit
}
return text || ''
}
const save = () => {
dialogVisible.value = false
}
const getTableData = () => {
return tableData.value
}
// 关闭弹窗
const close = () => {
dialogVisible.value = false
}
onMounted(() => {})
// 对外映射
defineExpose({ open, getTableData })
</script>
<style scoped>
.recalculation {
width: 100%;
display: flex;
justify-content: end;
margin-bottom: 10px;
}
</style>
<template>
<div class="table-container">
<div class="recalculation">
<el-button type="primary" :icon="Refresh" @click="recalculation">一键重算</el-button>
</div>
<el-table
:data="tableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="550px"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="pname" label="参考设定值类型" />
<el-table-column prop="name" label="参考设定值子类型" width="250">
<template #default="{ row }">{{ row.harmNum ? `(${row.harmNum}次)` : '' }} {{ row.name }}</template>
</el-table-column>
<!-- <el-table-column prop="dataType" label="值类型">
<template #default="{ row }">
<el-select v-model="row.dataType" v-if="!row.show">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span v-else>
{{ typeList.find(item => item.value == row.dataType)?.label || row.dataType }}
</span>
</template>
</el-table-column> -->
<el-table-column prop="phase" label="相别" />
<el-table-column prop="value" label="参考设定值">
<template #default="{ row }">
<span v-if="row.show">{{ parseFloat((row.value - 0).toFixed(4)) }}{{ setUnit(row) || '' }}</span>
<el-input type="number" v-else v-model="row.value" placeholder="请输入值" />
</template>
</el-table-column>
<el-table-column prop="value" label="参与误差比较">
<template #default="{ row }">
{{ row.errorFlag == 0 ? '否' : '是' }}
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" link :icon="EditPen" @click="row.show = !row.show" v-if="row.show">
编辑
</el-button>
<el-button type="primary" link :icon="Check" @click="row.show = !row.show" v-else>保存</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="dialogTitle" v-model="showForm" @close="close" width="500">
<el-form ref="form" :model="form" label-width="auto">
<el-form-item label="参考设定值类型" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="参考设定值子类型" prop="standardName">
<el-input v-model="form.standardName" />
</el-form-item>
<el-form-item label="参考设定值" prop="standardTime">
<el-input v-model="form.standardTime" />
</el-form-item>
</el-form>
<template #footer>
<div>
<el-button @click="close()"> </el-button>
<el-button type="primary" @click="save"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { Refresh, EditPen, Check, Share } from '@element-plus/icons-vue'
import { reactive, ref } from 'vue'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { dialogBig } from '@/utils/elementBind'
import { checkDataList, scriptDtlsCheckDataList } from '@/api/device/testScript/index'
const showForm = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('')
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: [Object, Array],
required: true
},
form: {
type: [Object, Array],
required: true
},
valueCode: {
type: String,
required: true
}
})
const emit = defineEmits(['recalculation'])
const tableData: any = ref([])
// 表格配置项
const typeList = [
{
label: '实时',
value: 'real'
},
{
label: 'CP95值',
value: 'cp95'
},
{
label: '平均值',
value: 'avg'
},
{
label: '最小值',
value: 'min'
},
{
label: '最大值',
value: 'max'
}
]
const form = ref({
name: 220,
standardName: 0,
standardTime: 0
})
// 打开弹窗,可能是新增,也可能是编辑
const open = async (row: any, copyRowList: any) => {
let treeData: any = []
await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
}).then((res: any) => {
treeData = res.data[0].children
})
let checkDataList: any = []
await row.forEach((item: any) => {
item.children.forEach((k: any) => {
if (k.enable != 0 || k.errorFlag != 0) {
checkDataList.push({
pid: k.pid,
valueType: k.id,
dataType: k.dataType,
enable: k.enable,
errorFlag: k.errorFlag
})
}
})
})
let form = handleHarmData(JSON.parse(JSON.stringify(props.form)))
let retryCompute = isEqual(form, copyRowList)
await scriptDtlsCheckDataList({
...form,
scriptId: props.formContent?.id,
scriptType: props.activeName,
checkDataList: checkDataList,
retryCompute: retryCompute
}).then((res: any) => {
res.data.forEach((item: any) => {
let pList = treeData.filter((i: any) => i.id == item.pid)[0]
item.pname = pList.name
item.name = pList.children.filter((i: any) => i.id == item.valueType)[0].name
item.show = true
})
tableData.value = res.data
})
}
// 重算
const recalculation = () => {
emit('recalculation')
}
// 处理多余数据
const handleHarmData = (row: any) => {
row.channelList.forEach((channel: any) => {
// 筛选出 famp 和 fphase 不同时为 0 的对象
channel.harmList = channel.harmList.filter((item: any) => item.famp != 0 || item.fphase != 0)
channel.inharmList = channel.inharmList.filter(
(item: any) => item.inharm !== '' || item.famp !== 0 || item.fphase !== 0
)
})
return row
}
// 判断数据是否变化
const isEqual = (obj1: any, obj2: any) => {
// 如果两个对象是同一个引用,直接返回 true
if (obj1 == obj2) return true
// 如果其中一个是 null 或者不是对象,返回 false
if (obj1 === null || typeof obj1 !== 'object' || obj2 === null || typeof obj2 !== 'object') {
return false
}
// 获取两个对象的键
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
// 如果键的数量不同,返回 false
if (keys1.length !== keys2.length) return false
// 遍历所有键,递归比较值
for (const key of keys1) {
if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
const unit = [
{
label: '频率',
unit: 'Hz'
},
{
label: '相电压有效值',
unit: 'V'
},
{
label: '电压偏差',
unit: '%'
},
{
label: '电压相角',
unit: '°'
},
{
label: '基波电压有效值',
unit: ''
},
{
label: '电流有效值',
unit: 'A'
},
{
label: '电流相角',
unit: '°'
},
{
label: '基波电流有效值',
unit: ''
},
{
label: '谐波电压',
unit: '%'
},
{
label: '谐波电流',
unit: '%'
},
{
label: '谐波电流幅值',
unit: 'A'
},
{
label: '谐波有功功率',
unit: 'W'
},
{
label: '间谐波电压',
unit: '%'
},
{
label: '间谐波电流',
unit: '%'
},
{
label: '电压幅值',
unit: '%'
},
{
label: '持续时间',
unit: '周波'
},
{
label: '三相电压不平衡度',
unit: '%'
},
{
label: '三相电流不平衡度',
unit: '%'
},
{
label: '闪变',
unit: ''
},
{
label: '电流',
unit: props.valueCode == 'Absolute' ? 'A' : '%'
},
]
// 参考设定值添加单位
const setUnit = (row: any) => {
let text = ''
if (row.pname == '暂态') {
row.name == '电压幅值' ? (text = '%') : ''
row.name == '持续时间' ? (text = '周波') : ''
} else if (row.pname == '电压') {
let o = props.valueCode == 'Absolute' ? 'V' : '%'
row.name == '相电压有效值' ? (text = o) : ''
row.name == '电压偏差' ? (text = '%') : ''
row.name == '电压相角' ? (text = '°') : ''
}else if (row.pname == '电流') {
let o = props.valueCode == 'Absolute' ? 'A' : '%'
row.name == '电流有效值' ? (text = o) : ''
row.name == '电流相角' ? (text = '°') : ''
} else {
text = unit.filter(item => item.label == row.pname)[0]?.unit
}
return text || ''
}
const save = () => {
dialogVisible.value = false
}
const getTableData = () => {
return tableData.value
}
// 关闭弹窗
const close = () => {
dialogVisible.value = false
}
onMounted(() => {})
// 对外映射
defineExpose({ open, getTableData })
</script>
<style scoped>
.recalculation {
width: 100%;
display: flex;
justify-content: end;
margin-bottom: 10px;
}
</style>

View File

@@ -1,378 +1,377 @@
<template>
<div class="tabs-container">
<el-tabs type="border-card" class="right-tabs" style="height: 100%">
<el-tab-pane label="电压通道">
<el-form :inline="true" :model="formInline" :disabled="!props.childForm[0].harmFlag">
<el-form-item label="次数">
<el-select
v-model="formInline.harm"
multiple
collapse-tags
collapse-tags-tooltip
style="width: 160px"
filterable
clearable
>
<el-option label="全部" value="0"/>
<el-option v-for="item in 49" :key="item" :label="item + 1" :value="item + 1"/>
</el-select>
</el-form-item>
<el-form-item label="含有率">
<el-input
v-model="formInline.famp"
type="number"
placeholder="含有率"
style="width: 80px"
onkeypress="return (/[\d.]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('famp',0)"
clearable
/>
</el-form-item>
<el-form-item label="相角">
<el-input
v-model="formInline.fphase"
type="number"
placeholder="相角"
style="width: 80px"
onkeypress="return (/[\d-]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('fphase',0)"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Check" @click="onSubmit" size="small">确定</el-button>
<el-button type="primary" :icon="Delete" @click="empty(0)" size="small">清空表格</el-button>
</el-form-item>
</el-form>
<!-- 电压通道内容 -->
<div class="table-container">
<el-table :data="form[0].harmList" border stripe size="small">
<el-table-column prop="harm" align="center" label="次数" width="60"/>
<el-table-column prop="famp" align="center" label="谐波含有率">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.famp"/>
<span v-else>{{ row.famp }}%</span>
</template>
</el-table-column>
<el-table-column prop="fphase" label="谐波相角" align="center">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.fphase"/>
<span v-else>{{ row.fphase }}°</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{ row, $index }">
<el-button
type="primary"
link
:icon="EditPen"
v-if="!row.show"
@click="row.show = true"
>
编辑
</el-button>
<el-button type="primary" link :icon="Check" v-else @click="row.show = false">
保存
</el-button>
<el-button type="primary" link :icon="Delete" @click="HarmFlagDelete(0, $index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" style="height: 100%">
<el-tab-pane label="电流通道">
<el-form :inline="true" :model="formInline1" :disabled="!props.childForm[1].harmFlag">
<el-form-item label="次数">
<el-select
v-model="formInline1.harm"
multiple
collapse-tags
collapse-tags-tooltip
style="width: 160px"
filterable
clearable
>
<el-option label="全部" value="0"/>
<el-option v-for="item in 49" :key="item" :label="item + 1" :value="item + 1"/>
</el-select>
</el-form-item>
<el-form-item label="含有率">
<el-input
v-model="formInline1.famp"
type="number"
placeholder="含有率"
style="width: 80px"
onkeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('famp',1)"
clearable
/>
</el-form-item>
<el-form-item label="相角">
<el-input
v-model="formInline1.fphase"
type="number"
placeholder="相角"
style="width: 80px"
onkeypress="return (/[\d-]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('fphase',1)"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Check" @click="onSubmit1" size="small">确定</el-button>
<el-button type="primary" :icon="Delete" @click="empty(1)" size="small">清空表格</el-button>
</el-form-item>
</el-form>
<!-- 电流通道内容 -->
<div class="table-container">
<el-table :data="form[1].harmList" border stripe size="small">
<el-table-column prop="harm" align="center" label="次数" width="60"/>
<el-table-column prop="famp" align="center" label="谐波含有率">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.famp"/>
<span v-else>{{ row.famp }}%</span>
</template>
</el-table-column>
<el-table-column prop="fphase" label="谐波相角" align="center">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.fphase"/>
<span v-else>{{ row.fphase }}°</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{ row, $index }">
<el-button
type="primary"
link
:icon="EditPen"
v-if="!row.show"
@click="row.show = true"
>
编辑
</el-button>
<el-button type="primary" link :icon="Check" v-else @click="row.show = false">
保存
</el-button>
<el-button type="primary" link :icon="Delete" @click="HarmFlagDelete(1, $index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import {Check, Delete, EditPen} from '@element-plus/icons-vue'
import {ref} from 'vue'
const props = defineProps({
childForm: {
type: Array as any,
required: true
}
})
const form: any = computed({
get() {
return props.childForm
},
set(value) {
}
})
const formInline = ref({
harm: [],
famp: '',
fphase: ''
})
const formInline1 = ref({
harm: [],
famp: '',
fphase: ''
})
// 定义表格数据项的类型
interface TableItem {
date: string
harmonicRate?: string
harmonicPhase?: string
name?: string
}
const empty = (index: number) => {
props.childForm[index].harmList = []
}
const onSubmit = () => {
console.log('🚀 ~ onSubmit ~ props.childForm[0]:', props.childForm[0].harmList)
if (formInline.value.harm.length == 0 || formInline.value.famp == '' || formInline.value.fphase == '') {
ElMessage.warning('请填写值!')
return
}
if (formInline.value.harm.includes('0')) {
props.childForm[0].harmList = []
for (let i = 2; i < 51; i++) {
props.childForm[0].harmList.push({
harm: i, //间谐波次数
famp: formInline.value.famp, //间谐波含有率
fphase: formInline.value.fphase // 间谐波相角
})
}
} else {
formInline.value.harm.forEach((item: any) => {
props.childForm[0].harmList.push({
harm: item, //间谐波次数
famp: formInline.value.famp, //间谐波含有率
fphase: formInline.value.fphase // 间谐波相角
})
})
const seen = new Set()
const uniqueData = []
// 反向遍历数组
for (let i = props.childForm[0].harmList.length - 1; i >= 0; i--) {
const item = props.childForm[0].harmList[i]
// 如果 harm 还未出现过,则添加到结果数组
if (!seen.has(item.harm)) {
seen.add(item.harm)
uniqueData.unshift(item) // 添加到结果数组的开头
}
}
props.childForm[0].harmList = uniqueData.sort((a, b) => a.harm - b.harm)
}
}
const onSubmit1 = () => {
if (formInline1.value.harm.length == 0 || formInline1.value.famp == '' || formInline1.value.fphase == '') {
ElMessage.warning('请填写值!')
return
}
if (formInline1.value.harm.includes('0')) {
props.childForm[1].harmList = []
for (let i = 2; i < 51; i++) {
props.childForm[1].harmList.push({
harm: i, //间谐波次数
famp: formInline1.value.famp, //间谐波含有率
fphase: formInline1.value.fphase // 间谐波相角
})
}
} else {
formInline1.value.harm.forEach((item: any) => {
props.childForm[1].harmList.push({
harm: item, //间谐波次数
famp: formInline1.value.famp, //间谐波含有率
fphase: formInline1.value.fphase // 间谐波相角
})
})
const seen = new Set()
const uniqueData = []
// 反向遍历数组
for (let i = props.childForm[1].harmList.length - 1; i >= 0; i--) {
const item = props.childForm[1].harmList[i]
// 如果 harm 还未出现过,则添加到结果数组
if (!seen.has(item.harm)) {
seen.add(item.harm)
uniqueData.unshift(item) // 添加到结果数组的开头
}
}
props.childForm[1].harmList = uniqueData.sort((a, b) => a.harm - b.harm)
}
}
// 删除
const HarmFlagDelete = (index: number, number: number) => {
props.childForm[index].harmList.splice(number, 1)
}
const validateInput = (type: string, index: number) => {
if (type == 'famp') {
if (Number(formInline.value.famp) < 0 || Number(formInline1.value.famp) < 0) {
ElMessage.warning("含有率不能低于0")
if (index == 0) {
formInline.value.famp = '0'
}
if (index == 1) {
formInline1.value.famp = '0'
}
}
if (Number(formInline.value.famp) > 200 || Number(formInline1.value.famp) > 200) {
ElMessage.warning("含有率不能高于200")
if (index == 0) {
formInline.value.famp = '200'
}
if (index == 1) {
formInline1.value.famp = '200'
}
}
}
if (type == 'fphase') {
if (Number(formInline.value.fphase) < -360 || Number(formInline1.value.fphase) < -360) {
ElMessage.warning("相角不能低于-360°")
if (index == 0) {
formInline.value.fphase = '-360';
}
if (index == 1) {
formInline1.value.fphase = '-360';
}
} else if (Number(formInline.value.fphase) > 360 || Number(formInline1.value.fphase) > 360) {
ElMessage.warning("相角不能高于360°")
if (index == 0) {
formInline.value.fphase = '360';
}
if (index == 1) {
formInline1.value.fphase = '360';
}
}
}
}
</script>
<style lang="scss" scoped>
.tabs-container {
display: flex;
justify-content: space-between; /* 使两个 el-tabs 之间有间距 */
height: 100%;
}
.right-tabs {
flex: 1; /* 使两个 el-tabs 占据相同的空间 */
margin-right: 10px; /* 可选:添加右侧间距 */
}
.el-tabs {
flex: 1; /* 使两个 el-tabs 占据相同的空间 */
}
.table-container {
display: flex;
justify-content: space-between; /* 使两个表格之间有间距 */
width: 100%;
}
.half-width-table {
flex: 1; /* 使两个表格占据相同的空间 */
margin-right: 10px; /* 可选:添加表格之间的间距 */
}
.half-width-table:last-child {
margin-right: 0; /* 最后一个表格不需要右侧间距 */
}
.input-label-container {
display: flex;
align-items: center; /* 垂直居中对齐 */
}
.input-label-container label {
margin-left: 5px; /* 添加标签与输入框之间的间距 */
}
// 全局css 加上以下代码,可以隐藏上下箭头
// 取消input的上下箭头
</style>
<template>
<div class="tabs-container">
<el-tabs type="border-card" class="right-tabs" style="height: 100%">
<el-tab-pane label="电压通道">
<el-form :inline="true" :model="formInline" :disabled="!props.childForm[0].harmFlag">
<el-form-item label="次数">
<el-select
v-model="formInline.harm"
multiple
collapse-tags
collapse-tags-tooltip
style="width: 160px"
filterable
clearable
>
<el-option label="全部" value="0"/>
<el-option v-for="item in 49" :key="item" :label="item + 1" :value="item + 1"/>
</el-select>
</el-form-item>
<el-form-item label="含有率">
<el-input
v-model="formInline.famp"
type="number"
placeholder="含有率"
style="width: 80px"
onkeypress="return (/[\d.]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('famp',0)"
clearable
/>
</el-form-item>
<el-form-item label="相角">
<el-input
v-model="formInline.fphase"
type="number"
placeholder="相角"
style="width: 80px"
onkeypress="return (/[\d-]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('fphase',0)"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Check" @click="onSubmit" size="small">确定</el-button>
<el-button type="primary" :icon="Delete" @click="empty(0)" size="small">清空表格</el-button>
</el-form-item>
</el-form>
<!-- 电压通道内容 -->
<div class="table-container">
<el-table :data="form[0].harmList" border stripe size="small">
<el-table-column prop="harm" align="center" label="次数" width="60"/>
<el-table-column prop="famp" align="center" label="谐波含有率">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.famp"/>
<span v-else>{{ row.famp }}%</span>
</template>
</el-table-column>
<el-table-column prop="fphase" label="谐波相角" align="center">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.fphase"/>
<span v-else>{{ row.fphase }}°</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{ row, $index }">
<el-button
type="primary"
link
:icon="EditPen"
v-if="!row.show"
@click="row.show = true"
>
编辑
</el-button>
<el-button type="primary" link :icon="Check" v-else @click="row.show = false">
保存
</el-button>
<el-button type="primary" link :icon="Delete" @click="HarmFlagDelete(0, $index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" style="height: 100%">
<el-tab-pane label="电流通道">
<el-form :inline="true" :model="formInline1" :disabled="!props.childForm[1].harmFlag">
<el-form-item label="次数">
<el-select
v-model="formInline1.harm"
multiple
collapse-tags
collapse-tags-tooltip
style="width: 160px"
filterable
clearable
>
<el-option label="全部" value="0"/>
<el-option v-for="item in 49" :key="item" :label="item + 1" :value="item + 1"/>
</el-select>
</el-form-item>
<el-form-item label="含有率">
<el-input
v-model="formInline1.famp"
type="number"
placeholder="含有率"
style="width: 80px"
onkeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('famp',1)"
clearable
/>
</el-form-item>
<el-form-item label="相角">
<el-input
v-model="formInline1.fphase"
type="number"
placeholder="相角"
style="width: 80px"
onkeypress="return (/[\d-]/.test(String.fromCharCode(event.keyCode)))"
@input="validateInput('fphase',1)"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Check" @click="onSubmit1" size="small">确定</el-button>
<el-button type="primary" :icon="Delete" @click="empty(1)" size="small">清空表格</el-button>
</el-form-item>
</el-form>
<!-- 电流通道内容 -->
<div class="table-container">
<el-table :data="form[1].harmList" border stripe size="small">
<el-table-column prop="harm" align="center" label="次数" width="60"/>
<el-table-column prop="famp" align="center" label="谐波含有率">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.famp"/>
<span v-else>{{ row.famp }}%</span>
</template>
</el-table-column>
<el-table-column prop="fphase" label="谐波相角" align="center">
<template #default="{ row }">
<el-input type="number" v-if="row.show" v-model="row.fphase"/>
<span v-else>{{ row.fphase }}°</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{ row, $index }">
<el-button
type="primary"
link
:icon="EditPen"
v-if="!row.show"
@click="row.show = true"
>
编辑
</el-button>
<el-button type="primary" link :icon="Check" v-else @click="row.show = false">
保存
</el-button>
<el-button type="primary" link :icon="Delete" @click="HarmFlagDelete(1, $index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import {Check, Delete, EditPen} from '@element-plus/icons-vue'
import {ref} from 'vue'
const props = defineProps({
childForm: {
type: Array as any,
required: true
}
})
const form: any = computed({
get() {
return props.childForm
},
set(value) {
}
})
const formInline = ref({
harm: [],
famp: '',
fphase: ''
})
const formInline1 = ref({
harm: [],
famp: '',
fphase: ''
})
// 定义表格数据项的类型
interface TableItem {
date: string
harmonicRate?: string
harmonicPhase?: string
name?: string
}
const empty = (index: number) => {
props.childForm[index].harmList = []
}
const onSubmit = () => {
if (formInline.value.harm.length == 0 || formInline.value.famp == '' || formInline.value.fphase == '') {
ElMessage.warning('请填写值!')
return
}
if (formInline.value.harm.includes('0')) {
props.childForm[0].harmList = []
for (let i = 2; i < 51; i++) {
props.childForm[0].harmList.push({
harm: i, //间谐波次数
famp: formInline.value.famp, //间谐波含有率
fphase: formInline.value.fphase // 间谐波相角
})
}
} else {
formInline.value.harm.forEach((item: any) => {
props.childForm[0].harmList.push({
harm: item, //间谐波次数
famp: formInline.value.famp, //间谐波含有率
fphase: formInline.value.fphase // 间谐波相角
})
})
const seen = new Set()
const uniqueData = []
// 反向遍历数组
for (let i = props.childForm[0].harmList.length - 1; i >= 0; i--) {
const item = props.childForm[0].harmList[i]
// 如果 harm 还未出现过,则添加到结果数组
if (!seen.has(item.harm)) {
seen.add(item.harm)
uniqueData.unshift(item) // 添加到结果数组的开头
}
}
props.childForm[0].harmList = uniqueData.sort((a, b) => a.harm - b.harm)
}
}
const onSubmit1 = () => {
if (formInline1.value.harm.length == 0 || formInline1.value.famp == '' || formInline1.value.fphase == '') {
ElMessage.warning('请填写值!')
return
}
if (formInline1.value.harm.includes('0')) {
props.childForm[1].harmList = []
for (let i = 2; i < 51; i++) {
props.childForm[1].harmList.push({
harm: i, //间谐波次数
famp: formInline1.value.famp, //间谐波含有率
fphase: formInline1.value.fphase // 间谐波相角
})
}
} else {
formInline1.value.harm.forEach((item: any) => {
props.childForm[1].harmList.push({
harm: item, //间谐波次数
famp: formInline1.value.famp, //间谐波含有率
fphase: formInline1.value.fphase // 间谐波相角
})
})
const seen = new Set()
const uniqueData = []
// 反向遍历数组
for (let i = props.childForm[1].harmList.length - 1; i >= 0; i--) {
const item = props.childForm[1].harmList[i]
// 如果 harm 还未出现过,则添加到结果数组
if (!seen.has(item.harm)) {
seen.add(item.harm)
uniqueData.unshift(item) // 添加到结果数组的开头
}
}
props.childForm[1].harmList = uniqueData.sort((a, b) => a.harm - b.harm)
}
}
// 删除
const HarmFlagDelete = (index: number, number: number) => {
props.childForm[index].harmList.splice(number, 1)
}
const validateInput = (type: string, index: number) => {
if (type == 'famp') {
if (Number(formInline.value.famp) < 0 || Number(formInline1.value.famp) < 0) {
ElMessage.warning("含有率不能低于0")
if (index == 0) {
formInline.value.famp = '0'
}
if (index == 1) {
formInline1.value.famp = '0'
}
}
if (Number(formInline.value.famp) > 200 || Number(formInline1.value.famp) > 200) {
ElMessage.warning("含有率不能高于200")
if (index == 0) {
formInline.value.famp = '200'
}
if (index == 1) {
formInline1.value.famp = '200'
}
}
}
if (type == 'fphase') {
if (Number(formInline.value.fphase) < -360 || Number(formInline1.value.fphase) < -360) {
ElMessage.warning("相角不能低于-360°")
if (index == 0) {
formInline.value.fphase = '-360';
}
if (index == 1) {
formInline1.value.fphase = '-360';
}
} else if (Number(formInline.value.fphase) > 360 || Number(formInline1.value.fphase) > 360) {
ElMessage.warning("相角不能高于360°")
if (index == 0) {
formInline.value.fphase = '360';
}
if (index == 1) {
formInline1.value.fphase = '360';
}
}
}
}
</script>
<style lang="scss" scoped>
.tabs-container {
display: flex;
justify-content: space-between; /* 使两个 el-tabs 之间有间距 */
height: 100%;
}
.right-tabs {
flex: 1; /* 使两个 el-tabs 占据相同的空间 */
margin-right: 10px; /* 可选:添加右侧间距 */
}
.el-tabs {
flex: 1; /* 使两个 el-tabs 占据相同的空间 */
}
.table-container {
display: flex;
justify-content: space-between; /* 使两个表格之间有间距 */
width: 100%;
}
.half-width-table {
flex: 1; /* 使两个表格占据相同的空间 */
margin-right: 10px; /* 可选:添加表格之间的间距 */
}
.half-width-table:last-child {
margin-right: 0; /* 最后一个表格不需要右侧间距 */
}
.input-label-container {
display: flex;
align-items: center; /* 垂直居中对齐 */
}
.input-label-container label {
margin-left: 5px; /* 添加标签与输入框之间的间距 */
}
// 全局css 加上以下代码,可以隐藏上下箭头
// 取消input的上下箭头
</style>

View File

@@ -206,7 +206,6 @@ const empty = (index: number) => {
props.childForm[index].inharmList = []
}
const onSubmit = () => {
console.log('🚀 ~ onSubmit ~ props.childForm[0]:', props.childForm[0].inharmList)
if (formInline.value.inharm.length == 0 || formInline.value.famp == '' || formInline.value.fphase == '') {
ElMessage.warning('请填写值!')
return

View File

@@ -224,7 +224,6 @@ const open = async (title: string, row: any) => {
} else {
let list = JSON.parse(row)
formContent.value = list
console.log('🚀 ~ open ~ list:', formContent.value)
show.value = true
}
// 重置表单
@@ -243,7 +242,6 @@ const treeInfo = async (currentMode: string) => {
const result = await getDictTreeByCode(data)
const result1 = (await getDictTreeByCode({ ...data, code: 'Script_Error' })).data[0].children
const allOptions = await convertToOptions(result.data as Dict.ResDictTree[])
//console.log('🚀 ~ treeInfo ~ result1:', allOptions[0]?.children)
const setallTree = await setTree(allOptions[0]?.children, result1)
secondLevelOptions.push(...(setallTree || []))
modeId.value = dictStore.getDictData('Pattern').find(item => item.name === currentMode)?.id

View File

@@ -1,106 +1,106 @@
<template>
<el-tree
node-key="id"
default-expand-all
:data="props.treeData"
:props="defaultProps"
style="width: 100%"
:expand-on-click-node="false"
@node-click="handleNodeClick"
>
<template #default="{ node, data }">
<el-tooltip effect="dark" :content="data.sourceDesc || data.scriptTypeName" placement="top" :hide-after="0">
<div class="custom-tree-node">
{{ data.scriptTypeName || data.sourceDesc }}
</div>
</el-tooltip>
</template>
</el-tree>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { CheckData } from '@/api/check/interface'
const props = defineProps({
treeData: {
type: Array,
required: true
}
})
const emit = defineEmits(['setTab'])
const dataTree = ref<CheckData.TreeItem[]>([])
const defaultProps = {
children: 'children',
label: 'scriptTypeName',
pid: 'pid'
}
const activeName = ref('')
const childActiveName = ref('')
const handleNodeClick = (data, node) => {
console.log('handleNodeClick', data, node)
let code = ['Base', 'VOL', 'Freq', 'Harm', 'Base_0_10', 'Base_20_85', 'Base_110_200']
const parents = getParentNodes(node, [])
parents.pop()
parents.unshift(node.data)
parents.reverse()
let active = parents[0].scriptTypeCode
let childActive = findTargetCodes(parents, code)[0] || ''
// 获取当前节点的直接父节点
if (activeName.value != active || childActiveName.value != childActive) {
activeName.value = active
childActiveName.value = childActive
emit('setTab', {
activeName: active,
childActiveName: childActive
})
}
}
// 返回父级
const getParentNodes = (node, parents) => {
if (node.parent) {
// 将父节点添加到数组中
parents.push(node.parent.data)
// 递归获取更高层级的父节点
getParentNodes(node.parent, parents)
}
return parents
}
// 判断childActiveName值
function findTargetCodes(data: any[], targetCodes: string[]) {
let result: string[] = []
data.forEach(item => {
if (item.scriptTypeCode != null) {
if (targetCodes.includes(item.scriptTypeCode)) {
result.push(item.scriptTypeCode)
}
}
})
return result
// for (let item of data) {
// // 判断当前项的 scriptTypeCode 是否包含目标值
// if (item.scriptTypeCode !=null && targetCodes.includes(item.scriptTypeCode)) {
// console.log("🚀 ~ findTargetCodes ~ targetCodes.includes(item.scriptTypeCode):",item.scriptTypeCode, targetCodes.includes(item.scriptTypeCode))
// result.push(item.scriptTypeCode)
// return result
// }
// // 如果存在 children递归检查
// if (item.children && item.children.length > 0) {
// result = result.concat(findTargetCodes(item.children, targetCodes))
// }
// }
// return result
}
onMounted(() => {})
// // 对外映射
// defineExpose({ init })
</script>
<style lang="scss" scoped>
.custom-tree-node {
max-width: 230px;
overflow-x: hidden !important;
white-space: nowrap !important;
text-overflow: ellipsis !important;
}
</style>
<template>
<el-tree
node-key="id"
default-expand-all
:data="props.treeData"
:props="defaultProps"
style="width: 100%"
:expand-on-click-node="false"
@node-click="handleNodeClick"
>
<template #default="{ node, data }">
<el-tooltip effect="dark" :content="data.sourceDesc || data.scriptTypeName" placement="top" :hide-after="0">
<div class="custom-tree-node">
{{ data.scriptTypeName || data.sourceDesc }}
</div>
</el-tooltip>
</template>
</el-tree>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { CheckData } from '@/api/check/interface'
const props = defineProps({
treeData: {
type: Array,
required: true
}
})
const emit = defineEmits(['setTab'])
const dataTree = ref<CheckData.TreeItem[]>([])
const defaultProps = {
children: 'children',
label: 'scriptTypeName',
pid: 'pid'
}
const activeName = ref('')
const childActiveName = ref('')
const handleNodeClick = (data, node) => {
console.log('handleNodeClick', data, node)
let code = ['Base', 'VOL', 'Freq', 'Harm', 'Base_0_10', 'Base_20_85', 'Base_110_200']
const parents = getParentNodes(node, [])
parents.pop()
parents.unshift(node.data)
parents.reverse()
let active = parents[0].scriptTypeCode
let childActive = findTargetCodes(parents, code)[0] || ''
// 获取当前节点的直接父节点
if (activeName.value != active || childActiveName.value != childActive) {
activeName.value = active
childActiveName.value = childActive
emit('setTab', {
activeName: active,
childActiveName: childActive
})
}
}
// 返回父级
const getParentNodes = (node, parents) => {
if (node.parent) {
// 将父节点添加到数组中
parents.push(node.parent.data)
// 递归获取更高层级的父节点
getParentNodes(node.parent, parents)
}
return parents
}
// 判断childActiveName值
function findTargetCodes(data: any[], targetCodes: string[]) {
let result: string[] = []
data.forEach(item => {
if (item.scriptTypeCode != null) {
if (targetCodes.includes(item.scriptTypeCode)) {
result.push(item.scriptTypeCode)
}
}
})
return result
// for (let item of data) {
// // 判断当前项的 scriptTypeCode 是否包含目标值
// if (item.scriptTypeCode !=null && targetCodes.includes(item.scriptTypeCode)) {
// result.push(item.scriptTypeCode)
// return result
// }
// // 如果存在 children递归检查
// if (item.children && item.children.length > 0) {
// result = result.concat(findTargetCodes(item.children, targetCodes))
// }
// }
// return result
}
onMounted(() => {})
// // 对外映射
// defineExpose({ init })
</script>
<style lang="scss" scoped>
.custom-tree-node {
max-width: 230px;
overflow-x: hidden !important;
white-space: nowrap !important;
text-overflow: ellipsis !important;
}
</style>

View File

@@ -1,405 +1,398 @@
<template>
<el-dialog v-model="dialogVisible" :title= "titleType" v-bind="dialogBig" @close="close">
<!-- <el-descriptions :column="5" border>
<el-descriptions-item label="脚本名称">测试</el-descriptions-item>
<el-descriptions-item label="参照标准名称">GBT 19862</el-descriptions-item>
<el-descriptions-item label="标准推行年份">2025</el-descriptions-item>
<el-descriptions-item label="模板类型">模版</el-descriptions-item>
<el-descriptions-item label="值类型">相对值</el-descriptions-item>
</el-descriptions> -->
<!-- tableData?.channelList -->
<el-tabs type="border-card">
<el-tab-pane :label="`L${item}`" v-for="item in 3" :key="item" >
<div class="tabPane">
<el-descriptions :column="4" border>
<el-descriptions-item label-align="right" label="电压有效值(%)">
{{
tableData?.channelList[item * 2 - 2].famp == null
? '/'
: tableData?.channelList[item * 2 - 2].famp
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电压相角(°)">
{{
tableData?.channelList[item * 2 - 2].fphase == null
? '/'
: tableData?.channelList[item * 2 - 2].fphase
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电流有效值(%)">
{{
tableData?.channelList[item * 2 - 1].famp == null
? '/'
: tableData?.channelList[item * 2 - 1].famp
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电流相角(°)">
{{
tableData?.channelList[item * 2 - 1].fphase == null
? '/'
: tableData?.channelList[item * 2 - 1].fphase
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="变动频度(次/min)">
{{ tableData?.channelList[item * 2 - 2].flickerData.fchagFre || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="变动量(%)">
{{ tableData?.channelList[item * 2 - 2].flickerData.fchagValue || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="波类型">
{{
tableData?.channelList[item * 2 - 2].flickerData.fchagValue == ''
? '/'
: tableData?.channelList[item * 2 - 2].flickerData.waveFluType
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="占空比(%)">
{{
tableData?.channelList[item * 2 - 2].flickerData.fchagValue == ''
? '/'
: tableData?.channelList[item * 2 - 2].flickerData.fdutyCycle
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="设定幅度(%)">
{{ tableData?.channelList[item * 2 - 2].dipData.ftransValue || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="持续时间(s)">
{{ tableData?.channelList[item * 2 - 2].dipData.retainTime || '/' }}
</el-descriptions-item>
</el-descriptions>
<!-- <el-descriptions :column="3" title="谐波电压" border class="mt10">
<div v-for="k in tableData?.channelList[item * 2 - 2].harmList">
<el-descriptions-item label-align="right" label="次数">{{ k.harm }}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波含有率(%)">{{k.famp}}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波相角(°)">{{k.fphase}}</el-descriptions-item>
</div>
</el-descriptions>
<el-descriptions :column="3" title="谐波电流" border class="mt10">
<div v-for="k in tableData?.channelList[item * 2 - 2].harmList">
<el-descriptions-item label-align="right" label="次数">{{ k.harm }}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波含有率(%)">{{k.famp}}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波相角(°)">{{k.fphase}}</el-descriptions-item>
</div>
</el-descriptions> -->
<div style="display: flex" class="mt10">
<el-tabs type="border-card" style="flex: 1" v-if="harmVIsShow">
<el-tab-pane label="谐波电压" >
<el-table
:data="tableData?.channelList[item * 2 - 2].harmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="harm" label="次数" />
<el-table-column prop="famp" label="谐波含有率(%)" />
<el-table-column prop="fphase" label="谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="ml10" style="flex: 1" v-if="harmAIsShow">
<el-tab-pane label="谐波电流">
<el-table
:data="tableData?.channelList[item * 2 - 1].harmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="harm" label="次数" />
<el-table-column prop="famp" label="谐波含有率(%)" />
<el-table-column prop="fphase" label="谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<div style="display: flex" class="mt10">
<el-tabs type="border-card" style="flex: 1" v-if="iHarmVIsShow">
<el-tab-pane label="间谐波电压">
<el-table
:data="tableData?.channelList[item * 2 - 2].inharmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="inharm" label="次数" />
<el-table-column prop="famp" label="间谐波含有率(%)" />
<el-table-column prop="fphase" label="间谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="ml10" style="flex: 1" v-if="iHarmAIsShow">
<el-tab-pane label="间谐波电流">
<el-table
:data="tableData?.channelList[item * 2 - 1].inharmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="inharm" label="次数" />
<el-table-column prop="famp" label="间谐波含有率(%)" />
<el-table-column prop="fphase" label="间谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="参考设定值列表" >
<div class="tabPane">
<el-table
:data="setValue_TableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="450px"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="pname" label="参考设定值类型" />
<el-table-column prop="name" label="参考设定值子类型" width="250">
<template #default="{ row }">{{ row.harmNum ? `(${row.harmNum}次)` : '' }} {{ row.name }}</template>
</el-table-column>
<el-table-column prop="dataType" label="值类型">
<template #default="{ row }">
<el-select v-model="row.dataType" v-if="!row.show">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span v-else>
{{ typeList.find(item => item.value == row.dataType)?.label || row.dataType }}
</span>
</template>
</el-table-column>
<el-table-column prop="phase" label="相别" />
<el-table-column prop="value" label="参考设定值">
<template #default="{ row }">
<span v-if="row.show">{{ row.value }}</span>
<el-input type="number" v-else v-model="row.value" placeholder="请输入值" />
</template>
</el-table-column>
<el-table-column prop="value" label="参与误差比较">
<template #default="{ row }">
{{ row.errorFlag == 0 ? '否' : '是' }}
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { dialogBig } from '@/utils/elementBind'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { scriptDtlsCheckDataList } from '@/api/device/testScript/index'
import { Dictionary } from 'lodash'
import { on } from 'events'
const dialogVisible = ref(false)
const titleType = ref('')
const tableData: any = ref({})
const setValue_TableData: any = ref([])
const copyRowList = ref({})
const harmVIsShow = ref(false)
const harmAIsShow = ref(false)
const iHarmVIsShow = ref(false)
const iHarmAIsShow = ref(false)
const emit = defineEmits(['close'])
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: [Object, Array],
required: true
},
})
// 表格配置项
const typeList = [
{
label: '实时',
value: 'real'
},
{
label: 'CP95值',
value: 'cp95'
},
{
label: '平均值',
value: 'avg'
},
{
label: '最小值',
value: 'min'
},
{
label: '最大值',
value: 'max'
}
]
const tabVisibilityMap: { [key: string]: { harmVIsShow: boolean, harmAIsShow: boolean, iHarmVIsShow: boolean, iHarmAIsShow: boolean } } = {
'谐波电压': { harmVIsShow: true, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: false },
'谐波电流': { harmVIsShow: false, harmAIsShow: true, iHarmVIsShow: false, iHarmAIsShow: false },
'间谐波电压': { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: true, iHarmAIsShow: false },
'间谐波电流': { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: true },
'谐波有功功率': { harmVIsShow: true, harmAIsShow: true, iHarmVIsShow: false, iHarmAIsShow: false },
};
const open = async (row: any,communicationList:any,parentTabName:string,childrenTabName:string) => {
console.log('🚀 ~ open ~ parentTabName:', parentTabName)
//对应表格显示隐藏
const visibilitySettings = tabVisibilityMap[parentTabName] || { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: false };
harmVIsShow.value = visibilitySettings.harmVIsShow;
harmAIsShow.value = visibilitySettings.harmAIsShow;
iHarmVIsShow.value = visibilitySettings.iHarmVIsShow;
iHarmAIsShow.value = visibilitySettings.iHarmAIsShow;
titleType.value = parentTabName + '_' + childrenTabName+ '_详情'
//console.log('🚀 ~ open ~ row:', row)
tableData.value = row
copyRowList.value = JSON.parse(JSON.stringify(row))
let treeData: any = []
await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
}).then((res: any) => {
treeData = res.data[0].children
})
let checkDataList: any = []
await communicationList.forEach((item: any) => {
item.children.forEach((k: any) => {
if (k.enable != 0 || k.errorFlag != 0) {
checkDataList.push({
pid: k.pid,
valueType: k.id,
dataType: k.dataType,
enable: k.enable,
errorFlag: k.errorFlag
})
}
})
})
let form = handleHarmData(JSON.parse(JSON.stringify(row)))
let retryCompute = isEqual(form, copyRowList)
console.log('🚀 ~ open ~ 1:', form)
console.log('🚀 ~ open ~ 2:', props.formContent?.id)
console.log('🚀 ~ open ~ 3:', props.activeName)
console.log('🚀 ~ open ~ 4:', checkDataList)
console.log('🚀 ~ open ~ 5:', retryCompute)
await scriptDtlsCheckDataList({
...form,
scriptId: props.formContent?.id,
scriptType: props.activeName,
checkDataList: checkDataList,
retryCompute: retryCompute
}).then((res: any) => {
res.data.forEach((item: any) => {
let pList = treeData.filter((i: any) => i.id == item.pid)[0]
item.pname = pList.name
item.name = pList.children.filter((i: any) => i.id == item.valueType)[0].name
item.show = true
})
setValue_TableData.value = res.data
console.log('🚀 ~ open ~ res.data:', res.data)
})
dialogVisible.value = true
}
// 关闭弹窗
const close = () => {
dialogVisible.value = false
emit('close')
}
// 处理多余数据
const handleHarmData = (row: any) => {
row.channelList.forEach((channel: any) => {
// 筛选出 famp 和 fphase 不同时为 0 的对象
channel.harmList = channel.harmList.filter((item: any) => item.famp != 0 || item.fphase != 0)
channel.inharmList = channel.inharmList.filter(
(item: any) => item.inharm !== '' || item.famp !== 0 || item.fphase !== 0
)
})
return row
}
// 判断数据是否变化
const isEqual = (obj1: any, obj2: any) => {
// 如果两个对象是同一个引用,直接返回 true
if (obj1 == obj2) return true
// 如果其中一个是 null 或者不是对象,返回 false
if (obj1 === null || typeof obj1 !== 'object' || obj2 === null || typeof obj2 !== 'object') {
return false
}
// 获取两个对象的键
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
// 如果键的数量不同,返回 false
if (keys1.length !== keys2.length) return false
// 遍历所有键,递归比较值
for (const key of keys1) {
if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-descriptions__cell) {
width: 12.5%;
}
:deep(.tabPane) {
height: 450px;
overflow-y: auto;
}
</style>
<template>
<el-dialog v-model="dialogVisible" :title= "titleType" v-bind="dialogBig" @close="close">
<!-- <el-descriptions :column="5" border>
<el-descriptions-item label="脚本名称">测试</el-descriptions-item>
<el-descriptions-item label="参照标准名称">GBT 19862</el-descriptions-item>
<el-descriptions-item label="标准推行年份">2025</el-descriptions-item>
<el-descriptions-item label="模板类型">模版</el-descriptions-item>
<el-descriptions-item label="值类型">相对值</el-descriptions-item>
</el-descriptions> -->
<!-- tableData?.channelList -->
<el-tabs type="border-card">
<el-tab-pane :label="`L${item}`" v-for="item in 3" :key="item" >
<div class="tabPane">
<el-descriptions :column="4" border>
<el-descriptions-item label-align="right" label="电压有效值(%)">
{{
tableData?.channelList[item * 2 - 2].famp == null
? '/'
: tableData?.channelList[item * 2 - 2].famp
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电压相角(°)">
{{
tableData?.channelList[item * 2 - 2].fphase == null
? '/'
: tableData?.channelList[item * 2 - 2].fphase
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电流有效值(%)">
{{
tableData?.channelList[item * 2 - 1].famp == null
? '/'
: tableData?.channelList[item * 2 - 1].famp
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="电流相角(°)">
{{
tableData?.channelList[item * 2 - 1].fphase == null
? '/'
: tableData?.channelList[item * 2 - 1].fphase
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="变动频度(次/min)">
{{ tableData?.channelList[item * 2 - 2].flickerData.fchagFre || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="变动量(%)">
{{ tableData?.channelList[item * 2 - 2].flickerData.fchagValue || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="波类型">
{{
tableData?.channelList[item * 2 - 2].flickerData.fchagValue == ''
? '/'
: tableData?.channelList[item * 2 - 2].flickerData.waveFluType
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="占空比(%)">
{{
tableData?.channelList[item * 2 - 2].flickerData.fchagValue == ''
? '/'
: tableData?.channelList[item * 2 - 2].flickerData.fdutyCycle
}}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="设定幅度(%)">
{{ tableData?.channelList[item * 2 - 2].dipData.ftransValue || '/' }}
</el-descriptions-item>
<el-descriptions-item label-align="right" label="持续时间(s)">
{{ tableData?.channelList[item * 2 - 2].dipData.retainTime || '/' }}
</el-descriptions-item>
</el-descriptions>
<!-- <el-descriptions :column="3" title="谐波电压" border class="mt10">
<div v-for="k in tableData?.channelList[item * 2 - 2].harmList">
<el-descriptions-item label-align="right" label="次数">{{ k.harm }}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波含有率(%)">{{k.famp}}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波相角(°)">{{k.fphase}}</el-descriptions-item>
</div>
</el-descriptions>
<el-descriptions :column="3" title="谐波电流" border class="mt10">
<div v-for="k in tableData?.channelList[item * 2 - 2].harmList">
<el-descriptions-item label-align="right" label="次数">{{ k.harm }}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波含有率(%)">{{k.famp}}</el-descriptions-item>
<el-descriptions-item label-align="right" label="谐波相角(°)">{{k.fphase}}</el-descriptions-item>
</div>
</el-descriptions> -->
<div style="display: flex" class="mt10">
<el-tabs type="border-card" style="flex: 1" v-if="harmVIsShow">
<el-tab-pane label="谐波电压" >
<el-table
:data="tableData?.channelList[item * 2 - 2].harmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="harm" label="次数" />
<el-table-column prop="famp" label="谐波含有率(%)" />
<el-table-column prop="fphase" label="谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="ml10" style="flex: 1" v-if="harmAIsShow">
<el-tab-pane label="谐波电流">
<el-table
:data="tableData?.channelList[item * 2 - 1].harmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="harm" label="次数" />
<el-table-column prop="famp" label="谐波含有率(%)" />
<el-table-column prop="fphase" label="谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<div style="display: flex" class="mt10">
<el-tabs type="border-card" style="flex: 1" v-if="iHarmVIsShow">
<el-tab-pane label="间谐波电压">
<el-table
:data="tableData?.channelList[item * 2 - 2].inharmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="inharm" label="次数" />
<el-table-column prop="famp" label="间谐波含有率(%)" />
<el-table-column prop="fphase" label="间谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="ml10" style="flex: 1" v-if="iHarmAIsShow">
<el-tab-pane label="间谐波电流">
<el-table
:data="tableData?.channelList[item * 2 - 1].inharmList"
border
size="small"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="250px"
>
<el-table-column prop="inharm" label="次数" />
<el-table-column prop="famp" label="间谐波含有率(%)" />
<el-table-column prop="fphase" label="间谐波相角(°)" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="参考设定值列表" >
<div class="tabPane">
<el-table
:data="setValue_TableData"
:header-cell-style="{
textAlign: 'center',
backgroundColor: 'var(--el-color-primary)',
color: '#fff'
}"
stripe
:cell-style="{ textAlign: 'center' }"
height="450px"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="pname" label="参考设定值类型" />
<el-table-column prop="name" label="参考设定值子类型" width="250">
<template #default="{ row }">{{ row.harmNum ? `(${row.harmNum}次)` : '' }} {{ row.name }}</template>
</el-table-column>
<el-table-column prop="dataType" label="值类型">
<template #default="{ row }">
<el-select v-model="row.dataType" v-if="!row.show">
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span v-else>
{{ typeList.find(item => item.value == row.dataType)?.label || row.dataType }}
</span>
</template>
</el-table-column>
<el-table-column prop="phase" label="相别" />
<el-table-column prop="value" label="参考设定值">
<template #default="{ row }">
<span v-if="row.show">{{ row.value }}</span>
<el-input type="number" v-else v-model="row.value" placeholder="请输入值" />
</template>
</el-table-column>
<el-table-column prop="value" label="参与误差比较">
<template #default="{ row }">
{{ row.errorFlag == 0 ? '否' : '是' }}
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { dialogBig } from '@/utils/elementBind'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { scriptDtlsCheckDataList } from '@/api/device/testScript/index'
import { Dictionary } from 'lodash'
import { on } from 'events'
const dialogVisible = ref(false)
const titleType = ref('')
const tableData: any = ref({})
const setValue_TableData: any = ref([])
const copyRowList = ref({})
const harmVIsShow = ref(false)
const harmAIsShow = ref(false)
const iHarmVIsShow = ref(false)
const iHarmAIsShow = ref(false)
const emit = defineEmits(['close'])
const props = defineProps({
activeName: {
type: String,
required: true
},
formContent: {
type: [Object, Array],
required: true
},
})
// 表格配置项
const typeList = [
{
label: '实时',
value: 'real'
},
{
label: 'CP95值',
value: 'cp95'
},
{
label: '平均值',
value: 'avg'
},
{
label: '最小值',
value: 'min'
},
{
label: '最大值',
value: 'max'
}
]
const tabVisibilityMap: { [key: string]: { harmVIsShow: boolean, harmAIsShow: boolean, iHarmVIsShow: boolean, iHarmAIsShow: boolean } } = {
'谐波电压': { harmVIsShow: true, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: false },
'谐波电流': { harmVIsShow: false, harmAIsShow: true, iHarmVIsShow: false, iHarmAIsShow: false },
'间谐波电压': { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: true, iHarmAIsShow: false },
'间谐波电流': { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: true },
'谐波有功功率': { harmVIsShow: true, harmAIsShow: true, iHarmVIsShow: false, iHarmAIsShow: false },
};
const open = async (row: any,communicationList:any,parentTabName:string,childrenTabName:string) => {
//对应表格显示隐藏
const visibilitySettings = tabVisibilityMap[parentTabName] || { harmVIsShow: false, harmAIsShow: false, iHarmVIsShow: false, iHarmAIsShow: false };
harmVIsShow.value = visibilitySettings.harmVIsShow;
harmAIsShow.value = visibilitySettings.harmAIsShow;
iHarmVIsShow.value = visibilitySettings.iHarmVIsShow;
iHarmAIsShow.value = visibilitySettings.iHarmAIsShow;
titleType.value = parentTabName + '_' + childrenTabName+ '_详情'
tableData.value = row
copyRowList.value = JSON.parse(JSON.stringify(row))
let treeData: any = []
await getDictTreeByCode({
name: '',
id: '',
pid: '',
pids: '',
code: 'Script_Error',
sort: 0
}).then((res: any) => {
treeData = res.data[0].children
})
let checkDataList: any = []
await communicationList.forEach((item: any) => {
item.children.forEach((k: any) => {
if (k.enable != 0 || k.errorFlag != 0) {
checkDataList.push({
pid: k.pid,
valueType: k.id,
dataType: k.dataType,
enable: k.enable,
errorFlag: k.errorFlag
})
}
})
})
let form = handleHarmData(JSON.parse(JSON.stringify(row)))
let retryCompute = isEqual(form, copyRowList)
await scriptDtlsCheckDataList({
...form,
scriptId: props.formContent?.id,
scriptType: props.activeName,
checkDataList: checkDataList,
retryCompute: retryCompute
}).then((res: any) => {
res.data.forEach((item: any) => {
let pList = treeData.filter((i: any) => i.id == item.pid)[0]
item.pname = pList.name
item.name = pList.children.filter((i: any) => i.id == item.valueType)[0].name
item.show = true
})
setValue_TableData.value = res.data
})
dialogVisible.value = true
}
// 关闭弹窗
const close = () => {
dialogVisible.value = false
emit('close')
}
// 处理多余数据
const handleHarmData = (row: any) => {
row.channelList.forEach((channel: any) => {
// 筛选出 famp 和 fphase 不同时为 0 的对象
channel.harmList = channel.harmList.filter((item: any) => item.famp != 0 || item.fphase != 0)
channel.inharmList = channel.inharmList.filter(
(item: any) => item.inharm !== '' || item.famp !== 0 || item.fphase !== 0
)
})
return row
}
// 判断数据是否变化
const isEqual = (obj1: any, obj2: any) => {
// 如果两个对象是同一个引用,直接返回 true
if (obj1 == obj2) return true
// 如果其中一个是 null 或者不是对象,返回 false
if (obj1 === null || typeof obj1 !== 'object' || obj2 === null || typeof obj2 !== 'object') {
return false
}
// 获取两个对象的键
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
// 如果键的数量不同,返回 false
if (keys1.length !== keys2.length) return false
// 遍历所有键,递归比较值
for (const key of keys1) {
if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-descriptions__cell) {
width: 12.5%;
}
:deep(.tabPane) {
height: 450px;
overflow-y: auto;
}
</style>