style: ui style

This commit is contained in:
jialin
2024-07-02 15:03:38 +08:00
parent 6989345088
commit 49efbd1a7f
38 changed files with 336 additions and 135 deletions
+20 -19
View File
@@ -1,4 +1,5 @@
import { defineConfig } from '@umijs/max';
import theme from './theme';
const CompressionWebpackPlugin = require('compression-webpack-plugin');
import proxy from './proxy';
@@ -44,6 +45,24 @@ export default defineConfig({
minRatio: 0.8
}
]);
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg|ico)(\?.*)?$/)
.use('url-loader')
.loader(require.resolve('url-loader'))
.tap((options: any) => {
console.log('iamges==options========', options);
return {
...options,
limit: 8192, // 小于8KB的图片会被转为base64
fallback: {
loader: require.resolve('file-loader'),
options: {
name: 'static/[name].[hash:8].[ext]' // 将所有图片输出到 static 目录
}
}
};
});
}
}
: {}),
@@ -58,25 +77,7 @@ export default defineConfig({
style: 'less',
configProvider: {
componentSize: 'large',
theme: {
'root-entry-name': 'variable',
cssVar: true,
hashed: false,
components: {
Input: {
inputFontSize: 12
},
Table: {
cellFontSize: 12
}
},
token: {
colorPrimary: '#2fbf85',
borderRadius: 8,
fontSize: 12,
motion: true
}
}
theme
}
},
hash: true,
+25
View File
@@ -0,0 +1,25 @@
export default {
'root-entry-name': 'variable',
cssVar: true,
hashed: false,
components: {
Input: {
inputFontSize: 12
},
Table: {
cellFontSize: 12,
rowSelectedHoverBg: '#e6f6ff'
},
Menu: {
iconSize: 16,
iconMarginInlineEnd: 12,
itemHeight: 44
}
},
token: {
colorPrimary: '#007BFF',
borderRadius: 8,
fontSize: 12,
motion: true
}
};
+1
View File
@@ -27,6 +27,7 @@
"dayjs": "^1.11.11",
"has-ansi": "^5.0.1",
"jotai": "^2.8.4",
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"numeral": "^2.0.6",
"query-string": "^9.0.0",
+23 -28
View File
@@ -53,6 +53,9 @@ dependencies:
jotai:
specifier: ^2.8.4
version: 2.8.4(@types/react@18.3.1)(react@18.3.1)
localforage:
specifier: ^1.10.0
version: 1.10.0
lodash:
specifier: ^4.17.21
version: 4.17.21
@@ -4285,7 +4288,7 @@ packages:
dependencies:
'@babel/core': 7.24.5
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss@8.4.38)
transitivePeerDependencies:
- supports-color
dev: false
@@ -4312,7 +4315,7 @@ packages:
postcss-syntax: '>=0.36.2'
dependencies:
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss@8.4.38)
remark: 13.0.0
unist-util-find-all-after: 3.0.2
transitivePeerDependencies:
@@ -10176,6 +10179,10 @@ packages:
requiresBuild: true
optional: true
/immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==, tarball: https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz}
dev: false
/immer@8.0.4:
resolution: {integrity: sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ==}
dev: false
@@ -10999,6 +11006,12 @@ packages:
prelude-ls: 1.2.1
type-check: 0.4.0
/lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==, tarball: https://registry.npmjs.org/lie/-/lie-3.1.1.tgz}
dependencies:
immediate: 3.0.6
dev: false
/lightningcss-darwin-arm64@1.22.1:
resolution: {integrity: sha512-ldvElu+R0QimNTjsKpaZkUv3zf+uefzLy/R1R19jtgOfSRM+zjUCUgDhfEDRmVqJtMwYsdhMI2aJtJChPC6Osg==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.22.1.tgz}
engines: {node: '>= 12.0.0'}
@@ -11158,6 +11171,12 @@ packages:
engines: {node: '>=14'}
dev: false
/localforage@1.10.0:
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==, tarball: https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz}
dependencies:
lie: 3.1.1
dev: false
/locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -12460,7 +12479,7 @@ packages:
dependencies:
htmlparser2: 3.10.1
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss@8.4.38)
dev: false
/postcss-image-set-function@4.0.7(postcss@8.4.38):
@@ -12750,30 +12769,6 @@ packages:
lodash: 4.17.21
postcss: 8.4.38
/postcss-syntax@0.36.2(postcss@7.0.39):
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
peerDependencies:
postcss: '>=5.0.0'
postcss-html: '*'
postcss-jsx: '*'
postcss-less: '*'
postcss-markdown: '*'
postcss-scss: '*'
peerDependenciesMeta:
postcss-html:
optional: true
postcss-jsx:
optional: true
postcss-less:
optional: true
postcss-markdown:
optional: true
postcss-scss:
optional: true
dependencies:
postcss: 7.0.39
dev: false
/postcss-syntax@0.36.2(postcss@8.4.38):
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
peerDependencies:
@@ -15900,7 +15895,7 @@ packages:
postcss-sass: 0.4.4
postcss-scss: 2.1.1
postcss-selector-parser: 6.0.16
postcss-syntax: 0.36.2(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss@8.4.38)
postcss-value-parser: 4.2.0
resolve-from: 5.0.0
slash: 3.0.0
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 KiB

