完成留言管理功能
This commit is contained in:
37
src/api/Wall.ts
Normal file
37
src/api/Wall.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import Request from '@/utils/request'
|
||||
import { Wall, Cate } from '@/types/app/wall'
|
||||
|
||||
// 新增留言
|
||||
export const addWallDataAPI = (data: Wall) => Request<Wall>("POST", "/wall", { data })
|
||||
|
||||
// 删除留言
|
||||
export const delWallDataAPI = (id: number) => Request<Wall>("DELETE", `/wall/${id}`)
|
||||
|
||||
// 审核留言
|
||||
export const auditWallDataAPI = (id: number) => Request<Wall>("PATCH", `/wall/audit/${id}`)
|
||||
|
||||
// 修改留言
|
||||
export const editWallDataAPI = (data: Wall) => Request<Wall>("PATCH", "/wall", { data })
|
||||
|
||||
// 获取留言
|
||||
export const getWallDataAPI = (id?: number) => Request<Paginate<Wall>>("GET", `/wall/${id}`)
|
||||
|
||||
// 获取留言列表
|
||||
export const getWallListAPI = (data?: QueryData) => Request<Wall[]>("POST", `/wall/list`, {
|
||||
data: { ...data?.query },
|
||||
params: {
|
||||
sort: data?.sort,
|
||||
}
|
||||
})
|
||||
|
||||
// 分页获取留言列表
|
||||
export const getWallPagingAPI = (data?: QueryData) => Request<Paginate<Wall[]>>("POST", `/wall/paging`, {
|
||||
data: { ...data?.query },
|
||||
params: {
|
||||
sort: data?.sort,
|
||||
...data?.pagination
|
||||
}
|
||||
})
|
||||
|
||||
// 获取留言分类列表
|
||||
export const getWallCateListAPI = () => Request<Cate[]>("GET", `/wall/cate`)
|
||||
@@ -7,6 +7,7 @@ import Create from '@/pages/Create';
|
||||
import Cate from '@/pages/Cate';
|
||||
import Article from '@/pages/Article';
|
||||
import Comment from '@/pages/Comment';
|
||||
import Wall from "@/pages/Wall";
|
||||
import Tag from '@/pages/Tag';
|
||||
import Web from '@/pages/Web';
|
||||
import Swiper from '@/pages/Swiper';
|
||||
@@ -41,6 +42,7 @@ export default () => {
|
||||
{ path: "/article", title: "文章管理", component: <Article /> },
|
||||
{ path: "/tag", title: "标签管理", component: <Tag /> },
|
||||
{ path: "/comment", title: "评论管理", component: <Comment /> },
|
||||
{ path: "/wall", title: "评论管理", component: <Wall /> },
|
||||
{ path: "/web", title: "网站管理", component: <Web /> },
|
||||
{ path: "/swiper", title: "轮播图管理", component: <Swiper /> },
|
||||
{ path: "/footprint", title: "足迹管理", component: <Footprint /> },
|
||||
|
||||
@@ -127,6 +127,11 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
|
||||
path: "comment",
|
||||
name: "评论管理"
|
||||
},
|
||||
{
|
||||
to: "/wall",
|
||||
path: "wall",
|
||||
name: "留言管理"
|
||||
},
|
||||
{
|
||||
to: "/cate",
|
||||
path: "cate",
|
||||
|
||||
@@ -126,11 +126,11 @@ const ArticlePage = () => {
|
||||
|
||||
const onSubmit = async (values: FilterForm) => {
|
||||
const query: FilterArticle = {
|
||||
key: values.title ? values.title : null,
|
||||
startDate: values.createTime ? values.createTime[0].valueOf() + '' : null,
|
||||
endDate: values.createTime ? values.createTime[1].valueOf() + '' : null,
|
||||
cateIds: values.cateIds ? values.cateIds : null,
|
||||
tagId: values.tagId ? values.tagId + "" : null,
|
||||
key: values.title,
|
||||
startDate: values.createTime ? values.createTime[0].valueOf() + '' : undefined,
|
||||
endDate: values.createTime ? values.createTime[1].valueOf() + '' : undefined,
|
||||
cateIds: values.cateIds,
|
||||
tagId: values.tagId ? values.tagId + "" : undefined,
|
||||
}
|
||||
|
||||
const { data } = await getArticleListAPI({ query });
|
||||
|
||||
@@ -43,26 +43,21 @@ const CommentPage = () => {
|
||||
key: 'id',
|
||||
align: "center"
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'auditStatus',
|
||||
key: 'auditStatus',
|
||||
fixed: 'left',
|
||||
render: (status: number) => status ?
|
||||
<Tag bordered={false} color="processing">通过</Tag>
|
||||
: <Tag bordered={false} color="error">待审核</Tag>
|
||||
},
|
||||
// {
|
||||
// title: '状态',
|
||||
// dataIndex: 'auditStatus',
|
||||
// key: 'auditStatus',
|
||||
// fixed: 'left',
|
||||
// render: (status: number) => status ?
|
||||
// <Tag bordered={false} color="processing">通过</Tag>
|
||||
// : <Tag bordered={false} color="error">待审核</Tag>
|
||||
// },
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
},
|
||||
{
|
||||
title: '内容',
|
||||
dataIndex: 'content',
|
||||
@@ -73,6 +68,12 @@ const CommentPage = () => {
|
||||
setIsModalOpen(true)
|
||||
}}>{text}</span>
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
render: (text: string) => text ? text : '暂无邮箱',
|
||||
},
|
||||
{
|
||||
title: '网站',
|
||||
dataIndex: 'url',
|
||||
|
||||
177
src/pages/Wall/index.tsx
Normal file
177
src/pages/Wall/index.tsx
Normal file
@@ -0,0 +1,177 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Card, message, Table, Popconfirm, Button, Tag, Modal, Form, Input, DatePicker, Select } from 'antd';
|
||||
import { getWallListAPI, delWallDataAPI, getWallCateListAPI } from '@/api/Wall';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import { titleSty } from '@/styles/sty';
|
||||
import Title from '@/components/Title';
|
||||
import { Cate, Wall } from '@/types/app/wall';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const WallPage = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [wall, setWall] = useState<Wall>();
|
||||
const [list, setList] = useState<Wall[]>([]);
|
||||
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
const getWallList = async () => {
|
||||
const { data } = await getWallListAPI();
|
||||
|
||||
// 根据时间排序:最新时间在前
|
||||
// const sortedData = (data as Wall[]).sort((a, b) => +b.createTime - +a.createTime);
|
||||
setList(data)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const delWallData = async (id: number) => {
|
||||
setLoading(true)
|
||||
await delWallDataAPI(id);
|
||||
getWallList();
|
||||
message.success('🎉 删除留言成功');
|
||||
};
|
||||
|
||||
// 获取留言的分类列表
|
||||
const [cateList, setCateList] = useState<Cate[]>([])
|
||||
const getCateList = async () => {
|
||||
const { data } = await getWallCateListAPI()
|
||||
setCateList((data as Cate[]).filter(item => item.id !== 1))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
getWallList();
|
||||
getCateList()
|
||||
}, []);
|
||||
|
||||
const columns: ColumnsType = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
align: "center"
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'cate',
|
||||
key: 'cate',
|
||||
render: ({ name }, { color }) => <Tag bordered={false} color={color} className='!text-[#565656]'>{name}</Tag>,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '内容',
|
||||
dataIndex: 'content',
|
||||
key: 'content',
|
||||
width: 400,
|
||||
render: (text: string, record) => <span className="hover:text-primary cursor-pointer line-clamp-2" onClick={() => {
|
||||
setWall(record)
|
||||
setIsModalOpen(true)
|
||||
}}>{text}</span>
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email',
|
||||
render: (text: string) => text ? text : '暂无邮箱',
|
||||
},
|
||||
{
|
||||
title: '留言时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
render: (date: string) => dayjs(+date).format('YYYY-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
render: (text: string, record: Wall) => (
|
||||
<div className='flex justify-center space-x-2'>
|
||||
<Button onClick={() => {
|
||||
setWall(record)
|
||||
setIsModalOpen(true)
|
||||
}}>查看</Button>
|
||||
|
||||
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delWallData(record.id)}>
|
||||
<Button type="primary" danger>删除</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const onSubmit = async (values: FilterForm) => {
|
||||
const query: FilterData = {
|
||||
key: values.title ? values.title : undefined,
|
||||
content: values.content ? values.content : undefined,
|
||||
startDate: values.createTime ? values.createTime[0].valueOf() + '' : undefined,
|
||||
endDate: values.createTime ? values.createTime[1].valueOf() + '' : undefined,
|
||||
}
|
||||
|
||||
const { data } = await getWallListAPI({ query });
|
||||
console.log(data);
|
||||
setList(data)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title value='留言管理' />
|
||||
|
||||
<Card className='my-2 overflow-scroll'>
|
||||
<Form layout="inline" onFinish={onSubmit} autoComplete="off" className='flex-nowrap'>
|
||||
<Form.Item label="内容" name="content" className='w-2/12'>
|
||||
<Input placeholder='请输入内容关键词' />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="分类" name="cateId" className='w-2/12'>
|
||||
<Select
|
||||
allowClear
|
||||
options={cateList}
|
||||
fieldNames={{ label: 'name', value: 'id' }}
|
||||
placeholder="请选择分类"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="时间范围" name="createTime" className='w-3/12'>
|
||||
<RangePicker placeholder={["选择起始时间", "选择结束时间"]} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className='pr-6'>
|
||||
<Button type="primary" htmlType="submit">查询</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
<Card className={`${titleSty} mt-2`}>
|
||||
<Table
|
||||
rowKey="id"
|
||||
dataSource={list}
|
||||
columns={columns}
|
||||
loading={loading}
|
||||
expandable={{ defaultExpandAllRows: true }}
|
||||
scroll={{ x: 'max-content' }}
|
||||
pagination={{
|
||||
position: ['bottomCenter'],
|
||||
defaultPageSize: 8,
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Modal title='留言详情' open={isModalOpen} onCancel={() => setIsModalOpen(false)} footer={null}>
|
||||
<div className='pt-2 space-y-2'>
|
||||
<div><b>留言时间:</b> {dayjs(wall?.createTime).format("YYYY-MM-DD HH:mm:ss")}</div>
|
||||
<div><b>留言用户:</b> {wall?.name}</div>
|
||||
<div><b>内容:</b> {wall?.content}</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WallPage;
|
||||
17
src/types/app/wall.d.ts
vendored
Normal file
17
src/types/app/wall.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface Cate {
|
||||
id: number;
|
||||
name: string;
|
||||
mark: string;
|
||||
order: number;
|
||||
}
|
||||
|
||||
export interface Wall {
|
||||
id: number;
|
||||
name: string;
|
||||
cateId: number;
|
||||
cate: Category;
|
||||
color: string;
|
||||
content: string;
|
||||
auditStatus: number;
|
||||
createTime: string;
|
||||
}
|
||||
Reference in New Issue
Block a user