✨ 列表导出补齐创建人创建时间,并修复组织类型提交

多模块列表与导出展示创建人、创建时间;组织类型强制提交数字编码,避免中文 dictKey 反序列化失败。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-30 14:22:39 +08:00
parent e5a7ad616c
commit 50c1afe9c8
87 changed files with 521 additions and 212 deletions
+69 -13
View File
@@ -34,7 +34,7 @@
type="primary"
plain
:loading="oaSyncLoading"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
@click="handleOaOrgSync"
>自动同步组织
</el-button>
@@ -43,7 +43,7 @@
<el-link
type="primary"
@click.stop="handleAdd(scope.row, scope.index)"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
>新增子项
</el-link>
</template>
@@ -365,6 +365,7 @@ export default {
label: '组织类型',
type: 'select',
dicData: [],
dataType: 'number',
minWidth: 120,
order: 90,
prop: 'deptCategory',
@@ -509,7 +510,7 @@ export default {
this.loadOrganizationTypeOptions();
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
permissionList() {
return {
addBtn: this.validData(this.permission.dept_add, false),
@@ -753,6 +754,9 @@ export default {
.map(item => this.normalizeOrganizationTypeOption(item))
.filter(Boolean);
this.resetDeptCategoryOptions();
if (list.length && !this.organizationTypeOptions.length) {
this.$message.warning('组织类型字典 dictKey 须为数字 1~6,当前无法解析,请检查业务字典配置');
}
// 字典异步返回后触发表格组织类型标签重绘
if (Array.isArray(this.data) && this.data.length) {
this.data = [...this.data];
@@ -760,24 +764,68 @@ export default {
});
},
/**
* 业务字典项转下拉选项:dictKey 为纯数字时转 number(兼容历史 deptCategory 1~6),否则保留原值。
* 业务字典项转下拉选项。后端 deptCategory 为 Integer,value 必须始终为数字。
* dictKey 为纯数字时直接使用;若配成中文则回退用 sort(1~6)作为层级码。
*/
normalizeOrganizationTypeOption(item) {
const label = item?.dictValue ?? item?.label;
const rawKey = item?.dictKey ?? item?.value;
if (label === undefined || label === null || String(label).trim() === '') {
return null;
}
if (rawKey === undefined || rawKey === null || String(rawKey).trim() === '') {
const rawKey = item?.dictKey ?? item?.value;
const keyText = rawKey === undefined || rawKey === null ? '' : String(rawKey).trim();
const keyNumber = Number(keyText);
const isPureNumber = keyText !== '' && !Number.isNaN(keyNumber) && String(keyNumber) === keyText;
if (isPureNumber) {
return {
label: String(label),
value: keyNumber,
};
}
// 兼容 dictKey 误配成中文:用排序号作为 1~6 层级码,保证下拉有数据且可提交 Integer
const sortNumber = Number(item?.sort);
if (!Number.isNaN(sortNumber) && sortNumber >= 1 && sortNumber <= 6) {
return {
label: String(label),
value: sortNumber,
};
}
return null;
},
/**
* 提交前将组织类型规范为 Integer;空状态字段去掉,避免 "" 反序列化失败。
*/
prepareDeptSubmitRow(row) {
const category = this.resolveDeptCategoryValue(row.deptCategory);
if (category === null) {
return false;
}
row.deptCategory = category;
if (row.status === '' || row.status === null || row.status === undefined) {
delete row.status;
} else {
row.status = Number(row.status);
}
return true;
},
resolveDeptCategoryValue(value) {
if (value === null || value === undefined || value === '') {
this.$message.warning('请选择组织类型');
return null;
}
const keyText = String(rawKey).trim();
const asNumber = Number(keyText);
const isPureNumber = keyText !== '' && !Number.isNaN(asNumber) && String(asNumber) === keyText;
return {
label: String(label),
value: isPureNumber ? asNumber : keyText,
};
const asNumber = Number(value);
if (!Number.isNaN(asNumber) && String(asNumber) === String(value).trim()) {
return asNumber;
}
// 容错:表单里残留了中文标签时,按字典项 label 反查数字编码
const matched = this.organizationTypeOptions.find(
item => String(item.label) === String(value) || this.isSameDeptCategory(item.value, value)
);
if (matched && typeof matched.value === 'number' && !Number.isNaN(matched.value)) {
return matched.value;
}
this.$message.warning('组织类型无效,请重新选择(字典键须为数字 1~6)');
return null;
},
resetDeptCategoryOptions() {
const categoryColumn = this.findColumn(this.option.column, 'deptCategory');
@@ -952,6 +1000,10 @@ export default {
row.kingdeeDeptCode = String(row.kingdeeDeptCode || '').trim();
row.leaderId = func.join(row.leaderId);
this.normalizeTopParent(row);
if (!this.prepareDeptSubmitRow(row)) {
loading();
return;
}
if (this.isCarrierDeptCategory(row.deptCategory) && !row.carrierCustomerId) {
this.$message.warning('请选择承运商');
loading();
@@ -983,6 +1035,10 @@ export default {
row.kingdeeDeptCode = String(row.kingdeeDeptCode || '').trim();
row.leaderId = func.join(row.leaderId);
this.normalizeTopParent(row);
if (!this.prepareDeptSubmitRow(row)) {
loading();
return;
}
if (this.isCarrierDeptCategory(row.deptCategory) && !row.carrierCustomerId) {
this.$message.warning('请选择承运商');
loading();
+3 -3
View File
@@ -35,7 +35,7 @@
<el-link
type="primary"
@click.stop="handleRowClick(scope.row)"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
>字典配置
</el-link>
</template>
@@ -81,7 +81,7 @@
<el-link
type="primary"
@click.stop="handleAdd(scope.row, scope.index)"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
>新增子项
</el-link>
</template>
@@ -137,7 +137,7 @@ export default {
};
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
permissionList() {
return {
addBtn: this.validData(this.permission.dict_add, false),
+3 -3
View File
@@ -35,7 +35,7 @@
<el-link
type="primary"
@click.stop="handleRowClick(scope.row)"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
>字典配置
</el-link>
</template>
@@ -81,7 +81,7 @@
<el-link
type="primary"
@click.stop="handleAdd(scope.row, scope.index)"
v-if="userInfo.authority.includes('admin')"
v-if="isAdministrator"
>新增子项
</el-link>
</template>
@@ -137,7 +137,7 @@ export default {
};
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
permissionList() {
return {
addBtn: this.validData(this.permission.dictbiz_add, false),
+2 -2
View File
@@ -35,7 +35,7 @@
<el-link
type="primary"
@click.stop="handleAdd(scope.row, scope.index)"
v-if="userInfo.authority.includes('admin') && scope.row.category === 1"
v-if="isAdministrator && scope.row.category === 1"
>新增子项
</el-link>
</template>
@@ -280,7 +280,7 @@ export default {
},
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
permissionList() {
return {
addBtn: this.validData(this.permission.menu_add, false),
+10 -10
View File
@@ -40,7 +40,7 @@
type="primary"
plain
icon="el-icon-refresh"
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
@click="handleRecycle"
>回收站
</el-button>
@@ -48,7 +48,7 @@
type="success"
plain
icon="el-icon-check"
v-if="userInfo.authority.includes('administrator') && recycleMode"
v-if="isAdministrator && recycleMode"
@click="handleRecyclePass"
>恢 复
</el-button>
@@ -56,7 +56,7 @@
type="danger"
plain
icon="el-icon-close"
v-if="userInfo.authority.includes('administrator') && recycleMode"
v-if="isAdministrator && recycleMode"
@click="handleRecycleRemove"
>删除
</el-button>
@@ -64,7 +64,7 @@
type="primary"
plain
icon="el-icon-refresh-left"
v-if="userInfo.authority.includes('administrator') && recycleMode"
v-if="isAdministrator && recycleMode"
@click="handleRecycleBack"
>返 回
</el-button>
@@ -77,7 +77,7 @@
<el-button
plain
type="info"
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
icon="el-icon-setting"
@click="handleSetting"
>批量授权配置
@@ -93,7 +93,7 @@
>
<el-button
plain
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
icon="el-icon-message-box"
@click="handleDatasourceSetting"
>数据源管理
@@ -107,7 +107,7 @@
>
<el-button
plain
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
icon="el-icon-set-up"
@click="handlePackageSetting"
>产品包管理
@@ -116,13 +116,13 @@
</template>
<template #menu="scope">
<el-link
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
type="primary"
@click.stop="handleRowDatasource(scope.row)"
>数据源
</el-link>
<el-link
v-if="userInfo.authority.includes('administrator') && !recycleMode"
v-if="isAdministrator && !recycleMode"
type="primary"
@click.stop="handleRowPackage(scope.row)"
>产品包
@@ -436,7 +436,7 @@ export default {
},
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
permissionList() {
return {
addBtn: this.validData(this.permission.tenant_add, false),
+12 -12
View File
@@ -52,7 +52,7 @@
type="primary"
plain
icon="el-icon-operation"
v-if="userInfo.authority.includes('admin') && !auditMode"
v-if="isAdministrator && !auditMode"
@click="handleAudit"
>审 核
</el-button>
@@ -60,7 +60,7 @@
type="primary"
plain
:loading="iamSyncLoading"
v-if="userInfo.authority.includes('admin') && !auditMode"
v-if="isAdministrator && !auditMode"
@click="handleIamSync"
>同步人员
</el-button>
@@ -68,7 +68,7 @@
type="success"
plain
icon="el-icon-check"
v-if="userInfo.authority.includes('admin') && auditMode"
v-if="isAdministrator && auditMode"
@click="handleAuditPass"
>通 过
</el-button>
@@ -76,7 +76,7 @@
type="danger"
plain
icon="el-icon-close"
v-if="userInfo.authority.includes('admin') && auditMode"
v-if="isAdministrator && auditMode"
@click="handleAuditRefuse"
>拒 绝
</el-button>
@@ -84,7 +84,7 @@
type="primary"
plain
icon="el-icon-refresh-left"
v-if="userInfo.authority.includes('admin') && auditMode"
v-if="isAdministrator && auditMode"
@click="handleAuditBack"
>返 回
</el-button>
@@ -97,7 +97,7 @@
>角色配置
</el-button>
<el-dropdown
v-if="userInfo.authority.includes('admin') && !auditMode"
v-if="isAdministrator && !auditMode"
@command="handleDataManageCommand"
style="margin-left: 10px"
>
@@ -120,13 +120,13 @@
</template>
<template #menu-right>
<el-button
v-if="userInfo.authority.includes('admin') && !auditMode"
v-if="isAdministrator && !auditMode"
icon="el-icon-document"
@click="$refs.authLog.openAuthLog()"
>认证日志
</el-button>
<el-button
v-if="userInfo.authority.includes('admin') && !auditMode"
v-if="isAdministrator && !auditMode"
icon="el-icon-lock"
@click="$refs.authLock.openLockLog()"
>锁定管理
@@ -149,16 +149,16 @@
<el-link type="primary">更多 </el-link>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="setLeader" v-if="userInfo.authority.includes('admin')">
<el-dropdown-item command="setLeader" v-if="isAdministrator">
{{ row.isLeader === 1 ? '取消主管' : '设置主管' }}
</el-dropdown-item>
<el-dropdown-item command="grantRole" v-if="permission.user_role">
角色配置
</el-dropdown-item>
<el-dropdown-item command="authLog" v-if="userInfo.authority.includes('admin')">
<el-dropdown-item command="authLog" v-if="isAdministrator">
认证日志
</el-dropdown-item>
<el-dropdown-item command="lockUser" v-if="userInfo.authority.includes('admin')">
<el-dropdown-item command="lockUser" v-if="isAdministrator">
锁定账号
</el-dropdown-item>
<el-dropdown-item command="resetPassword" v-if="permission.user_reset">
@@ -568,7 +568,7 @@ export default {
},
},
computed: {
...mapGetters(['userInfo', 'permission']),
...mapGetters(['userInfo', 'permission', 'isAdministrator']),
oaSyncDialogTitle() {
if (this.oaSyncStatus === 'done') {
return '同步完成';