diff --git a/package.json b/package.json index b70a3e7..b30e210 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "js-beautify": "1.13.0", "js-cookie": "3.0.1", "jsencrypt": "3.0.0-rc.1", + "node-forge": "^1.3.1", "nprogress": "0.2.0", "quill": "2.0.2", "screenfull": "5.0.2", diff --git a/src/api/login.js b/src/api/login.js index 7b7388f..ed1c38a 100644 --- a/src/api/login.js +++ b/src/api/login.js @@ -1,4 +1,4 @@ -import request from '@/utils/request' +import request from "@/utils/request"; // 登录方法 export function login(username, password, code, uuid) { @@ -6,55 +6,55 @@ export function login(username, password, code, uuid) { username, password, code, - uuid - } + uuid, + }; return request({ - url: '/login', + url: "/login", headers: { isToken: false, - repeatSubmit: false + repeatSubmit: false, }, - method: 'post', - data: data - }) + method: "post", + data: data, + }); } // 注册方法 export function register(data) { return request({ - url: '/register', + url: "/register", headers: { - isToken: false + isToken: false, }, - method: 'post', - data: data - }) + method: "post", + data: data, + }); } // 获取用户详细信息 export function getInfo() { return request({ - url: '/getInfo', - method: 'get' - }) + url: "/getInfo", + method: "get", + }); } // 退出方法 export function logout() { return request({ - url: '/logout', - method: 'post' - }) + url: "/logout", + method: "post", + }); } // 获取验证码 export function getCodeImg() { return request({ - url: '/captchaImage', + url: "/captchaImage", headers: { - isToken: false + isToken: false, }, - method: 'get', - timeout: 20000 - }) -} \ No newline at end of file + method: "get", + timeout: 20000, + }); +} diff --git a/src/assets/icons/svg/icon-dwgl-1.svg b/src/assets/icons/svg/icon-dwgl-1.svg new file mode 100644 index 0000000..ee14752 --- /dev/null +++ b/src/assets/icons/svg/icon-dwgl-1.svg @@ -0,0 +1 @@ +icon-dwgl-1 \ No newline at end of file diff --git a/src/assets/icons/svg/icon-rwgl.svg b/src/assets/icons/svg/icon-rwgl.svg new file mode 100644 index 0000000..e91993a --- /dev/null +++ b/src/assets/icons/svg/icon-rwgl.svg @@ -0,0 +1 @@ +icon-rwgl \ No newline at end of file diff --git a/src/assets/icons/svg/icon-zcgl-1.svg b/src/assets/icons/svg/icon-zcgl-1.svg new file mode 100644 index 0000000..46df9e1 --- /dev/null +++ b/src/assets/icons/svg/icon-zcgl-1.svg @@ -0,0 +1 @@ +icon-zcgl-1 \ No newline at end of file diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss index 34484d4..a69e1b0 100644 --- a/src/assets/styles/variables.scss +++ b/src/assets/styles/variables.scss @@ -1,25 +1,25 @@ // base color -$blue:#324157; -$light-blue:#3A71A8; -$red:#C03639; -$pink: #E65D6E; -$green: #30B08F; -$tiffany: #4AB7BD; -$yellow:#FEC171; -$panGreen: #30B08F; +$blue: #324157; +$light-blue: #3a71a8; +$red: #c03639; +$pink: #e65d6e; +$green: #30b08f; +$tiffany: #4ab7bd; +$yellow: #fec171; +$panGreen: #30b08f; // 默认菜单主题风格 -$base-menu-color:#bfcbd9; -$base-menu-color-active:#f4f4f5; -$base-menu-background:#304156; +$base-menu-color: #bfcbd9; +$base-menu-color-active: #f4f4f5; +$base-menu-background: #304156; $base-logo-title-color: #ffffff; -$base-menu-light-color:rgba(0,0,0,.70); -$base-menu-light-background:#ffffff; +$base-menu-light-color: rgba(0, 0, 0, 0.7); +$base-menu-light-background: #ffffff; $base-logo-light-title-color: #001529; -$base-sub-menu-background:#1f2d3d; -$base-sub-menu-hover:#001528; +$base-sub-menu-background: #1f2d3d; +$base-sub-menu-hover: #001528; // 自定义暗色菜单风格 /** @@ -36,7 +36,7 @@ $base-sub-menu-background:#000c17; $base-sub-menu-hover:#001528; */ -$base-sidebar-width: 200px; +$base-sidebar-width: 260px; // the :export directive is the magic sauce for webpack // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass @@ -50,5 +50,5 @@ $base-sidebar-width: 200px; subMenuHover: $base-sub-menu-hover; sideBarWidth: $base-sidebar-width; logoTitleColor: $base-logo-title-color; - logoLightTitleColor: $base-logo-light-title-color + logoLightTitleColor: $base-logo-light-title-color; } diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue index 080595a..8086aa1 100644 --- a/src/components/Breadcrumb/index.vue +++ b/src/components/Breadcrumb/index.vue @@ -2,8 +2,12 @@ - {{ item.meta.title }} - {{ item.meta.title }} + {{ item.meta.title }} + @@ -13,80 +17,86 @@ export default { data() { return { - levelList: null - } + levelList: null, + }; }, watch: { $route(route) { // if you go to the redirect page, do not update the breadcrumbs - if (route.path.startsWith('/redirect/')) { - return + if (route.path.startsWith("/redirect/")) { + return; } - this.getBreadcrumb() - } + this.getBreadcrumb(); + }, }, created() { - this.getBreadcrumb() + this.getBreadcrumb(); }, methods: { getBreadcrumb() { // only show routes with meta.title - let matched = [] - const router = this.$route - const pathNum = this.findPathNum(router.path) + let matched = []; + const router = this.$route; + const pathNum = this.findPathNum(router.path); // multi-level menu if (pathNum > 2) { - const reg = /\/\w+/gi + const reg = /\/\w+/gi; const pathList = router.path.match(reg).map((item, index) => { - if (index !== 0) item = item.slice(1) - return item - }) - this.getMatched(pathList, this.$store.getters.defaultRoutes, matched) + if (index !== 0) item = item.slice(1); + return item; + }); + this.getMatched(pathList, this.$store.getters.defaultRoutes, matched); } else { - matched = router.matched.filter(item => item.meta && item.meta.title) + matched = router.matched.filter((item) => item.meta && item.meta.title); } // 判断是否为首页 if (!this.isDashboard(matched[0])) { - matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched) + matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched); } - this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) + this.levelList = matched.filter( + (item) => item.meta && item.meta.title && item.meta.breadcrumb !== false + ); }, findPathNum(str, char = "/") { - let index = str.indexOf(char) - let num = 0 + let index = str.indexOf(char); + let num = 0; while (index !== -1) { - num++ - index = str.indexOf(char, index + 1) + num++; + index = str.indexOf(char, index + 1); } - return num + return num; }, getMatched(pathList, routeList, matched) { - let data = routeList.find(item => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]) + let data = routeList.find( + (item) => + item.path == pathList[0] || + (item.name += "").toLowerCase() == pathList[0] + ); if (data) { - matched.push(data) + matched.push(data); if (data.children && pathList.length) { - pathList.shift() - this.getMatched(pathList, data.children, matched) + pathList.shift(); + this.getMatched(pathList, data.children, matched); } } }, isDashboard(route) { - const name = route && route.name + const name = route && route.name; if (!name) { - return false + return false; } - return name.trim() === 'Index' + return name.trim() === "Index"; }, handleLink(item) { - const { redirect, path } = item + const { redirect, path } = item; if (redirect) { - this.$router.push(redirect) - return + this.$router.push(redirect); + return; } - this.$router.push(path) - } - } -} + this.$router.push(path); + }, + }, +}; diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue index 66b33bf..16c86dd 100644 --- a/src/layout/components/AppMain.vue +++ b/src/layout/components/AppMain.vue @@ -10,45 +10,47 @@ diff --git a/src/views/index.vue b/src/views/index.vue index 02b0300..e29202b 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -1,1133 +1,19 @@ - - + diff --git a/src/views/login.vue b/src/views/login.vue index 55b978e..49d4305 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -91,7 +91,7 @@ import { getCodeImg } from "@/api/login"; import Cookies from "js-cookie"; import { encrypt, decrypt } from "@/utils/jsencrypt"; - +import forge from "node-forge"; export default { name: "Login", data() { @@ -120,6 +120,7 @@ export default { // 注册开关 register: false, redirect: undefined, + publicKey: `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8bS1kYTiMhIS5MZU253bc0ukaxrA1lfCziABFxQrC2c09tMrQGjuH6V1x2ofNBMGhOD9uWN/qkAQy/HwOe/NKUqCw6N0ov6guSrqMDW/BdZ3Bl0rmM1/95jTC1xffFFvej7xWNffIbaPI+bJ4WLX9NViNi9HmT0BRNzJ4d2R86LPPCa+bxLaPjsh2R2tBkbLkUot9769aJaPPiwPCZHMkuQenjHSmpWL0okleqMH8EGX7j6A5A/4IUXPMNKMMzkiSRpsIJ65GJmDAbnR3ZXRfC8MzVBBJB6zr5N0F4N9xZfF+JS/Yx726tCu+rA6GDCyTxtQ/wnKpPdwFP5nUWCWQIDAQAB`, }; }, watch: { @@ -173,8 +174,28 @@ export default { Cookies.remove("password"); Cookies.remove("rememberMe"); } + // 生成一个 2048 位的 RSA 密钥对 + const lines = []; + lines.push("-----BEGIN PUBLIC KEY-----"); + for (let i = 0; i < this.publicKey.length; i += 64) { + lines.push(this.publicKey.slice(i, i + 64)); + } + lines.push("-----END PUBLIC KEY-----"); + lines.join("\n"); + const publicKey = forge.pki.publicKeyFromPem(lines.join("\n")); + // 将待加密的字符串转换为字节数组 + var dataBytes = forge.util.encodeUtf8(this.loginForm.password); + // 加密数据 + var encryptedBytes = publicKey.encrypt(dataBytes, "RSA-OAEP", { + md: forge.md.sha256.create(), + mgf1: { + md: forge.md.sha1.create(), + }, + }); + // 将加密后的字节数组转换为 Base64 编码的字符串 + var encryptedBase64 = forge.util.encode64(encryptedBytes); this.$store - .dispatch("Login", this.loginForm) + .dispatch("Login", { ...this.loginForm, password: encryptedBase64 }) .then(() => { this.$router.push({ path: this.redirect || "/" }).catch(() => {}); }) diff --git a/src/views/unitPages/myAssets.vue b/src/views/unitPages/myAssets.vue new file mode 100644 index 0000000..42bbb8c --- /dev/null +++ b/src/views/unitPages/myAssets.vue @@ -0,0 +1,9 @@ + + + + +