Browse Source

诗歌列表初步

master
nili 3 years ago
parent
commit
9354c22eb9
  1. 24
      config/config.ts
  2. 2
      config/proxy.ts
  3. 54
      config/routes.ts
  4. 1
      package.json
  5. 28
      src/app.tsx
  6. 28
      src/components/AuthorSelect/index.tsx
  7. 66
      src/components/DebunceSelect/index.tsx
  8. 9
      src/components/Footer/index.tsx
  9. 14
      src/components/RightContent/index.tsx
  10. 36
      src/global.tsx
  11. 28
      src/pages/Admin.tsx
  12. 56
      src/pages/PoemDetail/index.tsx
  13. 6
      src/pages/PoemPage/index.less
  14. 138
      src/pages/PoemPage/index.tsx
  15. 89
      src/pages/TableList/components/UpdateForm.tsx
  16. 148
      src/pages/TableList/index.tsx
  17. 16
      src/pages/Welcome.tsx
  18. 140
      src/pages/user/Login/index.tsx
  19. 68
      src/services/ant-design-pro/api.ts
  20. 2
      src/services/ant-design-pro/index.ts
  21. 29
      src/services/ant-design-pro/login.ts
  22. 42
      src/services/ant-design-pro/rule.ts
  23. 15
      src/services/ant-design-pro/typings.d.ts
  24. 18
      src/services/luigi/author.ts
  25. 12
      src/services/luigi/index.ts
  26. 30
      src/services/luigi/poem.ts
  27. 88
      src/services/luigi/typings.d.ts
  28. 11
      src/services/luigi/user.ts

24
config/config.ts

