From 6e676fb689370e33e38b50edb6782f7cefed2208 Mon Sep 17 00:00:00 2001 From: SunnyQjm Date: Thu, 31 Oct 2019 16:02:47 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E6=94=AF=E6=8C=81=E5=8D=9A=E6=96=87?= =?UTF-8?q?=E7=9A=84=E5=88=97=E8=A1=A8=E6=9F=A5=E7=9C=8B=E5=92=8C=E5=88=A0?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/editable-tag-group/index.tsx | 32 ++++ src/components/post-item/index.scss | 14 +- src/data/comment.ts | 6 + src/data/interface/response.interface.ts | 8 + src/data/network/api.ts | 28 +++- src/data/param/request.param.ts | 13 ++ src/data/post.ts | 7 + src/data/tag.ts | 4 + src/models/admin/index.ts | 21 ++- src/pages/admin/post-manager/index.tsx | 166 ++++++++++++++++++- src/pages/admin/post-manager/models/index.ts | 64 +++++++ src/pages/edit-post/index.scss | 9 - src/pages/edit-post/index.tsx | 47 ------ src/utils/date.util.ts | 19 +++ 14 files changed, 357 insertions(+), 81 deletions(-) create mode 100644 src/data/comment.ts create mode 100644 src/data/tag.ts create mode 100644 src/pages/admin/post-manager/models/index.ts delete mode 100644 src/pages/edit-post/index.scss delete mode 100644 src/pages/edit-post/index.tsx create mode 100644 src/utils/date.util.ts diff --git a/src/components/editable-tag-group/index.tsx b/src/components/editable-tag-group/index.tsx index e6a9b16..5084095 100644 --- a/src/components/editable-tag-group/index.tsx +++ b/src/components/editable-tag-group/index.tsx @@ -15,6 +15,37 @@ interface EditableTagGroupComponentState { inputValue: string } +const colors = [ + 'magenta', + 'red', + 'volcano', + 'orange', + 'gold', + 'lime', + 'green', + 'cyan', + 'blue', + 'geekblue', + 'purple' +]; + +function getHashCode(str: string, caseSensitive: boolean = false) { + if (!caseSensitive) { + str = str.toLowerCase(); + } + // 1315423911=b'1001110011001111100011010100111' + let hash = 1315423911, i, ch; + for (i = str.length - 1; i >= 0; i--) { + ch = str.charCodeAt(i); + hash ^= ((hash << 5) + ch + (hash >> 2)); + } + return (hash & 0x7FFFFFFF); +} + +function getRandColor(tag: string) { + return colors[getHashCode(tag) % colors.length]; +} + /** * 可编辑,带动画的标签组 */ @@ -87,6 +118,7 @@ class EditableTagGroupComponent extends React.Component {tag} diff --git a/src/components/post-item/index.scss b/src/components/post-item/index.scss index 2e463a0..4e183f8 100644 --- a/src/components/post-item/index.scss +++ b/src/components/post-item/index.scss @@ -28,10 +28,10 @@ } } -a { - text-decoration: none; - color: #555; - &:hover{ - color: #555; - } -} +//a { +// text-decoration: none; +// color: #555; +// &:hover{ +// color: #555; +// } +//} diff --git a/src/data/comment.ts b/src/data/comment.ts new file mode 100644 index 0000000..61bfef9 --- /dev/null +++ b/src/data/comment.ts @@ -0,0 +1,6 @@ +export interface Comment { + id: number, + name: string, + email: string, + content: string, +} diff --git a/src/data/interface/response.interface.ts b/src/data/interface/response.interface.ts index 7fbce51..5d8e301 100644 --- a/src/data/interface/response.interface.ts +++ b/src/data/interface/response.interface.ts @@ -4,3 +4,11 @@ export interface BaseResponseBody { message: string; data: T; } + + +export interface BaseListData { + list: T[], + total: number, + page: number, + size: number, +} diff --git a/src/data/network/api.ts b/src/data/network/api.ts index a31c4c3..74c1ffa 100644 --- a/src/data/network/api.ts +++ b/src/data/network/api.ts @@ -3,14 +3,19 @@ import {BaseResponseBody} from "@/data/interface/response.interface"; import {StatusCode} from "@/data/network/status-code"; import {User} from "@/data/user"; import router from "umi/router"; -import {CreatePostParam} from "@/data/param/request.param"; +import {CreatePostParam, DelPostParam, GetPostsParam} from "@/data/param/request.param"; +import {message} from "antd"; export const API = { INFO: { + DEFAULT_PAGE_SIZE: 10, + login: '/login', register: '/register', getUserInfo: '/admin/getUserInfo', createPost: '/admin/create-post', + delPost: 'admin/del-post', + getPosts: '/post/list', }, global: { token: '' @@ -58,12 +63,14 @@ export const API = { case StatusCode.NEED_ADMIN_PERMISSION: case StatusCode.COMMENT_ERROR: case StatusCode.NEED_LOGIN: + message.error(responseData.message); break; case StatusCode.UN_AUTHORIZED: + message.warning('请先登录'); router.replace('/login'); break; } - if(responseData.statusCode === StatusCode.SUCCESS) { + if (responseData.statusCode === StatusCode.SUCCESS) { return responseData.data; } else { return Promise.reject(responseData); @@ -112,7 +119,22 @@ export const API = { */ createPost(createPostParam: CreatePostParam) { return API.eastPost(API.INFO.createPost, createPostParam); - } + }, + /** + * 获取博文列表 + * @param getPostsParam + */ + getPosts(getPostsParam: GetPostsParam) { + return API.easyGet(API.INFO.getPosts, getPostsParam); + }, + + /** + * 删除博文 + * @param delPostParam + */ + delPost(delPostParam: DelPostParam) { + return API.eastPost(API.INFO.delPost, delPostParam); + } }; diff --git a/src/data/param/request.param.ts b/src/data/param/request.param.ts index d18b970..39c9879 100644 --- a/src/data/param/request.param.ts +++ b/src/data/param/request.param.ts @@ -3,3 +3,16 @@ export interface CreatePostParam { content: string, tags?: string[], } + +export interface GetListParam { + page: number, + size: number +} + +export interface GetPostsParam extends GetListParam { + tagId?: string, +} + +export interface DelPostParam { + postId: number +} diff --git a/src/data/post.ts b/src/data/post.ts index 7b4157b..842c1ad 100644 --- a/src/data/post.ts +++ b/src/data/post.ts @@ -1,7 +1,14 @@ +import {Tag} from "@/data/tag"; +import {Comment} from "@/data/comment"; +import {User} from "@/data/user"; + export interface Post { id: number, title: string, content: string, + tags: Tag[], + comments: Comment[], + owner: User, createdAt: number, updatedAt: number, } diff --git a/src/data/tag.ts b/src/data/tag.ts new file mode 100644 index 0000000..493c414 --- /dev/null +++ b/src/data/tag.ts @@ -0,0 +1,4 @@ +export interface Tag { + id: number, + tagName: string, +} diff --git a/src/models/admin/index.ts b/src/models/admin/index.ts index 767d255..7c37581 100644 --- a/src/models/admin/index.ts +++ b/src/models/admin/index.ts @@ -4,17 +4,14 @@ import {User} from "@/data/user"; import router from 'umi/router'; import {message} from 'antd' import {LocalStorageKeys, LocalStorageManager} from "@/manager/storage.manager"; -import {CreatePostParam} from "@/data/param/request.param"; - -export interface AdminModelState { - user: User, - loginIng: boolean -} +import {CreatePostParam, DelPostParam, GetPostsParam} from "@/data/param/request.param"; +import {Post} from "@/data/post"; export default { namespace: 'admin', state: { user: null, + posts: [], }, reducers: { /** @@ -23,7 +20,7 @@ export default { * @param action */ updateUser(state: any, action: Action) { - if(action.data && action.data.access_token) { + if (action.data && action.data.access_token) { API.global.token = action.data.access_token; } return { @@ -41,12 +38,14 @@ export default { ...state, user: null } - } + }, + + }, effects: { * init(action: Action, operators: Operators) { const user = yield LocalStorageManager.getObj(LocalStorageKeys.USER); - if(user) { + if (user) { yield operators.put({ type: 'updateUser', data: user @@ -79,8 +78,8 @@ export default { * createPost(action: Action, operators: Operators) { yield operators.call(API.createPost, action.data); - message.info('发表成功'); - } + message.success('发表成功'); + }, } } diff --git a/src/pages/admin/post-manager/index.tsx b/src/pages/admin/post-manager/index.tsx index 0b5ab15..26d03b5 100644 --- a/src/pages/admin/post-manager/index.tsx +++ b/src/pages/admin/post-manager/index.tsx @@ -1,14 +1,39 @@ import React from "react"; +import Antd, {Divider, message, Table, Popconfirm} from 'antd'; +import {connect} from 'dva'; +import withRouter from 'umi/withRouter'; import './index.scss' +import RouterTypes from "umi/routerTypes"; +import {Post} from "@/data/post"; +import {Tag} from "@/data/tag"; +import {dateFormat} from "@/utils/date.util"; -interface PostManagerPageProps { - +interface PostManagerPageProps extends RouterTypes { + dispatch: any, + loading: boolean, + posts: Post[], + total: number, + page: number, + pageSize: number, } interface PostManagerPageState { } + +// // rowSelection object indicates the need for row selection +// const rowSelection = { +// onChange: (selectedRowKeys: any, selectedRows: any) => { +// console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); +// }, +// getCheckboxProps: (record: any) => ({ +// disabled: record.name === 'Disabled User', // Column configuration not to be checked +// name: record.name, +// }), +// }; + + /** * 博文管理页面 */ @@ -17,13 +42,146 @@ class PostManagerPage extends React.Component {text}, + }, + { + title: '内容', + key: 'content', + dataIndex: 'content', + render: (content: string) => + { + content.length > 100 ? + content.substr(0, 100) + : + content + } + + }, + { + title: '标签', + key: 'tags', + dataIndex: 'tags', + render: (tags: Tag[]) => ( + + {tags.map(tag => { + let color = tag.tagName.length > 5 ? 'geekblue' : 'green'; + return ( + + {tag.tagName} + + ); + })} + + ) + }, + { + title: '创建时间', + key: 'createdAt', + dataIndex: 'createdAt', + render: (date: string) => { + return ( + {dateFormat("YYYY-mm-dd HH:MM", new Date(date))} + ) + } + }, + { + title: '更新时间', + ket: 'updatedAt', + dataIndex: 'updatedAt', + render: (date: string) => { + return ( + {dateFormat("YYYY-mm-dd HH:MM", new Date(date))} + ) + } + }, + { + title: '操作', + key: 'action', + render: (text: string, record: Post) => ( + + 预览 + + 编辑 + + this.handleDelete(record.id)}> + 删除 + + + ), + } + ]; + render(): React.ReactElement> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined { + const { + loading, + posts, + page, + pageSize, + total + } = this.props; + const data = posts.map(post => { + return { + ...post, + key: post.id + } + }); + const pagination: any = { + pageSize, + total: total, + current: page, + onChange: this.handlePageChange + }; return (
- PostManager Page + ); } } -export default PostManagerPage +function mapStateToProps(state: any) { + return { + ...state['post-manager'], + loading: state.loading.effects['post-manager/getPosts'], + }; +} + +export default connect(mapStateToProps)(withRouter(PostManagerPage)) diff --git a/src/pages/admin/post-manager/models/index.ts b/src/pages/admin/post-manager/models/index.ts new file mode 100644 index 0000000..2854055 --- /dev/null +++ b/src/pages/admin/post-manager/models/index.ts @@ -0,0 +1,64 @@ +import {Action, Operators} from "@/data/interface/dva.interface"; +import {DelPostParam, GetPostsParam} from "@/data/param/request.param"; +import {API} from "@/data/network/api"; +import {message} from "antd"; +import {Post} from "@/data/post"; +import {BaseListData} from "@/data/interface/response.interface"; + +export default { + namespace: 'post-manager', + state: { + posts: [], + total: 0, + page: 1, + pageSize: API.INFO.DEFAULT_PAGE_SIZE + }, + reducers: { + updatePosts(state: any, action: Action>) { + return { + ...state, + total: action.data.total, + posts: action.data.list, + page: action.data.page, + } + }, + + + removePost(state: any, action: Action) { + return { + ...state, + posts: state.posts.filter((post: Post) => post.id !== action.data) + } + } + }, + effects: { + * getPosts(action: Action, operators: Operators) { + const postList = yield operators.call(API.getPosts, action.data); + console.log(postList); + yield operators.put({ + type: 'updatePosts', + data: { + ...postList, + ...action.data, + } + }) + }, + + * delPost(action: Action, operators: Operators) { + const result = yield operators.call(API.delPost, { + postId: action.data + }); + message.destroy(); + if (result) { // 删除成功 + yield operators.put({ + type: 'removePost', + data: action.data + }); + message.success('删除成功') + } else { // 删除失败 + message.error('删除失败') + } + }, + + } +} diff --git a/src/pages/edit-post/index.scss b/src/pages/edit-post/index.scss deleted file mode 100644 index cbf26c3..0000000 --- a/src/pages/edit-post/index.scss +++ /dev/null @@ -1,9 +0,0 @@ - -.edit-post-page { - &__title-input { - border: none; - border-radius: 10px; - margin-bottom: 20px; - margin-top: 20px; - } -} diff --git a/src/pages/edit-post/index.tsx b/src/pages/edit-post/index.tsx deleted file mode 100644 index f690375..0000000 --- a/src/pages/edit-post/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from "react"; -import MdEditor from "for-editor"; -import { - Input -} from 'antd'; -import './index.scss' - -interface EditPostPageProps { - -} - -interface EditPostPageState { - value: string, -} - -/** - * 编辑和发布博文的界面 - */ -class EditPostPage extends React.Component { - constructor(props: EditPostPageProps) { - super(props); - this.state = { - value: '' - }; - this.handleChange = this.handleChange.bind(this); - } - - handleChange(value: string) { - this.setState({ - value - }) - } - - render(): React.ReactElement> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined { - const { - value - } = this.state; - return ( -
- - -
- ); - } -} - -export default EditPostPage diff --git a/src/utils/date.util.ts b/src/utils/date.util.ts new file mode 100644 index 0000000..230fec6 --- /dev/null +++ b/src/utils/date.util.ts @@ -0,0 +1,19 @@ +export const dateFormat = (fmt: any, date: any) => { + let ret; + let opt: any = { + "Y+": date.getFullYear().toString(), // 年 + "m+": (date.getMonth() + 1).toString(), // 月 + "d+": date.getDate().toString(), // 日 + "H+": date.getHours().toString(), // 时 + "M+": date.getMinutes().toString(), // 分 + "S+": date.getSeconds().toString() // 秒 + // 有其他格式化字符需求可以继续添加,必须转化成字符串 + }; + for (let k in opt) { + ret = new RegExp("(" + k + ")").exec(fmt); + if (ret) { + fmt = fmt.replace(ret[1], (ret[1].length === 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0"))) + } + } + return fmt; +};