240 lines
6.1 KiB
JavaScript
240 lines
6.1 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { Table, Button, Form, Input, Space, message, Popconfirm, Drawer } from 'antd';
|
|
import { PlusOutlined } from '@ant-design/icons';
|
|
import { supabase } from '@/config/supabase';
|
|
|
|
const CategoryDrawer = () => {
|
|
const [data, setData] = useState([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [editingKey, setEditingKey] = useState('');
|
|
const [drawerVisible, setDrawerVisible] = useState(false);
|
|
const [form] = Form.useForm();
|
|
|
|
// 获取分类数据
|
|
const fetchCategories = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const { data: categories, error } = await supabase
|
|
.from('resources')
|
|
.select('*')
|
|
.eq('type', 'categories')
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) throw error;
|
|
setData(categories || []);
|
|
} catch (error) {
|
|
message.error('获取分类数据失败');
|
|
console.error(error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (drawerVisible) {
|
|
fetchCategories();
|
|
}
|
|
}, [drawerVisible]);
|
|
|
|
// 新增分类
|
|
const handleAdd = () => {
|
|
const newData = {
|
|
id: Date.now().toString(),
|
|
attributes: { name: '' },
|
|
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) {
|
|
// 新增
|
|
const { error } = await supabase
|
|
.from('resources')
|
|
.insert([{
|
|
type: 'categories',
|
|
attributes: {
|
|
name: values.name
|
|
},
|
|
schema_version: 1
|
|
}]);
|
|
|
|
if (error) throw error;
|
|
} else {
|
|
// 更新
|
|
const { error } = await supabase
|
|
.from('resources')
|
|
.update({
|
|
attributes: {
|
|
name: values.name
|
|
},
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq('id', record.id);
|
|
|
|
if (error) throw error;
|
|
}
|
|
|
|
message.success('保存成功');
|
|
setEditingKey('');
|
|
fetchCategories();
|
|
} catch (error) {
|
|
message.error('保存失败');
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
// 删除分类
|
|
const handleDelete = async (record) => {
|
|
try {
|
|
const { error } = await supabase
|
|
.from('resources')
|
|
.delete()
|
|
.eq('id', record.id);
|
|
|
|
if (error) throw error;
|
|
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="请输入分类名称" />
|
|
</Form.Item>
|
|
) : (
|
|
<span className="text-gray-600">{text}</span>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: '操作',
|
|
render: (_, record) => {
|
|
const isEditing = record.id === editingKey;
|
|
return isEditing ? (
|
|
<Space>
|
|
<Button
|
|
type="link"
|
|
className="text-green-600 hover:text-green-500"
|
|
onClick={() => handleSave(record)}
|
|
>
|
|
保存
|
|
</Button>
|
|
<Button
|
|
type="link"
|
|
className="text-gray-600 hover:text-gray-500"
|
|
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"
|
|
disabled={editingKey !== ''}
|
|
onClick={() => {
|
|
setEditingKey(record.id);
|
|
form.setFieldsValue({
|
|
name: record.attributes.name,
|
|
});
|
|
}}
|
|
>
|
|
编辑
|
|
</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"
|
|
disabled={editingKey !== ''}
|
|
>
|
|
删除
|
|
</Button>
|
|
</Popconfirm>
|
|
</Space>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
type="primary"
|
|
onClick={() => setDrawerVisible(true)}
|
|
icon={<PlusOutlined />}
|
|
>
|
|
分类管理
|
|
</Button>
|
|
|
|
<Drawer
|
|
title="分类管理"
|
|
placement="right"
|
|
width={800}
|
|
onClose={() => setDrawerVisible(false)}
|
|
open={drawerVisible}
|
|
className="category-drawer"
|
|
>
|
|
<div className="p-6">
|
|
<Button
|
|
type="primary"
|
|
onClick={handleAdd}
|
|
className="mb-4"
|
|
icon={<PlusOutlined />}
|
|
>
|
|
新增分类
|
|
</Button>
|
|
<Form form={form}>
|
|
<Table
|
|
scroll={{ x: true }}
|
|
columns={columns}
|
|
dataSource={data}
|
|
rowKey="id"
|
|
loading={loading}
|
|
pagination={{
|
|
pageSize: 10,
|
|
showTotal: (total) => `共 ${total} 条`,
|
|
}}
|
|
className="bg-white rounded-lg shadow"
|
|
/>
|
|
</Form>
|
|
</div>
|
|
</Drawer>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default CategoryDrawer; |