@ -1,35 +1,41 @@
|
|||||||
{
|
{
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
},
|
},
|
||||||
"[html]": {
|
"[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.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.formatOnPaste": true,
|
"editor.formatOnPaste": true,
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true
|
||||||
},
|
},
|
||||||
"[typescriptreact]": {
|
"[javascriptreact]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.formatOnPaste": true,
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[json]": {
|
||||||
"typescript.tsdk":"./node_modules/typescript/lib"
|
"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
|
/.git
|
||||||
node_modules
|
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;
|