后台管理 登陆权限问题解决
This commit is contained in:
17
frontend/src/api/user.js
Normal file
17
frontend/src/api/user.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import send_request from '../utils/send_request';
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @returns
|
||||
*/
|
||||
export function userLogin({ username, password }) {
|
||||
return send_request({
|
||||
url: '/user/login',
|
||||
method: 'POST',
|
||||
useQS: true,
|
||||
params: {
|
||||
"username": username,
|
||||
"password": password,
|
||||
}
|
||||
});
|
||||
};
|
@@ -1,47 +1,47 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<!-- 折叠按钮 -->
|
||||
<div class="collapse-btn" @click="collapseChage">
|
||||
<el-icon v-if="sidebar.collapse">
|
||||
<Expand />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<Fold />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="logo">{{ settings.siteFullTitle }}</div>
|
||||
<div class="header-right">
|
||||
<div class="header-user-con">
|
||||
<!-- 消息中心 -->
|
||||
<div class="btn-bell" @click="router.push('/tabs')">
|
||||
<el-tooltip effect="dark" :content="message ? `有${message}条未读消息` : `消息中心`" placement="bottom">
|
||||
<i class="el-icon-lx-notice"></i>
|
||||
</el-tooltip>
|
||||
<span class="btn-bell-badge" v-if="message"></span>
|
||||
</div>
|
||||
<!-- 用户头像 -->
|
||||
<el-avatar class="user-avator" :size="30" :src="imgurl" />
|
||||
<!-- 用户名下拉菜单 -->
|
||||
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
|
||||
<span class="el-dropdown-link">
|
||||
{{ username }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
|
||||
<el-dropdown-item>项目仓库</el-dropdown-item>
|
||||
</a>
|
||||
<el-dropdown-item command="user">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<!-- 折叠按钮 -->
|
||||
<div class="collapse-btn" @click="collapseChage">
|
||||
<el-icon v-if="sidebar.collapse">
|
||||
<Expand />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<Fold />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="logo">{{ settings.siteFullTitle }}</div>
|
||||
<div class="header-right">
|
||||
<div class="header-user-con">
|
||||
<!-- 消息中心 -->
|
||||
<div class="btn-bell" @click="router.push('/tabs')">
|
||||
<el-tooltip effect="dark" :content="message ? `有${message}条未读消息` : `消息中心`" placement="bottom">
|
||||
<i class="el-icon-lx-notice"></i>
|
||||
</el-tooltip>
|
||||
<span class="btn-bell-badge" v-if="message"></span>
|
||||
</div>
|
||||
<!-- 用户头像 -->
|
||||
<el-avatar class="user-avator" :size="30" :src="imgurl" />
|
||||
<!-- 用户名下拉菜单 -->
|
||||
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
|
||||
<span class="el-dropdown-link">
|
||||
{{ username }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
|
||||
<el-dropdown-item>项目仓库</el-dropdown-item>
|
||||
</a>
|
||||
<el-dropdown-item command="user">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
@@ -59,131 +59,131 @@ const message: number = 2;
|
||||
const sidebar = useSidebarStore();
|
||||
// 侧边栏折叠
|
||||
const collapseChage = () => {
|
||||
sidebar.handleCollapse();
|
||||
sidebar.handleCollapse();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 网页打开时不折叠
|
||||
// if (document.body.clientWidth < 1500) {
|
||||
// collapseChage();
|
||||
// }
|
||||
// 网页打开时不折叠
|
||||
// if (document.body.clientWidth < 1500) {
|
||||
// collapseChage();
|
||||
// }
|
||||
});
|
||||
|
||||
// 用户名下拉菜单选择事件
|
||||
const router = useRouter();
|
||||
const handleCommand = (command: string) => {
|
||||
if (command == 'loginout') {
|
||||
// 发送退出登录请求
|
||||
send_request('v1/user/logout', "POST");
|
||||
// 关闭全部标签 (销毁页面对象)
|
||||
const tags = useTagsStore();
|
||||
tags.clearTags();
|
||||
// 清除本地 localStorage
|
||||
localStorage.clear();
|
||||
// localStorage.removeItem('ms_username');
|
||||
// localStorage.removeItem('ms_user_id');
|
||||
// localStorage.removeItem('ms_role_id');
|
||||
// 跳转到登录页面
|
||||
router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirectTo: router.currentRoute.value.path // window.location.href
|
||||
},
|
||||
});
|
||||
ElMessage.success('已退出登录');
|
||||
} else if (command == 'user') {
|
||||
router.push('/user');
|
||||
}
|
||||
if (command == 'loginout') {
|
||||
// 发送退出登录请求
|
||||
send_request({
|
||||
url: 'v1/user/logout',
|
||||
method: "POST",
|
||||
} as any);
|
||||
// 关闭全部标签 (销毁页面对象)
|
||||
const tags = useTagsStore();
|
||||
tags.clearTags();
|
||||
// 清除本地 localStorage
|
||||
localStorage.clear();
|
||||
// 跳转到登录页面
|
||||
router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirectTo: router.currentRoute.value.path // window.location.href
|
||||
},
|
||||
});
|
||||
ElMessage.success('已退出登录');
|
||||
} else if (command == 'user') {
|
||||
router.push('/user');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.header {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
font-size: 22px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
font-size: 22px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.collapse-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
float: left;
|
||||
padding: 0 21px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
float: left;
|
||||
padding: 0 21px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header .logo {
|
||||
float: left;
|
||||
/* width: 250px; */
|
||||
line-height: 70px;
|
||||
/* 系统名称不换行 */
|
||||
white-space: nowrap;
|
||||
float: left;
|
||||
/* width: 250px; */
|
||||
line-height: 70px;
|
||||
/* 系统名称不换行 */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
float: right;
|
||||
padding-right: 50px;
|
||||
float: right;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.header-user-con {
|
||||
display: flex;
|
||||
height: 70px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 70px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-fullscreen {
|
||||
transform: rotate(45deg);
|
||||
margin-right: 5px;
|
||||
font-size: 24px;
|
||||
transform: rotate(45deg);
|
||||
margin-right: 5px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.btn-bell,
|
||||
.btn-fullscreen {
|
||||
position: relative;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-bell-badge {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 0px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background: #f56c6c;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 0px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background: #f56c6c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-bell .el-icon-lx-notice {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
margin-left: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.user-avator {
|
||||
margin-left: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.el-dropdown-link {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
@@ -15,11 +15,13 @@ app.use(router);
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component);
|
||||
}
|
||||
|
||||
// 自定义权限指令
|
||||
const permiss = usePermissStore();
|
||||
app.directive('permiss', {
|
||||
app.directive('permiss', { // 元素级权限控制
|
||||
mounted(el, binding) {
|
||||
if (!permiss.key.includes(String(binding.value))) {
|
||||
const role = localStorage.getItem('ms_role_id');
|
||||
if (!permiss[role as string] || !permiss[role as string].includes(binding.value as string)) {
|
||||
el['hidden'] = true;
|
||||
}
|
||||
},
|
||||
|
@@ -198,18 +198,26 @@ const router = createRouter({
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = `${to.meta.title} | ${settings.siteTitle}`;
|
||||
const role = localStorage.getItem('ms_username');
|
||||
const username = localStorage.getItem('ms_username');
|
||||
const role = localStorage.getItem('ms_role_id');
|
||||
const permiss = usePermissStore();
|
||||
if (!role && to.path !== '/login') {
|
||||
const currentUserPermiss = permiss[role as string];
|
||||
// console.log("currentUserPermiss", currentUserPermiss)
|
||||
if (!username && to.path !== '/login') {
|
||||
next({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirectTo: router.currentRoute.value.path // window.location.href
|
||||
},
|
||||
});
|
||||
} else if (to.meta.permiss && !permiss.key.includes(to.meta.permiss)) {
|
||||
return
|
||||
} else if (
|
||||
to.meta.permiss &&
|
||||
!(currentUserPermiss && currentUserPermiss.includes(to.meta.permiss as string))
|
||||
) {
|
||||
// 如果没有权限,则进入403
|
||||
next('/403');
|
||||
return
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
|
@@ -2,21 +2,61 @@ import { defineStore } from 'pinia';
|
||||
import send_request from '../utils/send_request';
|
||||
|
||||
interface ObjectList {
|
||||
[key: string]: string[];
|
||||
[key: string]: string[];
|
||||
}
|
||||
|
||||
// 不同 role 的用户分别有哪些权限
|
||||
export const usePermissStore = defineStore('permiss', {
|
||||
state: () => {
|
||||
const keys = localStorage.getItem('ms_keys');
|
||||
const defaultList = localStorage.getItem('ms_default_list');
|
||||
return {
|
||||
key: keys ? JSON.parse(keys) : <string[]>[],
|
||||
defaultList: JSON.stringify(defaultList)
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
handleSet(val: string[]) {
|
||||
this.key = val;
|
||||
}
|
||||
}
|
||||
state: () => {
|
||||
return {
|
||||
"1": [
|
||||
"dashboard",
|
||||
"data-integration",
|
||||
"default",
|
||||
"equipment",
|
||||
"equipment-setting",
|
||||
"equipment-setting-manage",
|
||||
"equipment-view",
|
||||
"monitor-data",
|
||||
"monitor-data-statistics",
|
||||
"monitor-data-view",
|
||||
"privilege",
|
||||
"privilege-role-setting",
|
||||
"privilege-user-setting",
|
||||
"report",
|
||||
"report-upload",
|
||||
"resource",
|
||||
"resource-staff-setting",
|
||||
"resource-vehicle-setting",
|
||||
"site-info",
|
||||
"warning",
|
||||
"warning-log",
|
||||
"warning-setting",
|
||||
"warning-view"
|
||||
],
|
||||
"2": [
|
||||
"dashboard",
|
||||
"data-integration",
|
||||
"default",
|
||||
"equipment",
|
||||
"equipment-setting",
|
||||
"equipment-view",
|
||||
"monitor-data",
|
||||
"monitor-data-statistics",
|
||||
"monitor-data-view",
|
||||
"report",
|
||||
"report-upload",
|
||||
"site-info",
|
||||
"warning",
|
||||
"warning-log",
|
||||
"warning-setting",
|
||||
"warning-view"
|
||||
]
|
||||
};
|
||||
},
|
||||
// actions: {
|
||||
// handleSet(val: string[]) {
|
||||
// this.key = val;
|
||||
// }
|
||||
// }
|
||||
});
|
||||
|
@@ -1,52 +1,67 @@
|
||||
import request from './request';
|
||||
import settings from './settings';
|
||||
|
||||
async function send_request(url, method = "POST", params, callback) {
|
||||
if (!url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let returnData = await request({
|
||||
baseURL: settings.backendHost,
|
||||
url: url,
|
||||
method: method,
|
||||
withCredentials: true,
|
||||
// POST 请求参数
|
||||
data: method.toUpperCase() == "POST" ? params : null,
|
||||
// GET 请求参数
|
||||
params: method.toUpperCase() == "GET" ? params : null,
|
||||
}).then((response) => {
|
||||
let result = response.data;
|
||||
// 判断后端是否处理成功
|
||||
if (!result.isSuccess) {
|
||||
// 用户未登录情况
|
||||
if (result.data && result.data.errCode == 20003) {
|
||||
ElMessage.error(result?.data?.errMsg || "用户未登录");
|
||||
localStorage.clear();
|
||||
// window.location.reload();
|
||||
// 如果同时发出多个请求,可能会多次进来,第二次及之后进入时,hash已经变成 #/login 了
|
||||
if (!window.location.hash.includes("/login")) {
|
||||
let newUrl = '/#/login?redirectTo=' + encodeURIComponent(window.location.hash.substring(1).split('?')[0])
|
||||
console.log("newUrl", newUrl)
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(result?.data?.errMsg || "服务器错误");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
let data = result.data;
|
||||
if (typeof (callback) === "function") {
|
||||
callback(data);
|
||||
}
|
||||
return true;
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error(err.message);
|
||||
// ElMessage.error('请求超时,请检查网络连接');
|
||||
return false;
|
||||
})
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export default send_request;
|
||||
import request from './request';
|
||||
import settings from './settings';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
import qs from 'qs';
|
||||
|
||||
async function send_request({ url, method = "POST", params, useQS = false, callback }) {
|
||||
if (!url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '请稍候',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
});
|
||||
|
||||
let opt = {
|
||||
baseURL: settings.backendHost,
|
||||
url: url,
|
||||
method: method,
|
||||
withCredentials: true,
|
||||
}
|
||||
|
||||
if (method.toUpperCase() == "POST") {
|
||||
// POST 请求参数
|
||||
opt.headers = { 'content-type': 'application/x-www-form-urlencoded' }
|
||||
opt.data = useQS ? qs.stringify(params) : params
|
||||
} else if (method.toUpperCase() == "GET") {
|
||||
// GET 请求参数
|
||||
opt.params = params
|
||||
}
|
||||
|
||||
return request(opt).then((response) => {
|
||||
let result = response.data;
|
||||
// 判断后端是否处理成功
|
||||
if (!result.success) {
|
||||
// 用户未登录情况
|
||||
// if (result.data && result.data.errCode == 20003) {
|
||||
// ElMessage.error(result?.data?.msg || "用户未登录");
|
||||
// localStorage.clear();
|
||||
// // window.location.reload();
|
||||
// // 如果同时发出多个请求,可能会多次进来,第二次及之后进入时,hash已经变成 #/login 了
|
||||
// if (!window.location.hash.includes("/login")) {
|
||||
// let newUrl = '/#/login?redirectTo=' + encodeURIComponent(window.location.hash.substring(1).split('?')[0])
|
||||
// console.log("newUrl", newUrl)
|
||||
// window.location.href = newUrl;
|
||||
// }
|
||||
// } else {
|
||||
ElMessage.error(result?.data?.msg || "服务器错误");
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
let data = result.data;
|
||||
if (typeof (callback) === "function") {
|
||||
callback(data);
|
||||
}
|
||||
return data;
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
ElMessage.error(err.message);
|
||||
return false;
|
||||
}).finally(() => {
|
||||
loading.close();
|
||||
})
|
||||
}
|
||||
|
||||
export default send_request;
|
||||
|
@@ -11,7 +11,7 @@ export default {
|
||||
* (网页标题 / 登录页显示)
|
||||
*/
|
||||
siteTitle: "社区疫情防控系统",
|
||||
siteFullTitle: "社区疫情防控系统 - 后台管理系统(社区管理员)",
|
||||
siteFullTitle: "社区疫情防控系统 - 后台管理系统",
|
||||
|
||||
/**
|
||||
* 开发公司名称
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
|
||||
/**
|
||||
* 后端接口请求地址
|
||||
* (以 / 结尾)
|
||||
* (结尾加不加 / 都可)
|
||||
*/
|
||||
backendHost: "http://epp.only4.work/",
|
||||
backendHost: "https://epp.only4.work/",
|
||||
};
|
||||
|
@@ -1,163 +1,136 @@
|
||||
<template>
|
||||
<div class="login-wrap">
|
||||
<div class="login-container">
|
||||
<div class="ms-login">
|
||||
<div class="ms-title">{{ settings.siteFullTitle }}</div>
|
||||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="用户名">
|
||||
<template #prepend>
|
||||
<el-button :icon="User"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input type="password" placeholder="密码" v-model="param.password"
|
||||
@keyup.enter="submitForm(login)">
|
||||
<template #prepend>
|
||||
<el-button :icon="Lock"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="login-btn">
|
||||
<el-button type="primary" @click="submitForm(login)">
|
||||
<!-- <el-icon><UserFilled /></el-icon>-->
|
||||
登 录 <el-icon>
|
||||
<Right />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="company-info" v-if="settings.companyName">
|
||||
{{ settings.companyName }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-wrap">
|
||||
<div class="login-container">
|
||||
<div class="ms-login">
|
||||
<div class="ms-title">{{ settings.siteFullTitle }}</div>
|
||||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="用户名">
|
||||
<template #prepend>
|
||||
<el-button :icon="User"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input type="password" placeholder="密码" v-model="param.password"
|
||||
@keyup.enter="submitForm(login)">
|
||||
<template #prepend>
|
||||
<el-button :icon="Lock"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="login-btn">
|
||||
<el-button type="primary" @click="submitForm(login)">
|
||||
<!-- <el-icon><UserFilled /></el-icon>-->
|
||||
登 录 <el-icon>
|
||||
<Right />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="company-info" v-if="settings.companyName">
|
||||
{{ settings.companyName }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
import { useTagsStore } from '../store/tags';
|
||||
import { usePermissStore } from '../store/permiss';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { Lock, User } from '@element-plus/icons-vue';
|
||||
import send_request from '../utils/send_request';
|
||||
import settings from '../utils/settings';
|
||||
|
||||
import * as userApi from '../api/user';
|
||||
|
||||
interface LoginInfo {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
username: string;
|
||||
id: string;
|
||||
roleId: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface PrivilegeInfo {
|
||||
"id": Number,
|
||||
"roleId": Number,
|
||||
"privilegeName": string,
|
||||
"module": string
|
||||
"id": Number,
|
||||
"roleId": Number,
|
||||
"privilegeName": string,
|
||||
"module": string
|
||||
}
|
||||
|
||||
interface RoleInfo {
|
||||
id: Number,
|
||||
roleName: string,
|
||||
comment: any,
|
||||
privileges: Array<PrivilegeInfo>;
|
||||
id: Number,
|
||||
roleName: string,
|
||||
comment: any,
|
||||
privileges: Array<PrivilegeInfo>;
|
||||
}
|
||||
|
||||
const router = useRouter();
|
||||
const param = reactive<LoginInfo>({
|
||||
username: 'admin',
|
||||
password: '123123'
|
||||
username: 'root',
|
||||
password: 'root'
|
||||
});
|
||||
|
||||
const rules: FormRules = {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
};
|
||||
const permiss: any = usePermissStore();
|
||||
|
||||
const login = ref<FormInstance>();
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid: boolean, invalidFields: any) => {
|
||||
if (!valid) {
|
||||
// ElMessage.error('请填写用户名或密码');
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid: boolean, invalidFields: any) => {
|
||||
if (!valid) {
|
||||
// ElMessage.error('请填写用户名或密码');
|
||||
|
||||
console.log("invalidFields", invalidFields);
|
||||
// 对表单中的每一个不合法输入框进行遍历
|
||||
Object.values(invalidFields).forEach((input: any) => {
|
||||
// console.log("input", input)
|
||||
// 对该不合法输入框的提示信息进行遍历
|
||||
input.forEach((element: any) => {
|
||||
// console.log("element", element)
|
||||
ElMessage.error({ message: element.message, grouping: true });
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
console.log("invalidFields", invalidFields);
|
||||
// 对表单中的每一个不合法输入框进行遍历
|
||||
Object.values(invalidFields).forEach((input: any) => {
|
||||
// console.log("input", input)
|
||||
// 对该不合法输入框的提示信息进行遍历
|
||||
input.forEach((element: any) => {
|
||||
// console.log("element", element)
|
||||
ElMessage.error({ message: element.message, grouping: true });
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '请稍候',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
});
|
||||
userApi.userLogin({
|
||||
username: param.username,
|
||||
password: param.password
|
||||
}).then(async (data: any) => {
|
||||
// 判断用户是否登录成功
|
||||
if (!data) return;
|
||||
|
||||
console.log("login data", data, data.userInfo);
|
||||
|
||||
await send_request('v1/user/login', "POST", {
|
||||
userName: param.username,
|
||||
passWord: param.password
|
||||
}, async (data: UserInfo) => {
|
||||
// 判断用户是否登录成功
|
||||
if (!data) {
|
||||
ElMessage.error("用户名或密码错误");
|
||||
return;
|
||||
}
|
||||
ElMessage.success('登录成功');
|
||||
localStorage.setItem('ms_username', data.username);
|
||||
localStorage.setItem('ms_user_id', data.id);
|
||||
localStorage.setItem('ms_role_id', data.roleId);
|
||||
ElMessage.success('登录成功');
|
||||
localStorage.setItem('ms_username', data.userInfo?.username);
|
||||
localStorage.setItem('ms_realname', data.userInfo?.realname);
|
||||
localStorage.setItem('ms_user_id', data.userInfo?.id);
|
||||
localStorage.setItem('ms_role_id', data.userInfo?.role);
|
||||
|
||||
let defaultList = {};
|
||||
await send_request('v1/role/list', "GET", {}, (roleList: Array<RoleInfo>) => {
|
||||
for (let role of roleList) {
|
||||
defaultList[role.id.toString()] = role.privileges.map((i: any) => i.module)
|
||||
}
|
||||
});
|
||||
|
||||
permiss.defaultList = defaultList;
|
||||
permiss.key = defaultList[data.roleId];
|
||||
if (typeof (permiss.key) === "undefined") return;
|
||||
localStorage.setItem('ms_keys', JSON.stringify(permiss.key));
|
||||
localStorage.setItem('ms_default_list', JSON.stringify(defaultList));
|
||||
let targetRoute: any = router.currentRoute?.value?.query?.redirectTo
|
||||
if (targetRoute && !targetRoute.includes('/login')) {
|
||||
router.push(targetRoute);
|
||||
} else {
|
||||
router.push('/');
|
||||
}
|
||||
});
|
||||
loading.close();
|
||||
});
|
||||
let targetRoute: any = router.currentRoute?.value?.query?.redirectTo
|
||||
if (targetRoute && !targetRoute.includes('/login')) {
|
||||
router.push(targetRoute);
|
||||
} else {
|
||||
router.push('/');
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const tags = useTagsStore();
|
||||
@@ -166,57 +139,57 @@ tags.clearTags();
|
||||
|
||||
<style scoped>
|
||||
.login-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.ms-title {
|
||||
width: 100%;
|
||||
padding: 18px 24px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #ddd;
|
||||
width: 100%;
|
||||
padding: 18px 24px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.ms-login {
|
||||
width: min(380px, 95vw);
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
overflow: hidden;
|
||||
width: min(380px, 95vw);
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ms-content {
|
||||
padding: 30px 30px;
|
||||
padding: 30px 30px;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-btn button {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
color: #7589b6;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 10px;
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
color: #7589b6;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 10px;
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user