UPDATE: 重构检修计划选择被检设备组件,并处理对应数据逻辑

This commit is contained in:
贾同学
2025-09-03 20:44:32 +08:00
parent da6a72807b
commit 74e015bd12
6 changed files with 483 additions and 270 deletions

View File

@@ -1,123 +1,119 @@
import type {ReqPage, ResPage} from '@/api/interface' import type { ReqPage, ResPage } from '@/api/interface'
import type { Monitor } from './monitor'; import type { Monitor } from './monitor'
// 被检设备模块 // 被检设备模块
export namespace Device { export namespace Device {
/** /**
* 被检设备表格分页查询参数 * 被检设备表格分页查询参数
*/ */
export interface ReqPqDevParams extends ReqPage { export interface ReqPqDevParams extends ReqPage {
id: string; // 装置序号id 必填 id: string // 装置序号id 必填
name: string; //设备名称 name: string //设备名称
devType?: string; // 设备名称 devType?: string // 设备名称
createTime?: string; //创建时间 createTime?: string //创建时间
pattern: string; pattern: string
} }
/** /**
* 被检设备表格分页查询参数 * 被检设备表格分页查询参数
*/ */
export interface ReqDevReportParams extends ReqPage { export interface ReqDevReportParams extends ReqPage {
planId?: string; // 计划id planId?: string // 计划id
devId?: string; // 装置id devId?: string // 装置id
scriptId?: string; // 脚本id scriptId?: string // 脚本id
planCode?: string; planCode?: string
devIdList?: string[]; // 装置id列表 devIdList?: string[] // 装置id列表
} }
/** /**
* 被检设备新增、修改、根据id查询返回的对象 * 被检设备新增、修改、根据id查询返回的对象
*/ */
export interface ResPqDev { export interface ResPqDev {
id: string; //装置序号ID id: string //装置序号ID
name: string; //设备名称 name: string //设备名称
pattern: string; //设备模式 模拟 数字 比对 pattern: string //设备模式 模拟 数字 比对
devType: string;//设备类型 devType: string //设备类型
manufacturer?: string | null;//生产厂家 manufacturer?: string | null //生产厂家
createDate: string; //生产日期 createDate: string //生产日期
createId: string; //出厂编号 createId: string //出厂编号
hardwareVersion: string; //固件版本 hardwareVersion: string //固件版本
softwareVersion: string; //软件版本 softwareVersion: string //软件版本
protocol: string; //通讯协议 protocol: string //通讯协议
ip: string; //IP地址 ip: string //IP地址
port: number; //端口号 port: number //端口号
encryptionFlag: number; //装置是否为加密版本 encryptionFlag: number //装置是否为加密版本
series?: string | null; //装置识别码3ds加密 series?: string | null //装置识别码3ds加密
devKey?: string | null; //装置秘钥3ds加密 devKey?: string | null //装置秘钥3ds加密
sampleId?: string | null; //样品编号 sampleId?: string | null //样品编号
arrivedDate?: string; //送样日期 arrivedDate?: string //送样日期
cityName?: string | null; //所属地市名称 cityName?: string | null //所属地市名称
gdName?: string | null; //所属供电公司名称 gdName?: string | null //所属供电公司名称
subName?: string | null; //所属电站名称 subName?: string | null //所属电站名称
reportPath?: string | null; //报告路径 reportPath?: string | null //报告路径
planId?: string;//检测计划Id planId?: string //检测计划Id
factorFlag?: number;//是否支持系数校准(0:不支持,1:支持) factorFlag?: number //是否支持系数校准(0:不支持,1:支持)
preinvestmentPlan: string | null;//预投计划 preinvestmentPlan: string | null //预投计划
delegate: string | null; //委托方 delegate: string | null //委托方
inspectChannel?: string[] | string;//被检通道 inspectChannel?: string[] | string //被检通道
inspectDate?: string | null;//定检日期 inspectDate?: string | null //定检日期
harmSysId?: string | null;//谐波系统设备id harmSysId?: string | null //谐波系统设备id
importFlag?: number;//是否为导入设备 0否 1是 importFlag?: number //是否为导入设备 0否 1是
state: number; //状态 state: number //状态
createBy?: string | null; //创建用户 createBy?: string | null //创建用户
createTime?: string | null; //创建时间 createTime?: string | null //创建时间
updateBy?: string | null; //更新用户 updateBy?: string | null //更新用户
updateTime?: string | null; //更新时间 updateTime?: string | null //更新时间
devChns: number; //设备通道数 devChns: number //设备通道数
devVolt: number; //额定电压V devVolt: number //额定电压V
devCurr: number; //额定电流A devCurr: number //额定电流A
icdId: string | null; icdId: string | null
power: string | null;//工作电源 power: string | null //工作电源
devId?: number; devId?: number
checkState?: number | null; //检测状态(0:未检1:检测中2:检测完成 3:归档) checkState?: number | null //检测状态(0:未检1:检测中2:检测完成 3:归档)
checkResult?: number | null; //检测结果(0:不符合1:符合2:未检) checkResult?: number | null //检测结果(0:不符合1:符合2:未检)
reportState?: number | null; //报告状态(0:未生成1:已生成2:未检) reportState?: number | null //报告状态(0:未生成1:已生成2:未检)
recheckNum: number; //复检次数 recheckNum: number //复检次数
timeCheckResult?: number;//守时检测结果(0:不符合1:符合) timeCheckResult?: number //守时检测结果(0:不符合1:符合)
factorCheckResult?: number;//系数校准结果(0:不合格1:合格2:未检) factorCheckResult?: number //系数校准结果(0:不合格1:合格2:未检)
realtimeResult?: number;//实时数据结论(0:不符合1:符合2:未检) realtimeResult?: number //实时数据结论(0:不符合1:符合2:未检)
statisticsResult?: number;//统计数据结论(0:不符合1:符合2:未检) statisticsResult?: number //统计数据结论(0:不符合1:符合2:未检)
recordedResult?: number;//录波数据结论(0:不符合1:符合2:未检) recordedResult?: number //录波数据结论(0:不符合1:符合2:未检)
checkBy?: string | null;//检测人 checkBy?: string | null //检测人
checkTime?: string | null;//检测时间 checkTime?: string | null //检测时间
preDetectTime?: number;//预检测耗时 preDetectTime?: number //预检测耗时
coefficientTime?: number;//系数校准耗时 coefficientTime?: number //系数校准耗时
formalCheckTime?: number;//正式检测耗时 formalCheckTime?: number //正式检测耗时
boundPlanName?: string| null; boundPlanName?: string | null
assign?: number;////是否分配给检测人员 0否 1是 assign?: number ////是否分配给检测人员 0否 1是
monitorList: Monitor.ResPqMon[] ; monitorList: Monitor.ResPqMon[]
checked: boolean // 是否已选择
disabled: boolean // 是否禁用
} }
export interface SelectOption { export interface SelectOption {
label: string; label: string
value: string | number; value: string | number
} }
export interface ResDev { export interface ResDev {
id: string; id: string
name: string, name: string
icd: string, icd: string
power: string, power: string
devVolt: number, devVolt: number
devCurr: number, devCurr: number
devChns: number, devChns: number
} }
export interface ResTH { export interface ResTH {
temperature :number | null;//温度 temperature: number | null //温度
humidity:number | null;//湿度 humidity: number | null //湿度
} }
/** /**
* 被检设备表格查询分页返回的对象; * 被检设备表格查询分页返回的对象;
*/ */
export interface ResPqDevPage extends ResPage<ResPqDev> { export interface ResPqDevPage extends ResPage<ResPqDev> {}
}
} }

