diff --git a/src/components/charts/area.tsx b/src/components/charts/area.tsx index e69de29b..cfa940bd 100644 --- a/src/components/charts/area.tsx +++ b/src/components/charts/area.tsx @@ -0,0 +1,79 @@ +import { Area } from '@ant-design/plots'; +import EmptyData from './empty-data'; + +interface LineChartProps { + title?: string; + height?: number; + data: any[]; + color?: string[]; + xField?: string; + yField?: string; + locale?: string; + labelFormatter?: (v: any) => string; + slider?: any; +} +const LineChart: React.FC = (props) => { + const { + data, + title, + color, + xField, + locale, + yField, + slider, + height, + labelFormatter + } = props; + const config = { + title, + height, + xField: xField || 'time', + yField: yField || 'value', + autoFit: true, + slider, + shapeField: 'smooth', + axis: { + x: { + textStyle: { + autoRoate: true + } + }, + y: { + tick: false, + // size: 14, + // title: '%', + titlePosition: 'top', + titleFontSize: 12, + labelFormatter + } + }, + style: { + fill: 'rgba(84, 204, 152,0.8)' + }, + legend: { + color: { + layout: { justifyContent: 'center' } + }, + + size: { + itemLabelFontSize: 14, + itemLabelFontWeight: 500 + } + }, + tooltip: { + title: 'time', + items: [{ channel: 'y' }] + } + }; + return ( + <> + {data.length === 0 ? ( + + ) : ( + + )} + + ); +}; + +export default LineChart; diff --git a/src/components/charts/empty-data.tsx b/src/components/charts/empty-data.tsx index e833600d..e268bc2e 100644 --- a/src/components/charts/empty-data.tsx +++ b/src/components/charts/empty-data.tsx @@ -2,8 +2,8 @@ import { Empty } from 'antd'; import React from 'react'; const EmptyData: React.FC<{ - height: string | number; - title: React.ReactNode; + height?: string | number; + title?: React.ReactNode; }> = ({ height, title }) => { return (
-

- {title} -

+ {title && ( +

+ {title} +

+ )}
string; slider?: any; } @@ -79,7 +80,11 @@ const LineChart: React.FC = (props) => { }; return ( <> - + {data.length === 0 ? ( + + ) : ( + + )} ); }; diff --git a/src/components/seal-form/input-number.tsx b/src/components/seal-form/input-number.tsx index 8a7c95f5..defed6bd 100644 --- a/src/components/seal-form/input-number.tsx +++ b/src/components/seal-form/input-number.tsx @@ -39,6 +39,7 @@ const SealInputNumber: React.FC = ( }; const handleChange = (e: any) => { + e.target.value = e.target.value?.trim?.(); props.onChange?.(e); }; @@ -48,6 +49,7 @@ const SealInputNumber: React.FC = ( }; const handleOnBlur = (e: any) => { + e.target.value = e.target.value?.trim?.(); if (!inputRef.current?.value) { setIsFocus(false); props.onBlur?.(e); diff --git a/src/components/seal-form/password.tsx b/src/components/seal-form/password.tsx index cfa5dc1d..f101e598 100644 --- a/src/components/seal-form/password.tsx +++ b/src/components/seal-form/password.tsx @@ -37,6 +37,7 @@ const SealPassword: React.FC = (props) => { }; const handleChange = (e: any) => { + e.target.value = e.target.value?.trim?.(); props.onChange?.(e); }; @@ -46,6 +47,7 @@ const SealPassword: React.FC = (props) => { }; const handleOnBlur = (e: any) => { + e.target.value = e.target.value?.trim?.(); if (!inputRef.current?.input?.value) { setIsFocus(false); props.onBlur?.(e); diff --git a/src/components/seal-form/seal-input.tsx b/src/components/seal-form/seal-input.tsx index 9f4119b8..0c7314ac 100644 --- a/src/components/seal-form/seal-input.tsx +++ b/src/components/seal-form/seal-input.tsx @@ -42,6 +42,7 @@ const SealInput: React.FC = (props) => { }; const handleChange = (e: any) => { + e.target.value = e.target.value?.trim?.(); props.onChange?.(e); }; @@ -51,6 +52,7 @@ const SealInput: React.FC = (props) => { }; const handleOnBlur = (e: any) => { + e.target.value = e.target.value?.trim?.(); if (!inputRef.current?.input?.value) { setIsFocus(false); props.onBlur?.(e); diff --git a/src/components/seal-table/components/row-children.tsx b/src/components/seal-table/components/row-children.tsx index a3280092..bc7d8e3a 100644 --- a/src/components/seal-table/components/row-children.tsx +++ b/src/components/seal-table/components/row-children.tsx @@ -3,6 +3,7 @@ import '../styles/row-children.less'; const RowChildren = (props: any) => { const { children } = props; + return
{children}
; }; diff --git a/src/components/seal-table/components/table-row.tsx b/src/components/seal-table/components/table-row.tsx index 5409468b..b454235a 100644 --- a/src/components/seal-table/components/table-row.tsx +++ b/src/components/seal-table/components/table-row.tsx @@ -33,6 +33,7 @@ const TableRow: React.FC< const [loading, setLoading] = useState(false); const pollTimer = useRef(null); const chunkRequestRef = useRef(null); + const childrenRendered = useRef(null); const { updateChunkedList } = useUpdateChunkedList(childrenData, { setDataList: setChildrenData @@ -58,6 +59,10 @@ const TableRow: React.FC< }; }, []); + const renderChildrenData = () => { + return renderChildren?.(childrenData); + }; + const handlePolling = async () => { if (pollingChildren) { try { @@ -110,12 +115,12 @@ const TableRow: React.FC< setExpanded(!expanded); onExpand?.(!expanded, record); + chunkRequestRef.current?.current?.cancel?.(); if (pollTimer.current) { clearInterval(pollTimer.current); } if (expanded) { - chunkRequestRef.current?.current?.cancel?.(); return; } @@ -124,9 +129,6 @@ const TableRow: React.FC< pollTimer.current = setInterval(() => { handlePolling(); }, 1000); - } else if (watchChildren) { - await handleLoadChildren(); - createChunkRequest(); } else { handleLoadChildren(); } @@ -146,6 +148,12 @@ const TableRow: React.FC< } }; + useEffect(() => { + if (childrenData.length) { + createChunkRequest(); + } + }, [childrenData]); + const renderRowPrefix = () => { if (expandable && rowSelection) { return ( @@ -220,11 +228,7 @@ const TableRow: React.FC< {expanded && (
- {childrenData.length ? ( - renderChildren?.(childrenData) - ) : ( - - )} + {childrenData.length ? renderChildrenData() : }
)} diff --git a/src/components/seal-table/index.tsx b/src/components/seal-table/index.tsx index cc57874e..c6fc2527 100644 --- a/src/components/seal-table/index.tsx +++ b/src/components/seal-table/index.tsx @@ -118,7 +118,11 @@ const SealTable: React.FC = (props) => { const renderContent = () => { if (!props.dataSource.length) { - return ; + return ( +
+ +
+ ); } return (
diff --git a/src/components/seal-table/styles/index.less b/src/components/seal-table/styles/index.less index 4e627055..f4d69c19 100644 --- a/src/components/seal-table/styles/index.less +++ b/src/components/seal-table/styles/index.less @@ -74,4 +74,11 @@ margin-top: 20px; min-height: 100px; } + + .empty-wrapper { + display: flex; + min-height: 160px; + justify-content: center; + align-items: center; + } } diff --git a/src/hooks/use-update-chunk-list.ts b/src/hooks/use-update-chunk-list.ts index 666a5dca..0cc476cc 100644 --- a/src/hooks/use-update-chunk-list.ts +++ b/src/hooks/use-update-chunk-list.ts @@ -61,6 +61,7 @@ export function useUpdateChunkedList( dataList, (sItem: any) => sItem.id === item.id ); + console.log('updateIndex===========', dataList, updateIndex, data); if (updateIndex > -1) { const updateItem = _.cloneDeep(item); dataList[updateIndex] = updateItem; diff --git a/src/locales/en-US/users.ts b/src/locales/en-US/users.ts index 9c801078..a17cbfb5 100644 --- a/src/locales/en-US/users.ts +++ b/src/locales/en-US/users.ts @@ -19,5 +19,10 @@ export default { 'users.password.number': 'At least one number', 'users.password.special': 'At least one special character', 'users.password.length': 'Length between 6 and 12 characters', - 'users.password.modify.title': 'Modify Password' + 'users.password.modify.title': 'Modify Password', + 'users.password.modify.description': + "For your account's security, please change your initial password.", + 'users.password.confirm': 'Confirm New Password', + 'users.password.confirm.empty': 'Please confirm the new password.', + 'users.password.confirm.error': 'The two passwords entered do not match.' }; diff --git a/src/locales/zh-CN/users.ts b/src/locales/zh-CN/users.ts index 6c2bb54e..d25f7814 100644 --- a/src/locales/zh-CN/users.ts +++ b/src/locales/zh-CN/users.ts @@ -19,5 +19,9 @@ export default { 'users.password.number': '至少包含一个数字', 'users.password.special': '至少包含一个特殊字符', 'users.password.length': '长度在6至12个字符之间', - 'users.password.modify.title': '修改密码' + 'users.password.modify.title': '修改密码', + 'users.password.modify.description': '为了确保您的账户安全,请修改初始密码', + 'users.password.confirm': '确认新密码', + 'users.password.confirm.empty': '请确认新密码', + 'users.password.confirm.error': '两次输入的密码不一致' }; diff --git a/src/pages/dashboard/components/usage.tsx b/src/pages/dashboard/components/usage.tsx index 25fdffa0..aaebd7fd 100644 --- a/src/pages/dashboard/components/usage.tsx +++ b/src/pages/dashboard/components/usage.tsx @@ -1,4 +1,5 @@ import CardWrapper from '@/components/card-wrapper'; +import AreaChart from '@/components/charts/area'; import ColumnBar from '@/components/charts/column-bar'; import HBar from '@/components/charts/h-bar'; import PageTools from '@/components/page-tools'; @@ -34,16 +35,16 @@ const projects = [ const APIRequestData = generateRandomArray({ length: times.length, - max: 100, - min: 0, - offset: 10 + max: 1000, + min: 10, + offset: 0 }); const TokensData = generateRandomArray({ length: times.length, max: 2000, - min: 200, - offset: 200 + min: 0, + offset: 500 }); const usersData = generateRandomArray({ @@ -189,7 +190,11 @@ const Usage = () => { } right={ - + } /> @@ -204,13 +209,13 @@ const Usage = () => { - + > { }; useEffect(() => { - fetchData(); + // fetchData(); createModelsChunkRequest(); return () => { chunkRequedtRef.current?.current?.cancel?.(); diff --git a/src/pages/login/components/password-form.tsx b/src/pages/login/components/password-form.tsx index a168a2fe..bb35768f 100644 --- a/src/pages/login/components/password-form.tsx +++ b/src/pages/login/components/password-form.tsx @@ -47,8 +47,21 @@ const PasswordForm: React.FC = () => { style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }} onFinish={handleSubmit} > -

- {intl.formatMessage({ id: 'users.password.modify.title' })} +

+ + {' '} + {intl.formatMessage({ id: 'users.password.modify.title' })} + + + {intl.formatMessage({ id: 'users.password.modify.description' })} +

{ label={intl.formatMessage({ id: 'users.form.newpassword' })} /> + ({ + validator(_, value) { + if (!value || getFieldValue('new_password') === value) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ id: 'users.password.confirm.error' }) + ) + ); + } + }) + ]} + > + } + label={intl.formatMessage({ id: 'users.password.confirm' })} + /> + -