diff --git a/src/composables/useSubApproveUserResolver.ts b/src/composables/useSubApproveUserResolver.ts new file mode 100644 index 0000000..4f6fe9d --- /dev/null +++ b/src/composables/useSubApproveUserResolver.ts @@ -0,0 +1,72 @@ +import { ref } from 'vue'; +import { getUserList } from '/@/api/common/api'; + +function normalizeCommaList(value: string): string { + return String(value || '') + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + .join(','); +} + +function normalizeDisplayNames(value: string): string { + return String(value || '') + .split(/[,,;;、]/) + .map((s) => s.trim()) + .filter(Boolean) + .join('、'); +} + +/** + * 部门经办人选人 + 名称解析,统一 BgXiSpeak / DqInspectTask 等 BPM 表单的 + * username → realname 转换逻辑。 + * + * - `usernames`: 原始 username(逗号分隔),绑定 sz-dept-user-modal 的 v-model + * - `displayNames`: 真实姓名(顿号分隔),用于审批意见模板和 formScope + * - `setDisplayNames`: modal @confirm 已携带 realname 时直接设置(同步,无 API) + * - `initFromData`: 从已保存数据初始化时,通过 API 一次性解析 username → realname + */ +export function useSubApproveUserResolver() { + const usernames = ref(''); + const displayNames = ref(''); + + /** modal @confirm 回调直接设置已携带的 realname */ + function setDisplayNames(userIds: string, realnames: string) { + usernames.value = normalizeCommaList(userIds); + displayNames.value = normalizeDisplayNames(realnames); + } + + /** 从已保存数据初始化(需 API 解析 username → realname) */ + async function initFromData(rawUsernames: string) { + usernames.value = normalizeCommaList(rawUsernames); + if (!usernames.value) { + displayNames.value = ''; + return; + } + + try { + const res = await getUserList({ + username: usernames.value, + isMultiTranslate: 'true', + pageNo: 1, + pageSize: 999, + }); + const records = res?.records || res?.result?.records || res || []; + const nameMap: Record = {}; + for (const item of records) { + const u = String(item?.username || '').trim(); + const r = String(item?.realname || item?.name || '').trim(); + if (u && r) nameMap[u] = r; + } + const resolved = usernames.value + .split(',') + .map((u) => nameMap[u.trim()] || u.trim()) + .filter(Boolean); + displayNames.value = normalizeDisplayNames(resolved.join(',')); + } catch { + // 解析失败,保持空 + } + } + + return { usernames, displayNames, setDisplayNames, initFromData }; +} diff --git a/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue b/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue index 30dbf50..8869d7d 100644 --- a/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue +++ b/src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue @@ -246,7 +246,7 @@ - + @@ -278,7 +278,7 @@ import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue'; import Icon from '/@/components/Icon/index'; import { bgXiSpeakFeedbackList, bgXiSpeakFeedbackDelete, saveBpmForm, saveSubApprove, getProcessVariable } from '../BgXiSpeak.api'; - import { getUserList } from '/@/api/common/api'; + import { useSubApproveUserResolver } from '/@/composables/useSubApproveUserResolver'; import { usePermission } from '/@/hooks/web/usePermission'; import TaskHandleInnerContent from '/@/views/super/bpm/process/personalOffice/myHandleTask/content/TaskHandleInnerContent.vue'; import BgXiSpeakBPMFeedbackModal from './BgXiSpeakBPMFeedbackModal.vue'; @@ -328,9 +328,7 @@ import { const showBaseInfoDetail = ref(false); const showFeedbackDetail = ref(true); const feedbackList = ref([]); - const subApproveUser = ref(''); - const subApproveUserNameText = ref(''); - const userResolveVersion = ref(0); + const { usernames: subApproveUser, displayNames: subApproveUserNameText, setDisplayNames, initFromData } = useSubApproveUserResolver(); const isEnd = ref(0); const mainForm = reactive>({ @@ -469,9 +467,10 @@ import { Task_0jrgrzs: buildDeptHandlerFeedbackReason, Task_12vdqzv: buildDeptHandlerFeedbackReason, // 部门负责人接受任务并分配 - Task_1v9ce78: () => buildDeptLeaderAssignReason( - normalizeDeptNames(subApproveUserNameText.value || subApproveUser.value), - ), + Task_1v9ce78: () => { + if (isEnd.value === 1) return ''; + return buildDeptLeaderAssignReason(normalizeDeptNames(subApproveUserNameText.value)); + }, // 部门负责人直接反馈 Task_0sialna: buildDeptLeaderDirectFeedbackReason, // 督办部门经办人确认全部反馈事项 @@ -525,14 +524,13 @@ import { }, { immediate: true } ); - - watch( - subApproveUser, - (value) => { - resolveSubApproveUserName(value); - }, - { immediate: true } - ); + watch(isEnd, (val) => { + const vars = props.formData?.vars; + if (vars) { + vars.is_end = String(val); + vars.isEnd = String(val); + } + }); async function initFormData() { const dataId = props.formData?.dataId; @@ -560,7 +558,7 @@ import { if (approveInfo && deptId && approveInfo[deptId]) { const detail = approveInfo[deptId]; isEnd.value = detail.isEnd ?? 0; - subApproveUser.value = detail.implWorker ?? ''; + initFromData(detail.implWorker ?? ''); } } @@ -771,42 +769,6 @@ import { .join(','); } - async function resolveSubApproveUserName(value: any) { - const resolveVersion = ++userResolveVersion.value; - const usernames = normalizeUsernameList(value); - if (!usernames) { - subApproveUserNameText.value = ''; - return; - } - - subApproveUserNameText.value = normalizeDeptNames(usernames); - try { - const res = await getUserList({ username: usernames, isMultiTranslate: 'true', pageNo: 1, pageSize: 999 }); - if (resolveVersion !== userResolveVersion.value) { - return; - } - const records = res?.records || res?.result?.records || res || []; - const userNameMap = Array.isArray(records) - ? records.reduce((cache: Record, item: any) => { - const username = String(item?.username || '').trim(); - const realname = String(item?.realname || item?.name || '').trim(); - if (username && realname) { - cache[username] = realname; - } - return cache; - }, {}) - : {}; - const names = usernames - .split(',') - .map((username) => userNameMap[username] || username) - .filter(Boolean); - subApproveUserNameText.value = normalizeDeptNames(names.join(',')); - } catch { - if (resolveVersion === userResolveVersion.value) { - subApproveUserNameText.value = normalizeDeptNames(usernames); - } - } - } function handleProcessSuccess() { emit('success'); diff --git a/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue b/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue index 7536aec..804bcbe 100644 --- a/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue +++ b/src/views/dq/inspectTask/components/DqInspectTaskBPMForm.vue @@ -245,6 +245,8 @@ import SzDeptUserModal from '/@/components/semri/deptUserComponent/SzDeptUserMod import { usePermission } from '/@/hooks/web/usePermission'; import { PARTY_COMMITTEE_DEPT_ID, SDW_LEADER_ROLE_ID } from '/@/constant/supervision'; import { useSelectNameResolver } from '/@/composables/useSelectNameResolver'; +import { useSubApproveUserResolver } from '/@/composables/useSubApproveUserResolver'; +import { buildDeptLeaderAssignReason, normalizeDeptNames } from '/@/composables/useDefaultApprovalReason'; import TaskHandleInnerContent from '/@/views/super/bpm/process/personalOffice/myHandleTask/content/TaskHandleInnerContent.vue'; import DqInspectTaskBPMFeedbackModal from './DqInspectTaskBPMFeedbackModal.vue'; import SUploadFile from '/@/components/semri/fileComponent/SUploadFile.vue'; @@ -279,8 +281,7 @@ import { useSelectNameResolver } from '/@/composables/useSelectNameResolver'; const showBaseInfoDetail = ref(false); const showFeedbackDetail = ref(true); const feedbackList = ref([]); - const subApproveUser = ref(''); - const subApproveUserNames = ref(''); + const { usernames: subApproveUser, displayNames: subApproveUserNames, setDisplayNames } = useSubApproveUserResolver(); const isEnd = ref(0); const problemTreeData = ref([]); const loadingProblemOptions = ref(false); @@ -408,6 +409,22 @@ import { useSelectNameResolver } from '/@/composables/useSelectNameResolver'; processTableName: props.formData?.processTableName, })); + // ==================== 默认审批意见 ==================== + // 仅覆盖需要动态内容(人名)的节点,其余节点走后端节点配置 + const handleReasonTemplateMap: Record string> = { + // 责任部门领导接受任务并分配 + Task_1c64uvl: () => { + if (isEnd.value === 1) return ''; + return buildDeptLeaderAssignReason(normalizeDeptNames(subApproveUserNames.value)); + }, + }; + + const defaultHandleReason = computed(() => { + const builder = handleReasonTemplateMap[String(processInfo.value.taskDefKey || '')]; + return builder ? builder() : ''; + }); + + provide('formDefaultReason', defaultHandleReason); provide('extraVars', formScope); provide('flowVars', computed(() => props.formData?.vars || {})); @@ -613,7 +630,7 @@ import { useSelectNameResolver } from '/@/composables/useSelectNameResolver'; } function onSubApproveUserConfirm(userIds: string, realnames: string) { - subApproveUserNames.value = realnames || ''; + setDisplayNames(userIds, realnames); } async function saveSubApproveUserVariable(options: { showSuccessMessage?: boolean } = {}) {