修改功能
This commit is contained in:
@@ -45,14 +45,9 @@
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<!-- 第 4 行:手机号码2 / 性别 -->
|
||||
<!-- 第 4 行:性别 -->
|
||||
<Row>
|
||||
<Col span="12">
|
||||
<FormItem label="手机号码2:">
|
||||
<Input v-model="form.phone2" placeholder="请输入手机号码" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span="12">
|
||||
<Col span="24">
|
||||
<FormItem label="性别:">
|
||||
<RadioGroup v-model="form.gender">
|
||||
<Radio :label="0">女</Radio>
|
||||
@@ -62,12 +57,12 @@
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<!-- 第 5 行:所在组(整行) -->
|
||||
<Row>
|
||||
<!-- 第 5 行:所在组(只读)(仅编辑展示,显示用户全部所属组;不提交) -->
|
||||
<Row v-if="isEdit">
|
||||
<Col span="24">
|
||||
<FormItem label="所在组:" prop="groupId">
|
||||
<Select v-model="form.groupId" placeholder="请选择所在组" filterable transfer>
|
||||
<Option v-for="g in groupOptions" :key="g.id" :value="g.id" :label="g.name" />
|
||||
<FormItem label="所在组(只读):">
|
||||
<Select :value="userGroupIds" multiple disabled transfer class="group-readonly">
|
||||
<Option v-for="g in userGroups" :key="g.id" :value="g.id" :label="g.name" />
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
@@ -86,16 +81,18 @@
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<!-- 第 7 行:角色属性(整行) -->
|
||||
<!-- 第 7 行:角色属性(业务角色多选,可编辑;来自角色授权页) -->
|
||||
<Row>
|
||||
<Col span="24">
|
||||
<FormItem label="角色属性:" prop="role">
|
||||
<Select v-model="form.role" placeholder="请选择" clearable transfer style="width: 220px">
|
||||
<Option v-for="r in roleOptions" :key="r.value" :value="r.value" :label="r.label" />
|
||||
<FormItem label="角色属性:">
|
||||
<Select v-model="form.appRoles" multiple filterable clearable transfer
|
||||
placeholder="可选择业务角色(来自角色授权)">
|
||||
<Option v-for="r in roleOptions" :key="r.id" :value="r.id" :label="r.name" />
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</Form>
|
||||
|
||||
<template #footer>
|
||||
@@ -106,18 +103,20 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, watch } from "vue";
|
||||
import { computed, reactive, ref, watch } from "vue";
|
||||
|
||||
/* ---------- Props / Emits ---------- */
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue: boolean;
|
||||
initForm?: Record<string, any>;
|
||||
groupOptions?: any[];
|
||||
userGroups?: { id: number; name: string }[];
|
||||
roleOptions?: { id: number; name: string }[];
|
||||
isEdit?: boolean;
|
||||
loading?: boolean;
|
||||
}>(), {
|
||||
initForm: () => ({}),
|
||||
groupOptions: () => [],
|
||||
userGroups: () => [],
|
||||
roleOptions: () => [],
|
||||
isEdit: false,
|
||||
loading: false,
|
||||
});
|
||||
@@ -140,11 +139,9 @@ const defaultForm = (): Record<string, any> => ({
|
||||
confirmPassword: '',
|
||||
idcard: '',
|
||||
phone: '',
|
||||
phone2: '',
|
||||
gender: 0,
|
||||
groupId: undefined as number | undefined,
|
||||
userType: [] as number[],
|
||||
role: undefined as number | undefined,
|
||||
appRoles: [] as number[],
|
||||
});
|
||||
|
||||
const form = reactive(defaultForm());
|
||||
@@ -158,6 +155,9 @@ watch(() => props.initForm, (val) => {
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 所在组(只读) 多选值:用户全部所属组的 ID 列表
|
||||
const userGroupIds = computed(() => (props.userGroups || []).map(g => g.id));
|
||||
|
||||
/* ---------- 用户身份(业务身份多选)---------- */
|
||||
const userTypeOptions = [
|
||||
{ value: 1, label: '管理员' },
|
||||
@@ -169,74 +169,80 @@ const userTypeOptions = [
|
||||
{ value: 7, label: '工作号' },
|
||||
];
|
||||
|
||||
/* ---------- 角色属性(具体角色单选,固定枚举)---------- */
|
||||
const roleOptions = [
|
||||
{ value: 1, label: '超级管理员' },
|
||||
{ value: 2, label: '学校管理员' },
|
||||
{ value: 3, label: '普通用户' },
|
||||
];
|
||||
|
||||
/* ---------- 校验规则 ---------- */
|
||||
// 自定义确认密码校验
|
||||
// 自定义确认密码校验:新增必填且必须与密码一致;编辑时两者皆空表示不修改,任一非空则必须一致
|
||||
const validateConfirmPassword = (rule: any, value: string, callback: any) => {
|
||||
const pwd = form.password || '';
|
||||
const conf = value || '';
|
||||
if (!props.isEdit) {
|
||||
// 新增:必填 + 必须与密码一致
|
||||
if (!value) {
|
||||
callback(new Error('请再次输入密码'));
|
||||
} else if (value !== form.password) {
|
||||
callback(new Error('两次输入的密码不一致'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
} else {
|
||||
// 编辑:留空表示不修改密码;非空时必须与密码一致
|
||||
if (value && value !== form.password) {
|
||||
callback(new Error('两次输入的密码不一致'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
if (!conf) return callback(new Error('请再次输入密码'));
|
||||
if (conf !== pwd) return callback(new Error('两次输入的密码不一致'));
|
||||
return callback();
|
||||
}
|
||||
// 编辑:都为空 -> 不修改密码,放行
|
||||
if (!pwd && !conf) return callback();
|
||||
// 修改密码时两次输入必须同时填写且一致
|
||||
if (!pwd || !conf) return callback(new Error('修改密码时两次输入必须一致'));
|
||||
if (pwd !== conf) return callback(new Error('两次输入的密码不一致'));
|
||||
callback();
|
||||
};
|
||||
|
||||
// 自定义密码校验(编辑时可留空)
|
||||
// 自定义密码校验:新增必填(>=6位);编辑可留空,留空表示不修改
|
||||
const validatePassword = (rule: any, value: string, callback: any) => {
|
||||
if (!props.isEdit && !value) {
|
||||
callback(new Error('请输入密码'));
|
||||
} else if (value && value.length < 6) {
|
||||
callback(new Error('密码长度不能少于 6 位'));
|
||||
const pwd = value || '';
|
||||
if (!props.isEdit) {
|
||||
if (!pwd) return callback(new Error('请输入密码'));
|
||||
if (pwd.length < 6) return callback(new Error('密码长度不能少于 6 位'));
|
||||
return callback();
|
||||
}
|
||||
if (!pwd) return callback();
|
||||
if (pwd.length < 6) return callback(new Error('密码长度不能少于 6 位'));
|
||||
callback();
|
||||
};
|
||||
|
||||
// 用户名格式校验:新增时强制仅数字/字母;编辑时账号只读不可改,跳过格式校验
|
||||
const validateAccount = (rule: any, value: string, callback: any) => {
|
||||
if (props.isEdit) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (value && !/^[A-Za-z0-9]+$/.test(value)) {
|
||||
callback(new Error('用户名只能由数字或字母组成'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const rules = {
|
||||
// 密码红五星号仅新增显示;校验规则随 isEdit 变化
|
||||
const rules = computed(() => ({
|
||||
account: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 3, max: 30, message: '用户名长度 3-30 位', trigger: 'blur' },
|
||||
{ validator: validateAccount, trigger: 'blur' },
|
||||
],
|
||||
realName: [
|
||||
{ required: true, message: '请输入真实姓名', trigger: 'blur' },
|
||||
],
|
||||
password: [{ validator: validatePassword, trigger: 'blur' }],
|
||||
confirmPassword: [{ validator: validateConfirmPassword, trigger: 'blur' }],
|
||||
password: [{ required: !props.isEdit, validator: validatePassword, trigger: 'blur' }],
|
||||
confirmPassword: [{ required: !props.isEdit, validator: validateConfirmPassword, trigger: 'blur' }],
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号码', trigger: 'blur' },
|
||||
{ pattern: /^1\d{10}$/, message: '请输入正确的手机号', trigger: 'blur' },
|
||||
],
|
||||
groupId: [
|
||||
{ required: true, type: 'number' as const, message: '请选择所在组', trigger: 'change' },
|
||||
],
|
||||
userType: [
|
||||
{ required: true, type: 'array' as const, min: 1, message: '请选择至少一个用户身份', trigger: 'change' },
|
||||
],
|
||||
role: [
|
||||
{ required: true, type: 'number' as const, message: '请选择角色属性', trigger: 'change' },
|
||||
],
|
||||
};
|
||||
}));
|
||||
|
||||
/* ---------- 提交 ---------- */
|
||||
const formRef = ref();
|
||||
|
||||
// 密码变化时,若已填确认密码则重新校验确认密码,保持一致性提示
|
||||
watch(() => form.password, () => {
|
||||
if (form.confirmPassword) {
|
||||
formRef.value?.validateField('confirmPassword');
|
||||
}
|
||||
});
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await formRef.value?.validate();
|
||||
@@ -292,4 +298,15 @@ function onVisibleChange(val: boolean) {
|
||||
flex-wrap: wrap;
|
||||
gap: 0 18px;
|
||||
}
|
||||
|
||||
/* 所在组(只读):保留 disabled(防止误删标签),但去掉灰底灰字,显示为正常白底深色 */
|
||||
.user-form :deep(.group-readonly.ivu-select-disabled .ivu-select-selection) {
|
||||
background-color: #fff;
|
||||
color: #515a6e;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.user-form :deep(.group-readonly.ivu-select-disabled .ivu-select-arrow) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user