From 61305737428611ca4477f64dceb606d26dc05a4f Mon Sep 17 00:00:00 2001 From: fuguobin Date: Tue, 21 Nov 2023 17:10:13 +0800 Subject: [PATCH] =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=A2=9E=E5=8A=A0=E8=AE=B0?= =?UTF-8?q?=E4=BD=8F=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + src/types/auto-imports.d.ts | 4 -- src/utils/crypto.js | 20 +++++++ src/utils/storage.ts | 108 ++++++++++++++++++++++++++++++++++++ src/views/login/index.scss | 17 ++++-- src/views/login/index.vue | 25 ++++++++- vite.config.ts | 2 +- 7 files changed, 166 insertions(+), 12 deletions(-) create mode 100644 src/utils/crypto.js create mode 100644 src/utils/storage.ts diff --git a/package.json b/package.json index 4aa62ed..e536d3c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@wangeditor/editor-for-vue": "^5.1.10", "animate.css": "^4.1.1", "axios": "^1.3.4", + "crypto-js": "^4.2.0", "echarts": "^5.2.2", "element-plus": "^2.2.32", "mitt": "^3.0.1", @@ -39,6 +40,7 @@ "@commitlint/cli": "^16.2.3", "@commitlint/config-conventional": "^16.2.1", "@iconify-json/ep": "^1.1.8", + "@types/crypto-js": "^4.2.1", "@types/nprogress": "^0.2.0", "@types/path-browserify": "^1.0.0", "@typescript-eslint/eslint-plugin": "^5.19.0", diff --git a/src/types/auto-imports.d.ts b/src/types/auto-imports.d.ts index 5742656..e5c7bdb 100644 --- a/src/types/auto-imports.d.ts +++ b/src/types/auto-imports.d.ts @@ -5,8 +5,6 @@ declare global { const ElForm: typeof import('element-plus/es')['ElForm'] const ElMessage: typeof import('element-plus/es')['ElMessage'] const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] - const ElNotification: typeof import('element-plus/es')['ElNotification'] - const NEllipsis: typeof import('naive-ui')['NEllipsis'] const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] const computed: typeof import('vue')['computed'] @@ -276,8 +274,6 @@ declare module 'vue' { readonly ElForm: UnwrapRef readonly ElMessage: UnwrapRef readonly ElMessageBox: UnwrapRef - readonly ElNotification: UnwrapRef - readonly NEllipsis: UnwrapRef readonly asyncComputed: UnwrapRef readonly autoResetRef: UnwrapRef readonly computed: UnwrapRef diff --git a/src/utils/crypto.js b/src/utils/crypto.js new file mode 100644 index 0000000..04bd9b3 --- /dev/null +++ b/src/utils/crypto.js @@ -0,0 +1,20 @@ +import CryptoJS from 'crypto-js'; + +const key = CryptoJS.enc.Utf8.parse('1C1389D55E4522B2'); //十六位十六进制数作为密钥 +const iv = CryptoJS.enc.Utf8.parse('1C1389E43F01C1B2'); //十六位十六进制数作为密钥偏移量 + +//解密方法 +export function decryption(word) { + let encryptedHexStr = CryptoJS.enc.Hex.parse(word); + let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr); + let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); + let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8); + return decryptedStr.toString(); +} + +//加密方法 +export function encryption(word) { + let srcs = CryptoJS.enc.Utf8.parse(word); + let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); + return encrypted.ciphertext.toString().toUpperCase(); +} diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..05f76d6 --- /dev/null +++ b/src/utils/storage.ts @@ -0,0 +1,108 @@ +/** + * * 存储本地会话数据 + * @param k 键名 + * @param v 键值(无需stringiiy) + * @returns RemovableRef + */ +export const setLocalStorage = (k: string, v: T) => { + try { + window.localStorage.setItem(k, JSON.stringify(v)) + } catch (error) { + return false + } +} + +/** + * * 获取本地会话数据 + * @param k 键名 + * @returns any + */ +export const getLocalStorage = (k: string) => { + const item = window.localStorage.getItem(k) + try { + return item ? JSON.parse(item) : item + } catch (err) { + return item + } +} + +/** + * * 清除本地会话数据 + * @param name + */ +export const clearLocalStorage = (name: string) => { + window.localStorage.removeItem(name) +} + +/** + * * 存储临时会话数据 + * @param k 键名 + * @param v 键值 + * @returns RemovableRef + */ +export const setSessionStorage = (k: string, v: T) => { + try { + window.sessionStorage.setItem(k, JSON.stringify(v)) + } catch (error) { + return false + } +} + +/** + * * 获取临时会话数据 + * @returns any + */ +export const getSessionStorage: (k: string) => any = (k: string) => { + const item = window.sessionStorage.getItem(k) + try { + return item ? JSON.parse(item) : item + } catch (err) { + return item + } +} + +/** + * * 清除本地会话数据 + * @param name + */ +export const clearSessioStorage = (name: string) => { + window.sessionStorage.removeItem(name) +} + +/** + * * 设置 cookie + * @param name 键名 + * @param cvalue 键值 + * @param exdays 过期时间 + */ +export const setCookie = (name: string, cvalue: string, exdays: number) => { + const d = new Date(); + d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); + const expires = "expires=" + d.toUTCString(); + document.cookie = name + "=" + cvalue + "; " + expires; +} + +/** + * * 获取 cookie + * @param cname 键名 + * @returns string + */ +export const getCookie = (cname: string) => { + const name = cname + "="; + const ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1); + if (c.indexOf(name) != -1) return c.substring(name.length, c.length); + } + return ""; +} + +/** + * * 清除 cookie + * @param name 键名 + * @returns string + */ +export const clearCookie = (name: string) => { + setCookie(name, "", -1); +} \ No newline at end of file diff --git a/src/views/login/index.scss b/src/views/login/index.scss index b260539..127330a 100644 --- a/src/views/login/index.scss +++ b/src/views/login/index.scss @@ -78,8 +78,7 @@ &:-webkit-autofill:focus, &:-webkit-autofill:active { -webkit-transition-delay: 99999s; - -webkit-transition: color 99999s ease-out, - background-color 99999s ease-out; + -webkit-transition: color 99999s ease-out, background-color 99999s ease-out; } } } @@ -89,11 +88,19 @@ line-height: normal; } } + .el-form-item.remember { + border: none; + background-color: transparent; + .el-checkbox { + height: 20px; + // color: var(--el-checkbox-checked-text-color); + } + } } } .video { - object-fit: cover + object-fit: cover; } .videoCover { @@ -123,7 +130,6 @@ .loginForm { .title { - .switchLanguage, span { color: var(--el-text-color-regular); @@ -135,11 +141,10 @@ .videoContainer { .loginForm { .title { - .switchLanguage, span { color: var(--el-color-white); } } } -} \ No newline at end of file +} diff --git a/src/views/login/index.vue b/src/views/login/index.vue index d524a01..d513dd1 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -50,6 +50,10 @@ --> + + 记住密码 + + {{ $t('login.login') }} @@ -81,12 +85,15 @@ import { LocationQuery, LocationQueryValue, useRoute } from 'vue-router'; import { useSettingsStore } from '@/store/modules/settings'; // import { getCaptchaApi } from '@/api/auth'; import { LoginData } from '@/api/auth/types'; +import { setLocalStorage, getLocalStorage } from '@/utils/storage'; +import { encryption, decryption } from '@/utils/crypto'; const settingsStore = useSettingsStore(); const userStore = useUserStore(); const route = useRoute(); const loginForm = ref(ElForm); const isCapslock = ref(false); // 是否大写锁定 +const remember = ref(false); const resizeStyle = ref(); //视频背景自适应样式 const videoCanPlay = ref(false); @@ -103,7 +110,7 @@ const loginRules = { }; const loading = ref(false); -const captchaBase64 = ref(); +// const captchaBase64 = ref(); function validatePassword(rule: any, value: any, callback: any) { if (value.length < 6) { @@ -120,6 +127,15 @@ function checkCapslock(e: any) { onMounted(() => { // getCaptcha(); + resizeFun(); + const loginInfo = getLocalStorage('loginInfo'); + if (loginInfo != null && Object.keys(loginInfo).length >= 2) { + remember.value = true; + loginData.value.username = loginInfo.username; + loginData.value.password = decryption(loginInfo.password); + } else { + remember.value = false; + } resizeStyle.value = { height: '100vh', width: '100vw' @@ -153,6 +169,13 @@ function loginClick() { userStore .login(loginData.value) .then(() => { + if (remember.value) { + const loginRemember = loginData.value; + loginRemember.password = encryption(loginData.value.password); + setLocalStorage('loginInfo', loginRemember); + } else { + setLocalStorage('loginInfo', {}); + } const query: LocationQuery = route.query; const redirect = (query.redirect as LocationQueryValue) ?? '/'; const otherQueryParams = Object.keys(query).reduce((account: any, current: string) => { diff --git a/vite.config.ts b/vite.config.ts index d830e45..c625c75 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -45,7 +45,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { hmr: true, //配置HMR proxy: { '/dev-api': { - // target: 'http://172.1.2.132:9010/', //本地接口地址 + // target: 'http://172.1.2.146:9010/', //本地接口地址 // target: 'http://172.1.2.90:9010/', //本地接口地址 target: 'http://10.10.10.56:9010/', //线上测试接口地址 changeOrigin: true,