From d645c49450ca3daec8eea5be8e5f9921116d42ac Mon Sep 17 00:00:00 2001 From: bobowiki <69181829+bobowiki@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:30:06 +0800 Subject: [PATCH] Feat login page (#1473) * feat: login * feat: recommmit remove node-module --------- Co-authored-by: yikai --- node_modules/.yarn-integrity | 12 ++ threadpool/console-new/.eslintrc.js | 2 + threadpool/console-new/.prettierignore | 3 +- threadpool/console-new/craco.config.js | 20 +-- threadpool/console-new/package.json | 2 + threadpool/console-new/src/App.tsx | 6 +- .../src/components/header/index.module.less | 2 +- .../src/components/header/index.tsx | 33 ++-- .../components/layout-com/index.module.less | 6 +- .../src/components/layout-com/index.tsx | 31 ++-- .../src/components/theme-com/index.tsx | 4 +- .../console-new/src/config/i18n/index.ts | 2 +- threadpool/console-new/src/context/index.tsx | 31 ++-- threadpool/console-new/src/hooks/index.ts | 1 - .../console-new/src/hooks/useThemeMode.ts | 14 -- .../console-new/src/page/home/index.tsx | 7 - .../src/page/login/index.module.less | 37 +++++ .../console-new/src/page/login/index.tsx | 141 +++++++++++++++++- .../console-new/src/page/login/router.ts | 6 + .../console-new/src/page/login/service.ts | 13 ++ threadpool/console-new/src/react-app-env.d.ts | 1 + threadpool/console-new/src/route/index.tsx | 3 +- threadpool/console-new/src/typings/index.ts | 17 +++ .../console-new/src/utils/common/index.ts | 44 +++++- .../console-new/src/utils/request/index.ts | 5 +- threadpool/console-new/yarn.lock | 26 +++- 26 files changed, 369 insertions(+), 100 deletions(-) create mode 100644 node_modules/.yarn-integrity delete mode 100644 threadpool/console-new/src/hooks/useThemeMode.ts create mode 100644 threadpool/console-new/src/page/login/index.module.less create mode 100644 threadpool/console-new/src/page/login/router.ts create mode 100644 threadpool/console-new/src/page/login/service.ts diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity new file mode 100644 index 00000000..42a6cb98 --- /dev/null +++ b/node_modules/.yarn-integrity @@ -0,0 +1,12 @@ +{ + "systemParams": "darwin-arm64-93", + "modulesFolders": [ + "node_modules" + ], + "flags": [], + "linkedModules": [], + "topLevelPatterns": [], + "lockfileEntries": {}, + "files": [], + "artifacts": {} +} \ No newline at end of file diff --git a/threadpool/console-new/.eslintrc.js b/threadpool/console-new/.eslintrc.js index 38eb2edf..92c71e51 100644 --- a/threadpool/console-new/.eslintrc.js +++ b/threadpool/console-new/.eslintrc.js @@ -26,5 +26,7 @@ module.exports = { '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-non-null-assertion': 0, '@typescript-eslint/no-var-requires': 0, + 'import/no-anonymous-default-export': 0, + 'jsx-a11y/anchor-is-valid': 0, }, }; diff --git a/threadpool/console-new/.prettierignore b/threadpool/console-new/.prettierignore index 353efa09..473d9c18 100644 --- a/threadpool/console-new/.prettierignore +++ b/threadpool/console-new/.prettierignore @@ -1,3 +1,4 @@ /.git node_modules -build \ No newline at end of file +build +src/lib/* \ No newline at end of file diff --git a/threadpool/console-new/craco.config.js b/threadpool/console-new/craco.config.js index f94068ae..f06ec6af 100644 --- a/threadpool/console-new/craco.config.js +++ b/threadpool/console-new/craco.config.js @@ -1,4 +1,3 @@ -// craco.config.js const CracoLessPlugin = require('craco-less'); const lessModuleRegex = /\.module\.less$/; const path = require('path'); @@ -33,25 +32,28 @@ module.exports = { }, }, ], - // style: { - // modules: { - // localIdentName: '[local]_[hash:base64:5]', // 可以自定义你的类名生成规则 - // }, - // }, webpack: { alias: { '@': resolve('src'), }, }, devServer: { - port: 3001, + port: 3000, headers: { 'Access-Control-Allow-Origin': '*', }, proxy: { - '/hippo4j': { - target: 'http://console.hippo4j.cn', + '/hippo4j/v1/cs': { + target: 'http://console.hippo4j.cn:6691/hippo4j/v1/cs', + pathRewrite: { '^/hippo4j/v1/cs': '' }, changeOrigin: true, + secure: false, + onProxyReq: proxyReq => { + console.log(`Proxying request to: ${proxyReq.path}`); + }, + onProxyRes: proxyRes => { + console.log(`Received response with status: ${proxyRes.statusCode}`); + }, }, }, }, diff --git a/threadpool/console-new/package.json b/threadpool/console-new/package.json index 43c1e5f8..cef35383 100644 --- a/threadpool/console-new/package.json +++ b/threadpool/console-new/package.json @@ -11,6 +11,7 @@ "@testing-library/user-event": "^13.5.0", "ahooks": "^3.7.8", "antd": "^5.4.7", + "classnames": "^2.3.2", "dayjs": "^1.11.9", "i18next": "^23.5.1", "i18next-browser-languagedetector": "^7.1.0", @@ -69,6 +70,7 @@ "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", + "http-proxy-middleware": "^2.0.6", "husky": "^8.0.0", "less-loader": "^11.1.0", "lint-staged": "^13.2.2", diff --git a/threadpool/console-new/src/App.tsx b/threadpool/console-new/src/App.tsx index c983e76a..3dba11da 100644 --- a/threadpool/console-new/src/App.tsx +++ b/threadpool/console-new/src/App.tsx @@ -1,9 +1,6 @@ -// import { Suspense } from 'react'; import LayoutCom from './components/layout-com'; import { Routes, Route, Link } from 'react-router-dom'; - import routeList from './route'; -import Login from '@/page/login'; import { MenuProps } from 'antd'; import { useTran } from './hooks'; import { STR_MAP } from './config/i18n/locales/constants'; @@ -24,9 +21,8 @@ const App = () => { ]; return ( - + - {routeList.map(item => ( ))} diff --git a/threadpool/console-new/src/components/header/index.module.less b/threadpool/console-new/src/components/header/index.module.less index e4cf7f42..07c850e0 100644 --- a/threadpool/console-new/src/components/header/index.module.less +++ b/threadpool/console-new/src/components/header/index.module.less @@ -5,7 +5,7 @@ .logo { display: flex; flex-direction: column; - width: 200px; + width: 50px; img { flex: 1; object-fit: contain; diff --git a/threadpool/console-new/src/components/header/index.tsx b/threadpool/console-new/src/components/header/index.tsx index dddb3252..fdea38d5 100644 --- a/threadpool/console-new/src/components/header/index.tsx +++ b/threadpool/console-new/src/components/header/index.tsx @@ -2,13 +2,16 @@ import React, { useContext } from 'react'; import style from './index.module.less'; import { UserOutlined } from '@ant-design/icons'; import { Avatar, Button, Col, Dropdown, Row, Switch } from 'antd'; -import { useThemeMode } from '@/hooks'; import { MyContext } from '@/context'; import IconFont from '@/components/icon'; +import { LANG_NAME, MyStoreValues, THEME_NAME } from '@/typings'; +import { useNavigate } from 'react-router-dom'; const HeaderChild = () => { - const { isDark, setIsDark } = useThemeMode(); - const { lang, setLang } = useContext(MyContext); + const { lang, themeName, setLang, setThemeName } = useContext(MyContext); + const navigate = useNavigate(); + // console.log('setLang:::', setLang); + // setLang && setLang(LANG_NAME.EN); const items = [ { @@ -29,18 +32,14 @@ const HeaderChild = () => { }, { key: '3', - label: ( - - 登出 - - ), + label: navigate('/login')}>登出, }, ]; return (
-
- +
navigate('/home')}> +
@@ -51,18 +50,10 @@ const HeaderChild = () => { - {/* { - lang === 'zh' ? setLang('en') : setLang('zh'); - }} - style={{ cursor: 'pointer' }} - > - {lang === 'zh' ? 'zh' : 'en'} - */} +
+ + + + + + ), + [form, loading, handleLogin] + ); + + const items: TabsProps['items'] = [ + { + key: TABS_KEY.LOGIN, + label: '账号密码登陆', + children: formNode, + }, + { + key: TABS_KEY.PHONE, + label: '手机号登陆', + children: formNode, + }, + ]; + return ( +
+
+
+
+ +
+ 全球最好用的线程池管理工具 +
+ +
+
+
+ ); }; export default Login; diff --git a/threadpool/console-new/src/page/login/router.ts b/threadpool/console-new/src/page/login/router.ts new file mode 100644 index 00000000..143acaaf --- /dev/null +++ b/threadpool/console-new/src/page/login/router.ts @@ -0,0 +1,6 @@ +import { IRouterList } from '@/typings'; +import Login from '.'; + +const routerList: IRouterList[] = [{ path: '/login', component: Login }]; + +export default routerList; diff --git a/threadpool/console-new/src/page/login/service.ts b/threadpool/console-new/src/page/login/service.ts new file mode 100644 index 00000000..0e9c9426 --- /dev/null +++ b/threadpool/console-new/src/page/login/service.ts @@ -0,0 +1,13 @@ +import request from '@/utils'; + +const fetchLogin = async (body: any) => { + const { data } = await request<{ data: string; roles: string[] }>('/hippo4j/v1/cs/auth/login', { + method: 'POST', + body, + }); + return data; +}; + +export default { + fetchLogin, +}; diff --git a/threadpool/console-new/src/react-app-env.d.ts b/threadpool/console-new/src/react-app-env.d.ts index bb172a71..6ab136be 100644 --- a/threadpool/console-new/src/react-app-env.d.ts +++ b/threadpool/console-new/src/react-app-env.d.ts @@ -1,2 +1,3 @@ /// declare module '*.less'; +declare module 'crypto-browserify' {} diff --git a/threadpool/console-new/src/route/index.tsx b/threadpool/console-new/src/route/index.tsx index 7a2d8897..54d9f987 100644 --- a/threadpool/console-new/src/route/index.tsx +++ b/threadpool/console-new/src/route/index.tsx @@ -3,9 +3,10 @@ import homeRouter from '@/page/home/router'; import aboutRouter from '@/page/about/router'; import ThreadPoolRouter from '@/page/thread-pool/router'; import tenantRouter from '@/page/tenant/router'; +import LoginRouter from '@/page/login/router'; // import itemRouter from '@/page/item/router'; // import userRouter from '@/page/user/router'; // import logRouter from '@/page/log/router'; -const routerList: IRouterList[] = [...homeRouter, ...aboutRouter, ...tenantRouter, ...ThreadPoolRouter]; +const routerList: IRouterList[] = [...homeRouter, ...aboutRouter, ...tenantRouter, ...ThreadPoolRouter, ...LoginRouter]; export default routerList; diff --git a/threadpool/console-new/src/typings/index.ts b/threadpool/console-new/src/typings/index.ts index 6c1f658c..d7610df2 100644 --- a/threadpool/console-new/src/typings/index.ts +++ b/threadpool/console-new/src/typings/index.ts @@ -1,6 +1,16 @@ import { ReactNode } from 'react'; import React from 'react'; +export enum THEME_NAME { + DEFAULT = 'default', + DARK = 'dark', +} + +export enum LANG_NAME { + ZH = 'zh', + EN = 'en', +} + export type IRouterList = { path: string; component: () => React.JSX.Element; @@ -11,3 +21,10 @@ export type IMenuList = { key: string; icon?: ReactNode; }; + +export interface MyStoreValues { + themeName?: THEME_NAME | undefined; + lang?: LANG_NAME; + setThemeName?: (name: THEME_NAME) => void; + setLang?: (lang: LANG_NAME) => void; +} diff --git a/threadpool/console-new/src/utils/common/index.ts b/threadpool/console-new/src/utils/common/index.ts index 2fd348e0..8ae65582 100644 --- a/threadpool/console-new/src/utils/common/index.ts +++ b/threadpool/console-new/src/utils/common/index.ts @@ -1,6 +1,44 @@ +import Cookie from 'js-cookie'; +// import { Buffer } from 'buffer'; +// import crypto from 'crypto-browserify'; + +// /** +// * generate key +// * @returns {string} key(length 16) +// */ +// export function genKey() { +// let chars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; +// let result = ''; +// for (let i = 16; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]; +// return result; +// } +// /** +// * encode message +// * @param msg message +// * @param key key +// * @returns {string} encoded message +// */ +// export function encrypt(msg: string, key: string) { +// try { +// let pwd = Buffer.from(key); +// let iv = (crypto as any).randomBytes(12); +// let cipher = (crypto as any).createCipheriv('aes-128-gcm', pwd, iv); +// let enc = cipher.update(msg, 'utf8', 'base64'); +// enc += cipher.final('base64'); +// let tags = cipher.getAuthTag(); +// enc = Buffer.from(enc, 'base64') as any; +// let totalLength = iv.length + enc.length + tags.length; +// let bufferMsg = Buffer.concat([iv, enc as any, tags], totalLength); +// return bufferMsg.toString('base64'); +// } catch (e) { +// console.log('Encrypt is error', e); +// return null; +// } +// } import _ from 'lodash'; // is plain object +const TokenKey = 'Admin-Token'; const isPlainObject = (obj: { [key: string]: any }): boolean => { let proto, Ctor; if (!obj || typeof obj !== 'object') return false; @@ -10,6 +48,10 @@ const isPlainObject = (obj: { [key: string]: any }): boolean => { return typeof Ctor === 'function' && Ctor === Object; // insure is new by Object or {} }; +const setToken = (token: string) => { + Cookie.set(TokenKey, token); +}; + /** * @description 忽略 object 中 value 为空的元素 * @param obj @@ -37,4 +79,4 @@ const isEmpty = (value: any) => { return typeof value === 'object' ? _.isEmpty(value) : isNilValue(value); }; -export { isPlainObject, isEmpty, filterEmptyField }; +export { isPlainObject, isEmpty, filterEmptyField, setToken }; diff --git a/threadpool/console-new/src/utils/request/index.ts b/threadpool/console-new/src/utils/request/index.ts index 9d9a0f13..7a537a87 100644 --- a/threadpool/console-new/src/utils/request/index.ts +++ b/threadpool/console-new/src/utils/request/index.ts @@ -32,7 +32,7 @@ type Response = { code?: string | number; }; -let baseURL = 'http://console.hippo4j.cn'; +let baseURL = ''; const inital: RequestOptions = { method: 'GET', @@ -40,6 +40,8 @@ const inital: RequestOptions = { body: null, headers: { 'Content-Type': 'application/json', + Authorization: + 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMCxiYW94aW55aV91c2VyIiwiaXNzIjoiYWRtaW4iLCJleHAiOjE2OTU3MzAwNzYsImlhdCI6MTY5NTEyNTI3Niwicm9sIjoiUk9MRV9VU0VSIn0.4cWyhllP7u-aoRAIHs3nMggsgl4-LUCVBas8WE0FJYIe-YNS0wGf1_0RJq3TUGw00KmSaSRPKdoPgRTFqEphZA', }, credentials: true, responseType: 'JSON', @@ -117,6 +119,7 @@ function request(url: string, config: RequestOptions): Promise> { return fetch(url, config as any).then(function onfulfilled(response) { let { status, statusText } = response; + console.log('status:::', status, response); if (status >= 200 && status < 400) { let result; switch (responseType) { diff --git a/threadpool/console-new/yarn.lock b/threadpool/console-new/yarn.lock index dcdbc5fb..9bebc0fc 100644 --- a/threadpool/console-new/yarn.lock +++ b/threadpool/console-new/yarn.lock @@ -1196,7 +1196,7 @@ resolved "https://registry.npmmirror.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.22.15" resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== @@ -2060,6 +2060,14 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@tanem/react-nprogress@^5.0.51": + version "5.0.51" + resolved "https://registry.npmmirror.com/@tanem/react-nprogress/-/react-nprogress-5.0.51.tgz#6cbdb52a0a27ecf845f61d809ef6fd45b063662d" + integrity sha512-YxNUCpznuBVA+PhjEzFmxaa1czXgU+5Ojchw5JBK7DQS6SHIgNudpFohWpNBWMu2KWByGJ2OLH2OwbM/XyP18Q== + dependencies: + "@babel/runtime" "^7.22.15" + hoist-non-react-statics "^3.3.2" + "@testing-library/dom@^8.5.0": version "8.20.1" resolved "https://registry.npmmirror.com/@testing-library/dom/-/dom-8.20.1.tgz#2e52a32e46fc88369eef7eef634ac2a192decd9f" @@ -2332,6 +2340,11 @@ resolved "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash@^4.14.198": + version "4.14.198" + resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.198.tgz#4d27465257011aedc741a809f1269941fa2c5d4c" + integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== + "@types/mime@*": version "3.0.1" resolved "https://registry.npmmirror.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" @@ -5598,6 +5611,13 @@ he@^1.2.0: resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hoopy@^0.1.4: version "0.1.4" resolved "https://registry.npmmirror.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -5711,7 +5731,7 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@^2.0.3: +http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.6: version "2.0.6" resolved "https://registry.npmmirror.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== @@ -8996,7 +9016,7 @@ react-i18next@^13.2.2: "@babel/runtime" "^7.22.5" html-parse-stringify "^3.0.1" -react-is@^16.12.0, react-is@^16.13.1: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==