ADD: 检修计划添加项目负责人和项目成员

This commit is contained in:
贾同学
2025-09-08 10:21:54 +08:00
parent 6d6d03c03c
commit 629dff1256
5 changed files with 210 additions and 108 deletions

View File

@@ -36,6 +36,9 @@ export namespace Plan {
children?: ResPlan[];
testConfig?: PlanTestConfig;
importFlag?: number; // 导入标识0-否1-是
leader?: string; // 负责人
memberIds?: string[]; //成员
members?: string; //成员字符串
}
// 检测计划 + 分页

View File

@@ -42,7 +42,7 @@ export const getPqErrSysList = () => {
}
//获取指定模式下所有未绑定的设备
export const getUnboundPqDevList = (params: Plan.ReqPlan) => {
export const getUnboundPqDevList = (params: { pattern: string}) => {
return http.get(`/pqDev/listUnbound?pattern=${params.pattern}`)
}
@@ -152,6 +152,6 @@ export const mergeSubPlanCheckData = (params: Plan.ResPlan) => {
}
//根据误差体系id获取测试项
export const getPqErrSysTestItemList = (params: Plan.ResPlan) => {
export const getPqErrSysTestItemList = (params: {errorSysId : string}) => {
return http.get(`/pqErrSys/getTestItems?id=${params.errorSysId}`)
}

View File

@@ -1,23 +1,23 @@
// 登录模块
import type { ReqPage,ResPage } from '@/api/interface'
import type { ReqPage, ResPage } from '@/api/interface'
export namespace Login {
export interface ReqLoginForm {
username: string;
password: string;
checked: boolean;
}
export interface ResLogin {
accessToken: string;
refreshToken: string;
userInfo:{
id: string;
name: string;
export interface ReqLoginForm {
username: string
password: string
checked: boolean
}
export interface ResLogin {
accessToken: string
refreshToken: string
userInfo: {
id: string
name: string
}
}
export interface ResAuthButtons {
[key: string]: string[]
}
}
export interface ResAuthButtons {
[key: string]: string[];
}
}
@@ -52,6 +52,8 @@ export namespace User {
updateTime?: string;//更新时间
roleIds?: string[]; //
roleNames?:string[]; //
roleCodes?:string[]; //
disabled?: boolean;
}
// 用户接口

View File

@@ -24,9 +24,10 @@
<el-select
v-model="formContent.standardDevIds"
:disabled="planType == 2 || allDisabled"
:max-collapse-tags="2"
:max-collapse-tags="1"
clearable
collapse-tags
collapse-tags-tooltip
filterable
multiple
placeholder="请选择标准设备"
@@ -44,9 +45,10 @@
<el-select
v-model="formContent.testItems"
:disabled="planType != 0 || allDisabled"
:max-collapse-tags="3"
:max-collapse-tags="1"
clearable
collapse-tags
collapse-tags-tooltip
filterable
multiple
placeholder="请选择测试项"
@@ -82,6 +84,7 @@
v-model="formContent.datasourceIds"
:disabled="allDisabled"
:max-collapse-tags="1"
collapse-tags-tooltip
:multiple="selectByMode"
autocomplete="off"
:clearable="planType != 0"
@@ -95,7 +98,7 @@
:key="item.id"
:label="item.name"
:value="item.code || ''"
:disabled="planType == 0 || allDisabled"
:disabled="(selectByMode && planType == 0) || allDisabled"
/>
</el-select>
</el-form-item>
@@ -181,6 +184,45 @@
/>
</el-select>
</el-form-item>
<el-form-item v-if="selectByMode" :label-width="110" label="项目负责人" prop="leader">
<el-select
v-model="formContent.leader"
:disabled="planType != 0 || allDisabled"
clearable
autocomplete="off"
placeholder="请选择项目负责人"
>
<el-option
v-for="user in leaderData"
:key="user.id"
:label="user.name"
:value="user.id"
:disabled="user.disabled"
/>
</el-select>
</el-form-item>
<el-form-item v-if="selectByMode" :label-width="110" label="项目成员" prop="memberIds">
<el-select
v-model="formContent.memberIds"
:disabled="allDisabled"
multiple
autocomplete="off"
clearable
collapse-tags
collapse-tags-tooltip
:max-collapse-tags="2"
filterable
placeholder="请选择项目成员"
>
<el-option
v-for="user in memberData"
:key="user.id"
:label="user.name"
:value="user.id"
:disabled="user.disabled"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="15">
<DevSelect
@@ -188,7 +230,7 @@
:titles="['被检设备列表', '已选被检设备列表']"
filter-placeholder="请输入内容搜索"
:data="devData"
:height="220"
:height="selectByMode ? 325 : 220"
:disabled="allDisabled"
>
<template v-if="planType === 0 && !allDisabled" #footer>
@@ -353,16 +395,17 @@ import { type TestSource } from '@/api/device/interface/testSource'
import { type TestScript } from '@/api/device/interface/testScript'
import { type ErrorSystem } from '@/api/device/interface/error'
import { type Device } from '@/api/device/interface/device'
import { getPqReportAllName } from '@/api/device/report/index'
import { getPqReportAllName } from '@/api/device/report'
import { useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { canBindingList, getAllPqStandardDev } from '@/api/device/standardDevice/index'
import { canBindingList, getAllPqStandardDev } from '@/api/device/standardDevice'
import { type StandardDevice } from '@/api/device/interface/standardDevice'
import { type Dict } from '@/api/system/dictionary/interface'
import { getAllUser } from '@/api/user/user'
import ImportExcel from '@/components/ImportExcel/index.vue'
import { downloadTemplate, importPqDev } from '@/api/device/device/index'
import { downloadTemplate, importPqDev } from '@/api/device/device'
import { getTestConfig } from '@/api/system/base'
import { getRegRes } from '@/api/system/versionRegister'
import DevSelect from '@/views/plan/planList/components/devSelect.vue'
const modeStore = useModeStore()
const AppSceneStore = useAppSceneStore()
@@ -384,8 +427,6 @@ const pqScriptArray = ref<{ label: string; value: string }[]>()
const pqErrorArray = ref<{ label: string; value: string }[]>()
const pqStandardDevArray = ref<{ label: string; value: string }[]>()
const secondLevelOptions: any[] = []
const userArray = ref<{ label: string; value: string }[]>([])
const unboundPqDevList = ref<Device.ResPqDev[]>([]) //指定模式下所有未绑定的设备
const boundPqDevList = ref<Device.ResPqDev[]>([]) //根据检测计划id查询出所有已绑定的设备
const devData = ref<any[]>([])
@@ -394,6 +435,8 @@ const planType = ref<number>(0)
const subPlanBindStandardDev = ref<any>([]) //哪些标准设备已经被子计划绑定
const activeNames = ref(['1'])
const allDisabled = ref(false)
const leaderData = ref<any[]>([])
const memberData = ref<any[]>([])
const generateData = () => {
const manufacturerDict = dictStore.getDictData('Dev_Manufacturers')
@@ -472,12 +515,32 @@ function useMetaInfo() {
flicker: 0,
maxTime: 3
},
importFlag: 0
importFlag: 0,
leader: '',
memberIds: []
})
return { dialogVisible, titleType, formContent }
}
const { dialogVisible, titleType, formContent } = useMetaInfo()
watch(
() => formContent.leader,
val => {
// 只更新memberData中的disabled状态
memberData.value.forEach(item => {
item.disabled = val ? item.id === val : false
})
}
)
watch(
() => formContent.memberIds,
val => {
// 只更新leaderData中的disabled状态
leaderData.value.forEach(item => {
item.disabled = Array.isArray(val) && val.length > 0 ? val.includes(item.id) : false
})
}
)
// 清空formContent
const resetFormContent = () => {
@@ -520,7 +583,9 @@ const resetFormContent = () => {
flicker: 0,
maxTime: 3
},
importFlag: 0
importFlag: 0,
leader: '',
memberIds: []
})
}
@@ -548,7 +613,9 @@ const baseRules: Record<string, Array<FormItemRule>> = {
'testConfig.waveRecord': [{ required: true, message: '录波数据有效组数必填!', trigger: 'blur' }],
'testConfig.realTime': [{ required: true, message: '实时数据有效组数必填!', trigger: 'blur' }],
'testConfig.statistics': [{ required: true, message: '统计数据有效组数必填!', trigger: 'blur' }],
'testConfig.flicker': [{ required: true, message: '闪变数据有效组数必填!', trigger: 'blur' }]
'testConfig.flicker': [{ required: true, message: '闪变数据有效组数必填!', trigger: 'blur' }],
leader: [{ required: true, message: '项目负责人必选!', trigger: 'change' }],
memberIds: [{ required: true, message: '项目成员必选!', trigger: 'change' }]
}
// 使用计算属性根据 scene 动态生成规则
@@ -658,36 +725,37 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
titleType.value = sign
isSelectDisabled.value = false
planType.value = plan
if (sign == 'add') {
resetFormContent()
allDisabled.value = false
let pqSource_Result,
PqScript_Result,
PqErrSys_Result,
pqDevList_Result,
pqReportName_Result,
pqStandardDev_Result,
sysTestConfig_Result,
sysRegRes_Result
let pqSource_Result: any,
PqScript_Result: any,
PqErrSys_Result: any,
pqDevList_Result: any,
pqReportName_Result: any,
pqStandardDev_Result: any,
sysTestConfig_Result: any,
sysRegRes_Result: any,
user_Result: any
if (mode.value === '比对式') {
const commonResults = await Promise.all([
getPqErrSysList(),
getUnboundPqDevList(data),
getPqReportAllName(),
canBindingList(),
getTestConfig(),
getRegRes({ type: patternId })
])
;[
PqErrSys_Result,
pqDevList_Result,
pqReportName_Result,
pqStandardDev_Result,
sysTestConfig_Result,
sysRegRes_Result
] = commonResults
sysRegRes_Result,
user_Result
] = await Promise.all([
getPqErrSysList(),
getUnboundPqDevList({ pattern: data.pattern }),
getPqReportAllName(),
canBindingList(),
getTestConfig(),
getRegRes({ type: patternId }),
getAllUser()
])
// 比对式下这两个接口不需要
pqSource_Result = { data: [] }
@@ -699,19 +767,30 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
formContent.testConfig.statistics = (sysRegRes_Result.data as { statistics?: number })?.statistics || 0
formContent.testConfig.flicker = (sysRegRes_Result.data as { flicker?: number })?.flicker || 0
}
if (Array.isArray(user_Result.data)) {
if (user_Result.data.length > 0) {
// 为leaderData和memberData分别创建独立的对象数组
leaderData.value = user_Result.data
.filter((user: any) => !user.roleCodes.includes('root'))
.map((user: any) => ({ ...user, disabled: false }))
memberData.value = user_Result.data
.filter((user: any) => !user.roleCodes.includes('root'))
.map((user: any) => ({ ...user, disabled: false }))
}
}
} else {
const commonResults = await Promise.all([
getTestSourceList(data),
getPqScriptList(data),
getPqErrSysList(),
getUnboundPqDevList(data),
getPqReportAllName()
])
;[pqSource_Result, PqScript_Result, PqErrSys_Result, pqDevList_Result, pqReportName_Result] = commonResults
;[pqSource_Result, PqScript_Result, PqErrSys_Result, pqDevList_Result, pqReportName_Result] =
await Promise.all([
getTestSourceList(data),
getPqScriptList(data),
getPqErrSysList(),
getUnboundPqDevList({ pattern: data.pattern }),
getPqReportAllName()
])
}
if (Array.isArray(pqReportName_Result.data)) {
pqReportName.value = pqReportName_Result.data.map(item => ({ name: item }))
pqReportName.value = pqReportName_Result.data.map((item: any) => ({ name: item }))
} else {
pqReportName.value = []
}
@@ -733,10 +812,12 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
formContent.errorSysId = pqErrSysList.value[0]?.id ?? ''
formContent.sourceIds = pqSourceList.value[0]?.id ?? ''
const datasourceDicts = dictStore.getDictData('Datasource')
if (plan == 0) {
if (plan == 0 && mode.value === '比对式') {
formContent.datasourceIds = datasourceDicts.map(item => item.code)
} else {
formContent.datasourceIds = dictStore.getDictData('Datasource')[0]?.code ?? ''
}
// formContent.datasourceIds = dictStore.getDictData('Datasource')[0]?.code ?? ''
formContent.dataRule = dictStore.getDictData('Data_Rule')[0]?.id ?? ''
} else {
//编辑时先给表单赋值(这会没接收被检设备),需要手动再给被检设备复制后整体表单赋值
@@ -744,11 +825,7 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
if (plan == 1 || plan == 2) {
isSelectDisabled.value = true
} else {
if (data.testState === 0) {
isSelectDisabled.value = false
} else {
isSelectDisabled.value = true
}
isSelectDisabled.value = data.testState !== 0
if (data.importFlag === 1) {
allDisabled.value = true
}
@@ -756,29 +833,32 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
Object.assign(formContent, { ...data })
let pqSource_Result,
PqScript_Result,
PqErrSys_Result,
boundPqDevList_Result,
unboundPqDevList_Result,
pqReportName_Result,
pqStandardDev_Result
let pqSource_Result: any,
PqScript_Result: any,
PqErrSys_Result: any,
boundPqDevList_Result: any,
unboundPqDevList_Result: any,
pqReportName_Result: any,
pqStandardDev_Result: any,
user_Result: any
if (mode.value === '比对式') {
const commonResults = await Promise.all([
getPqErrSysList(),
getBoundPqDevList({ planIdList: [data.id] }),
getUnboundPqDevList(data),
getPqReportAllName(),
getAllPqStandardDev()
])
formContent.memberIds = data.members ? data.members.split(',') : []
;[
PqErrSys_Result,
boundPqDevList_Result,
unboundPqDevList_Result,
pqReportName_Result,
pqStandardDev_Result
] = commonResults
pqStandardDev_Result,
user_Result
] = await Promise.all([
getPqErrSysList(),
getBoundPqDevList({ planIdList: [data.id] }),
getUnboundPqDevList({ pattern: data.pattern }),
getPqReportAllName(),
getAllPqStandardDev(),
getAllUser()
])
// 比对式下这两个接口不需要
pqSource_Result = { data: [] }
@@ -788,22 +868,28 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
formContent.standardDevIds = Object.keys(formContent.standardDevMap)
//哪些标准设备已经被子计划绑定
subPlanBindStandardDev.value = Object.entries(formContent.standardDevMap)
.filter(([key, value]) => value === 1)
.filter(([, value]) => value === 1)
.map(([key]) => {
const matched = pqStandardDev_Result.data?.find(
(item: StandardDevice.ResPqStandardDevice) => item.id === key
)
return matched ? matched.name : key
})
if (Array.isArray(user_Result.data)) {
if (user_Result.data.length > 0) {
// 为leaderData和memberData分别创建独立的对象数组
leaderData.value = user_Result.data
.filter((user: any) => !user.roleCodes.includes('root'))
.map((user: any) => ({
...user,
disabled: formContent.memberIds ? formContent.memberIds.includes(user.id) : false
}))
memberData.value = user_Result.data
.filter((user: any) => !user.roleCodes.includes('root'))
.map((user: any) => ({ ...user, disabled: formContent.leader === user.id }))
}
}
} else {
const commonResults = await Promise.all([
getTestSourceList(data),
getPqScriptList(data),
getPqErrSysList(),
getBoundPqDevList({ planIdList: [data.id] }),
getUnboundPqDevList(data),
getPqReportAllName()
])
;[
pqSource_Result,
PqScript_Result,
@@ -811,11 +897,18 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
boundPqDevList_Result,
unboundPqDevList_Result,
pqReportName_Result
] = commonResults
] = await Promise.all([
getTestSourceList(data),
getPqScriptList(data),
getPqErrSysList(),
getBoundPqDevList({ planIdList: [data.id] }),
getUnboundPqDevList({ pattern: data.pattern }),
getPqReportAllName()
])
}
if (Array.isArray(pqReportName_Result.data)) {
pqReportName.value = pqReportName_Result.data.map(item => ({ name: item }))
pqReportName.value = pqReportName_Result.data.map((item: any) => ({ name: item }))
} else {
pqReportName.value = []
}
@@ -831,7 +924,7 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
const boundData = Array.isArray(boundPqDevList_Result.data) ? boundPqDevList_Result.data : []
const unboundData = Array.isArray(unboundPqDevList_Result.data) ? unboundPqDevList_Result.data : []
pqDevList.value = [...boundData, ...unboundData] as Device.ResPqDev[]
formContent.devIds = boundData.map(i => i.id) // 已绑定设备id集合
formContent.devIds = boundData.map((i: any) => i.id) // 已绑定设备id集合
Object.assign(formContent, { ...data })
//设备绑定显示
@@ -839,13 +932,13 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
unboundPqDevList.value = unboundData as Device.ResPqDev[]
boundPqDevList.value = boundData as Device.ResPqDev[]
} else if (planType.value === 1) {
unboundPqDevList.value = boundData.filter(i => !i.boundPlanName) as Device.ResPqDev[]
unboundPqDevList.value = boundData.filter((i: any) => !i.boundPlanName) as Device.ResPqDev[]
} else if (planType.value === 2) {
const fatherBoundData_Result = await getBoundPqDevList({ planIdList: [data.fatherPlanId] })
const fatherBoundData = Array.isArray(fatherBoundData_Result.data) ? fatherBoundData_Result.data : []
// 从 fatherBoundData 中排除 boundData 中已存在的数据(根据 id 进行比较)
unboundPqDevList.value = fatherBoundData.filter(
fatherItem => !boundData.some(boundItem => boundItem.id === fatherItem.id)
fatherItem => !boundData.some((boundItem: any) => boundItem.id === fatherItem.id)
) as Device.ResPqDev[]
boundPqDevList.value = boundData as Device.ResPqDev[]
}
@@ -882,13 +975,6 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
if (plan == 1) {
//新增子计划名称清空
formContent.name = ''
const userList = await getAllUser()
const sourceArray1 = Array.isArray(userList.data) ? userList.data : []
// 将 pqSource_Result 转换成 { label, value } 数组
userArray.value = sourceArray1.map(item => ({
label: item.loginName || '',
value: item.id
}))
}
generateData()
// 所有数据加载完成后显示对话框
@@ -907,12 +993,12 @@ const handleErrorSysChange = async (value: string) => {
// 清空原有选项
secondLevelOptions.length = 0
if (res.data) {
if (res.data && typeof res.data === 'object') {
// 将返回的键值对对象转换为下拉选项格式
Object.keys(res.data).forEach(key => {
secondLevelOptions.push({
value: key,
label: res.data[key]
label: (res.data as Record<string, string>)[key]
})
})
}
@@ -936,12 +1022,12 @@ const loadTestItemsForErrorSys = async (errorSysId: string) => {
// 清空原有选项
secondLevelOptions.length = 0
if (res.data) {
if (res.data && typeof res.data === 'object') {
// 将返回的键值对对象转换为下拉选项格式
Object.keys(res.data).forEach(key => {
secondLevelOptions.push({
value: key,
label: res.data[key]
label: (res.data as Record<string, string>)[key]
})
})
}
@@ -1070,9 +1156,8 @@ const importFile = async (pattern: string) => {
const importResult = async (success: boolean | undefined) => {
if (success) {
const patternId = dictStore.getDictData('Pattern').find(item => item.name === mode.value)?.id ?? ''
const data = { pattern: patternId }
// 刷新未绑定的
const unboundPqDevList_Result = await getUnboundPqDevList(data)
const unboundPqDevList_Result = await getUnboundPqDevList({ pattern: patternId })
const unboundData = Array.isArray(unboundPqDevList_Result.data) ? unboundPqDevList_Result.data : []
unboundPqDevList.value = unboundData
generateData()

View File

@@ -519,6 +519,18 @@ const columns = reactive<ColumnProps<Plan.ReqPlan>[]>([
fieldNames: { label: 'name', value: 'id' },
minWidth: 120
},
{
prop: 'leaderName',
label: '项目负责人',
minWidth: 120,
isShow: modeStore.currentMode == '比对式'
},
{
prop: 'membersName',
label: '项目成员',
minWidth: 100,
isShow: modeStore.currentMode == '比对式'
},
{ prop: 'operation', label: '操作', fixed: 'right', minWidth: 250 }
])