fix: languages config, update-password
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Space } from 'antd';
|
import { Button, Space } from 'antd';
|
||||||
|
|
||||||
type FormButtonsProps = {
|
type FormButtonsProps = {
|
||||||
@@ -18,6 +19,7 @@ const FormButtons: React.FC<FormButtonsProps> = ({
|
|||||||
showOk = true,
|
showOk = true,
|
||||||
htmlType = 'button'
|
htmlType = 'button'
|
||||||
}) => {
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
return (
|
return (
|
||||||
<Space size={40} style={{ marginTop: '80px' }}>
|
<Space size={40} style={{ marginTop: '80px' }}>
|
||||||
{showOk && (
|
{showOk && (
|
||||||
@@ -27,12 +29,12 @@ const FormButtons: React.FC<FormButtonsProps> = ({
|
|||||||
style={{ width: '120px' }}
|
style={{ width: '120px' }}
|
||||||
htmlType={htmlType}
|
htmlType={htmlType}
|
||||||
>
|
>
|
||||||
{okText || '保存'}
|
{okText || intl.formatMessage({ id: 'common.button.save' })}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{showCancel && (
|
{showCancel && (
|
||||||
<Button onClick={onCancel} style={{ width: '98px' }}>
|
<Button onClick={onCancel} style={{ width: '98px' }}>
|
||||||
{cancelText || '取消'}
|
{cancelText || intl.formatMessage({ id: 'common.button.cancel' })}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import {
|
||||||
|
digitReg,
|
||||||
|
lowercaseReg,
|
||||||
|
specialCharacterReg,
|
||||||
|
uppercaseReg
|
||||||
|
} from '@/config';
|
||||||
|
import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Space } from 'antd';
|
||||||
|
|
||||||
|
const PasswordValidate: React.FC<{ value: string }> = ({ value = '' }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const renderIcon = ({ valid, text }: { valid: boolean; text: string }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{valid ? (
|
||||||
|
<CheckCircleFilled style={{ color: 'green' }} />
|
||||||
|
) : (
|
||||||
|
<CloseCircleFilled style={{ color: 'red' }} />
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
className="m-l-5"
|
||||||
|
style={{ color: 'var(--ant-color-text-description)' }}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Space direction="vertical" style={{ paddingTop: '10px' }}>
|
||||||
|
<span>
|
||||||
|
{renderIcon({
|
||||||
|
valid: uppercaseReg.test(value),
|
||||||
|
text: intl.formatMessage({ id: 'users.password.uppcase' })
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{renderIcon({
|
||||||
|
valid: lowercaseReg.test(value),
|
||||||
|
text: intl.formatMessage({ id: 'users.password.lowercase' })
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{renderIcon({
|
||||||
|
valid: digitReg.test(value),
|
||||||
|
text: intl.formatMessage({ id: 'users.password.number' })
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{renderIcon({
|
||||||
|
valid: value.length >= 6 && value.length <= 12,
|
||||||
|
text: intl.formatMessage({ id: 'users.password.length' })
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{renderIcon({
|
||||||
|
valid: specialCharacterReg.test(value),
|
||||||
|
text: intl.formatMessage({ id: 'users.password.special' })
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PasswordValidate;
|
||||||
@@ -43,3 +43,18 @@ export const WatchEventType = {
|
|||||||
UPDATE: 'MODIFIED',
|
UPDATE: 'MODIFIED',
|
||||||
DELETE: 'DELETED'
|
DELETE: 'DELETED'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PasswordReg =
|
||||||
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_])(?=\S+$).{6,12}$/;
|
||||||
|
|
||||||
|
export const uppercaseReg = /(?=.*[A-Z])/;
|
||||||
|
|
||||||
|
export const lowercaseReg = /(?=.*[a-z])/;
|
||||||
|
|
||||||
|
export const digitReg = /(?=.*\d)/;
|
||||||
|
|
||||||
|
export const specialCharacterReg = /(?=.*[\W_])/;
|
||||||
|
|
||||||
|
export const noSpaceReg = /(?=\S+$)/;
|
||||||
|
|
||||||
|
export const lengthReg = /^.{6,12}$/;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import menu from './en-US/menu';
|
|||||||
import models from './en-US/models';
|
import models from './en-US/models';
|
||||||
import playground from './en-US/playground';
|
import playground from './en-US/playground';
|
||||||
import resources from './en-US/resources';
|
import resources from './en-US/resources';
|
||||||
|
import users from './en-US/users';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...common,
|
...common,
|
||||||
@@ -11,5 +12,6 @@ export default {
|
|||||||
...models,
|
...models,
|
||||||
...playground,
|
...playground,
|
||||||
...resources,
|
...resources,
|
||||||
...apikeys
|
...apikeys,
|
||||||
|
...users
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
export default {
|
export default {
|
||||||
'apikeys.title': 'API Keys',
|
'apikeys.title': 'API Keys',
|
||||||
|
'apikeys.table.apikeys': 'keys',
|
||||||
'apikeys.button.create': 'New API Key',
|
'apikeys.button.create': 'New API Key',
|
||||||
'apikeys.form.expiretime': 'Expiration',
|
'apikeys.form.expiretime': 'Expiration',
|
||||||
'apikeys.table.name': 'Key Name'
|
'apikeys.table.name': 'Key Name',
|
||||||
|
'apikeys.table.save.tips':
|
||||||
|
'Make sure to copy your key immediately. You will not be able to see it again.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -179,5 +179,8 @@ export default {
|
|||||||
'common.settings.language': 'Language',
|
'common.settings.language': 'Language',
|
||||||
'common.delete.confirm':
|
'common.delete.confirm':
|
||||||
'Are you sure you want to delete the selected {type}?',
|
'Are you sure you want to delete the selected {type}?',
|
||||||
'common.filter.name': 'Filter by name'
|
'common.filter.name': 'Filter by name',
|
||||||
|
'common.form.password': 'Password',
|
||||||
|
'common.form.username': 'Username',
|
||||||
|
'common.login.rember': 'Remember me'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export default {
|
||||||
|
'users.title': 'Users',
|
||||||
|
'users.button.create': 'Create User',
|
||||||
|
'users.form.edit': 'Edit User',
|
||||||
|
'users.form.create': 'Create User',
|
||||||
|
'users.table.username': 'User Name',
|
||||||
|
'users.table.role': 'Role',
|
||||||
|
'users.form.fullname': 'Full Name',
|
||||||
|
'users.table.user': 'users',
|
||||||
|
'users.form.admin': 'Admin',
|
||||||
|
'users.form.user': 'User',
|
||||||
|
'users.form.newpassword': 'New Password',
|
||||||
|
'users.form.currentpassword': 'Current Password',
|
||||||
|
'users.form.updatepassword': 'Modify Password',
|
||||||
|
'users.form.rule.password':
|
||||||
|
'Contains uppercase and lowercase letters, numbers, and special characters, 6 to 12 characters in length, no spaces allowed.',
|
||||||
|
'users.password.uppcase': 'At least one uppercase letter',
|
||||||
|
'users.password.lowercase': 'At least one lowercase letter',
|
||||||
|
'users.password.number': 'At least one number',
|
||||||
|
'users.password.special': 'At least one special character',
|
||||||
|
'users.password.length': 'Length between 6 and 12 characters'
|
||||||
|
};
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import menu from './en-US/menu';
|
|
||||||
import apikeys from './zh-CN/apikeys';
|
import apikeys from './zh-CN/apikeys';
|
||||||
import common from './zh-CN/common';
|
import common from './zh-CN/common';
|
||||||
|
import menu from './zh-CN/menu';
|
||||||
import models from './zh-CN/models';
|
import models from './zh-CN/models';
|
||||||
import playground from './zh-CN/playground';
|
import playground from './zh-CN/playground';
|
||||||
import resources from './zh-CN/resources';
|
import resources from './zh-CN/resources';
|
||||||
|
import users from './zh-CN/users';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...common,
|
...common,
|
||||||
@@ -11,5 +12,6 @@ export default {
|
|||||||
...models,
|
...models,
|
||||||
...playground,
|
...playground,
|
||||||
...resources,
|
...resources,
|
||||||
...apikeys
|
...apikeys,
|
||||||
|
...users
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
export default {
|
export default {
|
||||||
'apikeys.title': 'API 密钥',
|
'apikeys.title': 'API 密钥',
|
||||||
|
'apikeys.table.apikeys': '密钥',
|
||||||
'apikeys.button.create': '新建 API 密钥',
|
'apikeys.button.create': '新建 API 密钥',
|
||||||
'apikeys.form.expiretime': '过期时间',
|
'apikeys.form.expiretime': '过期时间',
|
||||||
'apikeys.table.name': '密钥名称'
|
'apikeys.table.name': '密钥名称',
|
||||||
|
'apikeys.table.save.tips': '确保立即复制您的密钥。您将无法再次看到它!'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -174,5 +174,8 @@ export default {
|
|||||||
'common.settings.instructions': '操作指引',
|
'common.settings.instructions': '操作指引',
|
||||||
'common.settings.language': '语言',
|
'common.settings.language': '语言',
|
||||||
'common.delete.confirm': '确定删除选中的{type}吗?',
|
'common.delete.confirm': '确定删除选中的{type}吗?',
|
||||||
'common.filter.name': '名称查询'
|
'common.filter.name': '名称查询',
|
||||||
|
'common.form.password': '密码',
|
||||||
|
'common.form.username': '用户名',
|
||||||
|
'common.login.rember': '记住我'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export default {
|
||||||
|
'users.title': '用户',
|
||||||
|
'users.button.create': '新建用户',
|
||||||
|
'users.form.edit': '编辑用户',
|
||||||
|
'users.form.create': '新建用户',
|
||||||
|
'users.table.username': '用户名',
|
||||||
|
'users.table.role': '角色',
|
||||||
|
'users.form.fullname': '全名',
|
||||||
|
'users.table.user': '用户',
|
||||||
|
'users.form.admin': '管理员',
|
||||||
|
'users.form.user': '普通用户',
|
||||||
|
'users.form.newpassword': '新密码',
|
||||||
|
'users.form.currentpassword': '当前密码',
|
||||||
|
'users.form.updatepassword': '修改密码',
|
||||||
|
'users.form.rule.password':
|
||||||
|
'包含大小写字母、数字和特殊字符,6至12个字符,不允许有空格',
|
||||||
|
'users.password.uppcase': '至少包含一个大写字母',
|
||||||
|
'users.password.lowercase': '至少包含一个小写字母',
|
||||||
|
'users.password.number': '至少包含一个数字',
|
||||||
|
'users.password.special': '至少包含一个特殊字符',
|
||||||
|
'users.password.length': '长度在6至12个字符之间'
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import SealInput from '@/components/seal-form/seal-input';
|
|||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
import { SyncOutlined } from '@ant-design/icons';
|
import { SyncOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form, Modal } from 'antd';
|
import { Form, Modal } from 'antd';
|
||||||
import { expirationOptions } from '../config';
|
import { expirationOptions } from '../config';
|
||||||
import { FormData } from '../config/types';
|
import { FormData } from '../config/types';
|
||||||
@@ -23,6 +24,7 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
onCancel
|
onCancel
|
||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const intl = useIntl();
|
||||||
const Suffix = (
|
const Suffix = (
|
||||||
<SyncOutlined
|
<SyncOutlined
|
||||||
style={{
|
style={{
|
||||||
@@ -53,18 +55,49 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Form name="addAPIKey" form={form} onFinish={onOk} preserve={false}>
|
<Form name="addAPIKey" form={form} onFinish={onOk} preserve={false}>
|
||||||
<Form.Item<FormData> name="name" rules={[{ required: true }]}>
|
<Form.Item<FormData>
|
||||||
<SealInput.Input label="Name" required></SealInput.Input>
|
name="name"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.table.name' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Input
|
||||||
|
label={intl.formatMessage({ id: 'common.table.name' })}
|
||||||
|
required
|
||||||
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="expires_in" rules={[{ required: true }]}>
|
<Form.Item<FormData>
|
||||||
|
name="expires_in"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.select' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'apikeys.form.expiretime' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<SealSelect
|
<SealSelect
|
||||||
label="Expiration"
|
label={intl.formatMessage({ id: 'apikeys.form.expiretime' })}
|
||||||
required
|
required
|
||||||
options={expirationOptions}
|
options={expirationOptions}
|
||||||
></SealSelect>
|
></SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="description" rules={[{ required: false }]}>
|
<Form.Item<FormData> name="description" rules={[{ required: false }]}>
|
||||||
<SealInput.TextArea label="Description"></SealInput.TextArea>
|
<SealInput.TextArea
|
||||||
|
label={intl.formatMessage({ id: 'common.table.description' })}
|
||||||
|
></SealInput.TextArea>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ const Models: React.FC = () => {
|
|||||||
};
|
};
|
||||||
const res = await createApisKey({ data: params });
|
const res = await createApisKey({ data: params });
|
||||||
setOpenAddModal(false);
|
setOpenAddModal(false);
|
||||||
message.success('successfully!');
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
setDataSource([res, ...dataSource]);
|
setDataSource([res, ...dataSource]);
|
||||||
setTotal(total + 1);
|
setTotal(total + 1);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -144,11 +144,14 @@ const Models: React.FC = () => {
|
|||||||
const handleDelete = (row: ListItem) => {
|
const handleDelete = (row: ListItem) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '',
|
title: '',
|
||||||
content: 'Are you sure you want to delete the selected keys?',
|
content: intl.formatMessage(
|
||||||
|
{ id: 'common.delete.confirm' },
|
||||||
|
{ type: intl.formatMessage({ id: 'apikeys.table.apikeys' }) }
|
||||||
|
),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
console.log('OK');
|
console.log('OK');
|
||||||
await deleteApisKey(row.id);
|
await deleteApisKey(row.id);
|
||||||
message.success('successfully!');
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
fetchData();
|
fetchData();
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
@@ -160,10 +163,13 @@ const Models: React.FC = () => {
|
|||||||
const handleDeleteBatch = () => {
|
const handleDeleteBatch = () => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '',
|
title: '',
|
||||||
content: 'Are you sure you want to delete the selected keys?',
|
content: intl.formatMessage(
|
||||||
|
{ id: 'common.delete.confirm' },
|
||||||
|
{ type: intl.formatMessage({ id: 'apikeys.table.apikeys' }) }
|
||||||
|
),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
await handleBatchRequest(rowSelection.selectedRowKeys, deleteApisKey);
|
await handleBatchRequest(rowSelection.selectedRowKeys, deleteApisKey);
|
||||||
message.success('successfully!');
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
fetchData();
|
fetchData();
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
@@ -172,12 +178,6 @@ const Models: React.FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditUser = () => {
|
|
||||||
setOpenAddModal(true);
|
|
||||||
setAction(PageAction.EDIT);
|
|
||||||
setTitle('Edit User');
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderSecrectKey = (text: string, record: ListItem) => {
|
const renderSecrectKey = (text: string, record: ListItem) => {
|
||||||
const { value } = record;
|
const { value } = record;
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ const Models: React.FC = () => {
|
|||||||
{value && (
|
{value && (
|
||||||
<span>
|
<span>
|
||||||
<Tag color="error" style={{ padding: '10px 12px' }}>
|
<Tag color="error" style={{ padding: '10px 12px' }}>
|
||||||
确保立即复制您的个人访问密钥。您将无法再次看到它!
|
{intl.formatMessage({ id: 'apikeys.table.save.tips' })}
|
||||||
</Tag>
|
</Tag>
|
||||||
<span className="flex-center">
|
<span className="flex-center">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -299,7 +299,7 @@ const Models: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Column
|
<Column
|
||||||
title="Operation"
|
title={intl.formatMessage({ id: 'common.table.operation' })}
|
||||||
key="operation"
|
key="operation"
|
||||||
render={(text, record: ListItem) => {
|
render={(text, record: ListItem) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -27,3 +27,10 @@ export const accessToken = async () => {
|
|||||||
method: 'POST'
|
method: 'POST'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updatePassword = async (params: any) => {
|
||||||
|
return request(`${AUTH_API}/update-password`, {
|
||||||
|
method: 'POST',
|
||||||
|
data: params
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
+58
-39
@@ -1,7 +1,7 @@
|
|||||||
import LogoIcon from '@/assets/images/logo.png';
|
import LogoIcon from '@/assets/images/logo.png';
|
||||||
import SealInput from '@/components/seal-form/seal-input';
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
import { GlobalOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
import { history, useModel } from '@umijs/max';
|
import { SelectLang, history, useIntl, useModel } from '@umijs/max';
|
||||||
import { Button, Checkbox, Form } from 'antd';
|
import { Button, Checkbox, Form } from 'antd';
|
||||||
import { flushSync } from 'react-dom';
|
import { flushSync } from 'react-dom';
|
||||||
import { login } from './apis';
|
import { login } from './apis';
|
||||||
@@ -24,7 +24,7 @@ const renderLogo = () => {
|
|||||||
};
|
};
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const { initialState, setInitialState } = useModel('@@initialState');
|
const { initialState, setInitialState } = useModel('@@initialState');
|
||||||
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const gotoDefaultPage = (userInfo: any) => {
|
const gotoDefaultPage = (userInfo: any) => {
|
||||||
@@ -61,44 +61,63 @@ const Login = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<div>
|
||||||
form={form}
|
<div style={{ position: 'fixed', right: 0, top: 0, padding: '0 20px' }}>
|
||||||
style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }}
|
<SelectLang icon={<GlobalOutlined />} reload={false} />
|
||||||
onFinish={handleLogin}
|
</div>
|
||||||
>
|
<Form
|
||||||
<div>{renderLogo()}</div>
|
form={form}
|
||||||
<Form.Item
|
style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }}
|
||||||
name="username"
|
onFinish={handleLogin}
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: 'Please input your Username!'
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<SealInput.Input label="Username" prefix={<UserOutlined />} />
|
<div>{renderLogo()}</div>
|
||||||
</Form.Item>
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{ name: intl.formatMessage({ id: 'common.form.username' }) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Input
|
||||||
|
label={intl.formatMessage({ id: 'common.form.username' })}
|
||||||
|
prefix={<UserOutlined />}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="password"
|
name="password"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please input your Password!'
|
message: intl.formatMessage(
|
||||||
}
|
{ id: 'common.form.rule.input' },
|
||||||
]}
|
{ name: intl.formatMessage({ id: 'common.form.password' }) }
|
||||||
>
|
)
|
||||||
<SealInput.Password prefix={<LockOutlined />} label="Password" />
|
}
|
||||||
</Form.Item>
|
]}
|
||||||
<Form.Item name="autoLogin">
|
>
|
||||||
<div style={{ paddingLeft: 10 }}>
|
<SealInput.Password
|
||||||
<Checkbox>Remember me</Checkbox>
|
prefix={<LockOutlined />}
|
||||||
</div>
|
label={intl.formatMessage({ id: 'common.form.password' })}
|
||||||
</Form.Item>
|
/>
|
||||||
<Button htmlType="submit" type="primary" block>
|
</Form.Item>
|
||||||
Login
|
<Form.Item name="autoLogin">
|
||||||
</Button>
|
<div style={{ paddingLeft: 10 }}>
|
||||||
</Form>
|
<Checkbox>
|
||||||
|
{intl.formatMessage({ id: 'common.login.rember' })}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
<Button htmlType="submit" type="primary" block>
|
||||||
|
{intl.formatMessage({ id: 'menu.login' })}
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export const receiveChatStream = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chunk = decoder.decode(value, { stream: true });
|
let chunk = decoder.decode(value, { stream: true });
|
||||||
if (chunk.startsWith('data: ')) {
|
if (chunk.startsWith('data:')) {
|
||||||
chunk = chunk.substring('data: '.length);
|
chunk = chunk.substring('data:'.length);
|
||||||
}
|
}
|
||||||
const item = JSON.parse(chunk?.trim());
|
const item = JSON.parse(chunk?.trim());
|
||||||
callback(item);
|
callback(item);
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ const MessageList: React.FC<MessageProps> = (props) => {
|
|||||||
const systemRef = useRef<any>(null);
|
const systemRef = useRef<any>(null);
|
||||||
const contentRef = useRef<any>('');
|
const contentRef = useRef<any>('');
|
||||||
|
|
||||||
const handleReceiveMessage = (data: any) => {
|
|
||||||
console.log('event source message: ', { data });
|
|
||||||
};
|
|
||||||
const handleSystemMessageChange = (e: any) => {
|
const handleSystemMessageChange = (e: any) => {
|
||||||
setSystemMessage(e.target.value);
|
setSystemMessage(e.target.value);
|
||||||
};
|
};
|
||||||
|
|||||||
+58
-23
@@ -1,21 +1,29 @@
|
|||||||
import FormButtons from '@/components/form-buttons';
|
import FormButtons from '@/components/form-buttons';
|
||||||
import SealInput from '@/components/seal-form/seal-input';
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
|
import { PasswordReg } from '@/config';
|
||||||
import { INPUT_WIDTH } from '@/constants';
|
import { INPUT_WIDTH } from '@/constants';
|
||||||
|
import { updatePassword } from '@/pages/login/apis';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { Form } from 'antd';
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Form, message } from 'antd';
|
||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
|
|
||||||
interface ProfileProps {
|
interface ProfileProps {
|
||||||
name: string;
|
username?: string;
|
||||||
password: string;
|
new_password: string;
|
||||||
originalPassword: string;
|
current_password: string;
|
||||||
email: string;
|
|
||||||
}
|
}
|
||||||
const Profile: React.FC = () => {
|
const Profile: React.FC = () => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleOnFinish = (values: any) => {
|
const newpasswordValue = Form.useWatch('new_password', form);
|
||||||
console.log('handleOnFinish', values);
|
|
||||||
|
const handleOnFinish = async (values: any) => {
|
||||||
|
try {
|
||||||
|
await updatePassword(values);
|
||||||
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnFinishFailed = (errorInfo: any) => {
|
const handleOnFinishFailed = (errorInfo: any) => {
|
||||||
@@ -30,7 +38,7 @@ const Profile: React.FC = () => {
|
|||||||
<PageContainer
|
<PageContainer
|
||||||
ghost
|
ghost
|
||||||
header={{
|
header={{
|
||||||
title: 'Profile'
|
title: intl.formatMessage({ id: 'users.form.updatepassword' })
|
||||||
}}
|
}}
|
||||||
extra={[]}
|
extra={[]}
|
||||||
>
|
>
|
||||||
@@ -41,33 +49,60 @@ const Profile: React.FC = () => {
|
|||||||
onFinish={handleOnFinish}
|
onFinish={handleOnFinish}
|
||||||
onFinishFailed={handleOnFinishFailed}
|
onFinishFailed={handleOnFinishFailed}
|
||||||
>
|
>
|
||||||
<Form.Item<ProfileProps> name="name" rules={[{ required: true }]}>
|
{/* <Form.Item<ProfileProps>
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.form.username' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<SealInput.Input
|
<SealInput.Input
|
||||||
label="Name"
|
label={intl.formatMessage({ id: 'common.form.username' })}
|
||||||
required
|
required
|
||||||
style={{ width: INPUT_WIDTH.default }}
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
></SealInput.Input>
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item> */}
|
||||||
<Form.Item<ProfileProps> name="email" rules={[{ required: true }]}>
|
|
||||||
<SealInput.Input
|
|
||||||
label="Email"
|
|
||||||
required
|
|
||||||
style={{ width: INPUT_WIDTH.default }}
|
|
||||||
></SealInput.Input>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item<ProfileProps>
|
<Form.Item<ProfileProps>
|
||||||
name="originalPassword"
|
name="current_password"
|
||||||
rules={[{ required: true }]}
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({
|
||||||
|
id: 'users.form.currentpassword'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
<SealInput.Password
|
<SealInput.Password
|
||||||
label="Original Password"
|
label={intl.formatMessage({ id: 'users.form.currentpassword' })}
|
||||||
required
|
required
|
||||||
style={{ width: INPUT_WIDTH.default }}
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
></SealInput.Password>
|
></SealInput.Password>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<ProfileProps> name="password" rules={[{ required: true }]}>
|
<Form.Item<ProfileProps>
|
||||||
|
name="new_password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
pattern: PasswordReg,
|
||||||
|
message: intl.formatMessage({ id: 'users.form.rule.password' })
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<SealInput.Password
|
<SealInput.Password
|
||||||
label="Password"
|
label={intl.formatMessage({ id: 'users.form.newpassword' })}
|
||||||
required
|
required
|
||||||
style={{ width: INPUT_WIDTH.default }}
|
style={{ width: INPUT_WIDTH.default }}
|
||||||
></SealInput.Password>
|
></SealInput.Password>
|
||||||
|
|||||||
@@ -3,8 +3,13 @@ import SealInput from '@/components/seal-form/seal-input';
|
|||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
import { SyncOutlined } from '@ant-design/icons';
|
import {
|
||||||
import { Form, Modal } from 'antd';
|
SyncOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
UserSwitchOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Form, Modal, Select } from 'antd';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { UserRoles, UserRolesOptions } from '../config';
|
import { UserRoles, UserRolesOptions } from '../config';
|
||||||
import { FormData, ListItem } from '../config/types';
|
import { FormData, ListItem } from '../config/types';
|
||||||
@@ -26,6 +31,7 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
onCancel
|
onCancel
|
||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const intl = useIntl();
|
||||||
const suffix = (
|
const suffix = (
|
||||||
<SyncOutlined
|
<SyncOutlined
|
||||||
style={{
|
style={{
|
||||||
@@ -68,18 +74,67 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Form name="addUserForm" form={form} onFinish={onOk} preserve={false}>
|
<Form name="addUserForm" form={form} onFinish={onOk} preserve={false}>
|
||||||
<Form.Item<FormData> name="username" rules={[{ required: true }]}>
|
<Form.Item<FormData>
|
||||||
<SealInput.Input label="Name" required></SealInput.Input>
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.table.name' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Input
|
||||||
|
label={intl.formatMessage({ id: 'common.table.name' })}
|
||||||
|
required
|
||||||
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="full_name" rules={[{ required: false }]}>
|
<Form.Item<FormData> name="full_name" rules={[{ required: false }]}>
|
||||||
<SealInput.Input label="FullName"></SealInput.Input>
|
<SealInput.Input
|
||||||
|
label={intl.formatMessage({ id: 'users.form.fullname' })}
|
||||||
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="is_admin" rules={[{ required: false }]}>
|
<Form.Item<FormData> name="is_admin" rules={[{ required: false }]}>
|
||||||
<SealSelect label="Role" options={UserRolesOptions}></SealSelect>
|
<SealSelect label={intl.formatMessage({ id: 'users.table.role' })}>
|
||||||
|
{UserRolesOptions.map((item) => {
|
||||||
|
return (
|
||||||
|
<Select.Option value={item.value} key={item.value}>
|
||||||
|
{item.value === UserRoles.ADMIN ? (
|
||||||
|
<UserSwitchOutlined className="size-16" />
|
||||||
|
) : (
|
||||||
|
<UserOutlined className="size-16" />
|
||||||
|
)}
|
||||||
|
<span className="m-l-5">
|
||||||
|
{intl.formatMessage({ id: item.label })}
|
||||||
|
</span>
|
||||||
|
</Select.Option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<FormData> name="password" rules={[{ required: true }]}>
|
<Form.Item<FormData>
|
||||||
<SealInput.Password label="Password" required></SealInput.Password>
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.form.password' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Password
|
||||||
|
label={intl.formatMessage({ id: 'common.form.password' })}
|
||||||
|
required
|
||||||
|
></SealInput.Password>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ export const UserRoles = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const UserRolesOptions = [
|
export const UserRolesOptions = [
|
||||||
{ label: '管理员', value: UserRoles.ADMIN },
|
{ label: 'users.form.admin', value: UserRoles.ADMIN },
|
||||||
{ label: '普通用户', value: UserRoles.USER }
|
{ label: 'users.form.user', value: UserRoles.USER }
|
||||||
];
|
];
|
||||||
|
|||||||
+41
-24
@@ -13,6 +13,7 @@ import {
|
|||||||
UserSwitchOutlined
|
UserSwitchOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Input, Modal, Space, Table, Tooltip, message } from 'antd';
|
import { Button, Input, Modal, Space, Table, Tooltip, message } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -27,6 +28,7 @@ const Models: React.FC = () => {
|
|||||||
const { sortOrder, setSortOrder } = useTableSort({
|
const { sortOrder, setSortOrder } = useTableSort({
|
||||||
defaultSortOrder: 'descend'
|
defaultSortOrder: 'descend'
|
||||||
});
|
});
|
||||||
|
const intl = useIntl();
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [openAddModal, setOpenAddModal] = useState(false);
|
const [openAddModal, setOpenAddModal] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -93,11 +95,7 @@ const Models: React.FC = () => {
|
|||||||
const handleAddUser = () => {
|
const handleAddUser = () => {
|
||||||
setOpenAddModal(true);
|
setOpenAddModal(true);
|
||||||
setAction(PageAction.CREATE);
|
setAction(PageAction.CREATE);
|
||||||
setTitle('Add User');
|
setTitle(intl.formatMessage({ id: 'users.form.create' }));
|
||||||
};
|
|
||||||
|
|
||||||
const handleClickMenu = (e: any) => {
|
|
||||||
console.log('click', e);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleModalOk = async (data: FormData) => {
|
const handleModalOk = async (data: FormData) => {
|
||||||
@@ -119,7 +117,7 @@ const Models: React.FC = () => {
|
|||||||
}
|
}
|
||||||
fetchData();
|
fetchData();
|
||||||
setOpenAddModal(false);
|
setOpenAddModal(false);
|
||||||
message.success('successfully!');
|
message.success('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setOpenAddModal(false);
|
setOpenAddModal(false);
|
||||||
}
|
}
|
||||||
@@ -133,11 +131,14 @@ const Models: React.FC = () => {
|
|||||||
const handleDelete = (row: ListItem) => {
|
const handleDelete = (row: ListItem) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '',
|
title: '',
|
||||||
content: 'Are you sure you want to delete the selected users?',
|
content: intl.formatMessage(
|
||||||
|
{ id: 'common.delete.confirm' },
|
||||||
|
{ type: intl.formatMessage({ id: 'users.table.user' }) }
|
||||||
|
),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
console.log('OK');
|
console.log('OK');
|
||||||
await deleteUser(row.id);
|
await deleteUser(row.id);
|
||||||
message.success('successfully!');
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
fetchData();
|
fetchData();
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
@@ -149,10 +150,13 @@ const Models: React.FC = () => {
|
|||||||
const handleDeleteBatch = () => {
|
const handleDeleteBatch = () => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '',
|
title: '',
|
||||||
content: 'Are you sure you want to delete the selected users?',
|
content: intl.formatMessage(
|
||||||
|
{ id: 'common.delete.confirm' },
|
||||||
|
{ type: intl.formatMessage({ id: 'users.table.user' }) }
|
||||||
|
),
|
||||||
async onOk() {
|
async onOk() {
|
||||||
await handleBatchRequest(rowSelection.selectedRowKeys, deleteUser);
|
await handleBatchRequest(rowSelection.selectedRowKeys, deleteUser);
|
||||||
message.success('successfully!');
|
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||||
fetchData();
|
fetchData();
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
@@ -165,7 +169,7 @@ const Models: React.FC = () => {
|
|||||||
setCurrentData(row);
|
setCurrentData(row);
|
||||||
setOpenAddModal(true);
|
setOpenAddModal(true);
|
||||||
setAction(PageAction.EDIT);
|
setAction(PageAction.EDIT);
|
||||||
setTitle('Edit User');
|
setTitle(intl.formatMessage({ id: 'users.form.edit' }));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -177,7 +181,7 @@ const Models: React.FC = () => {
|
|||||||
<PageContainer
|
<PageContainer
|
||||||
ghost
|
ghost
|
||||||
header={{
|
header={{
|
||||||
title: 'Users'
|
title: intl.formatMessage({ id: 'users.title' })
|
||||||
}}
|
}}
|
||||||
extra={[]}
|
extra={[]}
|
||||||
>
|
>
|
||||||
@@ -186,7 +190,7 @@ const Models: React.FC = () => {
|
|||||||
left={
|
left={
|
||||||
<Space>
|
<Space>
|
||||||
<Input
|
<Input
|
||||||
placeholder="名称查询"
|
placeholder={intl.formatMessage({ id: 'common.filter.name' })}
|
||||||
style={{ width: 300 }}
|
style={{ width: 300 }}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
></Input>
|
></Input>
|
||||||
@@ -205,7 +209,7 @@ const Models: React.FC = () => {
|
|||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleAddUser}
|
onClick={handleAddUser}
|
||||||
>
|
>
|
||||||
Add User
|
{intl.formatMessage({ id: 'users.button.create' })}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
icon={<DeleteOutlined />}
|
icon={<DeleteOutlined />}
|
||||||
@@ -213,7 +217,7 @@ const Models: React.FC = () => {
|
|||||||
onClick={handleDeleteBatch}
|
onClick={handleDeleteBatch}
|
||||||
disabled={!rowSelection.selectedRowKeys.length}
|
disabled={!rowSelection.selectedRowKeys.length}
|
||||||
>
|
>
|
||||||
Delete
|
{intl.formatMessage({ id: 'common.button.delete' })}
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
@@ -234,9 +238,14 @@ const Models: React.FC = () => {
|
|||||||
onChange: handlePageChange
|
onChange: handlePageChange
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Column title="Name" dataIndex="username" key="name" width={200} />
|
|
||||||
<Column
|
<Column
|
||||||
title="Create Time"
|
title={intl.formatMessage({ id: 'users.table.username' })}
|
||||||
|
dataIndex="username"
|
||||||
|
key="name"
|
||||||
|
width={200}
|
||||||
|
/>
|
||||||
|
<Column
|
||||||
|
title={intl.formatMessage({ id: 'common.table.createTime' })}
|
||||||
dataIndex="created_at"
|
dataIndex="created_at"
|
||||||
key="createTime"
|
key="createTime"
|
||||||
defaultSortOrder="descend"
|
defaultSortOrder="descend"
|
||||||
@@ -248,25 +257,29 @@ const Models: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Column
|
<Column
|
||||||
title="Role"
|
title={intl.formatMessage({ id: 'users.table.role' })}
|
||||||
dataIndex="role"
|
dataIndex="role"
|
||||||
key="role"
|
key="role"
|
||||||
render={(text, record: ListItem) => {
|
render={(text, record: ListItem) => {
|
||||||
return record.is_admin ? (
|
return record.is_admin ? (
|
||||||
<>
|
<>
|
||||||
<UserSwitchOutlined className="size-16" />
|
<UserSwitchOutlined className="size-16" />
|
||||||
<span className="m-l-5">管理员</span>
|
<span className="m-l-5">
|
||||||
|
{intl.formatMessage({ id: 'users.form.admin' })}
|
||||||
|
</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<UserOutlined className="size-16" />
|
<UserOutlined className="size-16" />
|
||||||
<span className="m-l-5">普通用户</span>
|
<span className="m-l-5">
|
||||||
|
{intl.formatMessage({ id: 'users.form.user' })}
|
||||||
|
</span>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Column
|
<Column
|
||||||
title="Update Time"
|
title={intl.formatMessage({ id: 'common.table.updateTime' })}
|
||||||
dataIndex="updated_at"
|
dataIndex="updated_at"
|
||||||
key="updateTime"
|
key="updateTime"
|
||||||
defaultSortOrder="descend"
|
defaultSortOrder="descend"
|
||||||
@@ -278,13 +291,15 @@ const Models: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Column
|
<Column
|
||||||
title="Operation"
|
title={intl.formatMessage({ id: 'common.table.operation' })}
|
||||||
key="operation"
|
key="operation"
|
||||||
width={200}
|
width={200}
|
||||||
render={(text, record: ListItem) => {
|
render={(text, record: ListItem) => {
|
||||||
return (
|
return (
|
||||||
<Space size={20}>
|
<Space size={20}>
|
||||||
<Tooltip title="编辑">
|
<Tooltip
|
||||||
|
title={intl.formatMessage({ id: 'common.button.edit' })}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -292,7 +307,9 @@ const Models: React.FC = () => {
|
|||||||
icon={<EditOutlined></EditOutlined>}
|
icon={<EditOutlined></EditOutlined>}
|
||||||
></Button>
|
></Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="删除">
|
<Tooltip
|
||||||
|
title={intl.formatMessage({ id: 'common.button.delete' })}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
Reference in New Issue
Block a user