feat:分类模块,单位模块完成
This commit is contained in:
288
src/pages/company/service/itemsManange/classify/index.jsx
Normal file
288
src/pages/company/service/itemsManange/classify/index.jsx
Normal file
@@ -0,0 +1,288 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Table, Button, Form, Input, Space, message, Popconfirm, Drawer, Select, Segmented, Badge } from 'antd';
|
||||
import { PlusOutlined, FileTextOutlined, ProjectOutlined, CheckSquareOutlined } from '@ant-design/icons';
|
||||
import { supabaseService } from '@/hooks/supabaseService';
|
||||
const Classify = ({activeType,typeList}) => {
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editingKey, setEditingKey] = useState('');
|
||||
const [form] = Form.useForm();
|
||||
const [filterType, setFilterType] = useState('all'); // 'all', 'common', 'current'
|
||||
|
||||
const fetchCategories = async (type = activeType, filterTypeValue = filterType) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
let filterCondition;
|
||||
|
||||
switch (filterTypeValue) {
|
||||
case 'common':
|
||||
filterCondition = { eq: 'common' };
|
||||
break;
|
||||
case 'current':
|
||||
filterCondition = { eq: type };
|
||||
break;
|
||||
default:
|
||||
filterCondition = { in: `(${type},common)` };
|
||||
}
|
||||
|
||||
const { data: categories } = await supabaseService.select('resources', {
|
||||
filter: {
|
||||
'type': { eq: 'categories' },
|
||||
'attributes->>template_type': filterCondition
|
||||
},
|
||||
order: {
|
||||
column: 'created_at',
|
||||
ascending: false
|
||||
}
|
||||
});
|
||||
|
||||
setData(categories || []);
|
||||
} catch (error) {
|
||||
message.error('获取分类数据失败');
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchCategories(activeType, filterType);
|
||||
}, [activeType]);
|
||||
|
||||
|
||||
// 新增分类
|
||||
const handleAdd = (type) => {
|
||||
const newData = {
|
||||
id: Date.now().toString(),
|
||||
attributes: {
|
||||
name: '',
|
||||
template_type: type
|
||||
},
|
||||
isNew: true
|
||||
};
|
||||
setData([newData, ...data]);
|
||||
setEditingKey(newData.id);
|
||||
form.setFieldsValue(newData.attributes);
|
||||
};
|
||||
|
||||
// 保存分类数据
|
||||
const handleSave = async (record) => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
if (record.isNew) {
|
||||
await supabaseService.insert('resources', {
|
||||
type: 'categories',
|
||||
attributes: {
|
||||
name: values.name,
|
||||
template_type: values.template_type
|
||||
},
|
||||
schema_version: 1
|
||||
});
|
||||
} else {
|
||||
await supabaseService.update('resources',
|
||||
{ id: record.id },
|
||||
{
|
||||
attributes: {
|
||||
name: values.name,
|
||||
template_type: values.template_type
|
||||
},
|
||||
updated_at: new Date().toISOString()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
message.success('保存成功');
|
||||
setEditingKey('');
|
||||
fetchCategories();
|
||||
} catch (error) {
|
||||
message.error('保存失败');
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 删除分类
|
||||
const handleDelete = async (record) => {
|
||||
try {
|
||||
await supabaseService.delete('resources', { id: record.id });
|
||||
message.success('删除成功');
|
||||
fetchCategories();
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '分类名称',
|
||||
dataIndex: ['attributes', 'name'],
|
||||
render: (text, record) => {
|
||||
const isEditing = record.id === editingKey;
|
||||
return isEditing ? (
|
||||
<Form.Item
|
||||
name="name"
|
||||
style={{ margin: 0 }}
|
||||
rules={[{ required: true, message: '请输入分类名称!' }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="请输入分类名称"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<span className="text-gray-700">{text}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '模板类型',
|
||||
dataIndex: ['attributes', 'template_type'],
|
||||
render: (text, record) => {
|
||||
const isEditing = record.id === editingKey;
|
||||
return isEditing ? (
|
||||
<Form.Item
|
||||
name="template_type"
|
||||
style={{ margin: 0 }}
|
||||
rules={[{ required: true, message: '请选择模板类型!' }]}
|
||||
>
|
||||
<Select
|
||||
options={typeList}
|
||||
placeholder="请选择模板类型"
|
||||
className="w-full rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<span className="text-gray-700 px-2 py-1 bg-gray-100 rounded-full text-sm">
|
||||
{typeList.find(t => t.value === text)?.label || text}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
render: (_, record) => {
|
||||
const isEditing = record.id === editingKey;
|
||||
return isEditing ? (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
className="text-green-600 hover:text-green-500 font-medium"
|
||||
onClick={() => handleSave(record)}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
className="text-gray-600 hover:text-gray-500 font-medium"
|
||||
onClick={() => {
|
||||
setEditingKey('');
|
||||
if (record.isNew) {
|
||||
setData(data.filter(item => item.id !== record.id));
|
||||
}
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
) : (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
className="text-blue-600 hover:text-blue-500 font-medium"
|
||||
disabled={editingKey !== ''}
|
||||
onClick={() => {
|
||||
setEditingKey(record.id);
|
||||
form.setFieldsValue({
|
||||
name: record.attributes.name,
|
||||
template_type: record.attributes.template_type
|
||||
});
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="确认删除"
|
||||
description="确定要删除这个分类吗?"
|
||||
onConfirm={() => handleDelete(record)}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
okButtonProps={{
|
||||
className: "bg-red-500 hover:bg-red-600 border-red-500"
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
className="text-red-600 hover:text-red-500 font-medium"
|
||||
disabled={editingKey !== ''}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-6 bg-gray-50">
|
||||
<div className="bg-white rounded-lg shadow-sm mb-6 p-4">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => handleAdd(activeType)}
|
||||
icon={<PlusOutlined />}
|
||||
className="bg-blue-600 hover:bg-blue-700 border-0 shadow-sm h-10"
|
||||
>
|
||||
新增分类
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Segmented
|
||||
value={filterType}
|
||||
onChange={(value) => {
|
||||
setFilterType(value);
|
||||
fetchCategories(activeType, value);
|
||||
}}
|
||||
options={[
|
||||
{
|
||||
label: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
{
|
||||
label: '仅当前类型',
|
||||
value: 'current',
|
||||
},
|
||||
{
|
||||
label: '仅通用类型',
|
||||
value: 'common',
|
||||
}
|
||||
]}
|
||||
className="bg-gray-50 p-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg shadow-sm">
|
||||
<Form form={form}>
|
||||
<Table
|
||||
scroll={{ x: true }}
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{
|
||||
pageSize: 10,
|
||||
showTotal: (total) => `共 ${total} 条`,
|
||||
className: "px-4"
|
||||
}}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Classify;
|
||||
Reference in New Issue
Block a user