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:
203
src/views/product/setting/modules/member-operate-dialog.vue
Normal file
203
src/views/product/setting/modules/member-operate-dialog.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, reactive, watch } from 'vue';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import BusinessFormSection from '@/components/custom/business-form-section.vue';
|
||||
import { getPreviousManagerRoleOptions, shouldRequireManagerHandover } from '../shared';
|
||||
|
||||
defineOptions({ name: 'MemberOperateDialog' });
|
||||
|
||||
type OperateMode = 'create' | 'edit';
|
||||
|
||||
interface Props {
|
||||
mode: OperateMode;
|
||||
member: Api.Product.ProductMember | null;
|
||||
currentManager: Api.Product.ProductMember | null;
|
||||
roleOptions: Api.SystemManage.RoleSimple[];
|
||||
userOptions: Api.SystemManage.UserSimple[];
|
||||
}
|
||||
|
||||
interface SubmitPayload {
|
||||
mode: OperateMode;
|
||||
memberId?: string;
|
||||
managerChanged: boolean;
|
||||
payload: Api.Product.CreateProductMemberParams | Api.Product.UpdateProductMemberParams;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'submit', payload: SubmitPayload): void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const { formRef, validate } = useForm();
|
||||
const { createRequiredRule } = useFormRules();
|
||||
|
||||
interface Model {
|
||||
userId: string;
|
||||
roleId: string;
|
||||
remark: string;
|
||||
reason: string;
|
||||
previousManagerRoleId: string;
|
||||
}
|
||||
|
||||
const model = reactive<Model>({
|
||||
userId: '',
|
||||
roleId: '',
|
||||
remark: '',
|
||||
reason: '',
|
||||
previousManagerRoleId: ''
|
||||
});
|
||||
|
||||
const dialogTitle = computed(() => (props.mode === 'create' ? '新增团队成员' : '调整成员角色'));
|
||||
const selectedUserId = computed(() => (props.mode === 'create' ? model.userId : props.member?.userId || ''));
|
||||
const showManagerHandover = computed(() => {
|
||||
return (
|
||||
shouldRequireManagerHandover(model.roleId, props.currentManager) &&
|
||||
Boolean(selectedUserId.value) &&
|
||||
selectedUserId.value !== props.currentManager?.userId
|
||||
);
|
||||
});
|
||||
const previousManagerRoleOptions = computed(() =>
|
||||
getPreviousManagerRoleOptions(props.roleOptions, props.currentManager?.roleId || '')
|
||||
);
|
||||
const userLabelMap = computed(() => new Map(props.userOptions.map(item => [item.id, item.nickname])));
|
||||
|
||||
const rules = computed(
|
||||
() =>
|
||||
({
|
||||
userId: props.mode === 'create' ? [createRequiredRule('请选择成员用户')] : [],
|
||||
roleId: [createRequiredRule('请选择角色')],
|
||||
previousManagerRoleId: showManagerHandover.value ? [createRequiredRule('请选择原产品经理交接后角色')] : []
|
||||
}) satisfies Record<string, App.Global.FormRule[]>
|
||||
);
|
||||
|
||||
async function handleConfirm() {
|
||||
await validate();
|
||||
|
||||
const sharedPayload = {
|
||||
roleId: model.roleId,
|
||||
remark: model.remark.trim() || null,
|
||||
previousManagerUserId: showManagerHandover.value ? props.currentManager?.userId || null : null,
|
||||
previousManagerRoleId: showManagerHandover.value ? model.previousManagerRoleId : null
|
||||
};
|
||||
|
||||
if (props.mode === 'create') {
|
||||
emit('submit', {
|
||||
mode: 'create',
|
||||
managerChanged: showManagerHandover.value,
|
||||
payload: {
|
||||
userId: model.userId,
|
||||
roleId: sharedPayload.roleId,
|
||||
remark: sharedPayload.remark,
|
||||
previousManagerUserId: sharedPayload.previousManagerUserId,
|
||||
previousManagerRoleId: sharedPayload.previousManagerRoleId
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
emit('submit', {
|
||||
mode: 'edit',
|
||||
memberId: props.member?.id,
|
||||
managerChanged: showManagerHandover.value,
|
||||
payload: {
|
||||
roleId: sharedPayload.roleId,
|
||||
remark: sharedPayload.remark,
|
||||
reason: model.reason.trim() || null,
|
||||
previousManagerUserId: sharedPayload.previousManagerUserId,
|
||||
previousManagerRoleId: sharedPayload.previousManagerRoleId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
async value => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
model.userId = props.mode === 'create' ? '' : props.member?.userId || '';
|
||||
model.roleId = props.mode === 'create' ? '' : props.member?.roleId || '';
|
||||
model.remark = props.mode === 'create' ? '' : props.member?.remark || '';
|
||||
model.reason = '';
|
||||
model.previousManagerRoleId = '';
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog v-model="visible" :title="dialogTitle" preset="lg" @confirm="handleConfirm">
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<BusinessFormSection title="成员信息">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem v-if="mode === 'create'" label="成员用户" prop="userId">
|
||||
<ElSelect v-model="model.userId" class="w-full" filterable placeholder="请选择成员用户">
|
||||
<ElOption v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem v-else label="成员用户">
|
||||
<ElInput :model-value="member?.userNickname || userLabelMap.get(member?.userId || '') || ''" readonly />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="目标角色" prop="roleId">
|
||||
<ElSelect v-model="model.roleId" class="w-full" placeholder="请选择角色">
|
||||
<ElOption v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="备注">
|
||||
<ElInput
|
||||
v-model="model.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</BusinessFormSection>
|
||||
|
||||
<BusinessFormSection v-if="mode === 'edit'" title="角色调整说明">
|
||||
<ElFormItem label="变更原因">
|
||||
<ElInput
|
||||
v-model="model.reason"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入变更原因"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</BusinessFormSection>
|
||||
|
||||
<BusinessFormSection v-if="showManagerHandover" title="产品经理交接">
|
||||
<ElAlert
|
||||
:title="`当前产品经理 ${currentManager?.userNickname || currentManager?.userId || ''} 将完成交接,请选择其交接后角色。`"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
class="mb-16px"
|
||||
/>
|
||||
<ElFormItem label="原产品经理交接后角色" prop="previousManagerRoleId">
|
||||
<ElSelect v-model="model.previousManagerRoleId" class="w-full" placeholder="请选择原产品经理交接后角色">
|
||||
<ElOption v-for="item in previousManagerRoleOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</BusinessFormSection>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
Reference in New Issue
Block a user