From 90c52d979ee3e001e1e373d8799d7e0dc0d60ccf Mon Sep 17 00:00:00 2001 From: xlsea Date: Mon, 8 Dec 2025 14:38:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(projects):=20=E7=99=BB=E5=BD=95=E8=AE=B0?= =?UTF-8?q?=E4=BD=8F=E5=AF=86=E7=A0=81=E5=8A=A0=E5=AF=86=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.dev | 3 + .env.prod | 3 + .env.test | 3 + pnpm-lock.yaml | 108 +++++++++--------- src/typings/storage.d.ts | 2 +- src/typings/vite-env.d.ts | 1 + .../_builtin/login/modules/pwd-login.vue | 15 ++- 7 files changed, 77 insertions(+), 58 deletions(-) diff --git a/.env.dev b/.env.dev index ab1a6ed4..5fa28ae9 100644 --- a/.env.dev +++ b/.env.dev @@ -13,6 +13,9 @@ VITE_APP_WEBSOCKET=N # app client id VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e +# 记住密码 AES 加密密钥 +VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG + # 接口加密功能开关(如需关闭 后端也必须对应关闭) VITE_APP_ENCRYPT=Y # AES 加密头标识 diff --git a/.env.prod b/.env.prod index b59f1eec..8c47c8ad 100644 --- a/.env.prod +++ b/.env.prod @@ -10,6 +10,9 @@ VITE_APP_WEBSOCKET=N # app client id VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e +# 记住密码 AES 加密密钥 +VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG + # 接口加密功能开关(如需关闭 后端也必须对应关闭) VITE_APP_ENCRYPT=Y # AES 加密头标识 diff --git a/.env.test b/.env.test index e6fa9816..e45ccdc6 100644 --- a/.env.test +++ b/.env.test @@ -10,6 +10,9 @@ VITE_APP_WEBSOCKET=N # app client id VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e +# 记住密码 AES 加密密钥 +VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG + # 接口加密功能开关(如需关闭 后端也必须对应关闭) VITE_APP_ENCRYPT=Y # AES 加密头标识 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 089cac32..398d54d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -972,73 +972,73 @@ packages: '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} - '@napi-rs/canvas-android-arm64@0.1.83': - resolution: {integrity: sha512-TbKM2fh9zXjqFIU8bgMfzG7rkrIYdLKMafgPhFoPwKrpWk1glGbWP7LEu8Y/WrMDqTGFdRqUmuX89yQEzZbkiw==} + '@napi-rs/canvas-android-arm64@0.1.84': + resolution: {integrity: sha512-pdvuqvj3qtwVryqgpAGornJLV6Ezpk39V6wT4JCnRVGy8I3Tk1au8qOalFGrx/r0Ig87hWslysPpHBxVpBMIww==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@napi-rs/canvas-darwin-arm64@0.1.83': - resolution: {integrity: sha512-gp8IDVUloPUmkepHly4xRUOfUJSFNvA4jR7ZRF5nk3YcGzegSFGeICiT4PnYyPgSKEhYAFe1Y2XNy0Mp6Tu8mQ==} + '@napi-rs/canvas-darwin-arm64@0.1.84': + resolution: {integrity: sha512-A8IND3Hnv0R6abc6qCcCaOCujTLMmGxtucMTZ5vbQUrEN/scxi378MyTLtyWg+MRr6bwQJ6v/orqMS9datIcww==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.83': - resolution: {integrity: sha512-r4ZJxiP9OgUbdGZhPDEXD3hQ0aIPcVaywtcTXvamYxTU/SWKAbKVhFNTtpRe1J30oQ25gWyxTkUKSBgUkNzdnw==} + '@napi-rs/canvas-darwin-x64@0.1.84': + resolution: {integrity: sha512-AUW45lJhYWwnA74LaNeqhvqYKK/2hNnBBBl03KRdqeCD4tKneUSrxUqIv8d22CBweOvrAASyKN3W87WO2zEr/A==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.83': - resolution: {integrity: sha512-Uc6aSB05qH1r+9GUDxIE6F5ZF7L0nTFyyzq8ublWUZhw8fEGK8iy931ff1ByGFT04+xHJad1kBcL4R1ZEV8z7Q==} + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.84': + resolution: {integrity: sha512-8zs5ZqOrdgs4FioTxSBrkl/wHZB56bJNBqaIsfPL4ZkEQCinOkrFF7xIcXiHiKp93J3wUtbIzeVrhTIaWwqk+A==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.83': - resolution: {integrity: sha512-eEeaJA7V5KOFq7W0GtoRVbd3ak8UZpK+XLkCgUiFGtlunNw+ZZW9Cr/92MXflGe7o3SqqMUg+f975LPxO/vsOQ==} + '@napi-rs/canvas-linux-arm64-gnu@0.1.84': + resolution: {integrity: sha512-i204vtowOglJUpbAFWU5mqsJgH0lVpNk/Ml4mQtB4Lndd86oF+Otr6Mr5KQnZHqYGhlSIKiU2SYnUbhO28zGQA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@napi-rs/canvas-linux-arm64-musl@0.1.83': - resolution: {integrity: sha512-cAvonp5XpbatVGegF9lMQNchs3z5RH6EtamRVnQvtoRtwbzOMcdzwuLBqDBQxQF79MFbuZNkWj3YRJjZCjHVzw==} + '@napi-rs/canvas-linux-arm64-musl@0.1.84': + resolution: {integrity: sha512-VyZq0EEw+OILnWk7G3ZgLLPaz1ERaPP++jLjeyLMbFOF+Tr4zHzWKiKDsEV/cT7btLPZbVoR3VX+T9/QubnURQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@napi-rs/canvas-linux-riscv64-gnu@0.1.83': - resolution: {integrity: sha512-WFUPQ9qZy31vmLxIJ3MfmHw+R2g/mLCgk8zmh7maJW8snV3vLPA7pZfIS65Dc61EVDp1vaBskwQ2RqPPzwkaew==} + '@napi-rs/canvas-linux-riscv64-gnu@0.1.84': + resolution: {integrity: sha512-PSMTh8DiThvLRsbtc/a065I/ceZk17EXAATv9uNvHgkgo7wdEfTh2C3aveNkBMGByVO3tvnvD5v/YFtZL07cIg==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] libc: [glibc] - '@napi-rs/canvas-linux-x64-gnu@0.1.83': - resolution: {integrity: sha512-X9YwIjsuy50WwOyYeNhEHjKHO8rrfH9M4U8vNqLuGmqsZdKua/GrUhdQGdjq7lTgdY3g4+Ta5jF8MzAa7UAs/g==} + '@napi-rs/canvas-linux-x64-gnu@0.1.84': + resolution: {integrity: sha512-N1GY3noO1oqgEo3rYQIwY44kfM11vA0lDbN0orTOHfCSUZTUyiYCY0nZ197QMahZBm1aR/vYgsWpV74MMMDuNA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@napi-rs/canvas-linux-x64-musl@0.1.83': - resolution: {integrity: sha512-Vv2pLWQS8EnlSM1bstJ7vVhKA+mL4+my4sKUIn/bgIxB5O90dqiDhQjUDLP+5xn9ZMestRWDt3tdQEkGAmzq/A==} + '@napi-rs/canvas-linux-x64-musl@0.1.84': + resolution: {integrity: sha512-vUZmua6ADqTWyHyei81aXIt9wp0yjeNwTH0KdhdeoBb6azHmFR8uKTukZMXfLCC3bnsW0t4lW7K78KNMknmtjg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@napi-rs/canvas-win32-x64-msvc@0.1.83': - resolution: {integrity: sha512-K1TtjbScfRNYhq8dengLLufXGbtEtWdUXPV505uLFPovyGHzDUGXLFP/zUJzj6xWXwgUjHNLgEPIt7mye0zr6Q==} + '@napi-rs/canvas-win32-x64-msvc@0.1.84': + resolution: {integrity: sha512-YSs8ncurc1xzegUMNnQUTYrdrAuaXdPMOa+iYYyAxydOtg0ppV386hyYMsy00Yip1NlTgLCseRG4sHSnjQx6og==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/canvas@0.1.83': - resolution: {integrity: sha512-f9GVB9VNc9vn/nroc9epXRNkVpvNPZh69+qzLJIm9DfruxFqX0/jsXG46OGWAJgkO4mN0HvFHjRROMXKVmPszg==} + '@napi-rs/canvas@0.1.84': + resolution: {integrity: sha512-88FTNFs4uuiFKP0tUrPsEXhpe9dg7za9ILZJE08pGdUveMIDeana1zwfVkqRHJDPJFAmGY3dXmJ99dzsy57YnA==} engines: {node: '>= 10'} '@napi-rs/wasm-runtime@0.2.12': @@ -2343,8 +2343,8 @@ packages: resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} engines: {node: '>=0.10.0'} - baseline-browser-mapping@2.9.3: - resolution: {integrity: sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==} + baseline-browser-mapping@2.9.4: + resolution: {integrity: sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==} hasBin: true big.js@5.2.2: @@ -3820,8 +3820,8 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - katex@0.16.25: - resolution: {integrity: sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==} + katex@0.16.27: + resolution: {integrity: sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==} hasBin: true keyv@4.5.4: @@ -6005,48 +6005,48 @@ snapshots: dependencies: langium: 3.3.1 - '@napi-rs/canvas-android-arm64@0.1.83': + '@napi-rs/canvas-android-arm64@0.1.84': optional: true - '@napi-rs/canvas-darwin-arm64@0.1.83': + '@napi-rs/canvas-darwin-arm64@0.1.84': optional: true - '@napi-rs/canvas-darwin-x64@0.1.83': + '@napi-rs/canvas-darwin-x64@0.1.84': optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.83': + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.84': optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.83': + '@napi-rs/canvas-linux-arm64-gnu@0.1.84': optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.83': + '@napi-rs/canvas-linux-arm64-musl@0.1.84': optional: true - '@napi-rs/canvas-linux-riscv64-gnu@0.1.83': + '@napi-rs/canvas-linux-riscv64-gnu@0.1.84': optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.83': + '@napi-rs/canvas-linux-x64-gnu@0.1.84': optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.83': + '@napi-rs/canvas-linux-x64-musl@0.1.84': optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.83': + '@napi-rs/canvas-win32-x64-msvc@0.1.84': optional: true - '@napi-rs/canvas@0.1.83': + '@napi-rs/canvas@0.1.84': optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.83 - '@napi-rs/canvas-darwin-arm64': 0.1.83 - '@napi-rs/canvas-darwin-x64': 0.1.83 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.83 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.83 - '@napi-rs/canvas-linux-arm64-musl': 0.1.83 - '@napi-rs/canvas-linux-riscv64-gnu': 0.1.83 - '@napi-rs/canvas-linux-x64-gnu': 0.1.83 - '@napi-rs/canvas-linux-x64-musl': 0.1.83 - '@napi-rs/canvas-win32-x64-msvc': 0.1.83 + '@napi-rs/canvas-android-arm64': 0.1.84 + '@napi-rs/canvas-darwin-arm64': 0.1.84 + '@napi-rs/canvas-darwin-x64': 0.1.84 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.84 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.84 + '@napi-rs/canvas-linux-arm64-musl': 0.1.84 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.84 + '@napi-rs/canvas-linux-x64-gnu': 0.1.84 + '@napi-rs/canvas-linux-x64-musl': 0.1.84 + '@napi-rs/canvas-win32-x64-msvc': 0.1.84 optional: true '@napi-rs/wasm-runtime@0.2.12': @@ -6938,7 +6938,7 @@ snapshots: highlight.js: 11.11.1 hotkeys-js: 3.13.15 jsbarcode: 3.12.1 - katex: 0.16.25 + katex: 0.16.27 lowlight: 3.3.0 mermaid: 11.12.2 nzh: 1.0.14 @@ -7018,7 +7018,7 @@ snapshots: highlight.js: 11.11.1 hotkeys-js: 3.13.15 jsbarcode: 3.12.1 - katex: 0.16.25 + katex: 0.16.27 lowlight: 3.3.0 mermaid: 11.12.2 nzh: 1.0.14 @@ -7584,7 +7584,7 @@ snapshots: mixin-deep: 1.3.2 pascalcase: 0.1.1 - baseline-browser-mapping@2.9.3: {} + baseline-browser-mapping@2.9.4: {} big.js@5.2.2: {} @@ -7626,7 +7626,7 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.3 + baseline-browser-mapping: 2.9.4 caniuse-lite: 1.0.30001759 electron-to-chromium: 1.5.266 node-releases: 2.0.27 @@ -9231,7 +9231,7 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - katex@0.16.25: + katex@0.16.27: dependencies: commander: 8.3.0 @@ -9395,7 +9395,7 @@ snapshots: dagre-d3-es: 7.0.13 dayjs: 1.11.19 dompurify: 3.3.0 - katex: 0.16.25 + katex: 0.16.27 khroma: 2.1.0 lodash-es: 4.17.21 marked: 16.4.2 @@ -9692,7 +9692,7 @@ snapshots: pdfjs-dist@5.4.296: optionalDependencies: - '@napi-rs/canvas': 0.1.83 + '@napi-rs/canvas': 0.1.84 perfect-debounce@1.0.0: {} diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts index 35b1b6c8..fe9bbaf6 100644 --- a/src/typings/storage.d.ts +++ b/src/typings/storage.d.ts @@ -45,7 +45,7 @@ declare namespace StorageType { /** The last login user id */ lastLoginUserId: CommonType.IdType; /** The login form rember */ - loginRember: Api.Auth.PwdLoginForm; + loginRember: string; /** The tenant id */ tenantId: CommonType.IdType; } diff --git a/src/typings/vite-env.d.ts b/src/typings/vite-env.d.ts index b114a2e8..ea6cc672 100644 --- a/src/typings/vite-env.d.ts +++ b/src/typings/vite-env.d.ts @@ -113,6 +113,7 @@ declare namespace Env { /** The launch editor */ readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor']; readonly VITE_APP_CLIENT_ID?: string; + readonly VITE_REMEMBER_ME_AES_KEY?: string; readonly VITE_APP_ENCRYPT?: CommonType.YesOrNo; readonly VITE_HEADER_FLAG?: string; readonly VITE_APP_RSA_PUBLIC_KEY?: string; diff --git a/src/views/_builtin/login/modules/pwd-login.vue b/src/views/_builtin/login/modules/pwd-login.vue index 1c35c668..0a60c645 100644 --- a/src/views/_builtin/login/modules/pwd-login.vue +++ b/src/views/_builtin/login/modules/pwd-login.vue @@ -2,13 +2,18 @@ import { computed, reactive, ref } from 'vue'; import type { SelectOption } from 'naive-ui'; import { useLoading } from '@sa/hooks'; +import CryptoJS from 'crypto-js'; import { fetchCaptchaCode, fetchTenantList } from '@/service/api'; import { fetchSocialAuthBinding } from '@/service/api/system'; import { useAuthStore } from '@/store/modules/auth'; import { useRouterPush } from '@/hooks/common/router'; import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { localStg } from '@/utils/storage'; +import { decryptWithAes, encryptWithAes } from '@/utils/crypto'; import { $t } from '@/locales'; + +const aesKey = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_REMEMBER_ME_AES_KEY || 'pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG'); + defineOptions({ name: 'PwdLogin' }); @@ -33,6 +38,7 @@ const model: Api.Auth.PwdLoginForm = reactive({ username: 'admin', password: 'admin123' }); + type RuleKey = Extract; const rules = computed>(() => { @@ -48,6 +54,7 @@ const rules = computed>(() => { return loginRules; }); + async function handleFetchTenantList() { startTenantLoading(); const { data, error } = await fetchTenantList(); @@ -71,7 +78,7 @@ async function handleSubmit() { // 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码 if (remberMe.value) { const { tenantId, username, password } = model; - localStg.set('loginRember', { tenantId, username, password }); + localStg.set('loginRember', encryptWithAes(JSON.stringify({ tenantId, username, password }), aesKey)); } else { // 否则移除 localStg.remove('loginRember'); @@ -101,8 +108,10 @@ handleFetchCaptchaCode(); function handleLoginRember() { const loginRember = localStg.get('loginRember'); if (!loginRember) return; - remberMe.value = true; - Object.assign(model, loginRember); + try { + remberMe.value = true; + Object.assign(model, JSON.parse(decryptWithAes(loginRember, aesKey))); + } catch {} } handleLoginRember();