@ -1,13 +1,10 @@
// https://umijs.org/config/
import { defineConfig } from 'umi';
import { join } from 'path';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import routes from './routes';
const { REACT_APP_ENV } = process.env;
export default defineConfig({
hash: true,
antd: {},
@ -16,18 +13,10 @@ export default defineConfig({
},
layout: {
// https://umijs.org/zh-CN/plugins/plugin-layout
locale: true,
locale: false,
siderWidth: 208,
...defaultSettings,
},
// https://umijs.org/zh-CN/plugins/plugin-locale
locale: {
// default zh-CN
default: 'zh-CN',
antd: true,
// default true, when it is true, will use `navigator.language` overwrite default
baseNavigator: true,
},
dynamicImport: {
loading: '@ant-design/pro-layout/es/PageLoading',
},
@ -64,11 +53,16 @@ export default defineConfig({
},
{
requestLibPath: "import { request } from 'umi'",
schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
projectName: 'swagger',
// 或者使用在线的版本
schemaPath: 'http://localhost:8001/api/luigi/swagger/v3/api-docs',
// schemaPath: join(__dirname, 'swaggerApi.json'),
mock: false,
projectName: 'luigi',
},
],
nodeModulesTransform: { type: 'none' },
nodeModulesTransform: {
type: 'none',
},
mfsu: {},
webpack5: {},
exportStatic: {},

2
config/proxy.ts

@ -11,7 +11,7 @@ export default {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
// 要代理的地址
target: 'https://preview.pro.ant.design',
target: 'http://localhost:8001',
// 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie
changeOrigin: true,

54
config/routes.ts

@ -1,58 +1,26 @@
export default [
export default [
{
path: '/user',
layout: false,
routes: [
{
path: '/user',
routes: [
{
name: 'login',
path: '/user/login',
component: './user/Login',
},
],
},
{
component: './404',
},
{ path: '/user', routes: [{ name: '登录', path: '/user/login', component: './user/Login' }] },
{ component: './404' },
],
},
{
path: '/welcome',
name: 'welcome',
icon: 'smile',
component: './Welcome',
},
{ path: '/welcome', name: '欢迎', icon: 'smile', component: './Welcome' },
{
path: '/admin',
name: 'admin',
name: '管理页',
icon: 'crown',
access: 'canAdmin',
component: './Admin',
routes: [
{
path: '/admin/sub-page',
name: 'sub-page',
icon: 'smile',
component: './Welcome',
},
{
component: './404',
},
{ path: '/admin/sub-page', name: '二级管理页', icon: 'smile', component: './Welcome' },
{ component: './404' },
],
},
{
name: 'list.table-list',
icon: 'table',
path: '/list',
component: './TableList',
},
{
path: '/',
redirect: '/welcome',
},
{
component: './404',
},
{ name: '查询表格', icon: 'table', path: '/list', component: './TableList' },
{ path: '/', redirect: '/welcome' },
{ icon: 'smile', path: '/poem', component: './PoemPage' },
{ component: './404' },
];

1
package.json

@ -85,6 +85,7 @@
"@umijs/preset-ant-design-pro": "^1.3.0",
"@umijs/preset-dumi": "^1.1.0",
"@umijs/preset-react": "^1.8.17",
"@umijs/preset-ui": "^2.2.9",
"@umijs/yorkie": "^2.0.5",
"cross-env": "^7.0.0",
"cross-port-killer": "^1.3.0",

28
src/app.tsx

@ -1,14 +1,14 @@
import type { Settings as LayoutSettings } from '@ant-design/pro-layout';
import { SettingDrawer } from '@ant-design/pro-layout';
import { PageLoading } from '@ant-design/pro-layout';
import type { RunTimeLayoutConfig } from 'umi';
import { history, Link } from 'umi';
import RightContent from '@/components/RightContent';
import Footer from '@/components/Footer';
import { currentUser as queryCurrentUser } from './services/ant-design-pro/api';
import RightContent from '@/components/RightContent';
import { BookOutlined, LinkOutlined } from '@ant-design/icons';
import { PageLoading, SettingDrawer } from '@ant-design/pro-layout';
import { history, Link, RequestConfig } from 'umi';
import defaultSettings from '../config/defaultSettings';
import { getCurrentUsingGET } from './services/luigi/user';
import type { Settings as LayoutSettings } from '@ant-design/pro-layout';
import type { RunTimeLayoutConfig } from 'umi';
const isDev = process.env.NODE_ENV === 'development';
const loginPath = '/user/login';
@ -28,7 +28,7 @@ export async function getInitialState(): Promise<{
}> {
const fetchUserInfo = async () => {
try {
const msg = await queryCurrentUser();
const msg = await getCurrentUsingGET();
return msg.data;
} catch (error) {
history.push(loginPath);
@ -106,3 +106,15 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
...initialState?.settings,
};
};
export const request: RequestConfig = {
errorConfig: {
adaptor: (resData) => {
return {
...resData,
success: resData.code == 1,
errorMessage: resData.message,
};
},
},
};

28
src/components/AuthorSelect/index.tsx

@ -0,0 +1,28 @@
import { seekUsingGET } from '@/services/luigi/author';
import React from 'react';
import DebounceSelect from '../DebunceSelect';
const AuthorSelect: React.FC<{
value?: string;
onChange?: (value: string) => void;
}> = (props) => {
return (
<DebounceSelect
initOption={props.value}
fetchOptions={seekUsingGET}
onChange={(newValue) => {
if (typeof newValue == 'string') {
props.onChange(JSON.parse(newValue));
} else {
props.onChange(newValue);
}
}}
style={{
width: '100%',
}}
/>
);
};
export default AuthorSelect;

66
src/components/DebunceSelect/index.tsx

@ -0,0 +1,66 @@
import { Select, Spin } from 'antd';
import { SelectProps } from 'antd/es/select';
import debounce from 'lodash/debounce';
import React from 'react';
import { useEffect } from '../../.umi/.cache/.mfsu/mf-dep_vendors-node_modules_react_index_js.598bdd42.async';
export interface DebounceSelectProps<ValueType = any>
extends Omit<SelectProps<ValueType>, 'options' | 'children'> {
fetchOptions: (search: string) => Promise<ValueType[]>;
debounceTimeout?: number;
initOption?: string;
}
function DebounceSelect<
ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any,
>({ fetchOptions, debounceTimeout = 800, initOption, ...props }: DebounceSelectProps) {
const [fetching, setFetching] = React.useState(false);
const initOptions = [];
let defaultValue = null;
if (initOption && typeof initOption == 'string') {
const option = JSON.parse(initOption);
initOptions.push(option);
defaultValue = option.value;
}
const [options, setOptions] = React.useState<ValueType[]>(initOptions);
const fetchRef = React.useRef(0);
const debounceFetcher = React.useMemo(() => {
const loadOptions = (value: string | number) => {
fetchRef.current += 1;
const fetchId = fetchRef.current;
setOptions([]);
setFetching(true);
fetchOptions({ query: value }).then((newOptions) => {
if (fetchId !== fetchRef.current) {
// for fetch callback order
return;
}
const list = newOptions.data.list.map((user: { id: number; name: string }) => ({
label: user.name,
value: user.id,
}));
setOptions(list);
setFetching(false);
});
};
return debounce(loadOptions, debounceTimeout);
}, [fetchOptions, debounceTimeout]);
return (
<Select<ValueType>
showSearch
labelInValue
filterOption={false}
defaultValue={defaultValue}
onSearch={debounceFetcher}
notFoundContent={fetching ? <Spin size="small" /> : null}
{...props}
options={options}
/>
);
}
export default DebounceSelect;

9
src/components/Footer/index.tsx

@ -1,16 +1,9 @@
import { useIntl } from 'umi';
import { GithubOutlined } from '@ant-design/icons';
import { DefaultFooter } from '@ant-design/pro-layout';
const Footer: React.FC = () => {
const intl = useIntl();
const defaultMessage = intl.formatMessage({
id: 'app.copyright.produced',
defaultMessage: '蚂蚁集团体验技术部出品',
});
const defaultMessage = '蚂蚁集团体验技术部出品';
const currentYear = new Date().getFullYear();
return (
<DefaultFooter
copyright={`${currentYear} ${defaultMessage}`}

14
src/components/RightContent/index.tsx

@ -1,11 +1,10 @@
import { Space } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import React from 'react';
import { useModel, SelectLang } from 'umi';
import { useModel } from 'umi';
import Avatar from './AvatarDropdown';
import HeaderSearch from '../HeaderSearch';
import styles from './index.less';
export type SiderTheme = 'light' | 'dark';
const GlobalHeaderRight: React.FC = () => {
@ -21,6 +20,7 @@ const GlobalHeaderRight: React.FC = () => {
if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
className = `${styles.right} ${styles.dark}`;
}
return (
<Space className={className}>
<HeaderSearch
@ -28,7 +28,10 @@ const GlobalHeaderRight: React.FC = () => {
placeholder="站内搜索"
defaultValue="umi ui"
options={[
{ label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
{
label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>,
value: 'umi ui',
},
{
label: <a href="next.ant.design">Ant Design</a>,
value: 'Ant Design',
@ -41,8 +44,7 @@ const GlobalHeaderRight: React.FC = () => {
label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
value: 'Pro Layout',
},
]}
// onSearch={value => {
]} // onSearch={value => {
// console.log('input', value);
// }}
/>
@ -55,8 +57,8 @@ const GlobalHeaderRight: React.FC = () => {
<QuestionCircleOutlined />
</span>
<Avatar />
<SelectLang className={styles.action} />
</Space>
);
};
export default GlobalHeaderRight;

36
src/global.tsx

@ -1,7 +1,5 @@
import { Button, message, notification } from 'antd';
import { useIntl } from 'umi';
import defaultSettings from '../config/defaultSettings';
const { pwa } = defaultSettings;
const isHttps = document.location.protocol === 'https:';
@ -17,28 +15,29 @@ const clearCache = () => {
})
.catch((e) => console.log(e));
}
};
}; // if pwa is true
// if pwa is true
if (pwa) {
// Notify user if offline now
window.addEventListener('sw.offline', () => {
message.warning(useIntl().formatMessage({ id: 'app.pwa.offline' }));
});
message.warning('当前处于离线状态');
}); // Pop up a prompt on the page asking the user if they want to use the latest version
// Pop up a prompt on the page asking the user if they want to use the latest version
window.addEventListener('sw.updated', (event: Event) => {
const e = event as CustomEvent;
const reloadSW = async () => {
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
const worker = e.detail && e.detail.waiting;
if (!worker) {
return true;
}
// Send skip-waiting event to waiting SW with MessageChannel
} // Send skip-waiting event to waiting SW with MessageChannel
await new Promise((resolve, reject) => {
const channel = new MessageChannel();
channel.port1.onmessage = (msgEvent) => {
if (msgEvent.data.error) {
reject(msgEvent.data.error);
@ -46,13 +45,19 @@ if (pwa) {
resolve(msgEvent.data);
}
};
worker.postMessage({ type: 'skip-waiting' }, [channel.port2]);
});
worker.postMessage(
{
type: 'skip-waiting',
},
[channel.port2],
);
});
clearCache();
window.location.reload();
return true;
};
const key = `open${Date.now()}`;
const btn = (
<Button
@ -62,12 +67,12 @@ if (pwa) {
reloadSW();
}}
>
{useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
{'刷新'}
</Button>
);
notification.open({
message: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated' }),
description: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
message: '有新内容',
description: '请点击“刷新”按钮或者手动刷新页面',
btn,
key,
onClose: async () => null,
@ -76,6 +81,7 @@ if (pwa) {
} else if ('serviceWorker' in navigator && isHttps) {
// unregister service worker
const { serviceWorker } = navigator;
if (serviceWorker.getRegistrations) {
serviceWorker.getRegistrations().then((sws) => {
sws.forEach((sw) => {
@ -83,9 +89,9 @@ if (pwa) {
});
});
}
serviceWorker.getRegistration().then((sw) => {
if (sw) sw.unregister();
});
clearCache();
}

28
src/pages/Admin.tsx

@ -2,23 +2,13 @@ import React from 'react';
import { HeartTwoTone, SmileTwoTone } from '@ant-design/icons';
import { Card, Typography, Alert } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { useIntl } from 'umi';
const Admin: React.FC = () => {
const intl = useIntl();
return (
<PageHeaderWrapper
content={intl.formatMessage({
id: 'pages.admin.subPage.title',
defaultMessage: 'This page can only be viewed by admin',
})}
>
<PageHeaderWrapper content={' 这个页面只有 admin 权限才能查看'}>
<Card>
<Alert
message={intl.formatMessage({
id: 'pages.welcome.alertMessage',
defaultMessage: 'Faster and stronger heavy-duty components have been released.',
})}
message={'更快更强的重型组件,已经发布。'}
type="success"
showIcon
banner
@ -27,11 +17,21 @@ const Admin: React.FC = () => {
marginBottom: 48,
}}
/>
<Typography.Title level={2} style={{ textAlign: 'center' }}>
<Typography.Title
level={2}
style={{
textAlign: 'center',
}}
>
<SmileTwoTone /> Ant Design Pro <HeartTwoTone twoToneColor="#eb2f96" /> You
</Typography.Title>
</Card>
<p style={{ textAlign: 'center', marginTop: 24 }}>
<p
style={{
textAlign: 'center',
marginTop: 24,
}}
>
Want to add more pages? Please refer to{' '}
<a href="https://pro.ant.design/docs/block-cn" target="_blank" rel="noopener noreferrer">
use block

56
src/pages/PoemDetail/index.tsx

@ -0,0 +1,56 @@
import React from 'react';
import { Form, message } from 'antd';
import ProForm, {
ProFormDateRangePicker,
ProFormSelect,
ProFormDatePicker,
} from '@ant-design/pro-form';
import AuthorSelect from '@/components/AuthorSelect';
export default () => {
return (
<ProForm
onFinish={async () => {
message.success('提交成功');
}}
syncToUrl={(values, type) => {
if (type === 'get') {
// 为了配合 transform
// startTime 和 endTime 拼成 createTimeRanger
return {
...values,
createTimeRanger:
values.startTime || values.endTime ? [values.startTime, values.endTime] : undefined,
};
}
// expirationTime 不同步到 url
return {
...values,
expirationTime: undefined,
};
}}
initialValues={{
name: '蚂蚁设计有限公司',
useMode: 'chapter',
}}
autoFocusFirstInput
>
<ProFormSelect
options={[
{
value: 'chapter',
label: '盖章后生效',
},
]}
width="sm"
name="useMode"
label="合同约定生效方式"
/>
<Form.Item name="authorId">
{(form) => {
return <AuthorSelect />;
}}
</Form.Item>
</ProForm>
);
};

6
src/pages/PoemPage/index.less

@ -0,0 +1,6 @@
@import '~antd/es/style/themes/default.less';
.main {
width: 100%;
background: @component-background;
}

138
src/pages/PoemPage/index.tsx

@ -0,0 +1,138 @@
import AuthorSelect from '@/components/AuthorSelect';
import { poemListUsingPOST } from '@/services/luigi/poem';
import { PlusOutlined } from '@ant-design/icons';
import ProTable from '@ant-design/pro-table';
import { Button } from 'antd';
import React, { useRef, useState } from 'react';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
const columns: ProColumns<API.PoemBo>[] = [
{
dataIndex: 'index',
valueType: 'indexBorder',
width: 48,
},
{
title: '标题',
dataIndex: 'title',
ellipsis: true,
hideInSearch: true,
tip: '标题过长会自动收缩',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
},
{
title: '状态',
dataIndex: 'status',
valueType: 'select',
valueEnum: {
0: {
text: '未校准',
status: 'Error',
},
1: {
text: '已校准',
status: 'Success',
},
},
},
{
title: '作者',
dataIndex: 'authorName',
hideInSearch: true,
},
{
title: '作者',
dataIndex: 'author',
hideInTable: true,
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
renderFormItem: (item, { type, defaultRender, ...rest }, form) => {
return <AuthorSelect {...rest} />;
},
},
{
title: '首行',
dataIndex: 'line',
hideInSearch: true,
},
];
export default () => {
const actionRef = useRef<ActionType>();
return (
<ProTable<API.PoemBo>
columns={columns}
actionRef={actionRef}
cardBordered
request={async (params = {}, sort, filter) => {
const query: API.QueryParam[] = [];
if (params.author) {
let author = params.author;
if (typeof params.author == 'string') {
author = JSON.parse(params.author);
}
query.push({ key: 'authorId', val: author.value });
}
if (params.status) {
query.push({ key: 'status', val: params.status });
}
const response = await poemListUsingPOST({
current: params.current,
pageSize: params.pageSize,
query: query,
});
return { data: response.data?.list, total: response.data?.total };
}}
editable={{
type: 'multiple',
}}
columnsState={{
persistenceKey: 'pro-table-singe-demos',
persistenceType: 'localStorage',
onChange(value) {
console.log('value: ', value);
},
}}
rowKey="id"
search={{
labelWidth: 'auto',
}}
form={{
// 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
syncToUrl: (values, type) => {
if (type === 'get') {
return {
...values,
created_at: [values.startTime, values.endTime],
};
}
return values;
},
}}
pagination={{
pageSize: 5,
}}
dateFormatter="string"
headerTitle="高级表格"
toolBarRender={() => [
<Button key="button" icon={<PlusOutlined />} type="primary">
</Button>,
]}
/>
);
};

89
src/pages/TableList/components/UpdateForm.tsx

@ -8,8 +8,6 @@ import {
ProFormRadio,
ProFormDateTimePicker,
} from '@ant-design/pro-form';
import { useIntl, FormattedMessage } from 'umi';
export type FormValueType = {
target?: string;
template?: string;
@ -17,7 +15,6 @@ export type FormValueType = {
time?: string;
frequency?: string;
} & Partial<API.RuleListItem>;
export type UpdateFormProps = {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => Promise<void>;
@ -26,7 +23,6 @@ export type UpdateFormProps = {
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
return (
<StepsForm
stepsProps={{
@ -36,12 +32,11 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
return (
<Modal
width={640}
bodyStyle={{ padding: '32px 40px 48px' }}
bodyStyle={{
padding: '32px 40px 48px',
}}
destroyOnClose
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleConfig',
defaultMessage: '规则配置',
})}
title={'规则配置'}
visible={props.updateModalVisible}
footer={submitter}
onCancel={() => {
@ -59,50 +54,28 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
name: props.values.name,
desc: props.values.desc,
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.basicConfig',
defaultMessage: '基本信息',
})}
title={'基本信息'}
>
<ProFormText
name="name"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleName.nameLabel',
defaultMessage: '规则名称',
})}
label={'规则名称'}
width="md"
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameRules"
defaultMessage="请输入规则名称!"
/>
),
message: '请输入规则名称!',
},
]}
/>
<ProFormTextArea
name="desc"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descLabel',
defaultMessage: '规则描述',
})}
placeholder={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descPlaceholder',
defaultMessage: '请输入至少五个字符',
})}
label={'规则描述'}
placeholder={'请输入至少五个字符'}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleDesc.descRules"
defaultMessage="请输入至少五个字符的规则描述!"
/>
),
message: '请输入至少五个字符的规则描述!',
min: 5,
},
]}
@ -113,18 +86,12 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
target: '0',
template: '0',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.title',
defaultMessage: '配置规则属性',
})}
title={'配置规则属性'}
>
<ProFormSelect
name="target"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
label={'监控对象'}
valueEnum={{
0: '表一',
1: '表二',
@ -133,10 +100,7 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
<ProFormSelect
name="template"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.templateLabel',
defaultMessage: '规则模板',
})}
label={'规则模板'}
valueEnum={{
0: '规则模板一',
1: '规则模板二',
@ -144,10 +108,7 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
/>
<ProFormRadio.Group
name="type"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.typeLabel',
defaultMessage: '规则类型',
})}
label={'规则类型'}
options={[
{
value: '0',
@ -165,36 +126,22 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
type: '1',
frequency: 'month',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.title',
defaultMessage: '设定调度周期',
})}
title={'设定调度周期'}
>
<ProFormDateTimePicker
name="time"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.timeLabel',
defaultMessage: '开始时间',
})}
label={'开始时间'}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.schedulingPeriod.timeRules"
defaultMessage="请选择开始时间!"
/>
),
message: '请选择开始时间!',
},
]}
/>
<ProFormSelect
name="frequency"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
label={'监控对象'}
width="md"
valueEnum={{
month: '月',

148
src/pages/TableList/index.tsx

@ -1,7 +1,6 @@
import { PlusOutlined } from '@ant-design/icons';
import { Button, message, Input, Drawer } from 'antd';
import React, { useState, useRef } from 'react';
import { useIntl, FormattedMessage } from 'umi';
import { PageContainer, FooterToolbar } from '@ant-design/pro-layout';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
@ -11,14 +10,15 @@ import ProDescriptions from '@ant-design/pro-descriptions';
import type { FormValueType } from './components/UpdateForm';
import UpdateForm from './components/UpdateForm';
import { rule, addRule, updateRule, removeRule } from '@/services/ant-design-pro/api';
/**
* @en-US Add node
* @zh-CN
* @param fields
*/
const handleAdd = async (fields: API.RuleListItem) => {
const hide = message.loading('正在添加');
try {
await addRule({ ...fields });
hide();
@ -30,15 +30,16 @@ const handleAdd = async (fields: API.RuleListItem) => {
return false;
}
};
/**
* @en-US Update node
* @zh-CN
*
* @param fields
*/
const handleUpdate = async (fields: FormValueType) => {
const hide = message.loading('Configuring');
try {
await updateRule({
name: fields.name,
@ -46,7 +47,6 @@ const handleUpdate = async (fields: FormValueType) => {
key: fields.key,
});
hide();
message.success('Configuration is successful');
return true;
} catch (error) {
@ -55,16 +55,17 @@ const handleUpdate = async (fields: FormValueType) => {
return false;
}
};
/**
* Delete node
* @zh-CN
*
* @param selectedRows
*/
const handleRemove = async (selectedRows: API.RuleListItem[]) => {
const hide = message.loading('正在删除');
if (!selectedRows) return true;
try {
await removeRule({
key: selectedRows.map((row) => row.key),
@ -89,28 +90,20 @@ const TableList: React.FC = () => {
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [showDetail, setShowDetail] = useState<boolean>(false);
const actionRef = useRef<ActionType>();
const [currentRow, setCurrentRow] = useState<API.RuleListItem>();
const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
/**
* @en-US International configuration
* @zh-CN
* */
const intl = useIntl();
const columns: ProColumns<API.RuleListItem>[] = [
{
title: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameLabel"
defaultMessage="Rule name"
/>
),
title: '规则名称',
dataIndex: 'name',
tip: 'The rule name is the unique key',
render: (dom, entity) => {
@ -127,94 +120,61 @@ const TableList: React.FC = () => {
},
},
{
title: <FormattedMessage id="pages.searchTable.titleDesc" defaultMessage="Description" />,
title: '描述',
dataIndex: 'desc',
valueType: 'textarea',
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleCallNo"
defaultMessage="Number of service calls"
/>
),
title: '服务调用次数',
dataIndex: 'callNo',
sorter: true,
hideInForm: true,
renderText: (val: string) =>
`${val}${intl.formatMessage({
id: 'pages.searchTable.tenThousand',
defaultMessage: ' 万 ',
})}`,
renderText: (val: string) => `${val}${'万'}`,
},
{
title: <FormattedMessage id="pages.searchTable.titleStatus" defaultMessage="Status" />,
title: '状态',
dataIndex: 'status',
hideInForm: true,
valueEnum: {
0: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.default"
defaultMessage="Shut down"
/>
),
text: '关闭',
status: 'Default',
},
1: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.running" defaultMessage="Running" />
),
text: '运行中',
status: 'Processing',
},
2: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.online" defaultMessage="Online" />
),
text: '已上线',
status: 'Success',
},
3: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.abnormal"
defaultMessage="Abnormal"
/>
),
text: '异常',
status: 'Error',
},
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleUpdatedAt"
defaultMessage="Last scheduled time"
/>
),
title: '上次调度时间',
sorter: true,
dataIndex: 'updatedAt',
valueType: 'dateTime',
renderFormItem: (item, { defaultRender, ...rest }, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return (
<Input
{...rest}
placeholder={intl.formatMessage({
id: 'pages.searchTable.exception',
defaultMessage: 'Please enter the reason for the exception!',
})}
/>
);
return <Input {...rest} placeholder={'请输入异常原因!'} />;
}
return defaultRender(item);
},
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
@ -225,25 +185,18 @@ const TableList: React.FC = () => {
setCurrentRow(record);
}}
>
<FormattedMessage id="pages.searchTable.config" defaultMessage="Configuration" />
</a>,
<a key="subscribeAlert" href="https://procomponents.ant.design/">
<FormattedMessage
id="pages.searchTable.subscribeAlert"
defaultMessage="Subscribe to alerts"
/>
</a>,
],
},
];
return (
<PageContainer>
<ProTable<API.RuleListItem, API.PageParams>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
headerTitle={'查询表格'}
actionRef={actionRef}
rowKey="key"
search={{
@ -257,7 +210,7 @@ const TableList: React.FC = () => {
handleModalVisible(true);
}}
>
<PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
<PlusOutlined />
</Button>,
]}
request={rule}
@ -272,17 +225,17 @@ const TableList: React.FC = () => {
<FooterToolbar
extra={
<div>
<FormattedMessage id="pages.searchTable.chosen" defaultMessage="Chosen" />{' '}
<a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
<FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
&nbsp;&nbsp;
{' '}
<a
style={{
fontWeight: 600,
}}
>
{selectedRowsState.length}
</a>{' '}
&nbsp;&nbsp;
<span>
<FormattedMessage
id="pages.searchTable.totalServiceCalls"
defaultMessage="Total number of service calls"
/>{' '}
{selectedRowsState.reduce((pre, item) => pre + item.callNo!, 0)}{' '}
<FormattedMessage id="pages.searchTable.tenThousand" defaultMessage="万" />
{selectedRowsState.reduce((pre, item) => pre + item.callNo!, 0)}
</span>
</div>
}
@ -294,31 +247,22 @@ const TableList: React.FC = () => {
actionRef.current?.reloadAndRest?.();
}}
>
<FormattedMessage
id="pages.searchTable.batchDeletion"
defaultMessage="Batch deletion"
/>
</Button>
<Button type="primary">
<FormattedMessage
id="pages.searchTable.batchApproval"
defaultMessage="Batch approval"
/>
</Button>
<Button type="primary"></Button>
</FooterToolbar>
)}
<ModalForm
title={intl.formatMessage({
id: 'pages.searchTable.createForm.newRule',
defaultMessage: 'New rule',
})}
title={'新建规则'}
width="400px"
visible={createModalVisible}
onVisibleChange={handleModalVisible}
onFinish={async (value) => {
const success = await handleAdd(value as API.RuleListItem);
if (success) {
handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
@ -329,12 +273,7 @@ const TableList: React.FC = () => {
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.ruleName"
defaultMessage="Rule name is required"
/>
),
message: '规则名称为必填项',
},
]}
width="md"
@ -345,9 +284,11 @@ const TableList: React.FC = () => {
<UpdateForm
onSubmit={async (value) => {
const success = await handleUpdate(value);
if (success) {
handleUpdateModalVisible(false);
setCurrentRow(undefined);
if (actionRef.current) {
actionRef.current.reload();
}
@ -355,6 +296,7 @@ const TableList: React.FC = () => {
}}
onCancel={() => {
handleUpdateModalVisible(false);
if (!showDetail) {
setCurrentRow(undefined);
}

16
src/pages/Welcome.tsx

@ -1,7 +1,6 @@
import React from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Card, Alert, Typography } from 'antd';
import { useIntl, FormattedMessage } from 'umi';
import styles from './Welcome.less';
const CodePreview: React.FC = ({ children }) => (
@ -13,16 +12,11 @@ const CodePreview: React.FC = ({ children }) => (
);
const Welcome: React.FC = () => {
const intl = useIntl();
return (
<PageContainer>
<Card>
<Alert
message={intl.formatMessage({
id: 'pages.welcome.alertMessage',
defaultMessage: 'Faster and stronger heavy-duty components have been released.',
})}
message={'更快更强的重型组件,已经发布。'}
type="success"
showIcon
banner
@ -32,13 +26,13 @@ const Welcome: React.FC = () => {
}}
/>
<Typography.Text strong>
<FormattedMessage id="pages.welcome.advancedComponent" defaultMessage="Advanced Form" />{' '}
{' '}
<a
href="https://procomponents.ant.design/components/table"
rel="noopener noreferrer"
target="__blank"
>
<FormattedMessage id="pages.welcome.link" defaultMessage="Welcome" />
使
</a>
</Typography.Text>
<CodePreview>yarn add @ant-design/pro-table</CodePreview>
@ -48,13 +42,13 @@ const Welcome: React.FC = () => {
marginBottom: 12,
}}
>
<FormattedMessage id="pages.welcome.advancedLayout" defaultMessage="Advanced layout" />{' '}
{' '}
<a
href="https://procomponents.ant.design/components/layout"
rel="noopener noreferrer"
target="__blank"
>
<FormattedMessage id="pages.welcome.link" defaultMessage="Welcome" />
使
</a>
</Typography.Text>
<CodePreview>yarn add @ant-design/pro-layout</CodePreview>

140
src/pages/user/Login/index.tsx

@ -9,11 +9,10 @@ import {
import { Alert, message, Tabs } from 'antd';
import React, { useState } from 'react';
import { ProFormCaptcha, ProFormCheckbox, ProFormText, LoginForm } from '@ant-design/pro-form';
import { useIntl, history, FormattedMessage, SelectLang, useModel } from 'umi';
import { history, useModel } from 'umi';
import Footer from '@/components/Footer';
import { login } from '@/services/ant-design-pro/api';
import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import styles from './index.less';
const LoginMessage: React.FC<{
@ -34,15 +33,11 @@ const Login: React.FC = () => {
const [type, setType] = useState<string>('account');
const { initialState, setInitialState } = useModel('@@initialState');
const intl = useIntl();
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
if (userInfo) {
await setInitialState((s) => ({
...s,
currentUser: userInfo,
}));
await setInitialState((s) => ({ ...s, currentUser: userInfo }));
}
};
@ -50,52 +45,44 @@ const Login: React.FC = () => {
try {
// 登录
const msg = await login({ ...values, type });
if (msg.status === 'ok') {
const defaultLoginSuccessMessage = intl.formatMessage({
id: 'pages.login.success',
defaultMessage: '登录成功!',
});
const defaultLoginSuccessMessage = '登录成功!';
message.success(defaultLoginSuccessMessage);
await fetchUserInfo();
/** 此方法会跳转到 redirect 参数所在的位置 */
if (!history) return;
const { query } = history.location;
const { redirect } = query as { redirect: string };
const { redirect } = query as {
redirect: string;
};
history.push(redirect || '/');
return;
}
console.log(msg);
// 如果失败去设置用户错误信息
console.log(msg); // 如果失败去设置用户错误信息
setUserLoginState(msg);
} catch (error) {
const defaultLoginFailureMessage = intl.formatMessage({
id: 'pages.login.failure',
defaultMessage: '登录失败,请重试!',
});
const defaultLoginFailureMessage = '登录失败,请重试!';
message.error(defaultLoginFailureMessage);
}
};
const { status, type: loginType } = userLoginState;
const { status, type: loginType } = userLoginState;
return (
<div className={styles.container}>
<div className={styles.lang} data-lang>
{SelectLang && <SelectLang />}
</div>
<div className={styles.content}>
<LoginForm
logo={<img alt="logo" src="/logo.svg" />}
title="Ant Design"
subTitle={intl.formatMessage({ id: 'pages.layouts.userLayout.title' })}
subTitle={'Ant Design 是西湖区最具影响力的 Web 设计规范'}
initialValues={{
autoLogin: true,
}}
actions={[
<FormattedMessage
key="loginWith"
id="pages.login.loginWith"
defaultMessage="其他登录方式"
/>,
'其他登录方式 :',
<AlipayCircleOutlined key="AlipayCircleOutlined" className={styles.icon} />,
<TaobaoCircleOutlined key="TaobaoCircleOutlined" className={styles.icon} />,
<WeiboCircleOutlined key="WeiboCircleOutlined" className={styles.icon} />,
@ -105,29 +92,12 @@ const Login: React.FC = () => {
}}
>
<Tabs activeKey={type} onChange={setType}>
<Tabs.TabPane
key="account"
tab={intl.formatMessage({
id: 'pages.login.accountLogin.tab',
defaultMessage: '账户密码登录',
})}
/>
<Tabs.TabPane
key="mobile"
tab={intl.formatMessage({
id: 'pages.login.phoneLogin.tab',
defaultMessage: '手机号登录',
})}
/>
<Tabs.TabPane key="account" tab={'账户密码登录'} />
<Tabs.TabPane key="mobile" tab={'手机号登录'} />
</Tabs>
{status === 'error' && loginType === 'account' && (
<LoginMessage
content={intl.formatMessage({
id: 'pages.login.accountLogin.errorMessage',
defaultMessage: '账户或密码错误(admin/ant.design)',
})}
/>
<LoginMessage content={'错误的用户名和密码(admin/ant.design)'} />
)}
{type === 'account' && (
<>
@ -137,19 +107,11 @@ const Login: React.FC = () => {
size: 'large',
prefix: <UserOutlined className={styles.prefixIcon} />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.username.placeholder',
defaultMessage: '用户名: admin or user',
})}
placeholder={'用户名: admin or user'}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.username.required"
defaultMessage="请输入用户名!"
/>
),
message: '用户名是必填项!',
},
]}
/>
@ -159,19 +121,11 @@ const Login: React.FC = () => {
size: 'large',
prefix: <LockOutlined className={styles.prefixIcon} />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.password.placeholder',
defaultMessage: '密码: ant.design',
})}
placeholder={'密码: ant.design'}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.password.required"
defaultMessage="请输入密码!"
/>
),
message: '密码是必填项!',
},
]}
/>
@ -187,28 +141,15 @@ const Login: React.FC = () => {
prefix: <MobileOutlined className={styles.prefixIcon} />,
}}
name="mobile"
placeholder={intl.formatMessage({
id: 'pages.login.phoneNumber.placeholder',
defaultMessage: '手机号',
})}
placeholder={'请输入手机号!'}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.phoneNumber.required"
defaultMessage="请输入手机号!"
/>
),
message: '手机号是必填项!',
},
{
pattern: /^1\d{10}$/,
message: (
<FormattedMessage
id="pages.login.phoneNumber.invalid"
defaultMessage="手机号格式错误!"
/>
),
message: '不合法的手机号!',
},
]}
/>
@ -220,41 +161,30 @@ const Login: React.FC = () => {
captchaProps={{
size: 'large',
}}
placeholder={intl.formatMessage({
id: 'pages.login.captcha.placeholder',
defaultMessage: '请输入验证码',
})}
placeholder={'请输入验证码!'}
captchaTextRender={(timing, count) => {
if (timing) {
return `${count} ${intl.formatMessage({
id: 'pages.getCaptchaSecondText',
defaultMessage: '获取验证码',
})}`;
return `${count} ${'秒后重新获取'}`;
}
return intl.formatMessage({
id: 'pages.login.phoneLogin.getVerificationCode',
defaultMessage: '获取验证码',
});
return '获取验证码';
}}
name="captcha"
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.login.captcha.required"
defaultMessage="请输入验证码!"
/>
),
message: '验证码是必填项!',
},
]}
onGetCaptcha={async (phone) => {
const result = await getFakeCaptcha({
phone,
});
if (result === false) {
return;
}
message.success('获取验证码成功!验证码为:1234');
}}
/>
@ -266,14 +196,14 @@ const Login: React.FC = () => {
}}
>
<ProFormCheckbox noStyle name="autoLogin">
<FormattedMessage id="pages.login.rememberMe" defaultMessage="自动登录" />
</ProFormCheckbox>
<a
style={{
float: 'right',
}}
>
<FormattedMessage id="pages.login.forgotPassword" defaultMessage="忘记密码" />
?
</a>
</div>
</LoginForm>

