diff --git a/package.json b/package.json index c0cc4f0..8a368e8 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "dependencies": { "@ant-design/icons": "^5.3.0", "antd": "^5.14.1", + "crypto-js": "^4.2.0", "dayjs": "^1.11.10", "dom-copilot": "1.0.0-Beta", "path-copilot": "1.0.0-Beta", @@ -44,6 +45,7 @@ "use-compare": "^1.0.0" }, "devDependencies": { + "@types/crypto-js": "^4.2.2", "@types/express": "^4.17.21", "@types/react": "^18.2.56", "@types/react-dom": "^18.2.19", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f7c7c5..afdd115 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: antd: specifier: ^5.14.1 version: 5.14.1(react-dom@18.2.0)(react@18.2.0) + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 dayjs: specifier: ^1.11.10 version: 1.11.10 @@ -43,6 +46,9 @@ dependencies: version: 1.0.0(react@18.2.0) devDependencies: + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 '@types/express': specifier: ^4.17.21 version: 4.17.21 @@ -2059,6 +2065,10 @@ packages: '@types/node': 20.11.19 dev: true + /@types/crypto-js@4.2.2: + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==, tarball: https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz} + dev: true + /@types/eslint-scope@3.7.7: resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==, tarball: https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz} dependencies: @@ -4056,6 +4066,10 @@ packages: randomfill: 1.0.4 dev: false + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==, tarball: https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz} + dev: false + /css-blank-pseudo@3.0.3(postcss@8.4.35): resolution: {integrity: sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==, tarball: https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz} engines: {node: ^12 || ^14 || >=16} diff --git a/src/pages/Login/components/LoginBg/index.tsx b/src/pages/Login/components/LoginBg/index.tsx index da16633..3b45837 100755 --- a/src/pages/Login/components/LoginBg/index.tsx +++ b/src/pages/Login/components/LoginBg/index.tsx @@ -10,7 +10,7 @@ const LoginBg: React.FC = ({ children }) => {
- R-ADMIN + G-ADMIN

用真诚

diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index 4f5ec7f..20f2828 100755 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -1,4 +1,5 @@ import { login } from '@/services/login'; +import { decrypt, encrypt } from '@/utils'; import { AlipayCircleFilled, GithubFilled, @@ -7,7 +8,7 @@ import { WechatFilled, } from '@ant-design/icons'; import { Button, Checkbox, Form, Input, Space, message } from 'antd'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { flushSync } from 'react-dom'; import storetify from 'storetify'; import { FormattedMessage, useModel, useNavigate } from 'umi'; @@ -27,6 +28,8 @@ const LoginPage: React.FC = () => { const { initialState, setInitialState } = useModel('@@initialState'); const [isLogging, setLogging] = useState(false); + const [form] = Form.useForm(); + const navigate = useNavigate(); const fetchUserInfo = async () => { @@ -44,6 +47,20 @@ const LoginPage: React.FC = () => { const handleSubmit = async (values: any) => { setLogging(true); + if (values.rememberMe) { + const { username, password, rememberMe } = values; + storetify( + 'rememberMe', + { + username, + password: encrypt(password), + rememberMe, + }, + 60 * 60 * 24 * 30, + ); + } else { + storetify('rememberMe', undefined); + } try { const res = await login({ ...values }); storetify(TOKEN_KEY, res.data.accessToken); @@ -55,6 +72,21 @@ const LoginPage: React.FC = () => { setLogging(false); } }; + const getRemember = () => { + const { username, password, rememberMe } = + (storetify('rememberMe') as any) || {}; + const values = form.getFieldsValue(['username', 'password', 'rememberMe']); + const loginForm = { + username: username === undefined ? values.username : username, + password: password === undefined ? values.password : decrypt(password), + rememberMe: + rememberMe === undefined ? values.rememberMe : Boolean(rememberMe), + }; + form.setFieldsValue(loginForm); + }; + useEffect(() => { + getRemember(); + }, []); return (
@@ -63,9 +95,10 @@ const LoginPage: React.FC = () => {
欢迎开启新世界
{ await handleSubmit(values); }} @@ -96,7 +129,7 @@ const LoginPage: React.FC = () => { /> - + diff --git a/src/utils/index.ts b/src/utils/index.ts index 5cced6b..ebd4bf8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1 +1,2 @@ export { default as logger } from './logger'; +export { decrypt, encrypt } from './secret'; diff --git a/src/utils/secret.ts b/src/utils/secret.ts new file mode 100644 index 0000000..6c0912f --- /dev/null +++ b/src/utils/secret.ts @@ -0,0 +1,30 @@ +import CryptoJS from 'crypto-js'; +const aseKey = '0123456789abcdef'; +const iv = 'abcdef0123456789'; +let key = CryptoJS.enc.Utf8.parse(aseKey); +let ivs = CryptoJS.enc.Utf8.parse(iv); + +//加密 +export function encrypt(data: any) { + let encrypted = CryptoJS.AES.encrypt(data, key, { + iv: ivs, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + return encrypted.toString(); +} + +//解密 +export function decrypt(data: any) { + let decrypt = CryptoJS.AES.decrypt(data, key, { + iv: ivs, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + return CryptoJS.enc.Utf8.stringify(decrypt).toString(); +} + +export default { + encrypt, + decrypt, +};