登录功能
This commit is contained in:
parent
3249880b0f
commit
31a2e46d4b
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "vue-next-admin-template-js",
|
"name": "vordm",
|
||||||
"version": "2.4.32",
|
"version": "2.4.32",
|
||||||
"description": "vue3 vite next admin template js setup",
|
"description": "vue3 vite next admin template js setup",
|
||||||
"author": "lyt_20201208",
|
"author": "lyt_20201208",
|
||||||
|
@ -15,16 +15,17 @@
|
||||||
"echarts": "^5.4.2",
|
"echarts": "^5.4.2",
|
||||||
"element-plus": "^2.3.1",
|
"element-plus": "^2.3.1",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
|
"js-md5": "^0.7.3",
|
||||||
"mitt": "^3.0.0",
|
"mitt": "^3.0.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^2.0.33",
|
||||||
"qrcodejs2-fixes": "^0.0.2",
|
"qrcodejs2-fixes": "^0.0.2",
|
||||||
|
"qs": "^6.11.1",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-demi": "^0.13.11",
|
"vue-demi": "^0.13.11",
|
||||||
"qs": "^6.11.1",
|
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import request from '/@/utils/request';
|
import request from '/@/utils/request';
|
||||||
|
import qs from 'qs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (不建议写成 request.post(xxx),因为这样 post 时,无法 params 与 data 同时传参)
|
* (不建议写成 request.post(xxx),因为这样 post 时,无法 params 与 data 同时传参)
|
||||||
|
@ -9,14 +10,14 @@ import request from '/@/utils/request';
|
||||||
*/
|
*/
|
||||||
export function useLoginApi() {
|
export function useLoginApi() {
|
||||||
return {
|
return {
|
||||||
signInByUsername: ({tenantId, deptId, roleId, username, password, type, key, code}) => {
|
signInByUsername: ({tenantId, deptId, roleId, username, password, type, key, code, grantType}) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/blade-auth/oauth/token',
|
url: '/api/system-manager/oauth/token',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Tenant-Id': tenantId,
|
'Tenant-Id': tenantId,
|
||||||
'Dept-Id': '',
|
'Dept-Id': deptId,
|
||||||
'Role-Id': '',
|
'Role-Id': roleId,
|
||||||
'Captcha-Key': key,
|
'Captcha-Key': key,
|
||||||
'Captcha-Code': code,
|
'Captcha-Code': code,
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
@ -25,7 +26,7 @@ export function useLoginApi() {
|
||||||
tenantId,
|
tenantId,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
grant_type: "captcha",
|
grant_type: grantType,
|
||||||
deptId,
|
deptId,
|
||||||
roleId,
|
roleId,
|
||||||
scope: "all",
|
scope: "all",
|
||||||
|
@ -34,6 +35,12 @@ export function useLoginApi() {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//获取验证码
|
||||||
|
getCaptcha: () => request({
|
||||||
|
url: '/api/system-manager/oauth/captcha',
|
||||||
|
method: 'get',
|
||||||
|
}),
|
||||||
|
|
||||||
signOut: (data) => {
|
signOut: (data) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/signOut',
|
url: '/user/signOut',
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import request from '/@/utils/request';
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
|
export const getUserInfo = () => {
|
||||||
|
return request({
|
||||||
|
url: '/api/system-manager/user/info',
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resetPassword = (userIds) => {
|
||||||
|
return request({
|
||||||
|
url: '/api/system-manager/user/reset-password',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
userIds,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updatePassword = (oldPassword, newPassword, newPassword1) => {
|
||||||
|
return request({
|
||||||
|
url: '/api/system-manager/user/update-password',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
oldPassword,
|
||||||
|
newPassword,
|
||||||
|
newPassword1,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getButtons = () => request({
|
||||||
|
url: '/api/system-manager/menu/buttons',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
|
||||||
|
export const refreshToken = (refresh_token, tenantId) => request({
|
||||||
|
url: '/api/system-manager/oauth/token',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Tenant-Id': tenantId,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
data: qs.stringify({
|
||||||
|
tenantId,
|
||||||
|
refresh_token,
|
||||||
|
grant_type: "refresh_token",
|
||||||
|
scope: "all",
|
||||||
|
})
|
||||||
|
});
|
|
@ -73,7 +73,7 @@ import { useUserInfo } from '/@/stores/userInfo';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
import mittBus from '/@/utils/mitt';
|
import mittBus from '/@/utils/mitt';
|
||||||
import { Session, Local } from '/@/utils/storage';
|
import { Session, Local } from '/@/utils/storage';
|
||||||
|
import { refreshToken } from '/@/api/system/user.js'
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue'));
|
const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue'));
|
||||||
const Search = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/search.vue'));
|
const Search = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/search.vue'));
|
||||||
|
@ -83,11 +83,13 @@ const router = useRouter();
|
||||||
const stores = useUserInfo();
|
const stores = useUserInfo();
|
||||||
const storesThemeConfig = useThemeConfig();
|
const storesThemeConfig = useThemeConfig();
|
||||||
const { userInfos } = storeToRefs(stores);
|
const { userInfos } = storeToRefs(stores);
|
||||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
const { themeConfig, website } = storeToRefs(storesThemeConfig);
|
||||||
|
|
||||||
const searchRef = ref();
|
const searchRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isScreenfull: false,
|
isScreenfull: false,
|
||||||
disabledSize: 'large',
|
disabledSize: 'large',
|
||||||
|
setIntervalId: null
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置分割样式
|
// 设置分割样式
|
||||||
|
@ -145,6 +147,7 @@ const onHandleCommandClick = (path) => {
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// 清除缓存/token等
|
// 清除缓存/token等
|
||||||
Session.clear();
|
Session.clear();
|
||||||
|
clearInterval(state.setIntervalId);
|
||||||
// 使用 reload 时,不需要调用 resetRoute() 重置路由
|
// 使用 reload 时,不需要调用 resetRoute() 重置路由
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
})
|
})
|
||||||
|
@ -176,6 +179,20 @@ onMounted(() => {
|
||||||
if (Local.get('themeConfig')) {
|
if (Local.get('themeConfig')) {
|
||||||
initI18nOrSize('globalComponentSize', 'disabledSize');
|
initI18nOrSize('globalComponentSize', 'disabledSize');
|
||||||
}
|
}
|
||||||
|
//刷新token
|
||||||
|
state.setIntervalId =setInterval(() => {
|
||||||
|
const dateTime = Session.get('token-time');
|
||||||
|
const rt = Session.get('refresh-token');
|
||||||
|
const now = new Date().getTime();
|
||||||
|
if((now - dateTime) / 1000 > website.value.tokenTime){
|
||||||
|
// 刷新token
|
||||||
|
refreshToken(rt, website.value.tenantId).then(res=>{
|
||||||
|
Session.set('token', res.access_token);
|
||||||
|
Session.set('token-time', new Date().getTime());
|
||||||
|
Session.set('refresh-token', res.refresh_token);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},10000);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@ import { defineStore } from 'pinia';
|
||||||
*/
|
*/
|
||||||
export const useThemeConfig = defineStore('themeConfig', {
|
export const useThemeConfig = defineStore('themeConfig', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
website: {
|
||||||
|
// 开启验证码模式
|
||||||
|
captchaMode: false,
|
||||||
|
tokenTime: 3000,
|
||||||
|
tenantId: '595035'
|
||||||
|
},
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
// 是否开启布局配置抽屉
|
// 是否开启布局配置抽屉
|
||||||
isDrawer: false,
|
isDrawer: false,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import Cookies from 'js-cookie';
|
|
||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
|
import { getUserInfo, getButtons } from '/@/api/system/user.js'
|
||||||
/**
|
/**
|
||||||
* 用户信息
|
* 用户信息
|
||||||
* @methods setUserInfos 设置用户信息
|
* @methods setUserInfos 设置用户信息
|
||||||
|
@ -26,47 +25,67 @@ export const useUserInfo = defineStore('userInfo', {
|
||||||
this.userInfos = userInfos;
|
this.userInfos = userInfos;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async Buttons() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
getButtons().then(data => {
|
||||||
|
console.log(data)
|
||||||
|
resolve(this.formatBtns(data));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
formatBtns(data) {
|
||||||
|
let map = [];
|
||||||
|
data.forEach(item => {
|
||||||
|
map.push(item.code)
|
||||||
|
//判断是否存在子菜单
|
||||||
|
if (item.children) {
|
||||||
|
map = map.concat(this.formatBtns(item.children));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return map;
|
||||||
|
},
|
||||||
// 模拟接口数据
|
// 模拟接口数据
|
||||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
||||||
async getApiUserInfo() {
|
async getApiUserInfo() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
// 获取用户信息
|
||||||
// 模拟数据,请求接口时,记得删除多余代码及对应依赖的引入
|
getUserInfo().then((user) => {
|
||||||
const userName = Cookies.get('userName');
|
const arr = [];
|
||||||
// 模拟数据
|
arr.push(user.roleName);
|
||||||
let defaultRoles = [];
|
|
||||||
let defaultAuthBtnList = [];
|
|
||||||
// admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
|
|
||||||
let adminRoles = ['admin'];
|
|
||||||
// admin 按钮权限标识
|
|
||||||
let adminAuthBtnList = ['btn.add', 'btn.del', 'btn.edit', 'btn.link'];
|
|
||||||
// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
|
|
||||||
let testRoles = ['common'];
|
|
||||||
// test 按钮权限标识
|
|
||||||
let testAuthBtnList = ['btn.add', 'btn.link'];
|
|
||||||
// 不同用户模拟不同的用户权限
|
|
||||||
if (userName === 'admin') {
|
|
||||||
defaultRoles = adminRoles;
|
|
||||||
defaultAuthBtnList = adminAuthBtnList;
|
|
||||||
} else {
|
|
||||||
defaultRoles = testRoles;
|
|
||||||
defaultAuthBtnList = testAuthBtnList;
|
|
||||||
}
|
|
||||||
// 用户信息模拟数据
|
|
||||||
const userInfos = {
|
const userInfos = {
|
||||||
userName: userName,
|
userName: user.account,
|
||||||
photo:
|
photo: user.account === 'admin'
|
||||||
userName === 'admin'
|
|
||||||
? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
|
? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
|
||||||
: 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
|
: 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
|
||||||
time: new Date().getTime(),
|
time: new Date().getTime(),
|
||||||
roles: defaultRoles,
|
roles: arr,
|
||||||
authBtnList: defaultAuthBtnList,
|
authBtnList: [],
|
||||||
|
...user
|
||||||
};
|
};
|
||||||
|
// 存储用户信息到浏览器缓存
|
||||||
Session.set('userInfo', userInfos);
|
Session.set('userInfo', userInfos);
|
||||||
resolve(userInfos);
|
resolve(userInfos)
|
||||||
}, 0);
|
// 获取权限按钮
|
||||||
|
// this.Buttons().then((res2) => {
|
||||||
|
// // 用户信息模拟数据
|
||||||
|
// const userInfos = {
|
||||||
|
// userName: user.account,
|
||||||
|
// photo: user.account === 'admin'
|
||||||
|
// ? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
|
||||||
|
// : 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
|
||||||
|
// time: new Date().getTime(),
|
||||||
|
// roles: arr,
|
||||||
|
// authBtnList: res2,
|
||||||
|
// ...user
|
||||||
|
// };
|
||||||
|
// // 存储用户信息到浏览器缓存
|
||||||
|
// Session.set('userInfo', userInfos);
|
||||||
|
// resolve(userInfos)
|
||||||
|
// })
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,9 +18,10 @@ const service = axios.create({
|
||||||
// 添加请求拦截器
|
// 添加请求拦截器
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
|
config.headers['Authorization'] = 'Basic Vm9SRE1BZG1pbjp2b3JkbV9hZG1pbl9zZWNyZXQ=';
|
||||||
// 在发送请求之前做些什么 token
|
// 在发送请求之前做些什么 token
|
||||||
if (Session.get('token')) {
|
if (Session.get('token')) {
|
||||||
config.headers['Authorization'] = `${Session.get('token')}`;
|
config.headers['Blade-Auth'] = `Bearer ${Session.get('token')}`;
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
@ -35,7 +36,7 @@ service.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
// 对响应数据做点什么
|
// 对响应数据做点什么
|
||||||
const res = response.data;
|
const res = response.data;
|
||||||
if (res.code && res.code !== 0) {
|
if (res.code && res.code !== 200) {
|
||||||
// `token` 过期或者账号已在别处登录
|
// `token` 过期或者账号已在别处登录
|
||||||
if (res.code === 401 || res.code === 4001) {
|
if (res.code === 401 || res.code === 4001) {
|
||||||
Session.clear(); // 清除浏览器全部临时缓存
|
Session.clear(); // 清除浏览器全部临时缓存
|
||||||
|
@ -43,10 +44,12 @@ service.interceptors.response.use(
|
||||||
ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
|
ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
|
} else if(res.code === 400){
|
||||||
|
ElMessage.error(res.msg)
|
||||||
}
|
}
|
||||||
return Promise.reject(service.interceptors.response);
|
return Promise.reject(service.interceptors.response);
|
||||||
} else {
|
} else {
|
||||||
return res;
|
return res.data || res;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
@ -56,7 +59,8 @@ service.interceptors.response.use(
|
||||||
} else if (error.message == 'Network Error') {
|
} else if (error.message == 'Network Error') {
|
||||||
ElMessage.error('网络连接错误');
|
ElMessage.error('网络连接错误');
|
||||||
} else {
|
} else {
|
||||||
if (error.response.data) ElMessage.error(error.response.statusText);
|
if( error.response.data.error_description ) ElMessage.error(error.response.data.error_description);
|
||||||
|
//if (error.response.data) ElMessage.error(error.response.statusText);
|
||||||
else ElMessage.error('接口路径找不到');
|
else ElMessage.error('接口路径找不到');
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form size="large" class="login-content-form">
|
<el-form size="large" class="login-content-form">
|
||||||
<el-form-item class="login-animation1">
|
<el-form-item class="login-animation1">
|
||||||
<el-input text placeholder="用户名 admin 或不输均为 common" v-model="state.ruleForm.userName" clearable autocomplete="off">
|
<el-input text placeholder="Please input username or email" v-model="state.ruleForm.userName" clearable autocomplete="off">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon class="el-input__icon"><ele-User /></el-icon>
|
<el-icon class="el-input__icon"><ele-User /></el-icon>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="login-animation2">
|
<el-form-item class="login-animation2">
|
||||||
<el-input :type="state.isShowPassword ? 'text' : 'password'" placeholder="密码:123456" v-model="state.ruleForm.password" autocomplete="off">
|
<el-input :type="state.isShowPassword ? 'text' : 'password'" placeholder="Please input password" v-model="state.ruleForm.password" autocomplete="off">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
||||||
</template>
|
</template>
|
||||||
|
@ -22,32 +22,34 @@
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="login-animation3">
|
<el-form-item class="login-animation3" v-if="state.captchaMode">
|
||||||
<el-col :span="15">
|
<el-col :span="15">
|
||||||
<el-input text maxlength="4" placeholder="请输入验证码" v-model="state.ruleForm.code" clearable autocomplete="off">
|
<el-input text maxlength="5" placeholder="Please input validate code" v-model="state.ruleForm.code" clearable autocomplete="off">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon class="el-input__icon"><ele-Position /></el-icon>
|
<el-icon class="el-input__icon"><ele-Position /></el-icon>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1"></el-col>
|
<el-col :span="1"></el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8" style="width: 132px; height: 48px;">
|
||||||
<el-button class="login-content-code" v-waves>1234</el-button>
|
<!-- <el-button class="login-content-code" v-waves>1234</el-button> -->
|
||||||
|
<img class="login-content-code-img" alt="" :src="state.captchaUrl" @click="getCaptchaCode" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="login-animation4">
|
<el-form-item class="login-animation4">
|
||||||
<el-button type="primary" class="login-content-submit" round v-waves @click="onSignIn" :loading="state.loading.signIn">
|
<el-button type="primary" class="login-content-submit" round v-waves @click="onSignIn" :loading="state.loading.signIn">
|
||||||
<span>登 录</span>
|
<span>LOGIN</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="loginAccount">
|
<script setup name="loginAccount">
|
||||||
import { reactive, computed } from 'vue';
|
import { reactive, computed, onMounted } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
import md5 from 'js-md5';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
|
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
|
||||||
|
@ -55,53 +57,95 @@ import { initBackEndControlRoutes } from '/@/router/backEnd';
|
||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
import { formatAxis } from '/@/utils/formatTime';
|
import { formatAxis } from '/@/utils/formatTime';
|
||||||
import { NextLoading } from '/@/utils/loading';
|
import { NextLoading } from '/@/utils/loading';
|
||||||
|
import { useLoginApi } from '/@/api/login';
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const storesThemeConfig = useThemeConfig();
|
const storesThemeConfig = useThemeConfig();
|
||||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
const { themeConfig, website } = storeToRefs(storesThemeConfig);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const loginApi = useLoginApi();
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowPassword: false,
|
isShowPassword: false,
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
userName: 'admin',
|
//租户ID
|
||||||
password: '123456',
|
tenantId: website.value.tenantId,
|
||||||
code: '1234',
|
//用户名
|
||||||
|
userName: "",
|
||||||
|
//密码
|
||||||
|
password: "",
|
||||||
|
//账号类型
|
||||||
|
type: "account",
|
||||||
|
//验证码key
|
||||||
|
key: "",
|
||||||
|
//验证码code
|
||||||
|
code: "",
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
signIn: false,
|
signIn: false,
|
||||||
},
|
},
|
||||||
|
captchaMode: website.value.captchaMode,
|
||||||
|
captchaUrl: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getCaptchaCode = async () => {
|
||||||
|
const res = await loginApi.getCaptcha()
|
||||||
|
state.captchaUrl = res.image;
|
||||||
|
state.ruleForm.key = res.key;
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
if(state.captchaMode) {
|
||||||
|
getCaptchaCode();
|
||||||
|
}
|
||||||
|
});
|
||||||
// 时间获取
|
// 时间获取
|
||||||
const currentTime = computed(() => {
|
const currentTime = computed(() => {
|
||||||
return formatAxis(new Date());
|
return formatAxis(new Date());
|
||||||
});
|
});
|
||||||
// 登录
|
// 登录
|
||||||
const onSignIn = async () => {
|
const onSignIn = () => {
|
||||||
state.loading.signIn = true;
|
//判断用户是否输入用户名和密码
|
||||||
// 存储 token 到浏览器缓存
|
if (state.ruleForm.userName === "") {
|
||||||
Session.set('token', Math.random().toString(36).substr(0));
|
ElMessage.error("请输入用户名");
|
||||||
// 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据)
|
return;
|
||||||
Cookies.set('userName', state.ruleForm.userName);
|
|
||||||
if (!themeConfig.value.isRequestRoutes) {
|
|
||||||
// 前端控制路由,2、请注意执行顺序
|
|
||||||
const isNoPower = await initFrontEndControlRoutes();
|
|
||||||
signInSuccess(isNoPower);
|
|
||||||
} else {
|
|
||||||
// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
|
||||||
// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
|
|
||||||
const isNoPower = await initBackEndControlRoutes();
|
|
||||||
// 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
|
||||||
signInSuccess(isNoPower);
|
|
||||||
}
|
}
|
||||||
|
if (state.ruleForm.password === "") {
|
||||||
|
ElMessage.error("请输入密码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.loading.signIn = true;
|
||||||
|
loginApi.signInByUsername({
|
||||||
|
tenantId: state.ruleForm.tenantId,
|
||||||
|
deptId: '',
|
||||||
|
roleId: '',
|
||||||
|
username: state.ruleForm.userName,
|
||||||
|
password: md5(state.ruleForm.password),
|
||||||
|
type: state.ruleForm.type,
|
||||||
|
key: state.ruleForm.key,
|
||||||
|
code: state.ruleForm.code,
|
||||||
|
grantType: state.captchaMode ? "captcha" : "password"
|
||||||
|
}).then((res) => {
|
||||||
|
Session.set('token', res.access_token);
|
||||||
|
Session.set('token-time', new Date().getTime());
|
||||||
|
Session.set('refresh-token', res.refresh_token);
|
||||||
|
if (themeConfig.value.isRequestRoutes) {
|
||||||
|
initBackEndControlRoutes().then(() => {
|
||||||
|
signInSuccess()
|
||||||
|
}).catch(() => {state.loading.signIn = false;});
|
||||||
|
} else {
|
||||||
|
initFrontEndControlRoutes().then(() => {
|
||||||
|
signInSuccess()
|
||||||
|
}).catch(() => {state.loading.signIn = false;});
|
||||||
|
}
|
||||||
|
}).catch(()=>{
|
||||||
|
if(state.captchaMode) {
|
||||||
|
getCaptchaCode()
|
||||||
|
}
|
||||||
|
state.loading.signIn = false;
|
||||||
|
})
|
||||||
};
|
};
|
||||||
// 登录成功后的跳转
|
// 登录成功后的跳转
|
||||||
const signInSuccess = (isNoPower) => {
|
const signInSuccess = () => {
|
||||||
if (isNoPower) {
|
|
||||||
ElMessage.warning('抱歉,您没有登录权限');
|
|
||||||
Session.clear();
|
|
||||||
} else {
|
|
||||||
// 初始化登录成功时间问候语
|
// 初始化登录成功时间问候语
|
||||||
let currentTimeInfo = currentTime.value;
|
let currentTimeInfo = currentTime.value;
|
||||||
// 登录成功,跳到转首页
|
// 登录成功,跳到转首页
|
||||||
|
@ -115,11 +159,10 @@ const signInSuccess = (isNoPower) => {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
// 登录成功提示
|
||||||
const signInText = '欢迎回来!';
|
const signInText = 'Welcome Back!';
|
||||||
ElMessage.success(`${currentTimeInfo},${signInText}`);
|
ElMessage.success(`${currentTimeInfo},${signInText}`);
|
||||||
// 添加 loading,防止第一次进入界面时出现短暂空白
|
// 添加 loading,防止第一次进入界面时出现短暂空白
|
||||||
NextLoading.start();
|
NextLoading.start();
|
||||||
}
|
|
||||||
state.loading.signIn = false;
|
state.loading.signIn = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="login-right-warp-main-form">
|
<div class="login-right-warp-main-form">
|
||||||
<div v-if="!state.isScan">
|
<div v-if="!state.isScan">
|
||||||
<el-tabs v-model="state.tabsActiveName">
|
<el-tabs v-model="state.tabsActiveName">
|
||||||
<el-tab-pane label="账号密码登录" name="account">
|
<el-tab-pane label="Account Login" name="account">
|
||||||
<Account />
|
<Account />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="手机号登录" name="mobile">
|
<el-tab-pane label="手机号登录" name="mobile">
|
||||||
|
|
|
@ -30,7 +30,7 @@ const viteConfig = defineConfig((mode) => {
|
||||||
hmr: true,
|
hmr: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'https://gitee.com',
|
target: 'http://192.168.31.14:9090',
|
||||||
ws: true,
|
ws: true,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
|
|
|
@ -1021,6 +1021,11 @@ js-cookie@^3.0.1:
|
||||||
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414"
|
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414"
|
||||||
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
|
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
|
||||||
|
|
||||||
|
js-md5@^0.7.3:
|
||||||
|
version "0.7.3"
|
||||||
|
resolved "https://registry.npmmirror.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2"
|
||||||
|
integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==
|
||||||
|
|
||||||
js-sdsl@^4.1.4:
|
js-sdsl@^4.1.4:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
|
resolved "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
|
||||||
|
|
Loading…
Reference in New Issue