68
src/services/ant-design-pro/api.ts

@ -4,34 +4,12 @@ import { request } from 'umi';
/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
}>('/api/currentUser', {
return request<API.CurrentUser>('/api/currentUser', {
method: 'GET',
...(options || {}),
});
}
/** 退出登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/login/account', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 此处后端没有提供注释 GET /api/notices */
export async function getNotices(options?: { [key: string]: any }) {
return request<API.NoticeIconList>('/api/notices', {
@ -39,47 +17,3 @@ export async function getNotices(options?: { [key: string]: any }) {
...(options || {}),
});
}
/** 获取规则列表 GET /api/rule */
export async function rule(
params: {
// query
/** 当前的页码 */
current?: number;
/** 页面的容量 */
pageSize?: number;
},
options?: { [key: string]: any },
) {
return request<API.RuleList>('/api/rule', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 新建规则 PUT /api/rule */
export async function updateRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'PUT',
...(options || {}),
});
}
/** 新建规则 POST /api/rule */
export async function addRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
...(options || {}),
});
}
/** 删除规则 DELETE /api/rule */
export async function removeRule(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/rule', {
method: 'DELETE',
...(options || {}),
});
}

2
src/services/ant-design-pro/index.ts

@ -4,7 +4,9 @@
// API 唯一标识:
import * as api from './api';
import * as login from './login';
import * as rule from './rule';
export default {
api,
login,
rule,
};

