page: 📄 用户可以用邮箱或者用户名登录,修改部分缺陷

This commit is contained in:
Bunny 2024-10-27 17:27:21 +08:00
parent 35957e7b7d
commit f2c809a142
19 changed files with 280 additions and 123 deletions

View File

@ -57,7 +57,7 @@ onMounted(() => {
<el-image :src="userinfo.avatar" style="width: 100px; height: 100px" /> <el-image :src="userinfo.avatar" style="width: 100px; height: 100px" />
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="$t('username')" :width="100">{{ userinfo.username }}</el-descriptions-item> <el-descriptions-item :label="$t('username')" :width="100">{{ userinfo.username }}</el-descriptions-item>
<el-descriptions-item :label="$t('nickName')" :width="100">{{ userinfo.nickName }}</el-descriptions-item> <el-descriptions-item :label="$t('nickname')" :width="100">{{ userinfo.nickname }}</el-descriptions-item>
<el-descriptions-item :label="$t('email')"> {{ userinfo.email }}</el-descriptions-item> <el-descriptions-item :label="$t('email')"> {{ userinfo.email }}</el-descriptions-item>
<el-descriptions-item :label="$t('phone')">{{ userinfo.phone }}</el-descriptions-item> <el-descriptions-item :label="$t('phone')">{{ userinfo.phone }}</el-descriptions-item>
@ -100,7 +100,7 @@ onMounted(() => {
<el-descriptions-item :label="$t('username')" :width="100"> <el-descriptions-item :label="$t('username')" :width="100">
<el-skeleton :rows="1" animated /> <el-skeleton :rows="1" animated />
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :label="$t('nickName')" :width="100"> <el-descriptions-item :label="$t('nickname')" :width="100">
<el-skeleton :rows="1" animated /> <el-skeleton :rows="1" animated />
</el-descriptions-item> </el-descriptions-item>

View File

@ -27,7 +27,7 @@ export const useAdminUserStore = defineStore('adminUserStore', {
// 用户名 // 用户名
username: undefined, username: undefined,
// 昵称 // 昵称
nickName: undefined, nickname: undefined,
// 邮箱 // 邮箱
email: undefined, email: undefined,
// 手机号 // 手机号

View File

@ -49,9 +49,8 @@ export const useUserStore = defineStore({
return false; return false;
}, },
/** 前端登出(不调用接口) */ /** 前端登出 */
async logOut() { async logOut() {
// 登出
const result = await fetchLogout(); const result = await fetchLogout();
if (result.code == 200) { if (result.code == 200) {
this.username = ''; this.username = '';
@ -83,7 +82,9 @@ export const useUserStore = defineStore({
async getUserinfo() { async getUserinfo() {
const result = await fetchGetUserinfo(); const result = await fetchGetUserinfo();
if (result.code === 200) { if (result.code === 200) {
return result.data; const data = result.data;
setToken(data);
return data;
} }
return {}; return {};
}, },

View File

@ -47,7 +47,11 @@ const onSubmit = async (formEl: FormInstance) => {
const avatar = uploadAvatarSrc.value; const avatar = uploadAvatarSrc.value;
if (avatar) userInfos.avatar = avatar; if (avatar) userInfos.avatar = avatar;
await adminUserStore.updateAdminUserByLocalUser(userInfos); //
const result = await adminUserStore.updateAdminUserByLocalUser(userInfos);
if (!result) return;
//
await onSearchByUserinfo(); await onSearchByUserinfo();
} else { } else {
message($t('required_fields'), { type: 'warning' }); message($t('required_fields'), { type: 'warning' });
@ -81,12 +85,12 @@ onMounted(() => {
<!-- 用户名 --> <!-- 用户名 -->
<el-form-item :label="$t('adminUser_username')" prop="username"> <el-form-item :label="$t('adminUser_username')" prop="username">
<el-input v-model="userInfos.username" :placeholder="$t('adminUser_username')" autocomplete="off" type="text" /> <el-input v-model="userInfos.username" :placeholder="$t('adminUser_username')" autocomplete="off" disabled type="text" />
</el-form-item> </el-form-item>
<!-- 昵称 --> <!-- 昵称 -->
<el-form-item :label="$t('adminUser_nickName')" prop="nickName"> <el-form-item :label="$t('adminUser_nickname')" prop="nickname">
<el-input v-model="userInfos.nickName" :placeholder="$t('adminUser_nickName')" autocomplete="off" type="text" /> <el-input v-model="userInfos.nickname" :placeholder="$t('adminUser_nickname')" autocomplete="off" type="text" />
</el-form-item> </el-form-item>
<!-- 邮箱 --> <!-- 邮箱 -->

View File

@ -13,8 +13,8 @@ export const columns: TableColumnList = [
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 }, { type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
// 用户名 // 用户名
{ label: $t('userLoginLog_username'), prop: 'username', width: 180 }, { label: $t('userLoginLog_username'), prop: 'username', width: 180 },
// // 登录Ip // 登录Ip
// { label: $t('userLoginLog_ipAddress'), prop: 'ipAddress', width: 140 }, { label: $t('userLoginLog_ipAddress'), prop: 'ipAddress', width: 140 },
// 登录Ip归属地 // 登录Ip归属地
{ label: $t('userLoginLog_ipRegion'), prop: 'ipRegion' }, { label: $t('userLoginLog_ipRegion'), prop: 'ipRegion' },
// // 登录时代理 // // 登录时代理
@ -35,8 +35,7 @@ export const columns: TableColumnList = [
// 修改用户信息规则校验 // 修改用户信息规则校验
export const rules = reactive<FormRules<any>>({ export const rules = reactive<FormRules<any>>({
username: [{ required: true, message: '昵称必填', trigger: 'blur' }], nickname: [{ required: true, message: '昵称必填', trigger: 'blur' }],
nickName: [{ required: true, message: '昵称必填', trigger: 'blur' }],
email: [{ required: true, message: '昵称必填', trigger: 'blur' }], email: [{ required: true, message: '昵称必填', trigger: 'blur' }],
}); });

View File

@ -12,7 +12,6 @@ export const uploadAvatarSrc = ref();
// 剪裁头像是否显示 // 剪裁头像是否显示
export const isShow = ref(false); export const isShow = ref(false);
const userStore = useUserStore(); const userStore = useUserStore();
// 用户信息内容 // 用户信息内容
@ -23,7 +22,7 @@ export const userInfos = reactive({
email: '', email: '',
phone: '', phone: '',
summary: '', summary: '',
nickName: '', nickname: '',
password: '', password: '',
sex: '', sex: '',
}); });
@ -31,7 +30,15 @@ export const userInfos = reactive({
/** 获取用户信息内容 */ /** 获取用户信息内容 */
export const onSearchByUserinfo = async () => { export const onSearchByUserinfo = async () => {
const data = await userStore.getUserinfo(); const data = await userStore.getUserinfo();
Object.assign(userInfos, data); userInfos.summary = data.personDescription;
userInfos.avatar = data.avatar;
userInfos.username = data.username;
userInfos.nickname = data.nickname;
userInfos.email = data.email;
userInfos.phone = data.phone;
userInfos.nickname = data.nickname;
userInfos.password = data.password;
userInfos.sex = data.sex;
}; };
/** 修改头像 */ /** 修改头像 */

View File

@ -2,22 +2,20 @@
import Motion from './utils/motion'; import Motion from './utils/motion';
import { useNav } from '@/layout/hooks/useNav'; import { useNav } from '@/layout/hooks/useNav';
import { useLayout } from '@/layout/hooks/useLayout'; import { useLayout } from '@/layout/hooks/useLayout';
import { avatar, bg, illustration } from './utils/static'; import bg from '@/assets/login/bg.png';
import avatar from '@/assets/login/avatar.svg?component';
import illustration from '@/assets/login/illustration.svg?component';
import { onMounted, toRaw } from 'vue'; import { onMounted, toRaw } from 'vue';
import { useTranslationLang } from '@/layout/hooks/useTranslationLang'; import { useTranslationLang } from '@/layout/hooks/useTranslationLang';
import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange'; import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange';
import dayIcon from '@/assets/svg/day.svg?component'; import dayIcon from '@/assets/svg/day.svg?component';
import darkIcon from '@/assets/svg/dark.svg?component'; import darkIcon from '@/assets/svg/dark.svg?component';
import globalization from '@/assets/svg/globalization.svg?component'; import globalization from '@/assets/svg/globalization.svg?component';
import Check from '@iconify-icons/ep/check'; import Check from '@iconify-icons/ep/check';
import LoginForm from '@/views/login/login-form.vue'; import LoginForm from '@/views/login/login-form.vue';
import LoginEmail from '@/views/login/login-email.vue';
import { userI18nTypeStore } from '@/store/i18n/i18nType'; import { userI18nTypeStore } from '@/store/i18n/i18nType';
import { currentPage } from '@/views/login/utils/hooks';
defineOptions({
name: 'Login',
});
const { initStorage } = useLayout(); const { initStorage } = useLayout();
initStorage(); initStorage();
@ -73,7 +71,8 @@ onMounted(() => {
</Motion> </Motion>
<!-- 登录表单 --> <!-- 登录表单 -->
<login-form /> <login-form v-if="currentPage === 0" />
<login-email v-if="currentPage === 1" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,155 @@
<script lang="ts" setup>
import { emailRules } from '@/views/login/utils/rule';
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
import User from '@iconify-icons/ri/user-3-fill';
import Lock from '@iconify-icons/ri/lock-fill';
import { onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useUserStore } from '@/store/system/user';
import { message } from '@/utils/message';
import { getTopMenu, initRouter } from '@/router/utils';
import Motion from './utils/motion';
import { ElMessage, FormInstance } from 'element-plus';
import { onBack } from '@/views/login/utils/hooks';
const router = useRouter();
const userStore = useUserStore();
const ruleFormRef = ref<FormInstance>();
const loading = ref(false);
const sendSecond = ref(60);
const timer = ref(null);
const { t } = useI18n();
const ruleForm = reactive({
username: '1319900154@qq.com',
password: 'admin123',
emailCode: '1',
});
/**
* * 发送邮箱验证码
*/
const onSendEmailCode = async () => {
//
if (ruleForm.username === '' || ruleForm.username === void 0) {
message('请先填写邮箱地址', { type: 'warning' });
return false;
}
const result = await userStore.postEmailCode(ruleForm.username);
if (result) {
//
onSendEmailTimer();
}
};
/**
* * 发送邮箱倒计时点击
*/
const onSendEmailTimer = () => {
//
timer.value = setInterval(() => {
// 0
if (sendSecond.value <= 0) {
clearInterval(timer.value);
timer.value = null;
sendSecond.value = 60;
return;
}
//
sendSecond.value--;
}, 1000);
};
/**
* 登录
* @param formEl
*/
const onLogin = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
loading.value = true;
//
await formEl.validate(async valid => {
if (valid) {
const result = await userStore.loginByUsername(ruleForm);
if (result) {
//
await initRouter();
router.push(getTopMenu(true).path).then(() => {
ElMessage.closeAll();
message(t('login.loginSuccess'), { type: 'success' });
});
}
}
});
loading.value = false;
};
/** 使用公共函数,避免`removeEventListener`失效 */
function onkeypress({ code }: KeyboardEvent) {
if (['Enter', 'NumpadEnter'].includes(code)) {
onLogin(ruleFormRef.value);
}
}
onMounted(() => {
window.document.addEventListener('keypress', onkeypress);
});
onBeforeUnmount(() => {
window.document.removeEventListener('keypress', onkeypress);
});
</script>
<template>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="emailRules" size="large">
<Motion :delay="100">
<el-form-item prop="username">
<el-input v-model="ruleForm.username" :placeholder="t('login.username')" :prefix-icon="useRenderIcon(User)" clearable />
</el-form-item>
</Motion>
<Motion :delay="150">
<el-form-item prop="password">
<el-input v-model="ruleForm.password" :placeholder="t('login.password')" :prefix-icon="useRenderIcon(Lock)" clearable show-password />
</el-form-item>
</Motion>
<Motion :delay="150">
<el-form-item prop="emailCode">
<el-input v-model="ruleForm.emailCode" :placeholder="t('login.emailCode')" :prefix-icon="useRenderIcon('ic:outline-email')" clearable @keydown.enter="onLogin(ruleFormRef)">
<template v-slot:append>
<el-link v-if="sendSecond === 60" :underline="false" class="px-2" type="primary" @click="onSendEmailCode">
{{ t('login.getEmailCode') }}
</el-link>
<el-link v-else :underline="false" class="px-2" type="primary">
{{ sendSecond }}
{{ t('login.getCodeInfo') }}
</el-link>
</template>
</el-input>
<el-checkbox v-model="userStore.isRemembered">
<el-text size="small" type="primary">{{ userStore.readMeDay }}天免登录(邮箱验证码随便输入,后端校验验证码已注释) </el-text>
</el-checkbox>
</el-form-item>
</Motion>
<Motion :delay="250">
<el-button :loading="loading" class="w-full" size="default" type="primary" @click="onLogin(ruleFormRef)">
{{ t('login.login') }}
</el-button>
</Motion>
<Motion :delay="200">
<el-form-item>
<el-button class="w-full mt-4" size="default" @click="onBack">
{{ t('login.pureBack') }}
</el-button>
</el-form-item>
</Motion>
</el-form>
</template>

View File

@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import { loginRules } from '@/views/login/utils/rule';
import { useRenderIcon } from '@/components/CommonIcon/src/hooks'; import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
import User from '@iconify-icons/ri/user-3-fill'; import User from '@iconify-icons/ri/user-3-fill';
import Lock from '@iconify-icons/ri/lock-fill'; import Lock from '@iconify-icons/ri/lock-fill';
@ -11,56 +10,20 @@ import { message } from '@/utils/message';
import { getTopMenu, initRouter } from '@/router/utils'; import { getTopMenu, initRouter } from '@/router/utils';
import Motion from './utils/motion'; import Motion from './utils/motion';
import { ElMessage, FormInstance } from 'element-plus'; import { ElMessage, FormInstance } from 'element-plus';
import { currentPage } from '@/views/login/utils/hooks';
import { formRules } from '@/views/login/utils/rule';
const router = useRouter(); const router = useRouter();
const userStore = useUserStore(); const userStore = useUserStore();
const ruleFormRef = ref<FormInstance>(); const ruleFormRef = ref<FormInstance>();
const loading = ref(false); const loading = ref(false);
const sendSecond = ref(60);
const timer = ref(null);
const { t } = useI18n(); const { t } = useI18n();
const ruleForm = reactive({ const ruleForm = reactive({
username: '1319900154@qq.com', username: 'bunny',
password: 'admin123', password: 'admin123',
emailCode: '1',
}); });
/**
* * 发送邮箱验证码
*/
const onSendEmailCode = async () => {
//
if (ruleForm.username === '' || ruleForm.username === void 0) {
message('请先填写邮箱地址', { type: 'warning' });
return false;
}
const result = await userStore.postEmailCode(ruleForm.username);
if (result) {
//
onSendEmailTimer();
}
};
/**
* * 发送邮箱倒计时点击
*/
const onSendEmailTimer = () => {
//
timer.value = setInterval(() => {
// 0
if (sendSecond.value <= 0) {
clearInterval(timer.value);
timer.value = null;
sendSecond.value = 60;
return;
}
//
sendSecond.value--;
}, 1000);
};
/** /**
* 登录 * 登录
* @param formEl * @param formEl
@ -103,8 +66,8 @@ onBeforeUnmount(() => {
</script> </script>
<template> <template>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="loginRules" size="large"> <el-form ref="ruleFormRef" :model="ruleForm" :rules="formRules" size="large">
<Motion :delay="100"> <Motion>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="ruleForm.username" :placeholder="t('login.username')" :prefix-icon="useRenderIcon(User)" clearable /> <el-input v-model="ruleForm.username" :placeholder="t('login.username')" :prefix-icon="useRenderIcon(User)" clearable />
</el-form-item> </el-form-item>
@ -113,32 +76,25 @@ onBeforeUnmount(() => {
<Motion :delay="150"> <Motion :delay="150">
<el-form-item prop="password"> <el-form-item prop="password">
<el-input v-model="ruleForm.password" :placeholder="t('login.password')" :prefix-icon="useRenderIcon(Lock)" clearable show-password /> <el-input v-model="ruleForm.password" :placeholder="t('login.password')" :prefix-icon="useRenderIcon(Lock)" clearable show-password />
</el-form-item>
</Motion>
<Motion :delay="150">
<el-form-item prop="emailCode">
<el-input v-model="ruleForm.emailCode" :placeholder="t('login.emailCode')" :prefix-icon="useRenderIcon('ic:outline-email')" clearable @keydown.enter="onLogin(ruleFormRef)">
<template v-slot:append>
<el-link v-if="sendSecond === 60" :underline="false" class="px-2" type="primary" @click="onSendEmailCode">
{{ t('login.getEmailCode') }}
</el-link>
<el-link v-else :underline="false" class="px-2" type="primary">
{{ sendSecond }}
{{ t('login.getCodeInfo') }}
</el-link>
</template>
</el-input>
<el-checkbox v-model="userStore.isRemembered"> <el-checkbox v-model="userStore.isRemembered">
<el-text size="small" type="primary">{{ userStore.readMeDay }}天免登录(邮箱验证码随便输入,后端校验验证码已注释) </el-text> <el-text size="small" type="primary">{{ userStore.readMeDay }}天免登录(邮箱验证码随便输入,后端校验验证码已注释) </el-text>
</el-checkbox> </el-checkbox>
</el-form-item> </el-form-item>
</Motion> </Motion>
<Motion :delay="250"> <Motion :delay="150">
<el-button :loading="loading" class="w-full mt-4" size="default" type="primary" @click="onLogin(ruleFormRef)"> <el-form-item>
{{ t('login.login') }} <el-button :loading="loading" class="w-full" size="default" type="primary" @click="onLogin(ruleFormRef)">
</el-button> {{ t('login.login') }}
</el-button>
</el-form-item>
</Motion>
<!-- 邮箱登录 -->
<Motion :delay="300">
<el-form-item>
<el-button class="w-full" size="default" @click="currentPage = 1"> 邮箱登录</el-button>
</el-form-item>
</Motion> </Motion>
</el-form> </el-form>
</template> </template>

View File

@ -0,0 +1,9 @@
import { ref } from 'vue';
// 0普通登录1邮箱登录其中0为普通登录
export const currentPage = ref(0);
/** 返回到默认登录页面 */
export const onBack = () => {
currentPage.value = 0;
};

View File

@ -5,8 +5,8 @@ import { $t } from '@/plugins/i18n';
/** 密码正则密码格式应为8-18位数字、字母、符号的任意两种组合 */ /** 密码正则密码格式应为8-18位数字、字母、符号的任意两种组合 */
export const REGEXP_PWD = /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/; export const REGEXP_PWD = /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/;
/** 登录校验 */ /** 邮箱登录校验 */
const loginRules = reactive(<FormRules>{ export const emailRules = reactive(<FormRules>{
username: [{ required: true, message: $t('login.usernameRegex'), trigger: 'blur' }], username: [{ required: true, message: $t('login.usernameRegex'), trigger: 'blur' }],
password: [ password: [
{ {
@ -25,4 +25,21 @@ const loginRules = reactive(<FormRules>{
emailCode: [{ required: true, trigger: 'blur', type: 'string' }], emailCode: [{ required: true, trigger: 'blur', type: 'string' }],
}); });
export { loginRules }; /** 登录校验 */
export const formRules = reactive(<FormRules>{
username: [{ required: true, message: $t('login.usernameRegex'), trigger: 'blur' }],
password: [
{
validator: (rule, value, callback) => {
if (value === '') {
callback(new Error($t('login.purePassWordReg')));
} else if (!REGEXP_PWD.test(value)) {
callback(new Error($t('login.purePassWordRuleReg')));
} else {
callback();
}
},
trigger: 'blur',
},
],
});

View File

@ -1,5 +0,0 @@
import bg from '@/assets/login/bg.png';
import avatar from '@/assets/login/avatar.svg?component';
import illustration from '@/assets/login/illustration.svg?component';
export { bg, avatar, illustration };

View File

@ -15,7 +15,7 @@ const props = withDefaults(defineProps<FormProps>(), {
// //
username: undefined, username: undefined,
// //
nickName: undefined, nickname: undefined,
// //
email: undefined, email: undefined,
// //
@ -55,8 +55,8 @@ defineExpose({ formRef });
<!-- 昵称 --> <!-- 昵称 -->
<re-col :sm="24" :value="12" :xs="24"> <re-col :sm="24" :value="12" :xs="24">
<el-form-item :label="$t('adminUser_nickName')" prop="nickName"> <el-form-item :label="$t('adminUser_nickname')" prop="nickname">
<el-input v-model="form.nickName" :placeholder="$t('adminUser_nickName')" autocomplete="off" type="text" /> <el-input v-model="form.nickname" :placeholder="$t('adminUser_nickname')" autocomplete="off" type="text" />
</el-form-item> </el-form-item>
</re-col> </re-col>

View File

@ -96,8 +96,8 @@ onMounted(() => {
</el-form-item> </el-form-item>
<!-- 查询昵称 --> <!-- 查询昵称 -->
<el-form-item :label="$t('adminUser_nickName')" prop="nickName"> <el-form-item :label="$t('adminUser_nickname')" prop="nickname">
<el-input v-model="adminUserStore.form.nickName" :placeholder="`${$t('input')}${$t('adminUser_nickName')}`" class="!w-[180px]" clearable /> <el-input v-model="adminUserStore.form.nickname" :placeholder="`${$t('input')}${$t('adminUser_nickname')}`" class="!w-[180px]" clearable />
</el-form-item> </el-form-item>
<!-- 查询邮箱 --> <!-- 查询邮箱 -->

View File

@ -13,7 +13,7 @@ export const columns: TableColumnList = [
// 状态 // 状态
{ label: $t('adminUser_status'), prop: 'status', slot: 'status' }, { label: $t('adminUser_status'), prop: 'status', slot: 'status' },
// 昵称 // 昵称
{ label: $t('adminUser_nickName'), prop: 'nickName', width: 260 }, { label: $t('adminUser_nickname'), prop: 'nickname', width: 260 },
// 邮箱 // 邮箱
{ label: $t('adminUser_email'), prop: 'email', width: 260 }, { label: $t('adminUser_email'), prop: 'email', width: 260 },
// 手机号 // 手机号

View File

@ -59,7 +59,7 @@ export function onAdd() {
props: { props: {
formInline: { formInline: {
username: undefined, username: undefined,
nickName: undefined, nickname: undefined,
email: undefined, email: undefined,
phone: undefined, phone: undefined,
password: undefined, password: undefined,
@ -100,7 +100,7 @@ export function onUpdate(row: any) {
props: { props: {
formInline: { formInline: {
username: row.username, username: row.username,
nickName: row.nickName, nickname: row.nickname,
email: row.email, email: row.email,
phone: row.phone, phone: row.phone,
password: row.password, password: row.password,

View File

@ -3,7 +3,7 @@ export interface FormItemProps {
// 用户名 // 用户名
username: string; username: string;
// 昵称 // 昵称
nickName: string; nickname: string;
// 邮箱 // 邮箱
email: string; email: string;
// 手机号 // 手机号

View File

@ -6,6 +6,7 @@ import { $t } from '@/plugins/i18n';
const props = defineProps({ const props = defineProps({
routerId: { type: String as PropType<String> }, routerId: { type: String as PropType<String> },
warning: { type: String as PropType<String> },
}); });
const roleStore = useRoleStore(); const roleStore = useRoleStore();
@ -36,7 +37,8 @@ defineExpose({ assignRoles });
</script> </script>
<template> <template>
<div class="flex justify-center"> <div class="flex flex-col items-center">
<el-text v-show="warning" class="mx-1" type="warning">{{ warning }}</el-text>
<el-transfer <el-transfer
v-model="assignRoles" v-model="assignRoles"
:button-texts="[$t('take_back'), $t('add')]" :button-texts="[$t('take_back'), $t('add')]"

View File

@ -1,6 +1,6 @@
import editForm from '../menu-dialog.vue'; import editForm from '../menu-dialog.vue';
import { $t } from '@/plugins/i18n'; import { $t } from '@/plugins/i18n';
import { addDialog } from '@/components/BaseDialog/index'; import { addDialog, closeAllDialog } from '@/components/BaseDialog/index';
import { h, ref } from 'vue'; import { h, ref } from 'vue';
import type { FormItemProps } from './types'; import type { FormItemProps } from './types';
import { cloneDeep, deviceDetection } from '@pureadmin/utils'; import { cloneDeep, deviceDetection } from '@pureadmin/utils';
@ -8,6 +8,7 @@ import { userMenuStore } from '@/store/system/menu';
import AssignRouterToRole from '@/views/system/menu/assign-router-to-role.vue'; import AssignRouterToRole from '@/views/system/menu/assign-router-to-role.vue';
import { messageBox } from '@/utils/message'; import { messageBox } from '@/utils/message';
import { formatHigherMenuOptions } from '@/views/system/menu/utils/columns'; import { formatHigherMenuOptions } from '@/views/system/menu/utils/columns';
import { ElText } from 'element-plus';
// 用户是否停用加载集合 // 用户是否停用加载集合
export const switchLoadMap = ref({}); export const switchLoadMap = ref({});
@ -234,6 +235,7 @@ export const assignBatchRolesToRouter = () => {
draggable: true, draggable: true,
closeOnClickModal: false, closeOnClickModal: false,
fullscreenIcon: true, fullscreenIcon: true,
props: { warning: $t('assignBatchRolesToRouterTip') },
contentRenderer: () => <AssignRouterToRole ref={assignRouterToRolesRef} />, contentRenderer: () => <AssignRouterToRole ref={assignRouterToRolesRef} />,
beforeSure: async (done: any) => { beforeSure: async (done: any) => {
// 表格功能 // 表格功能
@ -253,23 +255,34 @@ export const assignBatchRolesToRouter = () => {
/** 清除选中所以角色 */ /** 清除选中所以角色 */
export const clearAllRolesSelect = async () => { export const clearAllRolesSelect = async () => {
// 表格功能 addDialog({
const { clearSelection } = tableRef.value.getTableRef();
const confirm = await messageBox({
title: $t('batchUpdates'), title: $t('batchUpdates'),
showMessage: false, width: '35%',
confirmMessage: undefined, draggable: true,
cancelMessage: $t('cancel'), closeOnClickModal: false,
fullscreenIcon: true,
contentRenderer: () => <ElText type={'warning'}>{$t('clearAllRolesSelectTip')}</ElText>,
beforeSure: async () => {
// 表格功能
const { clearSelection } = tableRef.value.getTableRef();
addDialog({
title: $t('doubleCheck'),
width: '30%',
draggable: true,
closeOnClickModal: false,
fullscreenIcon: true,
contentRenderer: () => <ElText type={'warning'}>{$t('clearAllRolesSelectTip')}</ElText>,
beforeSure: async () => {
// 清除所有角色
const result = await menuStore.clearAllRolesSelect(selectIds.value);
// 更新成功关闭弹窗
if (!result) return;
clearSelection();
closeAllDialog();
},
});
},
}); });
// 取消修改
if (!confirm) return;
// 分配用户角色
const result = await menuStore.clearAllRolesSelect(selectIds.value);
// 更新成功关闭弹窗
if (!result) return;
clearSelection();
}; };