完成标签管理

This commit is contained in:
宇阳
2024-08-08 23:24:20 +08:00
parent af37fa997f
commit 805ea3b99f
5 changed files with 166 additions and 22 deletions

View File

@@ -8,6 +8,7 @@ import Create from './pages/Create';
import Cate from './pages/Cate'; import Cate from './pages/Cate';
import Article from './pages/Article'; import Article from './pages/Article';
import Comment from './pages/Comment'; import Comment from './pages/Comment';
import Tag from './pages/Tag';
import Web from './pages/Web'; import Web from './pages/Web';
import Swiper from './pages/Swiper'; import Swiper from './pages/Swiper';
import Setup from './pages/Setup'; import Setup from './pages/Setup';
@@ -101,6 +102,16 @@ function App() {
} }
/> />
<Route
path="/tag"
element={
<>
<PageTitle title="Thrive - 标签管理" />
<Tag />
</>
}
/>
<Route <Route
path="/comment" path="/comment"
element={ element={

View File

@@ -182,6 +182,18 @@ const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
</NavLink> </NavLink>
</li> </li>
<li>
<NavLink
to="/tag"
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
</NavLink>
</li>
<li> <li>
<NavLink <NavLink
to="/comment" to="/comment"

View File

@@ -4,9 +4,9 @@
width: 100% !important; width: 100% !important;
} }
.ant-tree-node-selected { // .ant-tree-node-selected {
.controls { // .controls {
display: block !important; // display: block !important;
} // }
} // }
} }

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'; import { useState, useEffect } from 'react';
import { Cate } from '@/types/cate'; import { Cate } from '@/types/cate';
import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate'; import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate';
import { DownOutlined } from '@ant-design/icons'; import { DownOutlined } from '@ant-design/icons';
@@ -6,13 +6,14 @@ import { Form, Input, Button, Tree, Modal, Spin, Dropdown, Card, MenuProps, Popc
import Title from '@/components/Title'; import Title from '@/components/Title';
import "./index.scss" import "./index.scss"
const CatePage: React.FC = () => { const CatePage = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [model, setModel] = useState(false); const [isModelOpen, setIsModelOpen] = useState(false);
const [cate, setCate] = useState<Cate>({} as Cate); const [cate, setCate] = useState<Cate>({} as Cate);
const [list, setList] = useState<Cate[]>([]); const [list, setList] = useState<Cate[]>([]);
const [isMethod, setIsMethod] = useState<'create' | 'edit'>('create'); const [isMethod, setIsMethod] = useState<'create' | 'edit'>('create');
const [form] = Form.useForm();
const getCateList = async () => { const getCateList = async () => {
const { data } = await getCateListAPI(); const { data } = await getCateListAPI();
setList(data as Cate[]); setList(data as Cate[]);
@@ -21,14 +22,18 @@ const CatePage: React.FC = () => {
const addCateData = (id: number) => { const addCateData = (id: number) => {
setIsMethod("create") setIsMethod("create")
setModel(true); setIsModelOpen(true);
console.log(cate, 333);
form.resetFields();
setCate({ ...cate, level: id }); setCate({ ...cate, level: id });
}; };
const editCateData = async (id: number) => { const editCateData = async (id: number) => {
setIsMethod("edit") setIsMethod("edit")
setLoading(true); setLoading(true);
setModel(true); setIsModelOpen(true);
const { data } = await getCateDataAPI(id); const { data } = await getCateDataAPI(id);
setCate(data); setCate(data);
form.setFieldsValue(data); form.setFieldsValue(data);
@@ -42,8 +47,6 @@ const CatePage: React.FC = () => {
getCateList(); getCateList();
}; };
const [form] = Form.useForm();
const submit = async () => { const submit = async () => {
form.validateFields().then(async (values: Cate) => { form.validateFields().then(async (values: Cate) => {
if (isMethod === "edit") { if (isMethod === "edit") {
@@ -58,7 +61,7 @@ const CatePage: React.FC = () => {
form.resetFields(); form.resetFields();
setCate({} as Cate); setCate({} as Cate);
setModel(false); setIsModelOpen(false);
getCateList(); getCateList();
setIsMethod("create") setIsMethod("create")
}) })
@@ -66,7 +69,7 @@ const CatePage: React.FC = () => {
const closeModel = () => { const closeModel = () => {
setIsMethod("create") setIsMethod("create")
setModel(false); setIsModelOpen(false);
form.resetFields(); form.resetFields();
setCate({} as Cate); setCate({} as Cate);
}; };
@@ -98,11 +101,9 @@ const CatePage: React.FC = () => {
<div className='group w-full flex justify-between items-center'> <div className='group w-full flex justify-between items-center'>
<h3>{item.name}</h3> <h3>{item.name}</h3>
<div className='controls hidden'> <Dropdown menu={{ items }} arrow>
<Dropdown menu={{ items }} arrow> <Button type='link' size='small'> <DownOutlined /></Button>
<Button type='link' size='small'> <DownOutlined /></Button> </Dropdown>
</Dropdown>
</div>
</div> </div>
), ),
key: item.id, key: item.id,
@@ -122,14 +123,14 @@ const CatePage: React.FC = () => {
<Card className={`CatePage [&>.ant-card-body]:!p-2 [&>.ant-card-body]:!pb-6 mt-2`}> <Card className={`CatePage [&>.ant-card-body]:!p-2 [&>.ant-card-body]:!pb-6 mt-2`}>
<div className='my-2 text-center'> <div className='my-2 text-center'>
<Button type="primary" onClick={() => setModel(true)}></Button> <Button type="primary" onClick={() => addCateData(0)}></Button>
</div> </div>
<Spin spinning={loading}> <Spin spinning={loading}>
<Tree defaultExpandAll={true} treeData={treeData(list)} /> <Tree defaultExpandAll={true} treeData={treeData(list)} />
</Spin> </Spin>
<Modal title={isMethod === "edit" ? "编辑分类" : "新增分类"} open={model} onCancel={closeModel} footer={null}> <Modal title={isMethod === "edit" ? "编辑分类" : "新增分类"} open={isModelOpen} onCancel={closeModel} footer={null}>
<Form form={form} layout="vertical" initialValues={cate} size='large' className='mt-6'> <Form form={form} layout="vertical" initialValues={cate} size='large' className='mt-6'>
<Form.Item label="名称" name="name" rules={[{ required: true, message: '分类名称不能为空' }]}> <Form.Item label="名称" name="name" rules={[{ required: true, message: '分类名称不能为空' }]}>
<Input placeholder="大前端" /> <Input placeholder="大前端" />

120
src/pages/Tag/index.tsx Normal file
View File

@@ -0,0 +1,120 @@
import React, { useState, useEffect } from 'react';
import { Form, Input, Button, Table, notification, Card, message, Popconfirm } from 'antd';
import { TagOutlined, SettingOutlined } from '@ant-design/icons';
import { addTagDataAPI, delTagDataAPI, editTagDataAPI, getTagListAPI } from '@/api/Tag';
import Title from '@/components/Title';
interface Tag {
id?: number;
name: string;
}
const TagManagement: React.FC = () => {
const [form] = Form.useForm<Tag>();
const [loading, setLoading] = useState(false);
const [tag, setTag] = useState<Tag>({ name: '' });
const [title, setTitle] = useState<string>('新增标签');
const [list, setList] = useState<Tag[]>([]);
// 获取标签列表
const getTagList = async () => {
const { data } = await getTagListAPI()
setList(data as Tag[]);
setLoading(false)
}
useEffect(() => {
setLoading(true)
getTagList()
}, []);
const delTagData = async (id: number) => {
setLoading(true);
await delTagDataAPI(id);
message.success('🎉 删除标签成功');
getTagList()
};
const editTagData = (data: Tag) => {
setLoading(true);
setTag(data);
setTitle('编辑标签');
};
const submit = () => {
form.validateFields().then(async (values) => {
const fn = (message: string) => {
form.resetFields();
notification.success({
message: '成功',
description: message,
});
getTagList()
};
if (tag.id) {
await editTagDataAPI(tag);
setTitle('新增标签');
fn('🎉 编辑标签成功');
} else {
await addTagDataAPI(values);
fn('🎉 新增标签成功');
}
})
};
return (
<>
<Title value="标签管理" />
<Card className="mt-2">
<div className="w-8/12 flex justify-between px-8 mx-auto">
<div className="flex flex-col w-[40%]">
<h2 className="text-xl pb-4 text-center">{title}</h2>
<Form form={form} size="large" layout="vertical" initialValues={tag}>
<Form.Item
label="标签名称"
name="name"
rules={[{ required: true, message: '标签不能为空' }]}
>
<Input placeholder="大前端" />
</Form.Item>
<Form.Item>
<Button type="primary" size="large" onClick={submit} className="w-full">{title}</Button>
</Form.Item>
</Form>
</div>
<div className="flex flex-col w-[50%]">
<h2 className="text-xl pb-4 text-center"></h2>
<Table dataSource={list} rowKey="id">
<Table.Column title="ID" dataIndex="id" />
<Table.Column title="名称" dataIndex="name" align="center" />
<Table.Column
title="操作"
align="center"
render={(text, record: Tag) => (
<>
<div className='flex justify-center space-x-4'>
<Button size="small" onClick={() => editTagData(record)}></Button>
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delTagData(record.id!)}>
<Button size="small" type="primary" danger></Button>
</Popconfirm>
</div>
</>
)}
/>
</Table>
</div>
</div>
</Card>
</>
);
};
export default TagManagement;