View File

@@ -120,7 +120,7 @@ export const getBoundStandardDevList = (params: Plan.ResPlan) => {
} }
//根据计划ID获取已绑定的所有标准设备 //根据计划ID获取已绑定的所有标准设备
export const getBoundStandardDevAllList = (params: Plan.ResPlan) => { export const getBoundStandardDevAllList = (params: { id: string }) => {
return http.get(`/adPlan/getBoundStandardDev?planId=${params.id}&all=1`) return http.get(`/adPlan/getBoundStandardDev?planId=${params.id}&all=1`)
} }
@@ -134,10 +134,11 @@ export const importSubPlan = (params: Plan.ResPlan) => {
return http.upload(`/adPlan/importSubPlan`, params) return http.upload(`/adPlan/importSubPlan`, params)
} }
// 导出计划检测结果数据 // 导出计划检测结果数据
export const exportPlanCheckData = (params: any) => { export const exportPlanCheckData = (params: any) => {
return http.download(`/adPlan/exportPlanCheckData?planId=${params.id}&devIds=${params.devIds}&report=${params.report}`) return http.download(
`/adPlan/exportPlanCheckData?planId=${params.id}&devIds=${params.devIds}&report=${params.report}`
)
} }
// 导入子检测计划检测结果数据 // 导入子检测计划检测结果数据

View File

