diff --git a/src/service/api/system.ts b/src/service/api/system.ts index ba108a2..5c8c358 100644 --- a/src/service/api/system.ts +++ b/src/service/api/system.ts @@ -85,14 +85,6 @@ export function getFlowApi(data:{category:number | null,level:number | null,dura params: data, }); } -// 本单审批流程·审批人设置 -export function setApproverApi(id:number,data:any) { - return request({ - url: `/api/changes/${id}/approval-flow`, - method: 'put', - data, - }); -} // 获取风险矩阵配置 export function matrixConfigApi() { diff --git a/src/views/details/disposal/index.vue b/src/views/details/disposal/index.vue index 6874104..05f2f6c 100644 --- a/src/views/details/disposal/index.vue +++ b/src/views/details/disposal/index.vue @@ -4,7 +4,7 @@ import { Icon } from '@iconify/vue' import { useThemeStore } from '@/store/modules/theme'; import { useRouterPush } from '@/hooks/common/router'; import { useRoute } from 'vue-router'; -import { getColorWithOpacity, tagTextColor, tagBgColor, tagBorderColor, formatTimestamp, downloadFileFun } from '@/utils/common'; +import { tagTextColor, tagBgColor, tagBorderColor, formatTimestamp, downloadFileFun } from '@/utils/common'; import { AiError, aiTypeJudge } from "@/service/api/ai"; import { systemConfigApi, peopleListApi } from '@/service/api/system'; import { getChangeDetailApi, urgeApi } from '@/service/api/change'; @@ -45,10 +45,18 @@ const judge = ref(''); const delayDate = ref(null); // 审批流程抽屉 const approvalDrawer = ref(false); -// 存储每个步骤选中的审核人 user_id -const approvers = ref>({}) const flowList = ref([]); const steps = ref([]); +// 专业 +const SPECIALTIES = [ + { label: '生产', value: '生产' }, + { label: '技术', value: '技术' }, + { label: '仪表', value: '仪表' }, + { label: '电气', value: '电气' }, + { label: '设备', value: '设备' }, + { label: '安全', value: '安全' }, + { label: '质量', value: '质量' } +]; // 审批链 const approvalFlowText = computed(() => { if (!flowList.value || flowList.value.length === 0) return '暂无步骤' @@ -236,28 +244,9 @@ const handleReminder = async (m: any) => { loading.value = false; } -// 更新选中审批人 user_id -const updateApprover = (stepId: number, usersId: number[]) => { - approvers.value[stepId] = usersId -} -// 匹配审批人 -function matchApprovers(steps: any[], mapping: Record) { - const result = []; - for (const [stepId, usersId] of Object.entries(mapping)) { - const step = steps.find(s => s.id === Number(stepId)); - if (step) { - const memberList = step.members.filter((m: any) => usersId.includes(m.user_id)); - result.push({ - members: memberList - }) - } - } - return result; -} // 完成设置 const finishApprover = async () => { - const matched = matchApprovers(flowList.value, approvers.value); - steps.value = matched; + steps.value = flowList.value || []; window.$message?.success("审批流程设置完成"); approvalDrawer.value = false; } @@ -349,6 +338,7 @@ const submitDisposal = async (type: string) => { const result = steps.value.map(({ members }:any) => ({ members: members.map(({ id, step_order, user_name, status, ...rest }:any) => rest) })); + loading.value = true; const {error} = await myTasksDisposalSubmitApi(currentId.value,{ action: type, act: actType, @@ -369,6 +359,7 @@ const submitDisposal = async (type: string) => { back(); } } + loading.value = false; } // 获取变更详情 @@ -379,20 +370,7 @@ const getDetail = async () => { currentInfo.value = data; // ******审批流程******** flowList.value = data?.approval_flow?.steps || []; - // ******默认审批人******** - if(Object.keys(approvers.value).length === 0){ - flowList.value.forEach((item: any) => { - if (item.members && item.members.length > 0) { - // 优先选 is_sign=1 的成员 ,否则选第一个 - const defaultMembers = item.members - .filter((m: any) => m.is_sign === 1) - .map((m: any) => m.user_id); - approvers.value[item.id] = defaultMembers.length > 0 ? defaultMembers : [item.members[0].user_id]; - } - }) - } - const matched = matchApprovers(flowList.value, approvers.value); - steps.value = matched; + steps.value = data?.approval_flow?.steps || []; // ******解析 PSSR 检查内容******** const map = new Map(); for (const item of currentInfo.value?.pssr?.items) { @@ -473,22 +451,105 @@ const getConfig = async () => { loading.value = false; } +// 人员数据转换 +const groupUsersByOrg = (users:any) => { + const orgMap = new Map(); // key: org.id, value: { id, label, children } + users.forEach((user:any) => { + const { id: userId, realname, user_departments } = user; + if (!user_departments || user_departments.length === 0) return; + + user_departments.forEach((dept:any) => { + const org = dept.org; + if (!org || !org.id) return; + + if (!orgMap.has(org.id)) { + orgMap.set(org.id, { + value: org.id, + label: org.label, + children: [] + }); + } + const targetOrg = orgMap.get(org.id); + // 避免同一个用户重复加入同一个组织(理论上不会发生,但做去重保护) + if (!targetOrg.children.some((child:any) => child.id === userId)) { + targetOrg.children.push({ + value: userId.toString(), + label: realname, + user_id: userId.toString() + }); + } + }); + }); + return Array.from(orgMap.values()); +} + // 获取所有人员 const getAllMembers = async () => { const {data,error} = await peopleListApi(); if(!error){ - const transformed = data.map((item:any) => ({ - user_id: item.id, - user_name: item.realname, - full_name: item.realname + (`(${item.user_departments.map((d:any) => d.label).join(';')})`), - org_id: item.user_departments.map((d:any) => d.organization_id).join(';'), - org_name: item.user_departments.map((d:any) => d.label).join(';') - })); - memberList.value = transformed; + memberList.value = groupUsersByOrg(data); } } +/** + * 在组织树中根据 user_id 查找用户信息 + * @param {Array} tree - 组织树数据 + * @param {string|number} targetUserId - 要查找的 user_id + * @returns {Object|null} - 返回 { userLabel, parentLabel, parentValue } 或 null + */ +function findUserInTree(tree: any[], targetUserId: string | number) { + for (const org of tree) { + const children = org.children || []; + for (const user of children) { + if (String(user.user_id) === String(targetUserId)) { + return { + user_name: user.label, + org_name: org.label, + org_id: org.value + }; + } + } + } + return null; // 未找到 +} +// 设置专业会签步骤 +const setStepCountersign = (target: any, v: boolean) => { + flowList.value.forEach((s:any) => { + s.countersign = s === target ? v : false; + if (!s.countersign) s.members.forEach((m:any) => { m.specialty = ""; m.is_sign = 0; }); + }); +} +// 选择专业 +const selectSpecialty = (idx: number, mIdx: number, v: string | null) => { + flowList.value[idx].members[mIdx].specialty = v ?? null; +} +// 选择是否必须参与会签 +const selectSign = (idx: number, mIdx: number, v: number) => { + flowList.value[idx].members[mIdx].is_sign = v; +} +// 当前打开人员选择器的步骤(步骤行「+」按钮切换) +const pickerStepId = ref(null); +const pick = ref(null); +const togglePicker = (s: any) => { + pickerStepId.value = pickerStepId.value === s.id ? null : s.id; + pick.value = null; +} +// 添加审批步骤人员 +const addMember = (s: any, v: string | null) => { + if (v && !s.members.some((m:any) => m.user_name === v)){ + let info = findUserInTree(memberList.value, v); + s.members.push({ user_id: Number(v), user_name: info?.user_name || '', org_id: info?.org_id || '', org_name: info?.org_name || '', specialty: "", is_sign: 0 }); + pick.value = null; + pickerStepId.value = null; + } +} +// 删除审批步骤人员 +const delMember = (s: any, p: number) => { + s.members = s.members.filter((m:any) => m.user_id !== p); +} + onMounted(async () => { + getAllMembers(); if(route.query && route.query.id){ if(route.query.id){ currentId.value = Number(route.query.id); @@ -1009,8 +1070,8 @@ onMounted(async () => { :style="{ borderRadius: themeStore.themeRadius + 'px' }" > 审批流程设置 - 保存 - 提交 + 保存 + 提交 @@ -1082,15 +1143,56 @@ onMounted(async () => {

审批链:{{ approvalFlowText }}。专业会签人由申请表「涉及专业」勾选自动增减,可在此调整人选;重要变更自动追加安全审查与分管领导终批。

-
-
- {{Number(index)+1}} {{item.name}} {{item.countersign ? '(专业会签)' : ''}} +
+
+ {{Number(idx)+1}} +

{{s.name}}

+ + 专业会签步骤 + + + + +
+ +
+ 预设人员: +
+
+ {{ m.user_name }} + + + + +
+

+ 必须参与会签:勾选的人员必须参与专业会签,未勾选的人员为可选会签(按需参加) +

+ + + 未预设 +
-
- 完成设置
+ diff --git a/src/views/my/initiateChange/modules/approvalDrawer.vue b/src/views/my/initiateChange/modules/approvalDrawer.vue deleted file mode 100644 index 33dff21..0000000 --- a/src/views/my/initiateChange/modules/approvalDrawer.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - - \ No newline at end of file