UPDATE: 处理控制台警告问题

This commit is contained in:
贾同学
2025-10-10 13:23:40 +08:00
parent 8e0b3be438
commit b319a89501
45 changed files with 6390 additions and 6341 deletions

View File

@@ -10,10 +10,11 @@
</template> </template>
<script setup lang="ts" name="403"> <script setup lang="ts" name="403">
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
const router = useRouter();
const router = useRouter()
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -10,10 +10,11 @@
</template> </template>
<script setup lang="ts" name="404"> <script setup lang="ts" name="404">
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
const router = useRouter();
const router = useRouter()
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -10,10 +10,11 @@
</template> </template>
<script setup lang="ts" name="500"> <script setup lang="ts" name="500">
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
const router = useRouter();
const router = useRouter()
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -9,5 +9,5 @@
<script setup lang="ts" name="Loading"></script> <script setup lang="ts" name="Loading"></script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use "./index.scss";;
</style> </style>

View File

@@ -1,49 +1,49 @@
<template> <template>
<div class='icon-box' > <div class="icon-box">
<el-input <el-input
ref='inputRef' ref="inputRef"
v-model='valueIcon' v-model="valueIcon"
v-bind='$attrs' v-bind="$attrs"
:placeholder='placeholder' :placeholder="placeholder"
:clearable='clearable' :clearable="clearable"
@clear='clearIcon' @clear="clearIcon"
@click='openDialog' @click="openDialog"
> >
<template #append> <template #append>
<el-button :icon='customIcons[iconValue]' /> <el-button :icon="customIcons[iconValue]" />
</template> </template>
</el-input> </el-input>
<el-dialog v-model='dialogVisible' :title='placeholder' top='5%' width='30%' > <el-dialog v-model="dialogVisible" :title="placeholder" top="5%" width="30%">
<el-input v-model='inputValue' placeholder='搜索图标' size='large' :prefix-icon='Icons.Search' /> <el-input v-model="inputValue" placeholder="搜索图标" size="large" :prefix-icon="Icons.Search" />
<el-scrollbar v-if='Object.keys(iconsList).length'> <el-scrollbar v-if="Object.keys(iconsList).length">
<div class='icon-list'> <div class="icon-list">
<div v-for='item in iconsList' :key='item' class='icon-item' @click='selectIcon(item)'> <div v-for="item in iconsList" :key="item" class="icon-item" @click="selectIcon(item)">
<component :is='item'></component> <component :is="item"></component>
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
</div> </div>
</div> </div>
</el-scrollbar> </el-scrollbar>
<el-empty v-else description='未搜索到您要找的图标~' /> <el-empty v-else description="未搜索到您要找的图标~" />
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script lang='ts' setup name='SelectIcon'> <script lang="ts" setup name="SelectIcon">
import * as Icons from '@element-plus/icons-vue' import * as Icons from '@element-plus/icons-vue'
import { computed, ref } from 'vue'; import { computed, ref } from 'vue'
interface SelectIconProps { interface SelectIconProps {
iconValue: string| undefined; iconValue: string | undefined
title?: string; title?: string
clearable?: boolean; clearable?: boolean
placeholder?: string; placeholder?: string
} }
const props = withDefaults(defineProps<SelectIconProps>(), { const props = withDefaults(defineProps<SelectIconProps>(), {
iconValue: '', iconValue: '',
title: '请选择图标', title: '请选择图标',
clearable: true, clearable: true,
placeholder: '请选择图标', placeholder: '请选择图标'
}) })
// 重新接收一下,防止打包后 clearable 报错 // 重新接收一下,防止打包后 clearable 报错
@@ -55,7 +55,7 @@ const openDialog = () => (dialogVisible.value = true)
// 选择图标(触发更新父组件数据) // 选择图标(触发更新父组件数据)
const emit = defineEmits<{ const emit = defineEmits<{
'update:iconValue': [value: string]; 'update:iconValue': [value: string]
}>() }>()
const selectIcon = (item: any) => { const selectIcon = (item: any) => {
dialogVisible.value = false dialogVisible.value = false
@@ -83,9 +83,8 @@ const iconsList = computed((): { [key: string]: any } => {
} }
return result return result
}) })
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -1,97 +1,84 @@
<template> <template>
<div class='time-control'> <div class="time-control">
<el-select <el-select class="select" v-model="timeUnit" placeholder="选择时间单位" @change="handleChange">
class='select'
v-model='timeUnit'
placeholder='选择时间单位'
@change='handleChange'
>
<!-- 采用 v-for 动态渲染 --> <!-- 采用 v-for 动态渲染 -->
<el-option <el-option v-for="unit in timeUnits" :key="unit.value" :label="unit.label" :value="unit.value"></el-option>
v-for='unit in timeUnits'
:key='unit.value'
:label='unit.label'
:value='unit.value'
></el-option>
</el-select> </el-select>
<!-- 禁用时间选择器 --> <!-- 禁用时间选择器 -->
<div class='date-display'> <div class="date-display">
<el-date-picker <el-date-picker
class='date-picker' class="date-picker"
v-model='startDate' v-model="startDate"
type='date' type="date"
placeholder='起始时间' placeholder="起始时间"
@change='emitDateChange' @change="emitDateChange"
:disabled-date='disableStartDate' :disabled-date="disableStartDate"
:readonly="timeUnit != '自定义'" :readonly="timeUnit != '自定义'"
></el-date-picker> ></el-date-picker>
<el-text>~</el-text> <el-text>~</el-text>
<el-date-picker <el-date-picker
class='date-picker' class="date-picker"
v-model='endDate' v-model="endDate"
type='date' type="date"
placeholder='结束时间' placeholder="结束时间"
@change='emitDateChange' @change="emitDateChange"
:disabled-date='disableEndDate' :disabled-date="disableEndDate"
:readonly="timeUnit !== '自定义'" :readonly="timeUnit !== '自定义'"
></el-date-picker> ></el-date-picker>
</div> </div>
<div class='date-display' v-if="timeUnit !== '自定义'"> <div class="date-display" v-if="timeUnit !== '自定义'">
<el-button <el-button
style='width: 10px;' style="width: 10px"
class='triangle-button' class="triangle-button"
type='primary' type="primary"
@click='prevPeriod' @click="prevPeriod"
@change='emitDateChange' @change="emitDateChange"
> >
<div class='left_triangle'></div> <div class="left_triangle"></div>
</el-button>
<el-button class='triangle-button' type='primary' @click='goToCurrent'>
当前
</el-button> </el-button>
<el-button class="triangle-button" type="primary" @click="goToCurrent">当前</el-button>
<el-button <el-button
style='width: 10px;' style="width: 10px"
class='triangle-button' class="triangle-button"
type='primary' type="primary"
@click='nextPeriod' @click="nextPeriod"
:disabled='isNextDisabled' :disabled="isNextDisabled"
> >
<div class='right_triangle'></div> <div class="right_triangle"></div>
</el-button> </el-button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts">
<script setup lang='ts'> import { onMounted, ref } from 'vue'
import { ref, onMounted, defineProps, defineEmits } from 'vue'
// 定义时间单位的类型 // 定义时间单位的类型
interface TimeUnit { interface TimeUnit {
label: string; label: string
value: string; value: string
} }
// 定义组件的props包含包括和排除的时间单位 // 定义组件的props包含包括和排除的时间单位
const props = defineProps({ const props = defineProps({
include: { include: {
type: Array as () => string[], type: Array as () => string[],
default: () => ['日', '周', '月', '季度', '年', '自定义'], default: () => ['日', '周', '月', '季度', '年', '自定义']
}, },
exclude: { exclude: {
type: Array as () => string[], type: Array as () => string[],
default: () => [], default: () => []
}, },
default: { default: {
type: String, type: String,
default: '月', default: '月'
}, }
}) })
// 定义事件 // 定义事件
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update-dates', startDate: string, endDate: string): void; (e: 'update-dates', startDate: string, endDate: string): void
}>() }>()
const timeUnit = ref<string>(props.default) // 默认选择 const timeUnit = ref<string>(props.default) // 默认选择
const startDate = ref<Date>(new Date()) // 起始日期 const startDate = ref<Date>(new Date()) // 起始日期
@@ -100,16 +87,17 @@ const isNextDisabled = ref<boolean>(false) // 控制下一周期按钮的禁用
const today = ref<Date>(new Date()) // 当前日期 const today = ref<Date>(new Date()) // 当前日期
// 过滤出可用的时间单位 // 过滤出可用的时间单位
const timeUnits = ref<TimeUnit[]>( const timeUnits = ref<TimeUnit[]>(
props.include.filter(unit => !props.exclude.includes(unit)).map(unit => ({ props.include
.filter(unit => !props.exclude.includes(unit))
.map(unit => ({
label: unit, label: unit,
value: unit, value: unit
})), }))
) )
// 发出日期变化事件 // 发出日期变化事件
const emitDateChange = () => { const emitDateChange = () => {
emit('update-dates', formatDate(startDate.value), formatDate(endDate.value)) emit('update-dates', formatDate(startDate.value), formatDate(endDate.value))
} }
// 在组件挂载时更新日期范围 // 在组件挂载时更新日期范围
@@ -139,7 +127,6 @@ const handleChange = (unit: string) => {
updateNextButtonStatus() updateNextButtonStatus()
} }
const updateDateRange = () => { const updateDateRange = () => {
// 根据选择的时间单位计算起始和结束日期 // 根据选择的时间单位计算起始和结束日期
if (timeUnit.value === '日') { if (timeUnit.value === '日') {
startDate.value = today.value startDate.value = today.value
@@ -147,32 +134,29 @@ const updateDateRange = () => {
} else if (timeUnit.value === '周') { } else if (timeUnit.value === '周') {
startDate.value = getStartOfWeek(today.value) startDate.value = getStartOfWeek(today.value)
endDate.value = getEndOfWeek(today.value) endDate.value = getEndOfWeek(today.value)
} else if (timeUnit.value === '月') { } else if (timeUnit.value === '月') {
// 获取本月的开始和结束日期 // 获取本月的开始和结束日期
startDate.value = new Date(today.value.getFullYear(), today.value.getMonth(), 1); startDate.value = new Date(today.value.getFullYear(), today.value.getMonth(), 1)
endDate.value = new Date(today.value.getFullYear(), today.value.getMonth() + 1, 0); endDate.value = new Date(today.value.getFullYear(), today.value.getMonth() + 1, 0)
// // 确保结束日期不超过今天 // // 确保结束日期不超过今天
// if (endDate.value > today.value) { // if (endDate.value > today.value) {
// endDate.value = new Date(today.value); // endDate.value = new Date(today.value);
// endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999 // endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999
// } // }
} else if (timeUnit.value === '季度') { } else if (timeUnit.value === '季度') {
const quarter = Math.floor(today.value.getMonth() / 3); const quarter = Math.floor(today.value.getMonth() / 3)
startDate.value = new Date(today.value.getFullYear(), quarter * 3, 1); startDate.value = new Date(today.value.getFullYear(), quarter * 3, 1)
endDate.value = new Date(today.value.getFullYear(), quarter * 3 + 3, 0); endDate.value = new Date(today.value.getFullYear(), quarter * 3 + 3, 0)
// // 确保结束日期不超过今天 // // 确保结束日期不超过今天
// if (endDate.value > today.value) { // if (endDate.value > today.value) {
// endDate.value = new Date(today.value); // endDate.value = new Date(today.value);
// endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999 // endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999
// } // }
} else if (timeUnit.value === '年') { } else if (timeUnit.value === '年') {
startDate.value = new Date(today.value.getFullYear(), 0, 1); startDate.value = new Date(today.value.getFullYear(), 0, 1)
endDate.value = new Date(today.value.getFullYear(), 11, 31); endDate.value = new Date(today.value.getFullYear(), 11, 31)
// // 确保结束日期不超过今天 // // 确保结束日期不超过今天
// if (endDate.value > today.value) { // if (endDate.value > today.value) {
@@ -205,8 +189,8 @@ const getEndOfWeek = (date: Date) => {
endOfWeek.setDate(endOfWeek.getDate() + diff) endOfWeek.setDate(endOfWeek.getDate() + diff)
// 获取今天的日期 // 获取今天的日期
const today = new Date(); const today = new Date()
today.setHours(23, 59, 59, 999); // 设置今天的结束时间23:59:59.999 today.setHours(23, 59, 59, 999) // 设置今天的结束时间23:59:59.999
// 返回不超过今天的结束时间 // 返回不超过今天的结束时间
//return endOfWeek > today ? today : endOfWeek; //return endOfWeek > today ? today : endOfWeek;
@@ -223,13 +207,8 @@ const prevPeriod = () => {
prevStartDate.setDate(prevStartDate.getDate() - 7) prevStartDate.setDate(prevStartDate.getDate() - 7)
prevEndDate.setDate(prevEndDate.getDate() - 7) prevEndDate.setDate(prevEndDate.getDate() - 7)
} else if (timeUnit.value === '月') { } else if (timeUnit.value === '月') {
prevStartDate.setMonth(prevStartDate.getMonth() - 1) prevStartDate.setMonth(prevStartDate.getMonth() - 1)
prevEndDate.setMonth(prevEndDate.getMonth() - 1) prevEndDate.setMonth(prevEndDate.getMonth() - 1)
} else if (timeUnit.value === '季度') { } else if (timeUnit.value === '季度') {
prevStartDate.setMonth(prevStartDate.getMonth() - 3) prevStartDate.setMonth(prevStartDate.getMonth() - 3)
prevEndDate.setMonth(prevEndDate.getMonth() - 3) prevEndDate.setMonth(prevEndDate.getMonth() - 3)
@@ -273,7 +252,6 @@ const nextPeriod = () => {
updateNextButtonStatus() updateNextButtonStatus()
} }
const updateNextButtonStatus = () => { const updateNextButtonStatus = () => {
// 更新下一个按钮的禁用状态 // 更新下一个按钮的禁用状态
const maxDate = new Date() // 假设最新日期为今天 const maxDate = new Date() // 假设最新日期为今天
// 将 maxDate 设置为当天的开始时间 // 将 maxDate 设置为当天的开始时间
@@ -286,7 +264,6 @@ const updateNextButtonStatus = () => {
emitDateChange() // 变化时也发出更新事件 emitDateChange() // 变化时也发出更新事件
} }
// 限制开始日期不能选择超过当前日期 // 限制开始日期不能选择超过当前日期
const disableStartDate = (date: Date) => { const disableStartDate = (date: Date) => {
return date > today.value return date > today.value
@@ -298,21 +275,18 @@ const disableEndDate = (date: Date) => {
return date > today.value || (start && date <= start) return date > today.value || (start && date <= start)
} }
// 格式化日期yyyy-mm-dd // 格式化日期yyyy-mm-dd
function formatDate(date: Date | null): string { function formatDate(date: Date | null): string {
if (!date) { if (!date) {
return ''; return ''
} }
const year = date.getFullYear(); const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`
} }
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -5,7 +5,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, defineExpose, watch, nextTick } from 'vue' import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
// import echarts from './echarts' // import echarts from './echarts'
import * as echarts from 'echarts' // 全引入 import * as echarts from 'echarts' // 全引入
// import 'echarts/lib/component/dataZoom' // import 'echarts/lib/component/dataZoom'

View File

@@ -1,7 +1,6 @@
<!-- 经典布局 --> <!-- 经典布局 -->
<template> <template>
<el-container class="layout"> <el-container class="layout">
<el-header> <el-header>
<div class="header-lf mask-image"> <div class="header-lf mask-image">
<div class="logo flx-center"> <div class="logo flx-center">
@@ -38,26 +37,26 @@
</template> </template>
<script setup lang="ts" name="layoutClassic"> <script setup lang="ts" name="layoutClassic">
import { computed } from "vue"; import { computed } from 'vue'
import { useRoute } from "vue-router"; import { useRoute } from 'vue-router'
import { useAuthStore } from "@/stores/modules/auth"; import { useAuthStore } from '@/stores/modules/auth'
import { useGlobalStore } from "@/stores/modules/global"; import { useGlobalStore } from '@/stores/modules/global'
import Main from "@/layouts/components/Main/index.vue"; import Main from '@/layouts/components/Main/index.vue'
import SubMenu from "@/layouts/components/Menu/SubMenu.vue"; import SubMenu from '@/layouts/components/Menu/SubMenu.vue'
import ToolBarLeft from "@/layouts/components/Header/ToolBarLeft.vue"; import ToolBarLeft from '@/layouts/components/Header/ToolBarLeft.vue'
import ToolBarRight from "@/layouts/components/Header/ToolBarRight.vue"; import ToolBarRight from '@/layouts/components/Header/ToolBarRight.vue'
const title = import.meta.env.VITE_GLOB_APP_TITLE; const title = import.meta.env.VITE_GLOB_APP_TITLE
const route = useRoute(); const route = useRoute()
const authStore = useAuthStore(); const authStore = useAuthStore()
const globalStore = useGlobalStore(); const globalStore = useGlobalStore()
const accordion = computed(() => globalStore.accordion); const accordion = computed(() => globalStore.accordion)
const isCollapse = computed(() => globalStore.isCollapse); const isCollapse = computed(() => globalStore.isCollapse)
const menuList = computed(() => authStore.showMenuListGet); const menuList = computed(() => authStore.showMenuListGet)
const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string); const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string)
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -11,7 +11,9 @@
v-for="item in menuList" v-for="item in menuList"
:key="item.path" :key="item.path"
class="split-item" class="split-item"
:class="{ 'split-active': splitActive === item.path || `/${splitActive.split('/')[1]}` === item.path }" :class="{
'split-active': splitActive === item.path || `/${splitActive.split('/')[1]}` === item.path
}"
@click="changeSubMenu(item)" @click="changeSubMenu(item)"
> >
<el-icon> <el-icon>
@@ -24,7 +26,7 @@
</div> </div>
<el-aside :class="{ 'not-aside': !subMenuList.length }" :style="{ width: isCollapse ? '65px' : '210px' }"> <el-aside :class="{ 'not-aside': !subMenuList.length }" :style="{ width: isCollapse ? '65px' : '210px' }">
<div class="logo flx-center"> <div class="logo flx-center">
<span v-show="subMenuList.length" class="logo-text">{{ isCollapse ? "G" : title }}</span> <span v-show="subMenuList.length" class="logo-text">{{ isCollapse ? 'G' : title }}</span>
</div> </div>
<el-scrollbar> <el-scrollbar>
<el-menu <el-menu
@@ -49,55 +51,55 @@
</template> </template>
<script setup lang="ts" name="layoutColumns"> <script setup lang="ts" name="layoutColumns">
import { ref, computed, watch } from "vue"; import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from 'vue-router'
import { useAuthStore } from "@/stores/modules/auth"; import { useAuthStore } from '@/stores/modules/auth'
import { useGlobalStore } from "@/stores/modules/global"; import { useGlobalStore } from '@/stores/modules/global'
import Main from "@/layouts/components/Main/index.vue"; import Main from '@/layouts/components/Main/index.vue'
import ToolBarLeft from "@/layouts/components/Header/ToolBarLeft.vue"; import ToolBarLeft from '@/layouts/components/Header/ToolBarLeft.vue'
import ToolBarRight from "@/layouts/components/Header/ToolBarRight.vue"; import ToolBarRight from '@/layouts/components/Header/ToolBarRight.vue'
import SubMenu from "@/layouts/components/Menu/SubMenu.vue"; import SubMenu from '@/layouts/components/Menu/SubMenu.vue'
const title = import.meta.env.VITE_GLOB_APP_TITLE; const title = import.meta.env.VITE_GLOB_APP_TITLE
const route = useRoute(); const route = useRoute()
const router = useRouter(); const router = useRouter()
const authStore = useAuthStore(); const authStore = useAuthStore()
const globalStore = useGlobalStore(); const globalStore = useGlobalStore()
const accordion = computed(() => globalStore.accordion); const accordion = computed(() => globalStore.accordion)
const isCollapse = computed(() => globalStore.isCollapse); const isCollapse = computed(() => globalStore.isCollapse)
const menuList = computed(() => authStore.showMenuListGet); const menuList = computed(() => authStore.showMenuListGet)
const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string); const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string)
const subMenuList = ref<Menu.MenuOptions[]>([]); const subMenuList = ref<Menu.MenuOptions[]>([])
const splitActive = ref(""); const splitActive = ref('')
watch( watch(
() => [menuList, route], () => [menuList, route],
() => { () => {
// 当前菜单没有数据直接 return // 当前菜单没有数据直接 return
if (!menuList.value.length) return; if (!menuList.value.length) return
splitActive.value = route.path; splitActive.value = route.path
const menuItem = menuList.value.filter((item: Menu.MenuOptions) => { const menuItem = menuList.value.filter((item: Menu.MenuOptions) => {
return route.path === item.path || `/${route.path.split("/")[1]}` === item.path; return route.path === item.path || `/${route.path.split('/')[1]}` === item.path
}); })
if (menuItem[0].children?.length) return (subMenuList.value = menuItem[0].children); if (menuItem[0].children?.length) return (subMenuList.value = menuItem[0].children)
subMenuList.value = []; subMenuList.value = []
}, },
{ {
deep: true, deep: true,
immediate: true immediate: true
} }
); )
// change SubMenu // change SubMenu
const changeSubMenu = (item: Menu.MenuOptions) => { const changeSubMenu = (item: Menu.MenuOptions) => {
splitActive.value = item.path; splitActive.value = item.path
if (item.children?.length) return (subMenuList.value = item.children); if (item.children?.length) return (subMenuList.value = item.children)
subMenuList.value = []; subMenuList.value = []
router.push(item.path); router.push(item.path)
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -4,11 +4,7 @@
<el-header> <el-header>
<div class="logo flx-center"> <div class="logo flx-center">
<!-- <img class="logo-img" src="@/assets/images/logo.svg" alt="logo" /> --> <!-- <img class="logo-img" src="@/assets/images/logo.svg" alt="logo" /> -->
<img <img class="logo-img" src="@/assets/images/cn_pms9100_logo.png" alt="logo" />
class="logo-img"
src="@/assets/images/cn_pms9100_logo.png"
alt="logo"
/>
<span class="logo-text">{{ title }}</span> <span class="logo-text">{{ title }}</span>
</div> </div>
<el-menu v-if="showMenuFlag" trigger="click" mode="horizontal" :router="false" :default-active="activeMenu"> <el-menu v-if="showMenuFlag" trigger="click" mode="horizontal" :router="false" :default-active="activeMenu">
@@ -45,37 +41,34 @@
<ToolBarRight /> <ToolBarRight />
</el-header> </el-header>
<Main /> <Main />
</el-container> </el-container>
</template> </template>
<script setup lang="ts" name="layoutTransverse"> <script setup lang="ts" name="layoutTransverse">
import { computed } from "vue"; import { computed } from 'vue'
import { useAuthStore } from "@/stores/modules/auth"; import { useAuthStore } from '@/stores/modules/auth'
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from 'vue-router'
import Main from "@/layouts/components/Main/index.vue"; import Main from '@/layouts/components/Main/index.vue'
import ToolBarRight from "@/layouts/components/Header/ToolBarRight.vue"; import ToolBarRight from '@/layouts/components/Header/ToolBarRight.vue'
import SubMenu from "@/layouts/components/Menu/SubMenu.vue"; import SubMenu from '@/layouts/components/Menu/SubMenu.vue'
const title = import.meta.env.VITE_GLOB_APP_TITLE; const title = import.meta.env.VITE_GLOB_APP_TITLE
const route = useRoute(); const route = useRoute()
const router = useRouter(); const router = useRouter()
const authStore = useAuthStore(); const authStore = useAuthStore()
const menuList = computed(() => authStore.showMenuListGet); const menuList = computed(() => authStore.showMenuListGet)
const showMenuFlag = computed(() => authStore.showMenuFlagGet) const showMenuFlag = computed(() => authStore.showMenuFlagGet)
const activeMenu = computed( const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string)
() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string
);
const handleClickMenu = (subItem: Menu.MenuOptions) => { const handleClickMenu = (subItem: Menu.MenuOptions) => {
if (subItem.meta.isLink) return window.open(subItem.meta.isLink, "_blank"); if (subItem.meta.isLink) return window.open(subItem.meta.isLink, '_blank')
router.push(subItem.path); router.push(subItem.path)
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
.logo { .logo {
margin-right: 0 !important; margin-right: 0 !important;
} }

View File

@@ -31,26 +31,26 @@
</template> </template>
<script setup lang="ts" name="layoutVertical"> <script setup lang="ts" name="layoutVertical">
import { computed } from "vue"; import { computed } from 'vue'
import { useRoute } from "vue-router"; import { useRoute } from 'vue-router'
import { useAuthStore } from "@/stores/modules/auth"; import { useAuthStore } from '@/stores/modules/auth'
import { useGlobalStore } from "@/stores/modules/global"; import { useGlobalStore } from '@/stores/modules/global'
import Main from "@/layouts/components/Main/index.vue"; import Main from '@/layouts/components/Main/index.vue'
import ToolBarLeft from "@/layouts/components/Header/ToolBarLeft.vue"; import ToolBarLeft from '@/layouts/components/Header/ToolBarLeft.vue'
import ToolBarRight from "@/layouts/components/Header/ToolBarRight.vue"; import ToolBarRight from '@/layouts/components/Header/ToolBarRight.vue'
import SubMenu from "@/layouts/components/Menu/SubMenu.vue"; import SubMenu from '@/layouts/components/Menu/SubMenu.vue'
const title = import.meta.env.VITE_GLOB_APP_TITLE; const title = import.meta.env.VITE_GLOB_APP_TITLE
const route = useRoute(); const route = useRoute()
const authStore = useAuthStore(); const authStore = useAuthStore()
const globalStore = useGlobalStore(); const globalStore = useGlobalStore()
const accordion = computed(() => globalStore.accordion); const accordion = computed(() => globalStore.accordion)
const isCollapse = computed(() => globalStore.isCollapse); const isCollapse = computed(() => globalStore.isCollapse)
const menuList = computed(() => authStore.showMenuListGet); const menuList = computed(() => authStore.showMenuListGet)
const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string); const activeMenu = computed(() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string)
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -10,62 +10,51 @@
<!-- <el-button dictType="primary"> --> <!-- <el-button dictType="primary"> -->
<div class="change_mode"> <div class="change_mode">
{{ title }} {{ title }}
<el-icon class="el-icon--right change_mode_down" <el-icon class="el-icon--right change_mode_down"><arrow-down /></el-icon>
><arrow-down
/></el-icon>
<el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon> <el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon>
</div> </div>
<!-- </el-button> --> <!-- </el-button> -->
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="handelOpen('模拟式')" <el-dropdown-item @click="handelOpen('模拟式')">模拟式模块</el-dropdown-item>
>模拟式模块</el-dropdown-item <el-dropdown-item @click="handelOpen('数字式')">数字式模块</el-dropdown-item>
> <el-dropdown-item @click="handelOpen('比对式')">比对式模块</el-dropdown-item>
<el-dropdown-item @click="handelOpen('数字式')"
>数字式模块</el-dropdown-item
>
<el-dropdown-item @click="handelOpen('比对式')"
>比对式模块</el-dropdown-item
>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
<p style="margin: 0;" > <p style="margin: 0">
<a href="http://www.shining-electric.com/" target="_blank"> <a href="http://www.shining-electric.com/" target="_blank">2024 © 南京灿能电力自动化股份有限公司</a>
2024 © 南京灿能电力自动化股份有限公司
</a>
</p> </p>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, computed, onMounted, watch } from "vue"; import { computed } from 'vue'
import { useAuthStore } from "@/stores/modules/auth"; import { useAuthStore } from '@/stores/modules/auth'
import { useModeStore } from '@/stores/modules/mode'; // 引入模式 store import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
const router = useRouter();
const authStore = useAuthStore(); const router = useRouter()
const modeStore = useModeStore(); const authStore = useAuthStore()
const modeStore = useModeStore()
const title = computed(() => { const title = computed(() => {
return modeStore.currentMode=== ''? '模拟式模块' : modeStore.currentMode+'模块'; return modeStore.currentMode === '' ? '模拟式模块' : modeStore.currentMode + '模块'
}); })
const handelOpen = async (item: string) => { const handelOpen = async (item: string) => {
await authStore.setShowMenu(); await authStore.setShowMenu()
modeStore.setCurrentMode(item); // 将模式code存入 store modeStore.setCurrentMode(item) // 将模式code存入 store
//if (router.currentRoute.value.path === '/home/index') { //if (router.currentRoute.value.path === '/home/index') {
// 强制刷新页面 // 强制刷新页面
window.location.reload(); window.location.reload()
//} else { //} else {
// router.push({ path: '/home/index' }); // router.push({ path: '/home/index' });
//} //}
}
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
.footer { .footer {
position: relative; position: relative;
background-color: var(--el-color-primary); background-color: var(--el-color-primary);

View File

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

View File

@@ -6,25 +6,32 @@
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="refresh"> <el-dropdown-item @click="refresh">
<el-icon><Refresh /></el-icon>{{ $t("tabs.refresh") }} <el-icon><Refresh /></el-icon>
{{ $t('tabs.refresh') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="maximize"> <el-dropdown-item @click="maximize">
<el-icon><FullScreen /></el-icon>{{ $t("tabs.maximize") }} <el-icon><FullScreen /></el-icon>
{{ $t('tabs.maximize') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item divided @click="closeCurrentTab"> <el-dropdown-item divided @click="closeCurrentTab">
<el-icon><Remove /></el-icon>{{ $t("tabs.closeCurrent") }} <el-icon><Remove /></el-icon>
{{ $t('tabs.closeCurrent') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'left')"> <el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'left')">
<el-icon><DArrowLeft /></el-icon>{{ $t("tabs.closeLeft") }} <el-icon><DArrowLeft /></el-icon>
{{ $t('tabs.closeLeft') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'right')"> <el-dropdown-item @click="tabStore.closeTabsOnSide(route.fullPath, 'right')">
<el-icon><DArrowRight /></el-icon>{{ $t("tabs.closeRight") }} <el-icon><DArrowRight /></el-icon>
{{ $t('tabs.closeRight') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item divided @click="tabStore.closeMultipleTab(route.fullPath)"> <el-dropdown-item divided @click="tabStore.closeMultipleTab(route.fullPath)">
<el-icon><CircleClose /></el-icon>{{ $t("tabs.closeOther") }} <el-icon><CircleClose /></el-icon>
{{ $t('tabs.closeOther') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click="closeAllTab"> <el-dropdown-item @click="closeAllTab">
<el-icon><FolderDelete /></el-icon>{{ $t("tabs.closeAll") }} <el-icon><FolderDelete /></el-icon>
{{ $t('tabs.closeAll') }}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
@@ -32,50 +39,50 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { inject, nextTick } from "vue"; import { inject, nextTick } from 'vue'
import { HOME_URL } from "@/config"; import { HOME_URL } from '@/config'
import { useTabsStore } from "@/stores/modules/tabs"; import { useTabsStore } from '@/stores/modules/tabs'
import { useGlobalStore } from "@/stores/modules/global"; import { useGlobalStore } from '@/stores/modules/global'
import { useKeepAliveStore } from "@/stores/modules/keepAlive"; import { useKeepAliveStore } from '@/stores/modules/keepAlive'
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from 'vue-router'
const route = useRoute(); const route = useRoute()
const router = useRouter(); const router = useRouter()
const tabStore = useTabsStore(); const tabStore = useTabsStore()
const globalStore = useGlobalStore(); const globalStore = useGlobalStore()
const keepAliveStore = useKeepAliveStore(); const keepAliveStore = useKeepAliveStore()
// refresh current page // refresh current page
const refreshCurrentPage: Function = inject("refresh") as Function; const refreshCurrentPage: Function = inject('refresh') as Function
const refresh = () => { const refresh = () => {
setTimeout(() => { setTimeout(() => {
keepAliveStore.removeKeepAliveName(route.name as string); keepAliveStore.removeKeepAliveName(route.name as string)
refreshCurrentPage(false); refreshCurrentPage(false)
nextTick(() => { nextTick(() => {
keepAliveStore.addKeepAliveName(route.name as string); keepAliveStore.addKeepAliveName(route.name as string)
refreshCurrentPage(true); refreshCurrentPage(true)
}); })
}, 0); }, 0)
}; }
// maximize current page // maximize current page
const maximize = () => { const maximize = () => {
globalStore.setGlobalState("maximize", true); globalStore.setGlobalState('maximize', true)
}; }
// Close Current // Close Current
const closeCurrentTab = () => { const closeCurrentTab = () => {
if (route.meta.isAffix) return; if (route.meta.isAffix) return
tabStore.removeTabs(route.fullPath); tabStore.removeTabs(route.fullPath)
}; }
// Close All // Close All
const closeAllTab = () => { const closeAllTab = () => {
tabStore.closeMultipleTab(); tabStore.closeMultipleTab()
router.push(HOME_URL); router.push(HOME_URL)
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "../index.scss"; @use '../index.scss';
</style> </style>

View File

@@ -24,12 +24,12 @@
<script setup lang="ts"> <script setup lang="ts">
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { ref, computed, watch, onMounted } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useGlobalStore } from '@/stores/modules/global' import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs' import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth' import { useAuthStore } from '@/stores/modules/auth'
import { TabsPaneContext, TabPaneName } from 'element-plus' import { TabPaneName, TabsPaneContext } from 'element-plus'
import MoreButton from './components/MoreButton.vue' import MoreButton from './components/MoreButton.vue'
const route = useRoute() const route = useRoute()
@@ -110,12 +110,10 @@ const tabClick = (tabItem: TabsPaneContext) => {
// Remove Tab // Remove Tab
const tabRemove = (fullPath: TabPaneName) => { const tabRemove = (fullPath: TabPaneName) => {
tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath) tabStore.removeTabs(fullPath as string, fullPath == route.fullPath || '/machine/testScriptAdd' == route.fullPath)
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import './index.scss'; @use './index.scss';
</style> </style>

View File

@@ -7,7 +7,10 @@
</el-divider> </el-divider>
<div class="layout-box"> <div class="layout-box">
<el-tooltip effect="dark" content="纵向" placement="top" :show-after="200"> <el-tooltip effect="dark" content="纵向" placement="top" :show-after="200">
<div :class="['layout-item layout-vertical', { 'is-active': layout == 'vertical' }]" @click="setLayout('vertical')"> <div
:class="['layout-item layout-vertical', { 'is-active': layout == 'vertical' }]"
@click="setLayout('vertical')"
>
<div class="layout-dark"></div> <div class="layout-dark"></div>
<div class="layout-container"> <div class="layout-container">
<div class="layout-light"></div> <div class="layout-light"></div>
@@ -19,7 +22,10 @@
</div> </div>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" content="经典" placement="top" :show-after="200"> <el-tooltip effect="dark" content="经典" placement="top" :show-after="200">
<div :class="['layout-item layout-classic', { 'is-active': layout == 'classic' }]" @click="setLayout('classic')"> <div
:class="['layout-item layout-classic', { 'is-active': layout == 'classic' }]"
@click="setLayout('classic')"
>
<div class="layout-dark"></div> <div class="layout-dark"></div>
<div class="layout-container"> <div class="layout-container">
<div class="layout-light"></div> <div class="layout-light"></div>
@@ -31,7 +37,10 @@
</div> </div>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" content="横向" placement="top" :show-after="200"> <el-tooltip effect="dark" content="横向" placement="top" :show-after="200">
<div :class="['layout-item layout-transverse', { 'is-active': layout == 'transverse' }]" @click="setLayout('transverse')"> <div
:class="['layout-item layout-transverse', { 'is-active': layout == 'transverse' }]"
@click="setLayout('transverse')"
>
<div class="layout-dark"></div> <div class="layout-dark"></div>
<div class="layout-content"></div> <div class="layout-content"></div>
<el-icon v-if="layout == 'transverse'"> <el-icon v-if="layout == 'transverse'">
@@ -40,7 +49,10 @@
</div> </div>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" content="分栏" placement="top" :show-after="200"> <el-tooltip effect="dark" content="分栏" placement="top" :show-after="200">
<div :class="['layout-item layout-columns', { 'is-active': layout == 'columns' }]" @click="setLayout('columns')"> <div
:class="['layout-item layout-columns', { 'is-active': layout == 'columns' }]"
@click="setLayout('columns')"
>
<div class="layout-dark"></div> <div class="layout-dark"></div>
<div class="layout-light"></div> <div class="layout-light"></div>
<div class="layout-content"></div> <div class="layout-content"></div>
@@ -128,18 +140,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from 'vue'
import { storeToRefs } from "pinia"; import { storeToRefs } from 'pinia'
import { useTheme } from "@/hooks/useTheme"; import { useTheme } from '@/hooks/useTheme'
import { useGlobalStore } from "@/stores/modules/global"; import { useGlobalStore } from '@/stores/modules/global'
import { LayoutType } from "@/stores/interface"; import { LayoutType } from '@/stores/interface'
import { DEFAULT_PRIMARY } from "@/config"; import { DEFAULT_PRIMARY } from '@/config'
import mittBus from "@/utils/mittBus"; import mittBus from '@/utils/mittBus'
import SwitchDark from "@/components/SwitchDark/index.vue"; import SwitchDark from '@/components/SwitchDark/index.vue'
const { changePrimary, changeGreyOrWeak, setAsideTheme, setHeaderTheme } = useTheme(); const { changePrimary, changeGreyOrWeak, setAsideTheme, setHeaderTheme } = useTheme()
const globalStore = useGlobalStore(); const globalStore = useGlobalStore()
const { const {
layout, layout,
primary, primary,
@@ -154,33 +166,33 @@ const {
tabs, tabs,
tabsIcon, tabsIcon,
footer footer
} = storeToRefs(globalStore); } = storeToRefs(globalStore)
// 预定义主题颜色 // 预定义主题颜色
const colorList = [ const colorList = [
DEFAULT_PRIMARY, DEFAULT_PRIMARY,
"#daa96e", '#daa96e',
"#0c819f", '#0c819f',
"#409eff", '#409eff',
"#27ae60", '#27ae60',
"#ff5c93", '#ff5c93',
"#e74c3c", '#e74c3c',
"#fd726d", '#fd726d',
"#f39c12", '#f39c12',
"#9b59b6" '#9b59b6'
]; ]
// 设置布局方式 // 设置布局方式
const setLayout = (val: LayoutType) => { const setLayout = (val: LayoutType) => {
globalStore.setGlobalState("layout", val); globalStore.setGlobalState('layout', val)
setAsideTheme(); setAsideTheme()
}; }
// 打开主题设置 // 打开主题设置
const drawerVisible = ref(false); const drawerVisible = ref(false)
mittBus.on("openThemeDrawer", () => (drawerVisible.value = true)); mittBus.on('openThemeDrawer', () => (drawerVisible.value = true))
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<el-dialog :title="dialogTitle" :model-value="dialogVisible" @close="close" v-bind="dialogMiddle" align-center> <el-dialog :title="dialogTitle" :model-value="dialogVisible" @close="close" v-bind="dialogMiddle" align-center>
<el-form :model="formContent" ref='dialogFormRef' :rules='rules' class="form-two"> <el-form :model="formContent" ref="dialogFormRef" :rules="rules" class="form-two">
<el-form-item label="上级菜单" prop="pid" :label-width="100"> <el-form-item label="上级菜单" prop="pid" :label-width="100">
<el-tree-select <el-tree-select
v-model="displayPid" v-model="displayPid"
@@ -23,7 +23,7 @@
<IconSelect <IconSelect
v-model="formContent.icon" v-model="formContent.icon"
:iconValue="formContent.icon" :iconValue="formContent.icon"
@update:icon-value="iconValue => formContent.icon = iconValue" @update:icon-value="iconValue => (formContent.icon = iconValue)"
placeholder="选择一个图标" placeholder="选择一个图标"
/> />
</el-form-item> </el-form-item>
@@ -34,9 +34,9 @@
<el-input v-model="formContent.component" maxlength="32" show-word-limit /> <el-input v-model="formContent.component" maxlength="32" show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort" :label-width="100"> <el-form-item label="排序" prop="sort" :label-width="100">
<el-input-number v-model="formContent.sort" :min='1' :max='999' /> <el-input-number v-model="formContent.sort" :min="1" :max="999" />
</el-form-item> </el-form-item>
<el-form-item label='类型' prop='type' :label-width="100"> <el-form-item label="类型" prop="type" :label-width="100">
<el-select v-model="formContent.type" clearable placeholder="请选择资源类型"> <el-select v-model="formContent.type" clearable placeholder="请选择资源类型">
<el-option label="菜单" :value="0"></el-option> <el-option label="菜单" :value="0"></el-option>
<el-option label="按钮" :value="1"></el-option> <el-option label="按钮" :value="1"></el-option>
@@ -58,20 +58,21 @@
</template> </template>
<script lang="ts" setup name="ResourceDialog"> <script lang="ts" setup name="ResourceDialog">
import { defineProps, defineEmits,watch,ref, type Ref, computed } from 'vue'; import { computed, type Ref, ref, watch } from 'vue'
import { dialogMiddle } from '@/utils/elementBind' import { dialogMiddle } from '@/utils/elementBind'
import { ElMessage, type FormInstance, type FormItemRule } from 'element-plus' import { ElMessage, type FormInstance, type FormItemRule } from 'element-plus'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import type { Function } from "@/api/user/interface/function" import type { Function } from '@/api/user/interface/function'
import {addFunction,updateFunction,getFunctionListNoButton} from '@/api/user/function/index' import { addFunction, getFunctionListNoButton, updateFunction } from '@/api/user/function/index'
import IconSelect from '@/components/SelectIcon/index.vue' import IconSelect from '@/components/SelectIcon/index.vue'
const value = ref() const value = ref()
// 树形节点配置 // 树形节点配置
const defaultProps = { const defaultProps = {
children: 'children', children: 'children',
label: 'name', label: 'name',
value: 'id' value: 'id'
}; }
const functionList = ref<Function.ResFunction[]>([]) const functionList = ref<Function.ResFunction[]>([])
const dictStore = useDictStore() const dictStore = useDictStore()
// 定义弹出组件元信息 // 定义弹出组件元信息
@@ -91,7 +92,7 @@
sort: 100, //排序 sort: 100, //排序
type: 0, //资源类型0-菜单、1-按钮、2-公共资源、3-服务间调用资源 type: 0, //资源类型0-菜单、1-按钮、2-公共资源、3-服务间调用资源
remark: '', //权限资源描述 remark: '', //权限资源描述
state:1,//权限资源状态 state: 1 //权限资源状态
}) })
return { dialogVisible, titleType, formContent } return { dialogVisible, titleType, formContent }
} }
@@ -111,7 +112,7 @@ const resetFormContent = () => {
sort: 100, //排序 sort: 100, //排序
type: 0, //资源类型0-菜单、1-按钮、2-公共资源、3-服务间调用资源 type: 0, //资源类型0-菜单、1-按钮、2-公共资源、3-服务间调用资源
remark: '', //权限资源描述 remark: '', //权限资源描述
state:1,//权限资源状态 state: 1 //权限资源状态
} }
} }
@@ -119,8 +120,6 @@ const resetFormContent = () => {
return titleType.value === 'add' ? '新增菜单' : '编辑菜单' return titleType.value === 'add' ? '新增菜单' : '编辑菜单'
}) })
// 定义规则 // 定义规则
const formRuleRef = ref<FormInstance>() const formRuleRef = ref<FormInstance>()
const rules: Ref<Record<string, Array<FormItemRule>>> = ref({ const rules: Ref<Record<string, Array<FormItemRule>>> = ref({
@@ -128,17 +127,20 @@ const resetFormContent = () => {
code: [{ required: true, trigger: 'blur', message: '编码必填!' }] code: [{ required: true, trigger: 'blur', message: '编码必填!' }]
}) })
watch(() => formContent.value.type, (newVal) => { watch(
() => formContent.value.type,
newVal => {
if (newVal === 1) { if (newVal === 1) {
// 选择按钮时,路由地址和组件地址无需校验 // 选择按钮时,路由地址和组件地址无需校验
rules.value.path = []; rules.value.path = []
rules.value.component = []; rules.value.component = []
} else { } else {
// 其他情况下,路由地址和组件地址需要校验 // 其他情况下,路由地址和组件地址需要校验
rules.value.path = [{ required: true, trigger: 'blur', message: '路由地址必填!' }]; rules.value.path = [{ required: true, trigger: 'blur', message: '路由地址必填!' }]
rules.value.component = [{ required: true, trigger: 'blur', message: '组件地址必填!' }]; rules.value.component = [{ required: true, trigger: 'blur', message: '组件地址必填!' }]
} }
}); }
)
// 关闭弹窗 // 关闭弹窗
const close = () => { const close = () => {
@@ -149,40 +151,40 @@ const close = () => {
dialogFormRef.value?.resetFields() dialogFormRef.value?.resetFields()
} }
// 计算属性,用于控制显示的 pid // 计算属性,用于控制显示的 pid
const displayPid = computed({ const displayPid = computed({
get: () => { get: () => {
return formContent.value.pid === '0' ? '' : formContent.value.pid; return formContent.value.pid === '0' ? '' : formContent.value.pid
}, },
set: (value) => { set: value => {
formContent.value.pid = value; formContent.value.pid = value
} }
}); })
// 保存数据 // 保存数据
const save = () => { const save = () => {
try { try {
dialogFormRef.value?.validate(async (valid: boolean) => { dialogFormRef.value?.validate(async (valid: boolean) => {
if (formContent.value.pid === undefined || formContent.value.pid === null || formContent.value.pid === '') { if (formContent.value.pid === undefined || formContent.value.pid === null || formContent.value.pid === '') {
formContent.value.pid = '0'; formContent.value.pid = '0'
} }
if (formContent.value.pids === undefined || formContent.value.pids === null || formContent.value.pids === '') { if (
formContent.value.pids = '0'; formContent.value.pids === undefined ||
formContent.value.pids === null ||
formContent.value.pids === ''
) {
formContent.value.pids = '0'
} }
if (valid) { if (valid) {
if (formContent.value.id) { if (formContent.value.id) {
await updateFunction(formContent.value); await updateFunction(formContent.value)
} else { } else {
await addFunction(formContent.value); await addFunction(formContent.value)
} }
ElMessage.success({ message: `${dialogTitle.value}成功!` }) ElMessage.success({ message: `${dialogTitle.value}成功!` })
close() close()
// 刷新表格 // 刷新表格
await props.refreshTable!() await props.refreshTable!()
} }
}) })
} catch (err) { } catch (err) {
@@ -190,7 +192,6 @@ const displayPid = computed({
} }
} }
// 打开弹窗,可能是新增,也可能是编辑 // 打开弹窗,可能是新增,也可能是编辑
const open = async (sign: string, data: Function.ResFunction) => { const open = async (sign: string, data: Function.ResFunction) => {
// 重置表单 // 重置表单
@@ -199,11 +200,11 @@ const displayPid = computed({
functionList.value = response.data as unknown as Function.ResFunction[] functionList.value = response.data as unknown as Function.ResFunction[]
titleType.value = sign titleType.value = sign
dialogVisible.value = true dialogVisible.value = true
rules.value.path = [{ required: true, trigger: 'blur', message: '路由地址必填!' }]; rules.value.path = [{ required: true, trigger: 'blur', message: '路由地址必填!' }]
rules.value.component = [{ required: true, trigger: 'blur', message: '组件地址必填!' }]; rules.value.component = [{ required: true, trigger: 'blur', message: '组件地址必填!' }]
if (formContent.value.pid === '0') { if (formContent.value.pid === '0') {
formContent.value.pid = ''; formContent.value.pid = ''
} }
if (data.id) { if (data.id) {
@@ -216,7 +217,6 @@ const displayPid = computed({
// 对外映射 // 对外映射
defineExpose({ open }) defineExpose({ open })
const props = defineProps<{ const props = defineProps<{
refreshTable: (() => Promise<void>) | undefined; refreshTable: (() => Promise<void>) | undefined
}>() }>()
</script> </script>

View File

@@ -1,11 +1,13 @@
<template> <template>
<div class="table-container table-main"> <div class="table-container table-main">
<el-table :data="tableData" <el-table
:data="tableData"
:header-cell-style="{ textAlign: 'center' }" :header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }"
style="width: 100%" style="width: 100%"
max-height="400px" max-height="400px"
:span-method="objectSpanMethod"> :span-method="objectSpanMethod"
>
<el-table-column prop="monitorNum" label="监测点序号" width="80" /> <el-table-column prop="monitorNum" label="监测点序号" width="80" />
<el-table-column prop="desc" label="描述" width="90" /> <el-table-column prop="desc" label="描述" width="90" />
<el-table-column label="电压通道"> <el-table-column label="电压通道">
@@ -29,7 +31,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4)+ 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.aV + 'V' }} 误差值{{ scope.row.aV + 'V' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -43,7 +49,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4)+ 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.aV + 'V' }} 误差值{{ scope.row.aV + 'V' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.aVuXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.aVuXi }}</el-tag>
@@ -80,7 +90,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4)+ 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.bV + 'V' }} 误差值{{ scope.row.bV + 'V' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -94,7 +108,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4)+ 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.bV + 'V' }} 误差值{{ scope.row.bV + 'V' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.bVuXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.bVuXi }}</el-tag>
@@ -125,7 +143,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4)+ 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.cV + 'V' }} 误差值{{ scope.row.cV + 'V' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -139,7 +161,11 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ (-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'}}<br/> 误差范围
{{
(-0.001 * props.curV).toFixed(4) + 'V~' + (0.001 * props.curV).toFixed(4) + 'V'
}}
<br />
误差值{{ scope.row.cV + 'V' }} 误差值{{ scope.row.cV + 'V' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.cVuXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.cVuXi }}</el-tag>
@@ -172,7 +198,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{-0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.aI + '%' }} 误差值{{ scope.row.aI + '%' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -186,7 +213,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ -0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.aI + '%' }} 误差值{{ scope.row.aI + '%' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.aIeXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.aIeXi }}</el-tag>
@@ -217,7 +245,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ -0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.bI + '%' }} 误差值{{ scope.row.bI + '%' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -231,7 +260,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ -0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.bI + '%' }} 误差值{{ scope.row.bI + '%' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.bIeXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.bIeXi }}</el-tag>
@@ -262,7 +292,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ -0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.cI + '%' }} 误差值{{ scope.row.cI + '%' }}
</template> </template>
<el-tag type="danger" class="tooltip-content"> <el-tag type="danger" class="tooltip-content">
@@ -276,7 +307,8 @@
placement="bottom-start" placement="bottom-start"
> >
<template #content> <template #content>
误差范围 {{ -0.5 + "%~" +0.5 + "%" }}<br/> 误差范围 {{ -0.5 + '%~' + 0.5 + '%' }}
<br />
误差值{{ scope.row.cI + '%' }} 误差值{{ scope.row.cI + '%' }}
</template> </template>
<el-tag type="success" class="tooltip-content">{{ scope.row.cIeXi }}</el-tag> <el-tag type="success" class="tooltip-content">{{ scope.row.cIeXi }}</el-tag>
@@ -293,56 +325,62 @@
</template> </template>
<script lang="ts" setup name="ErrorSystemDialog"> <script lang="ts" setup name="ErrorSystemDialog">
import { defineProps, type PropType } from 'vue'; import { ElIcon, ElTag } from 'element-plus'
import { ElIcon, ElLoading, ElTag } from 'element-plus'; import type { ChannelsTest } from '@/api/home/interface/channelsTest'
import type { ChannelsTest } from '@/api/home/interface/channelsTest';
import { number } from 'echarts';
interface Props { interface Props {
tableData: ChannelsTest.CoefficientVO[]; tableData: ChannelsTest.CoefficientVO[]
big_V_loading: boolean; big_V_loading: boolean
curV: number; curV: number
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
tableData: () => [], tableData: () => [],
big_V_loading: false, big_V_loading: false,
curV: 0, curV: 0
}); })
function objectSpanMethod({ row, column, rowIndex, columnIndex }: { row: any, column: any, rowIndex: number, columnIndex: number }) { function objectSpanMethod({
row,
column,
rowIndex,
columnIndex
}: {
row: any
column: any
rowIndex: number
columnIndex: number
}) {
if (columnIndex === 0) { if (columnIndex === 0) {
if (rowIndex % 4 === 0) { if (rowIndex % 4 === 0) {
return { return {
rowspan: 4, rowspan: 4,
colspan: 1, colspan: 1
}; }
} else { } else {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
}; }
} }
} }
if (columnIndex === 1) { if (columnIndex === 1) {
if (rowIndex % 2 === 0) { if (rowIndex % 2 === 0) {
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
}; }
} else { } else {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
}; }
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.form-grid { .form-grid {
display: flex; display: flex;
flex-direction: row; /* 横向排列 */ flex-direction: row; /* 横向排列 */
@@ -364,7 +402,8 @@ const props = withDefaults(defineProps<Props>(), {
margin-bottom: 20px; /* 添加底部边距 */ margin-bottom: 20px; /* 添加底部边距 */
} }
.el-table th, .el-table td { .el-table th,
.el-table td {
text-align: center; /* 所有单元格文字居中 */ text-align: center; /* 所有单元格文字居中 */
} }
@@ -391,7 +430,6 @@ const props = withDefaults(defineProps<Props>(), {
cursor: pointer; cursor: pointer;
} }
@keyframes rotate { @keyframes rotate {
from { from {
transform: rotate(0deg); transform: rotate(0deg);

View File

@@ -40,7 +40,12 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="检测次数"> <el-form-item label="检测次数">
<el-select v-model="formContent.num" clearable @change="handleNumChange" :disabled="sourceKey == 1"> <el-select
v-model="formContent.num"
clearable
@change="handleNumChange"
:disabled="sourceKey == 1"
>
<el-option <el-option
v-for="item in chnMapList[formContent.chnNum]" v-for="item in chnMapList[formContent.chnNum]"
:key="item" :key="item"
@@ -67,9 +72,7 @@
node-key="id" node-key="id"
ref="treeRef" ref="treeRef"
@node-click="handleNodeClick" @node-click="handleNodeClick"
> ></el-tree>
</el-tree>
</div> </div>
<div class="content-right"> <div class="content-right">
<div class="content-right-title"> <div class="content-right-title">
@@ -93,17 +96,19 @@
<span v-else style="color: var(--el-color-primary)">{{ rowList.scriptName }}</span> <span v-else style="color: var(--el-color-primary)">{{ rowList.scriptName }}</span>
</div> </div>
<el-form-item <el-form-item
style="margin: 0 auto; margin-bottom: 0px !important; width: 200px; position: absolute; left: 50%; transform: translateX(-50%);" style="
margin: 0 auto;
margin-bottom: 0px !important;
width: 200px;
position: absolute;
left: 50%;
transform: translateX(-50%);
"
label="录波次数" label="录波次数"
v-if="isWaveData" v-if="isWaveData"
> >
<el-select v-model="waveNumber" @change="handleWaveNumberChange"> <el-select v-model="waveNumber" @change="handleWaveNumberChange">
<el-option <el-option v-for="i in waveNumCount" :key="i" :label="i" :value="i" />
v-for="i in waveNumCount"
:key="i"
:label="i"
:value="i"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
@@ -128,7 +133,6 @@
:currentCheckItem="currentCheckItem" :currentCheckItem="currentCheckItem"
:currentScriptTypeName="currentScriptTypeName" :currentScriptTypeName="currentScriptTypeName"
v-if="activeTab === 'resultTab'" v-if="activeTab === 'resultTab'"
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="原始数据" name="rawDataTab"> <el-tab-pane label="原始数据" name="rawDataTab">
@@ -148,7 +152,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import { reactive, ref, watch, computed, nextTick } from 'vue' import { computed, reactive, ref } from 'vue'
import CompareDataCheckResultTable from './compareDataCheckResultTable.vue' import CompareDataCheckResultTable from './compareDataCheckResultTable.vue'
import CompareDataCheckRawDataTable from './compareDataCheckRawDataTable.vue' import CompareDataCheckRawDataTable from './compareDataCheckRawDataTable.vue'
import { CheckData } from '@/api/check/interface' import { CheckData } from '@/api/check/interface'
@@ -157,16 +161,20 @@ import { Histogram, Postcard } from '@element-plus/icons-vue'
import { getPqErrSysList } from '@/api/plan/plan' import { getPqErrSysList } from '@/api/plan/plan'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { getContrastFormContent, getContrastResult, getScriptList,reCalculate ,changeErrorSystem,deleteTempTable} from '@/api/check/test' import {
changeErrorSystem,
deleteTempTable,
getContrastFormContent,
getContrastResult,
getScriptList,
reCalculate
} from '@/api/check/test'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import {ResultEnum} from "@/enums/httpEnum"; import { ResultEnum } from '@/enums/httpEnum'
const { appendToBody } = withDefaults( const { appendToBody = true } = defineProps<{
defineProps<{
appendToBody: boolean appendToBody: boolean
}>(), }>()
{ appendToBody: true }
)
const checkStore = useCheckStore() const checkStore = useCheckStore()
const modeStore = useModeStore() const modeStore = useModeStore()
@@ -192,7 +200,7 @@ const selectedScriptName = ref('')
const pattern = ref('') const pattern = ref('')
// 添加以下内容 // 添加以下内容
const isWaveData = ref(false) const isWaveData = ref(false)
const scriptNameOptions = ref<{label: string, value: string}[]>([]) const scriptNameOptions = ref<{ label: string; value: string }[]>([])
// 表单数据 // 表单数据
const formContent = reactive<CheckData.DataCheck>({ const formContent = reactive<CheckData.DataCheck>({
@@ -230,7 +238,6 @@ const currentRawTableData = computed(() => {
return Array.isArray(data) ? data : [] return Array.isArray(data) ? data : []
}) })
const open = async (row: any, chnNum: string, deviceId: string | null, source: number) => { const open = async (row: any, chnNum: string, deviceId: string | null, source: number) => {
isWaveData.value = false isWaveData.value = false
pattern.value = dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '' //获取数据字典中对应的id pattern.value = dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '' //获取数据字典中对应的id
@@ -261,13 +268,13 @@ const open = async (row: any, chnNum: string, deviceId: string | null, source: n
Object.assign(pqErrorList, resPqErrorList) Object.assign(pqErrorList, resPqErrorList)
initGetResult() initGetResult()
} }
const initGetResult = async () => { const initGetResult = async () => {
// 判断是否为录波数据 // 判断是否为录波数据
const isLuoboData = (sourceKey.value == 1 && rowList.value.scriptName == "录波数据") || const isLuoboData =
(sourceKey.value == 2 && scriptData.value[0]?.code == "wave_data"); (sourceKey.value == 1 && rowList.value.scriptName == '录波数据') ||
(sourceKey.value == 2 && scriptData.value[0]?.code == 'wave_data')
if (isLuoboData) { if (isLuoboData) {
isWaveData.value = true isWaveData.value = true
// 设置录波数据相关的选项 // 设置录波数据相关的选项
@@ -292,7 +299,6 @@ const initGetResult = async () => {
} }
} }
// 查询大项树 // 查询大项树
const initScriptData = async () => { const initScriptData = async () => {
let response: any = await getScriptList({ let response: any = await getScriptList({
@@ -313,11 +319,10 @@ const initScriptData = async () => {
scriptData.value = temp scriptData.value = temp
// 查找code为"录波"的项 // 查找code为"录波"的项
let luoboItem = response.data.find((item: any) => item.code === 'wave_data'); let luoboItem = response.data.find((item: any) => item.code === 'wave_data')
// 如果找到了"录波"项则使用其subitems否则使用空数组 // 如果找到了"录波"项则使用其subitems否则使用空数组
let temp2 = []; let temp2 = []
if (luoboItem && luoboItem.subItems) { if (luoboItem && luoboItem.subItems) {
// 格式化脚本数据 // 格式化脚本数据
temp2 = luoboItem.subItems.map((item: any) => { temp2 = luoboItem.subItems.map((item: any) => {
return { return {
@@ -328,10 +333,8 @@ const initScriptData = async () => {
} }
selectScript.value = temp2 selectScript.value = temp2
// 只有在sourceKey == 2时才设置rowList和tree相关属性 // 只有在sourceKey == 2时才设置rowList和tree相关属性
if (sourceKey.value === 2 && temp.length > 0) { if (sourceKey.value === 2 && temp.length > 0) {
rowList.value.scriptName = temp[0].scriptName rowList.value.scriptName = temp[0].scriptName
rowList.value.scriptType = temp[0].id rowList.value.scriptType = temp[0].id
selectedScriptName.value = temp[0].scriptName selectedScriptName.value = temp[0].scriptName
@@ -339,8 +342,6 @@ const initScriptData = async () => {
treeRef.value?.setCurrentKey(temp[0].id) treeRef.value?.setCurrentKey(temp[0].id)
}, 0) }, 0)
} }
} }
// 获取基本信息 // 获取基本信息
@@ -389,8 +390,6 @@ const getBasicInformation = async (scriptType: any) => {
formContent.num = numList[numList.length - 1] formContent.num = numList[numList.length - 1]
} }
waveNumCount.value = res.data.waveNumTotal waveNumCount.value = res.data.waveNumTotal
} catch (error) { } catch (error) {
console.error('获取基本信息失败:', error) console.error('获取基本信息失败:', error)
} }
@@ -431,7 +430,7 @@ const handleCommonChange = async () => {
const tempNode = { const tempNode = {
scriptName: rowList.value.scriptName, scriptName: rowList.value.scriptName,
id: rowList.value.scriptType, id: rowList.value.scriptType,
code: rowList.value.scriptName === "录波数据" ? 'wave_data' : '' code: rowList.value.scriptName === '录波数据' ? 'wave_data' : ''
} }
handleNodeClick(tempNode) handleNodeClick(tempNode)
} }
@@ -464,7 +463,6 @@ const handleNodeClick = (data: any) => {
// 每次选中录波数据时都重置为第一个选项并触发getResults // 每次选中录波数据时都重置为第一个选项并触发getResults
if (scriptNameOptions.value.length > 0) { if (scriptNameOptions.value.length > 0) {
selectedScriptName.value = scriptNameOptions.value[0].value selectedScriptName.value = scriptNameOptions.value[0].value
// 更新rowList并触发getResults // 更新rowList并触发getResults
rowList.value.scriptName = selectedScriptName.value rowList.value.scriptName = selectedScriptName.value
@@ -476,7 +474,6 @@ const handleNodeClick = (data: any) => {
} }
} }
} else { } else {
isWaveData.value = false isWaveData.value = false
getResults(data.code) getResults(data.code)
} }
@@ -507,8 +504,6 @@ const getResults = async (code: any) => {
tesList.value = list tesList.value = list
checkResultData.value = res.data.resultMap checkResultData.value = res.data.resultMap
rawTableData.value = res.data.rawDataMap rawTableData.value = res.data.rawDataMap
}) })
} }
@@ -547,8 +542,8 @@ const handleErrorSysChange = async () => {
errorSysId: formContent.errorSysId, errorSysId: formContent.errorSysId,
deviceId: formContent.deviceId, deviceId: formContent.deviceId,
code: checkStore.plan.code + '', code: checkStore.plan.code + '',
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '', patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
}).then((res) => { }).then(res => {
if (res.code === ResultEnum.SUCCESS) { if (res.code === ResultEnum.SUCCESS) {
ElMessage.success('切换误差体系成功') ElMessage.success('切换误差体系成功')
handleChnNumChange(formContent.chnNum) handleChnNumChange(formContent.chnNum)
@@ -556,8 +551,6 @@ const handleErrorSysChange = async () => {
}) })
} }
const handleReCalculate = async () => { const handleReCalculate = async () => {
reCalculate({ reCalculate({
planId: checkStore.plan.id, planId: checkStore.plan.id,
@@ -565,14 +558,12 @@ const handleReCalculate = async () => {
errorSysId: formContent.errorSysId, errorSysId: formContent.errorSysId,
deviceId: formContent.deviceId, deviceId: formContent.deviceId,
code: checkStore.plan.code + '', code: checkStore.plan.code + '',
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '', patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
}).then((res) => { }).then(res => {
if (res.code === ResultEnum.SUCCESS) { if (res.code === ResultEnum.SUCCESS) {
ElMessage.success('重新计算成功!') ElMessage.success('重新计算成功!')
handleChnNumChange(formContent.chnNum) handleChnNumChange(formContent.chnNum)
} }
}) })
} }

View File

@@ -81,8 +81,8 @@
<RealTimeData ref="realTimeDataRef" /> <RealTimeData ref="realTimeDataRef" />
</template> </template>
<script lang="tsx" setup name="preTest"> <script lang="tsx" setup name="preTest">
import {ElMessage, ElMessageBox, StepProps} from "element-plus"; import { ElMessage, ElMessageBox, StepProps } from 'element-plus'
import {computed, defineExpose, PropType, ref, toRef, watch} from 'vue'; import { computed, PropType, ref, toRef, watch } from 'vue'
import RealTimeData from './realTimeDataAlign.vue' import RealTimeData from './realTimeDataAlign.vue'
const realTimeDataRef = ref() const realTimeDataRef = ref()

View File

@@ -134,30 +134,17 @@
</template> </template>
<script lang="tsx" setup name="testPopup"> <script lang="tsx" setup name="testPopup">
import { nextTick, PropType, reactive, ref, watch } from 'vue' import { nextTick, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { import { Coin, Edit, Key, Refresh, Right, SuccessFilled, Switch, VideoPause, VideoPlay } from '@element-plus/icons-vue'
Coin,
Edit,
Key,
Switch,
Refresh,
Right,
SuccessFilled,
UploadFilled,
VideoPause,
VideoPlay
} from '@element-plus/icons-vue'
import ComparePreTest from './comparePreTest.vue' import ComparePreTest from './comparePreTest.vue'
import ChannelPairing from './channelPairing.vue' import ChannelPairing from './channelPairing.vue'
import { Device } from '@/api/device/interface/device'
import CompareTest from './compareTest.vue' import CompareTest from './compareTest.vue'
import socketClient from '@/utils/webSocketClient' import socketClient from '@/utils/webSocketClient'
import { useCheckStore } from '@/stores/modules/check' import { useCheckStore } from '@/stores/modules/check'
import { pauseTest, resumeTest, startPreTest, contrastTest } from '@/api/socket/socket' import { contrastTest, pauseTest, resumeTest, startPreTest } from '@/api/socket/socket'
import { useUserStore } from '@/stores/modules/user' import { useUserStore } from '@/stores/modules/user'
import { JwtUtil } from '@/utils/jwtUtil' import { JwtUtil } from '@/utils/jwtUtil'
import { StandardDevice } from '@/api/device/interface/standardDevice'
const userStore = useUserStore() const userStore = useUserStore()
const checkStore = useCheckStore() const checkStore = useCheckStore()
@@ -242,8 +229,8 @@ const standardDevIds = ref<[]>()
const pairs = ref<any>() const pairs = ref<any>()
const testAgain = ref(false) //重新检测按钮是否显示 const testAgain = ref(false) //重新检测按钮是否显示
const checkNumber = ref(0) //检测次数 const checkNumber = ref(0) //检测次数
const deviceMonitor2= ref<Map<string, any[]>>(); const deviceMonitor2 = ref<Map<string, any[]>>()
const onlyWave = ref(false);//计划数据源是否只有录波 const onlyWave = ref(false) //计划数据源是否只有录波
const open = async ( const open = async (
title: string, title: string,
mapping: any, mapping: any,
@@ -258,8 +245,8 @@ const open = async (
if (checkStore.selectTestItems.preTest && !checkStore.selectTestItems.test) { if (checkStore.selectTestItems.preTest && !checkStore.selectTestItems.test) {
testAgain.value = true testAgain.value = true
} }
deviceMonitor2.value = deviceMonitor; deviceMonitor2.value = deviceMonitor
onlyWave.value = planIsOnlyWave; onlyWave.value = planIsOnlyWave
checkStore.setNodesConnectable(true) checkStore.setNodesConnectable(true)
dialogTitle.value = title dialogTitle.value = title
channelMapping.value = mapping channelMapping.value = mapping
@@ -588,7 +575,6 @@ const nextStep = () => {
} }
const handleStepClick = (step: number) => { const handleStepClick = (step: number) => {
if (step > stepsActive.value) { if (step > stepsActive.value) {
return return
} else { } else {
@@ -636,7 +622,7 @@ defineExpose({ open })
<style scoped lang="scss"> <style scoped lang="scss">
.test-head-steps { .test-head-steps {
::v-deep .el-step { :deep(.el-step) {
.el-step__head.is-success { .el-step__head.is-success {
color: #91cc75; color: #91cc75;
} }

View File

@@ -1,8 +1,12 @@
<template> <template>
<div class="table-main"> <div class="table-main">
<el-table v-if="tableData.length > 0" :data="tableData" height="357px" :header-cell-style="{ textAlign: 'center' } " <el-table
:cell-style="{ textAlign: 'center' }"> v-if="tableData.length > 0"
:data="tableData"
height="357px"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
>
<!-- <el-table-column prop="chnNum" label="通道号" width="80">--> <!-- <el-table-column prop="chnNum" label="通道号" width="80">-->
<!-- <template #default="{row}">--> <!-- <template #default="{row}">-->
<!-- {{ '通道' + row.chnNum }}--> <!-- {{ '通道' + row.chnNum }}-->
@@ -15,7 +19,8 @@
<template #default="scope"> <template #default="scope">
<el-tooltip effect="dark" placement="bottom"> <el-tooltip effect="dark" placement="bottom">
<template #content> <template #content>
误差范围{{ scope.row.maxErrorA }} <br/> 误差范围{{ scope.row.maxErrorA }}
<br />
误差值{{ scope.row.errorA }} {{ scope.row.errorA !== '/' ? innerUnitA : '' }} 误差值{{ scope.row.errorA }} {{ scope.row.errorA !== '/' ? innerUnitA : '' }}
</template> </template>
<el-tag type="success" v-if="scope.row.isDataA === 1">符合</el-tag> <el-tag type="success" v-if="scope.row.isDataA === 1">符合</el-tag>
@@ -33,7 +38,8 @@
<template #default="scope"> <template #default="scope">
<el-tooltip effect="dark" placement="bottom"> <el-tooltip effect="dark" placement="bottom">
<template #content> <template #content>
误差范围{{ scope.row.maxErrorB }}<br/> 误差范围{{ scope.row.maxErrorB }}
<br />
误差值{{ scope.row.errorB }} {{ scope.row.errorB !== '/' ? innerUnitB : '' }} 误差值{{ scope.row.errorB }} {{ scope.row.errorB !== '/' ? innerUnitB : '' }}
</template> </template>
<el-tag type="success" v-if="scope.row.isDataB === 1">符合</el-tag> <el-tag type="success" v-if="scope.row.isDataB === 1">符合</el-tag>
@@ -51,7 +57,8 @@
<template #default="scope"> <template #default="scope">
<el-tooltip effect="dark" placement="bottom"> <el-tooltip effect="dark" placement="bottom">
<template #content> <template #content>
误差范围 {{ scope.row.maxErrorC }}<br/> 误差范围 {{ scope.row.maxErrorC }}
<br />
误差值{{ scope.row.errorC }} {{ scope.row.errorC !== '/' ? innerUnitC : '' }} 误差值{{ scope.row.errorC }} {{ scope.row.errorC !== '/' ? innerUnitC : '' }}
</template> </template>
<el-tag type="success" v-if="scope.row.isDataC === 1">符合</el-tag> <el-tag type="success" v-if="scope.row.isDataC === 1">符合</el-tag>
@@ -70,7 +77,8 @@
<template #default="scope"> <template #default="scope">
<el-tooltip effect="dark" placement="bottom"> <el-tooltip effect="dark" placement="bottom">
<template #content> <template #content>
误差范围 {{ scope.row.maxErrorT }}<br/> 误差范围 {{ scope.row.maxErrorT }}
<br />
误差值{{ scope.row.errorT }} {{ scope.row.errorT !== '/' ? innerUnitT : '' }} 误差值{{ scope.row.errorT }} {{ scope.row.errorT !== '/' ? innerUnitT : '' }}
</template> </template>
<el-tag type="success" v-if="scope.row.isDataT === 1">符合</el-tag> <el-tag type="success" v-if="scope.row.isDataT === 1">符合</el-tag>
@@ -83,54 +91,52 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import {computed, defineProps} from 'vue'; import { computed } from 'vue'
import {CheckData} from "@/api/check/interface"; import { CheckData } from '@/api/check/interface'
const { tableData, currentScriptTypeName } = defineProps<{ const { tableData, currentScriptTypeName } = defineProps<{
tableData: CheckData.CheckResult[], tableData: CheckData.CheckResult[]
currentScriptTypeName: string currentScriptTypeName: string
}>(); }>()
const outerUnit = computed(() => { const outerUnit = computed(() => {
return tableData.length > 0 ? tableData[0].unit : ''; return tableData.length > 0 ? tableData[0].unit : ''
}) })
const innerUnitA = computed(() => { const innerUnitA = computed(() => {
return tableData.length > 0 ? tableData[0].unitA : ''; return tableData.length > 0 ? tableData[0].unitA : ''
}) })
const innerUnitB = computed(() => { const innerUnitB = computed(() => {
return tableData.length > 0 ? tableData[0].unitB : ''; return tableData.length > 0 ? tableData[0].unitB : ''
}) })
const innerUnitC = computed(() => { const innerUnitC = computed(() => {
return tableData.length > 0 ? tableData[0].unitC : ''; return tableData.length > 0 ? tableData[0].unitC : ''
}) })
const innerUnitT = computed(() => { const innerUnitT = computed(() => {
return tableData.length > 0 ? tableData[0].unitT : ''; return tableData.length > 0 ? tableData[0].unitT : ''
}) })
const phaseA = computed(() => { const phaseA = computed(() => {
return tableData.length <= 0 || tableData[0].dataA == null || tableData[0].dataA == "/" ? 0 : 1 return tableData.length <= 0 || tableData[0].dataA == null || tableData[0].dataA == '/' ? 0 : 1
}) })
const phaseB = computed(() => { const phaseB = computed(() => {
return tableData.length <= 0 || tableData[0].dataB == null || tableData[0].dataB == "/" ? 0 : 1 return tableData.length <= 0 || tableData[0].dataB == null || tableData[0].dataB == '/' ? 0 : 1
}) })
const phaseC = computed(() => { const phaseC = computed(() => {
return tableData.length <= 0 || tableData[0].dataC == null || tableData[0].dataC == "/" ? 0 : 1 return tableData.length <= 0 || tableData[0].dataC == null || tableData[0].dataC == '/' ? 0 : 1
}) })
const phaseT = computed(() => { const phaseT = computed(() => {
return tableData.length <= 0 || tableData[0].dataT == null || tableData[0].dataT == "/" ? 0 : 1 return tableData.length <= 0 || tableData[0].dataT == null || tableData[0].dataT == '/' ? 0 : 1
}) })
const tableHeader = computed(() => { const tableHeader = computed(() => {
if (phaseT.value === 1) { if (phaseT.value === 1) {
let index = currentScriptTypeName.indexOf('='); let index = currentScriptTypeName.indexOf('=')
return currentScriptTypeName.substring(0, index); return currentScriptTypeName.substring(0, index)
} }
return currentScriptTypeName return currentScriptTypeName
}) })
@@ -143,11 +149,9 @@ const tableHeader = computed(() => {
// } // }
// return result; // return result;
// }) // })
</script> </script>
<style scoped> <style scoped>
.form-grid { .form-grid {
display: flex; display: flex;
flex-direction: row; /* 横向排列 */ flex-direction: row; /* 横向排列 */
@@ -173,8 +177,8 @@ const tableHeader = computed(() => {
margin-bottom: 20px; /* 添加底部边距 */ margin-bottom: 20px; /* 添加底部边距 */
} }
.el-table th, .el-table td { .el-table th,
.el-table td {
text-align: center; /* 所有单元格文字居中 */ text-align: center; /* 所有单元格文字居中 */
} }
</style> </style>

View File

@@ -1,32 +1,50 @@
<template> <template>
<el-dialog :append-to-body="appendToBody" class="dialog" title="数据查询" :model-value='visible' @close="close" <el-dialog
v-bind="dialogBig" :draggable="false" width="1400px"> :append-to-body="appendToBody"
class="dialog"
title="数据查询"
:model-value="visible"
@close="close"
v-bind="dialogBig"
:draggable="false"
width="1400px"
>
<div class="data-check-dialog"> <div class="data-check-dialog">
<div class="data-check-head"> <div class="data-check-head">
<el-form :model='formContent' label-width="auto" class="form-three "> <el-form :model="formContent" label-width="auto" class="form-three">
<el-form-item label="检测脚本"> <el-form-item label="检测脚本">
<el-input v-model='formContent.scriptName' :disabled="true"/> <el-input v-model="formContent.scriptName" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="误差体系"> <el-form-item label="误差体系">
<el-select :disabled="checkStore.showDetailType===2 || checkStore.showDetailType===0" v-model="formContent.errorSysId" placeholder="请选择误差体系" <el-select
:disabled="checkStore.showDetailType === 2 || checkStore.showDetailType === 0"
v-model="formContent.errorSysId"
placeholder="请选择误差体系"
autocomplete="off" autocomplete="off"
@change="handleErrorSysChange"> @change="handleErrorSysChange"
>
<el-option <el-option
v-for="(option) in pqErrorList" v-for="option in pqErrorList"
:key="option.id" :key="option.id"
:label="option.name" :label="option.name"
:value="option.id"/> :value="option.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据原则"> <el-form-item label="数据原则">
<el-input v-model='formContent.dataRule' :disabled="true"/> <el-input v-model="formContent.dataRule" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="设备名称"> <el-form-item label="设备名称">
<el-input v-model='formContent.deviceName' :disabled="true"/> <el-input v-model="formContent.deviceName" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label='通道号'> <el-form-item label="通道号">
<el-select v-model="formContent.chnNum"> <el-select v-model="formContent.chnNum">
<el-option v-for="item in chnList" :key="item.value" :label="item.label" :value="item.value"/> <el-option
v-for="item in chnList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="checkStore.showDetailType === 1"> <el-form-item v-if="checkStore.showDetailType === 1">
@@ -40,24 +58,31 @@
<div class="data-check-body"> <div class="data-check-body">
<div class="content-left-tree"> <div class="content-left-tree">
<div style="width: 99%;"> <div style="width: 99%">
<el-input <el-input placeholder="请输入测试项名称" clearable v-model="searchValue"></el-input>
placeholder='请输入测试项名称'
clearable
v-model='searchValue'
></el-input>
</div> </div>
<div class="content-tree"> <div class="content-tree">
<el-tree :filter-node-method='filterNode' :highlight-current="true" :default-expanded-keys="defaultExpandedKeys" <el-tree
:filter-node-method="filterNode"
:highlight-current="true"
:default-expanded-keys="defaultExpandedKeys"
node-key="index" node-key="index"
:data="treeDataAll" :data="treeDataAll"
:props="defaultProps" :props="defaultProps"
@node-click="handleNodeClick" class="custom-tree" ref="treeRef"> @node-click="handleNodeClick"
class="custom-tree"
ref="treeRef"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<el-tooltip effect="dark" :content="data.scriptTypeName" placement="right"> <el-tooltip effect="dark" :content="data.scriptTypeName" placement="right">
<span class="custom-tree-node" :style="data.fly===2? 'color: #F56C6C;':data.fly===4? 'color: #e6a23c;':''">{{ <span
data.scriptTypeName class="custom-tree-node"
}}</span> :style="
data.fly === 2 ? 'color: #F56C6C;' : data.fly === 4 ? 'color: #e6a23c;' : ''
"
>
{{ data.scriptTypeName }}
</span>
</el-tooltip> </el-tooltip>
</template> </template>
</el-tree> </el-tree>
@@ -66,18 +91,23 @@
<div class="content-right"> <div class="content-right">
<div class="content-right-title"> <div class="content-right-title">
<div style="width: 840px;"> <div style="width: 840px">
<span class="content-right-title-text">当前检测项目 <span class="content-right-title-text">
当前检测项目
<el-popover trigger="hover" :content="currentDesc" width="500px" placement="right"> <el-popover trigger="hover" :content="currentDesc" width="500px" placement="right">
<template #reference> <template #reference>
<el-button type="text" style="font-size: 14px;"> <el-button type="text" style="font-size: 14px">
{{ currentScriptTypeName }} {{ currentScriptTypeName }}
</el-button> </el-button>
</template> </template>
</el-popover> </el-popover>
</span> </span>
</div> </div>
<el-form-item style="margin-left: 0px;margin-bottom:0px !important;width: 280px;" v-if="checkListLevel.length" label='测试项'> <el-form-item
style="margin-left: 0px; margin-bottom: 0px !important; width: 280px"
v-if="checkListLevel.length"
label="测试项"
>
<el-cascader <el-cascader
v-model="currentCheckItem" v-model="currentCheckItem"
:options="checkListLevel" :options="checkListLevel"
@@ -89,10 +119,17 @@
<div class="content-right-Tabs"> <div class="content-right-Tabs">
<el-tabs type="border-card" v-model="activeTab"> <el-tabs type="border-card" v-model="activeTab">
<el-tab-pane label="检测结果" name="resultTab"> <el-tab-pane label="检测结果" name="resultTab">
<DataCheckResultTable :tableData="checkResultData" :currentScriptTypeName="currentScriptTypeName"/> <DataCheckResultTable
:tableData="checkResultData"
:currentScriptTypeName="currentScriptTypeName"
/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="原始数据" name="rawDataTab"> <el-tab-pane label="原始数据" name="rawDataTab">
<DataCheckRawDataTable :tableData="rawTableData" :currentScriptTypeName="currentScriptTypeName" @exportRawDataHandler="exportRawDataHandler"/> <DataCheckRawDataTable
:tableData="rawTableData"
:currentScriptTypeName="currentScriptTypeName"
@exportRawDataHandler="exportRawDataHandler"
/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@@ -100,48 +137,54 @@
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import DataCheckResultTable from './dataCheckResultTable.vue' import DataCheckResultTable from './dataCheckResultTable.vue'
import DataCheckRawDataTable from './dataCheckRawDataTable.vue' import DataCheckRawDataTable from './dataCheckRawDataTable.vue'
import {CheckData} from "@/api/check/interface"; import { CheckData } from '@/api/check/interface'
import {useCheckStore} from "@/stores/modules/check"; import { useCheckStore } from '@/stores/modules/check'
import {changeErrorSystem, deleteTempTable, exportRawData, getFormData, getTableData, getTreeData, reCalculate} from "@/api/check/test"; import {
changeErrorSystem,
deleteTempTable,
exportRawData,
getFormData,
getTableData,
getTreeData,
reCalculate
} from '@/api/check/test'
import { generateDevReport, getPqErrSysList } from '@/api/plan/plan' import { generateDevReport, getPqErrSysList } from '@/api/plan/plan'
import {useDownload} from "@/hooks/useDownload"; import { useDownload } from '@/hooks/useDownload'
import {Histogram, Postcard} from "@element-plus/icons-vue"; import { Histogram, Postcard } from '@element-plus/icons-vue'
import {ResultEnum} from "@/enums/httpEnum"; import { ResultEnum } from '@/enums/httpEnum'
import {ElMessage} from "element-plus"; import { ElMessage } from 'element-plus'
import {useDictStore} from "@/stores/modules/dict"; import { useDictStore } from '@/stores/modules/dict'
import {useModeStore} from "@/stores/modules/mode"; import { useModeStore } from '@/stores/modules/mode'
const dictStore = useDictStore() const dictStore = useDictStore()
const modeStore = useModeStore() const modeStore = useModeStore()
const {appendToBody} = withDefaults(defineProps<{ const { appendToBody = true } = defineProps<{
appendToBody: boolean appendToBody: boolean
}>(), {appendToBody: true}) }>()
const defaultProps = { const defaultProps = {
label: "scriptTypeName", label: 'scriptTypeName',
children: "children", children: 'children'
}; }
const checkStore = useCheckStore() const checkStore = useCheckStore()
const visible = ref(false) const visible = ref(false)
const treeRef = ref() const treeRef = ref()
const searchValue = ref<string>('') const searchValue = ref<string>('')
const pqErrorList = reactive<{ id: string; name: string; }[]>([]) const pqErrorList = reactive<{ id: string; name: string }[]>([])
watch(searchValue, (val) => { watch(searchValue, val => {
treeRef.value!.filter(val) treeRef.value!.filter(val)
}) })
// 格式化数字 // 格式化数字
const fixed = 4; const fixed = 4
// 表单数据 // 表单数据
const formContent = reactive<CheckData.DataCheck>({ const formContent = reactive<CheckData.DataCheck>({
@@ -149,7 +192,7 @@ const formContent = reactive<CheckData.DataCheck>({
errorSysId: '', errorSysId: '',
dataRule: '', dataRule: '',
deviceName: '', deviceName: '',
chnNum: '', chnNum: ''
}) })
// 原始误差体系id // 原始误差体系id
let originErrorSysId: string = '' let originErrorSysId: string = ''
@@ -161,7 +204,7 @@ const currentCheckItem = ref<any>()
// 检测项列表 // 检测项列表
// const checkList = reactive<{ value: string, label: string }[]>([]) // const checkList = reactive<{ value: string, label: string }[]>([])
// 带有层级的检测项列表 // 带有层级的检测项列表
const checkListLevel = reactive<{ value: string, label: string, children: { value: string, label: string }[] }[]>([]) const checkListLevel = reactive<{ value: string; label: string; children: { value: string; label: string }[] }[]>([])
let deviceId: string = '' let deviceId: string = ''
let originScriptType: string | null = null let originScriptType: string | null = null
@@ -170,7 +213,6 @@ let scriptType: string | null = null
// 通道下拉列表 // 通道下拉列表
let chnList: any[] = [] let chnList: any[] = []
// 左侧树数据 // 左侧树数据
const treeDataAll = reactive<CheckData.TreeItem[]>([]) const treeDataAll = reactive<CheckData.TreeItem[]>([])
@@ -180,12 +222,15 @@ const checkIndex = ref<string>('')
// 当前检测项目名称 // 当前检测项目名称
const currentScriptTypeName = ref('') const currentScriptTypeName = ref('')
// 当前检测项目描述 // 当前检测项目描述
const currentDesc = ref(''); const currentDesc = ref('')
// 右侧Tab选中项 // 右侧Tab选中项
const activeTab = ref<string>('resultTab') const activeTab = ref<string>('resultTab')
//存放相应的表格数据 //存放相应的表格数据
const resTableData = reactive<{ resultData: Map<string, any>, rawData: Map<string, any> }>({resultData: new Map(), rawData: new Map()}) const resTableData = reactive<{ resultData: Map<string, any>; rawData: Map<string, any> }>({
resultData: new Map(),
rawData: new Map()
})
// 检测结果表格数据 // 检测结果表格数据
const checkResultData = reactive<CheckData.CheckResult[]>([]) const checkResultData = reactive<CheckData.CheckResult[]>([])
@@ -194,7 +239,6 @@ const popoverWidth: ComputedRef<string> = computed(() => {
return `${1140 - (currentScriptTypeName.value.length + 7 + 3) * 14 - (checkListLevel.length ? 280 : 0)}px` return `${1140 - (currentScriptTypeName.value.length + 7 + 3) * 14 - (checkListLevel.length ? 280 : 0)}px`
}) })
// 原始数据表格数据 // 原始数据表格数据
const rawTableData = reactive<CheckData.RawDataItem[]>([]) const rawTableData = reactive<CheckData.RawDataItem[]>([])
@@ -214,28 +258,28 @@ const handleNodeClick = async (data: any) => {
currentDesc.value = data.sourceDesc currentDesc.value = data.sourceDesc
scriptType = data.scriptType ?? scriptType scriptType = data.scriptType ?? scriptType
console.log("点击左侧树节点触发事件handleNodeClick", checkIndex.value) console.log('点击左侧树节点触发事件handleNodeClick', checkIndex.value)
if (checkIndex.value !== '') { if (checkIndex.value !== '') {
await updateTableData() await updateTableData()
activeTab.value = 'resultTab' activeTab.value = 'resultTab'
} }
} }
}; }
const handleErrorSysChange = async () => { const handleErrorSysChange = async () => {
console.log("切换误差体系", formContent.errorSysId); console.log('切换误差体系', formContent.errorSysId)
changeErrorSystem({ changeErrorSystem({
planId: checkStore.plan.id, planId: checkStore.plan.id,
scriptId: checkStore.plan.scriptId, scriptId: checkStore.plan.scriptId,
errorSysId: formContent.errorSysId, errorSysId: formContent.errorSysId,
deviceId: deviceId, deviceId: deviceId,
code: checkStore.plan.code + '', code: checkStore.plan.code + '',
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '', patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
}).then((res) => { }).then(res => {
if (res.code === ResultEnum.SUCCESS) { if (res.code === ResultEnum.SUCCESS) {
ElMessage.success('切换误差体系成功') ElMessage.success('切换误差体系成功')
if (originErrorSysId != formContent.errorSysId) { if (originErrorSysId != formContent.errorSysId) {
planCode = checkStore.plan.code + "_temp" planCode = checkStore.plan.code + '_temp'
} else { } else {
planCode = checkStore.plan.code + '' planCode = checkStore.plan.code + ''
} }
@@ -248,16 +292,18 @@ const handleErrorSysChange = async () => {
}) })
} }
watch(
watch(() => formContent.chnNum, async (newVal, oldVal) => { () => formContent.chnNum,
async (newVal, oldVal) => {
// console.log("通道号", newVal); // console.log("通道号", newVal);
if (newVal != '') { if (newVal != '') {
handleChnNumChange() handleChnNumChange()
} }
}) }
)
const handleChnNumChange = async () => { const handleChnNumChange = async () => {
console.log("通道号", formContent.chnNum); console.log('通道号', formContent.chnNum)
// 发起请求,查询该测试项的检测结果 // 发起请求,查询该测试项的检测结果
const { data: resTreeDataTemp }: { data: CheckData.TreeItem[] } = await getTreeData({ const { data: resTreeDataTemp }: { data: CheckData.TreeItem[] } = await getTreeData({
scriptId: checkStore.plan.scriptId, scriptId: checkStore.plan.scriptId,
@@ -278,14 +324,13 @@ const handleChnNumChange = async () => {
activeTab.value = 'resultTab' activeTab.value = 'resultTab'
} }
watch(currentCheckItem, (newVal, oldVal) => { watch(currentCheckItem, (newVal, oldVal) => {
if (newVal !== '') { if (newVal !== '') {
let key = newVal[0] let key = newVal[0]
if (newVal.length == 2) { if (newVal.length == 2) {
key += "_" + newVal[1] key += '_' + newVal[1]
} }
console.log("当前检测项", key); console.log('当前检测项', key)
doCurrentCheckItemUpdate(key) doCurrentCheckItemUpdate(key)
} else { } else {
activeTab.value = 'resultTab' activeTab.value = 'resultTab'
@@ -302,7 +347,7 @@ const defaultOperate = () => {
checkIndex.value = node.index checkIndex.value = node.index
defaultExpandedKeys = [node.index] defaultExpandedKeys = [node.index]
treeRef.value?.setCurrentKey(node.index); treeRef.value?.setCurrentKey(node.index)
scriptType = node.scriptType ?? scriptType scriptType = node.scriptType ?? scriptType
} else { } else {
currentScriptTypeName.value = '' currentScriptTypeName.value = ''
@@ -313,9 +358,8 @@ const defaultOperate = () => {
} }
const updateTableData = async () => { const updateTableData = async () => {
console.log("左侧树被选中的叶子节点checkIndex", checkIndex.value); console.log('左侧树被选中的叶子节点checkIndex', checkIndex.value)
if (checkIndex.value !== '') { if (checkIndex.value !== '') {
checkListLevel.length = 0 checkListLevel.length = 0
checkResultData.length = 0 checkResultData.length = 0
rawTableData.length = 0 rawTableData.length = 0
@@ -329,7 +373,7 @@ const updateTableData = async () => {
devId: deviceId, devId: deviceId,
devNum: formContent.chnNum + '', devNum: formContent.chnNum + '',
code: planCode, code: planCode,
index: parseInt(checkIndex.value), index: parseInt(checkIndex.value)
}) })
let keys1 = Object.keys(data.resultData) let keys1 = Object.keys(data.resultData)
@@ -340,13 +384,27 @@ const updateTableData = async () => {
if ((key.includes('谐波') || key.includes('简谐波')) && key !== '谐波有功功率') { if ((key.includes('谐波') || key.includes('简谐波')) && key !== '谐波有功功率') {
for (let item of data.resultData[key]) { for (let item of data.resultData[key]) {
let num = formatHarmNum(item.harmNum + '') let num = formatHarmNum(item.harmNum + '')
label = item.isData === 1 ? `${num}` : item.isData === 4 ? `${num}/` : item.isData === 5 ? `${num}-` : `${num}(不符合)` label =
item.isData === 1
? `${num}`
: item.isData === 4
? `${num}/`
: item.isData === 5
? `${num}-`
: `${num}(不符合)`
children.push({ label: label, value: num }) children.push({ label: label, value: num })
resultData.set(key + "_" + num, item) resultData.set(key + '_' + num, item)
} }
checkListLevel.push({ label: key, value: key, children: children }) checkListLevel.push({ label: key, value: key, children: children })
} else { } else {
label = data.resultData[key][0].isData === 1 ? `${key}` : data.resultData[key][0].isData === 4 ? `${key}/` : data.resultData[key][0].isData === 5 ? `${key}-` : `${key}(不符合)` label =
data.resultData[key][0].isData === 1
? `${key}`
: data.resultData[key][0].isData === 4
? `${key}/`
: data.resultData[key][0].isData === 5
? `${key}-`
: `${key}(不符合)`
resultData.set(key, data.resultData[key][0]) resultData.set(key, data.resultData[key][0])
checkListLevel.push({ label: label, value: key, children: [] }) checkListLevel.push({ label: label, value: key, children: [] })
let temp = checkListLevel.find(item => item.label.includes('电压幅值')) let temp = checkListLevel.find(item => item.label.includes('电压幅值'))
@@ -357,16 +415,15 @@ const updateTableData = async () => {
} }
} }
let keys2 = Object.keys(data.rawData) let keys2 = Object.keys(data.rawData)
let rawData = new Map() let rawData = new Map()
for (let key of keys2) { for (let key of keys2) {
if ((key.includes('谐波') || key.includes('简谐波')) && key !== '谐波有功功率') { if ((key.includes('谐波') || key.includes('简谐波')) && key !== '谐波有功功率') {
for (let item of data.rawData[key]) { for (let item of data.rawData[key]) {
let num = formatHarmNum(item.harmNum + '') let num = formatHarmNum(item.harmNum + '')
let value = rawData.get(key + "_" + num) let value = rawData.get(key + '_' + num)
if (!value) { if (!value) {
rawData.set(key + "_" + num, [item]) rawData.set(key + '_' + num, [item])
} else { } else {
value.push(item) value.push(item)
} }
@@ -376,7 +433,6 @@ const updateTableData = async () => {
} }
} }
resTableData.resultData = resultData resTableData.resultData = resultData
resTableData.rawData = rawData resTableData.rawData = rawData
@@ -389,8 +445,6 @@ const updateTableData = async () => {
currentCheckItem.value = [checkListLevel[0].value + ''] currentCheckItem.value = [checkListLevel[0].value + '']
} }
} }
} else { } else {
checkResultData.length = 0 checkResultData.length = 0
rawTableData.length = 0 rawTableData.length = 0
@@ -425,7 +479,7 @@ const open = async (_deviceId: string, chnNum: string, _scriptType: string | nul
scriptType scriptType
}) })
chnList = resFormContent.chnList.map((item: { value: string, label: string }) => ({ chnList = resFormContent.chnList.map((item: { value: string; label: string }) => ({
value: item.value, value: item.value,
label: item.value label: item.value
//label: item.label == '1' ? `${item.value}` : item.label == '2' ? `${item.value}(不符合)` : `${item.value}` //label: item.label == '1' ? `${item.value}` : item.label == '2' ? `${item.value}(不符合)` : `${item.value}`
@@ -433,7 +487,7 @@ const open = async (_deviceId: string, chnNum: string, _scriptType: string | nul
Object.assign(formContent, { Object.assign(formContent, {
...resFormContent, ...resFormContent,
chnNum: chnList.length > 0 ? chnList[0].value : '', chnNum: chnList.length > 0 ? chnList[0].value : ''
}) })
originErrorSysId = formContent.errorSysId originErrorSysId = formContent.errorSysId
@@ -441,11 +495,16 @@ const open = async (_deviceId: string, chnNum: string, _scriptType: string | nul
let { data: resPqErrorList } = await getPqErrSysList() let { data: resPqErrorList } = await getPqErrSysList()
Object.assign(pqErrorList, resPqErrorList) Object.assign(pqErrorList, resPqErrorList)
visible.value = true; visible.value = true
} }
const handleGenerateReport = async () => { const handleGenerateReport = async () => {
await generateDevReport({'planId': checkStore.plan.id, 'devIdList': [deviceId], 'scriptId': checkStore.plan.scriptId, 'planCode': planCode}) await generateDevReport({
planId: checkStore.plan.id,
devIdList: [deviceId],
scriptId: checkStore.plan.scriptId,
planCode: planCode
})
ElMessage.success({ message: `报告生成成功!` }) ElMessage.success({ message: `报告生成成功!` })
} }
@@ -456,8 +515,8 @@ const handleReCalculate = async () => {
errorSysId: formContent.errorSysId, errorSysId: formContent.errorSysId,
deviceId: deviceId, deviceId: deviceId,
code: checkStore.plan.code + '', code: checkStore.plan.code + '',
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '', patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
}).then((res) => { }).then(res => {
ElMessage.success('重新计算成功!') ElMessage.success('重新计算成功!')
// if (originErrorSysId != formContent.errorSysId) { // if (originErrorSysId != formContent.errorSysId) {
// planCode = checkStore.plan.code + "_temp" // planCode = checkStore.plan.code + "_temp"
@@ -479,7 +538,7 @@ const close = async () => {
errorSysName: '', errorSysName: '',
dataRule: '', dataRule: '',
deviceName: '', deviceName: '',
chnNum: '', chnNum: ''
}) })
treeDataAll.length = 0 treeDataAll.length = 0
// harmNumList.length = 0 // harmNumList.length = 0
@@ -496,12 +555,12 @@ const close = async () => {
pqErrorList.length = 0 pqErrorList.length = 0
planCode = '' planCode = ''
visible.value = false; visible.value = false
if (checkStore.showDetailType === 1) { if (checkStore.showDetailType === 1) {
await deleteTempTable(checkStore.plan.code + '') await deleteTempTable(checkStore.plan.code + '')
} }
}; }
const setCheckResultData = (data: CheckData.ResCheckResult | null) => { const setCheckResultData = (data: CheckData.ResCheckResult | null) => {
let result: CheckData.CheckResult[] = [] let result: CheckData.CheckResult[] = []
@@ -538,7 +597,7 @@ const setCheckResultData = (data: CheckData.ResCheckResult | null) => {
maxError: data.radius, maxError: data.radius,
unit: data.unit, unit: data.unit,
result: data.isData, result: data.isData
}) })
} }
@@ -555,22 +614,28 @@ const setCheckResultData = (data: CheckData.ResCheckResult | null) => {
maxError: data.radius, maxError: data.radius,
unit: data.unit, unit: data.unit,
result: data.isData, result: data.isData
}) })
} }
Object.assign(checkResultData, result) Object.assign(checkResultData, result)
console.log("检测结果", checkResultData); console.log('检测结果', checkResultData)
} }
const exportRawDataHandler = () => { const exportRawDataHandler = () => {
useDownload(exportRawData, '原始数据', { useDownload(
exportRawData,
'原始数据',
{
scriptType, scriptType,
scriptId: checkStore.plan.scriptId, scriptId: checkStore.plan.scriptId,
devId: deviceId, devId: deviceId,
devNum: formContent.chnNum + '', devNum: formContent.chnNum + '',
code: checkStore.plan.code + '', code: checkStore.plan.code + '',
index: parseInt(checkIndex.value), index: parseInt(checkIndex.value)
}, false, '.xlsx') },
false,
'.xlsx'
)
} }
const formatHarmNum = (num: string) => { const formatHarmNum = (num: string) => {
@@ -596,7 +661,7 @@ const setRawData = (data: CheckData.RawDataItem[]) => {
}) })
rawTableData.length = 0 rawTableData.length = 0
Object.assign(rawTableData, data) Object.assign(rawTableData, data)
console.log("原始数据", rawTableData) console.log('原始数据', rawTableData)
} }
const dataToShow = (num: number): string => { const dataToShow = (num: number): string => {
if (num == null || num == undefined) { if (num == null || num == undefined) {
@@ -605,14 +670,13 @@ const dataToShow = (num: number): string => {
return num + '' return num + ''
} }
const numberToFixed = (num: number): string => { const numberToFixed = (num: number): string => {
if (num == null || num == undefined) { if (num == null || num == undefined) {
return '/' return '/'
} else { } else {
let result = num.toFixed(fixed) let result = num.toFixed(fixed)
if (result === "-0.0000") { if (result === '-0.0000') {
return result.replace(/-/g, "") return result.replace(/-/g, '')
} }
return result return result
} }
@@ -627,8 +691,8 @@ const stringToFixed = (str: string): string => {
return '/' return '/'
} else { } else {
let result = num.toFixed(fixed) let result = num.toFixed(fixed)
if (result === "-0.0000") { if (result === '-0.0000') {
return result.replace(/-/g, "") return result.replace(/-/g, '')
} }
return result return result
} }
@@ -644,30 +708,30 @@ const getError = (num1: number, num2: number): string => {
const toMaxErrorStr = (oldMaxErroe: any, unit: any) => { const toMaxErrorStr = (oldMaxErroe: any, unit: any) => {
let result = oldMaxErroe ?? '/' let result = oldMaxErroe ?? '/'
let idx = result.indexOf('~'); let idx = result.indexOf('~')
if (idx > 0) { if (idx > 0) {
let left = result.substring(0, idx) let left = result.substring(0, idx)
let right = result.substring(idx, result.length) let right = result.substring(idx, result.length)
result = left + unit + right + unit; result = left + unit + right + unit
} }
return result; return result
} }
const findFirstLeafNode = (node: any): any => { const findFirstLeafNode = (node: any): any => {
if (!node.children || node.children.length === 0) { if (!node.children || node.children.length === 0) {
return node; return node
} }
return findFirstLeafNode(node.children[0]); return findFirstLeafNode(node.children[0])
} }
const getDefaultNode = (data: any[]) => { const getDefaultNode = (data: any[]) => {
if (!data || data.length === 0) { if (!data || data.length === 0) {
return null; return null
} }
const firstElement = data[0]; const firstElement = data[0]
return findFirstLeafNode(firstElement); return findFirstLeafNode(firstElement)
} }
const toAngleLast = () => { const toAngleLast = () => {
@@ -702,7 +766,7 @@ const filter = (treeData: any[], fly: number) => {
filter(node.children, fly) filter(node.children, fly)
// 检查 children 是否被全部移除 // 检查 children 是否被全部移除
if (node.children.length === 0) { if (node.children.length === 0) {
treeData.splice(i, 1); treeData.splice(i, 1)
} }
} else { } else {
treeData.splice(i, 1) treeData.splice(i, 1)
@@ -719,34 +783,33 @@ const updateTreeFly = (treeData: any[], fly: number) => {
// 如果当前节点是叶子节点且 fly 字段等于 targetFly // 如果当前节点是叶子节点且 fly 字段等于 targetFly
if (!node.children || node.children.length === 0) { if (!node.children || node.children.length === 0) {
if (node.fly === targetFly) { if (node.fly === targetFly) {
node.fly = targetFly; // 确保叶子节点的 fly 字段被设置为 targetFly node.fly = targetFly // 确保叶子节点的 fly 字段被设置为 targetFly
return true; // 返回 true 表示找到并更新了 return true // 返回 true 表示找到并更新了
} }
return false; // 否则返回 false return false // 否则返回 false
} }
// 递归更新子节点 // 递归更新子节点
let updated = false; let updated = false
for (let child of node.children) { for (let child of node.children) {
if (recursiveUpdate(child, targetFly)) { if (recursiveUpdate(child, targetFly)) {
updated = true; updated = true
} }
} }
// 如果有子节点被更新了,则更新当前节点的 fly 字段 // 如果有子节点被更新了,则更新当前节点的 fly 字段
if (updated) { if (updated) {
node.fly = targetFly; node.fly = targetFly
} }
return updated; return updated
} }
for (let i = 0; i < treeData.length; i++) { for (let i = 0; i < treeData.length; i++) {
// 调用递归函数从根节点开始更新 // 调用递归函数从根节点开始更新
recursiveUpdate(treeData[i], fly); recursiveUpdate(treeData[i], fly)
} }
} }
defineExpose({ defineExpose({
open open
}) })
@@ -759,7 +822,6 @@ defineExpose({
overflow-y: hidden; overflow-y: hidden;
overflow-x: hidden; overflow-x: hidden;
.data-check-dialog { .data-check-dialog {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -74,8 +74,8 @@
* 3. 协议校验 - 进行ICD报告触发测试 * 3. 协议校验 - 进行ICD报告触发测试
* 4. 相序校验 - 判断装置接线是否正确 * 4. 相序校验 - 判断装置接线是否正确
*/ */
import {ElMessage, ElMessageBox} from "element-plus"; import { ElMessage, ElMessageBox } from 'element-plus'
import {defineExpose, ref, toRef, watch} from 'vue'; import { ref, toRef, watch } from 'vue'
// ==================== 日志数据存储 ==================== // ==================== 日志数据存储 ====================
// 各步骤的日志数据,用于在右侧折叠面板中显示实时日志 // 各步骤的日志数据,用于在右侧折叠面板中显示实时日志

View File

@@ -4,18 +4,27 @@
<div class="result-title"> <div class="result-title">
<el-row> <el-row>
<el-form-item label="检测脚本"> <el-form-item label="检测脚本">
<el-input v-model='testScriptName' :disabled="true"/> <el-input v-model="testScriptName" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="误差体系"> <el-form-item label="误差体系">
<el-input v-model='errorSysName' :disabled="true"/> <el-input v-model="errorSysName" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="数据原则"> <el-form-item label="数据原则">
<el-input v-model='dataRule' :disabled="true"/> <el-input v-model="dataRule" :disabled="true" />
</el-form-item> </el-form-item>
</el-row> </el-row>
</div> </div>
<div class="result-content"> <div class="result-content">
<el-table :data="resultData" stripe max-height="350" :header-cell-style="{ textAlign: 'center' } " :cell-style="{ textAlign: 'center' }" style="width: 100%" border v-on:cell-click="handleClick"> <el-table
:data="resultData"
stripe
max-height="350"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
style="width: 100%"
border
v-on:cell-click="handleClick"
>
<el-table-column prop="deviceName" label="被检设备" /> <el-table-column prop="deviceName" label="被检设备" />
<el-table-column prop="result_1" label="通道1" /> <el-table-column prop="result_1" label="通道1" />
<el-table-column prop="result_2" label="通道2" /> <el-table-column prop="result_2" label="通道2" />
@@ -23,9 +32,7 @@
<el-table-column prop="result_4" label="通道4" /> <el-table-column prop="result_4" label="通道4" />
</el-table> </el-table>
</div> </div>
<div class="result-footer"> <div class="result-footer">你可以停留在本页查看数据或返回首页进行复检报告生成和归档</div>
你可以停留在本页查看数据或返回首页进行复检报告生成和归档
</div>
</div> </div>
<DataCheckPopup <DataCheckPopup
:visible="DataCheckDialogVisible" :visible="DataCheckDialogVisible"
@@ -35,65 +42,57 @@
</template> </template>
<script lang="ts" setup name="testPopup"> <script lang="ts" setup name="testPopup">
import{ElMessage, ElSelectV2, FormInstance,FormItemRule}from'element-plus' import { ref } from 'vue'
import { defineProps, defineEmits, reactive,watch,ref, Ref } from 'vue'; import { dialogBig } from '@/utils/elementBind'
import { dialogBig,dialogMiddle} from '@/utils/elementBind'
//import IndicatorTypeDialog from "@/views/machine/errorSystem/components/IndicatorTypeDialog.vue"; // 导入子组件 //import IndicatorTypeDialog from "@/views/machine/errorSystem/components/IndicatorTypeDialog.vue"; // 导入子组件
import {CirclePlus, Delete, EditPen,FolderOpened,CopyDocument,Edit, Picture, UploadFilled, SuccessFilled,VideoPlay,Right,Refresh,Close} from '@element-plus/icons-vue' import DataCheckPopup from './dataCheckPopup.vue'
import { useDictStore } from '@/stores/modules/dict'
import preTest from './preTest.vue'
import timeTest from './timeTest.vue'
import DataCheckPopup from './dataCheckPopup.vue';
import { log } from 'console';
const props = defineProps<{ const props = defineProps<{
visible: boolean; visible: boolean
}>(); }>()
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:visible', value: boolean): void; (e: 'update:visible', value: boolean): void
(e: 'submit', data: any): void; (e: 'submit', data: any): void
}>(); }>()
const testScriptName = ref('Q/GDW 10650.4-2021 模拟式'); const testScriptName = ref('Q/GDW 10650.4-2021 模拟式')
const errorSysName = ref('Q/GDW 10650.2-2021'); const errorSysName = ref('Q/GDW 10650.2-2021')
const dataRule = ref('所有值'); const dataRule = ref('所有值')
const DataCheckDialogVisible = ref(false); const DataCheckDialogVisible = ref(false)
const resultData = ref([ const resultData = ref([
{ {
deviceName: "被检设备1", deviceName: '被检设备1',
result_1: "合格", result_1: '合格',
result_2: "合格", result_2: '合格',
result_3: "合格", result_3: '合格',
result_4: "合格", result_4: '合格'
}, },
{ {
deviceName: "被检设备2", deviceName: '被检设备2',
result_1: "合格", result_1: '合格',
result_2: "合格", result_2: '合格',
result_3: "—", result_3: '—',
result_4: "—", result_4: '—'
}, },
{ {
deviceName: "被检设备3", deviceName: '被检设备3',
result_1: "不合格", result_1: '不合格',
result_2: "合格", result_2: '合格',
result_3: "—", result_3: '—',
result_4: "—", result_4: '—'
}, }
]); ])
const handleClick = (row: any) => { const handleClick = (row: any) => {
console.log(111) console.log(111)
DataCheckDialogVisible.value = true; DataCheckDialogVisible.value = true
}; }
const handleCancel = () => { const handleCancel = () => {
emit('update:visible', false); // 关闭对话框 emit('update:visible', false) // 关闭对话框
}; }
</script> </script>
<style scoped> <style scoped>

View File

@@ -1,117 +1,155 @@
<template> <template>
<!-- 检测流程弹窗容器 --> <!-- 检测流程弹窗容器 -->
<el-dialog :title='dialogTitle' width='1550px' :model-value='dialogVisible' :before-close='beforeClose' <el-dialog
@close='handleClose' height='1000px' draggable> :title="dialogTitle"
width="1550px"
:model-value="dialogVisible"
:before-close="beforeClose"
@close="handleClose"
height="1000px"
draggable
>
<!-- 步骤指示器容器 --> <!-- 步骤指示器容器 -->
<div class='steps-container'> <div class="steps-container">
<!-- 检测步骤进度条根据选择的检测项动态显示步骤 --> <!-- 检测步骤进度条根据选择的检测项动态显示步骤 -->
<!-- 注意Element Plus的active属性从0开始但业务逻辑从1开始所以需要减1 --> <!-- 注意Element Plus的active属性从0开始但业务逻辑从1开始所以需要减1 -->
<el-steps v-if='showSteps' class='test-head-steps' simple :active='stepsActiveIndex - 1' process-status='finish' <el-steps
finish-status='success'> v-if="showSteps"
class="test-head-steps"
simple
:active="stepsActiveIndex - 1"
process-status="finish"
finish-status="success"
>
<!-- 预检测步骤 --> <!-- 预检测步骤 -->
<el-step v-if='preTestSelected' title='预检测' <el-step
:icon='stepsActive > 1 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Edit' v-if="preTestSelected"
@click='handleStepClick(1)' /> title="预检测"
:icon="stepsActive > 1 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Edit"
@click="handleStepClick(1)"
/>
<!-- 守时检测步骤 --> <!-- 守时检测步骤 -->
<el-step v-if='timeTestSelected' title='守时检测' <el-step
:icon='stepsActive > 2 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :UploadFilled' v-if="timeTestSelected"
@click='handleStepClick(2)' /> title="守时检测"
:icon="stepsActive > 2 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : UploadFilled"
@click="handleStepClick(2)"
/>
<!-- 系数校准步骤 --> <!-- 系数校准步骤 -->
<el-step v-if='channelsTestSelected' title='系数校准' <el-step
:icon='stepsActive > 3 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Odometer' v-if="channelsTestSelected"
@click='handleStepClick(3)' /> title="系数校准"
:icon="stepsActive > 3 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Odometer"
@click="handleStepClick(3)"
/>
<!-- 正式检测步骤 --> <!-- 正式检测步骤 -->
<el-step v-if='testSelected' title='正式检测' <el-step
:icon='stepsActive > 4 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Coin' v-if="testSelected"
@click='handleStepClick(4)' /> title="正式检测"
:icon="stepsActive > 4 || stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Coin"
@click="handleStepClick(4)"
/>
<!-- 检测完成步骤 --> <!-- 检测完成步骤 -->
<el-step title='检测完成' :icon='stepsActiveIndex > stepsTotalNum-1 ? SuccessFilled :Key' /> <el-step title="检测完成" :icon="stepsActiveIndex > stepsTotalNum - 1 ? SuccessFilled : Key" />
</el-steps> </el-steps>
</div> </div>
<!-- 检测组件容器 - 根据当前步骤显示对应的检测组件 --> <!-- 检测组件容器 - 根据当前步骤显示对应的检测组件 -->
<!-- 预检测组件 --> <!-- 预检测组件 -->
<preTest v-if='showComponent&&preTestSelected' v-show='preTestSelected && stepsActiveView==1' ref='preTestRef' <preTest
v-model:testStatus='preTestStatus' v-if="showComponent && preTestSelected"
:webMsgSend='webMsgSend' /> v-show="preTestSelected && stepsActiveView == 1"
ref="preTestRef"
v-model:testStatus="preTestStatus"
:webMsgSend="webMsgSend"
/>
<!-- 守时检测组件 --> <!-- 守时检测组件 -->
<timeTest v-if='showComponent&&timeTestSelected' v-show='timeTestSelected && stepsActiveView==2' <timeTest
v-model:testStatus='timeTestStatus' /> v-if="showComponent && timeTestSelected"
v-show="timeTestSelected && stepsActiveView == 2"
v-model:testStatus="timeTestStatus"
/>
<!-- 系数校准检测组件 --> <!-- 系数校准检测组件 -->
<factorTest v-if='showComponent&&channelsTestSelected' v-show='channelsTestSelected && stepsActiveView==3' <factorTest
v-model:testStatus='channelsTestStatus' v-if="showComponent && channelsTestSelected"
:webMsgSend='webMsgSend' /> v-show="channelsTestSelected && stepsActiveView == 3"
v-model:testStatus="channelsTestStatus"
:webMsgSend="webMsgSend"
/>
<!-- 正式检测组件 --> <!-- 正式检测组件 -->
<test v-if='showComponent&&testSelected' ref='testRef' v-show='testSelected && stepsActiveView==4' <test
v-model:testStatus='TestStatus' :webMsgSend='webMsgSend' v-if="showComponent && testSelected"
@update:webMsgSend='webMsgSend=$event' @sendPause='sendPause' @sendResume='sendResume' ref="testRef"
@closeWebSocket='closeWebSocket' v-show="testSelected && stepsActiveView == 4"
:stepsActive='stepsActive' /> v-model:testStatus="TestStatus"
:webMsgSend="webMsgSend"
@update:webMsgSend="webMsgSend = $event"
@sendPause="sendPause"
@sendResume="sendResume"
@closeWebSocket="closeWebSocket"
:stepsActive="stepsActive"
/>
<!-- 弹窗底部操作按钮区域 --> <!-- 弹窗底部操作按钮区域 -->
<template #footer> <template #footer>
<div> <div>
<!-- 开始检测按钮 - 当前状态为等待时显示 --> <!-- 开始检测按钮 - 当前状态为等待时显示 -->
<el-button type='primary' :icon='VideoPlay' v-if="ActiveStatue === 'waiting'" @click='handleSubmitFast'> <el-button type="primary" :icon="VideoPlay" v-if="ActiveStatue === 'waiting'" @click="handleSubmitFast">
开始检测 开始检测
</el-button> </el-button>
<!-- 初始化中按钮 - 禁用状态显示加载动画 --> <!-- 初始化中按钮 - 禁用状态显示加载动画 -->
<el-button type='primary' v-if="TestStatus === 'test_init'" disabled> <el-button type="primary" v-if="TestStatus === 'test_init'" disabled>
<el-icon class='loading-box' style='color: #fff;margin-right: 8px;'> <el-icon class="loading-box" style="color: #fff; margin-right: 8px">
<component :is='Refresh' /> <component :is="Refresh" />
</el-icon> </el-icon>
初始化中 初始化中
</el-button> </el-button>
<!-- 停止检测按钮 - 检测进行中时显示 --> <!-- 停止检测按钮 - 检测进行中时显示 -->
<el-button <el-button type="primary" v-if="TestStatus == 'process'" :icon="VideoPause" @click="handlePause()">
type='primary' 停止检测
v-if="TestStatus=='process'"
:icon='VideoPause'
@click='handlePause()'>停止检测
</el-button> </el-button>
<!-- 暂停中按钮 - 禁用状态显示加载动画 --> <!-- 暂停中按钮 - 禁用状态显示加载动画 -->
<el-button type='warning' v-if="TestStatus === 'paused_ing'" disabled> <el-button type="warning" v-if="TestStatus === 'paused_ing'" disabled>
<el-icon class='loading-box' style='color: #fff;margin-right: 8px;'> <el-icon class="loading-box" style="color: #fff; margin-right: 8px">
<component :is='Refresh' /> <component :is="Refresh" />
</el-icon> </el-icon>
暂停中 暂停中
</el-button> </el-button>
<!-- 继续检测按钮 - 检测已暂停时显示 --> <!-- 继续检测按钮 - 检测已暂停时显示 -->
<el-button <el-button type="warning" v-if="TestStatus == 'paused'" :icon="VideoPlay" @click="sendResume">
type='warning' 继续检测
v-if="(TestStatus =='paused')"
:icon='VideoPlay'
@click='sendResume'
>继续检测
</el-button> </el-button>
<!-- 下一步/完成/错误状态按钮 --> <!-- 下一步/完成/错误状态按钮 -->
<el-button :type="ActiveStatue==='success'?'primary':'danger'" :icon='Right' <el-button
v-if="nextStepText !== '下一步' && (ActiveStatue === 'success'||ActiveStatue==='error'||ActiveStatue==='connect_timeout'||ActiveStatue==='pause_timeout')" :type="ActiveStatue === 'success' ? 'primary' : 'danger'"
@click='nextStep'> :icon="Right"
v-if="
nextStepText !== '下一步' &&
(ActiveStatue === 'success' ||
ActiveStatue === 'error' ||
ActiveStatue === 'connect_timeout' ||
ActiveStatue === 'pause_timeout')
"
@click="nextStep"
>
{{ nextStepText }} {{ nextStepText }}
</el-button> </el-button>
<!-- 退出检测按钮 - 默认显示 --> <!-- 退出检测按钮 - 默认显示 -->
<el-button type='primary' @click='handleQuit' v-else> <el-button type="primary" @click="handleQuit" v-else>退出检测</el-button>
退出检测
</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang='tsx' setup name='testPopup'> <script lang="tsx" setup name="testPopup">
// ====================== 导入依赖 ====================== // ====================== 导入依赖 ======================
import { reactive, ref, watch, onBeforeUnmount } from 'vue' import { onBeforeUnmount, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { import {
Coin, Coin,
@@ -123,7 +161,7 @@ import {
SuccessFilled, SuccessFilled,
UploadFilled, UploadFilled,
VideoPause, VideoPause,
VideoPlay, VideoPlay
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import preTest from './preTest.vue' import preTest from './preTest.vue'
import timeTest from './timeTest.vue' import timeTest from './timeTest.vue'
@@ -166,7 +204,7 @@ const webMsgSend = ref() // webSocket推送的数据用于组件间通信
const dataSocket = reactive<{ const dataSocket = reactive<{
socketServe: typeof socketClient.Instance | null socketServe: typeof socketClient.Instance | null
}>({ }>({
socketServe: socketClient.Instance, // WebSocket客户端实例 socketServe: socketClient.Instance // WebSocket客户端实例
}) })
// ====================== 检测项选择状态 ====================== // ====================== 检测项选择状态 ======================
@@ -262,7 +300,7 @@ const open = (title: string) => {
dataSocket.socketServe = socketClient.Instance dataSocket.socketServe = socketClient.Instance
// 注册新的回调 // 注册新的回调
dataSocket.socketServe.registerCallBack('aaa', (res) => { dataSocket.socketServe.registerCallBack('aaa', res => {
// 将接收到的数据传递给子组件 // 将接收到的数据传递给子组件
webMsgSend.value = res webMsgSend.value = res
}) })
@@ -278,7 +316,7 @@ const open = (title: string) => {
*/ */
const handleSubmitFast = () => { const handleSubmitFast = () => {
// 获取设备ID列表和计划ID // 获取设备ID列表和计划ID
let deviceIds = checkStore.devices.map((item) => item.deviceId) let deviceIds = checkStore.devices.map(item => item.deviceId)
let planId = checkStore.plan.id let planId = checkStore.plan.id
// 检查WebSocket连接状态 // 检查WebSocket连接状态
@@ -303,12 +341,16 @@ const handleSubmitFast = () => {
userId: userStore.userInfo.id, userId: userStore.userInfo.id,
temperature: checkStore.temperature, temperature: checkStore.temperature,
humidity: checkStore.humidity, humidity: checkStore.humidity,
testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test], testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => { }).then(res => {
if (res.code !== 'A0000') { if (res.code !== 'A0000') {
ElMessageBox.alert('预检测失败', '检测失败', { ElMessageBox.alert('预检测失败', '检测失败', {
confirmButtonText: '确定', confirmButtonText: '确定',
type: 'error', type: 'error'
}) })
preTestStatus.value = 'error' preTestStatus.value = 'error'
} }
@@ -332,12 +374,16 @@ const handleSubmitFast = () => {
userId: userStore.userInfo.id, userId: userStore.userInfo.id,
temperature: checkStore.temperature, temperature: checkStore.temperature,
humidity: checkStore.humidity, humidity: checkStore.humidity,
testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test], testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => { }).then(res => {
if (res.code !== 'A0000') { if (res.code !== 'A0000') {
ElMessageBox.alert('系数校准失败', '检测失败', { ElMessageBox.alert('系数校准失败', '检测失败', {
confirmButtonText: '确定', confirmButtonText: '确定',
type: 'error', type: 'error'
}) })
channelsTestStatus.value = 'error' channelsTestStatus.value = 'error'
} }
@@ -349,7 +395,11 @@ const handleSubmitFast = () => {
case 4: // 正式检测步骤 case 4: // 正式检测步骤
if (TestStatus.value == 'waiting') { if (TestStatus.value == 'waiting') {
// 如果没有预检测和系数校准,直接进行正式检测需要先初始化 // 如果没有预检测和系数校准,直接进行正式检测需要先初始化
if (!checkStore.selectTestItems.preTest && !checkStore.selectTestItems.channelsTest && checkStore.selectTestItems.test) { if (
!checkStore.selectTestItems.preTest &&
!checkStore.selectTestItems.channelsTest &&
checkStore.selectTestItems.test
) {
startPreTest({ startPreTest({
userPageId: JwtUtil.getLoginName(), userPageId: JwtUtil.getLoginName(),
devIds: deviceIds, devIds: deviceIds,
@@ -358,12 +408,16 @@ const handleSubmitFast = () => {
userId: userStore.userInfo.id, userId: userStore.userInfo.id,
temperature: checkStore.temperature, temperature: checkStore.temperature,
humidity: checkStore.humidity, humidity: checkStore.humidity,
testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test], testItemList: [
checkStore.selectTestItems.preTest,
checkStore.selectTestItems.channelsTest,
checkStore.selectTestItems.test
]
}).then(res => { }).then(res => {
if (res.code !== 'A0000') { if (res.code !== 'A0000') {
ElMessageBox.alert('正式检测失败', '检测失败', { ElMessageBox.alert('正式检测失败', '检测失败', {
confirmButtonText: '确定', confirmButtonText: '确定',
type: 'error', type: 'error'
}) })
TestStatus.value = 'error' TestStatus.value = 'error'
} }
@@ -380,10 +434,9 @@ const handleSubmitFast = () => {
} }
} }
// ====================== 事件定义 ====================== // ====================== 事件定义 ======================
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'quitClicked'): void; // 退出检测事件 (e: 'quitClicked'): void // 退出检测事件
}>() }>()
// ====================== 状态监听器 ====================== // ====================== 状态监听器 ======================
@@ -504,17 +557,17 @@ const sendResume = () => {
// 调用继续检测API // 调用继续检测API
resumeTest({ resumeTest({
userPageId: JwtUtil.getLoginName(), userPageId: JwtUtil.getLoginName(),
devIds: checkStore.devices.map((item) => item.deviceId), devIds: checkStore.devices.map(item => item.deviceId),
planId: checkStore.plan.id, planId: checkStore.plan.id,
reCheckType: '2', // 操作类型0-系数校验1-预检测2-正式检测8-不合格项复检 reCheckType: '2', // 操作类型0-系数校验1-预检测2-正式检测8-不合格项复检
userId: userStore.userInfo.id, userId: userStore.userInfo.id,
temperature: checkStore.temperature, temperature: checkStore.temperature,
humidity: checkStore.humidity, humidity: checkStore.humidity
}) })
// 发送继续成功消息给子组件 // 发送继续成功消息给子组件
Object.assign(webMsgSend.value, { Object.assign(webMsgSend.value, {
requestId: 'Resume_Success', requestId: 'Resume_Success'
}) })
} }
@@ -548,7 +601,12 @@ const closeWebSocket = () => {
*/ */
const nextStep = () => { const nextStep = () => {
// 如果已到最后或遇到错误状态,直接关闭弹窗 // 如果已到最后或遇到错误状态,直接关闭弹窗
if (stepsActiveIndex.value == stepsTotalNum.value + 1 || ActiveStatue.value === 'error' || ActiveStatue.value === 'connect_timeout' || ActiveStatue.value === 'pause_timeout') { if (
stepsActiveIndex.value == stepsTotalNum.value + 1 ||
ActiveStatue.value === 'error' ||
ActiveStatue.value === 'connect_timeout' ||
ActiveStatue.value === 'pause_timeout'
) {
handleClose() handleClose()
return return
} }
@@ -562,13 +620,19 @@ const nextStep = () => {
// 遍历检测项,找到下一个需要执行的步骤 // 遍历检测项,找到下一个需要执行的步骤
for (let selectTestItemsKey in checkStore.selectTestItems) { for (let selectTestItemsKey in checkStore.selectTestItems) {
if (tempStep == 0 && checkStore.selectTestItems[selectTestItemsKey as keyof typeof checkStore.selectTestItems]) { if (
tempStep == 0 &&
checkStore.selectTestItems[selectTestItemsKey as keyof typeof checkStore.selectTestItems]
) {
// 找到下一个要执行的检测项 // 找到下一个要执行的检测项
stepsActiveView.value = idx // 设置显示的组件 stepsActiveView.value = idx // 设置显示的组件
stepsActive.value = idx // 设置业务逻辑步骤 stepsActive.value = idx // 设置业务逻辑步骤
return return
} }
if (checkStore.selectTestItems[selectTestItemsKey as keyof typeof checkStore.selectTestItems] && tempStep != 0) { if (
checkStore.selectTestItems[selectTestItemsKey as keyof typeof checkStore.selectTestItems] &&
tempStep != 0
) {
tempStep-- // 跳过已选择的检测项 tempStep-- // 跳过已选择的检测项
} }
idx++ idx++
@@ -613,9 +677,8 @@ const beforeClose = () => {
ElMessageBox.confirm('检测未完成,是否退出当前检测流程?', '提示', { ElMessageBox.confirm('检测未完成,是否退出当前检测流程?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning', type: 'warning'
}, }).then(() => {
).then(() => {
handleClose() // 用户确认后关闭 handleClose() // 用户确认后关闭
}) })
} else { } else {
@@ -649,10 +712,9 @@ onBeforeUnmount(() => {
defineExpose({ open }) // 只暴露open方法供父组件调用 defineExpose({ open }) // 只暴露open方法供父组件调用
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
.test-head-steps { .test-head-steps {
::v-deep .el-step { :deep(.el-step) {
.el-step__head.is-success { .el-step__head.is-success {
color: #91cc75; color: #91cc75;
} }
@@ -705,6 +767,4 @@ defineExpose({ open }) // 只暴露open方法供父组件调用
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
</style> </style>

View File

@@ -1,61 +1,42 @@
<template> <template>
<el-form <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" size="large">
ref='loginFormRef' <el-form-item prop="username">
:model='loginForm' <el-input v-model="loginForm.username" placeholder="用户名">
:rules='loginRules'
size='large'
>
<el-form-item prop='username'>
<el-input v-model='loginForm.username' placeholder='用户名'>
<template #prefix> <template #prefix>
<el-icon class='el-input__icon'> <el-icon class="el-input__icon">
<user /> <user />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop='password'> <el-form-item prop="password">
<el-input <el-input
v-model='loginForm.password' v-model="loginForm.password"
type='password' type="password"
placeholder='密码' placeholder="密码"
show-password show-password
autocomplete='new-password' autocomplete="new-password"
> >
<template #prefix> <template #prefix>
<el-icon class='el-input__icon'> <el-icon class="el-input__icon">
<lock /> <lock />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop='checked'> <el-form-item prop="checked">
<el-checkbox v-model="loginForm.checked">记住我</el-checkbox> <el-checkbox v-model="loginForm.checked">记住我</el-checkbox>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class='login-btn'> <div class="login-btn">
<el-button <el-button :icon="UserFilled" round size="large" type="primary" :loading="loading" @click="login(loginFormRef)">
:icon='UserFilled'
round
size='large'
type='primary'
:loading='loading'
@click='login(loginFormRef)'
>
登录 登录
</el-button> </el-button>
<el-button <el-button :icon="CircleClose" round size="large" @click="resetForm(loginFormRef)">重置</el-button>
:icon='CircleClose'
round
size='large'
@click='resetForm(loginFormRef)'
>
重置
</el-button>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { HOME_URL } from '@/config' import { HOME_URL } from '@/config'
import { getTimeState } from '@/utils' import { getTimeState } from '@/utils'
@@ -70,7 +51,7 @@ import {useKeepAliveStore} from '@/stores/modules/keepAlive'
import { initDynamicRouter } from '@/routers/modules/dynamicRouter' import { initDynamicRouter } from '@/routers/modules/dynamicRouter'
import { CircleClose, UserFilled } from '@element-plus/icons-vue' import { CircleClose, UserFilled } from '@element-plus/icons-vue'
import { useAuthStore } from '@/stores/modules/auth' import { useAuthStore } from '@/stores/modules/auth'
import {useDictStore} from "@/stores/modules/dict"; import { useDictStore } from '@/stores/modules/dict'
import forge from 'node-forge' import forge from 'node-forge'
const authStore = useAuthStore() const authStore = useAuthStore()
@@ -80,39 +61,40 @@ const tabsStore = useTabsStore()
const keepAliveStore = useKeepAliveStore() const keepAliveStore = useKeepAliveStore()
const dictStore = useDictStore() const dictStore = useDictStore()
let publicKey: any = null; let publicKey: any = null
type FormInstance = InstanceType<typeof ElForm>
type FormInstance = InstanceType<typeof ElForm>;
const loginFormRef = ref<FormInstance>() const loginFormRef = ref<FormInstance>()
const loginRules = reactive({ const loginRules = reactive({
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{required: true, message: '请输入密码', trigger: 'blur'}], password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}) })
const loading = ref(false) const loading = ref(false)
const loginForm = reactive<Login.ReqLoginForm>({ const loginForm = reactive<Login.ReqLoginForm>({
username: '', username: '',
password: '', password: '',
checked: false, checked: false
}) })
// login // login
const login = (formEl: FormInstance | undefined) => { const login = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate(async (valid) => { formEl.validate(async valid => {
if (!valid) return if (!valid) return
loading.value = true loading.value = true
try { try {
let { data: publicKeyBase64 }: { data: string } = await getPublicKey(loginForm.username) let { data: publicKeyBase64 }: { data: string } = await getPublicKey(loginForm.username)
//将base64格式的公钥转换为Forge可以使用的格式 //将base64格式的公钥转换为Forge可以使用的格式
const publicKeyDer = forge.util.decode64(publicKeyBase64); const publicKeyDer = forge.util.decode64(publicKeyBase64)
publicKey = forge.pki.publicKeyFromPem(forge.pki.publicKeyToPem(forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyDer)))); publicKey = forge.pki.publicKeyFromPem(
forge.pki.publicKeyToPem(forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyDer)))
)
// 1.执行登录接口 // 1.执行登录接口
const { data } = await loginApi({ const { data } = await loginApi({
username: forge.util.encode64(loginForm.username), username: forge.util.encode64(loginForm.username),
password: encryptPassword(loginForm.password), password: encryptPassword(loginForm.password)
}) })
userStore.setAccessToken(data.accessToken) userStore.setAccessToken(data.accessToken)
userStore.setRefreshToken(data.refreshToken) userStore.setRefreshToken(data.refreshToken)
@@ -138,7 +120,7 @@ const login = (formEl: FormInstance | undefined) => {
title: getTimeState(), title: getTimeState(),
message: '登录成功', message: '登录成功',
type: 'success', type: 'success',
duration: 3000, duration: 3000
}) })
} finally { } finally {
loading.value = false loading.value = false
@@ -164,13 +146,12 @@ onMounted(() => {
}) })
const encryptPassword = (password: string) => { const encryptPassword = (password: string) => {
const encrypted = publicKey.encrypt(password, 'RSAES-PKCS1-V1_5'); const encrypted = publicKey.encrypt(password, 'RSAES-PKCS1-V1_5')
// 将加密后的数据转换为base64格式以便传输 // 将加密后的数据转换为base64格式以便传输
return forge.util.encode64(encrypted); return forge.util.encode64(encrypted)
} }
</script> </script>
<style scoped lang='scss'> <style scoped lang="scss">
@import "../index.scss"; @use '../index.scss';
</style> </style>

View File

@@ -18,11 +18,11 @@
</template> </template>
<script setup lang="ts" name="login"> <script setup lang="ts" name="login">
import LoginForm from "./components/LoginForm.vue"; import LoginForm from './components/LoginForm.vue'
const title = import.meta.env.VITE_GLOB_APP_TITLE;
const title = import.meta.env.VITE_GLOB_APP_TITLE
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "./index.scss"; @use './index.scss';
</style> </style>

View File

@@ -6,7 +6,7 @@
</div> </div>
<div class="data-check-content"> <div class="data-check-content">
<div class="content-tree"> <div class="content-tree">
<Tree ref="treeRef" :treeData="treeData" @setTab="setTab" /> <MachineTree ref="treeRef" :treeData="treeData" @setTab="setTab" />
</div> </div>
<div class="content-right-Tabs" style="height: calc(100vh - 315px); width: 100px"> <div class="content-right-Tabs" style="height: calc(100vh - 315px); width: 100px">
@@ -204,33 +204,22 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { type PropType, ref, nextTick, onMounted, watch } from 'vue' import { nextTick, onMounted, type PropType, ref, watch } from 'vue'
import Tree from './tree.vue' import MachineTree from './machineTree.vue'
import Commun from '@/views/machine/testScript/components//communication.vue' import Commun from '@/views/machine/testScript/components//communication.vue'
import { type CascaderOption, ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { getTreeData } from '@/api/check/test' import { getTreeData } from '@/api/check/test'
import { import { VideoPause, VideoPlay, View } from '@element-plus/icons-vue'
CirclePlus,
Delete,
Check,
CopyDocument,
View,
EditPen,
VideoPlay,
VideoPause,
Loading
} from '@element-plus/icons-vue'
import type { TestScript } from '@/api/device/interface/testScript' import type { TestScript } from '@/api/device/interface/testScript'
import TestProjectPopup from '@/views/machine/testScript/components/testProjectPopup.vue' import TestProjectPopup from '@/views/machine/testScript/components/testProjectPopup.vue'
import { CheckData } from '@/api/check/interface' import { CheckData } from '@/api/check/interface'
import { dlsDetails, deleteDtls, updateDtls, addScriptDtls, checkDataList } from '@/api/device/testScript' import { dlsDetails } from '@/api/device/testScript'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { useHandleData } from '@/hooks/useHandleData'
import { scriptDtlsCheckDataList } from '@/api/device/testScript/index'
import ViewRow from '@/views/machine/testScript/components/viewRow.vue' import ViewRow from '@/views/machine/testScript/components/viewRow.vue'
import { startSimulateTest, closeSimulateTest } from '@/api/device/controlSource/index.ts' import { closeSimulateTest, startSimulateTest } from '@/api/device/controlSource/index.ts'
import { controlSource } from '@/api/device/interface/controlSource' import { controlSource } from '@/api/device/interface/controlSource'
import {JwtUtil} from "@/utils/jwtUtil"; import { JwtUtil } from '@/utils/jwtUtil'
interface TabOption { interface TabOption {
label?: string label?: string
name?: string name?: string

View File

@@ -1,53 +1,80 @@
<!-- components/MonitorPointTable.vue --> <!-- components/MonitorPointTable.vue -->
<template> <template>
<div class='table-box'> <div class="table-box">
<ProTable <ProTable
ref='proTable' ref="proTable"
:pagination="false" :pagination="false"
:toolButton="false" :toolButton="false"
:columns='columns' :columns="columns"
:data="tableData" :data="tableData"
:style="{ height: tableHeight + 'px', overflow: 'hidden' }" :style="{ height: tableHeight + 'px', overflow: 'hidden' }"
> >
<!-- 表格 header 按钮 --> <!-- 表格 header 按钮 -->
<template #tableHeader='scope'> <template #tableHeader="scope">
<el-button type='primary' :icon='CirclePlus' @click="openDialog('add')" :disabled="props.DevFormContent.importFlag == 1">新增</el-button> <el-button
<el-button v-auth.device="'delete'" type='danger' :icon='Delete' plain :disabled='!scope.isSelected' type="primary"
@click='batchDelete(scope.selectedListIds)'> :icon="CirclePlus"
@click="openDialog('add')"
:disabled="props.DevFormContent.importFlag == 1"
>
新增
</el-button>
<el-button
v-auth.device="'delete'"
type="danger"
:icon="Delete"
plain
:disabled="!scope.isSelected"
@click="batchDelete(scope.selectedListIds)"
>
删除 删除
</el-button> </el-button>
</template> </template>
<!-- 表格操作 --> <!-- 表格操作 -->
<template #operation="scope"> <template #operation="scope">
<el-button v-auth.device="'edit'" type='primary' link :icon='EditPen' :model-value='false' :disabled="props.DevFormContent.importFlag == 1" <el-button
@click="openDialog('edit', scope.row)">编辑 v-auth.device="'edit'"
type="primary"
link
:icon="EditPen"
:model-value="false"
:disabled="props.DevFormContent.importFlag == 1"
@click="openDialog('edit', scope.row)"
>
编辑
</el-button> </el-button>
<el-button v-auth.device="'delete'" type='primary' link :icon='Delete' @click='handleDelete(scope.row.id)' >删除 <el-button
v-auth.device="'delete'"
type="primary"
link
:icon="Delete"
@click="handleDelete(scope.row.id)"
>
删除
</el-button> </el-button>
</template> </template>
</ProTable> </ProTable>
</div> </div>
<MonitorPopup @getParameter="getParameter" ref='monitorPopup'/> <MonitorPopup @getParameter="getParameter" ref="monitorPopup" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, defineProps, reactive, watch } from 'vue'; import { reactive, ref, watch } from 'vue'
import ProTable from '@/components/ProTable/index.vue'; // 假设 ProTable 是自定义组件 import ProTable from '@/components/ProTable/index.vue' // 假设 ProTable 是自定义组件
import { CirclePlus, Delete, EditPen, MessageBox } from '@element-plus/icons-vue'; import { CirclePlus, Delete, EditPen } from '@element-plus/icons-vue'
import MonitorPopup from '@/views/machine/device/components/monitorPopup.vue' import MonitorPopup from '@/views/machine/device/components/monitorPopup.vue'
import { ProTableInstance, type ColumnProps } from '@/components/ProTable/interface' import { type ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import { type Monitor } from '@/api/device/interface/monitor' import { type Monitor } from '@/api/device/interface/monitor'
import { useDictStore } from '@/stores/modules/dict'; import { useDictStore } from '@/stores/modules/dict'
import { useHandleData } from '@/hooks/useHandleData'; import { Device } from '@/api/device/interface/device'
import { Device } from '@/api/device/interface/device'; import { ElMessage, ElMessageBox } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus';
// 定义 props // 定义 props
const props = defineProps<{ const props = defineProps<{
DevFormContent:Device.ResPqDev, DevFormContent: Device.ResPqDev
tableHeight?: number, // 接收外部传入的高度 tableHeight?: number // 接收外部传入的高度
selectOptions: Record<string, Device.SelectOption[]>, selectOptions: Record<string, Device.SelectOption[]>
}>(); }>()
// ProTable 实例 // ProTable 实例
const proTable = ref<ProTableInstance>() const proTable = ref<ProTableInstance>()
@@ -63,39 +90,39 @@ const columns = reactive<ColumnProps<Monitor.ResPqMon>[]>([
{ {
prop: 'name', prop: 'name',
label: '名称', label: '名称',
width: 200, width: 200
}, },
{ {
prop: 'busbar', prop: 'busbar',
label: '所属母线', label: '所属母线',
width: 200, width: 200
}, },
{ {
prop: 'num', prop: 'num',
label: '线路号', label: '线路号',
width: 200, width: 200
}, },
{ {
prop: 'pt', prop: 'pt',
label: 'PT变比', label: 'PT变比',
width: 110, width: 110
}, },
{ {
prop: 'ct', prop: 'ct',
label: 'CT变比', label: 'CT变比',
width: 130, width: 130
}, },
{ {
prop: 'connection', prop: 'connection',
label: '接线方式', label: '接线方式',
enum: dictStore.getDictData('Dev_Connect'), enum: dictStore.getDictData('Dev_Connect'),
fieldNames: { label: 'name', value: 'id' }, fieldNames: { label: 'name', value: 'id' },
width: 130, width: 130
}, },
{ {
prop: 'statInterval', prop: 'statInterval',
label: '统计间隔', label: '统计间隔',
width: 130, width: 130
}, },
{ {
prop: 'checkFlag', prop: 'checkFlag',
@@ -103,12 +130,11 @@ const columns = reactive<ColumnProps<Monitor.ResPqMon>[]>([
render: (scope: any) => { render: (scope: any) => {
return scope.row.checkFlag === 1 ? '是' : '否' return scope.row.checkFlag === 1 ? '是' : '否'
}, },
width: 130, width: 130
}, },
{ prop: 'operation', label: '操作', fixed: 'right', width: 200 }, { prop: 'operation', label: '操作', fixed: 'right', width: 200 }
]) ])
const emit = defineEmits(['get-parameter']) const emit = defineEmits(['get-parameter'])
const getParameter = (data: Monitor.ResPqMon) => { const getParameter = (data: Monitor.ResPqMon) => {
@@ -117,83 +143,68 @@ const getParameter = (data: Monitor.ResPqMon) => {
// 编辑:替换已有的数据 // 编辑:替换已有的数据
const index = tableData.value.findIndex(item => item.id === data.id) const index = tableData.value.findIndex(item => item.id === data.id)
if (index > -1) { if (index > -1) {
tableData.value = [ tableData.value = [...tableData.value.slice(0, index), data, ...tableData.value.slice(index + 1)]
...tableData.value.slice(0, index),
data,
...tableData.value.slice(index + 1)
]
} }
} else { } else {
// 新增:追加数据 // 新增:追加数据
tableData.value = [...tableData.value, data] tableData.value = [...tableData.value, data]
} }
emit('get-parameter', tableData.value) emit('get-parameter', tableData.value)
} }
// 打开 drawer(新增、编辑) // 打开 drawer(新增、编辑)
const openDialog = (titleType: string, row: Partial<Monitor.ResPqMon> = {}) => { const openDialog = (titleType: string, row: Partial<Monitor.ResPqMon> = {}) => {
if (props.DevFormContent.devType == '' || props.DevFormContent.devType == undefined) { if (props.DevFormContent.devType == '' || props.DevFormContent.devType == undefined) {
ElMessageBox.confirm( ElMessageBox.confirm('请先选择被检设备类型', '提示', {
'请先选择被检设备类型',
'提示',
{
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning', type: 'warning'
}, })
)
return return
} }
title_Type.value = titleType title_Type.value = titleType
monitorPopup.value?.open(titleType, row, props.DevFormContent, tableData.value, props.selectOptions) monitorPopup.value?.open(titleType, row, props.DevFormContent, tableData.value, props.selectOptions)
} }
// 批量删除监测点台账 // 批量删除监测点台账
const batchDelete = (ids: string[]) => { const batchDelete = (ids: string[]) => {
ElMessageBox.confirm(`是否批量删除监测点?`, "温馨提示", { ElMessageBox.confirm(`是否批量删除监测点?`, '温馨提示', {
confirmButtonText: "确定", confirmButtonText: '确定',
cancelButtonText: "取消", cancelButtonText: '取消',
draggable: true draggable: true
}).then(async () => { }).then(async () => {
tableData.value = tableData.value.filter(item => !ids.includes(item.id)); tableData.value = tableData.value.filter(item => !ids.includes(item.id))
proTable.value?.clearSelection() proTable.value?.clearSelection()
emit('get-parameter', tableData.value) emit('get-parameter', tableData.value)
ElMessage({ ElMessage({
type: "success", type: 'success',
message: `批量删除监测点成功!` message: `批量删除监测点成功!`
}); })
}); })
} }
// 删除监测点台账 // 删除监测点台账
const handleDelete = (id: string) => { const handleDelete = (id: string) => {
ElMessageBox.confirm(`是否删除监测点?`, "温馨提示", { ElMessageBox.confirm(`是否删除监测点?`, '温馨提示', {
confirmButtonText: "确定", confirmButtonText: '确定',
cancelButtonText: "取消", cancelButtonText: '取消',
draggable: true draggable: true
}).then(async () => { }).then(async () => {
tableData.value = tableData.value.filter(item => item.id !== id) tableData.value = tableData.value.filter(item => item.id !== id)
proTable.value?.clearSelection() proTable.value?.clearSelection()
emit('get-parameter', tableData.value) emit('get-parameter', tableData.value)
ElMessage({ ElMessage({
type: "success", type: 'success',
message: `删除监测点成功!` message: `删除监测点成功!`
}); })
}); })
} }
watch( watch(
() => props.DevFormContent.monitorList, () => props.DevFormContent.monitorList,
(newVal) => { newVal => {
tableData.value = newVal || [] tableData.value = newVal || []
}, },
{ immediate: true } { immediate: true }
) )
</script> </script>

View File

@@ -1,8 +1,8 @@
<template> <template>
<el-dialog :title="dialogTitle" v-model="dialogVisible" @close="close" v-bind="dialogBig" align-center>
<el-dialog :title="dialogTitle" v-model='dialogVisible' @close="close" v-bind="dialogBig" align-center>
<div class="table-container"> <div class="table-container">
<el-table :data="errorData.value" <el-table
:data="errorData.value"
height="500" height="500"
:header-cell-style="rowClass" :header-cell-style="rowClass"
:cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }"
@@ -22,16 +22,20 @@
</el-table> </el-table>
</div> </div>
<div> <div>
<label class="left-align-label">注1UN测量的标称电压IN测量仪器的标称电流Uh和Ih测量值h表示谐波次数</label> <label class="left-align-label">
注1UN测量的标称电压IN测量仪器的标称电流Uh和Ih测量值h表示谐波次数
</label>
</div> </div>
<div> <div>
<label class="left-align-label">注2对于数字式接入监测终端与电能质量信号采集单元联合准确度需满足本表要求</label> <label class="left-align-label">
注2对于数字式接入监测终端与电能质量信号采集单元联合准确度需满足本表要求
</label>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup name="IndicatorTypeDialog"> <script lang="ts" setup name="IndicatorTypeDialog">
import {computed, type CSSProperties, defineProps, ref} from 'vue'; import { computed, type CSSProperties, ref } from 'vue'
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import type { ErrorSystem } from '@/api/device/interface/error' import type { ErrorSystem } from '@/api/device/interface/error'
import errorDataList from '@/api/device/error/errorData' import errorDataList from '@/api/device/error/errorData'
@@ -39,7 +43,7 @@ import type {TableColumnCtx} from 'element-plus'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
const dictStore = useDictStore() const dictStore = useDictStore()
const errorData = ref<ErrorSystem.Error_detail[]>([]); const errorData = ref<ErrorSystem.Error_detail[]>([])
const dialogTitle = ref() const dialogTitle = ref()
const devLevelName = ref<string>('') // 假设 devLevelName 是一个 ref const devLevelName = ref<string>('') // 假设 devLevelName 是一个 ref
function useMetaInfo() { function useMetaInfo() {
@@ -51,7 +55,7 @@ function useMetaInfo() {
standardTime: '', standardTime: '',
devLevel: '', devLevel: '',
enable: 1, enable: 1,
state: 1, state: 1
}) })
return { dialogVisible, formContent } return { dialogVisible, formContent }
} }
@@ -65,7 +69,17 @@ interface SpanMethodProps {
columnIndex: number columnIndex: number
} }
const rowClass = ({row, column, rowIndex, columnIndex}: { row: any; column: any; rowIndex: number; columnIndex: number }): CSSProperties => { const rowClass = ({
row,
column,
rowIndex,
columnIndex
}: {
row: any
column: any
rowIndex: number
columnIndex: number
}): CSSProperties => {
let res: CSSProperties = { let res: CSSProperties = {
textAlign: 'center' as CSSProperties['textAlign'], textAlign: 'center' as CSSProperties['textAlign'],
backgroundColor: 'var(--el-color-primary)', backgroundColor: 'var(--el-color-primary)',
@@ -77,137 +91,164 @@ const rowClass = ({row, column, rowIndex, columnIndex}: { row: any; column: any;
return res return res
} }
const spanMethod = computed(() => { const spanMethod = computed(() => {
return devLevelName.value === 'A级' ? spanAMethod : spanSMethod return devLevelName.value === 'A级' ? spanAMethod : spanSMethod
}) })
const spanAMethod = ({ const spanAMethod = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
row,
column,
rowIndex,
columnIndex,
}: SpanMethodProps) => {
if (columnIndex === 0) { if (columnIndex === 0) {
if (rowIndex <= 1 || rowIndex === 7 || rowIndex == 20) {//0电压偏差1频率偏差7闪变20功率简单的跨两列 if (rowIndex <= 1 || rowIndex === 7 || rowIndex == 20) {
//0电压偏差1频率偏差7闪变20功率简单的跨两列
return { return {
rowspan: 1, rowspan: 1,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 2) {//2三相不平衡跨三行两列 if (rowIndex === 2) {
//2三相不平衡跨三行两列
return { return {
rowspan: 3, rowspan: 3,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 3 || rowIndex === 4 || rowIndex === 6 || if (
rowIndex >= 9 && rowIndex <= 15 || rowIndex === 3 ||
rowIndex >= 17 && rowIndex <= 19 || rowIndex === 4 ||
rowIndex === 22 || rowIndex === 24) {//这些行不显示 rowIndex === 6 ||
(rowIndex >= 9 && rowIndex <= 15) ||
(rowIndex >= 17 && rowIndex <= 19) ||
rowIndex === 22 ||
rowIndex === 24
) {
//这些行不显示
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
} }
} }
if (rowIndex === 5 || rowIndex === 23) {//5电压波动23电压暂降暂升中断跨两列 if (rowIndex === 5 || rowIndex === 23) {
//5电压波动23电压暂降暂升中断跨两列
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
} }
} }
if (rowIndex === 8) {//谐波和间谐波跨八行两列 if (rowIndex === 8) {
//谐波和间谐波跨八行两列
return { return {
rowspan: 8, rowspan: 8,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 16) {//高频次谐波跨八行两列 if (rowIndex === 16) {
//高频次谐波跨八行两列
return { return {
rowspan: 4, rowspan: 4,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 21 || rowIndex === 22) {//电流跨两行两列 if (rowIndex === 21 || rowIndex === 22) {
//电流跨两行两列
return { return {
rowspan: 2, rowspan: 2,
colspan: 2, colspan: 2
} }
} }
} }
if (columnIndex === 1) { if (columnIndex === 1) {
if (rowIndex <= 4 || rowIndex >= 7 && rowIndex <= 22) { if (rowIndex <= 4 || (rowIndex >= 7 && rowIndex <= 22)) {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
} }
} }
} }
if (columnIndex === 2 || columnIndex === 3) { if (columnIndex === 2 || columnIndex === 3) {
if (rowIndex === 2 || rowIndex === 8 || rowIndex === 10 || if (
rowIndex === 12 || rowIndex === 14 || rowIndex === 16 || rowIndex === 2 ||
rowIndex === 18 || rowIndex === 21) { rowIndex === 8 ||
rowIndex === 10 ||
rowIndex === 12 ||
rowIndex === 14 ||
rowIndex === 16 ||
rowIndex === 18 ||
rowIndex === 21
) {
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
} }
} }
if (rowIndex === 3 || rowIndex === 9 || rowIndex === 11 || if (
rowIndex === 13 || rowIndex === 15 || rowIndex === 17 || rowIndex === 3 ||
rowIndex === 19 || rowIndex === 22) { rowIndex === 9 ||
rowIndex === 11 ||
rowIndex === 13 ||
rowIndex === 15 ||
rowIndex === 17 ||
rowIndex === 19 ||
rowIndex === 22
) {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
}
} }
} }
} }
};
const spanSMethod = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
const spanSMethod = ({
row,
column,
rowIndex,
columnIndex,
}: SpanMethodProps) => {
if (columnIndex === 0) { if (columnIndex === 0) {
if (rowIndex <= 1 || rowIndex === 8 || rowIndex == 17) {//0电压偏差1频率偏差7闪变20功率简单的跨两列 if (rowIndex <= 1 || rowIndex === 8 || rowIndex == 17) {
//0电压偏差1频率偏差7闪变20功率简单的跨两列
return { return {
rowspan: 1, rowspan: 1,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 2) {//2三相不平衡跨三行两列 if (rowIndex === 2) {
//2三相不平衡跨三行两列
return { return {
rowspan: 3, rowspan: 3,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 3 || rowIndex === 4 || rowIndex === 6 || rowIndex === 7 || if (
rowIndex >= 10 && rowIndex <= 12 || rowIndex === 3 ||
rowIndex >= 14 && rowIndex <= 16 || rowIndex === 4 ||
rowIndex === 19 || rowIndex === 21 || rowIndex === 22) {//这些行不显示 rowIndex === 6 ||
rowIndex === 7 ||
(rowIndex >= 10 && rowIndex <= 12) ||
(rowIndex >= 14 && rowIndex <= 16) ||
rowIndex === 19 ||
rowIndex === 21 ||
rowIndex === 22
) {
//这些行不显示
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
} }
} }
if (rowIndex === 5 || rowIndex === 20) {//5电压波动23电压暂降暂升中断跨两行 if (rowIndex === 5 || rowIndex === 20) {
//5电压波动23电压暂降暂升中断跨两行
return { return {
rowspan: 3, rowspan: 3,
colspan: 1, colspan: 1
} }
} }
if (rowIndex === 9 || rowIndex === 13) {//谐波和间谐波跨八行两列 if (rowIndex === 9 || rowIndex === 13) {
//谐波和间谐波跨八行两列
return { return {
rowspan: 4, rowspan: 4,
colspan: 2, colspan: 2
} }
} }
if (rowIndex === 18) {//电流跨两行两列 if (rowIndex === 18) {
//电流跨两行两列
return { return {
rowspan: 2, rowspan: 2,
colspan: 2, colspan: 2
} }
} }
} }
@@ -215,54 +256,81 @@ const spanSMethod = ({
if (rowIndex === 6 || rowIndex === 21) { if (rowIndex === 6 || rowIndex === 21) {
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
} }
} }
if (rowIndex <= 4 || rowIndex >= 7 && rowIndex <= 19 || rowIndex === 22) { if (rowIndex <= 4 || (rowIndex >= 7 && rowIndex <= 19) || rowIndex === 22) {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
} }
} }
} }
if (columnIndex === 2) { if (columnIndex === 2) {
if (rowIndex === 2 || rowIndex === 6 || rowIndex === 9 || if (
rowIndex === 11 || rowIndex === 13 || rowIndex === 15 || rowIndex === 2 ||
rowIndex === 18 || rowIndex === 21) { rowIndex === 6 ||
rowIndex === 9 ||
rowIndex === 11 ||
rowIndex === 13 ||
rowIndex === 15 ||
rowIndex === 18 ||
rowIndex === 21
) {
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
} }
} }
if (rowIndex === 3 || rowIndex === 7 || if (
rowIndex === 10 || rowIndex === 12 || rowIndex === 3 ||
rowIndex === 14 || rowIndex === 16 || rowIndex === 7 ||
rowIndex === 19 || rowIndex === 22) { rowIndex === 10 ||
rowIndex === 12 ||
rowIndex === 14 ||
rowIndex === 16 ||
rowIndex === 19 ||
rowIndex === 22
) {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
} }
} }
} }
if (columnIndex === 3) { if (columnIndex === 3) {
if (rowIndex === 2 || rowIndex === 6 || rowIndex === 9 || if (
rowIndex === 11 || rowIndex === 13 || rowIndex === 15 || rowIndex === 2 ||
rowIndex === 18 || rowIndex === 21) { rowIndex === 6 ||
rowIndex === 9 ||
rowIndex === 11 ||
rowIndex === 13 ||
rowIndex === 15 ||
rowIndex === 18 ||
rowIndex === 21
) {
return { return {
rowspan: 2, rowspan: 2,
colspan: 1, colspan: 1
} }
} }
if (rowIndex === 3 || rowIndex === 7 || rowIndex === 10 || if (
rowIndex === 12 || rowIndex === 14 || rowIndex === 16 || rowIndex === 3 ||
rowIndex === 19 || rowIndex === 22) { rowIndex === 7 ||
rowIndex === 10 ||
rowIndex === 12 ||
rowIndex === 14 ||
rowIndex === 16 ||
rowIndex === 19 ||
rowIndex === 22
) {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0, colspan: 0
}
} }
} }
} }
};
// 关闭弹窗 // 关闭弹窗
const close = () => { const close = () => {
@@ -275,22 +343,21 @@ const open = async (sign: string, data: ErrorSystem.ErrorSystemList) => {
dialogVisible.value = true dialogVisible.value = true
if (data.id) { if (data.id) {
formContent.value = data as ErrorSystem.ErrorSystemList; formContent.value = data as ErrorSystem.ErrorSystemList
devLevelName.value = dictStore.getDictData('Dev_Level').find(item => item.id === data.devLevel)?.name || ''; devLevelName.value = dictStore.getDictData('Dev_Level').find(item => item.id === data.devLevel)?.name || ''
if (devLevelName.value === 'A级' || data.devLevel === 'A级') { if (devLevelName.value === 'A级' || data.devLevel === 'A级') {
errorData.value = errorDataList.errorADetail as unknown as ErrorSystem.Error_detail[]; errorData.value = errorDataList.errorADetail as unknown as ErrorSystem.Error_detail[]
} else { } else {
errorData.value = errorDataList.errorSDetail as unknown as ErrorSystem.Error_detail[]; errorData.value = errorDataList.errorSDetail as unknown as ErrorSystem.Error_detail[]
} }
} }
} }
// 对外映射 // 对外映射
defineExpose({ open }) defineExpose({ open })
const props = defineProps<{ const props = defineProps<{
refreshTable: (() => Promise<void>) | undefined; refreshTable: (() => Promise<void>) | undefined
}>() }>()
</script> </script>
<style> <style>
@@ -313,6 +380,4 @@ const props = defineProps<{
display: block; /* 使每个label标签上下排列 */ display: block; /* 使每个label标签上下排列 */
margin-bottom: 10px; /* 调整两个label之间的间距 */ margin-bottom: 10px; /* 调整两个label之间的间距 */
} }
</style> </style>

View File

@@ -1,35 +1,43 @@
<template> <template>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button :icon='CirclePlus' type="primary" @click="openAddDialog">新增</el-button> <el-button :icon="CirclePlus" type="primary" @click="openAddDialog">新增</el-button>
<el-button :icon='Delete' type="danger" plain :disabled='!multipleSelection.length' @click="deleteSelectedRows">删除</el-button> <el-button :icon="Delete" type="danger" plain :disabled="!multipleSelection.length" @click="deleteSelectedRows">
删除
</el-button>
</div> </div>
<div class="table-container"> <div class="table-container">
<el-table :data="tableData" <el-table
:data="tableData"
:header-cell-style="{ textAlign: 'center', backgroundColor: 'var(--el-color-primary)', color: '#fff' }" :header-cell-style="{ textAlign: 'center', backgroundColor: 'var(--el-color-primary)', color: '#fff' }"
:cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }"
style="width: 100%" style="width: 100%"
:style="{ height: '400px', maxHeight: '400px', overflow: 'hidden' }" :style="{ height: '400px', maxHeight: '400px', overflow: 'hidden' }"
@selection-change="handleSelectionChange"> @selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column prop="sort" label="序号" width="60" /> <el-table-column prop="sort" label="序号" width="60" />
<el-table-column prop="type" label="误差类型" min-width="180"> <el-table-column prop="type" label="误差类型" min-width="180">
<template #default="{ row }"> <template #default="{ row }">
<el-cascader style="min-width: 180px;" <el-cascader
style="min-width: 180px"
:options="errorOptions" :options="errorOptions"
v-model="row.errorType" v-model="row.errorType"
:props="{ checkStrictly: false, emitPath: false }" :props="{ checkStrictly: false, emitPath: false }"
placeholder="请选择误差类型" placeholder="请选择误差类型"
@change="handleErrorTypeChange($event, row)"/> @change="handleErrorTypeChange($event, row)"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="type" label="脚本类型" min-width="230"> <el-table-column prop="type" label="脚本类型" min-width="230">
<template #default="{ row }"> <template #default="{ row }">
<el-cascader style="min-width: 230px;" <el-cascader
style="min-width: 230px"
:options="scriptOptions" :options="scriptOptions"
v-model="row.scriptType" v-model="row.scriptType"
:props="{ checkStrictly: false, emitPath: false }" :props="{ checkStrictly: false, emitPath: false }"
placeholder="请选择脚本类型" placeholder="请选择脚本类型"
@change="handleScriptTypeChange(row)"/> @change="handleScriptTypeChange(row)"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="起止范围"> <el-table-column label="起止范围">
@@ -37,14 +45,22 @@
<template #default="{ row }"> <template #default="{ row }">
<el-row type="flex" :gutter="24"> <el-row type="flex" :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-select v-model="row.startFlag" placeholder="选择起始值" style="width: 70px;" @change="(value) => handleStartFlagChange(row, value)"> <el-select
v-model="row.startFlag"
placeholder="选择起始值"
style="width: 70px"
@change="value => handleStartFlagChange(row, value)"
>
<el-option label="无" :value="2"></el-option> <el-option label="无" :value="2"></el-option>
<el-option label=">=" :value="1"></el-option> <el-option label=">=" :value="1"></el-option>
<el-option label=">" :value="0"></el-option> <el-option label=">" :value="0"></el-option>
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-input v-model="row.startValue" style="width: 60px;" :disabled="isStartValueDisabled[row.sort]" <el-input
v-model="row.startValue"
style="width: 60px"
:disabled="isStartValueDisabled[row.sort]"
/> />
</el-col> </el-col>
</el-row> </el-row>
@@ -54,14 +70,23 @@
<template #default="{ row }"> <template #default="{ row }">
<el-row type="flex" :gutter="24"> <el-row type="flex" :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-select v-model="row.endFlag" placeholder="选择结束值" style="width: 70px;" @change="(value) => handleEndFlagChange(row, value)"> <el-select
v-model="row.endFlag"
placeholder="选择结束值"
style="width: 70px"
@change="value => handleEndFlagChange(row, value)"
>
<el-option label="无" :value="2"></el-option> <el-option label="无" :value="2"></el-option>
<el-option label="<=" :value="1"></el-option> <el-option label="<=" :value="1"></el-option>
<el-option label="<" :value="0"></el-option> <el-option label="<" :value="0"></el-option>
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-input v-model="row.endValue" style="width: 60px;" :disabled="isEndValueDisabled[row.sort]"/> <el-input
v-model="row.endValue"
style="width: 60px"
:disabled="isEndValueDisabled[row.sort]"
/>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@@ -82,14 +107,16 @@
<el-table-column label="最大误差"> <el-table-column label="最大误差">
<el-table-column prop="maxErrorValue" label="最大误差值" width="100"> <el-table-column prop="maxErrorValue" label="最大误差值" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-input v-model="row.maxErrorValue" style="width: 70px;"/> <el-input v-model="row.maxErrorValue" style="width: 70px" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="误差类型" width="170"> <el-table-column label="误差类型" width="170">
<template #default="{ row }"> <template #default="{ row }">
<el-cascader :options="errorValueTypeOptions" <el-cascader
:options="errorValueTypeOptions"
v-model="row.errorValueType" v-model="row.errorValueType"
@change="handleErrorValueTypeChange(row)"/> @change="handleErrorValueTypeChange(row)"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="误差单位" width="100" prop="errorUnit"> <el-table-column label="误差单位" width="100" prop="errorUnit">
@@ -100,8 +127,8 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" min-width="150"> <el-table-column label="操作" min-width="150">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link :icon='CopyDocument' @click="copyRow(row)">复制</el-button> <el-button type="primary" link :icon="CopyDocument" @click="copyRow(row)">复制</el-button>
<el-button type='primary' link :icon='Delete' @click="deleteRow(row)">删除</el-button> <el-button type="primary" link :icon="Delete" @click="deleteRow(row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -109,17 +136,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {type ErrorSystem} from '@/api/device/interface/error'; import { type ErrorSystem } from '@/api/device/interface/error'
import {useDictStore,} from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { CirclePlus, CopyDocument, Delete } from '@element-plus/icons-vue' import { CirclePlus, CopyDocument, Delete } from '@element-plus/icons-vue'
import {type CascaderOption} from 'element-plus'; import { type CascaderOption } from 'element-plus'
import {defineEmits, type PropType, reactive, ref, watch} from 'vue'; import { type PropType, reactive, ref, watch } from 'vue'
const emit = defineEmits(['updateTableData']); const emit = defineEmits(['updateTableData'])
const multipleSelection = ref<number[]>([]) const multipleSelection = ref<number[]>([])
const dictStore = useDictStore() const dictStore = useDictStore()
const isStartValueDisabled = ref<{ [key: number]: boolean }>({}); const isStartValueDisabled = ref<{ [key: number]: boolean }>({})
const isEndValueDisabled = ref<{ [key: number]: boolean }>({}); const isEndValueDisabled = ref<{ [key: number]: boolean }>({})
const props = defineProps({ const props = defineProps({
errorOptions: { errorOptions: {
type: Array as PropType<CascaderOption[]>, type: Array as PropType<CascaderOption[]>,
@@ -135,14 +162,15 @@ const props = defineProps({
type: Array as PropType<ErrorSystem.ErrorSystemDetail[]>, type: Array as PropType<ErrorSystem.ErrorSystemDetail[]>,
default: () => [] default: () => []
} }
}); })
const errorValueTypeOptions = reactive<{ value: number, label: string, children: { value: number, label: string }[] }[]>([]) const errorValueTypeOptions = reactive<
{ value: number; label: string; children: { value: number; label: string }[] }[]
>([])
const conditionTypes = dictStore.getDictData('Condition_Type') const conditionTypes = dictStore.getDictData('Condition_Type')
const errorValueTypes = dictStore.getDictData('Error_Value_Type') const errorValueTypes = dictStore.getDictData('Error_Value_Type')
const valueTypes = dictStore.getDictData('Script_Value_Type') const valueTypes = dictStore.getDictData('Script_Value_Type')
onBeforeMount(() => { onBeforeMount(() => {
valueTypes.forEach(item1 => { valueTypes.forEach(item1 => {
let children = [] let children = []
@@ -156,7 +184,6 @@ onBeforeMount(() => {
}) })
}) })
const handleErrorTypeChange = (value: any, row: any) => { const handleErrorTypeChange = (value: any, row: any) => {
// const matchedRow = findRowById(row.errorType, props.errorOptions);//选中误差id找对应结构中的含chilren的code // const matchedRow = findRowById(row.errorType, props.errorOptions);//选中误差id找对应结构中的含chilren的code
// console.log('matchedRow.code',matchedRow.code) // console.log('matchedRow.code',matchedRow.code)
// const code = errSysAndScriptMap.get(matchedRow?.code || '') || ''; // 确保 code 不为 undefined // const code = errSysAndScriptMap.get(matchedRow?.code || '') || ''; // 确保 code 不为 undefined
@@ -188,103 +215,101 @@ const handleErrorValueTypeChange = (row: any) => {
case 1: // 绝对值 case 1: // 绝对值
row.valueType = 1 row.valueType = 1
row.errorUnit = scriptType.remark row.errorUnit = scriptType.remark
break; break
case 2: // 相对值 case 2: // 相对值
row.valueType = 2 row.valueType = 2
row.errorUnit = "%" row.errorUnit = '%'
break; break
default: default:
break; break
} }
} }
} }
// 假设 props.errorOptions 是一个数组,每个元素可能包含 children 属性 // 假设 props.errorOptions 是一个数组,每个元素可能包含 children 属性
const findRowById = (id: string, options: any[]): any | null => { const findRowById = (id: string, options: any[]): any | null => {
for (const option of options) { for (const option of options) {
if (option.value === id) { if (option.value === id) {
return option; return option
} }
if (option.children && option.children.length > 0) { if (option.children && option.children.length > 0) {
const result = findRowById(id, option.children); const result = findRowById(id, option.children)
if (result) { if (result) {
return result; return result
} }
} }
} }
return null; return null
}; }
// 假设 props.errorOptions 是一个数组,每个元素可能包含 children 属性 // 假设 props.errorOptions 是一个数组,每个元素可能包含 children 属性
const findRowByCode = (code: string, options: any[]): any | null => { const findRowByCode = (code: string, options: any[]): any | null => {
for (const option of options) { for (const option of options) {
if (option.code === code) { if (option.code === code) {
return option; return option
} }
if (option.children && option.children.length > 0) { if (option.children && option.children.length > 0) {
const result = findRowByCode(code, option.children); const result = findRowByCode(code, option.children)
if (result) { if (result) {
return result; return result
} }
} }
} }
return null; return null
}; }
// 监听 props.tableData 的变化,确保每次数据变化时都重新设置 sort // 监听 props.tableData 的变化,确保每次数据变化时都重新设置 sort
watch(() => props.tableData, async (newTableData) => { watch(
() => props.tableData,
async newTableData => {
for (let i = 0; i < newTableData.length; i++) { for (let i = 0; i < newTableData.length; i++) {
newTableData[i].sort = i + 1; newTableData[i].sort = i + 1
if (newTableData[i].startFlag === 2) { if (newTableData[i].startFlag === 2) {
newTableData[i].startValue = null; // 设置 startValue 为 null newTableData[i].startValue = null // 设置 startValue 为 null
} }
if (newTableData[i].endFlag === 2) { if (newTableData[i].endFlag === 2) {
newTableData[i].endValue = null; // 设置 endValue 为 null newTableData[i].endValue = null // 设置 endValue 为 null
} }
} }
// 重新设置 isStartValueDisabled 和 isEndValueDisabled,并清空输入框 // 重新设置 isStartValueDisabled 和 isEndValueDisabled,并清空输入框
props.tableData.forEach(row => { props.tableData.forEach(row => {
isStartValueDisabled.value[row.sort] = row.startFlag === 2; isStartValueDisabled.value[row.sort] = row.startFlag === 2
})
});
props.tableData.forEach(row => { props.tableData.forEach(row => {
isEndValueDisabled.value[row.sort] = row.endFlag === 2; isEndValueDisabled.value[row.sort] = row.endFlag === 2
}); })
}, {immediate: true}); },
{ immediate: true }
)
// 处理 startFlag 变化的方法 // 处理 startFlag 变化的方法
const handleStartFlagChange = (row: ErrorSystem.ErrorSystemDetail, value: number) => { const handleStartFlagChange = (row: ErrorSystem.ErrorSystemDetail, value: number) => {
if (value === 2) { if (value === 2) {
row.startValue = null; // 清空输入框 row.startValue = null // 清空输入框
isStartValueDisabled.value[row.sort] = true; // 禁用输入框 isStartValueDisabled.value[row.sort] = true // 禁用输入框
} else { } else {
isStartValueDisabled.value[row.sort] = false; // 启用输入框 isStartValueDisabled.value[row.sort] = false // 启用输入框
}
} }
};
// 处理 endFlag 变化的方法 // 处理 endFlag 变化的方法
const handleEndFlagChange = (row: ErrorSystem.ErrorSystemDetail, value: number) => { const handleEndFlagChange = (row: ErrorSystem.ErrorSystemDetail, value: number) => {
if (value === 2) { if (value === 2) {
row.endValue = null; // 清空输入框 row.endValue = null // 清空输入框
isEndValueDisabled.value[row.sort] = true; // 禁用输入框 isEndValueDisabled.value[row.sort] = true // 禁用输入框
} else { } else {
isEndValueDisabled.value[row.sort] = false; // 启用输入框 isEndValueDisabled.value[row.sort] = false // 启用输入框
}
} }
};
//选中 //选中
const handleSelectionChange = (selection: ErrorSystem.ErrorSystemDetail[]) => { const handleSelectionChange = (selection: ErrorSystem.ErrorSystemDetail[]) => {
multipleSelection.value = selection.map(row => row.sort); // 更新选中的行 multipleSelection.value = selection.map(row => row.sort) // 更新选中的行
}; }
//新增 //新增
const openAddDialog = () => { const openAddDialog = () => {
// 获取字典数据 // 获取字典数据
const newRow = { const newRow = {
sort: props.tableData.length + 1, sort: props.tableData.length + 1,
id: '', id: '',
@@ -293,41 +318,37 @@ const openAddDialog = () => {
conditionType: conditionTypes.length > 0 ? Number(conditionTypes[0].value) : 0, // 设置默认值为第一个选项的值 conditionType: conditionTypes.length > 0 ? Number(conditionTypes[0].value) : 0, // 设置默认值为第一个选项的值
valueType: valueTypes.length > 0 ? Number(valueTypes[0].value) : 1, valueType: valueTypes.length > 0 ? Number(valueTypes[0].value) : 1,
errorValueType: [errorValueTypeOptions[0].value, errorValueTypeOptions[0].children[0].value], errorValueType: [errorValueTypeOptions[0].value, errorValueTypeOptions[0].children[0].value],
errorSysId: "", errorSysId: '',
errorType: "", errorType: '',
scriptType: "", scriptType: '',
maxErrorValue: 0 maxErrorValue: 0
}; }
emit('updateTableData', [...props.tableData, newRow])
emit('updateTableData', [...props.tableData, newRow]); }
};
const copyRow = (row: ErrorSystem.ErrorSystemDetail) => { const copyRow = (row: ErrorSystem.ErrorSystemDetail) => {
// 深拷贝行数据 // 深拷贝行数据
const newRow = {...row}; const newRow = { ...row }
const maxNextId = Math.max(...props.tableData.map(item => item.sort), 0); const maxNextId = Math.max(...props.tableData.map(item => item.sort), 0)
newRow.sort = maxNextId + 1; newRow.sort = maxNextId + 1
emit('updateTableData', [...props.tableData, newRow]); emit('updateTableData', [...props.tableData, newRow])
}; }
//删除行 //删除行
const deleteRow = (row: ErrorSystem.ErrorSystemDetail) => { const deleteRow = (row: ErrorSystem.ErrorSystemDetail) => {
const index = props.tableData.indexOf(row); const index = props.tableData.indexOf(row)
if (index !== -1) { if (index !== -1) {
const newTableData = [...props.tableData]; const newTableData = [...props.tableData]
newTableData.splice(index, 1); newTableData.splice(index, 1)
emit('updateTableData', newTableData); emit('updateTableData', newTableData)
}
} }
};
//批量删除选中行 //批量删除选中行
const deleteSelectedRows = () => { const deleteSelectedRows = () => {
const newTableData = props.tableData.filter(row => !multipleSelection.value.includes(row.sort)); const newTableData = props.tableData.filter(row => !multipleSelection.value.includes(row.sort))
multipleSelection.value = []; // 清空已选择的行 multipleSelection.value = [] // 清空已选择的行
emit('updateTableData', newTableData); emit('updateTableData', newTableData)
}; }
</script> </script>
<style scoped> <style scoped>
@@ -338,7 +359,8 @@ const deleteSelectedRows = () => {
margin-top: 10px; margin-top: 10px;
} }
.el-table th, .el-table td { .el-table th,
.el-table td {
text-align: center; /* 所有单元格文字居中 */ text-align: center; /* 所有单元格文字居中 */
} }

View File

@@ -1,11 +1,29 @@
<template> <template>
<el-dialog :title="dialogTitle" v-model='dialogVisible' @close="close" v-bind="dialogBig" width="1660px" align-center> <el-dialog
:title="dialogTitle"
v-model="dialogVisible"
@close="close"
v-bind="dialogBig"
width="1660px"
align-center
>
<el-tabs type="border-card"> <el-tabs type="border-card">
<el-tab-pane label="基础信息"> <el-tab-pane label="基础信息">
<div> <div>
<el-form :model="formContent" ref='dialogFormRef' :rules='rules' label-width="auto" class="form-four"> <el-form
:model="formContent"
ref="dialogFormRef"
:rules="rules"
label-width="auto"
class="form-four"
>
<el-form-item label="标准号" prop="standardName"> <el-form-item label="标准号" prop="standardName">
<el-input v-model='formContent.standardName' placeholder="请填写标准号" maxlength="32" show-word-limit/> <el-input
v-model="formContent.standardName"
placeholder="请填写标准号"
maxlength="32"
show-word-limit
/>
</el-form-item> </el-form-item>
<el-form-item label="标准推行年份" prop="standardTime"> <el-form-item label="标准推行年份" prop="standardTime">
<el-date-picker <el-date-picker
@@ -15,16 +33,17 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="适用设备等级" prop="devLevel"> <el-form-item label="适用设备等级" prop="devLevel">
<el-select v-model='formContent.devLevel' placeholder="请选择设备等级"> <el-select v-model="formContent.devLevel" placeholder="请选择设备等级">
<el-option <el-option
v-for="item in dictStore.getDictData('Dev_Level')" v-for="item in dictStore.getDictData('Dev_Level')"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id"/> :value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="enable"> <el-form-item label="状态" prop="enable">
<el-select v-model='formContent.enable' placeholder="请选择状态"> <el-select v-model="formContent.enable" placeholder="请选择状态">
<el-option label="启用" :value="1"></el-option> <el-option label="启用" :value="1"></el-option>
<el-option label="停用" :value="0"></el-option> <el-option label="停用" :value="0"></el-option>
</el-select> </el-select>
@@ -34,41 +53,42 @@
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<ErrorSystemDetailTable
<ErrorSystemDetailTable :tableData="tableData" :errorOptions="errorOptions" :scriptOptions="scriptOptions" @updateTableData="handleTableDataUpdate" /> :tableData="tableData"
:errorOptions="errorOptions"
:scriptOptions="scriptOptions"
@updateTableData="handleTableDataUpdate"
/>
<template #footer> <template #footer>
<div> <div>
<el-button @click='close()'> </el-button> <el-button @click="close()"> </el-button>
<el-button type="primary" @click='save()'>保存</el-button> <el-button type="primary" @click="save()">保存</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup name="ErrorSystemDialog"> <script lang="ts" setup name="ErrorSystemDialog">
import{type CascaderOption, ElMessage, type FormInstance,type FormItemRule}from'element-plus' import { type CascaderOption, ElMessage, type FormItemRule } from 'element-plus'
import { defineProps, defineEmits, reactive,watch,ref, type Ref, computed } from 'vue'; import { computed, type Ref, ref } from 'vue'
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import { addPqErrSys,updatePqErrSys,getPqErrSysListById} from '@/api/device/error/index' import { addPqErrSys, getPqErrSysListById, updatePqErrSys } from '@/api/device/error/index'
import {CirclePlus, Delete, EditPen,FolderOpened,CopyDocument} from '@element-plus/icons-vue'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { type ErrorSystem } from '@/api/device/interface/error'; import { type ErrorSystem } from '@/api/device/interface/error'
import ErrorSystemDetailTable from '@/views/machine/errorSystem/components/errorSystemDetailTable.vue'; import ErrorSystemDetailTable from '@/views/machine/errorSystem/components/errorSystemDetailTable.vue'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree' import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { type Dict } from '@/api/system/dictionary/interface'; import { type Dict } from '@/api/system/dictionary/interface'
// 定义弹出组件元信息 // 定义弹出组件元信息
const dialogFormRef = ref() const dialogFormRef = ref()
const dictStore = useDictStore() const dictStore = useDictStore()
const tableData = ref<ErrorSystem.ErrorSystemDetail[]>([]); const tableData = ref<ErrorSystem.ErrorSystemDetail[]>([])
const errorOptions: Ref<CascaderOption[]> = ref([]); // 修改这里 const errorOptions: Ref<CascaderOption[]> = ref([]) // 修改这里
const scriptOptions: Ref<CascaderOption[]> = ref([]); // 修改这里 const scriptOptions: Ref<CascaderOption[]> = ref([]) // 修改这里
const handleTableDataUpdate = (newTableData: ErrorSystem.ErrorSystemDetail[]) => { const handleTableDataUpdate = (newTableData: ErrorSystem.ErrorSystemDetail[]) => {
tableData.value = newTableData; tableData.value = newTableData
}; }
function useMetaInfo() { function useMetaInfo() {
const dialogVisible = ref(false) const dialogVisible = ref(false)
@@ -111,10 +131,9 @@ const handleTableDataUpdate = (newTableData: ErrorSystem.ErrorSystemDetail[]) =>
name: [{ required: true, message: '误差体系名称必填!', trigger: 'blur' }], name: [{ required: true, message: '误差体系名称必填!', trigger: 'blur' }],
standardName: [{ required: true, message: '参照标准名称必填!', trigger: 'blur' }], standardName: [{ required: true, message: '参照标准名称必填!', trigger: 'blur' }],
standardTime: [{ required: true, message: '标准推行年份必选!', trigger: 'blur' }], standardTime: [{ required: true, message: '标准推行年份必选!', trigger: 'blur' }],
devLevel:[{ required: true, message: '请选择一项设备等级', trigger: 'change' },], devLevel: [{ required: true, message: '请选择一项设备等级', trigger: 'change' }],
enable:[{ required: true, message: '请选择一项状态', trigger: 'change '},] enable: [{ required: true, message: '请选择一项状态', trigger: 'change ' }]
}); })
// 关闭弹窗 // 关闭弹窗
const close = () => { const close = () => {
@@ -132,25 +151,24 @@ const handleTableDataUpdate = (newTableData: ErrorSystem.ErrorSystemDetail[]) =>
if (valid) { if (valid) {
// 确保 standardTime 是 Date 对象 // 确保 standardTime 是 Date 对象
if (formContent.value.standardTime) { if (formContent.value.standardTime) {
const date = new Date(formContent.value.standardTime); const date = new Date(formContent.value.standardTime)
formContent.value.standardTime = date.getFullYear().toString(); formContent.value.standardTime = date.getFullYear().toString()
} }
formContent.value.pqErrSysDtlsList = tableData.value formContent.value.pqErrSysDtlsList = tableData.value
formContent.value.pqErrSysDtlsList.forEach((item) => { formContent.value.pqErrSysDtlsList.forEach(item => {
item.errorValueType = item.errorValueType[1] item.errorValueType = item.errorValueType[1]
}) })
if (formContent.value.id) { if (formContent.value.id) {
await updatePqErrSys(formContent.value); await updatePqErrSys(formContent.value)
ElMessage.success({ message: `${dialogTitle.value}成功!` }) ElMessage.success({ message: `${dialogTitle.value}成功!` })
} else { } else {
await addPqErrSys(formContent.value); await addPqErrSys(formContent.value)
ElMessage.success({ message: `${dialogTitle.value}成功!` }) ElMessage.success({ message: `${dialogTitle.value}成功!` })
} }
close() close()
// 刷新表格 // 刷新表格
await props.refreshTable!() await props.refreshTable!()
} }
}) })
} catch (err) { } catch (err) {
@@ -159,8 +177,8 @@ const handleTableDataUpdate = (newTableData: ErrorSystem.ErrorSystemDetail[]) =>
} }
// 封装提取第二层节点的逻辑 // 封装提取第二层节点的逻辑
const loadSecondLevelOptions = async () => { const loadSecondLevelOptions = async () => {
const dictCode = 'Err_Sys_Items'; // 替换为实际需要的字典代码 const dictCode = 'Err_Sys_Items' // 替换为实际需要的字典代码
const dictCode2 = 'Script_Error'; // 替换为实际需要的字典代码 const dictCode2 = 'Script_Error' // 替换为实际需要的字典代码
const resDictTree: Dict.ResDictTree = { const resDictTree: Dict.ResDictTree = {
name: '', name: '',
@@ -169,7 +187,7 @@ const loadSecondLevelOptions = async () => {
pids: '', pids: '',
code: dictCode, code: dictCode,
sort: 0 sort: 0
}; }
const resDictTree2: Dict.ResDictTree = { const resDictTree2: Dict.ResDictTree = {
name: '', name: '',
@@ -178,36 +196,33 @@ const loadSecondLevelOptions = async () => {
pids: '', pids: '',
code: dictCode2, code: dictCode2,
sort: 0 sort: 0
}; }
// 并行请求两个字典树列表 // 并行请求两个字典树列表
const [result, result2] = await Promise.all([ const [result, result2] = await Promise.all([getDictTreeByCode(resDictTree), getDictTreeByCode(resDictTree2)])
getDictTreeByCode(resDictTree),
getDictTreeByCode(resDictTree2)
]);
const allOptions = convertToOptions(result.data as Dict.ResDictTree[]); const allOptions = convertToOptions(result.data as Dict.ResDictTree[])
const allOptions2 = convertToOptions(result2.data as Dict.ResDictTree[]); const allOptions2 = convertToOptions(result2.data as Dict.ResDictTree[])
// 提取第二层节点 // 提取第二层节点
const secondLevelOptions: any[] = []; const secondLevelOptions: any[] = []
allOptions.forEach(option => { allOptions.forEach(option => {
if (option.children && option.children.length > 0) { if (option.children && option.children.length > 0) {
secondLevelOptions.push(...option.children); secondLevelOptions.push(...option.children)
} }
}); })
const secondLevelOptions2: any[] = []; const secondLevelOptions2: any[] = []
allOptions2.forEach(option => { allOptions2.forEach(option => {
if (option.children && option.children.length > 0) { if (option.children && option.children.length > 0) {
secondLevelOptions2.push(...option.children); secondLevelOptions2.push(...option.children)
} }
}); })
// 将第二层节点赋值给 options.value // 将第二层节点赋值给 options.value
errorOptions.value = secondLevelOptions; errorOptions.value = secondLevelOptions
scriptOptions.value = secondLevelOptions2; scriptOptions.value = secondLevelOptions2
}; }
// 转换函数 // 转换函数
const convertToOptions = (dictTree: Dict.ResDictTree[]): CascaderOption[] => { const convertToOptions = (dictTree: Dict.ResDictTree[]): CascaderOption[] => {
@@ -217,43 +232,38 @@ const loadSecondLevelOptions = async () => {
code: item.code, code: item.code,
children: item.children ? convertToOptions(item.children) : undefined, children: item.children ? convertToOptions(item.children) : undefined,
remark: item.remark remark: item.remark
})); }))
}; }
// 打开弹窗,可能是新增,也可能是编辑 // 打开弹窗,可能是新增,也可能是编辑
const open = async (sign: string, data: ErrorSystem.ErrorSystemList) => { const open = async (sign: string, data: ErrorSystem.ErrorSystemList) => {
titleType.value = sign; titleType.value = sign
// 并行执行两个异步操作 // 并行执行两个异步操作
const loadOptionsPromise = loadSecondLevelOptions(); const loadOptionsPromise = loadSecondLevelOptions()
const fetchDataPromise = data.id ? getPqErrSysListById(data) : Promise.resolve(null); const fetchDataPromise = data.id ? getPqErrSysListById(data) : Promise.resolve(null)
const [_, result] = await Promise.all([loadOptionsPromise, fetchDataPromise]); const [_, result] = await Promise.all([loadOptionsPromise, fetchDataPromise])
if (result && result.data) { if (result && result.data) {
formContent.value = result.data as ErrorSystem.ErrorSystemList; formContent.value = result.data as ErrorSystem.ErrorSystemList
tableData.value = formContent.value.pqErrSysDtlsList || []; tableData.value = formContent.value.pqErrSysDtlsList || []
tableData.value.forEach((item) => { tableData.value.forEach(item => {
item.errorValueType = [item.valueType, item.errorValueType] item.errorValueType = [item.valueType, item.errorValueType]
}) })
} else { } else {
resetFormContent(); resetFormContent()
} }
// 重置表单 // 重置表单
dialogFormRef.value?.resetFields(); dialogFormRef.value?.resetFields()
dialogVisible.value = true; dialogVisible.value = true
}; }
// 对外映射 // 对外映射
defineExpose({ open }) defineExpose({ open })
const props = defineProps<{ const props = defineProps<{
refreshTable: (() => Promise<void>) | undefined; refreshTable: (() => Promise<void>) | undefined
}>() }>()
</script> </script>
<style> <style></style>
</style>

View File

@@ -7,7 +7,7 @@
</div> </div>
<div class="data-check-content"> <div class="data-check-content">
<div class="content-tree" :style="{ height: `calc(100vh - ${props.shrink ? '370px' : '315px'})` }"> <div class="content-tree" :style="{ height: `calc(100vh - ${props.shrink ? '370px' : '315px'})` }">
<Tree :treeData="treeData" @setTab="setTab" /> <TestScriptTree :treeData="treeData" @setTab="setTab" />
</div> </div>
<div <div
@@ -19,7 +19,8 @@
<el-tab-pane v-for="tab in tabData" :key="tab.value" :label="tab.label" :name="tab.value"> <el-tab-pane v-for="tab in tabData" :key="tab.value" :label="tab.label" :name="tab.value">
<div v-if="activeName == tab.value"> <div v-if="activeName == tab.value">
<div class="dialog-footer"> <div class="dialog-footer">
<el-switch v-model="value1" <el-switch
v-model="value1"
inline-prompt inline-prompt
:active-value="1" :active-value="1"
:inactive-value="0" :inactive-value="0"
@@ -28,7 +29,7 @@
@change="enableScript" @change="enableScript"
size="large" size="large"
width="80px" width="80px"
style="margin-right: 10px;" style="margin-right: 10px"
/> />
<el-button :icon="CirclePlus" type="primary" @click="openDialog('add')">新增</el-button> <el-button :icon="CirclePlus" type="primary" @click="openDialog('add')">新增</el-button>
</div> </div>
@@ -215,20 +216,21 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { type PropType, ref, nextTick } from 'vue' import { type PropType, ref } from 'vue'
import Tree from './tree.vue' import TestScriptTree from './testScriptTree.vue'
import Commun from './communication.vue' import Commun from './communication.vue'
import { type CascaderOption, ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { getTreeData } from '@/api/check/test' import { getTreeData } from '@/api/check/test'
import { CirclePlus, Delete, Check, CopyDocument, View, EditPen } from '@element-plus/icons-vue' import { CirclePlus, CopyDocument, Delete, EditPen, View } from '@element-plus/icons-vue'
import type { TestScript } from '@/api/device/interface/testScript' import type { TestScript } from '@/api/device/interface/testScript'
import TestProjectPopup from '@/views/machine/testScript/components/testProjectPopup.vue' import TestProjectPopup from '@/views/machine/testScript/components/testProjectPopup.vue'
import { CheckData } from '@/api/check/interface' import { CheckData } from '@/api/check/interface'
import { dlsDetails, deleteDtls, updateDtls, addScriptDtls, checkDataList } from '@/api/device/testScript' import { addScriptDtls, deleteDtls, dlsDetails, updateDtls } from '@/api/device/testScript'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import { useHandleData } from '@/hooks/useHandleData' import { useHandleData } from '@/hooks/useHandleData'
import { scriptDtlsCheckDataList } from '@/api/device/testScript/index' import { scriptDtlsCheckDataList } from '@/api/device/testScript/index'
import ViewRow from '@/views/machine/testScript/components/viewRow.vue' import ViewRow from '@/views/machine/testScript/components/viewRow.vue'
interface TabOption { interface TabOption {
label?: string label?: string
name?: string name?: string
@@ -370,8 +372,6 @@ const inquireTable = () => {
value1.value = tableData.value.some(item => item.enable === 1) ? 1 : 0 value1.value = tableData.value.some(item => item.enable === 1) ? 1 : 0
} }
}) })
} }
// 打开 drawer(新增、编辑) // 打开 drawer(新增、编辑)
const openDialog = (titleType: string, row: Partial<TestScript.ResTestScript> = {}) => { const openDialog = (titleType: string, row: Partial<TestScript.ResTestScript> = {}) => {
@@ -466,7 +466,6 @@ const enableRow = async (row: any) => {
}) })
} }
// 启用/禁用脚本的方法 // 启用/禁用脚本的方法
const enableScript = async () => { const enableScript = async () => {
const willEnable = value1.value === 1 const willEnable = value1.value === 1
@@ -496,7 +495,6 @@ const enableScript = async () => {
} }
} }
// 获取左边树数据 // 获取左边树数据
// 新增保存 // 新增保存
const addTab = (row: any) => { const addTab = (row: any) => {
@@ -537,7 +535,6 @@ onMounted(() => {
overflow-x: hidden; overflow-x: hidden;
} }
/* 确保 el-tree 内容可以超出容器宽度 */ /* 确保 el-tree 内容可以超出容器宽度 */
.el-tree { .el-tree {
width: fit-content; /* 根据内容自适应宽度 */ width: fit-content; /* 根据内容自适应宽度 */
@@ -553,7 +550,6 @@ onMounted(() => {
margin-bottom: 10px; margin-bottom: 10px;
} }
.divider-container { .divider-container {
display: flex; display: flex;
} }

View File

@@ -1,6 +1,5 @@
<template> <template>
<el-dialog v-model="dialogVisible" :title="dialogTitle" <el-dialog v-model="dialogVisible" :title="dialogTitle" v-bind="dialogSmall" @close="close" align-center>
v-bind="dialogSmall" @close="close" align-center>
<div> <div>
<el-form :model="formContent" ref="dialogFormRef" :rules="rules"> <el-form :model="formContent" ref="dialogFormRef" :rules="rules">
<el-form-item label="参数所属" prop="pId" :label-width="100"> <el-form-item label="参数所属" prop="pId" :label-width="100">
@@ -21,31 +20,28 @@
<el-form-item label="源参数类型" :label-width="100" prop="type"> <el-form-item label="源参数类型" :label-width="100" prop="type">
<el-input v-model="formContent.type" autocomplete="off" maxlength="32" show-word-limit /> <el-input v-model="formContent.type" autocomplete="off" maxlength="32" show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="源参数值" :label-width="100" <el-form-item label="源参数值" :label-width="100" prop="value">
prop="value">
<el-input v-model="formContent.value" autocomplete="off" /> <el-input v-model="formContent.value" autocomplete="off" />
</el-form-item> </el-form-item>
<el-form-item label="排序" :label-width="100"> <el-form-item label="排序" :label-width="100">
<el-input-number v-model="formContent.sort" :min='1' :max='999'/> <el-input-number v-model="formContent.sort" :min="1" :max="999" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="close()">取消</el-button> <el-button @click="close()">取消</el-button>
<el-button type="primary" @click="save()"> <el-button type="primary" @click="save()">保存</el-button>
保存
</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {computed, defineEmits, reactive, watch} from 'vue' import { computed, reactive } from 'vue'
import {dialogSmall} from "@/utils/elementBind" import { dialogSmall } from '@/utils/elementBind'
import {TestSource} from "@/api/device/interface/testSource" import { type TestSource } from '@/api/device/interface/testSource'
import {ElMessage, FormItemRule} from "element-plus" import { type FormItemRule } from 'element-plus'
defineProps<{ defineProps<{
tableData: TestSource.ParameterType[] tableData: TestSource.ParameterType[]
@@ -56,22 +52,19 @@ const emit = defineEmits(['get-parameter'])
// 计算属性,用于控制显示的 pid // 计算属性,用于控制显示的 pid
const displayPid = computed({ const displayPid = computed({
get: () => { get: () => {
return formContent.pId === '0' ? '' : formContent.pId
return formContent.pId === '0' ? '' : formContent.pId;
}, },
set: (value) => { set: value => {
formContent.pId = value
formContent.pId = value;
} }
})
});
// 树形节点配置 // 树形节点配置
const defaultProps = { const defaultProps = {
children: 'children', children: 'children',
label: 'desc', label: 'desc',
value: 'id' value: 'id'
}; }
const dialogFormRef = ref() const dialogFormRef = ref()
const { dialogVisible, titleType, formContent } = useMetaInfo() const { dialogVisible, titleType, formContent } = useMetaInfo()
@@ -81,20 +74,26 @@ function useMetaInfo() {
const titleType = ref('add') const titleType = ref('add')
const formContent = reactive<TestSource.ParameterType>({ const formContent = reactive<TestSource.ParameterType>({
id: "", id: '',
type: "", type: '',
value: null, value: null,
desc: "", desc: '',
sort: 100, sort: 100,
pId: "0", pId: '0'
}) })
return { dialogVisible, titleType, formContent } return { dialogVisible, titleType, formContent }
} }
const rules: reactive<Record<string, Array<FormItemRule>>> = reactive({ const rules: reactive<Record<string, Array<FormItemRule>>> = reactive({
desc: [{required: true, message: '源参数描述必填!', trigger: 'blur'},{min: 1, max: 32, message: '长度为1~32个字符', trigger: 'blur'}], desc: [
type: [{required: true, message: '源参数类型必填!', trigger: 'blur'},{min: 1, max: 32, message: '长度为1~32个字符', trigger: 'blur'}], { required: true, message: '源参数描述必填!', trigger: 'blur' },
{ min: 1, max: 32, message: '长度为1~32个字符', trigger: 'blur' }
],
type: [
{ required: true, message: '源参数类型必填!', trigger: 'blur' },
{ min: 1, max: 32, message: '长度为1~32个字符', trigger: 'blur' }
],
sort: [{ required: true, message: '排序必填!', trigger: 'blur' }] sort: [{ required: true, message: '排序必填!', trigger: 'blur' }]
}) })
@@ -113,12 +112,12 @@ let dialogTitle = computed(() => {
const resetFormContent = () => { const resetFormContent = () => {
Object.assign(formContent, { Object.assign(formContent, {
id: "", id: '',
type: "", type: '',
value: null, value: null,
desc: "", desc: '',
sort: 100, sort: 100,
pId: "0", pId: '0'
}) })
} }
const open = (sign: string, data: TestSource.ParameterType) => { const open = (sign: string, data: TestSource.ParameterType) => {
@@ -156,6 +155,4 @@ const close = () => {
defineExpose({ open }) defineExpose({ open })
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -1,8 +1,8 @@
<template> <template>
<div class='table-box' > <div class="table-box">
<ProTable <ProTable
ref='proTable' ref="proTable"
:columns='columns' :columns="columns"
:pagination="false" :pagination="false"
:toolButton="false" :toolButton="false"
:data="tableData" :data="tableData"
@@ -11,64 +11,85 @@
:expand-row-keys="defaultExpandRowKeys" :expand-row-keys="defaultExpandRowKeys"
> >
<!-- 表格 header 按钮 --> <!-- 表格 header 按钮 -->
<template #tableHeader='scope'> <template #tableHeader="scope">
<el-button :disabled="isDisable" v-auth.testSource="'add'" type='primary' :icon='CirclePlus' @click="openDialog('add')">新增 <el-button
:disabled="isDisable"
v-auth.testSource="'add'"
type="primary"
:icon="CirclePlus"
@click="openDialog('add')"
>
新增
</el-button> </el-button>
<el-button v-auth.testSource="'delete'" type='danger' :icon='Delete' <el-button
plain :disabled='isDisable || !scope.isSelected' @click='batchDelete(scope.selectedListIds)'> v-auth.testSource="'delete'"
type="danger"
:icon="Delete"
plain
:disabled="isDisable || !scope.isSelected"
@click="batchDelete(scope.selectedListIds)"
>
删除 删除
</el-button> </el-button>
</template> </template>
<!-- 表格操作 --> <!-- 表格操作 -->
<template #operation='scope'> <template #operation="scope">
<!-- <el-button type="primary" link :icon='CopyDocument' @click="copyRow(scope.row)">复制</el-button> --> <!-- <el-button type="primary" link :icon='CopyDocument' @click="copyRow(scope.row)">复制</el-button> -->
<el-button :disabled="isDisable" type='primary' link :icon='EditPen' @click="openDialog('edit', scope.row)">编辑</el-button> <el-button
<el-button :disabled="isDisable" type='primary' link :icon='Delete' @click='handleDelete(scope.row.id)'>删除</el-button> :disabled="isDisable"
type="primary"
link
:icon="EditPen"
@click="openDialog('edit', scope.row)"
>
编辑
</el-button>
<el-button :disabled="isDisable" type="primary" link :icon="Delete" @click="handleDelete(scope.row.id)">
删除
</el-button>
</template> </template>
</ProTable> </ProTable>
</div> </div>
<ParameterPopup @getParameter="getParameter" ref='parameterPopup' :tableData="tableData"/> <ParameterPopup @getParameter="getParameter" ref="parameterPopup" :tableData="tableData" />
</template> </template>
<script setup lang='tsx' name='useRole'> <script setup lang="tsx" name="useRole">
import { type TestSource } from '@/api/device/interface/testSource' import { type TestSource } from '@/api/device/interface/testSource'
import ProTable from '@/components/ProTable/index.vue' import ProTable from '@/components/ProTable/index.vue'
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface' import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import {CirclePlus, CopyDocument, Delete, EditPen} from '@element-plus/icons-vue' import { CirclePlus, Delete, EditPen } from '@element-plus/icons-vue'
import {useDictStore} from '@/stores/modules/dict' import ParameterPopup from '@/views/machine/testSource/components/parameterPopup.vue'
import ParameterPopup from '@/views/machine/testSource/components/parameterPopup.vue';
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import {generateUUID} from "@/styles"; import { generateUUID } from '@/styles'
import {defineEmits} from "vue/dist/vue";
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
const parameterPopup = ref() const parameterPopup = ref()
const dictStore = useDictStore()
const btnDelete = ref(false)
// ProTable 实例 // ProTable 实例
const proTable = ref<ProTableInstance>() const proTable = ref<ProTableInstance>()
const tableData = ref<any[]>([]) const tableData = ref<any[]>([])
const props = defineProps({ const props = defineProps({
parameterStr: { parameterStr: {
type: String, type: String,
required: true, required: true
}, },
isDisable: { isDisable: {
type: Boolean, type: Boolean,
default: false, default: false
}, }
}); })
const emit = defineEmits(['change-parameter']) const emit = defineEmits(['change-parameter'])
let originalParameterArr = reactive<TestSource.ParameterType[]>([]) let originalParameterArr = reactive<TestSource.ParameterType[]>([])
watch(() => props.parameterStr, (newData) => { watch(
() => props.parameterStr,
newData => {
if (newData) { if (newData) {
getTableList() getTableList()
} }
}) }
)
const defaultExpandRowKeys = computed(() => { const defaultExpandRowKeys = computed(() => {
return getDefaultKeyArray(tableData.value) return getDefaultKeyArray(tableData.value)
@@ -98,24 +119,23 @@ const getTableList = () => {
originalParameterArr = JSON.parse(props.parameterStr) originalParameterArr = JSON.parse(props.parameterStr)
tableData.value = getTreeData(originalParameterArr) tableData.value = getTreeData(originalParameterArr)
} }
}; }
const getTreeData = (data: TestSource.ParameterType[]): TestSource.ParameterType[] => { const getTreeData = (data: TestSource.ParameterType[]): TestSource.ParameterType[] => {
const result: TestSource.ParameterType[] = [] // 最终返回的树形结构数据 const result: TestSource.ParameterType[] = [] // 最终返回的树形结构数据
//不能修改原数组,所以需要深拷贝 //不能修改原数组,所以需要深拷贝
const copyData = JSON.parse(JSON.stringify(data)) const copyData = JSON.parse(JSON.stringify(data))
const map = new Map<string, TestSource.ParameterType>(); const map = new Map<string, TestSource.ParameterType>()
copyData.forEach(item => { copyData.forEach(item => {
map.set(item.id, item) map.set(item.id, item)
}); })
for (const item of copyData) { for (const item of copyData) {
let parent = map.get(item.pId); let parent = map.get(item.pId)
if (parent) { if (parent) {
if (!parent.children) { if (!parent.children) {
parent.children = []; parent.children = []
} }
parent.children.push(item); parent.children.push(item)
parent.children.sort((a, b) => { parent.children.sort((a, b) => {
if (a.sort && b.sort) { if (a.sort && b.sort) {
return a.sort - b.sort return a.sort - b.sort
@@ -138,13 +158,16 @@ const getTreeData = (data: TestSource.ParameterType[]): TestSource.ParameterType
} }
const columns = reactive<ColumnProps<any>[]>([ const columns = reactive<ColumnProps<any>[]>([
{type: 'selection', fixed: 'left', width: 70, {
type: 'selection',
fixed: 'left',
width: 70,
selectable(row, index) { selectable(row, index) {
if (props.isDisable) { if (props.isDisable) {
return false; return false
}
return true
} }
return true;
},
}, },
{ type: 'index', fixed: 'left', width: 70, label: '序号' }, { type: 'index', fixed: 'left', width: 70, label: '序号' },
{ {
@@ -153,89 +176,88 @@ const columns = reactive<ColumnProps<any>[]>([
minWidth: 180, minWidth: 180,
align: 'left', align: 'left',
headerAlign: 'center' headerAlign: 'center'
}, },
{ {
prop: 'desc', prop: 'desc',
label: '参数描述', label: '参数描述',
minWidth: 220, minWidth: 220
}, },
{ {
prop: 'value', prop: 'value',
label: '值', label: '值',
minWidth: 150, minWidth: 150
}, },
{prop: 'operation', label: '操作', fixed: 'right', width: 250}, { prop: 'operation', label: '操作', fixed: 'right', width: 250 }
]) ])
// 打开 drawer(新增、编辑) // 打开 drawer(新增、编辑)
const openDialog = (titleType: string, row: Partial<TestSource.ParameterType> = {}) => { const openDialog = (titleType: string, row: Partial<TestSource.ParameterType> = {}) => {
parameterPopup.value?.open(titleType, row) parameterPopup.value?.open(titleType, row)
} }
// 批量删除源参数 // 批量删除源参数
const batchDelete = async (ids: string[]) => { const batchDelete = async (ids: string[]) => {
ElMessageBox.confirm(`是否批量删除检测源?`, "温馨提示", { ElMessageBox.confirm(`是否批量删除检测源?`, '温馨提示', {
confirmButtonText: "确定", confirmButtonText: '确定',
cancelButtonText: "取消", cancelButtonText: '取消',
draggable: true draggable: true
}).then(async () => { }).then(async () => {
let parentIds = originalParameterArr.map(item => item.pId); let parentIds = originalParameterArr.map(item => item.pId)
if (parentIds.some(item => ids.includes(item))) { if (parentIds.some(item => ids.includes(item))) {
ElMessage.error('不能删除父节点'); ElMessage.error('不能删除父节点')
return; return
} }
// 直接过滤掉需要删除的项 // 直接过滤掉需要删除的项
originalParameterArr = originalParameterArr.filter(item => !ids.includes(item.id)); originalParameterArr = originalParameterArr.filter(item => !ids.includes(item.id))
emit('change-parameter', originalParameterArr); emit('change-parameter', originalParameterArr)
tableData.value = getTreeData(originalParameterArr); tableData.value = getTreeData(originalParameterArr)
ElMessage({ ElMessage({
type: "success", type: 'success',
message: `批量删除检测源成功!` message: `批量删除检测源成功!`
}); })
}); })
} }
// 删除源参数 // 删除源参数
const handleDelete = (id: string) => { const handleDelete = (id: string) => {
ElMessageBox.confirm(`是否删除检测源?`, "温馨提示", { ElMessageBox.confirm(`是否删除检测源?`, '温馨提示', {
confirmButtonText: "确定", confirmButtonText: '确定',
cancelButtonText: "取消", cancelButtonText: '取消',
draggable: true draggable: true
}).then(async () => { }).then(async () => {
let parentIds = originalParameterArr.map(item => item.pId); let parentIds = originalParameterArr.map(item => item.pId)
if (parentIds.includes(id)) { if (parentIds.includes(id)) {
ElMessage.error('不能删除父节点'); ElMessage.error('不能删除父节点')
return; return
} }
originalParameterArr = originalParameterArr.filter(item => item.id !== id); originalParameterArr = originalParameterArr.filter(item => item.id !== id)
emit('change-parameter', originalParameterArr); emit('change-parameter', originalParameterArr)
tableData.value = getTreeData(originalParameterArr); tableData.value = getTreeData(originalParameterArr)
ElMessage({ ElMessage({
type: "success", type: 'success',
message: `删除检测源成功!` message: `删除检测源成功!`
}); })
}); })
} }
// 复制源参数 // 复制源参数
const copyRow = (row) => { const copyRow = row => {
delete row.children delete row.children
let parentIds = originalParameterArr.map(item => item.pId) let parentIds = originalParameterArr.map(item => item.pId)
if (parentIds.includes(row.id)) { if (parentIds.includes(row.id)) {
let newParameterId = generateUUID().replaceAll("-","") let newParameterId = generateUUID().replaceAll('-', '')
let children = originalParameterArr.filter(item => item.pId == row.id).map(item => ({ let children = originalParameterArr
.filter(item => item.pId == row.id)
.map(item => ({
...item, ...item,
id: generateUUID().replaceAll("-",""), id: generateUUID().replaceAll('-', ''),
pId: newParameterId pId: newParameterId
})) }))
originalParameterArr.push({ ...row, id: newParameterId }) originalParameterArr.push({ ...row, id: newParameterId })
originalParameterArr.push(...children) originalParameterArr.push(...children)
} else { } else {
originalParameterArr.push({...row, id: generateUUID().replaceAll("-",""), pId: row.pId}) originalParameterArr.push({ ...row, id: generateUUID().replaceAll('-', ''), pId: row.pId })
} }
emit('change-parameter', originalParameterArr) emit('change-parameter', originalParameterArr)
tableData.value = getTreeData(originalParameterArr) tableData.value = getTreeData(originalParameterArr)
@@ -248,9 +270,8 @@ const getParameter = (data: TestSource.ParameterType) => {
// } // }
let index = originalParameterArr.findIndex(item => item.id === data.id) let index = originalParameterArr.findIndex(item => item.id === data.id)
if (index === -1) { if (index === -1) {
data.id = generateUUID().replaceAll("-","") data.id = generateUUID().replaceAll('-', '')
// 新增 // 新增
originalParameterArr.push(data) originalParameterArr.push(data)
ElMessage.success({ message: '新增成功!' }) ElMessage.success({ message: '新增成功!' })
@@ -274,7 +295,4 @@ defineExpose({
}) })
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -1,9 +1,16 @@
<template> <template>
<el-dialog :title="dialogTitle" v-model='dialogVisible' @close="close" v-bind="dialogBig" align-center> <el-dialog :title="dialogTitle" v-model="dialogVisible" @close="close" v-bind="dialogBig" align-center>
<div> <div>
<el-form :model="formContent" ref='dialogFormRef' :rules='rules' :disabled="tableIsDisable" label-width="auto" class="form-three"> <el-form
:model="formContent"
ref="dialogFormRef"
:rules="rules"
:disabled="tableIsDisable"
label-width="auto"
class="form-three"
>
<el-form-item label="设备类型" prop="devType"> <el-form-item label="设备类型" prop="devType">
<el-select v-model='formContent.devType' placeholder="请选择源型号"> <el-select v-model="formContent.devType" placeholder="请选择源型号">
<el-option <el-option
v-for="item in dictStore.getDictData(dictTypeCode)" v-for="item in dictStore.getDictData(dictTypeCode)"
:key="item.id" :key="item.id"
@@ -13,7 +20,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="检测源类型" prop="type"> <el-form-item label="检测源类型" prop="type">
<el-select v-model='formContent.type' placeholder="请选择检测源类型"> <el-select v-model="formContent.type" placeholder="请选择检测源类型">
<el-option <el-option
v-for="item in dictStore.getDictData('Pq_Source_Type')" v-for="item in dictStore.getDictData('Pq_Source_Type')"
:key="item.id" :key="item.id"
@@ -25,25 +32,28 @@
</el-form> </el-form>
</div> </div>
<ParameterTable :parameterStr="formContent.parameter" @change-parameter="changeParameter" ref="parameterTable" :is-disable="tableIsDisable"/> <ParameterTable
:parameterStr="formContent.parameter"
@change-parameter="changeParameter"
ref="parameterTable"
:is-disable="tableIsDisable"
/>
<template #footer> <template #footer>
<div> <div>
<el-button :disabled="tableIsDisable" @click='close()'> </el-button> <el-button :disabled="tableIsDisable" @click="close()"> </el-button>
<el-button :disabled="tableIsDisable" type="primary" @click='save()'>保存</el-button> <el-button :disabled="tableIsDisable" type="primary" @click="save()">保存</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup name="ErrorSystemDialog"> <script lang="ts" setup name="ErrorSystemDialog">
import { ElMessage, type FormItemRule } from 'element-plus' import { ElMessage, type FormItemRule } from 'element-plus'
import {computed, defineProps, Ref, ref} from 'vue'; import { computed, Ref, ref } from 'vue'
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import { addTestSource, getTestSourceById, updateTestSource } from '@/api/device/testSource/index' import { addTestSource, getTestSourceById, updateTestSource } from '@/api/device/testSource/index'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import {type TestSource} from '@/api/device/interface/testSource'; import { type TestSource } from '@/api/device/interface/testSource'
// 定义弹出组件元信息 // 定义弹出组件元信息
const dialogFormRef = ref() const dialogFormRef = ref()
const dictStore = useDictStore() const dictStore = useDictStore()
@@ -61,7 +71,7 @@ function useMetaInfo() {
parameter: '', parameter: '',
type: '', type: '',
devType: '', devType: '',
state: 1, state: 1
}) })
return { dialogVisible, titleType, formContent } return { dialogVisible, titleType, formContent }
} }
@@ -75,7 +85,7 @@ const resetFormContent = () => {
parameter: '', parameter: '',
type: '', type: '',
devType: '', devType: '',
state: 1, state: 1
} }
} }
@@ -83,17 +93,17 @@ let dialogTitle = computed(() => {
switch (titleType.value) { switch (titleType.value) {
case 'add': case 'add':
tableIsDisable.value = false tableIsDisable.value = false
return '新增检测源'; return '新增检测源'
case 'edit': case 'edit':
tableIsDisable.value = false tableIsDisable.value = false
return '编辑检测源'; return '编辑检测源'
case 'view': case 'view':
tableIsDisable.value = true tableIsDisable.value = true
return '查看检测源'; return '查看检测源'
default: default:
return ''; // 默认情况,可选 return '' // 默认情况,可选
} }
}); })
let dictTypeCode = computed(() => { let dictTypeCode = computed(() => {
return 'S_Dev_Type_' + dictStore.getDictData('Pattern').find(item => item.id === modeId.value)?.code return 'S_Dev_Type_' + dictStore.getDictData('Pattern').find(item => item.id === modeId.value)?.code
@@ -101,10 +111,9 @@ let dictTypeCode = computed(() => {
// 定义规则 // 定义规则
const rules: Ref<Record<string, Array<FormItemRule>>> = ref({ const rules: Ref<Record<string, Array<FormItemRule>>> = ref({
name: [{ required: true, message: '检测源名称必填!', trigger: 'blur' }], name: [{ required: true, message: '检测源名称必填!', trigger: 'blur' }],
devType: [{required: true, message: '请选择一项设备类型', trigger: 'change'},], devType: [{ required: true, message: '请选择一项设备类型', trigger: 'change' }],
type: [{required: true, message: '请选择一项检测源类型', trigger: 'change '},] type: [{ required: true, message: '请选择一项检测源类型', trigger: 'change ' }]
}); })
// 关闭弹窗 // 关闭弹窗
const close = () => { const close = () => {
@@ -120,13 +129,12 @@ const close = () => {
const save = () => { const save = () => {
try { try {
dialogFormRef.value?.validate(async (valid: boolean) => { dialogFormRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {
if (formContent.value.id) { if (formContent.value.id) {
await updateTestSource(formContent.value); await updateTestSource(formContent.value)
ElMessage.success({ message: `${dialogTitle.value}成功!` }) ElMessage.success({ message: `${dialogTitle.value}成功!` })
} else { } else {
await addTestSource(formContent.value); await addTestSource(formContent.value)
ElMessage.success({ message: `${dialogTitle.value}成功!` }) ElMessage.success({ message: `${dialogTitle.value}成功!` })
} }
close() close()
@@ -144,11 +152,11 @@ const open = async (sign: string, data: TestSource.ResTestSource, currentMode: s
titleType.value = sign titleType.value = sign
dialogVisible.value = true dialogVisible.value = true
mode.value = currentMode mode.value = currentMode
modeId.value = dictStore.getDictData('Pattern').find(item => item.name === currentMode)?.id; modeId.value = dictStore.getDictData('Pattern').find(item => item.name === currentMode)?.id
if (data.id) { if (data.id) {
const result = await getTestSourceById(data); const result = await getTestSourceById(data)
if (result && result.data) { if (result && result.data) {
formContent.value = result.data as TestSource.ResTestSource; formContent.value = result.data as TestSource.ResTestSource
} }
} else { } else {
resetFormContent() resetFormContent()
@@ -157,8 +165,6 @@ const open = async (sign: string, data: TestSource.ResTestSource, currentMode: s
dialogFormRef.value?.resetFields() dialogFormRef.value?.resetFields()
} }
const changeParameter = (parameterArr: any) => { const changeParameter = (parameterArr: any) => {
formContent.value.parameter = JSON.stringify(parameterArr) formContent.value.parameter = JSON.stringify(parameterArr)
} }
@@ -166,9 +172,7 @@ const changeParameter = (parameterArr: any) => {
// 对外映射 // 对外映射
defineExpose({ open }) defineExpose({ open })
const props = defineProps<{ const props = defineProps<{
refreshTable: (() => Promise<void>) | undefined; refreshTable: (() => Promise<void>) | undefined
}>() }>()
</script> </script>
<style> <style></style>
</style>

View File

@@ -0,0 +1,527 @@
<template>
<div class="table_info">
<ProTable
ref="proTable"
:columns="columns"
:request-api="getTableList"
:init-param="initParam"
:data-callback="dataCallback"
@drag-sort="sortTable"
:height="tableHeight"
:stripe="true"
>
<!-- 表格 header 按钮 -->
<template #tableHeader="scope">
<el-form :model="form" label-width="80px" :inline="true">
<el-form-item label="检测状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkStatus">
<el-option
v-for="(item, index) in checkStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="报告状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkReportStatus">
<el-option
v-for="(item, index) in checkReportStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="检测结果" v-if="form.activeTabs != 5">
<el-select v-model="form.checkResult">
<el-option
v-for="(item, index) in checkResultList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="绑定状态" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceBindStatus">
<el-option
v-for="(item, index) in deviceBindStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备类型" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceType">
<el-option
v-for="(item, index) in deviceTypeList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="制造厂商" v-if="form.activeTabs == 5">
<el-select v-model="form.manufacturer">
<el-option
v-for="(item, index) in manufacturerList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
<el-button type="primary" @click="handleTest" v-if="form.activeTabs === 0">
启动自动检测
</el-button>
<el-button type="primary" @click="handleTest" v-if="form.activeTabs === 1">
启动手动检测
</el-button>
<el-button type="primary" v-if="form.activeTabs === 2">报告生成</el-button>
<el-button type="primary" v-if="form.activeTabs === 5">设备导入</el-button>
</el-form-item>
</el-form>
</template>
<!-- 表格操作 -->
<!-- <template #operation="scope">
<el-button
dictType="primary"
link
:icon="View"
@click="openDrawer('查看', scope.row)"
>查看</el-button
>
<el-button
dictType="primary"
link
:icon="EditPen"
@click="openDrawer('编辑', scope.row)"
>导出</el-button
>
<el-button
dictType="primary"
link
:icon="Delete"
@click="deleteAccount(scope.row)"
>删除</el-button
>
</template> -->
</ProTable>
</div>
</template>
<script setup lang="tsx" name="useProTable">
import { onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { User } from '@/api/interface'
import { useHandleData } from '@/hooks/useHandleData'
import { ElMessage } from 'element-plus'
import ProTable from '@/components/ProTable/index.vue'
import { Search } from '@element-plus/icons-vue'
import { getPlanList } from '@/api/plan/planList'
const router = useRouter()
const value1 = ref('')
const value2 = ref('')
const tableHeight = ref(0)
console.log(window.innerHeight, '+++++++++')
tableHeight.value = window.innerHeight - 630
//下拉框数据
//检测状态数据
const checkStatusList = [
{
label: '未检',
value: 0
},
{
label: '检测中',
value: 1
},
{
label: '检测完成',
value: 2
},
{
label: '归档',
value: 3
}
]
//检测报告状态数据
const checkReportStatusList = [
{
label: '未生成报告',
value: 0
},
{
label: '已生成报告',
value: 1
}
]
//检测结果数组
const checkResultList = [
{
label: '/',
value: null
},
{
label: '不合格',
value: 0
},
{
label: '合格',
value: 1
}
]
//绑定状态数组
const deviceBindStatusList = [
{
label: '未绑定',
value: 0
},
{
label: '已绑定',
value: 1
}
]
//设备类型数组
const deviceTypeList = [
{
label: 'PQS882A',
value: 0
},
{
label: 'PQS882B4',
value: 1
},
{
label: 'PQS882B5',
value: 2
},
{
label: 'PQS882B6',
value: 3
},
{
label: 'PQS882B7',
value: 4
},
{
label: 'PQS882B8',
value: 5
}
]
//制造厂商数组
const manufacturerList = [
{
label: '南京灿能电力',
value: 0
},
{
label: '南瑞继保',
value: 1
},
{
label: '中电',
value: 2
}
]
//查询条件
const form: any = ref({
activeTabs: 0, //功能选择
checkStatus: 0, //检测状态
checkReportStatus: 0, //检测报告状态
checkResult: 0, //检测结果
deviceBindStatus: 0, //绑定状态
deviceType: 0, //设备类型
manufacturer: 0 //制造厂商
})
const searchForm = ref({
intervalType: 0,
time: ['2024-08-20', '2024-08-27'],
searchBeginTime: '',
searchEndTime: '',
checkStatus: 0,
checkReportStatus: 0,
checkResult: 0
})
// ProTable 实例
const proTable = ref<ProTableInstance>()
// 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
const initParam = reactive({ type: 1, pageNum: 1, pageSize: 10 })
// dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
// 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
const tableList = ref([])
const dataCallback = (data: any) => {
return {
list: data || data.data || data.list,
total: data.length || data.total //total
}
}
// 如果你想在请求之前对当前请求参数做一些操作可以自定义如下函数params 为当前所有的请求参数(包括分页),最后返回请求列表接口
// 默认不做操作就直接在 ProTable 组件上绑定 :requestApi="getUserList"
const getTableList = (params: any) => {
let newParams = JSON.parse(JSON.stringify(params))
newParams.createTime && (newParams.startTime = newParams.createTime[0])
newParams.createTime && (newParams.endTime = newParams.createTime[1])
delete newParams.createTime
return getPlanList(newParams)
}
// 表格配置项
const columns = reactive<ColumnProps<User.ResUserList>[]>([
{ type: 'selection', fixed: 'left', width: 70 },
{
prop: 'checkMode',
label: '设备序列号',
width: 140,
render: scope => {
return scope.row.checkMode == 0
? '设备1'
: scope.row.checkMode == 1
? '设备2'
: scope.row.checkMode == 2
? '设备3'
: scope.row.checkMode
}
},
{
prop: 'checkMode',
label: '设备类型',
width: 140,
render: scope => {
return scope.row.checkMode == 0
? 'PQS991'
: scope.row.checkMode == 1
? 'PQS882'
: scope.row.checkMode == 2
? 'PQS6666'
: scope.row.checkMode
}
},
{
prop: 'checkFrom',
label: '制造厂商',
width: 140,
render: scope => {
return scope.row.checkFrom == 0
? '南京灿能'
: scope.row.checkFrom == 1
? '南瑞继保'
: scope.row.checkFrom == 2
? '/'
: scope.row.checkFrom
}
},
{
prop: 'numberFromName',
label: 'MAC/IP',
render: scope => {
return scope.row.numberFromName == 0
? '192.168.0.1'
: scope.row.numberFromName == 1
? '192.168.0.2'
: scope.row.numberFromName == 2
? '192.168.0.3'
: scope.row.numberFromName
}
}
// {
// prop: "checkExe",
// label: "检测脚本",
// render: (scope) => {
// return scope.row.checkExe == 0
// ? "国网入网检测脚本(单影响量-模拟式)"
// : scope.row.checkExe == 1
// ? "国网入网检测脚本"
// : scope.row.checkExe == 2
// ? "/"
// : scope.row.checkExe;
// },
// },
// {
// prop: "wctx",
// label: "误差体系",
// render: (scope) => {
// return scope.row.wctx == 0
// ? "Q/GDW 1650.2- 2016"
// : scope.row.wctx == 1
// ? "Q/GDW 10650.2 - 2021"
// : scope.row.wctx == 2
// ? "/"
// : scope.row.wctx;
// },
// },
// {
// prop: "checkStatus",
// label: "检测状态",
// width: 120,
// render: (scope) => {
// return scope.row.checkStatus == 1
// ? "未检"
// : scope.row.checkStatus == 2
// ? "检测中"
// : scope.row.checkStatus == 3
// ? "检测完成"
// : scope.row.checkStatus;
// },
// },
// {
// prop: "checkReport",
// label: "检测报告",
// width: 120,
// render: (scope) => {
// return scope.row.checkReport == 1
// ? "未生成"
// : scope.row.checkReport == 2
// ? "部分生成"
// : scope.row.checkReport == 3
// ? "全部生成"
// : scope.row.checkReport;
// },
// },
// {
// prop: "checkResult",
// label: "检测结果",
// width: 120,
// render: (scope) => {
// return scope.row.checkReport == 1
// ? "/"
// : scope.row.checkReport == 2
// ? "符合"
// : scope.row.checkReport == 3
// ? "不符合"
// : scope.row.checkReport;
// },
// },
// {
// prop: "parentNode",
// label: "父节点",
// width: 90,
// render: (scope) => {
// return scope.row.checkReport == 0
// ? "/"
// : scope.row.checkReport == 1
// ? "检测计划1"
// : scope.row.checkReport == 2
// ? "检测计划2"
// : scope.row.checkReport == 3
// ? "检测计划3"
// : scope.row.checkReport;
// },
// },
// { prop: "operation", label: "操作", fixed: "right", width: 250 },
])
// 跳转详情页
const toDetail = () => {
router.push(`/proTable/useProTable/detail/${Math.random().toFixed(3)}?params=detail-page`)
}
//重置查询条件
const resetSearchForm = () => {
searchForm.value = {
intervalType: 0,
time: ['2024-08-20', '2024-08-27'],
searchBeginTime: '',
searchEndTime: '',
checkStatus: 0,
checkReportStatus: 0,
checkResult: 0
}
}
//查询
const handleSearch = () => {
proTable.value?.getTableList()
}
//重置
const handleRefresh = () => {
proTable.value?.getTableList()
}
// 表格拖拽排序
const sortTable = ({ newIndex, oldIndex }: { newIndex?: number; oldIndex?: number }) => {
console.log(newIndex, oldIndex)
console.log(proTable.value?.tableData)
ElMessage.success('修改列表排序成功')
}
// 删除用户信息
const deleteAccount = async (params: User.ResUserList) => {
await useHandleData(deleteUser, { id: [params.id] }, `删除【${params.username}`)
proTable.value?.getTableList()
}
// 批量删除用户信息
const batchDelete = async (id: string[]) => {
await useHandleData(deleteUser, { id }, '删除所选用户信息')
proTable.value?.clearSelection()
proTable.value?.getTableList()
}
// 重置用户密码
const resetPass = async (params: User.ResUserList) => {
await useHandleData(resetUserPassWord, { id: params.id }, `重置【${params.username}】用户密码`)
proTable.value?.getTableList()
}
// 切换用户状态
const changeStatus = async (row: User.ResUserList) => {
await useHandleData(
changeUserStatus,
{ id: row.id, status: row.status == 1 ? 0 : 1 },
`切换【${row.username}】用户状态`
)
proTable.value?.getTableList()
}
//顶部功能切换时修改activeTabs
const changeActiveTabs = (val: number) => {
form.value.activeTabs = val
}
//启动自动检测/手动检测
const handleTest = () => {
//自动检测
if (form.value.activeTabs === 0) {
ElMessage.success('自动检测')
router.push({
path: '/plan/autoTest'
})
} else {
ElMessage.warning('手动检测')
}
}
onMounted(() => {
console.log(proTable.value?.tableData)
})
defineExpose({ changeActiveTabs })
</script>
<style lang="scss" scoped>
/* 当屏幕宽度小于或等于1300像素时 */
@media screen and (max-width: 1300px) {
.el-select {
width: 130px !important;
}
}
@media screen and (min-width: 1300px) {
.el-select {
width: 150px !important;
}
}
.el-form {
width: 100%;
display: flex;
flex-wrap: wrap;
.el-form-item {
display: flex;
align-items: center;
justify-content: space-between;
.el-button {
margin: 0 !important;
margin-right: 10px !important;
}
}
}
</style>

View File

@@ -1,568 +0,0 @@
<template>
<div class="table_info">
<ProTable
ref="proTable"
:columns="columns"
:request-api="getTableList"
:init-param="initParam"
:data-callback="dataCallback"
@drag-sort="sortTable"
:height="tableHeight"
:stripe="true"
>
<!-- 表格 header 按钮 -->
<template #tableHeader="scope">
<el-form :model="form" label-width="80px" :inline="true">
<el-form-item label="检测状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkStatus">
<el-option
v-for="(item, index) in checkStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="报告状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkReportStatus">
<el-option
v-for="(item, index) in checkReportStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="检测结果" v-if="form.activeTabs != 5">
<el-select v-model="form.checkResult">
<el-option
v-for="(item, index) in checkResultList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="绑定状态" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceBindStatus">
<el-option
v-for="(item, index) in deviceBindStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备类型" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceType">
<el-option
v-for="(item, index) in deviceTypeList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="制造厂商" v-if="form.activeTabs == 5">
<el-select v-model="form.manufacturer">
<el-option
v-for="(item, index) in manufacturerList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleSearch"
>查询</el-button
>
<el-button
type="primary"
@click="handleTest"
v-if="form.activeTabs === 0"
>启动自动检测</el-button
>
<el-button
type="primary"
@click="handleTest"
v-if="form.activeTabs === 1"
>启动手动检测</el-button
>
<el-button type="primary" v-if="form.activeTabs === 2"
>报告生成</el-button
>
<el-button type="primary" v-if="form.activeTabs === 5"
>设备导入</el-button
>
</el-form-item>
</el-form>
</template>
<!-- 表格操作 -->
<!-- <template #operation="scope">
<el-button
dictType="primary"
link
:icon="View"
@click="openDrawer('查看', scope.row)"
>查看</el-button
>
<el-button
dictType="primary"
link
:icon="EditPen"
@click="openDrawer('编辑', scope.row)"
>导出</el-button
>
<el-button
dictType="primary"
link
:icon="Delete"
@click="deleteAccount(scope.row)"
>删除</el-button
>
</template> -->
</ProTable>
</div>
</template>
<script setup lang="tsx" name="useProTable">
import { ref, reactive, onMounted } from "vue";
import { useRouter } from "vue-router";
import { User } from "@/api/interface";
import { useHandleData } from "@/hooks/useHandleData";
import { useDownload } from "@/hooks/useDownload";
import { ElMessage, ElMessageBox } from "element-plus";
import ProTable from "@/components/ProTable/index.vue";
import ImportExcel from "@/components/ImportExcel/index.vue";
import {
CirclePlus,
Delete,
EditPen,
Download,
Upload,
View,
Refresh,
Search,
} from "@element-plus/icons-vue";
import { getPlanList } from "@/api/plan/planList";
const router = useRouter();
const value1 = ref("");
const value2 = ref("");
const tableHeight = ref(0);
console.log(window.innerHeight, "+++++++++");
tableHeight.value = window.innerHeight - 630;
//下拉框数据
//检测状态数据
const checkStatusList = [
{
label: "未检",
value: 0,
},
{
label: "检测中",
value: 1,
},
{
label: "检测完成",
value: 2,
},
{
label: "归档",
value: 3,
},
];
//检测报告状态数据
const checkReportStatusList = [
{
label: "未生成报告",
value: 0,
},
{
label: "已生成报告",
value: 1,
},
];
//检测结果数组
const checkResultList = [
{
label: "/",
value: null,
},
{
label: "不合格",
value: 0,
},
{
label: "合格",
value: 1,
},
];
//绑定状态数组
const deviceBindStatusList = [
{
label: "未绑定",
value: 0,
},
{
label: "已绑定",
value: 1,
},
];
//设备类型数组
const deviceTypeList = [
{
label: "PQS882A",
value: 0,
},
{
label: "PQS882B4",
value: 1,
},
{
label: "PQS882B5",
value: 2,
},
{
label: "PQS882B6",
value: 3,
},
{
label: "PQS882B7",
value: 4,
},
{
label: "PQS882B8",
value: 5,
},
];
//制造厂商数组
const manufacturerList = [
{
label: "南京灿能电力",
value: 0,
},
{
label: "南瑞继保",
value: 1,
},
{
label: "中电",
value: 2,
},
];
//查询条件
const form: any = ref({
activeTabs: 0, //功能选择
checkStatus: 0, //检测状态
checkReportStatus: 0, //检测报告状态
checkResult: 0, //检测结果
deviceBindStatus: 0, //绑定状态
deviceType: 0, //设备类型
manufacturer: 0, //制造厂商
});
const searchForm = ref({
intervalType: 0,
time: ["2024-08-20", "2024-08-27"],
searchBeginTime: "",
searchEndTime: "",
checkStatus: 0,
checkReportStatus: 0,
checkResult: 0,
});
// ProTable 实例
const proTable = ref<ProTableInstance>();
// 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
const initParam = reactive({ type: 1, pageNum: 1, pageSize: 10 });
// dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
// 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
const tableList = ref([]);
const dataCallback = (data: any) => {
return {
list: data || data.data || data.list,
total: data.length || data.total, //total
};
};
// 如果你想在请求之前对当前请求参数做一些操作可以自定义如下函数params 为当前所有的请求参数(包括分页),最后返回请求列表接口
// 默认不做操作就直接在 ProTable 组件上绑定 :requestApi="getUserList"
const getTableList = (params: any) => {
let newParams = JSON.parse(JSON.stringify(params));
newParams.createTime && (newParams.startTime = newParams.createTime[0]);
newParams.createTime && (newParams.endTime = newParams.createTime[1]);
delete newParams.createTime;
return getPlanList(newParams);
};
// 表格配置项
const columns = reactive<ColumnProps<User.ResUserList>[]>([
{ type: "selection", fixed: "left", width: 70 },
{
prop: "checkMode",
label: "设备序列号",
width: 140,
render: (scope) => {
return scope.row.checkMode == 0
? "设备1"
: scope.row.checkMode == 1
? "设备2"
: scope.row.checkMode == 2
? "设备3"
: scope.row.checkMode;
},
},
{
prop: "checkMode",
label: "设备类型",
width: 140,
render: (scope) => {
return scope.row.checkMode == 0
? "PQS991"
: scope.row.checkMode == 1
? "PQS882"
: scope.row.checkMode == 2
? "PQS6666"
: scope.row.checkMode;
},
},
{
prop: "checkFrom",
label: "制造厂商",
width: 140,
render: (scope) => {
return scope.row.checkFrom == 0
? "南京灿能"
: scope.row.checkFrom == 1
? "南瑞继保"
: scope.row.checkFrom == 2
? "/"
: scope.row.checkFrom;
},
},
{
prop: "numberFromName",
label: "MAC/IP",
render: (scope) => {
return scope.row.numberFromName == 0
? "192.168.0.1"
: scope.row.numberFromName == 1
? "192.168.0.2"
: scope.row.numberFromName == 2
? "192.168.0.3"
: scope.row.numberFromName;
},
},
// {
// prop: "checkExe",
// label: "检测脚本",
// render: (scope) => {
// return scope.row.checkExe == 0
// ? "国网入网检测脚本(单影响量-模拟式)"
// : scope.row.checkExe == 1
// ? "国网入网检测脚本"
// : scope.row.checkExe == 2
// ? "/"
// : scope.row.checkExe;
// },
// },
// {
// prop: "wctx",
// label: "误差体系",
// render: (scope) => {
// return scope.row.wctx == 0
// ? "Q/GDW 1650.2- 2016"
// : scope.row.wctx == 1
// ? "Q/GDW 10650.2 - 2021"
// : scope.row.wctx == 2
// ? "/"
// : scope.row.wctx;
// },
// },
// {
// prop: "checkStatus",
// label: "检测状态",
// width: 120,
// render: (scope) => {
// return scope.row.checkStatus == 1
// ? "未检"
// : scope.row.checkStatus == 2
// ? "检测中"
// : scope.row.checkStatus == 3
// ? "检测完成"
// : scope.row.checkStatus;
// },
// },
// {
// prop: "checkReport",
// label: "检测报告",
// width: 120,
// render: (scope) => {
// return scope.row.checkReport == 1
// ? "未生成"
// : scope.row.checkReport == 2
// ? "部分生成"
// : scope.row.checkReport == 3
// ? "全部生成"
// : scope.row.checkReport;
// },
// },
// {
// prop: "checkResult",
// label: "检测结果",
// width: 120,
// render: (scope) => {
// return scope.row.checkReport == 1
// ? "/"
// : scope.row.checkReport == 2
// ? "符合"
// : scope.row.checkReport == 3
// ? "不符合"
// : scope.row.checkReport;
// },
// },
// {
// prop: "parentNode",
// label: "父节点",
// width: 90,
// render: (scope) => {
// return scope.row.checkReport == 0
// ? "/"
// : scope.row.checkReport == 1
// ? "检测计划1"
// : scope.row.checkReport == 2
// ? "检测计划2"
// : scope.row.checkReport == 3
// ? "检测计划3"
// : scope.row.checkReport;
// },
// },
// { prop: "operation", label: "操作", fixed: "right", width: 250 },
]);
// 跳转详情页
const toDetail = () => {
router.push(
`/proTable/useProTable/detail/${Math.random().toFixed(3)}?params=detail-page`
);
};
//重置查询条件
const resetSearchForm = () => {
searchForm.value = {
intervalType: 0,
time: ["2024-08-20", "2024-08-27"],
searchBeginTime: "",
searchEndTime: "",
checkStatus: 0,
checkReportStatus: 0,
checkResult: 0,
};
};
//查询
const handleSearch = () => {
proTable.value?.getTableList();
};
//重置
const handleRefresh = () => {
proTable.value?.getTableList();
};
// 表格拖拽排序
const sortTable = ({
newIndex,
oldIndex,
}: {
newIndex?: number;
oldIndex?: number;
}) => {
console.log(newIndex, oldIndex);
console.log(proTable.value?.tableData);
ElMessage.success("修改列表排序成功");
};
// 删除用户信息
const deleteAccount = async (params: User.ResUserList) => {
await useHandleData(
deleteUser,
{ id: [params.id] },
`删除【${params.username}`
);
proTable.value?.getTableList();
};
// 批量删除用户信息
const batchDelete = async (id: string[]) => {
await useHandleData(deleteUser, { id }, "删除所选用户信息");
proTable.value?.clearSelection();
proTable.value?.getTableList();
};
// 重置用户密码
const resetPass = async (params: User.ResUserList) => {
await useHandleData(
resetUserPassWord,
{ id: params.id },
`重置【${params.username}】用户密码`
);
proTable.value?.getTableList();
};
// 切换用户状态
const changeStatus = async (row: User.ResUserList) => {
await useHandleData(
changeUserStatus,
{ id: row.id, status: row.status == 1 ? 0 : 1 },
`切换【${row.username}】用户状态`
);
proTable.value?.getTableList();
};
//顶部功能切换时修改activeTabs
const changeActiveTabs = (val: number) => {
form.value.activeTabs = val;
};
//启动自动检测/手动检测
const handleTest = () => {
//自动检测
if (form.value.activeTabs === 0) {
ElMessage.success("自动检测");
router.push({
path:"/plan/autoTest"
})
}else{
ElMessage.warning("手动检测");
}
};
onMounted(() => {
console.log(proTable.value?.tableData);
});
defineExpose({ changeActiveTabs });
</script>
<style lang="scss" scoped>
/* 当屏幕宽度小于或等于1300像素时 */
@media screen and (max-width: 1300px) {
.el-select {
width: 130px !important;
}
}
@media screen and (min-width: 1300px) {
.el-select {
width: 150px !important;
}
}
// ::v-deep .el-select {
// width: 150px !important;
// }
.el-form {
width: 100%;
display: flex;
flex-wrap: wrap;
.el-form-item {
display: flex;
align-items: center;
justify-content: space-between;
.el-button {
margin: 0 !important;
margin-right: 10px !important;
}
}
}
</style>

View File

@@ -11,14 +11,11 @@
v-model="item.selected" v-model="item.selected"
:key="index" :key="index"
:label="item.name" :label="item.name"
></el-checkbox ></el-checkbox>
>
<el-button type="primary" @click="handlePreTest">预检测</el-button> <el-button type="primary" @click="handlePreTest">预检测</el-button>
<el-button type="primary" @click="handleAutoTest">正式检测</el-button> <el-button type="primary" @click="handleAutoTest">正式检测</el-button>
<el-button type="primary" @click="handleBackDeviceList" <el-button type="primary" @click="handleBackDeviceList">返回首页</el-button>
>返回首页</el-button
>
<!-- <el-select v-model="currentErrSysID" placeholder="请选择误差体系" autocomplete="off"> <!-- <el-select v-model="currentErrSysID" placeholder="请选择误差体系" autocomplete="off">
<el-option <el-option
@@ -33,44 +30,24 @@
</div> </div>
<div class="test_bot"> <div class="test_bot">
<div class="test_left"> <div class="test_left">
<Tree ref="treeRef"></Tree> <AutoTestTree ref="treeRef"></AutoTestTree>
</div> </div>
<div class="test_right"> <div class="test_right">
<el-descriptions <el-descriptions
style=" style="width: 100%; border-radius: 6px; margin-bottom: 10px; background-color: #fff; padding: 10px"
width: 100%;
border-radius: 6px;
margin-bottom: 10px;
background-color: #fff;
padding: 10px;
"
:column="3" :column="3"
border border
> >
<template #extra> <template #extra>
<el-progress <el-progress style="width: 80%" :percentage="percentage" :color="customColors" />
style="width: 80%"
:percentage="percentage"
:color="customColors"
/>
<div class="test_button"> <div class="test_button">
<el-button <el-button type="primary" v-if="!isPause" :icon="VideoPause" @click="handlePauseTest">
type="primary" 暂停检测
v-if="!isPause" </el-button>
:icon="VideoPause" <el-button type="warning" v-if="isPause" :icon="Refresh" @click="handlePauseTest">
@click="handlePauseTest" 继续检测
>暂停检测</el-button </el-button>
> <el-button type="danger" :icon="Close" @click="handleFinishTest">停止检测</el-button>
<el-button
type="warning"
v-if="isPause"
:icon="Refresh"
@click="handlePauseTest"
>继续检测</el-button
>
<el-button type="danger" :icon="Close" @click="handleFinishTest"
>停止检测</el-button
>
<!-- <el-button <!-- <el-button
type="danger" type="danger"
v-if="!isPause" v-if="!isPause"
@@ -148,82 +125,69 @@
</div> </div>
<div class="right_status" ref="statusRef" v-if="!beforeTest"> <div class="right_status" ref="statusRef" v-if="!beforeTest">
<!-- ,fontSize:index%5===0?'16px':'14px' --> <!-- ,fontSize:index%5===0?'16px':'14px' -->
<p v-for="(item, index) in statusList" :key="index" :style="{color:index%5===0?'#F56C6C':'var(--el-text-color-regular)'}"> <p
输入{{ item.remark }} -{{ v-for="(item, index) in statusList"
item.status == 0 ? "输出完毕" : "输入中请稍后" :key="index"
}}<br /> :style="{ color: index % 5 === 0 ? '#F56C6C' : 'var(--el-text-color-regular)' }"
>
输入{{ item.remark }} -{{ item.status == 0 ? '输出完毕' : '输入中,请稍后!' }}
<br />
<span v-if="index == statusList.length - 1">...</span> <span v-if="index == statusList.length - 1">...</span>
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<ShowDataPopup ref='showDataPopup'/> <ShowDataPopup ref="showDataPopup" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, reactive, nextTick } from "vue"; import { nextTick, onMounted, ref } from 'vue'
import Tree from "./components/tree.vue"; import AutoTestTree from './components/autoTestTree.vue'
import { data } from "@/api/plan/autoTest.json"; import { data } from '@/api/plan/autoTest.json'
import { useTransition } from "@vueuse/core"; import { ElMessage, ElMessageBox } from 'element-plus'
import { getPlanList } from "@/api/plan/planList";
import { ElMessage, ElMessageBox } from "element-plus";
import ShowDataPopup from './components/ShowDataPopup.vue' import ShowDataPopup from './components/ShowDataPopup.vue'
import { import { Close, Refresh, VideoPause } from '@element-plus/icons-vue'
CirclePlus,
Delete,
EditPen,
Download,
Upload,
View,
Check,
Plus,
Refresh,
Search,
Close,
VideoPause,
} from "@element-plus/icons-vue";
import {dictPattern,dictTestState,dictReportState,dictResult,testPlanDataList,testSoureDataList,testScriptDataList,testErrSystDataList,planData,testFatherPlanList} from '@/api/plan/planData'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
const router = useRouter() const router = useRouter()
const currentErrSysID = ref("2") const currentErrSysID = ref('2')
const treeRef = ref<any>(); const treeRef = ref<any>()
const PopupVisible = ref(false) const PopupVisible = ref(false)
const showDataPopup = ref() const showDataPopup = ref()
const beforeTest = ref(true) const beforeTest = ref(true)
const testModel = ref("") const testModel = ref('')
//定义与预检测配置数组 //定义与预检测配置数组
const detectionOptions = ref([ const detectionOptions = ref([
{ {
id: 0, id: 0,
name: "标准源通讯检测",//判断源通讯是否正常 name: '标准源通讯检测', //判断源通讯是否正常
selected: true, selected: true
}, },
{ {
id: 1, id: 1,
name: "设备通讯检测",//判断设备的IP、Port、识别码、秘钥是否正常 name: '设备通讯检测', //判断设备的IP、Port、识别码、秘钥是否正常
selected: true, selected: true
}, },
{ {
id: 2, id: 2,
name: "协议校验",//ICD报告触发测试 name: '协议校验', //ICD报告触发测试
selected: true, selected: true
}, },
{ {
id: 3, id: 3,
name: "相序校验",//判断装置的接线是否正确 name: '相序校验', //判断装置的接线是否正确
selected: true, selected: true
}, },
{ {
id: 4, id: 4,
name: "守时校验",//判断装置24小时内的守时误差是否小于1s name: '守时校验', //判断装置24小时内的守时误差是否小于1s
selected: true, selected: true
}, },
{ {
id: 5, id: 5,
name: "通道系数校准",//通过私有协议与装置进行通讯,校准三相电压电流的通道系数 name: '通道系数校准', //通过私有协议与装置进行通讯,校准三相电压电流的通道系数
selected: true, selected: true
}, }
// { // {
// id: 6, // id: 6,
// name: "实时数据比对", // name: "实时数据比对",
@@ -232,7 +196,7 @@ const detectionOptions = ref([
// id: 7, // id: 7,
// name: "录波数据比对", // name: "录波数据比对",
// }, // },
]); ])
const leftDeviceData = ref<any>([ const leftDeviceData = ref<any>([
// { // {
@@ -265,59 +229,59 @@ const leftDeviceData = ref<any>([
// name: "设备6-预检测", // name: "设备6-预检测",
// status: 0, // status: 0,
// }, // },
]); ])
const initLeftDeviceData = () => { const initLeftDeviceData = () => {
leftDeviceData.value.map((item, index) => { leftDeviceData.value.map((item, index) => {
// handlePrintText(item.name, index); // handlePrintText(item.name, index);
}); })
}; }
const preTestData = [ const preTestData = [
{ {
"id": 0, id: 0,
"name": "预检测项目", name: '预检测项目',
"children": [ children: [
{ {
"scriptIdx":1, scriptIdx: 1,
"isChildNode":true, isChildNode: true,
"pid": "0-2", pid: '0-2',
"id": "0-2-2", id: '0-2-2',
"name": "标准源通讯检测" name: '标准源通讯检测'
}, },
{ {
"scriptIdx":2, scriptIdx: 2,
"isChildNode":true, isChildNode: true,
"pid": "0-3", pid: '0-3',
"id": "0-3-1", id: '0-3-1',
"name": "设备通讯检测" name: '设备通讯检测'
}, },
{ {
"scriptIdx":3, scriptIdx: 3,
"isChildNode":true, isChildNode: true,
"pid": "0-3", pid: '0-3',
"id": "0-3-1", id: '0-3-1',
"name": "协议校验" name: '协议校验'
}, },
{ {
"scriptIdx":4, scriptIdx: 4,
"isChildNode":true, isChildNode: true,
"pid": "0-3", pid: '0-3',
"id": "0-3-1", id: '0-3-1',
"name": "相序校验" name: '相序校验'
}, },
{ {
"scriptIdx":5, scriptIdx: 5,
"isChildNode":true, isChildNode: true,
"pid": "0-3", pid: '0-3',
"id": "0-3-1", id: '0-3-1',
"name": "守时校验" name: '守时校验'
}, },
{ {
"scriptIdx":6, scriptIdx: 6,
"isChildNode":true, isChildNode: true,
"pid": "0-3", pid: '0-3',
"id": "0-3-1", id: '0-3-1',
"name": "通道系数校准" name: '通道系数校准'
} }
] ]
} }
@@ -328,23 +292,23 @@ const handleClick = (item,index,vvs) => {
console.log(vvs, index, item.name, item.children) console.log(vvs, index, item.name, item.children)
PopupVisible.value = true PopupVisible.value = true
showDataPopup.value.open() showDataPopup.value.open()
}; }
let currentIndex = 0; let currentIndex = 0
let totalNum = 0; let totalNum = 0
//启动预检测 //启动预检测
const handlePreTest = () => { const handlePreTest = () => {
ElMessage.success("启动预检测"); ElMessage.success('启动预检测')
currentIndex = 0; currentIndex = 0
percentage.value = 0; percentage.value = 0
statusList.value = []; statusList.value = []
deviceTestList.value = []; deviceTestList.value = []
statusId.value = 0; statusId.value = 0
testModel.value = "preTest" testModel.value = 'preTest'
beforeTest.value = false; beforeTest.value = false
getTreeData(preTestData) getTreeData(preTestData)
totalNum = preTestData[0].children.length; totalNum = preTestData[0].children.length
interValTest(); interValTest()
// let count = 0; // let count = 0;
// if (timer) { // if (timer) {
@@ -368,37 +332,37 @@ const handlePreTest = () => {
// }); // });
// }, 2000); // }, 2000);
// } // }
}; }
//进入检测流程 //进入检测流程
const handleAutoTest = () => { const handleAutoTest = () => {
ElMessage.success("启动正式检测"); ElMessage.success('启动正式检测')
currentIndex = 0; currentIndex = 0
percentage.value = 0; percentage.value = 0
statusList.value = []; statusList.value = []
deviceTestList.value = []; deviceTestList.value = []
statusId.value = 0; statusId.value = 0
testModel.value = "Test" testModel.value = 'Test'
beforeTest.value = false; beforeTest.value = false
getTreeData(data) getTreeData(data)
// totalNum = data.length; // totalNum = data.length;
totalNum = 10; totalNum = 10
interValTest(); interValTest()
}; }
//返回设备列表 //返回设备列表
const handleBackDeviceList = () => { const handleBackDeviceList = () => {
router.push({ router.push({
path: "/home/index", path: '/home/index'
}); })
}; }
const getTreeData = (val) => { const getTreeData = val => {
treeRef.value && treeRef.value.getTreeData(val); treeRef.value && treeRef.value.getTreeData(val)
}; }
const tableList = ref([]); const tableList = ref([])
const percentage = ref(0); const percentage = ref(0)
const customColors = [ const customColors = [
// { color: "red", percentage: 0 }, // { color: "red", percentage: 0 },
@@ -411,38 +375,31 @@ const customColors = [
// { color: "#e6a23c", percentage: 70 }, //黄 // { color: "#e6a23c", percentage: 70 }, //黄
// { color: "#e6a23c", percentage: 80 }, //1989fa // { color: "#e6a23c", percentage: 80 }, //1989fa
// { color: "#e6a23c", percentage: 90 }, //1989fa // { color: "#e6a23c", percentage: 90 }, //1989fa
{ color: "#5cb87a", percentage: 100 }, //绿 { color: '#5cb87a', percentage: 100 } //绿
]; ]
//加载进度条 //加载进度条
const refreshProgress = () => { const refreshProgress = () => {
console.log(currentIndex, totalNum, percentage.value) console.log(currentIndex, totalNum, percentage.value)
if (percentage.value < 100) { if (percentage.value < 100) {
percentage.value = Math.trunc(currentIndex/totalNum * 100); percentage.value = Math.trunc((currentIndex / totalNum) * 100)
} else { } else {
clearInterval(timer.value) clearInterval(timer.value)
clearInterval(statusTimer.value) clearInterval(statusTimer.value)
let strTemp = "" let strTemp = ''
if(testModel.value === "preTest") if (testModel.value === 'preTest') strTemp = '预检测过程全部结束'
strTemp = "预检测过程全部结束" else if (testModel.value === 'Test') strTemp = '正式检测全部结束'
else if(testModel.value === "Test")
strTemp = "正式检测全部结束"
statusId.value++; statusId.value++
statusList.value.push({ statusList.value.push({
id: statusId.value, id: statusId.value,
remark: strTemp, remark: strTemp,
status: 0, status: 0
}); })
console.log('检测结束')
console.log("检测结束") if (testModel.value === 'preTest') ElMessage.success('预检测过程全部结束')
if(testModel.value === "preTest") else if (testModel.value === 'Test')
ElMessage.success("预检测过程全部结束")
else if(testModel.value === "Test")
//ElMessage.success("正式检测全部结束,你可以停留在此页面查看检测结果,或返回首页进行复检、报告生成和归档等操作") //ElMessage.success("正式检测全部结束,你可以停留在此页面查看检测结果,或返回首页进行复检、报告生成和归档等操作")
ElMessageBox.confirm( ElMessageBox.confirm(
'检测全部结束,你可以停留在此页面查看检测结果,或返回首页进行复检、报告生成和归档等操作', '检测全部结束,你可以停留在此页面查看检测结果,或返回首页进行复检、报告生成和归档等操作',
@@ -450,143 +407,129 @@ ElMessageBox.confirm(
{ {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'success', type: 'success'
} }
) ).then()
.then()
// percentage.value = 0; // percentage.value = 0;
// statusList.value = []; // statusList.value = [];
// deviceTestList.value = []; // deviceTestList.value = [];
// statusId.value = 0; // statusId.value = 0;
} }
}; }
let timer: any = ref(""); let timer: any = ref('')
const statusTimer: any = ref(""); const statusTimer: any = ref('')
//检测列表数据 //检测列表数据
const deviceTestList = ref<any>([]); const deviceTestList = ref<any>([])
//检测结果数据 //检测结果数据
const deviceList = ref<any>([]); const deviceList = ref<any>([])
//前一个页面带过来的设备数据 //前一个页面带过来的设备数据
// const deviceData = ref<any>([]); // const deviceData = ref<any>([]);
const deviceData = ref([ const deviceData = ref([
{ {
id: 0, id: 0,
name: "设备1通道1", name: '设备1通道1',
status: Math.floor(Math.random() * 4), status: Math.floor(Math.random() * 4),
type:"info", type: 'info',
label:"/", label: '/',
devID:"dev1", devID: 'dev1',
monitorIndex:1, monitorIndex: 1
}, },
{ {
id: 1, id: 1,
name: "设备1通道2", name: '设备1通道2',
status: Math.floor(Math.random() * 4), status: Math.floor(Math.random() * 4),
type:"success", type: 'success',
label:"√", label: '√',
devID:"dev1", devID: 'dev1',
monitorIndex:2, monitorIndex: 2
}, },
{ {
id: 2, id: 2,
name: "设备2通道1", name: '设备2通道1',
status: Math.floor(Math.random() * 4), status: Math.floor(Math.random() * 4),
type:"danger", type: 'danger',
label:"×", label: '×',
devID:"dev2", devID: 'dev2',
monitorIndex:1, monitorIndex: 1
}, },
{ {
id: 3, id: 3,
name: "设备3通道1", name: '设备3通道1',
status: Math.floor(Math.random() * 4), status: Math.floor(Math.random() * 4),
type:"success", type: 'success',
label:"√", label: '√',
devID:"dev3", devID: 'dev3',
monitorIndex:1, monitorIndex: 1
}, }
]); ])
const interValTest = () => { const interValTest = () => {
timer.value = setInterval(() => { timer.value = setInterval(() => {
deviceTestList.value.push({ deviceTestList.value.push({
id: 0, id: 0,
name: `频率 ${statusId.value}Hz`, name: `频率 ${statusId.value}Hz`,
children: deviceData.value, children: deviceData.value
// status: Math.floor(Math.random() * 4), // status: Math.floor(Math.random() * 4),
}); })
currentIndex++; currentIndex++
treeRef.value && treeRef.value.getCurrentIndex(currentIndex) treeRef.value && treeRef.value.getCurrentIndex(currentIndex)
refreshProgress(); refreshProgress()
}, 2000); }, 2000)
statusTimer.value = setInterval(() => { statusTimer.value = setInterval(() => {
getStatusList(); getStatusList()
statusList.value.map((item: any, index: any) => { statusList.value.map((item: any, index: any) => {
if (index == statusList.value.length - 1) { if (index == statusList.value.length - 1) {
item.status = 1; item.status = 1
} else { } else {
item.status = 0; item.status = 0
}
})
}, 2000)
} }
});
}, 2000);
};
//暂停检测 //暂停检测
const isPause = ref<boolean>(false); const isPause = ref<boolean>(false)
const handlePauseTest = () => { const handlePauseTest = () => {
if (!isPause.value) { if (!isPause.value) {
clearInterval(timer.value); clearInterval(timer.value)
clearInterval(statusTimer.value); clearInterval(statusTimer.value)
} else { } else {
interValTest(); interValTest()
}
isPause.value = !isPause.value
} }
isPause.value = !isPause.value;
};
//完成检测 //完成检测
const handleFinishTest = () => { const handleFinishTest = () => {
ElMessage.success("完成检测"); ElMessage.success('完成检测')
}; }
// 表格拖拽排序 // 表格拖拽排序
const sortTable = ({ const sortTable = ({ newIndex, oldIndex }: { newIndex?: number; oldIndex?: number }) => {
newIndex, console.log(newIndex, oldIndex)
oldIndex, ElMessage.success('修改列表排序成功')
}: { }
newIndex?: number;
oldIndex?: number;
}) => {
console.log(newIndex, oldIndex);
ElMessage.success("修改列表排序成功");
};
const statusList: any = ref([])
const statusList: any = ref([]); let statusId = ref(0)
let statusId = ref(0); const statusRef = ref()
const statusRef = ref();
const getStatusList = () => { const getStatusList = () => {
statusId.value++; statusId.value++
statusList.value.push({ statusList.value.push({
id: statusId.value, id: statusId.value,
remark: `频率 ${statusId.value}Hz`, remark: `频率 ${statusId.value}Hz`,
status: 0, status: 0
}); })
// console.log(statusRef.value.offsetHeight); // console.log(statusRef.value.offsetHeight);
nextTick(() => { nextTick(() => {
if (statusRef.value) if (statusRef.value) statusRef.value.scrollTop = statusRef.value.scrollHeight
statusRef.value.scrollTop = statusRef.value.scrollHeight; })
}); }
};
onMounted(() => { onMounted(() => {})
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.empty__div { .empty__div {
position: absolute; position: absolute;
left: 50%; left: 50%;
@@ -741,11 +684,11 @@ onMounted(() => {
} }
} }
::v-deep .header-button-lf { :deep(.header-button-lf) {
clear: both !important; clear: both !important;
} }
::v-deep .el-descriptions__extra { :deep(.el-descriptions__extra) {
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@@ -383,7 +383,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { type CascaderOption, ElMessage, type FormItemRule } from 'element-plus' import { type CascaderOption, ElMessage, type FormItemRule } from 'element-plus'
import { computed, defineProps, reactive, ref } from 'vue' import { computed, reactive, ref } from 'vue'
import { dialogBig } from '@/utils/elementBind' import { dialogBig } from '@/utils/elementBind'
import { type Plan } from '@/api/plan/interface' import { type Plan } from '@/api/plan/interface'
import { import {

View File

@@ -12,10 +12,7 @@
<template #tableHeader> <template #tableHeader>
<el-form :model="searchForm"> <el-form :model="searchForm">
<el-form-item label="检测时间"> <el-form-item label="检测时间">
<el-select <el-select v-model="searchForm.intervalType" style="width: 80px !important">
v-model="searchForm.intervalType"
style="width: 80px !important"
>
<el-option :value="0" label="按周">按周</el-option> <el-option :value="0" label="按周">按周</el-option>
<el-option :value="1" label="按月">按月</el-option> <el-option :value="1" label="按月">按月</el-option>
<el-option :value="2" label="按日">按日</el-option> <el-option :value="2" label="按日">按日</el-option>
@@ -58,30 +55,20 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :icon="Search" @click="handleSearch" <el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
>查询</el-button
>
<el-button :icon="Refresh" @click="handleRefresh">重置</el-button> <el-button :icon="Refresh" @click="handleRefresh">重置</el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :icon="Upload" @click="handleRefresh" <el-button type="primary" :icon="Upload" @click="handleRefresh">导入</el-button>
>导入</el-button
>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :icon="Check" @click="handleRefresh" <el-button type="primary" :icon="Check" @click="handleRefresh">合并</el-button>
>合并</el-button
>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :icon="Plus" @click="handleRefresh" <el-button type="primary" :icon="Plus" @click="handleRefresh">新增</el-button>
>新增</el-button
>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="danger" :icon="Delete" @click="handleRefresh" <el-button type="danger" :icon="Delete" @click="handleRefresh">删除</el-button>
>删除</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- <el-button <!-- <el-button
@@ -126,27 +113,9 @@
</template> --> </template> -->
<!-- 表格操作 --> <!-- 表格操作 -->
<template #operation="scope"> <template #operation="scope">
<el-button <el-button type="primary" link :icon="View" @click="handleDetails('查看', scope.row)">查看</el-button>
type="primary" <el-button type="primary" link :icon="EditPen" @click="openDrawer('编辑', scope.row)">导出</el-button>
link <el-button type="primary" link :icon="Delete" @click="deleteAccount(scope.row)">删除</el-button>
:icon="View"
@click="handleDetails('查看', scope.row)"
>查看</el-button
>
<el-button
type="primary"
link
:icon="EditPen"
@click="openDrawer('编辑', scope.row)"
>导出</el-button
>
<el-button
type="primary"
link
:icon="Delete"
@click="deleteAccount(scope.row)"
>删除</el-button
>
</template> </template>
</ProTable> </ProTable>
</div> </div>
@@ -154,292 +123,263 @@
</template> </template>
<script setup lang="tsx" name="useProTable"> <script setup lang="tsx" name="useProTable">
import { ref, reactive, onMounted } from "vue"; import { onMounted, reactive, ref } from 'vue'
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
import { User } from "@/api/interface"; import { User } from '@/api/interface'
import { useHandleData } from "@/hooks/useHandleData"; import { useHandleData } from '@/hooks/useHandleData'
import { useDownload } from "@/hooks/useDownload"; import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from "element-plus"; import ProTable from '@/components/ProTable/index.vue'
import ProTable from "@/components/ProTable/index.vue"; import planDetails from './components/details.vue'
import ImportExcel from "@/components/ImportExcel/index.vue"; import { Check, Delete, EditPen, Plus, Refresh, Search, Upload, View } from '@element-plus/icons-vue'
import planDetails from "./components/details.vue"; import { getPlanList } from '@/api/plan/planList'
import {
CirclePlus,
Delete,
EditPen,
Download,
Upload,
View,
Check,
Plus,
Refresh,
Search,
} from "@element-plus/icons-vue";
import { getPlanList } from "@/api/plan/planList";
const router = useRouter(); const router = useRouter()
const value1 = ref(""); const value1 = ref('')
const value2 = ref(""); const value2 = ref('')
const shortcuts = [ const shortcuts = [
{ {
text: "最近一周", text: '最近一周',
value: () => { value: () => {
const end = new Date(); const end = new Date()
const start = new Date(); const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start, end]; return [start, end]
}, }
}, },
{ {
text: "最近一个月", text: '最近一个月',
value: () => { value: () => {
const end = new Date(); const end = new Date()
const start = new Date(); const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start, end]; return [start, end]
}, }
}, },
{ {
text: "最近三个月", text: '最近三个月',
value: () => { value: () => {
const end = new Date(); const end = new Date()
const start = new Date(); const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start, end]; return [start, end]
}, }
}, }
]; ]
// 跳转详情页 // 跳转详情页
const toDetail = () => { const toDetail = () => {
router.push( router.push(`/proTable/useProTable/detail/${Math.random().toFixed(3)}?params=detail-page`)
`/proTable/useProTable/detail/${Math.random().toFixed(3)}?params=detail-page` }
);
};
const searchForm = ref({ const searchForm = ref({
intervalType: 0, intervalType: 0,
time: ["2024-08-20", "2024-08-27"], time: ['2024-08-20', '2024-08-27'],
searchBeginTime: "", searchBeginTime: '',
searchEndTime: "", searchEndTime: '',
checkStatus: 0, checkStatus: 0,
checkReportStatus: 0, checkReportStatus: 0,
checkResult: 0, checkResult: 0
}); })
// ProTable 实例 // ProTable 实例
const proTable = ref<ProTableInstance>(); const proTable = ref<ProTableInstance>()
// 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据) // 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
const initParam = reactive({ type: 1, pageNum: 1, pageSize: 10 }); const initParam = reactive({ type: 1, pageNum: 1, pageSize: 10 })
// dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段 // dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
// 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行 // 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
const tableList = ref([]); const tableList = ref([])
const dataCallback = (data: any) => { const dataCallback = (data: any) => {
return { return {
list: data || data.data || data.list, list: data || data.data || data.list,
total: data.length || data.total, total: data.length || data.total
}; }
}; }
// 如果你想在请求之前对当前请求参数做一些操作可以自定义如下函数params 为当前所有的请求参数(包括分页),最后返回请求列表接口 // 如果你想在请求之前对当前请求参数做一些操作可以自定义如下函数params 为当前所有的请求参数(包括分页),最后返回请求列表接口
// 默认不做操作就直接在 ProTable 组件上绑定 :requestApi="getUserList" // 默认不做操作就直接在 ProTable 组件上绑定 :requestApi="getUserList"
const getTableList = (params: any) => { const getTableList = (params: any) => {
let newParams = JSON.parse(JSON.stringify(params)); let newParams = JSON.parse(JSON.stringify(params))
newParams.createTime && (newParams.startTime = newParams.createTime[0]); newParams.createTime && (newParams.startTime = newParams.createTime[0])
newParams.createTime && (newParams.endTime = newParams.createTime[1]); newParams.createTime && (newParams.endTime = newParams.createTime[1])
delete newParams.createTime; delete newParams.createTime
return getPlanList(newParams); return getPlanList(newParams)
}; }
//查看详情 //查看详情
const detailsRef: any = ref(); const detailsRef: any = ref()
const handleDetails = () => { const handleDetails = () => {
console.log(detailsRef.value, "+++++++++++++++"); console.log(detailsRef.value, '+++++++++++++++')
detailsRef.value.open("查看计划"); detailsRef.value.open('查看计划')
}; }
// 表格配置项 // 表格配置项
const columns = reactive<ColumnProps<User.ResUserList>[]>([ const columns = reactive<ColumnProps<User.ResUserList>[]>([
{ type: "selection", fixed: "left", width: 70 }, { type: 'selection', fixed: 'left', width: 70 },
{ type: "sort", label: "Sort", width: 80 }, { type: 'sort', label: 'Sort', width: 80 },
{ type: "expand", label: "Expand", width: 85 }, { type: 'expand', label: 'Expand', width: 85 },
{ {
prop: "planName", prop: 'planName',
label: "计划名称", label: '计划名称',
width: 120, width: 120
}, },
{ {
prop: "checkMode", prop: 'checkMode',
label: "检测模式", label: '检测模式',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkMode == 0 return scope.row.checkMode == 0
? "模拟式" ? '模拟式'
: scope.row.checkMode == 1 : scope.row.checkMode == 1
? "比对式" ? '比对式'
: scope.row.checkMode == 2 : scope.row.checkMode == 2
? "数字式" ? '数字式'
: scope.row.checkMode; : scope.row.checkMode
}, }
}, },
{ {
prop: "checkFrom", prop: 'checkFrom',
label: "检测源", label: '检测源',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkFrom == 0 return scope.row.checkFrom == 0
? "标准源-福禄克-6100A" ? '标准源-福禄克-6100A'
: scope.row.checkFrom == 1 : scope.row.checkFrom == 1
? "标准源-昂立-PF2" ? '标准源-昂立-PF2'
: scope.row.checkFrom == 2 : scope.row.checkFrom == 2
? "高精度设备-PQS882-1" ? '高精度设备-PQS882-1'
: scope.row.checkFrom; : scope.row.checkFrom
}, }
}, },
{ {
prop: "numberFromName", prop: 'numberFromName',
label: "源名称", label: '源名称',
render: (scope) => { render: scope => {
return scope.row.numberFromName == 0 return scope.row.numberFromName == 0
? "分钟统计数据最大值" ? '分钟统计数据最大值'
: scope.row.numberFromName == 1 : scope.row.numberFromName == 1
? "分钟统计数据最小值" ? '分钟统计数据最小值'
: scope.row.numberFromName == 2 : scope.row.numberFromName == 2
? "分钟统计数据CP95值" ? '分钟统计数据CP95值'
: scope.row.numberFromName; : scope.row.numberFromName
}, }
}, },
{ {
prop: "checkExe", prop: 'checkExe',
label: "检测脚本", label: '检测脚本',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkExe == 0 return scope.row.checkExe == 0
? "国网入网检测脚本(单影响量-模拟式)" ? '国网入网检测脚本(单影响量-模拟式)'
: scope.row.checkExe == 1 : scope.row.checkExe == 1
? "国网入网检测脚本" ? '国网入网检测脚本'
: scope.row.checkExe == 2 : scope.row.checkExe == 2
? "/" ? '/'
: scope.row.checkExe; : scope.row.checkExe
}, }
}, },
{ {
prop: "wctx", prop: 'wctx',
label: "误差体系", label: '误差体系',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.wctx == 0 return scope.row.wctx == 0
? "Q/GDW 1650.2- 2016" ? 'Q/GDW 1650.2- 2016'
: scope.row.wctx == 1 : scope.row.wctx == 1
? "Q/GDW 10650.2 - 2021" ? 'Q/GDW 10650.2 - 2021'
: scope.row.wctx == 2 : scope.row.wctx == 2
? "/" ? '/'
: scope.row.wctx; : scope.row.wctx
}, }
}, },
{ {
type: "tag", type: 'tag',
prop: "checkStatus", prop: 'checkStatus',
label: "检测状态", label: '检测状态',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkStatus == 1 return scope.row.checkStatus == 1
? "未检" ? '未检'
: scope.row.checkStatus == 2 : scope.row.checkStatus == 2
? "检测中" ? '检测中'
: scope.row.checkStatus == 3 : scope.row.checkStatus == 3
? "检测完成" ? '检测完成'
: scope.row.checkStatus; : scope.row.checkStatus
}, }
}, },
{ {
prop: "checkReport", prop: 'checkReport',
label: "检测报告", label: '检测报告',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkReport == 1 return scope.row.checkReport == 1
? "未生成" ? '未生成'
: scope.row.checkReport == 2 : scope.row.checkReport == 2
? "部分生成" ? '部分生成'
: scope.row.checkReport == 3 : scope.row.checkReport == 3
? "全部生成" ? '全部生成'
: scope.row.checkReport; : scope.row.checkReport
}, }
}, },
{ {
prop: "checkResult", prop: 'checkResult',
label: "检测结果", label: '检测结果',
width: 120, width: 120,
render: (scope) => { render: scope => {
return scope.row.checkReport == 1 return scope.row.checkReport == 1
? "/" ? '/'
: scope.row.checkReport == 2 : scope.row.checkReport == 2
? "符合" ? '符合'
: scope.row.checkReport == 3 : scope.row.checkReport == 3
? "不符合" ? '不符合'
: scope.row.checkReport; : scope.row.checkReport
}
}, },
}, { prop: 'operation', label: '操作', fixed: 'right', width: 250 }
{ prop: "operation", label: "操作", fixed: "right", width: 250 }, ])
]);
//重置查询条件 //重置查询条件
const resetSearchForm = () => { const resetSearchForm = () => {
searchForm.value = { searchForm.value = {
intervalType: 0, intervalType: 0,
time: ["2024-08-20", "2024-08-27"], time: ['2024-08-20', '2024-08-27'],
searchBeginTime: "", searchBeginTime: '',
searchEndTime: "", searchEndTime: '',
checkStatus: 0, checkStatus: 0,
checkReportStatus: 0, checkReportStatus: 0,
checkResult: 0, checkResult: 0
}; }
}; }
//查询 //查询
const handleSearch = () => { const handleSearch = () => {
proTable.value?.getTableList(); proTable.value?.getTableList()
}; }
//重置 //重置
const handleRefresh = () => { const handleRefresh = () => {
proTable.value?.getTableList(); proTable.value?.getTableList()
}; }
// 表格拖拽排序 // 表格拖拽排序
const sortTable = ({ const sortTable = ({ newIndex, oldIndex }: { newIndex?: number; oldIndex?: number }) => {
newIndex,
oldIndex,
}: {
newIndex?: number;
oldIndex?: number;
}) => {
// console.log(newIndex, oldIndex); // console.log(newIndex, oldIndex);
//console.log(proTable.value?.tableData); //console.log(proTable.value?.tableData);
ElMessage.success("修改列表排序成功"); ElMessage.success('修改列表排序成功')
}; }
// 删除用户信息 // 删除用户信息
const deleteAccount = async (params: User.ResUserList) => { const deleteAccount = async (params: User.ResUserList) => {
await useHandleData( await useHandleData(deleteUser, { id: [params.id] }, `删除【${params.username}`)
deleteUser, proTable.value?.getTableList()
{ id: [params.id] }, }
`删除【${params.username}`
);
proTable.value?.getTableList();
};
// 批量删除用户信息 // 批量删除用户信息
const batchDelete = async (id: string[]) => { const batchDelete = async (id: string[]) => {
await useHandleData(deleteUser, { id }, "删除所选用户信息"); await useHandleData(deleteUser, { id }, '删除所选用户信息')
proTable.value?.clearSelection(); proTable.value?.clearSelection()
proTable.value?.getTableList(); proTable.value?.getTableList()
}; }
// 重置用户密码 // 重置用户密码
const resetPass = async (params: User.ResUserList) => { const resetPass = async (params: User.ResUserList) => {
await useHandleData( await useHandleData(resetUserPassWord, { id: params.id }, `重置【${params.username}】用户密码`)
resetUserPassWord, proTable.value?.getTableList()
{ id: params.id }, }
`重置【${params.username}】用户密码`
);
proTable.value?.getTableList();
};
// 切换用户状态 // 切换用户状态
const changeStatus = async (row: User.ResUserList) => { const changeStatus = async (row: User.ResUserList) => {
@@ -447,12 +387,12 @@ const changeStatus = async (row: User.ResUserList) => {
changeUserStatus, changeUserStatus,
{ id: row.id, status: row.status == 1 ? 0 : 1 }, { id: row.id, status: row.status == 1 ? 0 : 1 },
`切换【${row.username}】用户状态` `切换【${row.username}】用户状态`
); )
proTable.value?.getTableList(); proTable.value?.getTableList()
}; }
onMounted(() => { onMounted(() => {
console.log(proTable.value?.tableData); console.log(proTable.value?.tableData)
}); })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.planList { .planList {
@@ -460,7 +400,7 @@ onMounted(() => {
// height: calc(100vh - 165px); // height: calc(100vh - 165px);
height: 100%; height: 100%;
} }
::v-deep .el-select { :deep(.el-select) {
width: 150px !important; width: 150px !important;
} }