Files
cn-rdms-web/src/views/system/user-management-relation/modules/relation-operate-dialog.vue

323 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
/**
* 用户汇报关系操作对话框
*
* 功能说明:
* - 新增用户汇报关系
* - 编辑用户汇报关系
* - 表单验证和提交
*
* 表单字段:
* - 管理者用户:必填,下拉选择,默认当前登录用户
* - 被管理用户:必填,下拉选择,默认空
* - 生效开始时间:可选
* - 生效结束时间:可选
* - 备注:可选
*
* 用户列表通过 props 传入,由父组件统一管理
*/
import { computed, nextTick, ref, watch } from 'vue';
import {
fetchCreateUserManagementRelation,
fetchGetUserManagementRelation,
fetchUpdateUserManagementRelation
} from '@/service/api';
import { useAuthStore } from '@/store/modules/auth';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
defineOptions({ name: 'RelationOperateDialog' });
/**
* 组件 Props 定义
*/
interface Props {
/** 操作类型:新增或编辑 */
operateType: UI.TableOperateType;
/** 编辑时的行数据 */
rowData?: Api.SystemManage.UserManagementRelation | null;
/** 用户列表,由父组件统一提供 */
userList: Api.SystemManage.UserSimple[];
}
const props = defineProps<Props>();
/**
* 组件 Emits 定义
*
* 使用 Vue 3.5 标准语法
*/
const emit = defineEmits<{
/** 提交事件:返回提交后的关系 ID */
submitted: [relationId: number];
}>();
/**
* 对话框可见性,支持 v-model 双向绑定
*/
const visible = defineModel<boolean>('visible', {
default: false
});
// 表单相关
const { formRef, validate } = useForm();
const { createRequiredRule } = useFormRules();
// 获取当前登录用户信息
const authStore = useAuthStore();
// 加载和提交状态
const detailLoading = ref(false);
const submitting = ref(false);
// 计算属性:是否为编辑模式
const isEdit = computed(() => props.operateType === 'edit');
/**
* 计算对话框标题
*/
const title = computed(() => {
const titleMap: Record<UI.TableOperateType, string> = {
add: '新增用户汇报关系',
edit: '编辑用户汇报关系'
};
return titleMap[props.operateType];
});
/**
* 表单模型类型
*/
type Model = Api.SystemManage.UserManagementRelationSaveReqVO;
/**
* 表单模型
*/
const model = ref(createDefaultModel());
/**
* 创建默认表单模型
*
* @returns 默认模型对象
*/
function createDefaultModel(): Model {
return {
managerUserId: null,
subordinateUserId: null,
effectiveFrom: null,
effectiveUntil: null,
remark: null
};
}
/**
* 表单验证规则
*/
const rules = {
managerUserId: createRequiredRule('请选择管理者用户'),
subordinateUserId: createRequiredRule('请选择被管理用户')
} satisfies Record<string, App.Global.FormRule>;
/**
* 关闭对话框
*/
function closeModal() {
visible.value = false;
}
/**
* 初始化表单模型
*
* 编辑模式下加载详情数据,新增模式下设置默认值
*/
async function initModel() {
model.value = createDefaultModel();
if (!isEdit.value) {
// 新增模式:设置管理者用户
// 优先使用 rowData 中传入的管理者用户 ID如从树形节点新增
// 否则使用当前登录用户
let managerUserIdToSet: number | undefined;
if (props.rowData && props.rowData.managerUserId) {
// 从树形节点点击新增,管理者为当前节点用户
managerUserIdToSet = props.rowData.managerUserId;
} else if (authStore.userInfo.userId) {
// 头部新增,管理者为当前登录用户
const currentUserId = Number(authStore.userInfo.userId);
const currentUserName = authStore.userInfo.userName;
// 先尝试通过 ID 匹配
let currentUser = props.userList.find(user => Number(user.id) === currentUserId);
// 如果 ID 匹配失败,尝试通过用户名匹配
if (!currentUser && currentUserName) {
currentUser = props.userList.find(user => user.nickname === currentUserName);
}
if (currentUser) {
managerUserIdToSet = currentUser.id;
}
}
if (managerUserIdToSet) {
model.value.managerUserId = managerUserIdToSet;
}
await nextTick();
formRef.value?.clearValidate();
return;
}
// 编辑模式:加载详情数据
if (!props.rowData) {
await nextTick();
formRef.value?.clearValidate();
return;
}
detailLoading.value = true;
try {
const { error, data } = await fetchGetUserManagementRelation(props.rowData.id);
if (data !== null && !error) {
model.value = {
id: data.id,
managerUserId: data.managerUserId,
subordinateUserId: data.subordinateUserId,
effectiveFrom: data.effectiveFrom ? new Date(data.effectiveFrom).getTime() : null,
effectiveUntil: data.effectiveUntil ? new Date(data.effectiveUntil).getTime() : null,
remark: data.remark ?? null
};
}
} finally {
detailLoading.value = false;
}
await nextTick();
formRef.value?.clearValidate();
}
/**
* 处理表单提交
*
* 验证通过后调用创建或更新接口
*/
async function handleSubmit() {
await validate();
submitting.value = true;
try {
const submitData: Api.SystemManage.UserManagementRelationSaveReqVO = {
...model.value
};
const request =
isEdit.value && props.rowData
? await fetchUpdateUserManagementRelation({ id: props.rowData.id, ...submitData })
: await fetchCreateUserManagementRelation(submitData);
const { error, data } = request;
if (error) {
return;
}
const relationId = isEdit.value && props.rowData ? props.rowData.id : Number(data);
window.$message?.success(isEdit.value ? '修改成功' : '新增成功');
closeModal();
emit('submitted', relationId);
} finally {
submitting.value = false;
}
}
/**
* 监听对话框可见性
*
* 打开时初始化表单
*/
watch(visible, value => {
if (value) {
initModel();
}
});
</script>
<template>
<BusinessFormDialog
v-model="visible"
:title="title"
preset="md"
:loading="detailLoading"
:confirm-loading="submitting"
:scrollbar="false"
@confirm="handleSubmit"
>
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
<ElRow :gutter="16">
<ElCol :span="12">
<ElFormItem label="管理者用户" prop="managerUserId">
<ElSelect v-model="model.managerUserId" class="w-full" placeholder="请选择管理者用户" filterable>
<ElOption v-for="user in props.userList" :key="user.id" :label="user.nickname" :value="user.id" />
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol :span="12">
<ElFormItem label="被管理用户" prop="subordinateUserId">
<ElSelect
v-model="model.subordinateUserId"
class="w-full"
placeholder="请选择被管理用户"
filterable
:disabled="isEdit"
>
<ElOption v-for="user in props.userList" :key="user.id" :label="user.nickname" :value="user.id" />
</ElSelect>
</ElFormItem>
</ElCol>
</ElRow>
<ElRow :gutter="16">
<ElCol :span="12">
<ElFormItem label="生效开始时间" prop="effectiveFrom" style="width: 100%">
<ElDatePicker
v-model="model.effectiveFrom"
class="w-full"
type="datetime"
placeholder="请选择生效开始时间"
value-format="x"
style="width: 100%"
/>
</ElFormItem>
</ElCol>
<ElCol :span="12">
<ElFormItem label="生效结束时间" prop="effectiveUntil" style="width: 100%">
<ElDatePicker
v-model="model.effectiveUntil"
class="w-full"
type="datetime"
placeholder="请选择生效结束时间"
value-format="x"
style="width: 100%"
/>
</ElFormItem>
</ElCol>
</ElRow>
<ElRow :gutter="16">
<ElCol :span="24">
<ElFormItem label="备注" prop="remark">
<ElInput v-model="model.remark" type="textarea" :rows="4" placeholder="请输入备注" />
</ElFormItem>
</ElCol>
</ElRow>
</ElForm>
</BusinessFormDialog>
</template>
<style scoped></style>