Archived
forked from admin/userbase
This commit is contained in:
@@ -57,19 +57,19 @@
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<!-- 第 5 行:所在组(只读)(仅编辑展示,普通单选、默认选中当前组;提交时不带 groupId,不改变所在组) -->
|
||||
<!-- 第 5 行:所在组(仅编辑展示;切换只触发下方「用户身份」回显,不改变实际所在组) -->
|
||||
<Row v-if="isEdit">
|
||||
<Col span="24">
|
||||
<FormItem label="所在组(只读):">
|
||||
<FormItem label="所在组:">
|
||||
<Select v-model="form.userGroupId" transfer clearable
|
||||
placeholder="默认选中当前组(提交不改变所在组)">
|
||||
placeholder="切换后回显该组身份(不改变实际所在组)">
|
||||
<Option v-for="g in userGroups" :key="g.id" :value="g.id" :label="g.name" />
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<!-- 第 6 行:用户身份(checkbox 多选,整行) -->
|
||||
<!-- 第 6 行:用户身份(checkbox 多选,整行;编辑时跟随所在组 Select 回显) -->
|
||||
<Row>
|
||||
<Col span="24">
|
||||
<FormItem label="用户身份:" prop="userType">
|
||||
@@ -105,7 +105,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, watch } from "vue";
|
||||
import { Message } from "view-ui-plus";
|
||||
import { useDefaultStore } from "@/store";
|
||||
import MyConfirm from "@/components/MyConfirm";
|
||||
|
||||
/* ---------- Props / Emits ---------- */
|
||||
const props = withDefaults(defineProps<{
|
||||
@@ -145,10 +147,14 @@ const defaultForm = (): Record<string, any> => ({
|
||||
userType: [] as number[],
|
||||
appRoles: [] as number[],
|
||||
userGroupId: null as number | null,
|
||||
schoolId: null as number | null,
|
||||
});
|
||||
|
||||
const form = reactive(defaultForm());
|
||||
|
||||
// 编辑模式回显到的最新的身份基线(用于「非空清成空」二次确认;随所在组切换同步更新)
|
||||
let baselineUserType: number[] = [];
|
||||
|
||||
// 外部 initForm 变化时回填
|
||||
watch(() => props.initForm, (val) => {
|
||||
if (val && Object.keys(val).length > 0) {
|
||||
@@ -179,6 +185,24 @@ const userTypeOptions = computed(() => {
|
||||
return SYS_ROLE_FALLBACK;
|
||||
});
|
||||
|
||||
/* ---------- 用户身份回显(唯一来源 GET UserIdentity) ---------- */
|
||||
// 所在组 Select 切换(含弹窗打开时的初始选中)→ 后端解析 schoolId 后回显 {schoolId, roleIds}。
|
||||
// 同一学校多组由后端返回同一 schoolId 与角色并集;前端不感知解析逻辑。
|
||||
watch(() => form.userGroupId, (gid: number | null) => {
|
||||
if (!props.isEdit || gid == null || !form.id) return;
|
||||
Apis.SysUser.userIdentity({ params: { userId: form.id, groupId: gid }, cacheFor: null })
|
||||
.then((resp: any) => {
|
||||
const roleIds = Array.isArray(resp?.roleIds) ? resp.roleIds.map((v: any) => Number(v)) : [];
|
||||
form.schoolId = resp?.schoolId ?? null;
|
||||
form.userType = roleIds;
|
||||
baselineUserType = roleIds;
|
||||
})
|
||||
.catch((e: any) => {
|
||||
// 全局拦截器已弹窗,这里仅记录日志避免二次弹窗;schoolId 保持 null 时提交会被后端拒绝,不会误清空
|
||||
console.warn('[UserForm] 加载用户身份失败:', e?.message || '未知错误');
|
||||
});
|
||||
});
|
||||
|
||||
/* ---------- 校验规则 ---------- */
|
||||
// 自定义确认密码校验:新增必填且必须与密码一致;编辑时两者皆空表示不修改,任一非空则必须一致
|
||||
const validateConfirmPassword = (rule: any, value: string, callback: any) => {
|
||||
@@ -223,6 +247,14 @@ const validateAccount = (rule: any, value: string, callback: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 用户身份校验拆分:新增强制 ≥1 必填;编辑允许为空(空数组提交 = 清空该校身份,
|
||||
// 否则切到一个尚无身份数据的学校后连改手机号都会被 min:1 卡死)
|
||||
const validateUserType = (rule: any, value: number[], callback: any) => {
|
||||
if (props.isEdit) return callback();
|
||||
if (!value || value.length === 0) return callback(new Error('请选择至少一个用户身份'));
|
||||
callback();
|
||||
};
|
||||
|
||||
// 密码红五星号仅新增显示;校验规则随 isEdit 变化
|
||||
const rules = computed(() => ({
|
||||
account: [
|
||||
@@ -239,7 +271,7 @@ const rules = computed(() => ({
|
||||
{ pattern: /^1\d{10}$/, message: '请输入正确的手机号', trigger: 'blur' },
|
||||
],
|
||||
userType: [
|
||||
{ required: true, type: 'array' as const, min: 1, message: '请选择至少一个用户身份', trigger: 'change' },
|
||||
{ required: !props.isEdit, validator: validateUserType, trigger: 'change' },
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -254,6 +286,19 @@ watch(() => form.password, () => {
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
// 编辑模式身份回显未就绪(schoolId 为空)时拦截:避免在身份数据未加载时提交造成误清空
|
||||
if (props.isEdit && form.schoolId == null) {
|
||||
Message.warning('用户身份数据加载中,请稍候再提交');
|
||||
return false;
|
||||
}
|
||||
// 勾选由非空清成空:二次确认(空数组提交 = 清空该校身份)
|
||||
if (props.isEdit && baselineUserType.length > 0 && form.userType.length === 0) {
|
||||
const ok = await MyConfirm({
|
||||
msg: '确定清空该用户在此学校的身份吗?',
|
||||
info: '清空后该校用户将无任何身份',
|
||||
});
|
||||
if (!ok) return false;
|
||||
}
|
||||
try {
|
||||
await formRef.value?.validate();
|
||||
} catch {
|
||||
@@ -308,4 +353,4 @@ function onVisibleChange(val: boolean) {
|
||||
flex-wrap: wrap;
|
||||
gap: 0 18px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user