@@ -1,12 +1,11 @@
import http from '@/api' import http from '@/api'
import {type VersionRegister} from '@/api/system/versionRegister/interface' import { type VersionRegister } from '@/api/system/versionRegister/interface'
//获取有效数据配置 //获取有效数据配置
export const getRegRes = (params: VersionRegister.ResSys_Reg_Res) => { export const getRegRes = (params: { type: string }) => {
return http.get(`/sysRegRes/getRegResByType?id=${params.type}`) return http.get(`/sysRegRes/getRegResByType?id=${params.type}`)
} }
//编辑有效数据配置 //编辑有效数据配置
export const updateRegRes = (params: VersionRegister.Sys_Reg_Res) => { export const updateRegRes = (params: VersionRegister.Sys_Reg_Res) => {
return http.post(`/sysRegRes/update`, params) return http.post(`/sysRegRes/update`, params)

View File

@@ -1,12 +1,11 @@
<template> <template>
<el-dialog v-model="dialogVisible" :title="parameter.title" :destroy-on-close="true" width="580px" draggable> <el-dialog v-model="dialogVisible" :title="parameter.title" :destroy-on-close="true" width="450px" draggable>
<el-form class="drawer-multiColumn-form" style="margin-top: 10px" label-width="100px"> <el-form class="drawer-multiColumn-form" label-width="100px">
<el-form-item label="文件上传:"> <el-form-item label="">
<el-upload <el-upload
ref="uploadRef" ref="uploadRef"
action="#" action="#"
class="upload" class="upload"
drag
:http-request="uploadZip" :http-request="uploadZip"
accept=".zip" accept=".zip"
:auto-upload="!parameter.confirmMessage" :auto-upload="!parameter.confirmMessage"
@@ -18,8 +17,7 @@
<upload-filled /> <upload-filled />
</el-icon> </el-icon>
<div class="el-upload__text"> <div class="el-upload__text">
将文件拖到此处 <spam>点击上传</spam>
<em>点击上传</em>
</div> </div>
</slot> </slot>
<template #tip> <template #tip>

View File

@@ -0,0 +1,305 @@
<template>
<el-row>
<el-col :span="24">
<el-card header-class="card-header" body-class="card-body" footer-class="card-footer">
<template #header>
<el-text size="large">{{ props.title }}</el-text>
<el-text type="info" size="small">{{ statistics.checked }}/{{ statistics.total }}</el-text>
</template>
<el-row>
<el-col :span="24">
<div style="display: flex; justify-content: space-between; align-items: center">
<el-checkbox
:disabled="props.disabled"
size="small"
v-model="filter.checkAll"
label="全选"
></el-checkbox>
<el-input
style="width: 82%; margin: 0 10px"
size="small"
v-model="filter.text"
:placeholder="props.filterPlaceholder"
/>
<el-dropdown size="small" @command="handleCommand">
<span class="el-dropdown-link">
<el-icon size="16"><Filter /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="">默认</el-dropdown-item>
<el-dropdown-item command="manufacturer">设备厂家</el-dropdown-item>
<el-dropdown-item command="cityName">所属地市</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-col>
</el-row>
<el-tree
ref="treeRef"
show-checkbox
accordion
default-expand-all
:data="treeData"
:default-checked-keys="defaultCheckedKeys"
:filter-node-method="filterNode"
node-key="id"
:style="{ marginTop: '20px', height: `${props.height}px` }"
@check-change="handleCheckChange"
>
<template #empty>
<el-empty :image-size="80" description="暂无可选设备" />
</template>
<template #default="{ node, data }">
<div v-if="data.id.startsWith('manufacturer')" style="display: flex; align-items: center">
<el-icon><OfficeBuilding /></el-icon>
<span style="margin-left: 4px">{{ data.label }}</span>
</div>
<div v-else-if="data.id.startsWith('cityName')" style="display: flex; align-items: center">
<el-icon><Location /></el-icon>
<span style="margin-left: 4px">{{ data.label }}</span>
</div>
<div v-else style="flex: 1; display: flex; align-items: center; justify-content: space-between">
<span>
<el-icon><Cpu /></el-icon>
<span v-if="node.level === 1" style="margin-left: 4px">
{{ data.cityName + ' - ' + data.manufacturer + ' - ' + data.name }}
</span>
<span v-if="node.level === 2" style="margin-left: 4px">
{{ data.name }}
</span>
</span>
<el-tooltip effect="light" placement="top">
<template #content>
<el-descriptions border size="small" title="被检设备详情">
<el-descriptions-item label="设备名称">
{{ data.name }}
</el-descriptions-item>
<el-descriptions-item label="设备厂家">
{{ data.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="所属地市">
{{ data.cityName }}
</el-descriptions-item>
<el-descriptions-item label="所属供电公司">
{{ data.gdName }}
</el-descriptions-item>
<el-descriptions-item label="所属电站">
{{ data.subName }}
</el-descriptions-item>
</el-descriptions>
</template>
<el-icon>
<Warning />
</el-icon>
</el-tooltip>
</div>
</template>
</el-tree>
<!-- 传递 footer 插槽到 el-card -->
<template #footer>
<slot name="footer"></slot>
</template>
</el-card>
</el-col>
</el-row>
</template>
<script lang="ts" name="DevSelect" setup>
import { ref, watch } from 'vue'
import type { FilterNodeMethodFunction, TreeInstance } from 'element-plus'
interface Tree {
[key: string]: any
}
interface Device {
id: string
name: string
checked: boolean
importFlag: number
[key: string]: any
}
const modelValue = defineModel<string[]>({ default: [] })
const props = defineProps({
data: {
type: Array as unknown as PropType<Device[]>,
default: (): Device[] => []
},
height: {
type: Number,
default: 240
},
title: {
type: String,
default: ''
},
filterPlaceholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
})
const treeRef = ref<TreeInstance>()
const treeData = ref<Tree[]>([])
const defaultCheckedKeys = ref<string[]>([])
const filter = ref({
groupBy: '',
text: '',
checkAll: false
})
const statistics = ref({
total: 0,
checked: 0
})
const disabledKeys = ref<string[]>([])
onMounted(() => {
if (props.data) {
initTree(props.data)
}
})
watch(
() => props.data,
(newVal: Device[]) => {
if (newVal) {
initTree(newVal)
}
}
)
watch(
() => filter.value.checkAll,
val => {
setCheckedStatus(val)
if (val) {
statistics.value.checked = statistics.value.total
} else {
statistics.value.checked = treeRef.value?.getCheckedNodes().length || 0
}
}
)
watch(
() => filter.value.text,
val => {
treeRef.value!.filter(val)
}
)
const initTree = (data: Device[]) => {
disabledKeys.value = data.filter(item => item.disabled).map(item => item.id)
if (disabledKeys.value.length > 0) {
modelValue.value = []
}
treeData.value = convertToTree(data, filter.value.groupBy)
defaultCheckedKeys.value = data.filter(item => item.checked).map(item => item.id)
statistics.value.checked = defaultCheckedKeys.value.length
statistics.value.total = data.length
if (statistics.value.total > 0) {
filter.value.checkAll = statistics.value.checked === statistics.value.total
}
}
const setCheckedStatus = (checked: boolean) => {
treeData.value.forEach(item => {
if (!disabledKeys.value.includes(item.id)) {
treeRef.value?.setChecked(item.id, checked, true)
}
})
}
const convertToTree = (data: any[], groupBy?: string | undefined) => {
if (groupBy) {
// 创建一个映射来存储每个分组
const groupMap = new Map()
// 遍历数据根据groupBy字段值进行分组
data.forEach(item => {
const groupValue = item[groupBy] || '未分组'
if (!groupMap.has(groupValue)) {
groupMap.set(groupValue, [])
}
groupMap.get(groupValue).push(item)
})
// 将分组转换为树形结构
const treeData: Tree[] = []
groupMap.forEach((items, groupName) => {
const groupNode: Tree = {
id: `${groupBy}_${groupName}`,
label: groupName,
disabled: props.disabled,
children: (items as any[]).map((item: any) => ({
label: item.name,
children: [],
disabled: item.disabled ? item.disabled : props.disabled,
...item
}))
}
treeData.push(groupNode)
})
return treeData
} else {
return data.map(item => {
const treeItem: Tree = {
label: item.name,
children: [],
disabled: item.disabled ? item.disabled : props.disabled,
...item
}
return treeItem
})
}
}
const filterNode: FilterNodeMethodFunction = (value: string, data: Tree) => {
if (!value) return true
return data.label.includes(value)
}
const handleCommand = (command: string) => {
filter.value.groupBy = command
const oldCheckedKeys = treeRef.value?.getCheckedKeys() || []
treeData.value = convertToTree(props.data, filter.value.groupBy)
treeRef.value?.setCheckedKeys(oldCheckedKeys)
if (filter.value.checkAll) {
setCheckedStatus(true)
}
}
const handleCheckChange = () => {
const checkedKeys = treeRef.value?.getCheckedKeys().filter(item => !item.toString().includes('_')) || []
modelValue.value = checkedKeys
.filter(key => !disabledKeys.value.includes(key.toString()))
.map(key => key.toString())
statistics.value.checked = checkedKeys.length || 0
filter.value.checkAll = statistics.value.checked === statistics.value.total
}
</script>
<style lang="scss">
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
background: var(--el-color-info-light-9);
margin: 0;
padding: 10px 15px;
color: var(--el-color-black);
border: 1px solid var(--el-border-color);
user-select: none;
}
.card-body {
padding: 15px;
}
.card-footer {
margin: 0;
padding: 10px 15px;
}
.el-dropdown-link {
cursor: pointer;
color: var(--el-color-primary);
display: flex;
align-items: center;
}
</style>

View File

@@ -10,7 +10,7 @@
> >
<el-form ref="dialogFormRef" :model="formContent" :rules="rules"> <el-form ref="dialogFormRef" :model="formContent" :rules="rules">
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="10"> <el-col :span="12">
<el-form-item :label-width="110" label="名称" prop="name"> <el-form-item :label-width="110" label="名称" prop="name">
<el-input <el-input
v-model="formContent.name" v-model="formContent.name"
@@ -181,52 +181,21 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="14"> <el-col :span="12">
<el-transfer <DevSelect
v-model="value" v-model="formContent.devIds"
:data="allData" title="被检设备列表"
:filter-method="filterMethod"
:titles="['未绑定被检设备', '已绑定被检设备']"
filter-placeholder="请输入内容搜索" filter-placeholder="请输入内容搜索"
filterable :data="devData"
:height="250"
:disabled="allDisabled"
> >
<template #default="{ option }"> <template v-if="planType === 0 && !allDisabled" #footer>
<div style="display: flex; align-items: center; justify-content: space-between"> <div style="text-align: right">
<span>
{{ JSON.parse(option.label).manufacturer }} - {{ JSON.parse(option.label).name }}
</span>
<el-tooltip effect="light" placement="top">
<template #content>
<el-descriptions border size="small" title="被检设备详情">
<el-descriptions-item label="设备名称">
{{ JSON.parse(option.label).name }}
</el-descriptions-item>
<el-descriptions-item label="设备厂家">
{{ JSON.parse(option.label).manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="所属地市">
{{ JSON.parse(option.label).cityName }}
</el-descriptions-item>
<el-descriptions-item label="所属供电公司">
{{ JSON.parse(option.label).gdName }}
</el-descriptions-item>
<el-descriptions-item label="所属电站">
{{ JSON.parse(option.label).subName }}
</el-descriptions-item>
</el-descriptions>
</template>
<el-icon>
<Warning />
</el-icon>
</el-tooltip>
</div>
</template>
<template v-if="planType === 0 && !allDisabled" #left-footer>
<el-button <el-button
v-if="modeStore.currentMode !== '比对式'" v-if="modeStore.currentMode !== '比对式'"
v-auth.plan="'import'" v-auth.plan="'import'"
:icon="Download" icon="Download"
class="transfer-footer" class="transfer-footer"
size="small" size="small"
type="primary" type="primary"
@@ -237,7 +206,7 @@
<el-button <el-button
v-if="modeStore.currentMode === '比对式'" v-if="modeStore.currentMode === '比对式'"
v-auth.plan="'import'" v-auth.plan="'import'"
:icon="Download" icon="Download"
class="transfer-footer" class="transfer-footer"
size="small" size="small"
type="primary" type="primary"
@@ -245,17 +214,9 @@
> >
导入被检设备 导入被检设备
</el-button> </el-button>
</div>
</template> </template>
<template v-if="planType === 0 && !allDisabled" #right-footer> </DevSelect>
<el-text></el-text>
</template>
<template #left-empty>
<el-empty :image-size="60" description="暂无被检设备" />
</template>
<template #right-empty>
<el-empty :image-size="60" description="暂无被检设备" />
</template>
</el-transfer>
</el-col> </el-col>
</el-row> </el-row>
@@ -274,7 +235,7 @@
<el-input-number <el-input-number
:disabled="isSelectDisabled || allDisabled" :disabled="isSelectDisabled || allDisabled"
style="width: 240px" style="width: 240px"
v-model="formContent.testConfig.maxTime" v-model="formContent.testConfig!.maxTime"
:precision="0" :precision="0"
:step="1" :step="1"
:min="1" :min="1"
@@ -292,7 +253,7 @@
<el-input-number <el-input-number
:disabled="isSelectDisabled || allDisabled" :disabled="isSelectDisabled || allDisabled"
style="width: 240px" style="width: 240px"
v-model="formContent.testConfig.waveRecord" v-model="formContent.testConfig!.waveRecord"
:precision="0" :precision="0"
:step="1" :step="1"
:min="1" :min="1"
@@ -310,7 +271,7 @@
<el-input-number <el-input-number
:disabled="isSelectDisabled || allDisabled" :disabled="isSelectDisabled || allDisabled"
style="width: 240px" style="width: 240px"
v-model="formContent.testConfig.realTime" v-model="formContent.testConfig!.realTime"
:precision="0" :precision="0"
:step="1" :step="1"
:min="1" :min="1"
@@ -328,7 +289,7 @@
<el-input-number <el-input-number
:disabled="isSelectDisabled || allDisabled" :disabled="isSelectDisabled || allDisabled"
style="width: 240px" style="width: 240px"
v-model="formContent.testConfig.statistics" v-model="formContent.testConfig!.statistics"
:precision="0" :precision="0"
:step="1" :step="1"
:min="1" :min="1"
@@ -346,7 +307,7 @@
<el-input-number <el-input-number
:disabled="isSelectDisabled || allDisabled" :disabled="isSelectDisabled || allDisabled"
style="width: 240px" style="width: 240px"
v-model="formContent.testConfig.flicker" v-model="formContent.testConfig!.flicker"
:precision="0" :precision="0"
:step="1" :step="1"
:min="1" :min="1"
@@ -371,7 +332,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { 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, defineProps, 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'
@@ -380,31 +341,28 @@ import {
getBoundPqDevList, getBoundPqDevList,
getBoundStandardDevAllList, getBoundStandardDevAllList,
getPqErrSysList, getPqErrSysList,
getPqErrSysTestItemList,
getPqScriptList, getPqScriptList,
getTestSourceList, getTestSourceList,
getUnboundPqDevList, getUnboundPqDevList,
updatePlan, updatePlan
getPqErrSysTestItemList } from '@/api/plan/plan'
} from '@/api/plan/plan.ts'
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'
import { type TestScript } from '@/api/device/interface/testScript' import { type TestScript } from '@/api/device/interface/testScript'
import { type ErrorSystem } from '@/api/device/interface/error' import { type ErrorSystem } from '@/api/device/interface/error'
import { type Device } from '@/api/device/interface/device' import { type Device } from '@/api/device/interface/device'
import { getPqReportAllName } from '@/api/device/report/index.ts' import { getPqReportAllName } from '@/api/device/report/index'
import { useAppSceneStore, useModeStore } from '@/stores/modules/mode' import { useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { Download } from '@element-plus/icons-vue' import { getAllPqStandardDev } from '@/api/device/standardDevice/index'
import { getAllPqStandardDev } from '@/api/device/standardDevice/index.ts' import { type StandardDevice } from '@/api/device/interface/standardDevice'
import { StandardDevice } from '@/api/device/interface/standardDevice' import { type Dict } from '@/api/system/dictionary/interface'
import { Dict } from '@/api/system/dictionary/interface'
import { getDictTreeByCode } from '@/api/system/dictionary/dictTree'
import { getAllUser } from '@/api/user/user' import { getAllUser } from '@/api/user/user'
import ImportExcel from '@/components/ImportExcel/index.vue' import ImportExcel from '@/components/ImportExcel/index.vue'
import { downloadTemplate, importPqDev } from '@/api/device/device/index' import { downloadTemplate, importPqDev } from '@/api/device/device/index'
import { getTestConfig } from '@/api/system/base' import { getTestConfig } from '@/api/system/base'
import { getRegRes } from '@/api/system/versionRegister' import { getRegRes } from '@/api/system/versionRegister'
const modeStore = useModeStore() const modeStore = useModeStore()
const AppSceneStore = useAppSceneStore() const AppSceneStore = useAppSceneStore()
const dictStore = useDictStore() const dictStore = useDictStore()
@@ -423,15 +381,13 @@ const pqReportName = ref<{ name: string }[]>([])
const pqSourceArray = ref<{ label: string; value: string }[]>() const pqSourceArray = ref<{ label: string; value: string }[]>()
const pqScriptArray = ref<{ label: string; value: string }[]>() const pqScriptArray = ref<{ label: string; value: string }[]>()
const pqErrorArray = ref<{ label: string; value: string }[]>() const pqErrorArray = ref<{ label: string; value: string }[]>()
const pqDevArray = ref<{ label: string; value: string }[]>()
const pqStandardDevArray = ref<{ label: string; value: string }[]>() const pqStandardDevArray = ref<{ label: string; value: string }[]>()
const secondLevelOptions: any[] = [] const secondLevelOptions: any[] = []
const userArray = ref<{ label: string; value: string }[]>([]) const userArray = ref<{ label: string; value: string }[]>([])
const unboundPqDevList = ref<Device.ResPqDev[]>([]) //指定模式下所有未绑定的设备 const unboundPqDevList = ref<Device.ResPqDev[]>([]) //指定模式下所有未绑定的设备
const boundPqDevList = ref<Device.ResPqDev[]>([]) //根据检测计划id查询出所有已绑定的设备 const boundPqDevList = ref<Device.ResPqDev[]>([]) //根据检测计划id查询出所有已绑定的设备
const value = ref<string[]>([]) const devData = ref<any[]>([])
const allData = ref<[any[], any[]]>([])
const isSelectDisabled = ref(false) const isSelectDisabled = ref(false)
const planType = ref<number>(0) const planType = ref<number>(0)
const subPlanBindStandardDev = ref<any>([]) //哪些标准设备已经被子计划绑定 const subPlanBindStandardDev = ref<any>([]) //哪些标准设备已经被子计划绑定
@@ -439,7 +395,11 @@ const activeNames = ref(['1'])
const allDisabled = ref(false) const allDisabled = ref(false)
const generateData = () => { const generateData = () => {
const manufacturerDict = dictStore.getDictData('Dev_Manufacturers') const manufacturerDict = dictStore.getDictData('Dev_Manufacturers')
unboundPqDevList.value.forEach(i => {
const boundPqDevIds: string[] = boundPqDevList.value.map(i => i.id)
const allPqDevList = [...unboundPqDevList.value, ...boundPqDevList.value]
allPqDevList.forEach(i => {
// 确保字段不为空且字典存在再进行查找 // 确保字段不为空且字典存在再进行查找
if (i.manufacturer && manufacturerDict) { if (i.manufacturer && manufacturerDict) {
const manufacturer = manufacturerDict.find(item => item.id === i.manufacturer) const manufacturer = manufacturerDict.find(item => item.id === i.manufacturer)
@@ -447,42 +407,14 @@ const generateData = () => {
i.manufacturer = manufacturer.name i.manufacturer = manufacturer.name
} }
} }
}) i.checked = boundPqDevIds.includes(i.id)
if (i.assign) {
const unboundData = unboundPqDevList.value.map((i: Device.ResPqDev) => ({ i.disabled = i.checkState != 0 || i.assign == 1 || allDisabled.value
key: i.id, } else {
label: JSON.stringify(i), i.disabled = allDisabled.value
disabled: allDisabled.value
}))
boundPqDevList.value.forEach(i => {
// 确保字段不为空且字典存在再进行查找
if (i.manufacturer && manufacturerDict) {
const manufacturer = manufacturerDict.find(item => item.id === i.manufacturer)
if (manufacturer) {
i.manufacturer = manufacturer.name
}
} }
}) })
const boundData = boundPqDevList.value.map((i: Device.ResPqDev) => ({ devData.value = allPqDevList
key: i.id,
label: JSON.stringify(i),
//tips: i.description
disabled: i.checkState != 0 || i.assign == 1 || allDisabled.value
}))
allData.value = [...unboundData, ...boundData]
}
const filterMethod = (query: string, item: { label?: string }) => {
const dataJSON = item.label ? JSON.parse(item.label) : {}
return (
(dataJSON.name?.toLowerCase().includes(query.toLowerCase()) ||
dataJSON.manufacturer?.toLowerCase().includes(query.toLowerCase()) ||
dataJSON.subName?.toLowerCase().includes(query.toLowerCase()) ||
dataJSON.gdName?.toLowerCase().includes(query.toLowerCase()) ||
dataJSON.cityName?.toLowerCase().includes(query.toLowerCase())) ??
false
)
} }
function useMetaInfo() { function useMetaInfo() {
@@ -621,7 +553,6 @@ const rules = computed(() => {
// 关闭弹窗 // 关闭弹窗
const close = () => { const close = () => {
value.value = []
dialogVisible.value = false dialogVisible.value = false
// 清空dialogForm中的值 // 清空dialogForm中的值
resetFormContent() resetFormContent()
@@ -636,7 +567,6 @@ const save = () => {
try { try {
dialogFormRef.value?.validate(async (valid: boolean) => { dialogFormRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {
formContent.devIds = value.value
if (formContent.id) { if (formContent.id) {
// 把数据处理原则转成字典ID // 把数据处理原则转成字典ID
const patternItem = dictStore const patternItem = dictStore
@@ -650,9 +580,6 @@ const save = () => {
if (planType.value == 1) { if (planType.value == 1) {
formContent.fatherPlanId = formContent.id formContent.fatherPlanId = formContent.id
formContent.id = '' formContent.id = ''
//formContent.devIds = []
//formContent.standardDevIds = []
// formContent.standardDevMap = new Map<string, number>()
await addPlan(formContent) await addPlan(formContent)
emit('update:tab') emit('update:tab')
// 编辑子计划 // 编辑子计划
@@ -709,7 +636,6 @@ const save = () => {
// 打开弹窗,可能是新增,也可能是编辑 // 打开弹窗,可能是新增,也可能是编辑
const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan: number) => { const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan: number) => {
unboundPqDevList.value = [] unboundPqDevList.value = []
boundPqDevList.value = [] boundPqDevList.value = []
//处理异步调用 //处理异步调用
@@ -753,11 +679,13 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
// 比对式下这两个接口不需要 // 比对式下这两个接口不需要
pqSource_Result = { data: [] } pqSource_Result = { data: [] }
PqScript_Result = { data: [] } PqScript_Result = { data: [] }
formContent.testConfig.maxTime = sysTestConfig_Result.data?.maxTime if (formContent.testConfig) {
formContent.testConfig.waveRecord = sysRegRes_Result.data?.waveRecord formContent.testConfig.maxTime = (sysTestConfig_Result.data as { maxTime?: number })?.maxTime || 3
formContent.testConfig.realTime = sysRegRes_Result.data?.realTime formContent.testConfig.waveRecord = (sysRegRes_Result.data as { waveRecord?: number })?.waveRecord || 0
formContent.testConfig.statistics = sysRegRes_Result.data?.statistics formContent.testConfig.realTime = (sysRegRes_Result.data as { realTime?: number })?.realTime || 0
formContent.testConfig.flicker = sysRegRes_Result.data?.flicker formContent.testConfig.statistics = (sysRegRes_Result.data as { statistics?: number })?.statistics || 0
formContent.testConfig.flicker = (sysRegRes_Result.data as { flicker?: number })?.flicker || 0
}
} else { } else {
const commonResults = await Promise.all([ const commonResults = await Promise.all([
getTestSourceList(data), getTestSourceList(data),
@@ -793,9 +721,6 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
formContent.sourceIds = pqSourceList.value[0]?.id ?? '' formContent.sourceIds = pqSourceList.value[0]?.id ?? ''
formContent.datasourceIds = dictStore.getDictData('Datasource')[0]?.code ?? '' formContent.datasourceIds = dictStore.getDictData('Datasource')[0]?.code ?? ''
formContent.dataRule = dictStore.getDictData('Data_Rule')[0]?.id ?? '' formContent.dataRule = dictStore.getDictData('Data_Rule')[0]?.id ?? ''
} else { } else {
//编辑时先给表单赋值(这会没接收被检设备),需要手动再给被检设备复制后整体表单赋值 //编辑时先给表单赋值(这会没接收被检设备),需要手动再给被检设备复制后整体表单赋值
@@ -911,16 +836,14 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
pqToArray() //将对象转为数组 pqToArray() //将对象转为数组
//比对式测试项下拉框 //比对式测试项下拉框
if (mode.value == '比对式') { if (mode.value == '比对式') {
// 如果是编辑模式且已有误差体系ID则加载对应的测试项 // 如果是编辑模式且已有误差体系ID则加载对应的测试项
if (formContent.errorSysId) { if (formContent.errorSysId) {
await loadTestItemsForErrorSys(formContent.errorSysId); await loadTestItemsForErrorSys(formContent.errorSysId)
} }
} }
if (mode.value != '比对式') { if (mode.value != '比对式') {
selectByMode.value = false selectByMode.value = false
// 将 formContent.sourceIds 从数组转换为字符串 // 将 formContent.sourceIds 从数组转换为字符串
@@ -933,8 +856,6 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
} }
} }
value.value = boundPqDevList.value.map((i: { id: { toString: () => any } }) => i.id.toString())
if (AppSceneStore.currentScene == '1') { if (AppSceneStore.currentScene == '1') {
//楼下场景不用报告模版 //楼下场景不用报告模版
formContent.associateReport = 0 formContent.associateReport = 0
@@ -960,14 +881,14 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
// 误差体系选择变化时的处理函数 // 误差体系选择变化时的处理函数
const handleErrorSysChange = async (value: string) => { const handleErrorSysChange = async (value: string) => {
// 清空测试项选择 // 清空测试项选择
formContent.testItems = []; formContent.testItems = []
// 如果是比对式模式且选择了误差体系 // 如果是比对式模式且选择了误差体系
if (mode.value === '比对式' && value) { if (mode.value === '比对式' && value) {
try { try {
const res = await getPqErrSysTestItemList({ errorSysId: value }); const res = await getPqErrSysTestItemList({ errorSysId: value })
// 清空原有选项 // 清空原有选项
secondLevelOptions.length = 0; secondLevelOptions.length = 0
if (res.data) { if (res.data) {
// 将返回的键值对对象转换为下拉选项格式 // 将返回的键值对对象转换为下拉选项格式
@@ -975,29 +896,28 @@ const handleErrorSysChange = async (value: string) => {
secondLevelOptions.push({ secondLevelOptions.push({
value: key, value: key,
label: res.data[key] label: res.data[key]
}); })
}); })
} }
} catch (error) { } catch (error) {
console.error('获取测试项失败:', error); console.error('获取测试项失败:', error)
// 发生错误时清空选项 // 发生错误时清空选项
secondLevelOptions.length = 0; secondLevelOptions.length = 0
} }
} else { } else {
// 如果没有选择误差体系,清空测试项选项 // 如果没有选择误差体系,清空测试项选项
secondLevelOptions.length = 0; secondLevelOptions.length = 0
} }
} }
// 根据误差体系ID加载测试项用于初始化 // 根据误差体系ID加载测试项用于初始化
const loadTestItemsForErrorSys = async (errorSysId: string) => { const loadTestItemsForErrorSys = async (errorSysId: string) => {
if (!errorSysId) return; if (!errorSysId) return
try { try {
const res = await getPqErrSysTestItemList({ errorSysId: errorSysId }); const res = await getPqErrSysTestItemList({ errorSysId: errorSysId })
// 清空原有选项 // 清空原有选项
secondLevelOptions.length = 0; secondLevelOptions.length = 0
if (res.data) { if (res.data) {
// 将返回的键值对对象转换为下拉选项格式 // 将返回的键值对对象转换为下拉选项格式
@@ -1005,12 +925,12 @@ const loadTestItemsForErrorSys = async (errorSysId: string) => {
secondLevelOptions.push({ secondLevelOptions.push({
value: key, value: key,
label: res.data[key] label: res.data[key]
}); })
}); })
} }
} catch (error) { } catch (error) {
console.error('获取测试项失败:', error); console.error('获取测试项失败:', error)
secondLevelOptions.length = 0; secondLevelOptions.length = 0
} }
} }
@@ -1045,12 +965,6 @@ function pqToArray() {
value: item.id value: item.id
})) }))
const sourceArray4 = Array.isArray(pqDevList.value) ? pqDevList.value : []
pqDevArray.value = sourceArray4.map(item => ({
label: item.name,
value: item.id
}))
const sourceArray5 = Array.isArray(pqStandardDevList.value) ? pqStandardDevList.value : [] const sourceArray5 = Array.isArray(pqStandardDevList.value) ? pqStandardDevList.value : []
if (planType.value === 0) { if (planType.value === 0) {
pqStandardDevArray.value = sourceArray5.map(item => ({ pqStandardDevArray.value = sourceArray5.map(item => ({