style: help menu

This commit is contained in:
jialin
2024-07-10 15:41:05 +08:00
parent f103da4178
commit 0ed7568859
25 changed files with 226 additions and 678 deletions
+2 -2
View File
@@ -168,12 +168,12 @@ export const gaugeItemConfig = {
},
rich: {
value: {
fontSize: 20,
fontSize: 16,
fontWeight: '500',
color: 'rgba(0, 0, 0, 0.88)'
},
unit: {
fontSize: 16,
fontSize: 14,
color: 'rgba(0, 0, 0, 0.88)',
fontWeight: '500',
padding: [0, 0, 0, 2]
+2 -1
View File
@@ -59,8 +59,9 @@ const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
e.target.value = e.target.value?.trim?.();
if (!inputRef.current?.input?.value) {
setIsFocus(false);
props.onBlur?.(e);
}
props.onChange?.(e);
props.onBlur?.(e);
};
const handleInput = (e: any) => {
+16 -13
View File
@@ -273,7 +273,8 @@ body {
}
.ant-pro-sider-logo {
padding-left: 20px;
padding-left: 18px;
border-block-end: none;
}
.ant-pro-sider-logo-collapsed {
@@ -320,20 +321,12 @@ body {
.ant-pro-layout {
height: 100vh;
// .ant-pro-layout-content {
// padding-block: var(--layout-content-blockpadding);
// padding-inline: var(--layout-content-inlinepadding);
// }
.ant-pro-page-container-children-container {
padding-block: var(--layout-content-blockpadding);
padding-inline: var(--layout-content-inlinepadding);
}
.ant-pro-sider-logo {
padding-left: 22px;
border-block-end: none;
}
.ant-layout {
min-height: 100vh;
}
@@ -382,6 +375,18 @@ body {
}
}
// ======== menu style end ============
.ant-menu-submenu-popup {
.ant-menu-sub {
.ant-menu-item-only-child {
height: 40px;
line-height: 40px;
.anticon {
font-size: var(--font-size-middle);
}
}
}
}
.user-menu-container {
.user-avatar.ant-menu-submenu {
@@ -425,9 +430,7 @@ body {
left: 0;
bottom: 0;
right: 0;
// background: url('@/assets/images/bg-11.png') center center no-repeat;
// background-size: cover;
background-color: #fff;
background-color: var(--color-white-1);
&::after {
content: '';
+3 -4
View File
@@ -21,15 +21,14 @@ export default function useContainerScroll(
scrollHeight > clientHeight + scrollTop
) {
scroller.current.current.scrollTop = scrollHeight;
toBottomFlag.current = false;
// toBottomFlag.current = false;
isWheeled.current = false;
}
if (
} else if (
!isWheeled.current &&
scrollHeight > clientHeight + scrollTop &&
scroller.current?.current
) {
scroller.current.current.scrollTop += 5;
scroller.current.current.scrollTop += 10;
window.requestAnimationFrame(scrollerRun);
}
};
+77 -3
View File
@@ -3,8 +3,14 @@
import avatarImg from '@/assets/images/avatar.png';
import langConfigMap from '@/locales/lang-config-map';
import {
DiscordOutlined,
GithubOutlined,
GlobalOutlined,
HomeOutlined,
InfoCircleOutlined,
LogoutOutlined,
QuestionCircleOutlined,
ReadOutlined,
SettingOutlined
} from '@ant-design/icons';
import { getAllLocales, history, setLocale } from '@umijs/max';
@@ -62,6 +68,66 @@ export function getRightRenderContent(opts: {
);
}
const helpList = [
{
key: 'site',
icon: <HomeOutlined />,
label: 'GPUStack',
url: 'https://gpustack.ai/'
},
{
key: 'github',
icon: <GithubOutlined />,
label: 'GitHub'
},
{
key: 'Discord',
icon: <DiscordOutlined />,
label: 'Discord'
},
{
key: 'docs',
icon: <ReadOutlined />,
label: intl.formatMessage({ id: 'common.button.docs' })
},
{
key: 'version',
icon: <InfoCircleOutlined />,
label: intl.formatMessage({ id: 'common.button.version' })
}
];
const helpMenu = {
selectedKeys: [],
className: collapsed
? 'user-menu-container user-menu-collapsed'
: 'user-menu-container',
mode: 'vertical',
expandIcon: false,
inlineCollapsed: collapsed,
triggerSubMenuAction: 'hover',
items: [
{
key: 'help',
icon: <QuestionCircleOutlined />,
label: (
<span>{intl?.formatMessage?.({ id: 'common.button.help' })}</span>
),
children: helpList.map((item) => ({
key: item.key,
label: (
<span className="flex flex-center">
{item.icon}
<a className="m-l-8" href="#" target="_blank">
{item.label}
</a>
</span>
)
}))
}
]
};
const langMenu = {
selectedKeys: [],
className: collapsed
@@ -84,7 +150,9 @@ export function getRightRenderContent(opts: {
key,
label: (
<span className="flex flex-center">
<span>{_.get(langConfigMap, [key, 'icon'])}</span>
<span className="font-size-14">
{_.get(langConfigMap, [key, 'icon'])}
</span>
<span className="m-l-8">
{_.get(langConfigMap, [key, 'label'])}
</span>
@@ -139,7 +207,7 @@ export function getRightRenderContent(opts: {
label: (
<span className="flex flex-center">
<SettingOutlined />
<span>
<span className="m-l-8" style={{ marginLeft: 8 }}>
{intl?.formatMessage?.({ id: 'common.button.settings' })}
</span>
</span>
@@ -153,7 +221,7 @@ export function getRightRenderContent(opts: {
label: (
<span className="flex flex-center">
<LogoutOutlined />
<span>
<span className="m-l-8" style={{ marginLeft: 8 }}>
{intl?.formatMessage?.({ id: 'common.button.logout' })}
</span>
</span>
@@ -169,6 +237,12 @@ export function getRightRenderContent(opts: {
return (
<div>
<Menu
{...helpMenu}
style={{
width: collapsed ? 64 : `calc(${siderWidth}px - 16px)`
}}
></Menu>
<Menu
{...langMenu}
style={{
+5 -1
View File
@@ -187,5 +187,9 @@ export default {
'common.form.password': 'Password',
'common.form.username': 'Username',
'common.login.rember': 'Remember me',
'settings.company': 'SEAL'
'settings.company': 'SEAL',
'common.button.help': 'Help',
'common.button.feedback': 'Feedback',
'common.button.docs': 'Documentation',
'common.button.version': 'Version'
};
+11 -1
View File
@@ -14,5 +14,15 @@ export default {
'playground.prompt': 'Prompt',
'playground.tokenusage': 'Token Usage',
'models.openinplayground': 'Open in Playground',
'playground.tokenoutput': 'Output'
'playground.tokenoutput': 'Output',
'playground.params.temperature.tips':
'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',
'playground.params.maxtokens.tips':
"The maximum number of tokens to generated. The total length of input tokens and generated tokens is limited by the model's context length.",
'playground.params.topp.tips':
'Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered.',
'playground.params.seed.tips':
'Specify a random seed to ensure deterministic sampling. Using the same seed and parameters will produce the same results for repeated requests.',
'playground.params.stop.tips':
'A stop sequence is a predefined or user-specified text string that signals the AI to stop generating further tokens when these sequences appear.'
};
+5 -1
View File
@@ -180,5 +180,9 @@ export default {
'common.form.password': '密码',
'common.form.username': '用户名',
'common.login.rember': '记住我',
'settings.company': '数澈软件'
'settings.company': '数澈软件',
'common.button.help': '帮助',
'common.button.feedback': '反馈',
'common.button.docs': '文档',
'common.button.version': '版本'
};
+11 -1
View File
@@ -14,5 +14,15 @@ export default {
'playground.prompt': '提示',
'playground.tokenusage': 'Token 使用量',
'models.openinplayground': '打开试验场',
'playground.tokenoutput': '输出'
'playground.tokenoutput': '输出',
'playground.params.temperature.tips':
'控制随机性:降低温度会导致更少的随机完成。当温度接近零时,模型将变得确定性和重复性。',
'playground.params.maxtokens.tips':
'生成的最大 token 数。输入标记和生成的标记的总长度受模型上下文长度的限制。',
'playground.params.topp.tips':
'通过核采样控制多样性:0.5 表示考虑所有基于概率权重选项的一半。',
'playground.params.seed.tips':
'指定随机种子以确保确定性采样。使用相同的种子和参数对于重复请求将产生相同的结果。',
'playground.params.stop.tips':
'停止序列是一个预定义或用户指定的文本字符串,当这些序列出现时,它会提示 AI 停止生成后续的标记。'
};
@@ -70,7 +70,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
<RowChildren key={`${item.id}_row`}>
<Row style={{ width: '100%' }} align="middle">
<Col span={4}>{item.name}</Col>
<Col span={3}>{getWorkerIp(item)}</Col>
<Col span={3}>{item.worker_name || '-'}</Col>
<Col span={4}>
<span>
{item.source === 'huggingface'
+1
View File
@@ -37,6 +37,7 @@ export interface ModelInstanceListItem {
download_progress: number;
model_id: number;
model_name: string;
worker_name: string;
id: number;
created_at: string;
updated_at: string;
+1 -1
View File
@@ -60,7 +60,7 @@ const renderWelCome = (intl: any) => {
const LoginForm = () => {
const [userInfo, setUserInfo] = useAtom(userAtom);
const [initialPassword, setInitialPassword] = useAtom(initialPasswordAtom);
const { initialState, setInitialState } = useModel('@@initialState');
const { initialState, setInitialState } = useModel('@@initialState') || {};
const intl = useIntl();
const [form] = Form.useForm();
@@ -8,7 +8,7 @@ import {
PlusOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Col, Dropdown, Row, Space } from 'antd';
import { Button, Col, Row, Space } from 'antd';
import { useHotkeys } from 'react-hotkeys-hook';
import { Roles } from '../config';
import '../style/chat-footer.less';
@@ -22,6 +22,7 @@ interface ChatFooterProps {
disabled?: boolean;
feedback?: React.ReactNode;
hasTokenResult?: boolean;
selectedModel?: string;
}
const ChatFooter: React.FC<ChatFooterProps> = (props) => {
@@ -35,7 +36,8 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
onView,
feedback,
disabled,
hasTokenResult
hasTokenResult,
selectedModel
} = props;
useHotkeys(
HotKeys.SUBMIT.join(','),
@@ -58,15 +60,25 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
<Row style={{ width: '100%' }}>
<Col span={hasTokenResult ? 8 : 12}>
<Space size={20}>
<Dropdown
{/* <Dropdown
menu={{ items: MessageRoles, onClick: onNewMessage }}
placement="topLeft"
>
<Button disabled={disabled} icon={<PlusOutlined />}>
<Button
disabled={disabled}
icon={<PlusOutlined />}
onClick={onNewMessage}
>
{intl.formatMessage({ id: 'playground.newMessage' })}
</Button>
</Dropdown>
</Dropdown> */}
<Button
disabled={disabled}
icon={<PlusOutlined />}
onClick={onNewMessage}
>
{intl.formatMessage({ id: 'playground.newMessage' })}
</Button>
<Button
icon={<DeleteOutlined></DeleteOutlined>}
onClick={onClear}
@@ -87,7 +99,11 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
{!disabled ? (
<Button type="primary" disabled={disabled} onClick={onSubmit}>
<Button
type="primary"
disabled={disabled || !selectedModel}
onClick={onSubmit}
>
{intl.formatMessage({ id: 'common.button.submit' })}
<span className="m-l-5 opct-7">
{platform.isMac ? (
@@ -56,11 +56,10 @@ const MessageList: React.FC<MessageProps> = (props) => {
const setMessageId = () => {
messageId.current = messageId.current + 1;
};
const handleNewMessage = (role: any) => {
const handleNewMessage = (role?: any) => {
messageList.push({
// role:
// _.last(messageList)?.role === Roles.User ? Roles.Assistant : Roles.User,
role: role.key,
role:
_.last(messageList)?.role === Roles.User ? Roles.Assistant : Roles.User,
content: '',
uid: messageId.current + 1
});
@@ -142,11 +141,14 @@ const MessageList: React.FC<MessageProps> = (props) => {
if (!messageList.length) {
return;
}
const headItem = _.cloneDeep(_.get(messageList, '0'));
headItem.content = '';
headItem.role = Roles.User;
headItem.uid = messageId.current + 1;
setMessageList(headItem ? [headItem] : []);
setMessageId();
setMessageList([
{
role: Roles.User,
content: '',
uid: messageId.current
}
]);
};
const handleView = () => {
@@ -261,6 +263,7 @@ const MessageList: React.FC<MessageProps> = (props) => {
onView={handleView}
onStop={handleStopConversation}
disabled={loading}
selectedModel={parameters.model}
hasTokenResult={!!tokenResult}
feedback={<ReferenceParams usage={tokenResult}></ReferenceParams>}
></ChatFooter>
@@ -2,8 +2,9 @@ import FieldWrapper from '@/components/seal-form/field-wrapper';
import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { INPUT_WIDTH } from '@/constants';
import { InfoCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Form, InputNumber, Slider } from 'antd';
import { Form, InputNumber, Slider, Tooltip } from 'antd';
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { queryModelsList } from '../apis';
@@ -100,13 +101,27 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
form.setFieldsValue(initialValues);
setParams(initialValues);
};
const renderLabel = (args: { field: string; label: string }) => {
const renderLabel = (args: {
field: string;
label: string;
description: string;
}) => {
return (
<span
className={CustomLabelStyles.label}
style={{ width: INPUT_WIDTH.mini }}
>
<span className="text">{args.label}</span>
<span className="text">
<span> {args.label}</span>
{args.description && (
<span className="m-l-5">
<Tooltip title={args.description}>
<InfoCircleOutlined />
</Tooltip>
</span>
)}
</span>
<InputNumber
className="label-val"
variant="outlined"
@@ -150,7 +165,10 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
<FieldWrapper
label={renderLabel({
field: 'temperature',
label: 'Temperature'
label: 'Temperature',
description: intl.formatMessage({
id: 'playground.params.temperature.tips'
})
})}
style={{ paddingInline: 0 }}
variant="borderless"
@@ -173,7 +191,10 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
<FieldWrapper
label={renderLabel({
field: 'max_tokens',
label: 'Max Tokens'
label: 'Max Tokens',
description: intl.formatMessage({
id: 'playground.params.maxtokens.tips'
})
})}
style={{ paddingInline: 0 }}
variant="borderless"
@@ -196,7 +217,10 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
<FieldWrapper
label={renderLabel({
field: 'top_p',
label: 'Top P'
label: 'Top P',
description: intl.formatMessage({
id: 'playground.params.topp.tips'
})
})}
style={{ paddingInline: 0 }}
variant="borderless"
@@ -219,7 +243,10 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
<FieldWrapper
label={renderLabel({
field: 'seed',
label: 'Seed'
label: 'Seed',
description: intl.formatMessage({
id: 'playground.params.seed.tips'
})
})}
style={{ paddingInline: 0 }}
variant="borderless"
@@ -240,6 +267,9 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
>
<SealInput.Input
label="Stop Sequence"
description={intl.formatMessage({
id: 'playground.params.stop.tips'
})}
style={{ width: INPUT_WIDTH.mini }}
></SealInput.Input>
</Form.Item>
-27
View File
@@ -1,27 +0,0 @@
import { Modal } from 'antd';
import React, { PropsWithChildren } from 'react';
interface CreateFormProps {
modalVisible: boolean;
onCancel: () => void;
}
const CreateForm: React.FC<PropsWithChildren<CreateFormProps>> = (props) => {
const { modalVisible, onCancel } = props;
return (
<Modal
destroyOnClose
title="新建"
width={420}
centered={true}
open={modalVisible}
onCancel={() => onCancel()}
footer={null}
>
{props.children}
</Modal>
);
};
export default CreateForm;
-138
View File
@@ -1,138 +0,0 @@
import {
ProFormDateTimePicker,
ProFormRadio,
ProFormSelect,
ProFormText,
ProFormTextArea,
StepsForm
} from '@ant-design/pro-components';
import { Modal } from 'antd';
import React from 'react';
export interface FormValueType extends Partial<API.UserInfo> {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
}
export interface UpdateFormProps {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => Promise<void>;
updateModalVisible: boolean;
values: Partial<API.UserInfo>;
}
const UpdateForm: React.FC<UpdateFormProps> = (props) => (
<StepsForm
stepsProps={{
size: 'small'
}}
stepsFormRender={(dom, submitter) => {
return (
<Modal
width={640}
bodyStyle={{ padding: '32px 40px 48px' }}
destroyOnClose
title="规则配置"
open={props.updateModalVisible}
footer={submitter}
onCancel={() => props.onCancel()}
>
{dom}
</Modal>
);
}}
onFinish={props.onSubmit}
>
<StepsForm.StepForm
initialValues={{
name: props.values.name,
nickName: props.values.nickName
}}
title="基本信息"
>
<ProFormText
width="md"
name="name"
label="规则名称"
rules={[{ required: true, message: '请输入规则名称!' }]}
/>
<ProFormTextArea
name="desc"
width="md"
label="规则描述"
placeholder="请输入至少五个字符"
rules={[
{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
target: '0',
template: '0'
}}
title="配置规则属性"
>
<ProFormSelect
width="md"
name="target"
label="监控对象"
valueEnum={{
0: '表一',
1: '表二'
}}
/>
<ProFormSelect
width="md"
name="template"
label="规则模板"
valueEnum={{
0: '规则模板一',
1: '规则模板二'
}}
/>
<ProFormRadio.Group
name="type"
width="md"
label="规则类型"
options={[
{
value: '0',
label: '强'
},
{
value: '1',
label: '弱'
}
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
type: '1',
frequency: 'month'
}}
title="设定调度周期"
>
<ProFormDateTimePicker
name="time"
label="开始时间"
rules={[{ required: true, message: '请选择开始时间!' }]}
/>
<ProFormSelect
name="frequency"
label="监控对象"
width="xs"
valueEnum={{
month: '月',
week: '周'
}}
/>
</StepsForm.StepForm>
</StepsForm>
);
export default UpdateForm;
-270
View File
@@ -1,270 +0,0 @@
import services from '@/services/demo';
import {
ActionType,
FooterToolbar,
PageContainer,
ProDescriptions,
ProDescriptionsItemProps,
ProTable
} from '@ant-design/pro-components';
import { Button, Divider, Drawer, message } from 'antd';
import React, { useRef, useState } from 'react';
import CreateForm from './components/CreateForm';
import UpdateForm, { FormValueType } from './components/UpdateForm';
const { addUser, queryUserList, deleteUser, modifyUser } =
services.UserController;
/**
* 添加节点
* @param fields
*/
const handleAdd = async (fields: API.UserInfo) => {
const hide = message.loading('正在添加');
try {
await addUser({ ...fields });
hide();
message.success('添加成功');
return true;
} catch (error) {
hide();
message.error('添加失败请重试!');
return false;
}
};
/**
* 更新节点
* @param fields
*/
const handleUpdate = async (fields: FormValueType) => {
const hide = message.loading('正在配置');
try {
await modifyUser(
{
userId: fields.id || ''
},
{
name: fields.name || '',
nickName: fields.nickName || '',
email: fields.email || ''
}
);
hide();
message.success('配置成功');
return true;
} catch (error) {
hide();
message.error('配置失败请重试!');
return false;
}
};
/**
* 删除节点
* @param selectedRows
*/
const handleRemove = async (selectedRows: API.UserInfo[]) => {
const hide = message.loading('正在删除');
if (!selectedRows) return true;
try {
await deleteUser({
userId: selectedRows.find((row) => row.id)?.id || ''
});
hide();
message.success('删除成功,即将刷新');
return true;
} catch (error) {
hide();
message.error('删除失败,请重试');
return false;
}
};
const TableList: React.FC<unknown> = () => {
const [createModalVisible, handleModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] =
useState<boolean>(false);
const [stepFormValues, setStepFormValues] = useState({});
const actionRef = useRef<ActionType>();
const [row, setRow] = useState<API.UserInfo>();
const [selectedRowsState, setSelectedRows] = useState<API.UserInfo[]>([]);
const columns: ProDescriptionsItemProps<API.UserInfo>[] = [
{
title: '名称',
dataIndex: 'name',
tip: '名称是唯一的 key',
formItemProps: {
rules: [
{
required: true,
message: '名称为必填项'
}
]
}
},
{
title: '昵称',
dataIndex: 'nickName',
valueType: 'text'
},
{
title: '性别',
dataIndex: 'gender',
hideInForm: true,
valueEnum: {
0: { text: '男', status: 'MALE' },
1: { text: '女', status: 'FEMALE' }
}
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<a
onClick={() => {
handleUpdateModalVisible(true);
setStepFormValues(record);
}}
>
</a>
<Divider type="vertical" />
<a href=""></a>
</>
)
}
];
return (
<PageContainer
header={{
title: 'CRUD 示例'
}}
>
<ProTable<API.UserInfo>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
search={{
labelWidth: 120
}}
toolBarRender={() => [
<Button
key="1"
type="primary"
onClick={() => handleModalVisible(true)}
>
</Button>
]}
request={async (params, sorter, filter) => {
const { data, success } = await queryUserList({
...params,
// FIXME: remove @ts-ignore
// @ts-ignore
sorter,
filter
});
return {
data: data?.list || [],
success
};
}}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows)
}}
/>
{selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
{' '}
<a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
&nbsp;&nbsp;
</div>
}
>
<Button
onClick={async () => {
await handleRemove(selectedRowsState);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}}
>
</Button>
<Button type="primary"></Button>
</FooterToolbar>
)}
<CreateForm
onCancel={() => handleModalVisible(false)}
modalVisible={createModalVisible}
>
<ProTable<API.UserInfo, API.UserInfo>
onSubmit={async (value) => {
const success = await handleAdd(value);
if (success) {
handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
rowKey="id"
type="form"
columns={columns}
/>
</CreateForm>
{stepFormValues && Object.keys(stepFormValues).length ? (
<UpdateForm
onSubmit={async (value) => {
const success = await handleUpdate(value);
if (success) {
handleUpdateModalVisible(false);
setStepFormValues({});
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
onCancel={() => {
handleUpdateModalVisible(false);
setStepFormValues({});
}}
updateModalVisible={updateModalVisible}
values={stepFormValues}
/>
) : null}
<Drawer
width={600}
open={!!row}
onClose={() => {
setRow(undefined);
}}
closable={false}
>
{row?.name && (
<ProDescriptions<API.UserInfo>
column={2}
title={row?.name}
request={async () => ({
data: row || {}
})}
params={{
id: row?.name
}}
columns={columns}
/>
)}
</Drawer>
</PageContainer>
);
};
export default TableList;
+5
View File
@@ -290,6 +290,11 @@ const Users: React.FC = () => {
);
}}
/>
<Column
title={intl.formatMessage({ id: 'users.form.fullname' })}
dataIndex="full_name"
key="full_name"
/>
<Column
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
-96
View File
@@ -1,96 +0,0 @@
/* eslint-disable */
// 该文件由 OneAPI 自动生成,请勿手动修改!
import { request } from '@umijs/max';
/** 此处后端没有提供注释 GET /api/v1/queryUserList */
export async function queryUserList(
params: {
// query
/** keyword */
keyword?: string;
/** current */
current?: number;
/** pageSize */
pageSize?: number;
},
options?: { [key: string]: any },
) {
return request<API.Result_PageInfo_UserInfo__>('/api/v1/queryUserList', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /api/v1/user */
export async function addUser(
body?: API.UserInfoVO,
options?: { [key: string]: any },
) {
return request<API.Result_UserInfo_>('/api/v1/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/v1/user/${param0} */
export async function getUserDetail(
params: {
// path
/** userId */
userId?: string;
},
options?: { [key: string]: any },
) {
const { userId: param0 } = params;
return request<API.Result_UserInfo_>(`/api/v1/user/${param0}`, {
method: 'GET',
params: { ...params },
...(options || {}),
});
}
/** 此处后端没有提供注释 PUT /api/v1/user/${param0} */
export async function modifyUser(
params: {
// path
/** userId */
userId?: string;
},
body?: API.UserInfoVO,
options?: { [key: string]: any },
) {
const { userId: param0 } = params;
return request<API.Result_UserInfo_>(`/api/v1/user/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...params },
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 DELETE /api/v1/user/${param0} */
export async function deleteUser(
params: {
// path
/** userId */
userId?: string;
},
options?: { [key: string]: any },
) {
const { userId: param0 } = params;
return request<API.Result_string_>(`/api/v1/user/${param0}`, {
method: 'DELETE',
params: { ...params },
...(options || {}),
});
}
-7
View File
@@ -1,7 +0,0 @@
/* eslint-disable */
// 该文件由 OneAPI 自动生成,请勿手动修改!
import * as UserController from './UserController';
export default {
UserController,
};
-68
View File
@@ -1,68 +0,0 @@
/* eslint-disable */
// 该文件由 OneAPI 自动生成,请勿手动修改!
declare namespace API {
interface PageInfo {
/**
1 */
current?: number;
pageSize?: number;
total?: number;
list?: Array<Record<string, any>>;
}
interface PageInfo_UserInfo_ {
/**
1 */
current?: number;
pageSize?: number;
total?: number;
list?: Array<UserInfo>;
}
interface Result {
success?: boolean;
errorMessage?: string;
data?: Record<string, any>;
}
interface Result_PageInfo_UserInfo__ {
success?: boolean;
errorMessage?: string;
data?: PageInfo_UserInfo_;
}
interface Result_UserInfo_ {
success?: boolean;
errorMessage?: string;
data?: UserInfo;
}
interface Result_string_ {
success?: boolean;
errorMessage?: string;
data?: string;
}
type UserGenderEnum = 'MALE' | 'FEMALE';
interface UserInfo {
id?: string;
name?: string;
/** nick */
nickName?: string;
/** email */
email?: string;
gender?: UserGenderEnum;
}
interface UserInfoVO {
name?: string;
/** nick */
nickName?: string;
/** email */
email?: string;
}
type definitions_0 = null;
}