diff --git a/package.json b/package.json index abdbabe..216700c 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/App.vue b/src/App.vue index 91f3d88..5a71a97 100644 --- a/src/App.vue +++ b/src/App.vue @@ -15,17 +15,15 @@ locale.value = localStorage.getItem('locale') || 'zh-cn'; diff --git a/src/apis/login.js b/src/apis/login.js index b97cee8..b55a6a8 100644 --- a/src/apis/login.js +++ b/src/apis/login.js @@ -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, - }) -}; \ No newline at end of file + }); +}; diff --git a/src/layout/components/PageHeader.vue b/src/layout/components/PageHeader.vue index 746ec72..57778b7 100644 --- a/src/layout/components/PageHeader.vue +++ b/src/layout/components/PageHeader.vue @@ -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: () => { diff --git a/src/main.js b/src/main.js index ebbc3a2..7f6f7d7 100644 --- a/src/main.js +++ b/src/main.js @@ -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); diff --git a/src/mock/data.js b/src/mock/data.js new file mode 100644 index 0000000..d399a21 --- /dev/null +++ b/src/mock/data.js @@ -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", + }, + ], + }, +]; diff --git a/src/mock/index.js b/src/mock/index.js new file mode 100644 index 0000000..4d9fa4a --- /dev/null +++ b/src/mock/index.js @@ -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]() || {}); + } + } +} diff --git a/src/mock/modules/login.js b/src/mock/modules/login.js new file mode 100644 index 0000000..823d901 --- /dev/null +++ b/src/mock/modules/login.js @@ -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: {}, + }, + }; +} diff --git a/src/mock/modules/personal.js b/src/mock/modules/personal.js new file mode 100644 index 0000000..46f0676 --- /dev/null +++ b/src/mock/modules/personal.js @@ -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, + }; + }, + }; +} + + diff --git a/src/request/config.js b/src/request/config.js index c8e3826..ad3bbc9 100644 --- a/src/request/config.js +++ b/src/request/config.js @@ -1,10 +1,10 @@ export default { method: 'get', baseURL: 'http://localhost:8001', - header: { + headers: { 'Content-Type': 'application/json;charset=UTF-8' }, timeout: 10000, withCredentials: true, responseType: 'json', -} \ No newline at end of file +} diff --git a/src/request/index.js b/src/request/index.js index 75b5ade..ab1ece9 100644 --- a/src/request/index.js +++ b/src/request/index.js @@ -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); @@ -106,4 +108,4 @@ export default function request(options) { } ) }) -} \ No newline at end of file +} diff --git a/src/router/index.js b/src/router/index.js index 0e00ed2..d5d5687 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -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 diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 05ecaa9..fa8608b 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,5 +1,6 @@ -import { userInfo } from "@/apis/personal.js" +import {userInfo} from "@/apis/personal.js" import {info} from "sass"; + export default { namespaced: true, state: { @@ -29,7 +30,7 @@ export default { }, actions: { refreshInfo({commit}) { - userInfo().then((res) => { + userInfo().then(res => { commit('setUserInfo', res.data) }) } diff --git a/src/views/login/index.vue b/src/views/login/index.vue index de35ef7..e2ac834 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -1,10 +1,10 @@