@ -1,35 +1,41 @@
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"typescript.tsdk":"./node_modules/typescript/lib"
|
||||
}
|
||||
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[less]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 2.1 MiB |
After Width: | Height: | Size: 904 KiB |
After Width: | Height: | Size: 2.9 MiB |
After Width: | Height: | Size: 925 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 33 KiB |
@ -0,0 +1,12 @@
|
||||
{
|
||||
"systemParams": "darwin-arm64-93",
|
||||
"modulesFolders": [
|
||||
"node_modules"
|
||||
],
|
||||
"flags": [],
|
||||
"linkedModules": [],
|
||||
"topLevelPatterns": [],
|
||||
"lockfileEntries": {},
|
||||
"files": [],
|
||||
"artifacts": {}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
/.git
|
||||
node_modules
|
||||
build
|
||||
build
|
||||
src/lib/*
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.3 KiB |
@ -1,128 +0,0 @@
|
||||
import request from "../axios/request"
|
||||
|
||||
export function userLogin(data) {
|
||||
return request('post', '/hippo4j/v1/cs/auth/login', data)
|
||||
}
|
||||
|
||||
export function getInfo() {
|
||||
return request('get', '/hippo4j/v1/cs/user/info')
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request('post', '/hippo4j/v1/cs/user/logout')
|
||||
}
|
||||
|
||||
function islogin({commit}, userInfo) {
|
||||
const {username, password} = userInfo
|
||||
return new Promise((resolve, reject) => {
|
||||
let key = genKey()
|
||||
let encodePassword = encrypt(password, key)
|
||||
key = key.split("").reverse().join("")
|
||||
login({username: username.trim(), password: encodePassword, tag: key, rememberMe: 1})
|
||||
.then((response) => {
|
||||
const {data} = response
|
||||
const {roles} = response
|
||||
commit('SET_TOKEN', data)
|
||||
localStorage.setItem('roles', JSON.stringify(roles))
|
||||
localStorage.setItem('USER_ROLE', roles[0])
|
||||
setToken(data)
|
||||
resolve()
|
||||
})
|
||||
.catch((error) => {
|
||||
// alert('登录失败')
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// get user info
|
||||
function getInfo({commit, state}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = {}
|
||||
data.roles = JSON.parse(localStorage.getItem('roles'))
|
||||
commit('SET_ROLES', data.roles)
|
||||
resolve(data)
|
||||
})
|
||||
}
|
||||
|
||||
// user logout
|
||||
function logout({commit, state}) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// logout(state.token).then(() => {
|
||||
// commit('SET_TOKEN', '')
|
||||
// commit('SET_ROLES', [])
|
||||
// removeToken()
|
||||
// resetRouter()
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
return new Promise((resolve) => {
|
||||
commit('SET_TOKEN', '')
|
||||
commit('SET_ROLES', [])
|
||||
removeToken()
|
||||
resetRouter()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
// remove token
|
||||
function resetToken({commit}) {
|
||||
return new Promise((resolve) => {
|
||||
commit('SET_TOKEN', '')
|
||||
commit('SET_ROLES', [])
|
||||
removeToken()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
// dynamically modify permissions
|
||||
function changeRoles({commit, dispatch}, role) {
|
||||
return new Promise(async (resolve) => {
|
||||
const token = role + '-token'
|
||||
|
||||
commit('SET_TOKEN', token)
|
||||
setToken(token)
|
||||
|
||||
const {roles} = await dispatch('getInfo')
|
||||
|
||||
resetRouter()
|
||||
|
||||
// generate accessible routes map based on roles
|
||||
const accessRoutes = await dispatch('permission/generateRoutes', roles, {root: true})
|
||||
|
||||
// dynamically add accessible routes
|
||||
router.addRoutes(accessRoutes)
|
||||
|
||||
// reset visited views and cached views
|
||||
dispatch('tagsView/delAllViews', null, {root: true})
|
||||
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const mutations = {
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
},
|
||||
SET_INTRODUCTION: (state, introduction) => {
|
||||
state.introduction = introduction
|
||||
},
|
||||
SET_NAME: (state, name) => {
|
||||
state.name = name
|
||||
},
|
||||
SET_AVATAR: (state, avatar) => {
|
||||
state.avatar = avatar
|
||||
},
|
||||
SET_ROLES: (state, roles) => {
|
||||
state.roles = roles
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
userLogin,
|
||||
getInfo,
|
||||
logout,
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
const devBaseUrl = 'http://console.hippo4j.cn:6691/hippo4j/v1/cs'
|
||||
const proBaseUrl = 'http://console.hippo4j.cn:6691/hippo4j/v1/cs '
|
||||
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseUrl : proBaseUrl
|
||||
export const TIMEOUT = 5000
|
@ -1,192 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import { BASE_URL, TIMEOUT } from './config';
|
||||
const instance = axios.create({
|
||||
baseURL: BASE_URL,
|
||||
timeout: TIMEOUT,
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(
|
||||
config => {
|
||||
config.data = JSON.stringify(config.data);
|
||||
config.headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
return config
|
||||
}, err => {
|
||||
return Promise.reject(err)
|
||||
}
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
res => {
|
||||
if (res.code === 'A000004') {
|
||||
removeToken()
|
||||
resetRouter()
|
||||
alert(res.message)
|
||||
document.location.href = 'index.html'
|
||||
} else if (res.code !== '20000' && res.code !== '0' && res.code !== '200') {
|
||||
Message({
|
||||
message: res.message || 'Error',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
|
||||
if (res.code === '50008' || res.code === '50012' || res.code === '50014') {
|
||||
// to re-login
|
||||
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
|
||||
confirmButtonText: 'Re-Login',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
store.dispatch('user/resetToken').then(() => {
|
||||
location.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
console.log(res)
|
||||
return Promise.reject(new Error(res.message || 'Error'))
|
||||
} else {
|
||||
const { data } = response
|
||||
const { code } = data
|
||||
// 状态码为0||200表示api成功
|
||||
if (code === '0') {
|
||||
const { data: res } = data
|
||||
return res
|
||||
} else if (code === '200') {
|
||||
return data
|
||||
} else {
|
||||
// 返回数据
|
||||
return res
|
||||
}
|
||||
}
|
||||
return response
|
||||
}, err => {
|
||||
console.log('err' + err) // for debug
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(err)
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 封装get
|
||||
* @param {String} url
|
||||
* @param {String} param
|
||||
* @returns
|
||||
*/
|
||||
export function get(url, param = {}) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
axios.get(url, {
|
||||
params: param
|
||||
}).then((response) => {
|
||||
console.log("get error: url, params, state",url, params, response.data)
|
||||
resolve(response.data)
|
||||
}).catch(err => {
|
||||
msg(err)
|
||||
reject(err)
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 封装post
|
||||
* @param {String} url
|
||||
* @param {Object} param
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function post(url, param) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
axios.post(url, param).then(response => {
|
||||
resolve(response.data)
|
||||
}, err => {
|
||||
reject(err)
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
export default function (fecth, url, param) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
switch(fecth) {
|
||||
case "get":
|
||||
console.log("a get request, url:", url)
|
||||
get(url, param)
|
||||
.then(response => {
|
||||
resolve(response)
|
||||
}).catch(err => {
|
||||
console.log("GET request error, err:", err)
|
||||
reject(err)
|
||||
})
|
||||
break
|
||||
case "post":
|
||||
post(url, param)
|
||||
.then(response => {
|
||||
resolve(response)
|
||||
}).catch(err => {
|
||||
console.log("POST request error, err:", err)
|
||||
reject(err)
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function msg(err) {
|
||||
if (err && err.response) {
|
||||
switch (err.response.status) {
|
||||
case 400:
|
||||
alert(err.response.data.error.details);
|
||||
break;
|
||||
case 401:
|
||||
alert("未授权,请登录");
|
||||
break;
|
||||
|
||||
case 403:
|
||||
alert("拒绝访问");
|
||||
break;
|
||||
|
||||
case 404:
|
||||
alert("请求地址出错");
|
||||
break;
|
||||
|
||||
case 408:
|
||||
alert("请求超时");
|
||||
break;
|
||||
|
||||
case 500:
|
||||
alert("服务器内部错误");
|
||||
break;
|
||||
|
||||
case 501:
|
||||
alert("服务未实现");
|
||||
break;
|
||||
|
||||
case 502:
|
||||
alert("网关错误");
|
||||
break;
|
||||
|
||||
case 503:
|
||||
alert("服务不可用");
|
||||
break;
|
||||
|
||||
case 504:
|
||||
alert("网关超时");
|
||||
break;
|
||||
|
||||
case 505:
|
||||
alert("HTTP版本不受支持");
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
.header-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
.logo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 50px;
|
||||
img {
|
||||
flex: 1;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
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 { 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 { lang, themeName, setLang, setThemeName } = useContext<MyStoreValues>(MyContext);
|
||||
const navigate = useNavigate();
|
||||
// console.log('setLang:::', setLang);
|
||||
// setLang && setLang(LANG_NAME.EN);
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
|
||||
1st menu
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: (
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
|
||||
2nd menu
|
||||
</a>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: <a onClick={() => navigate('/login')}>登出</a>,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={style['header-wrapper']}>
|
||||
<div className={style['logo']} onClick={() => navigate('/home')}>
|
||||
<img src="https://nageoffer.com/img/logo3.png" alt="" style={{ cursor: 'pointer' }} />
|
||||
</div>
|
||||
<div className={style['edit-container']}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col></Col>
|
||||
<Col>
|
||||
<Dropdown menu={{ items }} placement="bottomRight" trigger={['click']}>
|
||||
<Avatar size={30} icon={<UserOutlined />} style={{ cursor: 'pointer' }} />
|
||||
</Dropdown>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => {
|
||||
lang === LANG_NAME.EN ? setLang && setLang(LANG_NAME.ZH) : setLang && setLang(LANG_NAME.EN);
|
||||
}}
|
||||
>
|
||||
<IconFont type="icon-qiehuanyuyan"></IconFont>
|
||||
</Button>
|
||||
</Col>
|
||||
<Col>
|
||||
<Switch
|
||||
checkedChildren={'🌞'}
|
||||
unCheckedChildren={'🌛'}
|
||||
defaultChecked={themeName === THEME_NAME.DARK}
|
||||
onChange={e => {
|
||||
setThemeName && setThemeName(e ? THEME_NAME.DARK : THEME_NAME.DEFAULT);
|
||||
}}
|
||||
></Switch>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default HeaderChild;
|
@ -0,0 +1,14 @@
|
||||
import { createFromIconfontCN } from '@ant-design/icons';
|
||||
import React from 'react';
|
||||
|
||||
const MyIcon = createFromIconfontCN({
|
||||
scriptUrl: '//at.alicdn.com/t/c/font_4254722_vw34zn7su2.js', // 在 iconfont.cn 上生成
|
||||
});
|
||||
|
||||
type MyComponentProps = React.HTMLProps<HTMLDivElement> & { type: string };
|
||||
|
||||
const IconFont: React.FC<MyComponentProps> = props => {
|
||||
return <MyIcon {...props}></MyIcon>;
|
||||
};
|
||||
|
||||
export default IconFont;
|
@ -1,25 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var react_1 = require("react");
|
||||
var styled_components_1 = require("styled-components");
|
||||
var antd_1 = require("antd");
|
||||
var useThemeMode_1 = require("@/hooks/useThemeMode");
|
||||
var index_module_less_1 = require("./index.module.less");
|
||||
var Header = antd_1.Layout.Header, Sider = antd_1.Layout.Sider, Content = antd_1.Layout.Content;
|
||||
var LayoutCom = function (props) {
|
||||
var sideMenuList = props.sideMenuList, children = props.children, _a = props.isSider, isSider = _a === void 0 ? true : _a;
|
||||
var myThemes = react_1.useContext(styled_components_1.ThemeContext);
|
||||
var _b = react_1.useState('mail'), current = _b[0], setCurrent = _b[1];
|
||||
var onClick = function (e) {
|
||||
setCurrent(e.key);
|
||||
};
|
||||
var setIsDark = useThemeMode_1["default"]()[0];
|
||||
return (React.createElement("main", { className: index_module_less_1["default"].container, style: { backgroundColor: myThemes.backgroundColor.bg1 } },
|
||||
React.createElement(Header, { className: index_module_less_1["default"].header, style: { backgroundColor: myThemes.backgroundColor.bg2 } },
|
||||
React.createElement(antd_1.Button, { onClick: function () { return setIsDark(function (pre) { return !pre; }); } }, "\u5207\u6362\u4E3B\u9898")),
|
||||
React.createElement(antd_1.Layout, { style: { backgroundColor: myThemes.backgroundColor.bg1, height: 'calc(100vh - 64px)' } },
|
||||
isSider && (React.createElement(Sider, { className: index_module_less_1["default"].sider, style: { backgroundColor: myThemes.backgroundColor.bg1 } },
|
||||
React.createElement(antd_1.Menu, { onClick: onClick, selectedKeys: [current], mode: "inline", items: sideMenuList }))),
|
||||
React.createElement(Content, { className: index_module_less_1["default"].content }, children))));
|
||||
};
|
||||
exports["default"] = LayoutCom;
|
@ -0,0 +1,27 @@
|
||||
import { Button, ButtonProps } from 'antd';
|
||||
import React from 'react';
|
||||
import { SearchOutlined, PlusOutlined, RedoOutlined } from '@ant-design/icons';
|
||||
|
||||
function withSearchIconButton<P extends ButtonProps>(WrappedComponent: React.ComponentType<P>) {
|
||||
return function EnhancedComponent(props: P) {
|
||||
return <WrappedComponent icon={<SearchOutlined></SearchOutlined>} {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
function withAddIconButton<P extends ButtonProps>(WrappedComponent: React.ComponentType<P>) {
|
||||
return function EnhancedComponent(props: P) {
|
||||
return <WrappedComponent icon={<PlusOutlined />} {...props}></WrappedComponent>;
|
||||
};
|
||||
}
|
||||
|
||||
function withResetIconButton<P extends ButtonProps>(WrappedComponent: React.ComponentType<P>) {
|
||||
return function EnhancedComponent(props: P) {
|
||||
return <WrappedComponent {...props} icon={<RedoOutlined />}></WrappedComponent>;
|
||||
};
|
||||
}
|
||||
|
||||
export const SearchButton = withSearchIconButton(Button);
|
||||
|
||||
export const AddButton = withAddIconButton(Button);
|
||||
|
||||
export const ResetButton = withResetIconButton(Button);
|
@ -0,0 +1,28 @@
|
||||
// i18n.js
|
||||
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import zh from './locales/zh';
|
||||
import en from './locales/en';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources: {
|
||||
zh: {
|
||||
translation: zh,
|
||||
},
|
||||
en: {
|
||||
translation: en,
|
||||
},
|
||||
},
|
||||
// debug: true,
|
||||
fallbackLng: 'zh', // 默认语言
|
||||
interpolation: {
|
||||
escapeValue: false, // 不转义HTML标签
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
@ -0,0 +1,36 @@
|
||||
export enum STR_MAP {
|
||||
GLOBAL_TITLE = 'globalTitle',
|
||||
DYNAMIC_THREAD_POOL = 'dynamicThreadPool',
|
||||
THREAD_POOL_MANAGE = 'threadPoolManage',
|
||||
PROJECT = 'project',
|
||||
SEARCH = 'search',
|
||||
ADD = 'add',
|
||||
SERIAL_NUMBER = 'serialNumber',
|
||||
TENANTRY = 'tenantry',
|
||||
THREAD_POOL = 'threadPool',
|
||||
CORE_THREAD = 'coreThread',
|
||||
MAXIMUM_THREAD = 'maximumThread',
|
||||
QUEUE_TYPE = 'queueType',
|
||||
QUEUE_CAPACITY = 'queueCapacity',
|
||||
REJECTION_STRATEGY = 'rejectionStrategy',
|
||||
EXECUTION_TIMEOUT = 'executionTimeout',
|
||||
ALARM_OR_NOT = 'alarmOrNot',
|
||||
CREATION_TIME = 'creationTime',
|
||||
UPDATE_TIME = 'updateTime',
|
||||
EDIT = 'edit',
|
||||
TENANT_MANAGE = 'tenantManage',
|
||||
LOG_MANAGE = 'logManage',
|
||||
PROJECT_MANAGE = 'projectManage',
|
||||
USER_MANAGE = 'userManage',
|
||||
LOGIN_SUCCESSFUL = 'loginSuccessful',
|
||||
USER_INPUT_MESSAGE = 'userInputMessage',
|
||||
USRE_NAME = 'username',
|
||||
PASSWORD_INPUT_MESSAGE = 'passwordInputMessage',
|
||||
REMERBER_PASSWORD = 'rememberPassWord',
|
||||
FORGOT_PASSWORD = 'forgotPassword',
|
||||
ACCOUNT_PASSWORD_LOGIN = 'accountPasswordLogin',
|
||||
PASSWOR = 'password',
|
||||
LOGIN = 'login',
|
||||
PHONE_LOGIN = 'phoneLogin',
|
||||
ALARM_EDITING_SUCCESS = 'alarmEditingSuccess',
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import { STR_MAP } from './constants';
|
||||
|
||||
const enTranslationMap: { [key: string]: string } = {
|
||||
[STR_MAP.DYNAMIC_THREAD_POOL]: 'Dynamic thread pool',
|
||||
[STR_MAP.THREAD_POOL_MANAGE]: 'Thread pool management',
|
||||
[STR_MAP.PROJECT]: 'project',
|
||||
[STR_MAP.SEARCH]: 'search',
|
||||
[STR_MAP.ADD]: 'add',
|
||||
[STR_MAP.SERIAL_NUMBER]: 'number',
|
||||
[STR_MAP.TENANTRY]: 'tenantry',
|
||||
[STR_MAP.THREAD_POOL]: 'thread pool',
|
||||
[STR_MAP.CORE_THREAD]: 'core thread',
|
||||
[STR_MAP.MAXIMUM_THREAD]: 'maximum thread',
|
||||
[STR_MAP.QUEUE_TYPE]: 'queue type',
|
||||
[STR_MAP.QUEUE_CAPACITY]: 'queue capacity',
|
||||
[STR_MAP.REJECTION_STRATEGY]: 'rejection strategy',
|
||||
[STR_MAP.EXECUTION_TIMEOUT]: 'execution timeout',
|
||||
[STR_MAP.ALARM_OR_NOT]: 'alarm or not',
|
||||
[STR_MAP.CREATION_TIME]: 'creation time',
|
||||
[STR_MAP.UPDATE_TIME]: 'update time',
|
||||
[STR_MAP.EDIT]: 'edit',
|
||||
[STR_MAP.TENANT_MANAGE]: 'tenant management',
|
||||
[STR_MAP.PROJECT_MANAGE]: 'project management',
|
||||
[STR_MAP.USER_MANAGE]: 'user management',
|
||||
[STR_MAP.LOG_MANAGE]: 'log management',
|
||||
[STR_MAP.LOGIN_SUCCESSFUL]: 'login successful',
|
||||
[STR_MAP.USER_INPUT_MESSAGE]: 'please enter your username',
|
||||
[STR_MAP.USRE_NAME]: 'username',
|
||||
[STR_MAP.PASSWORD_INPUT_MESSAGE]: 'please enter password',
|
||||
[STR_MAP.REMERBER_PASSWORD]: 'remember the password',
|
||||
[STR_MAP.FORGOT_PASSWORD]: 'forgot password',
|
||||
[STR_MAP.ACCOUNT_PASSWORD_LOGIN]: 'account password login',
|
||||
[STR_MAP.GLOBAL_TITLE]: `The world's best thread pool management tool`,
|
||||
[STR_MAP.PASSWOR]: 'password',
|
||||
[STR_MAP.LOGIN]: 'login',
|
||||
[STR_MAP.PHONE_LOGIN]: 'Mobile login',
|
||||
[STR_MAP.ALARM_EDITING_SUCCESS]: 'alarm editing success',
|
||||
};
|
||||
|
||||
export default enTranslationMap;
|
@ -0,0 +1,40 @@
|
||||
import { STR_MAP } from './constants';
|
||||
|
||||
const zhTranslationMap: { [key: string]: string } = {
|
||||
[STR_MAP.DYNAMIC_THREAD_POOL]: '动态线程池',
|
||||
[STR_MAP.THREAD_POOL_MANAGE]: '线程池管理',
|
||||
[STR_MAP.PROJECT]: '项目',
|
||||
[STR_MAP.SEARCH]: '搜索',
|
||||
[STR_MAP.ADD]: '添加',
|
||||
[STR_MAP.SERIAL_NUMBER]: '序号',
|
||||
[STR_MAP.TENANTRY]: '租户',
|
||||
[STR_MAP.THREAD_POOL]: '线程池',
|
||||
[STR_MAP.CORE_THREAD]: '核心线程',
|
||||
[STR_MAP.MAXIMUM_THREAD]: '最大线程',
|
||||
[STR_MAP.QUEUE_TYPE]: '队列类型',
|
||||
[STR_MAP.QUEUE_CAPACITY]: '队列容量',
|
||||
[STR_MAP.REJECTION_STRATEGY]: '拒绝策略',
|
||||
[STR_MAP.EXECUTION_TIMEOUT]: '执行超时',
|
||||
[STR_MAP.ALARM_OR_NOT]: '是否报警',
|
||||
[STR_MAP.CREATION_TIME]: '创建时间',
|
||||
[STR_MAP.UPDATE_TIME]: '更新时间',
|
||||
[STR_MAP.EDIT]: '操作',
|
||||
[STR_MAP.TENANT_MANAGE]: '租户管理',
|
||||
[STR_MAP.PROJECT_MANAGE]: '项目管理',
|
||||
[STR_MAP.USER_MANAGE]: '用户权限',
|
||||
[STR_MAP.LOG_MANAGE]: '日志管理',
|
||||
[STR_MAP.LOGIN_SUCCESSFUL]: '登录成功',
|
||||
[STR_MAP.USER_INPUT_MESSAGE]: '请输入用户名',
|
||||
[STR_MAP.USRE_NAME]: '用户名',
|
||||
[STR_MAP.PASSWORD_INPUT_MESSAGE]: '请输入密码',
|
||||
[STR_MAP.REMERBER_PASSWORD]: '记住密码',
|
||||
[STR_MAP.FORGOT_PASSWORD]: '忘记密码',
|
||||
[STR_MAP.ACCOUNT_PASSWORD_LOGIN]: '账号密码登录',
|
||||
[STR_MAP.GLOBAL_TITLE]: `全球最好用的线程池管理工具`,
|
||||
[STR_MAP.PASSWOR]: '密码',
|
||||
[STR_MAP.LOGIN]: '登录',
|
||||
[STR_MAP.PHONE_LOGIN]: '手机号登录',
|
||||
[STR_MAP.ALARM_EDITING_SUCCESS]: '报警编辑成功',
|
||||
};
|
||||
|
||||
export default zhTranslationMap;
|
@ -0,0 +1,50 @@
|
||||
import { theme } from 'antd';
|
||||
import { darkDefaultTheme } from '.';
|
||||
export const darkAlgorithm = {
|
||||
token: {
|
||||
colorPrimary: darkDefaultTheme.primary,
|
||||
fontSize: 14,
|
||||
fontSizeHeading1: 18,
|
||||
},
|
||||
components: {
|
||||
Layout: {
|
||||
bodyBg: darkDefaultTheme.backgroundColor.bg1,
|
||||
headerBg: darkDefaultTheme.backgroundColor.bgHeader,
|
||||
triggerBg: darkDefaultTheme.backgroundColor.bg1,
|
||||
triggerColor: darkDefaultTheme.fontColor.fc1,
|
||||
},
|
||||
Button: {
|
||||
// fontSize: 14,
|
||||
},
|
||||
Table: {
|
||||
// borderRadius: 0,
|
||||
// borderRadiusLG: 0,
|
||||
// padding: 10,
|
||||
// paddingXS: 5,
|
||||
// margin: 0,
|
||||
// cellFontSize: 12,
|
||||
// colorBorderSecondary: darkDefaultTheme.borderColor.bl1,
|
||||
// paddingContentVerticalLG: 4,
|
||||
},
|
||||
Modal: {
|
||||
borderRadiusLG: 2,
|
||||
borderRadiusSM: 2,
|
||||
colorText: darkDefaultTheme.fontColor.fc3,
|
||||
borderRadius: 2,
|
||||
paddingContentHorizontalLG: 0,
|
||||
paddingMD: 0,
|
||||
},
|
||||
Menu: {
|
||||
itemBg: darkDefaultTheme.backgroundColor.bg1,
|
||||
// itemSelectedBg: darkDefaultTheme.primary,
|
||||
// itemSelectedColor: darkDefaultTheme.fontColor.fc1,
|
||||
activeBarWidth: 0,
|
||||
activeBarHeight: 0,
|
||||
activeBarBorderWidth: 0,
|
||||
// subMenuItemBorderRadius: 8,
|
||||
// horizontalItemBorderRadius: 8,
|
||||
// itemBorderRadius: 8,
|
||||
},
|
||||
},
|
||||
algorithm: theme.darkAlgorithm,
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
import { theme } from 'antd';
|
||||
import { lightDefaultTheme } from '.';
|
||||
export const defaultAlgorithm = {
|
||||
token: {
|
||||
colorPrimary: lightDefaultTheme.primary,
|
||||
fontSize: 14,
|
||||
fontSizeHeading1: 18,
|
||||
},
|
||||
components: {
|
||||
Layout: {
|
||||
bodyBg: lightDefaultTheme.backgroundColor.bg1,
|
||||
headerBg: lightDefaultTheme.backgroundColor.bgHeader,
|
||||
triggerBg: lightDefaultTheme.backgroundColor.bg1,
|
||||
triggerColor: lightDefaultTheme.fontColor.fc1,
|
||||
},
|
||||
Button: {
|
||||
// fontSize: 14,
|
||||
},
|
||||
Table: {
|
||||
// padding: 10,
|
||||
// paddingXS: 5,
|
||||
// margin: 0,
|
||||
// cellFontSize: 12,
|
||||
// colorBorderSecondary: lightDefaultTheme.borderColor.bl1,
|
||||
// paddingContentVerticalLG: 4,
|
||||
},
|
||||
Modal: {
|
||||
// borderRadiusLG: 2,
|
||||
// borderRadiusSM: 2,
|
||||
// colorText: lightDefaultTheme.fontColor.fc3,
|
||||
// borderRadius: 2,
|
||||
// paddingContentHorizontalLG: 0,
|
||||
// paddingMD: 0,
|
||||
},
|
||||
Menu: {
|
||||
itemBg: lightDefaultTheme.backgroundColor.bg1,
|
||||
// itemSelectedBg: lightDefaultTheme.primary,
|
||||
// itemSelectedColor: lightDefaultTheme.fontColor.fc1,
|
||||
activeBarWidth: 0,
|
||||
activeBarHeight: 0,
|
||||
activeBarBorderWidth: 0,
|
||||
// subMenuItemBorderRadius: 8,
|
||||
// horizontalItemBorderRadius: 8,
|
||||
// itemBorderRadius: 8,
|
||||
},
|
||||
},
|
||||
algorithm: theme.defaultAlgorithm,
|
||||
};
|
@ -0,0 +1,58 @@
|
||||
import React, { createContext, useState, ReactNode, useEffect } from 'react';
|
||||
import { ConfigProvider, theme } from 'antd';
|
||||
import { DefaultTheme, ThemeProvider } from 'styled-components';
|
||||
import enUS from 'antd/locale/en_US';
|
||||
import zhCN from 'antd/locale/zh_CN';
|
||||
import { darkDefaultTheme, lightDefaultTheme } from '@/config/theme';
|
||||
import { defaultAlgorithm } from '@/config/theme/default-algnorithm';
|
||||
import { darkAlgorithm } from '@/config/theme/dark-algorithm';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocalStorageState } from 'ahooks';
|
||||
import { LANG_NAME, MyStoreValues, THEME_NAME } from '@/typings';
|
||||
|
||||
export const MyContext = createContext<MyStoreValues>({});
|
||||
|
||||
export const MyStore: React.FC<{
|
||||
children: ReactNode;
|
||||
}> = ({ children }) => {
|
||||
const [themeName, setThemeName] = useLocalStorageState<THEME_NAME>('current-mode', {
|
||||
defaultValue: THEME_NAME.DEFAULT,
|
||||
});
|
||||
const [lang, setLang] = useLocalStorageState<LANG_NAME>('current-lang', {
|
||||
defaultValue: LANG_NAME.ZH,
|
||||
});
|
||||
const [themes, setThemes] = useState(defaultAlgorithm);
|
||||
const [myThemes, setMyThemes] = useState<DefaultTheme>(lightDefaultTheme);
|
||||
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const changeMode = (themeName: THEME_NAME) => {
|
||||
if (themeName === THEME_NAME.DARK) {
|
||||
darkAlgorithm.algorithm = theme.darkAlgorithm;
|
||||
// for ant change mode
|
||||
setThemes(darkAlgorithm);
|
||||
// for custome use mode
|
||||
setMyThemes(darkDefaultTheme);
|
||||
} else {
|
||||
defaultAlgorithm.algorithm = theme.defaultAlgorithm;
|
||||
setThemes(defaultAlgorithm);
|
||||
setMyThemes(lightDefaultTheme);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
changeMode(themeName as THEME_NAME);
|
||||
}, [themeName]);
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(lang);
|
||||
}, [lang, i18n]);
|
||||
|
||||
return (
|
||||
<MyContext.Provider value={{ themeName, lang, setThemeName, setLang }}>
|
||||
<ConfigProvider locale={lang === LANG_NAME.ZH ? zhCN : enUS} theme={themes}>
|
||||
<ThemeProvider theme={myThemes}>{children}</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
</MyContext.Provider>
|
||||
);
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
import React, { createContext, useState, ReactNode } from 'react';
|
||||
|
||||
export enum THEME_NAME {
|
||||
DEFAULT = 'default',
|
||||
DARK = 'dark',
|
||||
}
|
||||
|
||||
export const MyThemeContext = createContext<{ themeName: string; setThemeName: (name: THEME_NAME) => void } | null>(
|
||||
null
|
||||
);
|
||||
|
||||
export const ThemeStore: React.FC<{
|
||||
children: ReactNode;
|
||||
}> = ({ children }) => {
|
||||
const [themeName, setThemeName] = useState<string>(THEME_NAME.DEFAULT);
|
||||
return <MyThemeContext.Provider value={{ themeName, setThemeName }}>{children}</MyThemeContext.Provider>;
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var layout_com_1 = require("./components/layout-com");
|
||||
var react_router_dom_1 = require("react-router-dom");
|
||||
var route_1 = require("./route");
|
||||
var login_1 = require("@/page/login");
|
||||
var icons_1 = require("@ant-design/icons");
|
||||
var sideMenuList = [
|
||||
{
|
||||
label: React.createElement("a", { href: "/about" }, "about"),
|
||||
key: 'mail',
|
||||
icon: React.createElement(icons_1.MailOutlined, null)
|
||||
},
|
||||
{
|
||||
label: React.createElement("a", { href: "/home" }, "\u4E3B\u9875"),
|
||||
key: 'app',
|
||||
icon: React.createElement(icons_1.AppstoreOutlined, null)
|
||||
},
|
||||
];
|
||||
var App = function () {
|
||||
return (React.createElement(layout_com_1["default"], { sideMenuList: sideMenuList, isSider: false },
|
||||
React.createElement(react_router_dom_1.Routes, null,
|
||||
React.createElement(react_router_dom_1.Route, { path: "/Login", Component: login_1["default"] }),
|
||||
route_1["default"].map(function (item) { return (React.createElement(react_router_dom_1.Route, { key: item.path, path: item.path, Component: item.component })); }))));
|
||||
};
|
||||
exports["default"] = App;
|
@ -0,0 +1,2 @@
|
||||
export * from './useTransLate';
|
||||
export * from './useFormToUrl';
|
@ -0,0 +1,52 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { parse } from 'qs';
|
||||
import useUrlState from '@ahooksjs/use-url-state';
|
||||
import { FormInstance } from 'antd';
|
||||
|
||||
export function useFormStateToUrl<T extends Record<string, any>>(
|
||||
form: FormInstance,
|
||||
params?: T
|
||||
): {
|
||||
urlState: any;
|
||||
isFirstMount: boolean;
|
||||
handleSetUrlState: () => void;
|
||||
} {
|
||||
const [state, setState] = useState<any>();
|
||||
const [urlState, setUrlState] = useUrlState<any>();
|
||||
const [count, setCount] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
const url = window.location.search.split('?')[1] ?? null;
|
||||
const urlParams = parse(url) as T;
|
||||
const result: Partial<T> = {};
|
||||
setState(urlParams);
|
||||
for (const key in params) {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
||||
const paramValue = urlParams[key];
|
||||
if (paramValue ?? false) {
|
||||
if (typeof params[key] === 'number') {
|
||||
const parsedValue = parseFloat(paramValue);
|
||||
if (!isNaN(parsedValue)) {
|
||||
result[key] = parsedValue as T[keyof T];
|
||||
}
|
||||
} else {
|
||||
result[key] = paramValue as T[keyof T];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
form.setFieldsValue(result);
|
||||
setCount(count => count + 1);
|
||||
}, [setState, setCount, form, params]);
|
||||
|
||||
const handleSetUrlState = () => {
|
||||
const values = form.getFieldsValue();
|
||||
setUrlState({ ...state, ...values });
|
||||
};
|
||||
|
||||
const isFirstMount = useMemo(() => {
|
||||
return count === 1;
|
||||
}, [count]);
|
||||
|
||||
return { urlState, isFirstMount, handleSetUrlState };
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useLocalStorageState } from 'ahooks';
|
||||
import { MyThemeContext, THEME_NAME } from '@/context/themeContext';
|
||||
|
||||
const useThemeMode = () => {
|
||||
const [isDark, setIsDark] = useLocalStorageState<boolean>('current-mode', { defaultValue: false });
|
||||
const { setThemeName } = useContext<any>(MyThemeContext);
|
||||
|
||||
useEffect(() => {
|
||||
isDark ? setThemeName(THEME_NAME.DARK) : setThemeName(THEME_NAME.DEFAULT);
|
||||
}, [isDark, setThemeName]);
|
||||
|
||||
return [setIsDark];
|
||||
};
|
||||
|
||||
export default useThemeMode;
|
@ -0,0 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useTran = (str: string): string => {
|
||||
const { t } = useTranslation();
|
||||
return t(str);
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
import useUrlState from '@ahooksjs/use-url-state';
|
||||
|
||||
export const useUrlSet = (options: { form: any }) => {
|
||||
const { form } = options;
|
||||
const [state, setState] = useUrlState({});
|
||||
|
||||
const setUrl = () => {
|
||||
const params = form.getFieldsValue();
|
||||
Object.keys(params).forEach(key => {
|
||||
if (!params[key]) {
|
||||
params[key] = undefined;
|
||||
}
|
||||
});
|
||||
setState({ ...params });
|
||||
};
|
||||
|
||||
return { setUrl };
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
const HomeDetail = () => {
|
||||
return <></>;
|
||||
};
|
||||
export default HomeDetail;
|