2024-08-08 23:24:20 +08:00
|
|
|
import { useState, useEffect } from 'react';
|
2024-08-15 15:28:58 +08:00
|
|
|
import { Cate } from '@/types/app/cate';
|
2024-08-04 15:58:33 +08:00
|
|
|
import { addCateDataAPI, delCateDataAPI, editCateDataAPI, getCateDataAPI, getCateListAPI } from '@/api/Cate';
|
2024-08-06 21:02:06 +08:00
|
|
|
import { DownOutlined } from '@ant-design/icons';
|
2024-10-18 13:12:03 +08:00
|
|
|
import { Form, Input, Button, Tree, Modal, Spin, Dropdown, Card, MenuProps, Popconfirm, message, Radio } from 'antd';
|
2024-08-07 14:35:10 +08:00
|
|
|
import Title from '@/components/Title';
|
2024-08-08 15:27:57 +08:00
|
|
|
import "./index.scss"
|
2024-08-04 15:58:33 +08:00
|
|
|
|
2024-08-08 23:24:20 +08:00
|
|
|
const CatePage = () => {
|
2024-08-04 15:58:33 +08:00
|
|
|
const [loading, setLoading] = useState(false);
|
2024-11-22 14:40:15 +08:00
|
|
|
const [btnLoading, setBtnLoading] = useState(false)
|
|
|
|
|
|
2024-08-08 23:24:20 +08:00
|
|
|
const [isModelOpen, setIsModelOpen] = useState(false);
|
2024-08-08 18:47:49 +08:00
|
|
|
const [cate, setCate] = useState<Cate>({} as Cate);
|
2024-08-04 15:58:33 +08:00
|
|
|
const [list, setList] = useState<Cate[]>([]);
|
2024-08-08 18:47:49 +08:00
|
|
|
const [isMethod, setIsMethod] = useState<'create' | 'edit'>('create');
|
2024-10-18 13:12:03 +08:00
|
|
|
const [isCateShow, setIsCateShow] = useState(false)
|
2024-08-08 23:24:20 +08:00
|
|
|
const [form] = Form.useForm();
|
2024-08-09 14:35:26 +08:00
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
const getCateList = async () => {
|
|
|
|
|
const { data } = await getCateListAPI();
|
2024-11-22 15:34:21 +08:00
|
|
|
data.sort((a, b) => a.order - b.order)
|
2024-12-09 15:17:04 +08:00
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
setList(data as Cate[]);
|
|
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-22 14:40:15 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
getCateList();
|
|
|
|
|
}, []);
|
|
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
const addCateData = (id: number) => {
|
2024-08-08 18:47:49 +08:00
|
|
|
setIsMethod("create")
|
2024-08-08 23:24:20 +08:00
|
|
|
setIsModelOpen(true);
|
2024-10-18 13:12:03 +08:00
|
|
|
setIsCateShow(false)
|
2024-08-08 23:24:20 +08:00
|
|
|
|
|
|
|
|
form.resetFields();
|
|
|
|
|
|
2024-10-18 13:12:03 +08:00
|
|
|
setCate({ ...cate, level: id, type: "cate" });
|
2024-08-04 15:58:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const editCateData = async (id: number) => {
|
2024-08-08 18:47:49 +08:00
|
|
|
setIsMethod("edit")
|
2024-08-04 15:58:33 +08:00
|
|
|
setLoading(true);
|
2024-08-08 23:24:20 +08:00
|
|
|
setIsModelOpen(true);
|
2024-10-18 13:12:03 +08:00
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
const { data } = await getCateDataAPI(id);
|
2024-10-18 13:12:03 +08:00
|
|
|
setIsCateShow(data.type === "cate" ? false : true)
|
2024-08-04 15:58:33 +08:00
|
|
|
setCate(data);
|
2024-10-18 13:12:03 +08:00
|
|
|
|
2024-08-08 18:47:49 +08:00
|
|
|
form.setFieldsValue(data);
|
2024-08-04 15:58:33 +08:00
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
2024-08-08 13:46:28 +08:00
|
|
|
const delCateData = async (id: number) => {
|
2024-08-08 18:47:49 +08:00
|
|
|
setLoading(true);
|
2024-12-09 15:17:04 +08:00
|
|
|
try {
|
|
|
|
|
await delCateDataAPI(id);
|
|
|
|
|
message.success('🎉 删除分类成功');
|
|
|
|
|
getCateList();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
2024-08-08 13:46:28 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
const submit = async () => {
|
2024-11-22 14:40:15 +08:00
|
|
|
setBtnLoading(true)
|
|
|
|
|
|
2024-08-08 18:47:49 +08:00
|
|
|
form.validateFields().then(async (values: Cate) => {
|
2024-10-18 13:12:03 +08:00
|
|
|
if (values.type === "cate") values.url = '/'
|
2024-11-04 13:57:35 +08:00
|
|
|
|
2024-08-08 18:47:49 +08:00
|
|
|
if (isMethod === "edit") {
|
|
|
|
|
await editCateDataAPI({ ...cate, ...values });
|
|
|
|
|
message.success('🎉 修改分类成功');
|
|
|
|
|
} else {
|
|
|
|
|
await addCateDataAPI({ ...cate, ...values });
|
|
|
|
|
message.success('🎉 新增分类成功');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化表单状态
|
|
|
|
|
form.resetFields();
|
|
|
|
|
setCate({} as Cate);
|
|
|
|
|
|
2024-08-08 23:24:20 +08:00
|
|
|
setIsModelOpen(false);
|
2024-08-08 18:47:49 +08:00
|
|
|
getCateList();
|
|
|
|
|
setIsMethod("create")
|
|
|
|
|
})
|
2024-11-22 14:40:15 +08:00
|
|
|
|
|
|
|
|
setBtnLoading(false)
|
2024-08-04 15:58:33 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-06 21:02:06 +08:00
|
|
|
const closeModel = () => {
|
2024-10-18 13:12:03 +08:00
|
|
|
setIsCateShow(false)
|
2024-08-08 18:47:49 +08:00
|
|
|
setIsMethod("create")
|
2024-08-08 23:24:20 +08:00
|
|
|
setIsModelOpen(false);
|
2024-08-08 18:47:49 +08:00
|
|
|
form.resetFields();
|
|
|
|
|
setCate({} as Cate);
|
2024-08-04 15:58:33 +08:00
|
|
|
};
|
|
|
|
|
|
2024-08-05 02:42:35 +08:00
|
|
|
// 将数据转换为树形结构
|
|
|
|
|
const treeData = (data: Cate[]): any[] => (
|
|
|
|
|
data.map(item => {
|
|
|
|
|
const items: MenuProps['items'] = [
|
|
|
|
|
{
|
|
|
|
|
key: '1',
|
|
|
|
|
label: <span onClick={() => addCateData(item.id!)}>新增</span>,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '2',
|
|
|
|
|
label: <span onClick={() => editCateData(item.id!)}>编辑</span>,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '3',
|
2024-08-06 21:02:06 +08:00
|
|
|
label: (
|
2024-08-06 23:04:42 +08:00
|
|
|
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delCateData(item.id!)}>
|
2024-08-06 21:02:06 +08:00
|
|
|
<span>删除</span>
|
|
|
|
|
</Popconfirm>
|
|
|
|
|
),
|
2024-08-05 02:42:35 +08:00
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return ({
|
|
|
|
|
title: (
|
|
|
|
|
<div className='group w-full flex justify-between items-center'>
|
2024-09-21 13:47:08 +08:00
|
|
|
<h3>{item.icon} <span className='ml-2'>{item.name}</span></h3>
|
2024-08-05 02:42:35 +08:00
|
|
|
|
2024-08-08 23:24:20 +08:00
|
|
|
<Dropdown menu={{ items }} arrow>
|
|
|
|
|
<Button type='link' size='small'>操作 <DownOutlined /></Button>
|
|
|
|
|
</Dropdown>
|
2024-08-05 02:42:35 +08:00
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
key: item.id,
|
|
|
|
|
children: item.children ? treeData(item.children) : [],
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
|
2024-08-04 15:58:33 +08:00
|
|
|
return (
|
2024-08-07 14:35:10 +08:00
|
|
|
<>
|
2024-11-04 13:57:35 +08:00
|
|
|
<Title value="分类管理">
|
2024-11-14 20:39:19 +08:00
|
|
|
<Button type="primary" size='large' onClick={() => addCateData(0)}>新增分类</Button>
|
2024-11-04 13:57:35 +08:00
|
|
|
</Title>
|
2024-08-07 14:35:10 +08:00
|
|
|
|
2024-11-12 19:55:24 +08:00
|
|
|
<Card className={`CatePage [&>.ant-card-body]:!p-[30px_20px] [&>.ant-card-body]:!pb-6 mt-2 min-h-[calc(100vh-180px)]`}>
|
2024-08-07 14:35:10 +08:00
|
|
|
<Spin spinning={loading}>
|
|
|
|
|
<Tree defaultExpandAll={true} treeData={treeData(list)} />
|
|
|
|
|
</Spin>
|
|
|
|
|
|
2024-08-09 14:35:26 +08:00
|
|
|
<Modal title={isMethod === "edit" ? "编辑分类" : "新增分类"} open={isModelOpen} onCancel={closeModel} destroyOnClose footer={null}>
|
|
|
|
|
<Form form={form} layout="vertical" initialValues={cate} size='large' preserve={false} className='mt-6'>
|
2024-08-08 18:47:49 +08:00
|
|
|
<Form.Item label="名称" name="name" rules={[{ required: true, message: '分类名称不能为空' }]}>
|
2024-09-14 15:17:31 +08:00
|
|
|
<Input placeholder="请输入分类名称" />
|
2024-08-07 14:35:10 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
|
2024-08-08 18:47:49 +08:00
|
|
|
<Form.Item label="标识" name="mark" rules={[{ required: true, message: '分类标识不能为空' }]}>
|
2024-09-14 15:17:31 +08:00
|
|
|
<Input placeholder="请输入分类标识" />
|
2024-08-07 14:35:10 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item label="图标" name="icon">
|
2024-09-14 15:17:31 +08:00
|
|
|
<Input placeholder="请输入分类图标" />
|
2024-08-07 14:35:10 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
|
2024-10-18 13:12:03 +08:00
|
|
|
{
|
|
|
|
|
isCateShow && <Form.Item label="链接" name="url">
|
|
|
|
|
<Input placeholder="请输入分类链接" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
}
|
2024-08-07 14:35:10 +08:00
|
|
|
|
2024-09-14 15:17:31 +08:00
|
|
|
<Form.Item label="顺序" name="order">
|
|
|
|
|
<Input placeholder="请输入分类顺序(值越小越靠前)" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
2024-10-18 13:12:03 +08:00
|
|
|
<Form.Item label="模式" name="type">
|
|
|
|
|
<Radio.Group onChange={(e) => {
|
|
|
|
|
const type = e.target.value
|
|
|
|
|
type === "nav" ? setIsCateShow(true) : setIsCateShow(false)
|
|
|
|
|
}}>
|
|
|
|
|
<Radio value="cate">分类</Radio>
|
|
|
|
|
<Radio value="nav">导航</Radio>
|
|
|
|
|
</Radio.Group>
|
|
|
|
|
</Form.Item>
|
2024-09-14 15:17:31 +08:00
|
|
|
|
2024-11-22 14:40:15 +08:00
|
|
|
<Form.Item className='!mb-0 w-full'>
|
|
|
|
|
<Button type="primary" onClick={submit} loading={btnLoading} className='w-full ml-2'>新增分类</Button>
|
2024-08-07 14:35:10 +08:00
|
|
|
</Form.Item>
|
|
|
|
|
</Form>
|
|
|
|
|
</Modal>
|
|
|
|
|
</Card>
|
|
|
|
|
</>
|
2024-08-04 15:58:33 +08:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2024-08-08 12:47:44 +08:00
|
|
|
export default CatePage;
|