✨ 新增业务部门配置页并简化项目/合同部门选择

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-02 21:10:47 +08:00
parent 8e1430491b
commit 8388a55481
7 changed files with 1145 additions and 372 deletions
+407
View File
@@ -0,0 +1,407 @@
<template>
<basic-container class="business-dept-config-page">
<avue-crud
ref="crud"
v-model="form"
v-model:page="page"
:option="option"
:data="data"
:table-loading="loading"
:permission="permissionList"
:before-open="beforeOpen"
@row-save="rowSave"
@row-update="rowUpdate"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad"
>
<template #menu="{ row, index }">
<el-link
v-if="permission.business_dept_config_edit"
type="primary"
@click="$refs.crud.rowEdit(row, index)"
>
编辑
</el-link>
<el-link
v-if="permission.business_dept_config_delete"
type="danger"
@click="rowDel(row)"
>
删除
</el-link>
</template>
<template #initialSerial="{ row }">
{{ formatSerial(row.initialSerial) }}
</template>
<template #platformCompanyId-form>
<el-select
v-model="form.platformCompanyId"
filterable
clearable
placeholder="请选择平台公司"
style="width: 100%"
@change="handlePlatformCompanyChange"
>
<el-option
v-for="item in platformCompanyOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<template #businessDeptId-form>
<el-select
v-model="form.businessDeptId"
filterable
clearable
placeholder="请选择业务部门"
style="width: 100%"
@change="handleBusinessDeptChange"
>
<el-option
v-for="item in businessDeptOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<template #kingdeeCompanyCode-form>
<el-input
v-model="form.kingdeeCompanyCode"
disabled
placeholder="关联组织中配置的平台公司金蝶代码"
/>
</template>
</avue-crud>
</basic-container>
</template>
<script>
import { getList, getDetail, submit, remove } from '@/api/system/business-dept-config';
import { getBusinessDeptSelect, getPlatformCompanySelect } from '@/api/system/dept';
import { mapGetters } from 'vuex';
export default {
data() {
return {
form: {},
data: [],
loading: true,
query: {},
page: {
pageSize: 10,
pageSizes: [10, 30, 50, 100, 200],
currentPage: 1,
total: 0,
},
platformCompanyOptions: [],
businessDeptOptions: [],
option: {
height: 'auto',
calcHeight: 32,
tip: false,
border: true,
stripe: true,
index: true,
indexLabel: '序号',
indexWidth: 70,
selection: false,
addBtn: true,
editBtn: false,
delBtn: false,
viewBtn: false,
menuWidth: 140,
dialogWidth: 900,
dialogClickModal: false,
labelPosition: 'right',
labelWidth: 'auto',
searchShow: true,
searchIcon: true,
searchIndex: 4,
searchMenuSpan: 24,
searchMenuPosition: 'right',
column: [
{
label: '业务部门',
prop: 'businessDeptId',
type: 'select',
filterable: true,
search: true,
searchOrder: 2,
searchFilterable: true,
minWidth: 160,
span: 12,
formslot: true,
hide: true,
props: { label: 'label', value: 'value' },
dicData: [],
rules: [{ required: true, message: '请选择业务部门', trigger: 'change' }],
},
{
label: '业务部门',
prop: 'businessDeptName',
minWidth: 160,
display: false,
},
{
label: '平台公司',
prop: 'platformCompanyId',
type: 'select',
filterable: true,
search: true,
searchOrder: 1,
searchFilterable: true,
minWidth: 220,
span: 12,
formslot: true,
hide: true,
props: { label: 'label', value: 'value' },
dicData: [],
rules: [{ required: true, message: '请选择平台公司', trigger: 'change' }],
},
{
label: '平台公司',
prop: 'platformCompanyName',
minWidth: 220,
display: false,
},
{
label: '合同编码前缀',
prop: 'contractCodePrefix',
minWidth: 140,
span: 12,
maxlength: 64,
rules: [{ required: true, message: '请输入合同编码前缀', trigger: 'blur' }],
},
{
label: '金蝶公司代码',
prop: 'kingdeeCompanyCode',
minWidth: 140,
span: 12,
formslot: true,
addDisplay: true,
editDisplay: true,
hide: true,
},
{
label: '初始流水号',
prop: 'initialSerial',
type: 'number',
minWidth: 120,
span: 12,
minRows: 1,
maxRows: 999,
controls: false,
slot: true,
placeholder: '如果系统已有相同流水号,则跳过这个流水号',
},
{
label: '金蝶部门代码',
prop: 'kingdeeDeptCode',
minWidth: 140,
span: 12,
maxlength: 64,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minWidth: 160,
span: 24,
maxlength: 200,
showWordLimit: true,
hide: true,
overHidden: true,
},
{
label: '创建时间',
prop: 'createTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
addDisplay: false,
editDisplay: false,
viewDisplay: false,
hide: true,
},
{
label: '更新人',
prop: 'updateUserName',
addDisplay: false,
editDisplay: false,
viewDisplay: false,
hide: true,
},
],
},
};
},
computed: {
...mapGetters(['permission']),
permissionList() {
return {
addBtn: this.validData(this.permission.business_dept_config_add, false),
editBtn: false,
delBtn: false,
};
},
},
created() {
this.loadSelectOptions();
},
methods: {
loadSelectOptions() {
Promise.all([getPlatformCompanySelect(), getBusinessDeptSelect()]).then(
([platformRes, businessRes]) => {
this.platformCompanyOptions = this.normalizeDeptOptions(platformRes?.data?.data);
this.businessDeptOptions = this.normalizeDeptOptions(businessRes?.data?.data);
const platformColumn = this.findColumn(this.option.column, 'platformCompanyId');
if (platformColumn) platformColumn.dicData = this.platformCompanyOptions;
const businessColumn = this.findColumn(this.option.column, 'businessDeptId');
if (businessColumn) businessColumn.dicData = this.businessDeptOptions;
}
);
},
normalizeDeptOptions(list) {
return (list || []).map(item => ({
label: item.deptName || item.fullName || String(item.id),
value: String(item.id),
kingdeeDeptCode: item.kingdeeDeptCode || '',
}));
},
formatSerial(value) {
if (value === null || value === undefined || value === '') return '-';
const number = Number(value);
if (!Number.isInteger(number) || number < 1) return String(value);
return String(number).padStart(3, '0');
},
handlePlatformCompanyChange(value) {
const matched = this.platformCompanyOptions.find(item => String(item.value) === String(value));
this.form.platformCompanyName = matched ? matched.label : '';
this.form.kingdeeCompanyCode = matched ? matched.kingdeeDeptCode || '' : '';
},
handleBusinessDeptChange(value) {
const matched = this.businessDeptOptions.find(item => String(item.value) === String(value));
this.form.businessDeptName = matched ? matched.label : '';
},
beforeOpen(done, type) {
this.loadSelectOptions();
if (['edit', 'view'].includes(type) && this.form.id) {
getDetail(this.form.id).then(res => {
const detail = res.data?.data || {};
this.form = {
...detail,
platformCompanyId: detail.platformCompanyId ? String(detail.platformCompanyId) : '',
businessDeptId: detail.businessDeptId ? String(detail.businessDeptId) : '',
};
done();
});
return;
}
if (type === 'add') {
this.form = {
platformCompanyId: '',
platformCompanyName: '',
businessDeptId: '',
businessDeptName: '',
contractCodePrefix: '',
initialSerial: undefined,
kingdeeCompanyCode: '',
kingdeeDeptCode: '',
remark: '',
};
}
done();
},
normalizeSubmitRow(row) {
const initialSerial =
row.initialSerial === '' || row.initialSerial === undefined || row.initialSerial === null
? null
: Number(row.initialSerial);
return {
...row,
platformCompanyId: row.platformCompanyId || null,
businessDeptId: row.businessDeptId || null,
contractCodePrefix: String(row.contractCodePrefix || '').trim(),
kingdeeDeptCode: String(row.kingdeeDeptCode || '').trim(),
remark: String(row.remark || '').trim(),
initialSerial: Number.isFinite(initialSerial) ? initialSerial : null,
};
},
rowSave(row, done, loading) {
submit(this.normalizeSubmitRow(row)).then(
() => {
this.$message.success('新增成功');
done();
this.onLoad(this.page);
},
() => loading()
);
},
rowUpdate(row, index, done, loading) {
submit(this.normalizeSubmitRow(row)).then(
() => {
this.$message.success('修改成功');
done();
this.onLoad(this.page);
},
() => loading()
);
},
rowDel(row) {
this.$confirm('确定删除该业务部门配置?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => remove(row.id))
.then(() => {
this.$message.success('删除成功');
this.onLoad(this.page);
})
.catch(() => {});
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
searchReset() {
this.query = {};
this.onLoad(this.page);
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
refreshChange() {
this.onLoad(this.page, this.query);
},
onLoad(page, params = {}) {
this.loading = true;
const query = {
...this.query,
...params,
};
getList(page.currentPage, page.pageSize, query)
.then(res => {
const result = res.data?.data || {};
this.page.total = result.total || 0;
this.data = result.records || [];
})
.finally(() => {
this.loading = false;
});
},
},
};
</script>
+61 -123
View File
@@ -303,7 +303,7 @@ export default {
headerAlign: 'left',
order: 80,
search: true,
searchOrder: 2,
searchOrder: 3,
rules: [
{
required: true,
@@ -366,105 +366,13 @@ export default {
},
],
},
{
label: '金蝶部门代码',
prop: 'kingdeeDeptCode',
minWidth: 140,
order: 65,
maxlength: 64,
showWordLimit: true,
rules: [
{
validator: (rule, value, callback) => {
const code = String(value || '').trim();
if (!code) {
callback();
return;
}
if (code.length > 64) {
callback(new Error('金蝶部门代码不能超过64个字符'));
return;
}
callback();
},
trigger: 'blur',
},
],
},
{
label: '合同编码前缀',
prop: 'contractCodePrefix',
minWidth: 160,
order: 62,
maxlength: 64,
showWordLimit: true,
placeholder: '如 GWZH成都',
tip: '合同编号规则:前缀(年份)三位流水号,流水按本部门独立编号',
rules: [
{
validator: (rule, value, callback) => {
const prefix = String(value || '').trim();
if (!prefix) {
callback();
return;
}
if (prefix.length > 64) {
callback(new Error('合同编码前缀不能超过64个字符'));
return;
}
callback();
},
trigger: 'blur',
},
],
},
{
label: '合同初始流水号',
prop: 'contractInitialSerial',
type: 'input',
minWidth: 140,
order: 61,
placeholder: '如 1',
// -1 为空占位,列表展示为空
formatter: row =>
Number(row.contractInitialSerial) === -1 ? '' : row.contractInitialSerial,
tip: '该部门当年首个合同时从此流水号起编,后续递增;范围1-999,不填默认从1开始',
rules: [
{
validator: (rule, value, callback) => {
// -1 为空占位,不填时按空处理
if (
value === undefined ||
value === null ||
value === '' ||
Number(value) === -1
) {
callback();
return;
}
const text = String(value).trim();
if (!/^\d+$/.test(text)) {
callback(new Error('合同初始流水号只能输入正整数'));
return;
}
const serial = Number(text);
if (serial < 1 || serial > 999) {
callback(new Error('合同初始流水号范围为1到999'));
return;
}
callback();
},
trigger: 'blur',
},
],
},
{
label: '组织简称',
prop: 'shortName',
minWidth: 140,
order: 60,
search: true,
searchOrder: 1,
searchOrder: 4,
},
{
label: '助记码',
@@ -525,8 +433,12 @@ export default {
dataType: 'number',
value: 0,
width: 120,
order: 35,
order: 36,
search: true,
searchOrder: 2,
searchPlaceholder: '请选择是否平台公司',
formatter: row => (Number(row.isPlatformCompany) === 1 ? '是' : '否'),
change: ({ value }) => this.handlePlatformCompanyChange(value),
rules: [
{
required: true,
@@ -535,6 +447,37 @@ export default {
},
],
},
{
label: '金蝶部门代码',
prop: 'kingdeeDeptCode',
minWidth: 140,
order: 35,
maxlength: 64,
showWordLimit: true,
// 仅平台公司维护/展示金蝶组织代码;非平台公司列表留空
addDisplay: false,
editDisplay: false,
viewDisplay: false,
formatter: row =>
Number(row.isPlatformCompany) === 1 ? String(row.kingdeeDeptCode || '').trim() : '',
rules: [
{
validator: (rule, value, callback) => {
const code = String(value || '').trim();
if (!code) {
callback();
return;
}
if (code.length > 64) {
callback(new Error('金蝶部门代码不能超过64个字符'));
return;
}
callback();
},
trigger: 'blur',
},
],
},
{
label: '是否业务部门',
prop: 'isBusinessDept',
@@ -547,6 +490,9 @@ export default {
value: 0,
width: 120,
order: 34,
search: true,
searchOrder: 1,
searchPlaceholder: '请选择是否业务部门',
formatter: row => (Number(row.isBusinessDept) === 1 ? '是' : '否'),
rules: [
{
@@ -1217,28 +1163,20 @@ export default {
row.parentId = 0;
}
},
normalizeContractInitialSerial(value) {
// -1 为空占位,不填时不落库、不回显
if (
value === undefined ||
value === null ||
value === '' ||
Number(value) === -1
) {
return null;
handlePlatformCompanyChange(value) {
const isPlatform = Number(value) === 1;
this.syncKingdeeDeptCodeDisplay(isPlatform);
if (!isPlatform && this.form) {
this.form.kingdeeDeptCode = '';
}
const text = String(value).trim();
if (!text) {
return null;
}
const serial = Number(text);
return Number.isInteger(serial) ? serial : value;
},
clearEmptyContractInitialSerial(form = this.form) {
if (!form) return;
if (Number(form.contractInitialSerial) === -1) {
form.contractInitialSerial = '';
}
syncKingdeeDeptCodeDisplay(isPlatformCompany) {
const column = this.findColumn(this.option.column, 'kingdeeDeptCode');
if (!column) return;
const visible = Number(isPlatformCompany) === 1;
column.addDisplay = visible;
column.editDisplay = visible;
column.viewDisplay = visible;
},
isRootDept(row) {
return row && (row.parentId === 0 || String(row.parentId) === '0');
@@ -1384,9 +1322,9 @@ export default {
rowSave(row, done, loading) {
row.tenantId = row.tenantId || this.userInfo.tenantId || website.tenantId;
row.deptCode = String(row.deptCode || '').trim();
row.kingdeeDeptCode = String(row.kingdeeDeptCode || '').trim();
row.contractCodePrefix = String(row.contractCodePrefix || '').trim();
row.contractInitialSerial = this.normalizeContractInitialSerial(row.contractInitialSerial);
// 合同前缀/流水已迁至业务部门配置;组织管理仅维护平台公司金蝶代码
row.kingdeeDeptCode =
Number(row.isPlatformCompany) === 1 ? String(row.kingdeeDeptCode || '').trim() : '';
row.leaderId = func.join(row.leaderId);
this.normalizeTopParent(row);
if (!this.prepareDeptSubmitRow(row)) {
@@ -1432,9 +1370,9 @@ export default {
rowUpdate(row, index, done, loading) {
row.tenantId = row.tenantId || this.userInfo.tenantId || website.tenantId;
row.deptCode = String(row.deptCode || '').trim();
row.kingdeeDeptCode = String(row.kingdeeDeptCode || '').trim();
row.contractCodePrefix = String(row.contractCodePrefix || '').trim();
row.contractInitialSerial = this.normalizeContractInitialSerial(row.contractInitialSerial);
// 合同前缀/流水已迁至业务部门配置;组织管理仅维护平台公司金蝶代码
row.kingdeeDeptCode =
Number(row.isPlatformCompany) === 1 ? String(row.kingdeeDeptCode || '').trim() : '';
row.leaderId = func.join(row.leaderId);
this.normalizeTopParent(row);
if (!this.prepareDeptSubmitRow(row)) {
@@ -1547,7 +1485,7 @@ export default {
if (this.form.isBusinessDept === undefined || this.form.isBusinessDept === null) {
this.form.isBusinessDept = 0;
}
this.clearEmptyContractInitialSerial(this.form);
this.syncKingdeeDeptCodeDisplay(this.form.isPlatformCompany);
this.initData(this.form.tenantId);
this.loadParentDeptCode(this.form.parentId);
}
@@ -1562,7 +1500,7 @@ export default {
if (this.form.parentId === '0') {
this.form.parentId = '';
}
this.clearEmptyContractInitialSerial(this.form);
this.syncKingdeeDeptCodeDisplay(this.form.isPlatformCompany);
this.loadParentDeptCode(this.form.parentId);
if (this.form.hasOwnProperty('leaderId')) {
const splitResult = func.split(this.form.leaderId);