Compare commits

..

2 Commits

  1. 1
      package.json
  2. 16
      src/App.vue
  3. 4
      src/apis/login.js
  4. 9
      src/apis/personal.js
  5. 18
      src/layout/components/PageHeader.vue
  6. 1
      src/main.js
  7. 103
      src/mock/data.js
  8. 52
      src/mock/index.js
  9. 54
      src/mock/modules/login.js
  10. 66
      src/mock/modules/personal.js
  11. 2
      src/request/config.js
  12. 6
      src/request/index.js
  13. 11
      src/router/index.js
  14. 25
      src/store/index.js
  15. 38
      src/store/modules/user.js
  16. 31
      src/views/login/index.vue
  17. 12
      yarn.lock

@ -13,6 +13,7 @@
"@types/node": "^20.8.7",
"axios": "^1.5.1",
"element-plus": "^2.4.1",
"mockjs": "^1.1.0",
"normalize.css": "^8.0.1",
"vue": "^3.3.4",
"vue-i18n": "^9.4.1",

@ -15,17 +15,15 @@ locale.value = localStorage.getItem('locale') || 'zh-cn';
<style>
html,
body {
height: 100%;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
height: 100%;
align-items: center;
justify-content: center;
}
.flex-center {
@ -37,4 +35,10 @@ body {
.cursor {
cursor: pointer;
}
.txt-c {
text-align: center;
}
.w100p {
width: 100%;
}
</style>

@ -1,4 +1,4 @@
import request from "@/request/index.js";
import request from "@/request";
// 登录
export const login = (data) => {
@ -6,5 +6,5 @@ export const login = (data) => {
url: 'login',
method: 'post',
data,
})
});
};

@ -0,0 +1,9 @@
import request from "@/request/index.js"
export const userInfo = (data) => {
return request({
url: '/personal/userinfo',
method: 'get',
data,
})
}

