feat(product): 新增产品管理模块与字典组件功能
- 新增产品管理相关路由和页面(dashboard、list、requirement、setting) - 实现产品基础信息编辑弹窗组件(base-info-dialog.vue) - 添加运行时字典功能(dict-select、dict-text、dict-tag组件) - 集成字典管理store和API调用 - 规范ID类型定义为string避免精度丢失问题 - 完善国际化资源文件支持中英文对照 - 新增对象上下文业务域入口页导航实现说明 - 添加Vue DevTools浮动入口注释说明 - 统一权限控制支持全局和对象作用域区分 - 规范分页查询参数类型定义与使用方式
This commit is contained in:
@@ -54,10 +54,6 @@ const { fromUserIndex = false, deptId = 100, orgType = 'company' } = defineProps
|
||||
*
|
||||
* @param data 节点数据
|
||||
*/
|
||||
function isRootNode(data: Api.SystemManage.UserManagementRelationTreeRespVO): boolean {
|
||||
return treeData.value.some(node => node.userId === data.userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断母节点的编辑按钮是否应该隐藏
|
||||
*
|
||||
@@ -89,11 +85,15 @@ const userList = ref<Api.SystemManage.UserSimple[]>([]);
|
||||
const relationTreeRef = ref<InstanceType<typeof ElTree>>();
|
||||
|
||||
// 已选中的节点 ID 列表
|
||||
const checkedNodeKeys = ref<number[]>([]);
|
||||
const checkedNodeKeys = ref<string[]>([]);
|
||||
|
||||
// 树形数据
|
||||
const treeData = ref<Api.SystemManage.UserManagementRelationTreeRespVO[]>([]);
|
||||
|
||||
function isRootNode(data: Api.SystemManage.UserManagementRelationTreeRespVO): boolean {
|
||||
return treeData.value.some(node => node.userId === data.userId);
|
||||
}
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
|
||||
@@ -225,7 +225,8 @@ function openAdd(item?: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
operateType.value = 'add';
|
||||
// 如果是从某一行的新增按钮触发,则默认管理者为当前节点用户
|
||||
// 否则默认管理者为当前登录用户(在对话框组件中处理)
|
||||
editingData.value = item ? {
|
||||
editingData.value = item
|
||||
? {
|
||||
id: null,
|
||||
managerUserId: item.userId,
|
||||
subordinateUserId: null,
|
||||
@@ -233,7 +234,8 @@ function openAdd(item?: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
effectiveUntil: null,
|
||||
remark: null,
|
||||
createTime: Date.now()
|
||||
} : null;
|
||||
}
|
||||
: null;
|
||||
openOperateModal();
|
||||
}
|
||||
|
||||
@@ -245,7 +247,8 @@ function openAdd(item?: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
function openEdit(item: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
operateType.value = 'edit';
|
||||
// 构建树节点数据为编辑所需格式
|
||||
editingData.value = item.id ? {
|
||||
editingData.value = item.id
|
||||
? {
|
||||
id: item.id,
|
||||
managerUserId: item.managerUserId,
|
||||
subordinateUserId: item.userId,
|
||||
@@ -253,7 +256,8 @@ function openEdit(item: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
effectiveUntil: null,
|
||||
remark: null,
|
||||
createTime: Date.now()
|
||||
} : null;
|
||||
}
|
||||
: null;
|
||||
openOperateModal();
|
||||
}
|
||||
|
||||
@@ -300,7 +304,9 @@ async function handleBatchDelete() {
|
||||
* @param checkedInfo 包含 checkedKeys 和 halfCheckedKeys 的对象
|
||||
*/
|
||||
function handleNodeCheck(checkedData: any, checkedInfo: any) {
|
||||
checkedNodeKeys.value = checkedInfo.checkedNodes.map((node: any) => node.id);
|
||||
checkedNodeKeys.value = checkedInfo.checkedNodes
|
||||
.map((node: any) => node.id)
|
||||
.filter((id: string | null): id is string => Boolean(id));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,7 +314,7 @@ function handleNodeCheck(checkedData: any, checkedInfo: any) {
|
||||
*
|
||||
* @param relationId 提交后的关系 ID
|
||||
*/
|
||||
function handleSubmitted(relationId: number) {
|
||||
function handleSubmitted(_relationId: string) {
|
||||
closeOperateModal();
|
||||
reloadTreeData();
|
||||
}
|
||||
@@ -411,14 +417,20 @@ onMounted(async () => {
|
||||
<span>{{ node.label }}</span>
|
||||
<!-- <ElTag v-if="data.managerNickname" size="small" type="info">上级:{{ data.managerNickname }}</ElTag>-->
|
||||
</span>
|
||||
<div class="flex items-center" style="min-width: 200px;">
|
||||
<div class="flex items-center" style="min-width: 200px">
|
||||
<ElButton link type="primary" size="default" @click.stop="openAdd(data)">
|
||||
<template #icon>
|
||||
<icon-ic-round-plus class="text-icon" />
|
||||
</template>
|
||||
新增
|
||||
</ElButton>
|
||||
<ElButton v-if="!(isRootNode(data) && shouldHideRootEdit)" link type="primary" size="small" @click.stop="openEdit(data)">
|
||||
<ElButton
|
||||
v-if="!(isRootNode(data) && shouldHideRootEdit)"
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click.stop="openEdit(data)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-ic-round-edit class="text-icon" />
|
||||
</template>
|
||||
|
||||
@@ -50,7 +50,7 @@ const props = defineProps<Props>();
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
/** 提交事件:返回提交后的关系 ID */
|
||||
submitted: [relationId: number];
|
||||
submitted: [relationId: string];
|
||||
}>();
|
||||
|
||||
/**
|
||||
@@ -126,11 +126,38 @@ function closeModal() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function resetValidateState() {
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
function resolveDefaultManagerUserId() {
|
||||
if (props.rowData?.managerUserId) {
|
||||
return props.rowData.managerUserId;
|
||||
}
|
||||
|
||||
const currentUserId = authStore.userInfo.userId;
|
||||
const currentUserName = authStore.userInfo.userName;
|
||||
|
||||
if (!currentUserId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const matchedById = props.userList.find(user => user.id === currentUserId);
|
||||
|
||||
if (matchedById) {
|
||||
return matchedById.id;
|
||||
}
|
||||
|
||||
return currentUserName ? props.userList.find(user => user.nickname === currentUserName)?.id : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化表单模型
|
||||
*
|
||||
* 编辑模式下加载详情数据,新增模式下设置默认值
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
async function initModel() {
|
||||
model.value = createDefaultModel();
|
||||
|
||||
@@ -138,18 +165,18 @@ async function initModel() {
|
||||
// 新增模式:设置管理者用户
|
||||
// 优先使用 rowData 中传入的管理者用户 ID(如从树形节点新增)
|
||||
// 否则使用当前登录用户
|
||||
let managerUserIdToSet: number | undefined;
|
||||
let managerUserIdToSet = resolveDefaultManagerUserId();
|
||||
|
||||
if (props.rowData && props.rowData.managerUserId) {
|
||||
// 从树形节点点击新增,管理者为当前节点用户
|
||||
managerUserIdToSet = props.rowData.managerUserId;
|
||||
} else if (authStore.userInfo.userId) {
|
||||
// 头部新增,管理者为当前登录用户
|
||||
const currentUserId = Number(authStore.userInfo.userId);
|
||||
const currentUserId = authStore.userInfo.userId;
|
||||
const currentUserName = authStore.userInfo.userName;
|
||||
|
||||
// 先尝试通过 ID 匹配
|
||||
let currentUser = props.userList.find(user => Number(user.id) === currentUserId);
|
||||
let currentUser = props.userList.find(user => user.id === currentUserId);
|
||||
|
||||
// 如果 ID 匹配失败,尝试通过用户名匹配
|
||||
if (!currentUser && currentUserName) {
|
||||
@@ -165,26 +192,31 @@ async function initModel() {
|
||||
model.value.managerUserId = managerUserIdToSet;
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
await resetValidateState();
|
||||
return;
|
||||
}
|
||||
|
||||
// 编辑模式:加载详情数据
|
||||
if (!props.rowData) {
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
await resetValidateState();
|
||||
return;
|
||||
}
|
||||
|
||||
const relationId = props.rowData.id;
|
||||
|
||||
if (!relationId) {
|
||||
await resetValidateState();
|
||||
return;
|
||||
}
|
||||
|
||||
detailLoading.value = true;
|
||||
|
||||
try {
|
||||
const { error, data } = await fetchGetUserManagementRelation(props.rowData.id);
|
||||
const { error, data } = await fetchGetUserManagementRelation(relationId);
|
||||
|
||||
if (data !== null && !error) {
|
||||
model.value = {
|
||||
id: data.id,
|
||||
id: data.id ?? undefined,
|
||||
managerUserId: data.managerUserId,
|
||||
subordinateUserId: data.subordinateUserId,
|
||||
effectiveFrom: data.effectiveFrom ? new Date(data.effectiveFrom).getTime() : null,
|
||||
@@ -196,8 +228,7 @@ async function initModel() {
|
||||
detailLoading.value = false;
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
await resetValidateState();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,23 +246,31 @@ async function handleSubmit() {
|
||||
...model.value
|
||||
};
|
||||
|
||||
const request =
|
||||
isEdit.value && props.rowData
|
||||
? await fetchUpdateUserManagementRelation({ id: props.rowData.id, ...submitData })
|
||||
: await fetchCreateUserManagementRelation(submitData);
|
||||
const editRelationId = props.rowData?.id ?? null;
|
||||
|
||||
const { error, data } = request;
|
||||
if (isEdit.value && editRelationId) {
|
||||
const { error } = await fetchUpdateUserManagementRelation({ ...submitData, id: editRelationId });
|
||||
|
||||
if (error) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success('淇敼鎴愬姛');
|
||||
closeModal();
|
||||
emit('submitted', editRelationId);
|
||||
return;
|
||||
}
|
||||
|
||||
const relationId = isEdit.value && props.rowData ? props.rowData.id : Number(data);
|
||||
const { error, data } = await fetchCreateUserManagementRelation(submitData);
|
||||
|
||||
if (error || !data) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success(isEdit.value ? '修改成功' : '新增成功');
|
||||
|
||||
closeModal();
|
||||
emit('submitted', relationId);
|
||||
emit('submitted', data);
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user