yxk-20260611-我为四所把把脉模块自动生成审批意见
This commit is contained in:
@@ -44,7 +44,7 @@
|
|||||||
<!--插槽:table标题-->
|
<!--插槽:table标题-->
|
||||||
<template #tableTitle>
|
<template #tableTitle>
|
||||||
<a-button type="primary" v-auth="actionAuth.add" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
<a-button type="primary" v-auth="actionAuth.add" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||||
<!-- <a-button type="primary" v-auth="actionAuth.exportXls" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>-->
|
<a-button type="primary" v-auth="actionAuth.exportXls" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<!-- <j-upload-button type="primary" v-auth="actionAuth.importExcel" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>-->
|
<!-- <j-upload-button type="primary" v-auth="actionAuth.importExcel" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>-->
|
||||||
<!-- <a-dropdown v-if="selectedRowKeys.length > 0">-->
|
<!-- <a-dropdown v-if="selectedRowKeys.length > 0">-->
|
||||||
<!-- <template #overlay>-->
|
<!-- <template #overlay>-->
|
||||||
|
|||||||
@@ -496,7 +496,7 @@
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const assistDeptName = normalizeDeptNames(deptNameText.assistDeptid);
|
const assistDeptName = normalizeDeptNames(deptNameText.assistDeptid);
|
||||||
return assistDeptName ? `请${responDeptName}牵头办理,请${assistDeptName}协办;` : `请${responDeptName}牵头办理;`;
|
return assistDeptName ? `请${responDeptName}牵头办理,请${assistDeptName}协办;` : `请${responDeptName}牵头办理。`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDeptLeaderAssignReason() {
|
function buildDeptLeaderAssignReason() {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
<template #tableTitle>
|
<template #tableTitle>
|
||||||
<a-button type="primary" v-auth="'bqtakepulse:bg_takepulse:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
<a-button type="primary" v-auth="'bqtakepulse:bg_takepulse:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||||
<a-button type="primary" v-auth="'bqtakepulse:bg_takepulse:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'bqtakepulse:bg_takepulse:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'bqtakepulse:bg_takepulse:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<!-- <j-upload-button type="primary" v-auth="'bqtakepulse:bg_takepulse:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>-->
|
||||||
<!-- 高级查询 -->
|
<!-- 高级查询 -->
|
||||||
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
|
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -66,12 +66,28 @@
|
|||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="牵头部门" name="responDeptid">
|
<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-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-form-item label="协办部门" name="assistDeptid">
|
<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-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
@@ -207,6 +223,7 @@
|
|||||||
:form-data="formData"
|
:form-data="formData"
|
||||||
:claim="claim"
|
:claim="claim"
|
||||||
:beforeHandle="saveMainFormBeforeProcessHandle"
|
:beforeHandle="saveMainFormBeforeProcessHandle"
|
||||||
|
:defaultReason="defaultHandleReason"
|
||||||
@success="handleProcessSuccess"
|
@success="handleProcessSuccess"
|
||||||
@claimSuccess="handleClaimSuccess"
|
@claimSuccess="handleClaimSuccess"
|
||||||
/>
|
/>
|
||||||
@@ -218,6 +235,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||||
import { defHttp } from '/@/utils/http/axios';
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
|
import { getUserList, queryDepartTreeSync } from '/@/api/common/api';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
|
import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
|
||||||
import JSelectUser from '/@/components/Form/src/jeecg/components/JSelectUser.vue';
|
import JSelectUser from '/@/components/Form/src/jeecg/components/JSelectUser.vue';
|
||||||
@@ -259,7 +277,18 @@
|
|||||||
const showBaseInfoDetail = ref(false);
|
const showBaseInfoDetail = ref(false);
|
||||||
const feedbackList = ref<any[]>([]);
|
const feedbackList = ref<any[]>([]);
|
||||||
const feedbackAttachmentRefreshKey = ref(0);
|
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 subApproveUser = ref('');
|
||||||
|
const subApproveUserNameText = ref('');
|
||||||
|
const userResolveVersion = ref(0);
|
||||||
const isEnd = ref(0);
|
const isEnd = ref(0);
|
||||||
|
|
||||||
const mainForm = reactive<Record<string, any>>({
|
const mainForm = reactive<Record<string, any>>({
|
||||||
@@ -337,6 +366,18 @@
|
|||||||
processDataId: props.formData?.processDataId,
|
processDataId: props.formData?.processDataId,
|
||||||
processTableName: props.formData?.processTableName,
|
processTableName: props.formData?.processTableName,
|
||||||
}));
|
}));
|
||||||
|
const handleReasonTemplateMap: Record<string, () => string> = {
|
||||||
|
Task_137y5vq: buildLeaderDeptReason,
|
||||||
|
Task_0d4iflp: buildDeptLeaderAssignReason,
|
||||||
|
Task_01ynnpq: buildDeptHandlerFeedbackReason,
|
||||||
|
Task_1s7zk9h: buildDeptLeaderApproveReason,
|
||||||
|
Task_0mpxssh: buildSuperviseHandlerConfirmReason,
|
||||||
|
Task_1g8igx5: buildSuperviseHandlerArchiveReason,
|
||||||
|
};
|
||||||
|
const defaultHandleReason = computed(() => {
|
||||||
|
const builder = handleReasonTemplateMap[String(processInfo.value.taskDefKey || '')];
|
||||||
|
return builder ? builder() : '';
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initFormData();
|
initFormData();
|
||||||
@@ -352,6 +393,14 @@
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
subApproveUser,
|
||||||
|
(value) => {
|
||||||
|
resolveSubApproveUserName(value);
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
async function initFormData() {
|
async function initFormData() {
|
||||||
const dataId = props.formData?.dataId;
|
const dataId = props.formData?.dataId;
|
||||||
if (!dataId) {
|
if (!dataId) {
|
||||||
@@ -361,7 +410,14 @@
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const data = await defHttp.get({ url: queryByIdUrl, params: { id: dataId } });
|
const data = await defHttp.get({ url: queryByIdUrl, params: { id: dataId } });
|
||||||
|
if (dataId !== props.formData?.dataId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setMainForm(data || {});
|
setMainForm(data || {});
|
||||||
|
await syncDeptNamesFromRecord(data || {});
|
||||||
|
if (dataId !== props.formData?.dataId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await loadFeedbackList();
|
await loadFeedbackList();
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@@ -372,6 +428,196 @@
|
|||||||
Object.keys(mainForm).forEach((key) => {
|
Object.keys(mainForm).forEach((key) => {
|
||||||
mainForm[key] = record[key] ?? '';
|
mainForm[key] = record[key] ?? '';
|
||||||
});
|
});
|
||||||
|
// 基础信息默认折叠时部门组件不会挂载,先使用详情里的字典文本生成默认办理意见。
|
||||||
|
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);
|
||||||
|
const implementDeptName = normalizeDeptNames(mainForm.implementDeptid);
|
||||||
|
const reasonParts = [`请${responDeptName}牵头办理`];
|
||||||
|
if (assistDeptName) {
|
||||||
|
reasonParts.push(`请${assistDeptName}协办`);
|
||||||
|
}
|
||||||
|
if (implementDeptName) {
|
||||||
|
reasonParts.push(`请${implementDeptName}落实`);
|
||||||
|
}
|
||||||
|
return `${reasonParts.join(',')}。`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDeptLeaderAssignReason() {
|
||||||
|
if (String(isEnd.value) === '1') {
|
||||||
|
return '已反馈完成情况,请确认。';
|
||||||
|
}
|
||||||
|
const userNameText = normalizeDeptNames(subApproveUserNameText.value || subApproveUser.value);
|
||||||
|
return userNameText ? `请${userNameText}办理。` : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDeptHandlerFeedbackReason() {
|
||||||
|
return '已完成反馈,请领导审批。';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDeptLeaderApproveReason() {
|
||||||
|
return '已审批,请督办部门确认。';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSuperviseHandlerConfirmReason() {
|
||||||
|
return '已确认。';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSuperviseHandlerArchiveReason() {
|
||||||
|
return '已归档确认。';
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveSubApproveUserName(value: any) {
|
||||||
|
const resolveVersion = ++userResolveVersion.value;
|
||||||
|
const usernames = normalizeUsernameList(value);
|
||||||
|
if (!usernames) {
|
||||||
|
subApproveUserNameText.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSelectUser 的 v-model 存 username,默认办理意见尽量展示真实姓名。
|
||||||
|
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<string, string>, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadFeedbackList() {
|
async function loadFeedbackList() {
|
||||||
|
|||||||
Reference in New Issue
Block a user