@ -55,10 +55,13 @@
import {Message} from '@element-plus/icons-vue'
import {useI18n} from "vue-i18n";
import {ref} from 'vue';
import {useRoute} from "vue-router";
import {useRouter} from "vue-router";
import router from "@/router/index.js";
import store from "@/store/index.js";
import user from "@/store/modules/user.js";
// import {useStore} from "vuex";
const route = useRoute();
const route = useRouter();
const {locale, t} = useI18n();
function changeLanguage(lang) {
@ -66,10 +69,13 @@ function changeLanguage(lang) {
localStorage.setItem('locale', lang)
}
const isLogin = ref(false);
const username = ref('admin');
const unReadCount = ref(2);
isLogin.value = true;
// const store = useStore();
const isLogin = computed(() => store.getters['user/isLogin']);
const userInfo = computed(() => store.state.user.userInfo)
const username = computed(() => userInfo.value?.name);
const unReadCount = computed(() => userInfo.value?.unReadCount);
store.dispatch('user/refreshInfo');
const commands = {
toPersonal: () => {

@ -5,6 +5,7 @@ import store from "./store/index.js";
import i18n from "./i18n/index.js";
import * as ElIcons from "@element-plus/icons-vue";
import 'normalize.css/normalize.css'
import "./mock"
const app = createApp(App);

@ -0,0 +1,103 @@
export const users = [
{
name: "visitor",
roleId: 'visitor',
password: "visitor",
},
{
name: "master",
roleId: "master",
password: "master",
},
{
name: "admin",
roleId: "admin",
password: "admin",
},
];
export const menuTreeData = [
{
id: 1,
parentId: 0,
name: 'App',
path: "/app",
icon: "el-icon-menu",
children: [
{
id: 11,
parentId: 1,
name: 'AppUser',
path: "/app/user",
icon: "user",
},
{
id: 12,
parentId: 1,
name: 'AppDept',
path: "/app/dept",
icon: "office-building",
},
{
id: 13,
parentId: 1,
name: 'AppRole',
path: "/app/role",
icon: "avatar",
},
{
id: 14,
parentId: 1,
name: 'AppResource',
path: "/app/resource",
icon: "management",
},
],
},
{
id: 2,
parentId: 0,
name: 'Sys',
path: "/sys",
icon: "setting",
children: [
{
id: 21,
parentId: 2,
name: 'SysUser',
path: "/sys/user",
icon: "user-filled",
},
{
id: 22,
parentId: 2,
name: 'SysNotice',
path: "/sys/notice",
icon: "chat-dot-round",
},
],
},
{
id: 3,
parentId: 0,
name: 'Logs',
path: "/logs",
icon: "document",
children: [
{
id: 31,
parentId: 3,
name: 'LogsVisit',
path: "/logs/visit",
icon: "tickets",
},
{
id: 32,
parentId: 3,
name: 'LogsOperation',
path: "/logs/operation",
icon: "operation",
},
],
},
];

@ -0,0 +1,52 @@
import Mock from "mockjs";
import config from "@/request/config";
import * as login from "./modules/login";
import * as personal from "./modules/personal";
const { baseURL } = config;
// 1. 开启/关闭所有模块拦截, 通过openMock开关设置.
// 2. 开启/关闭单个模块拦截, 通过调用mock方法isOpen参数设置.
// 3. 开启/关闭模块中某个请求拦截, 通过函数返回对象中的isOpen属性设置.
const openMock = true;
// 模拟所有模块
// mockAll([login], openMock);
// function mockAll(modules, isOpen = true) {
// for (const k in modules) {
// mock(modules[k], isOpen);
// }
// }
// 模拟单个模块
mock(login, openMock)
mock(personal, openMock)
/**
* 创建mock模拟数据
* @param {*} mod 模块
* @param {*} isOpen 是否开启?
*/
function mock(mod, isOpen = true) {
if (isOpen) {
for (var key in mod) {
((res) => {
if (res.isOpen !== false) {
let url = baseURL;
if (!url.endsWith("/")) {
url = url + "/";
}
url = url + res.url;
Mock.mock(new RegExp(url), res.method, (opts) => {
opts.data = opts.body ? JSON.parse(opts.body) : null;
const resData = Mock.mock(
typeof res.response === "function"
? res.response(opts)
: res.response
);
console.log("%cmock拦截, 请求: ", "color:blue", opts);
console.log("%cmock拦截, 响应: ", "color:blue", resData);
return resData;
});
}
})(mod[key]() || {});
}
}
}

@ -0,0 +1,54 @@
/*
* 系统登录模块
*/
import { users } from "../data";
// 登录
export function login() {
return {
url: "login",
method: "post",
response: (opts) => {
const name = opts.data.account;
if (
users.find((v) => v.name === name && v.password === opts.data.password)
) {
return {
code: 200,
msg: "",
data: {
token: name + "@eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cC",
name,
},
};
}
return {
code: -1,
msg: "用户名或密码错误",
};
},
};
}
// export function login() {
// return {
// url: "login",
// method: "post",
// response: () => {
// return {
// code: -1,
// msg: "用户名或密码不正确!",
// };
// },
// };
// }
// 登出接口
export function logout() {
return {
url: "logout",
method: "get",
response: {
code: 200,
msg: null,
data: {},
},
};
}

@ -0,0 +1,66 @@
import { users, menuTreeData } from "../data";
export function userInfo() {
return {
url: "personal/userinfo",
method: "get",
response: () => {
const token = localStorage.getItem('pm_token');
if (token) {
const uinfo = {...users.find((v) => v.name === token.split('@')[0])}
delete uinfo.password;
return {
code: 200,
data: {
...uinfo,
'unReadCount|0-10': 0
}
};
} else {
return {
code: -2,
msg: '请先登录!'
}
}
},
};
}
export function menuTree() {
return {
url: "personal/menuTree",
method: "get",
response: () => {
const token = localStorage.getItem('pm_token');
if (!token) {
return {
code: 200,
msg: ''
}
}
const name = token.split('@')[0]
const info = users.find(v => v.name === name)
const role = info.roleId;
let treeData = [menuTreeData[2]];
switch (role) {
case "admin":
treeData = menuTreeData;
break;
case "master":
treeData = [menuTreeData[0], menuTreeData[2]];
break;
case "visitor":
treeData = [menuTreeData[2]];
break;
default:
break;
}
return {
code: 200,
data: treeData,
};
},
};
}

@ -1,7 +1,7 @@
export default {
method: 'get',
baseURL: 'http://localhost:8001',
header: {
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
timeout: 10000,

@ -1,7 +1,7 @@
import axios from "axios";
import config from "@/request/config.js";
import router from "@/router/index.js";
import ElMessage from 'element-plus';
import router from "@/router";
import { ElMessage } from 'element-plus';
export default function request(options) {
return new Promise((resolve, reject) => {
@ -12,9 +12,11 @@ export default function request(options) {
let token = localStorage.getItem('pm_token');
if (token) {
config.headers.token = token;
} else {
router.push('/login')
}
return config;
},
(error) => {
console.log("request:", error);

@ -50,7 +50,16 @@ const routes = [
name: "404",
redirect: "/404"
}
]
];
const router = createRouter({history: createWebHashHistory(), routes})
router.beforeEach((to) => {
const token = localStorage.getItem("pm_token");
if (to.meta.requireAuth && !token) {
return {name: 'Login'}
}
return true;
});
export default router

@ -1,12 +1,27 @@
import {createStore} from "vuex";
import user from "./modules/user.js"
export default createStore({
modules: {
user
},
state: {
count: 0,
routeLoaded: false, // 菜单和路由是否已经加载
firstRoute: null, // 第一个路由,用于设置进入主页 的redirect
menuTree: null, // 菜单树
},
mutations: {
increase (state, count) {
state.count += count;
}
}
// 改变菜单和路由的加载状态
setRouteLoaded(state, loaded) {
state.routeLoaded = loaded;
},
setFirstRoute(state, route) {
state.firstRoute = route;
},
setMenuTree(state, data) {
state.menuTree = data
},
},
actions: {},
})

@ -0,0 +1,38 @@
import {userInfo} from "@/apis/personal.js"
import {info} from "sass";
export default {
namespaced: true,
state: {
token: '',
userInfo: {} // 用户基本信息
},
getters: {
isLogin(state) {
return !!state.token || !!localStorage.getItem("pm_token");
}
},
mutations: {
setToken(state, token) {
localStorage.setItem('pm_token', token);
state.token = token;
},
clearToken(state) {
state.token = '';
localStorage.removeItem('pm_token');
},
setUserInfo(state, info) {
state.userInfo = info || {};
},
clearUserInfo(state) {
state.userInfo = {}
}
},
actions: {
refreshInfo({commit}) {
userInfo().then(res => {
commit('setUserInfo', res.data)
})
}
}
}

@ -1,10 +1,10 @@
<template>
<div class="page flex-center">
<div class="single-box">
<div class="sign-box">
<el-form ref="formRef" :model="form" :rules="rules" label-width="86px">
<h3 class="title">{{ t('login') }}</h3>
<el-form-item :label="t('form.username')" prop="account">
<el-input v-model="form.account" :placeholder="t('form.accountHolder')" prefix-icon="user"></el-input>
<el-input v-model="form.account" :placeholder="t('form.usernameHolder')" prefix-icon="user"></el-input>
</el-form-item>
<el-form-item :label="t('form.password')" prop="password">
<el-input v-model="form.password" type="password" :placeholder="t('form.passwordHolder')"
@ -27,6 +27,7 @@ import {login} from "@/apis/login.js";
import {useI18n} from "vue-i18n";
import {useStore} from "vuex";
import router from "@/router/index.js";
import {ref, reactive} from "vue";
const {t} = useI18n();
@ -50,12 +51,13 @@ function doLogin() {
//
if (!valid) return;
//
console.log('登录了');
loading.value = true
login(form).then((res) => {
store.commit("user/setToken", res.data.token);
store.dispatch("user/refreshInfo");
store.commit("setRouteLoaded", false);
localStorage.setItem("pm_token", res.data.token);
// localStorage.setItem("pm_token", res.data.token);
router.push("/")
}).finally(() => {
loading.value = false;
@ -65,6 +67,27 @@ function doLogin() {
</script>
<style scoped>
<style lang="scss">
.page {
height: 100%;
background: url(@/assets/bg.jpg) no-repeat;
background-size: cover;
}
.sign-box {
width: 400px;
background: #ffffff;
padding: 30px 50px 20px 30px;
border-radius: 4px;
box-shadow: 0 0 10px #022c44;
}
.title {
text-align: center;
font-size: 20px;
line-height: 20px;
margin-top: 0;
margin-bottom: 10px;
color: #000000;
}
</style>

@ -442,6 +442,11 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
commander@*:
version "11.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
csstype@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
@ -699,6 +704,13 @@ mlly@^1.2.0, mlly@^1.4.2:
pkg-types "^1.0.3"
ufo "^1.3.0"
mockjs@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mockjs/-/mockjs-1.1.0.tgz#e6a0c378e91906dbaff20911cc0273b3c7d75b06"
integrity sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==
dependencies:
commander "*"
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"

Loading…
Cancel
Save