Skip to content

Commit d916f65

Browse files
committed
feat: add create page
1 parent 00a56b5 commit d916f65

File tree

11 files changed

+166
-39
lines changed

11 files changed

+166
-39
lines changed

config/routes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const routes: IRoute[] = [
2727
name: 'API',
2828
component: '@/page/api',
2929
},
30+
{
31+
path: '/topic/create',
32+
exact: true,
33+
title: '新建话题',
34+
component: '@/page/topic/create',
35+
access: 'canPostTopic',
36+
},
3037
{
3138
path: '/topic/:id',
3239
exact: true,

src/access.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export default function (initialState: InitialState) {
22
const { token } = initialState;
33

44
return {
5+
canPostTopic: !!token,
56
canPostComment: !!token,
67
};
78
}

src/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const patchRoutes = ({ routes }: { routes: Array<IRoute> }) => {
7171
};
7272

7373
export const request: RequestConfig = {
74-
timeout: 1000,
74+
timeout: 6 * 1000,
7575
errorConfig: {},
7676
middlewares: [],
7777
requestInterceptors: [],

src/component/Markdown/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as styles from './index.less';
88
const mdParser = new MarkdownIt();
99

1010
const Markdown: React.FC<Props> = (props) => {
11-
const { value, type, onChange } = props;
11+
const { value = '', type, onChange, customClassName = '' } = props;
1212

1313
let view;
1414
let classname = styles.markdown;
@@ -33,6 +33,10 @@ const Markdown: React.FC<Props> = (props) => {
3333
classname += ` ${styles.markdown_editor}`;
3434
}
3535

36+
if (customClassName) {
37+
classname += ` ${customClassName}`;
38+
}
39+
3640
return (
3741
<MdEditor
3842
className={classname}
@@ -51,6 +55,7 @@ export default Markdown;
5155

5256
interface Props {
5357
type: 'editor' | 'render';
54-
value: string;
58+
value?: string;
59+
customClassName?: '';
5560
onChange?: (text: string) => void;
5661
}

src/constants/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@ export const BASE_URL = 'https://cnodejs.org';
33
export const TABS_MAP = {
44
good: {
55
name: '精华',
6-
color: '#5BD8A6',
6+
color: '#87d068',
77
},
88
share: {
99
name: '分享',
10-
color: '#5BD8A6',
10+
color: '#2db7f5',
1111
},
1212
ask: {
1313
name: '问答',
1414
color: '#5BD8A6',
1515
},
1616
job: {
1717
name: '招聘',
18-
color: '#5BD8A6',
18+
color: '#108ee9',
1919
},
2020
dev: {
2121
name: '客户端测试',
22-
color: '#5BD8A6',
22+
color: 'green',
2323
},
2424
};
2525

src/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ const layoutConfig = ({
9999
copyright={`${new Date().getFullYear()} - CNodejs.org`}
100100
/>
101101
),
102+
103+
onPageChange: () => {},
102104
};
103105
};
104106

src/layout/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import ProCard from '@ant-design/pro-card';
44
import { IRoute, Link } from 'umi';
55
import { PageContainer } from '@ant-design/pro-layout';
66
import { Affix, Button } from 'antd';
7+
import { UpCircleOutlined } from '@ant-design/icons';
78

89
import UserInfo from './component/UserInfo';
910

@@ -36,7 +37,9 @@ const Layout: React.FC<React.PropsWithChildren<Props>> = (props) => {
3637
title: currentRoute?.title || currentRoute?.name,
3738
};
3839

39-
if (location.pathname.startsWith('/topic/')) {
40+
const topicDetailRegx = /\/topic\/([a-f0-9]){24}/g;
41+
42+
if (location.pathname.match(topicDetailRegx)) {
4043
const topicBreadcrumbName = location.pathname.split('/').pop();
4144

4245
headerConfig = {
@@ -79,10 +82,9 @@ const Layout: React.FC<React.PropsWithChildren<Props>> = (props) => {
7982
</ProCard>
8083
</ProCard>
8184
<Affix
82-
offsetBottom={200}
85+
offsetBottom={50}
8386
style={{
8487
position: 'fixed',
85-
bottom: '50px',
8688
right: '24px',
8789
}}
8890
>
@@ -91,6 +93,7 @@ const Layout: React.FC<React.PropsWithChildren<Props>> = (props) => {
9193
window.scrollTo(0, 0);
9294
}}
9395
>
96+
<UpCircleOutlined />
9497
回到顶部
9598
</Button>
9699
</Affix>

src/page/topic/create/index.less

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.editor_create {
2+
min-height: 600px;
3+
}

src/page/topic/create/index.tsx

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React from 'react';
2+
import { useModel, useHistory } from 'umi';
3+
import { Form, Input, Select, Button, Space } from 'antd';
4+
import { TABS_MAP } from '@/constants';
5+
6+
import Markdown from '@/component/Markdown';
7+
8+
import * as API from '@/service/topic';
9+
import * as styles from './index.less';
10+
11+
const CreateTopic: React.FC<Props> = (props) => {
12+
const history = useHistory();
13+
const [form] = Form.useForm();
14+
const { initialState } = useModel('@@initialState');
15+
16+
const token = initialState?.token;
17+
18+
const onFinish = async (values: any) => {
19+
console.debug('===create.values', values);
20+
21+
if (!token) {
22+
return;
23+
}
24+
25+
await API.postTopic({
26+
...values,
27+
accesstoken: token,
28+
});
29+
30+
onReset();
31+
32+
history.push('/');
33+
};
34+
35+
const onReset = () => {
36+
form.resetFields();
37+
};
38+
39+
const tabs = Object.entries(TABS_MAP).map(([value, info]) => {
40+
return {
41+
label: info.name,
42+
value,
43+
};
44+
});
45+
46+
return (
47+
<div>
48+
<Form
49+
form={form}
50+
onFinish={onFinish}
51+
initialValues={{
52+
tab: tabs[1].value,
53+
}}
54+
>
55+
<Form.Item
56+
label="标题"
57+
name="title"
58+
rules={[{ required: true }, { min: 8 }]}
59+
>
60+
<Input allowClear />
61+
</Form.Item>
62+
<Form.Item label="分类" name="tab" required>
63+
<Select options={tabs} />
64+
</Form.Item>
65+
<Form.Item
66+
label="内容"
67+
name="content"
68+
rules={[{ required: true }, { min: 10 }]}
69+
>
70+
<Markdown type="editor" customClassName={styles.editor_create} />
71+
</Form.Item>
72+
<Form.Item
73+
style={{
74+
textAlign: 'right',
75+
}}
76+
>
77+
<Space>
78+
<Button htmlType="button" onClick={onReset}>
79+
重置
80+
</Button>
81+
<Button type="primary" htmlType="submit">
82+
提交
83+
</Button>
84+
</Space>
85+
</Form.Item>
86+
</Form>
87+
</div>
88+
);
89+
};
90+
91+
export default CreateTopic;
92+
93+
interface Props {}

src/page/topic/index.tsx

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, { useEffect } from 'react';
22
import dayjs from 'dayjs';
33

4-
import { useHistory } from 'umi';
4+
import { useHistory, useAccess } from 'umi';
55
import { Avatar, Tag, Space, Divider, Button } from 'antd';
66
import { useRequest, useReactive } from 'ahooks';
77
import { ProListMetas } from '@ant-design/pro-list';
88
import ProList from '@ant-design/pro-list';
9-
import { ReloadOutlined } from '@ant-design/icons';
9+
import { ReloadOutlined, EditOutlined } from '@ant-design/icons';
1010

1111
import { TABS_MAP } from '@/constants';
1212
import type { TabType } from '@/constants';
@@ -17,6 +17,7 @@ import * as styles from './index.less';
1717
interface Props {}
1818

1919
const TopicList: React.FC<Props> = (props) => {
20+
const access = useAccess();
2021
const history = useHistory();
2122

2223
const state = useReactive({
@@ -76,18 +77,12 @@ const TopicList: React.FC<Props> = (props) => {
7677
const offsetHeight = document.body.offsetHeight;
7778
const pageYOffset = window.pageYOffset;
7879

79-
console.debug('===pageYOffset', pageYOffset);
80-
console.debug('===offsetHeight', offsetHeight);
81-
console.debug('===scrollHeight', scrollHeight);
82-
83-
// if(pageYOffset) {
84-
// console.log('===onReachStart', hasNext, loading);
85-
// onReachStart();
86-
// return;
87-
// }
80+
// console.debug('===pageYOffset', pageYOffset);
81+
// console.debug('===offsetHeight', offsetHeight);
82+
// console.debug('===scrollHeight', scrollHeight);
8883

8984
if (pageYOffset + offsetHeight === scrollHeight) {
90-
console.log('===onReachEnd', hasNext, loading);
85+
// console.log('===onReachEnd', hasNext, loading);
9186
onReachEnd();
9287
}
9388
};
@@ -166,6 +161,26 @@ const TopicList: React.FC<Props> = (props) => {
166161
refresh();
167162
};
168163

164+
const onCreate = () => {
165+
history.push('/topic/create');
166+
};
167+
168+
const actions = [
169+
<Button key="refresh" type="default" size="small" onClick={onRefresh}>
170+
<ReloadOutlined />
171+
刷新
172+
</Button>,
173+
];
174+
175+
if (access.canPostTopic) {
176+
actions.push(
177+
<Button key="create" type="primary" size="small" onClick={onCreate}>
178+
<EditOutlined />
179+
新建
180+
</Button>,
181+
);
182+
}
183+
169184
return (
170185
<div>
171186
<ProList
@@ -187,12 +202,7 @@ const TopicList: React.FC<Props> = (props) => {
187202
}),
188203
onChange: onChangeTabKey,
189204
},
190-
actions: [
191-
<Button key="refresh" type="primary" onClick={onRefresh}>
192-
<ReloadOutlined />
193-
刷新
194-
</Button>,
195-
],
205+
actions,
196206
}}
197207
onRow={(record) => {
198208
return {
@@ -202,17 +212,6 @@ const TopicList: React.FC<Props> = (props) => {
202212
},
203213
};
204214
}}
205-
// request={async (params) => {
206-
// state.page = params.current || page;
207-
// state.limit = params.pageSize || limit;
208-
// return Promise.resolve({});
209-
// }}
210-
// pagination={{
211-
// total: 100,
212-
// current: page,
213-
// pageSize: limit,
214-
// responsive: true,
215-
// }}
216215
/>
217216
<Divider type="horizontal" />
218217
{renderFooter()}

0 commit comments

Comments
 (0)