+1 -1
View File
@@ -7,7 +7,7 @@
background-color: var(--color-fill-1);
border-inline: none;
border-radius: 0;
padding-inline: 16px;
// padding-inline: 16px;
padding-block-end: 12px;
}
+3 -1
View File
@@ -1,6 +1,8 @@
.cardWrapper {
border-radius: var(--border-radius-small);
background-color: var(--color-white-1);
box-shadow: var(--box-shadow-base);
// box-shadow: var(--box-shadow-base);
box-shadow: none;
padding: 10px;
border: 1px solid var(--ant-color-border);
}
+3 -3
View File
@@ -35,15 +35,15 @@ const LineChart: React.FC<LineChartProps> = (props) => {
x: {
textStyle: {
autoRoate: true
}
},
labelFormatter
},
y: {
tick: false,
// size: 14,
// title: '%',
titlePosition: 'top',
titleFontSize: 12,
labelFormatter
titleFontSize: 12
}
},
style: {
+6 -6
View File
@@ -13,6 +13,7 @@ interface BarChartProps {
seriesField?: string;
stack?: boolean;
legend?: any;
labelFormatter?: (v: any) => string;
}
const BarChart: React.FC<BarChartProps> = (props) => {
const {
@@ -25,7 +26,8 @@ const BarChart: React.FC<BarChartProps> = (props) => {
colorField,
seriesField,
stack,
legend = undefined
legend = undefined,
labelFormatter
} = props;
const config = {
data,
@@ -57,7 +59,8 @@ const BarChart: React.FC<BarChartProps> = (props) => {
axis: {
x: {
xAxis: true,
tick: false
tick: false,
labelFormatter
},
y: {
tick: false,
@@ -86,10 +89,7 @@ const BarChart: React.FC<BarChartProps> = (props) => {
style: {
fill: (params: any) => {
return (
params.color ||
'linear-gradient(90deg,rgba(84, 204, 152,0.8) 0%,rgb(0, 168, 143,.7) 100%)'
);
return params.color || 'rgba(84, 204, 152,0.8)';
},
// radiusTopLeft: 12,
// radiusTopRight: 12,
+9 -5
View File
@@ -1,21 +1,25 @@
.editor-wrap {
border-radius: 16px;
border-radius: 8px;
overflow: hidden;
.editor-header {
display: flex;
padding: 6px 10px;
justify-content: space-between;
align-items: center;
background-color: rgb(56, 56, 56);
.ant-select-selector {
background-color: rgba(255, 255, 255, 0.09) !important;
color: rgba(255, 255, 255, 0.7);
background-color: rgba(255, 255, 255, 9%) !important;
color: rgba(255, 255, 255, 70%);
.ant-select-selection-item {
color: rgba(255, 255, 255, 0.7);
color: rgba(255, 255, 255, 70%);
}
}
.ant-select-arrow {
color: rgba(255, 255, 255, 0.7);
color: rgba(255, 255, 255, 70%);
}
}
// set scrollbar style
+4 -2
View File
@@ -1,3 +1,4 @@
import { useIntl } from '@umijs/max';
import { Button, Space } from 'antd';
type ModalFooterProps = {
@@ -18,10 +19,11 @@ const ModalFooter: React.FC<ModalFooterProps> = ({
htmlType = 'button',
form
}) => {
const intl = useIntl();
return (
<Space size={20}>
<Button onClick={onCancel} style={{ width: '88px' }} loading={loading}>
{cancelText || '取消'}
{cancelText || intl.formatMessage({ id: 'common.button.cancel' })}
</Button>
<Button
type="primary"
@@ -30,7 +32,7 @@ const ModalFooter: React.FC<ModalFooterProps> = ({
loading={loading}
htmlType={htmlType}
>
{okText || '保存'}
{okText || intl.formatMessage({ id: 'common.button.save' })}
</Button>
</Space>
);
+1 -1
View File
@@ -14,7 +14,7 @@ const PageTools: React.FC<PageToolsProps> = (props) => {
left,
right,
marginBottom = 0,
marginTop = 70,
marginTop = 60,
style: pageStyle
} = props;
+4 -4
View File
@@ -29,12 +29,12 @@ const RenderProgress = memo(
<Tooltip title={label}>
<Progress
percentPosition={{ align: 'center', type: 'inner' }}
size={[undefined, 12]}
size={[undefined, 16]}
format={() => {
return (
<span
style={{
color: 'var(--ant-color-text)'
color: '#fff'
}}
>
{percent}%
@@ -49,12 +49,12 @@ const RenderProgress = memo(
<Progress
type="line"
percentPosition={{ align: 'center', type: 'inner' }}
size={[undefined, 12]}
size={[undefined, 16]}
format={() => {
return (
<span
style={{
color: 'var(--ant-color-text)'
color: '#fff'
}}
>
{percent}%
@@ -3,11 +3,12 @@
@inputheight: 32px;
@borderRadius: 8px;
@input-inner-padding: 12px;
@bgColor: transparent;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
align-items: flex-start;
height: 54px;
border-width: var(--ant-line-width);
border-style: var(--ant-line-type);
@@ -15,6 +16,7 @@
border-radius: @borderRadius;
padding-inline: 12px;
padding-block: 20px 0;
background-color: var(--color-white-1);
&.filled {
border: none;
@@ -105,6 +107,7 @@
}
// ==================== select ==================
:global(.ant-select) {
display: flex;
align-items: center;
@@ -118,6 +121,7 @@
padding-block: 5px;
padding-inline: @input-inner-padding !important;
box-shadow: none !important;
background-color: @bgColor !important;
}
:global(.ant-select-selection-item) {
@@ -127,6 +131,10 @@
padding-inline-end: 0 !important;
}
:global(.ant-select-auto-complete) :global(.ant-select-selector) {
padding-inline: 0 !important;
}
:global(.ant-select-arrow) {
top: 10px;
}
@@ -144,6 +152,7 @@
// ==================== input ====================
:global(.ant-input),
:global(.ant-input-password) {
width: 100%;
display: flex;
align-items: center;
border: none;
@@ -151,6 +160,11 @@
padding-block: 5px;
padding-inline: 12px;
height: @inputheight !important;
background-color: @bgColor;
}
:global(.ant-input.seal-textarea) {
width: 100%;
}
:global(.ant-input-number) {
@@ -160,6 +174,7 @@
box-shadow: none;
padding: 0;
height: @inputheight !important;
background-color: @bgColor;
}
:global(.ant-input-outlined) {
@@ -170,6 +185,7 @@
padding-block: 5px;
padding-inline: @input-inner-padding;
height: @inputheight !important;
background-color: transparent;
&.seal-textarea {
min-height: 100px !important;
@@ -213,7 +229,7 @@
:global(.ant-input-search-button) {
position: absolute;
top: -20px;
right: -11px;
right: 0;
border-radius: 0 @borderRadius @borderRadius 0 !important;
overflow: hidden;
border: none;
+1
View File
@@ -68,6 +68,7 @@ const SealPassword: React.FC<InputProps & SealFormItemProps> = (props) => {
{...rest}
ref={inputRef}
autoComplete="off"
className="seal-input-password"
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onChange={handleChange}
+4 -1
View File
@@ -4,13 +4,16 @@
display: flex;
align-items: center;
justify-content: flex-start;
height: 70px;
height: 68px;
&-left {
justify-content: flex-start;
}
&-right {
justify-content: flex-end;
}
&-center {
justify-content: center;
}
+2 -2
View File
@@ -23,7 +23,7 @@
margin-bottom: 20px;
border-radius: var(--ant-table-header-border-radius);
overflow: hidden;
box-shadow: var(--box-shadow-base);
// box-shadow: var(--box-shadow-base);
}
.expanded-row {
@@ -39,7 +39,7 @@
display: flex;
justify-content: flex-start;
align-items: center;
background-color: var(--color-white-1);
background-color: var(--color-fill-sider);
transition: all 0.2s ease;
&:hover {
+1 -1
View File
@@ -1,5 +1,5 @@
.transition-wrapper {
border-radius: 16px;
border-radius: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
+3 -3
View File
@@ -25,12 +25,12 @@ const UitilBar: React.FC<UitilBarProps> = (props) => {
const strokeColorFunc = (percent: number) => {
if (percent <= 50) {
return 'var(--ant-color-primary)';
return 'var(--color-chart-green)';
}
if (percent <= 80) {
return 'var(--ant-color-warning)';
return 'var(--color-chart-glod)';
}
return 'var(--ant-color-error)';
return 'var(--color-chart-red)';
};
return (
<div className="util-bar-box">
+1 -1
View File
@@ -1,5 +1,5 @@
export default {
CREATE: ['ctrl+n', 'meta+n'],
CREATE: ['ctrl+shift+n', 'meta+shift+n'],
SAVE: ['ctrl+s', 'meta+s'],
SUBMIT: ['ctrl+enter', 'meta+enter'],
SAVEAS: ['ctrl+shift+s', 'meta+shift+s'],
+39 -19
View File
@@ -5,6 +5,7 @@ html {
--ant-color-fill-tertiary: rgba(0, 0, 0, 4%);
--color-fill-1: var(--ant-color-fill-tertiary);
// --color-fill-1: #fff;
--ant-color-text: #000;
--color-fill-2: #fff;
--color-fill-3: #f3f6fa;
--color-logs-bg: #1e1e1e;
@@ -16,11 +17,12 @@ html {
--border-radius-middle: 20px;
--border-radius-small: 8px;
--color-white-1: rgba(255, 255, 255, 100%);
--color-fill-sider: #f4f5f4;
--font-weight-normal: 500;
--font-weight-medium: 600;
--font-weight-bold: 700;
--color-text-1: var(--ant-color-text);
--color-bg-light-1: #f0fff6;
--color-bg-light-1: #e6f6ff;
--font-size-base: 12px;
--font-size-large: 16px;
--font-size-middle: 14px;
@@ -31,18 +33,19 @@ html {
--ant-table-cell-padding-block: 8px;
--ant-table-header-border-radius: 8px;
--ant-table-header-split-color: #f0f0f0;
--ant-table-row-selected-bg: #f0fff6;
--ant-table-row-selected-hover-bg: #d8f2e4;
--ant-table-row-hover-bg: rgba(230, 230, 230, 70%);
--color-chart-red: #ff7875;
--color-chart-green: #54cc98;
--color-chart-glod: #ffd666;
--ant-table-row-selected-bg: #e6f6ff;
--ant-table-row-selected-hover-bg: #e6f6ff;
--ant-table-row-hover-bg: rgba(230, 230, 230, 88%);
--color-chart-red: rgba(255, 77, 79, 80%);
--color-chart-green: rgb(84, 204, 152, 80%);
--color-chart-glod: rgba(250, 173, 20, 80%);
--seal-transition-func: cubic-bezier(0, 0, 1, 1);
// ======== input ============
--ant-input-active-shadow: 0 0 0 2px rgba(5, 255, 105, 6%);
--ant-input-active-border-color: #2fbf85;
--ant-input-hover-border-color: #54cc98;
--box-shadow-base: 0 4px 12px rgba(227, 232, 240, 70%);
--ant-input-active-border-color: #007bff;
--ant-input-hover-border-color: #2997ff;
--box-shadow-base: 0 4px 6px rgba(227, 232, 240, 70%);
// --box-shadow-base: none;
.css-var-rf {
--ant-font-size: var(--font-size-base);
@@ -54,7 +57,6 @@ html {
--ant-font-size: var(--font-size-base);
&.ant-menu-css-var {
--ant-menu-item-height: 46px;
--ant-menu-item-selected-bg: var(--color-white-1);
--ant-menu-item-border-radius: 8px;
--ant-menu-item-selected-color: var(--ant-color-primary);
@@ -72,6 +74,7 @@ html {
--ant-font-size: var(--font-size-base);
--ant-padding-sm: 14px;
--ant-border-radius-lg: 8px;
--ant-color-text: #000;
--ant-color-error: #ff4d4f;
--ant-color-bg-mask: rgba(0, 0, 0, 35%);
--ant-color-border: rgb(217 217 217 / 50%);
@@ -171,7 +174,7 @@ body {
tr > td {
// background-color: var(--color-fill-1);
border-bottom: none;
height: 70px;
height: 68px;
&:first-child {
border-top-left-radius: var(--table-td-radius);
@@ -237,8 +240,9 @@ body {
height: 100%;
.ant-pro-sider .ant-layout-sider-children {
background-color: var(--color-white-1);
box-shadow: var(--box-shadow-base);
background-color: var(--color-fill-sider);
// box-shadow: var(--box-shadow-base);
border-right: 1px solid var(--ant-color-border);
}
}
@@ -254,8 +258,9 @@ body {
.ant-table-tbody {
.ant-table-row {
border-radius: var(--table-td-radius);
background-color: var(--color-white-1);
box-shadow: var(--box-shadow-base);
// background-color: var(--color-white-1);
background-color: var(--color-fill-sider);
// box-shadow: var(--box-shadow-base);
> td {
background-color: unset;
@@ -297,10 +302,15 @@ body {
}
.ant-pro-layout-container {
min-height: 100vh;
// background-color: var(--color-fill-2);
}
.ant-pro-sider {
.ant-pro-base-menu-inline-item-title {
gap: 12px;
}
.ant-menu {
.ant-menu-item {
border-radius: var(--border-radius-small);
@@ -325,7 +335,7 @@ body {
.ant-menu-item.ant-menu-item-selected {
color: var(--ant-color-primary);
background-color: unset;
background-color: var(--ant-menu-item-selected-bg);
}
}
}
@@ -343,8 +353,9 @@ body {
left: 0;
bottom: 0;
right: 0;
background: url('./assets/images/bg-11.png') center center no-repeat;
background-size: cover;
// background: url('@/assets/images/bg-11.png') center center no-repeat;
// background-size: cover;
background-color: #fff;
&::after {
content: '';
@@ -357,6 +368,15 @@ body {
height: 100%;
}
}
// .login-wrapper {
// position: fixed;
// top: 0;
// left: 0;
// bottom: 0;
// right: 0;
// background: url('@/assets/images/bg-2.png') center center no-repeat;
// background-size: cover;
// }
.ant-pro-page-container {
background: transparent;
@@ -105,7 +105,7 @@ const ActiveTable = () => {
<Row gutter={[20, 0]}>
<Col xs={24} sm={24} md={24} lg={24} xl={24}>
<PageTools
style={{ margin: '32px 8px' }}
style={{ margin: '26px 0px' }}
left={
<span
style={{ fontSize: 'var(--font-size-large)', padding: '9px 0' }}
@@ -3,8 +3,9 @@
height: 110px;
display: flex;
justify-content: space-around;
box-shadow: var(--box-shadow-base);
// box-shadow: var(--box-shadow-base);
border-radius: var(--ant-border-radius-lg);
// border: 1px solid var(--ant-color-border);
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ const renderCardItem = (data: {
const { label, value, bgColor } = data;
return (
<Card
bordered={false}
bordered={true}
style={{ background: bgColor }}
className={styles['card-body']}
>
@@ -11,11 +11,6 @@ import { DashboardContext } from '../config/dashboard-context';
import ResourceUtilization from './resource-utilization';
const SystemLoad = () => {
const colors = [
'linear-gradient(90deg, rgba(84, 204, 152,.8) 0%, rgba(84, 204, 152,0.5) 50%, rgba(84, 204, 152,.8) 100%)',
'linear-gradient(90deg, rgba(255, 214, 102,.8) 0%, rgba(255, 214, 102,0.5) 50%, rgba(255, 214, 102,.8) 100%)',
'linear-gradient(90deg, rgba(255, 120, 117,.8) 0%, rgba(255, 120, 117,0.5) 50%, rgba(255, 120, 117,.8) 100%)'
];
const intl = useIntl();
const data = useContext(DashboardContext)?.system_load?.current || {};
const { size } = useWindowResize();
@@ -39,7 +34,7 @@ const SystemLoad = () => {
<div>
<div className="system-load">
<PageTools
style={{ margin: '32px 8px' }}
style={{ margin: '26px 0px' }}
left={
<span style={{ fontSize: 'var(--font-size-large)' }}>
{intl.formatMessage({ id: 'dashboard.systemload' })}
+7 -1
View File
@@ -225,6 +225,10 @@ const Usage = () => {
setUserData(userList);
};
const labelFormatter = (v: any) => {
return dayjs(v).format('MM-DD');
};
useEffect(() => {
if (size.width < breakpoints.xl) {
setPaddingRight('0');
@@ -240,7 +244,7 @@ const Usage = () => {
return (
<>
<PageTools
style={{ margin: '32px 8px' }}
style={{ margin: '26px 0px' }}
left={
<span style={{ fontSize: 'var(--font-size-large)' }}>
{intl.formatMessage({ id: 'dashboard.usage' })}
@@ -272,6 +276,7 @@ const Usage = () => {
xField="time"
yField="value"
height={360}
labelFormatter={labelFormatter}
></AreaChart>
</Col>
<Col span={12}>
@@ -285,6 +290,7 @@ const Usage = () => {
legend={false}
yField="value"
height={360}
labelFormatter={labelFormatter}
></ColumnBar>
</Col>
</Row>
+57 -13
View File
@@ -1,13 +1,23 @@
import LogoIcon from '@/assets/images/logo.png';
import { initialPasswordAtom, userAtom } from '@/atoms/user';
import SealInput from '@/components/seal-form/seal-input';
import {
getRememberMe,
rememberMe,
removeRememberMe
} from '@/utils/localstore/index';
import { GlobalOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
import { SelectLang, history, useIntl, useModel } from '@umijs/max';
import { Button, Checkbox, Form } from 'antd';
import CryptoJS from 'crypto-js';
import { useAtom } from 'jotai';
import { useEffect } from 'react';
import { flushSync } from 'react-dom';
import { login } from '../apis';
const REMEMBER_ME_KEY = 'r_m';
const CRYPT_TEXT = 'seal';
const renderLogo = () => {
return (
<div
@@ -28,7 +38,6 @@ const LoginForm = () => {
const [userInfo, setUserInfo] = useAtom(userAtom);
const [initialPassword, setInitialPassword] = useAtom(initialPasswordAtom);
const { initialState, setInitialState } = useModel('@@initialState');
const { globalState, setGlobalState } = useModel('global');
const intl = useIntl();
const [form] = Form.useForm();
@@ -51,28 +60,65 @@ const LoginForm = () => {
return userInfo;
};
const encryptPassword = (password: string) => {
const psw = CryptoJS.AES?.encrypt?.(password, CRYPT_TEXT).toString();
return psw;
};
const decryptPassword = (password: string) => {
const bytes = CryptoJS.AES?.decrypt?.(password, CRYPT_TEXT);
const res = bytes.toString(CryptoJS.enc.Utf8);
return res;
};
const callRememberMe = async (values: any) => {
const { autoLogin } = values;
if (autoLogin) {
await rememberMe(REMEMBER_ME_KEY, {
um: encryptPassword(values.username),
pw: encryptPassword(values.password),
f: true
});
} else {
await removeRememberMe(REMEMBER_ME_KEY);
}
};
const callGetRememberMe = async () => {
const rememberMe = await getRememberMe(REMEMBER_ME_KEY);
if (rememberMe?.f) {
const username = decryptPassword(rememberMe?.um);
const password = decryptPassword(rememberMe?.pw);
form.setFieldsValue({ username, password, autoLogin: true });
}
};
const handleLogin = async (values: any) => {
console.log('values', values, form);
try {
await login({
username: values.username,
password: values.password
});
const userInfo = await fetchUserInfo();
setGlobalState({
userInfo
});
setUserInfo(userInfo);
setInitialPassword(values.password);
if (values.autoLogin) {
await callRememberMe(values);
} else {
await removeRememberMe(REMEMBER_ME_KEY);
}
if (!userInfo?.require_password_change) {
gotoDefaultPage(userInfo);
}
// gotoDefaultPage(userInfo);
} catch (error) {
console.log('error====', error);
// to do something
}
};
useEffect(() => {
callGetRememberMe();
}, []);
return (
<div>
<div style={{ position: 'fixed', right: 0, top: 0, padding: '0 20px' }}>
@@ -119,12 +165,10 @@ const LoginForm = () => {
label={intl.formatMessage({ id: 'common.form.password' })}
/>
</Form.Item>
<Form.Item name="autoLogin">
<div style={{ paddingLeft: 10 }}>
<Checkbox>
{intl.formatMessage({ id: 'common.login.rember' })}
</Checkbox>
</div>
<Form.Item name="autoLogin" valuePropName="checked">
<Checkbox style={{ marginLeft: 10 }}>
{intl.formatMessage({ id: 'common.login.rember' })}
</Checkbox>
</Form.Item>
<Button htmlType="submit" type="primary" block>
{intl.formatMessage({ id: 'menu.login' })}
+1 -1
View File
@@ -21,7 +21,7 @@ const Login = () => {
}, [userInfo]);
return (
<div>
<div className="login-wrapper">
{userInfo?.require_password_change ? <PasswordForm /> : <LoginForm />}
</div>
);
@@ -39,6 +39,13 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
},
{ enabled: !disabled }
);
useHotkeys(
HotKeys.CREATE.join(','),
(e) => {
onNewMessage();
},
{ enabled: !disabled }
);
return (
<div className="chat-footer">
@@ -52,6 +59,7 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
onClick={onNewMessage}
>
{intl.formatMessage({ id: 'playground.newMessage' })}
<span className="m-l-5 opct-7">CTRL+SHIFT+ N</span>
</Button>
<Button
icon={<DeleteOutlined></DeleteOutlined>}
@@ -1,7 +1,4 @@
.chat-footer {
display: flex;
align-items: center;
padding-inline: 0 32px;
height: 100px;
// box-shadow: 0px -1px 2px 0px var(--ant-color-border);
}
+2 -1
View File
@@ -9,8 +9,9 @@
top: -14px;
right: 26px;
width: 80px;
border-radius: var(--border-radius-small);
border-radius: 8px;
text-align: center;
border: 1px solid var(--ant-color-border) !important;
:global(.ant-input-number-input) {
text-align: center !important;
+8 -5
View File
@@ -1,7 +1,10 @@
.ground-left {
display: flex;
justify-content: space-between;
flex-direction: column;
position: relative;
height: calc(100vh - 84px);
padding-bottom: 120px;
height: calc(100vh - 136px);
// padding-bottom: 120px;
padding-right: 32px;
.message-list-wrap {
@@ -10,8 +13,8 @@
}
.ground-left-footer {
position: absolute;
bottom: 20px;
width: 100%;
// position: absolute;
// bottom: 20px;
// width: 100%;
}
}
+2 -2
View File
@@ -9,8 +9,8 @@
}
.params {
// width: 465px;
padding: 20px;
padding-top: 0;
}
.divider-line {
@@ -18,7 +18,7 @@
.ant-divider {
margin: 0;
min-height: calc(100vh - 84px);
min-height: calc(100vh - 136px);
}
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ const Resources = () => {
}}
extra={[]}
>
<div style={{ marginTop: 70 }}>
<div style={{ marginTop: 60 }}>
<Tabs
type="card"
defaultActiveKey="workers"
+25
View File
@@ -0,0 +1,25 @@
import localStore from './store';
const store = localStore.createInstance({ name: '_xWXJKJ_S1Sna_' });
const rememberMe = (key: string, data: any) => {
if (store) {
store.setItem(key, data);
}
};
const getRememberMe = (key: string) => {
if (store) {
return store.getItem(key);
}
};
const removeRememberMe = (key: string) => {
if (store) {
store.removeItem(key);
}
};
export { getRememberMe, rememberMe, removeRememberMe };
export default store;
+51
View File
@@ -0,0 +1,51 @@
import dayjs from 'dayjs';
import localForage from 'localforage';
import { get } from 'lodash';
class Localestore extends Object.getPrototypeOf(localForage).constructor {
constructor() {
super();
this.state = {};
}
public async removeValue(key: string) {
return localForage.removeItem(key);
}
public async setValue(
key: string,
value: any,
callback?: (args?: any) => void,
expire?: number
) {
if (!expire) {
return localForage.setItem(key, { value }, callback);
}
return localForage.setItem(
key,
{
value,
expire: {
expire,
createTime: dayjs().valueOf(),
expiration: dayjs().add(expire, 'day').valueOf()
}
},
callback
);
}
public async getValue(key: string, callback?: (args?: any) => void) {
const storeValue = await localForage.getItem(key, callback);
const expire = get(storeValue, 'expire');
if (!expire) return storeValue;
const expiration = get(expire, 'expiration');
return {
value: get(storeValue, 'value'),
isExpiration: dayjs().isAfter(expiration)
};
}
}
export default new Localestore();