Files
UserbaseFront/src/views/group-user/user/AddUserContainer.vue
T
chenxing af94e1d2cb
build / build (push) Successful in 2m53s
fix(permission): 角色节点联动已授权应用、所属部门按行收窄、树滚动条收敛
- 权限一览:formatRoleAuthzTree 子节点键 apps→children(zTree 只认 children,导致除分类外全不渲染)
- 权限一览:所属部门按行所在组请求 UserGroupTree,多组用户只显示该组链路,(本组)标记指向该组
- 角色授权:用户管理新增「部门」列,添加/删除按(用户,组)维度,切组清空勾选避免误绑
- 编辑用户:切「所在组」时身份与角色属性双回显,该组角色未就绪拦截提交防误存;保存按组覆盖
- 组用户管理:左侧树滚动条收敛到树节点(页面级新增 group-user-tree 类,不动全局 .tree-container)
2026-09-16 16:33:58 +08:00

107 lines
4.2 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.
<template>
<UserForm v-model="visible" :initForm="initFormData" :roleOptions="roleOptions" :isEdit="false"
:loading="submitting" @submit="handleSubmit" @cancel="visible = false" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import UserForm from "./UserForm.vue";
/* ---------- 对外暴露:由父组件(group-user/index)调用 ---------- */
const visible = ref(false);
// 当前所在组(新增时由左侧选中节点带入,作为创建分组,不展示)
const currentGroupId = ref<number | null>(null);
// 新增模式:始终传空初始值
const initFormData = ref<Record<string, any>>({});
// 角色属性下拉:来自角色授权页的全量角色
const roleOptions = ref<{ id: number; name: string }[]>([]);
// 待保存的角色属性(用户多选结果)
let appRolesToSave: number[] = [];
// 成功后回调
let onSuccessCallback: (() => void) | null = null;
// useForm 托管提交:loading=submitting、sendForm 发请求、onSuccess/onError 处理结果
const { form, loading: submitting, send: sendForm, onSuccess, onError } = useForm(
(dto) => Apis.SysUser.add({ data: dto }),
{ initialForm: { account: '', realName: '', password: '', confirmPassword: '', idcard: '', phone: '', gender: 0, userType: [] }, resetAfterSubmiting: true }
);
onSuccess(() => {
Message.success('新增用户成功!');
visible.value = false;
onSuccessCallback?.();
});
onError((event) => {
// 错误提示已由全局 alova 拦截器统一弹出,这里仅记录日志避免二次弹窗
console.warn('[AddUserContainer] 新增失败:', event?.error?.message || '新增失败');
});
/* ---------- 打开弹窗 ---------- */
function open(groups: any[], defaultGroupId?: number | null, onSuccess?: () => void) {
// 当前所在组作为创建分组(提交时回写 groupId),新增模式不展示
currentGroupId.value = defaultGroupId != null ? defaultGroupId : null;
initFormData.value = {};
onSuccessCallback = onSuccess || null;
visible.value = true;
// 加载角色属性下拉(失败时静默降级,不影响新增主流程)
Apis.AppRole.roleList({ params: { pageIndex: 1, pageSize: 999 } })
.then((resp: any) => {
roleOptions.value = (resp?.content || []).map((r: any) => ({ id: r.id, name: r.name }));
})
.catch(() => {
roleOptions.value = [];
});
}
/* ---------- 提交:由 useForm 接管 loading 与异常处理 ---------- */
async function handleSubmit(formData: Record<string, any>) {
appRolesToSave = (formData.appRoles || []) as number[];
form.value = buildPayload(formData);
let newId: number | undefined;
try {
newId = (await sendForm()) as number;
} catch {
// 新增失败(onError 已提示),不继续绑定角色
return;
}
// 新增成功后再绑定业务角色(组维度:绑定挂在创建分组上,即左侧当前选中组)
if (newId != null && appRolesToSave.length) {
try {
await Apis.AppRole.saveUserRoles({
data: { userId: newId, groupId: currentGroupId.value ?? undefined, roleIds: appRolesToSave },
});
} catch (e: any) {
// 全局拦截器已弹窗,这里仅记录日志避免二次弹窗
console.warn('[AddUserContainer] 用户已创建,但角色属性保存失败:', e?.message || '未知错误');
}
}
}
/**
* 把表单字段映射成 SysUserRequest:
* - 只提交后端 SysUserRequest 里声明的字段
* - 身份角色来自"用户身份"勾选(userType → roleIds);schoolId 不传,由后端按 groupId 解析落库
* - groupId 由当前所在组回写
*/
function buildPayload(formData: Record<string, any>) {
const roleIds: number[] = (formData.userType || []).map((v: any) => Number(v));
return {
account: formData.account,
password: formData.password,
confirmPassword: formData.confirmPassword,
realName: formData.realName,
idcard: formData.idcard || undefined,
phone: formData.phone || undefined,
gender: formData.gender,
groupId: currentGroupId.value,
roleIds,
};
}
defineExpose({ open, visible });
</script>