Files
fe_supplier_frontend/src/pages/friendLinkManage/friendLinkCategory.tsx

410 lines
12 KiB
TypeScript
Raw Normal View History

2025-06-17 21:06:27 +08:00
import React, { useState, useEffect } from 'react';
import { useIntl } from 'umi';
import { Card, Table, Button, Modal, Form, Input, Space, message, Select, TreeSelect } from 'antd';
import { PlusOutlined, DeleteOutlined, ExclamationCircleOutlined, EditOutlined } from '@ant-design/icons';
import './friendLinkManage.less';
const { Option } = Select;
// 友情链接分类类型定义
interface CategoryType {
id: string;
name: string;
parentId: string | null;
level: number;
sort: number;
children?: CategoryType[];
key?: string;
}
const FriendLinkCategory: React.FC = () => {
const intl = useIntl();
const [loading, setLoading] = useState<boolean>(false);
const [modalVisible, setModalVisible] = useState<boolean>(false);
const [isEdit, setIsEdit] = useState<boolean>(false);
const [isAddChild, setIsAddChild] = useState<boolean>(false);
const [currentCategory, setCurrentCategory] = useState<CategoryType | null>(null);
const [categoryData, setCategoryData] = useState<CategoryType[]>([]);
const [form] = Form.useForm();
// 模拟分类数据
const mockCategories: CategoryType[] = [
{
id: '1',
name: '政府机构',
parentId: null,
level: 1,
sort: 1,
children: [
{
id: '1-1',
name: '中央部委',
parentId: '1',
level: 2,
sort: 1,
},
{
id: '1-2',
name: '地方政府',
parentId: '1',
level: 2,
sort: 2,
children: [
{
id: '1-2-1',
name: '省级政府',
parentId: '1-2',
level: 3,
sort: 1,
},
{
id: '1-2-2',
name: '市级政府',
parentId: '1-2',
level: 3,
sort: 2,
}
]
}
]
},
{
id: '2',
name: '港口集团',
parentId: null,
level: 1,
sort: 2,
children: [
{
id: '2-1',
name: '沿海港口',
parentId: '2',
level: 2,
sort: 1,
},
{
id: '2-2',
name: '内河港口',
parentId: '2',
level: 2,
sort: 2,
}
]
},
{
id: '3',
name: '航运企业',
parentId: null,
level: 1,
sort: 3,
}
];
// 获取分类列表
const fetchCategoryList = () => {
setLoading(true);
// 实际项目中应调用API
setTimeout(() => {
// 为每个节点添加key属性用于Table组件
const processData = (data: CategoryType[]): CategoryType[] => {
return data.map(item => {
const newItem = { ...item, key: item.id };
if (item.children && item.children.length > 0) {
newItem.children = processData(item.children);
}
return newItem;
});
};
const processedData = processData(mockCategories);
setCategoryData(processedData);
setLoading(false);
}, 500);
};
// 首次加载时获取数据
useEffect(() => {
fetchCategoryList();
}, []);
// 获取所有分类(扁平化)用于选择父分类
const getAllCategories = (categories: CategoryType[] = categoryData, result: CategoryType[] = []): CategoryType[] => {
categories.forEach(category => {
result.push(category);
if (category.children && category.children.length > 0) {
getAllCategories(category.children, result);
}
});
return result;
};
// 处理添加分类
const handleAddCategory = () => {
setIsEdit(false);
setIsAddChild(false);
setCurrentCategory(null);
form.resetFields();
setModalVisible(true);
};
// 处理添加子分类
const handleAddChildCategory = (record: CategoryType) => {
setIsEdit(false);
setIsAddChild(true);
setCurrentCategory(record);
form.resetFields();
form.setFieldsValue({
parentId: record.id,
});
setModalVisible(true);
};
// 处理编辑分类
const handleEditCategory = (record: CategoryType) => {
setIsEdit(true);
setIsAddChild(false);
setCurrentCategory(record);
form.setFieldsValue({
name: record.name,
parentId: record.parentId,
sort: record.sort,
});
setModalVisible(true);
};
// 处理删除分类
const handleDeleteCategory = (record: CategoryType) => {
// 检查是否有子分类
if (record.children && record.children.length > 0) {
message.error('该分类下有子分类,不能直接删除');
return;
}
Modal.confirm({
title: '删除分类',
icon: <ExclamationCircleOutlined />,
content: `确定要删除分类"${record.name}"吗?`,
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {
// 实际项目中应调用API
// 递归查找并删除分类
const deleteCategory = (data: CategoryType[], id: string): CategoryType[] => {
return data.filter(item => {
if (item.id === id) {
return false;
}
if (item.children && item.children.length > 0) {
item.children = deleteCategory(item.children, id);
}
return true;
});
};
const newData = deleteCategory(categoryData, record.id);
setCategoryData(newData);
message.success('删除成功');
},
});
};
// 处理表单提交
const handleModalSubmit = () => {
form.validateFields().then(values => {
// 准备提交数据
const formData = {
...values,
level: values.parentId ? (isAddChild ? currentCategory!.level + 1 : 2) : 1,
};
if (isEdit && currentCategory) {
// 编辑模式
// 递归更新分类
const updateCategory = (data: CategoryType[], id: string, newData: any): CategoryType[] => {
return data.map(item => {
if (item.id === id) {
return { ...item, ...newData };
}
if (item.children && item.children.length > 0) {
item.children = updateCategory(item.children, id, newData);
}
return item;
});
};
const newData = updateCategory(categoryData, currentCategory.id, formData);
setCategoryData(newData);
message.success('更新成功');
} else {
// 新增模式
const newId = isAddChild
? `${currentCategory!.id}-${Date.now().toString().substr(-4)}`
: (categoryData.length + 1).toString();
const newCategory: CategoryType = {
id: newId,
name: formData.name,
parentId: formData.parentId,
level: formData.level,
sort: formData.sort || 99,
key: newId,
};
if (formData.parentId) {
// 有父分类需要将新分类添加到父分类的children中
const addChildToParent = (data: CategoryType[], parentId: string, newChild: CategoryType): CategoryType[] => {
return data.map(item => {
if (item.id === parentId) {
if (!item.children) {
item.children = [];
}
item.children.push(newChild);
return item;
}
if (item.children && item.children.length > 0) {
item.children = addChildToParent(item.children, parentId, newChild);
}
return item;
});
};
const newData = addChildToParent(categoryData, formData.parentId, newCategory);
setCategoryData(newData);
} else {
// 无父分类,直接添加到顶级
setCategoryData([...categoryData, newCategory]);
}
message.success('添加成功');
}
setModalVisible(false);
form.resetFields();
});
};
// 表格列定义
const columns = [
{
title: '分类名称',
dataIndex: 'name',
key: 'name',
},
{
title: '层级',
dataIndex: 'level',
key: 'level',
width: 100,
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
width: 100,
sorter: (a: CategoryType, b: CategoryType) => a.sort - b.sort,
},
{
title: '操作',
key: 'operation',
width: 250,
render: (_: any, record: CategoryType) => (
<Space size="middle">
2025-06-18 14:37:42 +08:00
<Button type="link" onClick={() => handleAddChildCategory(record)}>
2025-06-17 21:06:27 +08:00
</Button>
2025-06-18 14:37:42 +08:00
<Button type="link" onClick={() => handleEditCategory(record)}>
2025-06-17 21:06:27 +08:00
</Button>
2025-06-18 14:37:42 +08:00
<Button type="link" onClick={() => handleDeleteCategory(record)}>
2025-06-17 21:06:27 +08:00
</Button>
</Space>
),
},
];
return (
<div className="friend-link-category-container common-container">
<div className="action-bar">
<Button type="primary" icon={<PlusOutlined />} onClick={handleAddCategory}>
</Button>
</div>
<div className='content-area'>
<Table
rowKey="id"
columns={columns}
dataSource={categoryData}
loading={loading}
pagination={false}
expandable={{
defaultExpandAllRows: true
}}
/>
</div>
{/* 新增/编辑分类模态框 */}
<Modal
title={isEdit ? '编辑分类' : (isAddChild ? '新增子分类' : '新增分类')}
visible={modalVisible}
onOk={handleModalSubmit}
onCancel={() => setModalVisible(false)}
destroyOnClose
>
<Form
form={form}
layout="vertical"
>
<Form.Item
name="name"
label="分类名称"
rules={[{ required: true, message: '请输入分类名称' }]}
>
<Input placeholder="请输入分类名称" />
</Form.Item>
<Form.Item
name="parentId"
label="父级分类"
rules={[{ required: isAddChild, message: '请选择父级分类' }]}
>
<TreeSelect
placeholder="请选择父级分类"
allowClear
treeData={categoryData.map(item => ({
title: item.name,
value: item.id,
disabled: isEdit && currentCategory ? (item.id === currentCategory.id || item.parentId === currentCategory.id) : false,
children: item.children?.map(child => ({
title: child.name,
value: child.id,
disabled: isEdit && currentCategory ? (child.id === currentCategory.id || child.parentId === currentCategory.id) : false,
children: child.children?.map(grandChild => ({
title: grandChild.name,
value: grandChild.id,
disabled: isEdit && currentCategory ? (grandChild.id === currentCategory.id || grandChild.parentId === currentCategory.id) : false,
}))
}))
}))}
disabled={isAddChild}
/>
</Form.Item>
<Form.Item
name="sort"
label="排序"
rules={[{ required: true, message: '请输入排序值' }]}
initialValue={99}
>
<Input type="number" placeholder="请输入排序值,数字越小越靠前" />
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default FriendLinkCategory;