29
src/services/ant-design-pro/login.ts

@ -4,18 +4,35 @@ import { request } from 'umi';
/** 发送验证码 POST /api/login/captcha */
export async function getFakeCaptcha(
params: {
// query
/** 手机号 */
phone?: string;
},
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getFakeCaptchaParams,
options?: { [key: string]: any },
) {
return request<API.FakeCaptcha>('/api/login/captcha', {
method: 'GET',
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
/** 登录接口 POST /api/login/outLogin */
export async function outLogin(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/login/outLogin', {
method: 'POST',
...(options || {}),
});
}
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/login/account', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}

42
src/services/ant-design-pro/rule.ts

@ -0,0 +1,42 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** 获取规则列表 GET /api/rule */
export async function rule(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.ruleParams,
options?: { [key: string]: any },
) {
return request<API.RuleList>('/api/rule', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 新建规则 PUT /api/rule */
export async function updateRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'PUT',
...(options || {}),
});
}
/** 新建规则 POST /api/rule */
export async function addRule(options?: { [key: string]: any }) {
return request<API.RuleListItem>('/api/rule', {
method: 'POST',
...(options || {}),
});
}
/** 删除规则 DELETE /api/rule */
export async function removeRule(options?: { [key: string]: any }) {
return request<Record<string, any>>('/api/rule', {
method: 'DELETE',
...(options || {}),
});
}

