yxk-20260611-自动生成审批意见
督办部门负责人审批节点自动生成审批意见
This commit is contained in:
@@ -71,12 +71,28 @@
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="责任部门" name="responDeptid">
|
||||
<j-select-dept v-model:value="mainForm.responDeptid" :disabled="mainDisabled" :multiple="true" checkStrictly allow-clear />
|
||||
<j-select-dept
|
||||
v-model:value="mainForm.responDeptid"
|
||||
:disabled="mainDisabled"
|
||||
:multiple="true"
|
||||
checkStrictly
|
||||
allow-clear
|
||||
@change="handleDeptChange('responDeptid', $event)"
|
||||
@select="handleDeptSelect('responDeptid', $event)"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="协办部门" name="assistDeptid">
|
||||
<j-select-dept v-model:value="mainForm.assistDeptid" :disabled="mainDisabled" :multiple="true" checkStrictly allow-clear />
|
||||
<j-select-dept
|
||||
v-model:value="mainForm.assistDeptid"
|
||||
:disabled="mainDisabled"
|
||||
:multiple="true"
|
||||
checkStrictly
|
||||
allow-clear
|
||||
@change="handleDeptChange('assistDeptid', $event)"
|
||||
@select="handleDeptSelect('assistDeptid', $event)"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
@@ -188,6 +204,7 @@
|
||||
:form-data="formData"
|
||||
:claim="claim"
|
||||
:beforeHandle="saveMainFormBeforeProcessHandle"
|
||||
:defaultReason="defaultHandleReason"
|
||||
@success="handleProcessSuccess"
|
||||
@claimSuccess="handleClaimSuccess"
|
||||
/>
|
||||
@@ -199,6 +216,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { queryDepartTreeSync } from '/@/api/common/api';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
@@ -241,6 +259,15 @@
|
||||
const showBaseInfoDetail = ref(false);
|
||||
const feedbackList = ref<any[]>([]);
|
||||
const feedbackAttachmentRefreshKey = ref(0);
|
||||
const deptNameText = reactive<Record<string, string>>({
|
||||
responDeptid: '',
|
||||
assistDeptid: '',
|
||||
});
|
||||
const deptOptionCache = reactive<Record<string, Record<string, string>>>({
|
||||
responDeptid: {},
|
||||
assistDeptid: {},
|
||||
});
|
||||
const deptResolveVersion = ref(0);
|
||||
const subApproveUser = ref('');
|
||||
const isEnd = ref(0);
|
||||
const lastGeneratedNumber = ref('');
|
||||
@@ -318,6 +345,13 @@
|
||||
processDataId: props.formData?.processDataId,
|
||||
processTableName: props.formData?.processTableName,
|
||||
}));
|
||||
const handleReasonTemplateMap: Record<string, () => string> = {
|
||||
Task_137y5vq: buildLeaderDeptReason,
|
||||
};
|
||||
const defaultHandleReason = computed(() => {
|
||||
const builder = handleReasonTemplateMap[String(processInfo.value.taskDefKey || '')];
|
||||
return builder ? builder() : '';
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initFormData();
|
||||
@@ -353,7 +387,14 @@
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = await defHttp.get({ url: queryByIdUrl, params: { id: dataId } });
|
||||
if (dataId !== props.formData?.dataId) {
|
||||
return;
|
||||
}
|
||||
setMainForm(data || {});
|
||||
await syncDeptNamesFromRecord(data || {});
|
||||
if (dataId !== props.formData?.dataId) {
|
||||
return;
|
||||
}
|
||||
await loadFeedbackList();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@@ -364,6 +405,126 @@
|
||||
Object.keys(mainForm).forEach((key) => {
|
||||
mainForm[key] = record[key] ?? '';
|
||||
});
|
||||
// 部门选择组件未展开时不会立刻回传 label,先使用详情接口的字典文本生成默认办理意见。
|
||||
deptNameText.responDeptid = normalizeDeptNames(record.responDeptid_dictText || record.responDeptname);
|
||||
deptNameText.assistDeptid = normalizeDeptNames(record.assistDeptid_dictText || record.assistDeptname);
|
||||
}
|
||||
|
||||
async function syncDeptNamesFromRecord(record: Record<string, any>) {
|
||||
const resolveVersion = ++deptResolveVersion.value;
|
||||
const [responDept, assistDept] = await Promise.all([
|
||||
resolveDeptNameText('responDeptid', record.responDeptid, record.responDeptid_dictText || record.responDeptname),
|
||||
resolveDeptNameText('assistDeptid', record.assistDeptid, record.assistDeptid_dictText || record.assistDeptname),
|
||||
]);
|
||||
if (resolveVersion !== deptResolveVersion.value) {
|
||||
return;
|
||||
}
|
||||
applyResolvedDeptName(responDept);
|
||||
applyResolvedDeptName(assistDept);
|
||||
}
|
||||
|
||||
async function resolveDeptNameText(field: 'responDeptid' | 'assistDeptid', ids: any, fallbackText: any) {
|
||||
const deptIds = normalizeDeptIds(ids);
|
||||
const fallbackNames = splitDeptNames(fallbackText);
|
||||
if (!deptIds.length) {
|
||||
return { field, cache: {}, nameText: '' };
|
||||
}
|
||||
|
||||
if (fallbackNames.length) {
|
||||
return { field, cache: buildDeptOptionCache(deptIds, fallbackNames), nameText: normalizeDeptNames(fallbackNames.join(',')) };
|
||||
}
|
||||
|
||||
try {
|
||||
const records = (await queryDepartTreeSync({ ids: deptIds.join(','), primaryKey: 'id' })) || [];
|
||||
const cache = records.reduce((cache: Record<string, string>, item: any) => {
|
||||
const id = String(item?.id || item?.value || item?.key || '').trim();
|
||||
const name = String(item?.departName || item?.title || item?.label || '').trim();
|
||||
if (id && name) {
|
||||
cache[id] = name;
|
||||
}
|
||||
return cache;
|
||||
}, {});
|
||||
const names = deptIds.map((id) => cache[id]).filter(Boolean);
|
||||
return { field, cache, nameText: normalizeDeptNames(names.join(',')) };
|
||||
} catch {
|
||||
return { field, cache: {}, nameText: '' };
|
||||
}
|
||||
}
|
||||
|
||||
function applyResolvedDeptName(result: { field: 'responDeptid' | 'assistDeptid'; cache: Record<string, string>; nameText: string }) {
|
||||
deptOptionCache[result.field] = result.cache;
|
||||
deptNameText[result.field] = result.nameText;
|
||||
}
|
||||
|
||||
function handleDeptSelect(field: 'responDeptid' | 'assistDeptid', options?: any[] | null) {
|
||||
const nextCache: Record<string, string> = {};
|
||||
if (Array.isArray(options)) {
|
||||
options.forEach((item) => {
|
||||
const value = String(item?.value || item?.id || item?.key || '').trim();
|
||||
const label = String(item?.label || item?.title || item?.departName || item?.text || '').trim();
|
||||
if (value && label) {
|
||||
nextCache[value] = label;
|
||||
}
|
||||
});
|
||||
}
|
||||
deptOptionCache[field] = nextCache;
|
||||
syncDeptNameText(field, mainForm[field]);
|
||||
}
|
||||
|
||||
function handleDeptChange(field: 'responDeptid' | 'assistDeptid', value: any) {
|
||||
syncDeptNameText(field, value);
|
||||
}
|
||||
|
||||
function buildLeaderDeptReason() {
|
||||
const responDeptName = normalizeDeptNames(deptNameText.responDeptid);
|
||||
if (!responDeptName) {
|
||||
return '';
|
||||
}
|
||||
const assistDeptName = normalizeDeptNames(deptNameText.assistDeptid);
|
||||
return assistDeptName ? `请${responDeptName}牵头办理,请${assistDeptName}协办;` : `请${responDeptName}牵头办理;`;
|
||||
}
|
||||
|
||||
function normalizeDeptNames(value: any) {
|
||||
return splitDeptNames(value).join('、');
|
||||
}
|
||||
|
||||
function splitDeptNames(value: any) {
|
||||
return String(value || '')
|
||||
.split(/[,,;;、]/)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function buildDeptOptionCache(ids: string[], names: string[]) {
|
||||
return ids.reduce((cache: Record<string, string>, id, index) => {
|
||||
const name = names[index];
|
||||
if (id && name) {
|
||||
cache[id] = name;
|
||||
}
|
||||
return cache;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function syncDeptNameText(field: 'responDeptid' | 'assistDeptid', value: any) {
|
||||
const ids = normalizeDeptIds(value);
|
||||
if (!ids.length) {
|
||||
deptNameText[field] = '';
|
||||
return;
|
||||
}
|
||||
const names = ids.map((id) => deptOptionCache[field][id]).filter(Boolean);
|
||||
if (names.length) {
|
||||
deptNameText[field] = normalizeDeptNames(names.join(','));
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeDeptIds(value: any) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) => String(item || '').trim()).filter(Boolean);
|
||||
}
|
||||
return String(value || '')
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function syncGeneratedNumber() {
|
||||
|
||||
+24
-1
@@ -108,7 +108,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, computed, toRaw, unref, watchEffect } from 'vue';
|
||||
import { ref, reactive, computed, toRaw, unref, watch, watchEffect } from 'vue';
|
||||
import { initDictOptions } from '/@/utils/dict';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { taskComplaint, taskComplete, beforeAddSignTask, afterAddSignTask, addMultiInstance} from "../task.handle.api";
|
||||
@@ -176,6 +176,10 @@
|
||||
beforeHandle: {
|
||||
type: Function,
|
||||
default: undefined,
|
||||
},
|
||||
defaultReason: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
},
|
||||
emits: ['success'],
|
||||
@@ -216,6 +220,7 @@
|
||||
ccUserRealNames: '',
|
||||
fileList: '',
|
||||
});
|
||||
const lastAutoReason = ref('');
|
||||
//审批人用户是否多选
|
||||
const multiSelectUser = computed(() => {
|
||||
return unref(selectUserType) == 'change-user' ? false : true;
|
||||
@@ -224,6 +229,24 @@
|
||||
watchEffect(() => {
|
||||
props.turnbackTaskId && (model.rejectModelNode = props.turnbackTaskId);
|
||||
});
|
||||
// 默认处理意见只在空值或仍为上一条自动意见时刷新,避免覆盖用户手动输入。
|
||||
watch(
|
||||
() => props.defaultReason,
|
||||
(value) => {
|
||||
const nextReason = value || '';
|
||||
const canApplyDefaultReason = !model.reason || model.reason === lastAutoReason.value;
|
||||
if (nextReason && canApplyDefaultReason) {
|
||||
model.reason = nextReason;
|
||||
lastAutoReason.value = nextReason;
|
||||
return;
|
||||
}
|
||||
if (!nextReason && model.reason === lastAutoReason.value) {
|
||||
model.reason = '';
|
||||
}
|
||||
lastAutoReason.value = nextReason;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
// 选择下一步操作人
|
||||
const checkedNext = ref(false);
|
||||
const nextPersonList = ref([]);
|
||||
|
||||
+5
@@ -20,6 +20,7 @@
|
||||
:allowCounterSignAddUser="allowCounterSignAddUser"
|
||||
:allowReject="allowReject"
|
||||
:beforeHandle="beforeHandle"
|
||||
:defaultReason="defaultReason"
|
||||
:currentTaskName="currentNode.taskName">
|
||||
</my-handle-content>
|
||||
|
||||
@@ -61,6 +62,10 @@
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
defaultReason: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
showSelnextUser: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
||||
Reference in New Issue
Block a user