15
src/services/ant-design-pro/typings.d.ts

@ -1,6 +1,3 @@
// @ts-ignore
/* eslint-disable */
declare namespace API {
type CurrentUser = {
name?: string;
@ -98,4 +95,16 @@ declare namespace API {
description?: string;
type?: NoticeIconItemType;
};
type getFakeCaptchaParams = {
/** 手机号 */
phone?: string;
};
type ruleParams = {
/** 当前的页码 */
current?: number;
/** 页面的容量 */
pageSize?: number;
};
}

18
src/services/luigi/author.ts

@ -0,0 +1,18 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** seek GET /api/luigi/author/seek */
export async function seekUsingGET(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.seekUsingGETParams,
options?: { [key: string]: any },
) {
return request<API.ResponseCommonListAuthor>('/api/luigi/author/seek', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}

12
src/services/luigi/index.ts

@ -0,0 +1,12 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as author from './author';
import * as poem from './poem';
import * as user from './user';
export default {
author,
poem,
user,
};

30
src/services/luigi/poem.ts

@ -0,0 +1,30 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** poemDetail GET /api/luigi/poem/detail */
export async function poemDetailUsingGET(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.poemDetailUsingGETParams,
options?: { [key: string]: any },
) {
return request<API.ResponsePoemBo>('/api/luigi/poem/detail', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** poemList POST /api/luigi/poem/list */
export async function poemListUsingPOST(body: API.PoemQuery, options?: { [key: string]: any }) {
return request<API.ResponseCommonListPoemBo>('/api/luigi/poem/list', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}

88
src/services/luigi/typings.d.ts

@ -0,0 +1,88 @@
declare namespace API {
type Author = {
dynasty?: string;
id?: number;
introduction?: string;
name?: string;
poemCnt?: number;
status?: number;
};
type CommonListAuthor = {
current?: number;
list?: Author[];
pageSize?: number;
total?: number;
};
type CommonListPoemBo = {
current?: number;
list?: PoemBo[];
pageSize?: number;
total?: number;
};
type PoemBo = {
authorId?: number;
authorName?: string;
content?: string;
id?: number;
line?: string;
note?: string;
status?: number;
title?: string;
translation?: string;
};
type PoemQuery = {
current?: number;
pageSize?: number;
query?: QueryParam[];
};
type QueryParam = {
key?: string;
val?: string;
};
type ResponseCommonListAuthor = {
code?: number;
data?: CommonListAuthor;
message?: string;
};
type ResponseCommonListPoemBo = {
code?: number;
data?: CommonListPoemBo;
message?: string;
};
type ResponsePoemBo = {
code?: number;
data?: PoemBo;
message?: string;
};
type ResponseUserBo = {
code?: number;
data?: UserBo;
message?: string;
};
type UserBo = {
avatar?: string;
id?: number;
name?: string;
role?: string;
};
type seekUsingGETParams = {
/** name */
name: string;
};
type poemDetailUsingGETParams = {
/** id */
id: number;
};
}

11
src/services/luigi/user.ts

@ -0,0 +1,11 @@
// @ts-ignore
/* eslint-disable */
import { request } from 'umi';
/** getCurrent GET /api/luigi/user/current */
export async function getCurrentUsingGET(options?: { [key: string]: any }) {
return request<API.ResponseUserBo>('/api/luigi/user/current', {
method: 'GET',
...(options || {}),
});
}
Loading…
Cancel
Save