黑暗模式 优化

This commit is contained in:
‘Liammcl’
2024-12-28 17:47:33 +08:00
parent b97cdd4685
commit 0942ed68ab
11 changed files with 239 additions and 124 deletions

View File

@@ -8,7 +8,7 @@ import {
message,
Popconfirm,
Select,
Segmented,
Divider,
InputNumber,
Card,
Typography
@@ -19,30 +19,22 @@ import { v4 as uuidv4 } from 'uuid';
const { Text } = Typography;
const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
const SectionsManagement = ({ activeType = 'quotation' }) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [editingKey, setEditingKey] = useState('');
const [form] = Form.useForm();
const [filterType, setFilterType] = useState('all');
const fetchSections = async (type = activeType, filterTypeValue = filterType) => {
const [loadingUnits,setLoadingUnits]=useState(false)
const [units,setUnit]=useState([])
const [formValues, setFormValues] = useState({});
const fetchSections = async () => {
setLoading(true);
try {
let filterCondition;
switch (filterTypeValue) {
case 'current':
filterCondition = { eq: type };
break;
default:
filterCondition = { eq: type };
}
const { data: sections } = await supabaseService.select('resources', {
filter: {
'type': { eq: 'sections' },
'attributes->>template_type': filterCondition
'attributes->>template_type': {eq:activeType}
},
order: {
column: 'created_at',
@@ -58,9 +50,30 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
setLoading(false);
}
};
const fetchUnits = async () => {
setLoadingUnits(true);
try {
const { data: units } = await supabaseService.select("resources", {
filter: {
type: { eq: "units" },
"attributes->>template_type": { in: `(${activeType},common)` },
},
order: {
column: "created_at",
ascending: false,
},
});
setUnit(units || []);
} catch (error) {
message.error("获取单位列表失败");
console.error(error);
} finally {
setLoadingUnits(false);
}
};
useEffect(() => {
fetchSections(activeType, filterType);
fetchSections();
}, [activeType]);
const handleAdd = () => {
@@ -139,7 +152,32 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
console.error(error);
}
};
const handleAddUnit = async (unitName) => {
try {
const { error } = await supabase.from("resources").insert([
{
type: "units",
attributes: {
name: unitName,
template_type: activeType,
},
schema_version: 1,
},
]);
if (error) throw error;
message.success("新增单位成功");
fetchUnits();
return true;
} catch (error) {
message.error("新增单位失败");
console.error(error);
return false;
}
};
const handleValuesChange = (changedValues, allValues) => {
setFormValues(allValues);
};
const columns = [
{
title: '模块名称',
@@ -155,11 +193,10 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
>
<Input
placeholder="请输入模块名称"
className="rounded-md"
/>
</Form.Item>
) : (
<span className="text-gray-700 font-medium">{text}</span>
<span className=" font-medium">{text}</span>
);
},
},
@@ -168,61 +205,114 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
dataIndex: ['attributes', 'items'],
render: (items, record) => {
const isEditing = record.id === editingKey;
if (isEditing) {
return (
<Form.List name="items">
{(fields, { add, remove }) => (
<div className="space-y-2">
{fields.map((field, index) => (
<Card key={field.key} size="small" className="bg-gray-50">
<div className="grid grid-cols-6 gap-2">
<Form.Item
{...field}
name={[field.name, 'name']}
className="col-span-2 mb-0"
>
<Input placeholder="项目名称" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'unit']}
className="mb-0"
>
<Input placeholder="单位" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'quantity']}
className="mb-0"
>
<InputNumber
placeholder="数量"
min={0}
className="w-full"
{fields.map((field, index) => {
const items = formValues.items || [];
const currentItem = items[field.name] || {};
const subtotal = (currentItem.quantity || 0) * (currentItem.price || 0);
return (
<Card key={field.key} size="small" className="bg-gray-50 dark:bg-gray-600 ">
<div className="grid grid-cols-6 gap-2">
<Form.Item
{...field}
name={[field.name, 'name']}
className="col-span-2 mb-0"
>
<Input placeholder="项目名称" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'unit']}
className="mb-0"
>
<Select
placeholder="选择单位"
loading={loadingUnits}
showSearch
allowClear
style={{ minWidth: "120px" }}
options={units.map((unit) => ({
label: unit.attributes.name,
value: unit.attributes.name,
}))}
onDropdownVisibleChange={(open) => {
if (open) fetchUnits();
}}
dropdownRender={(menu) => (
<>
{menu}
<Divider style={{ margin: "12px 0" }} />
<div style={{ padding: "4px" }}>
<Input.Search
placeholder="输入新单位名称"
enterButton={<PlusOutlined />}
onSearch={async (value) => {
if (!value.trim()) return;
if (
await handleAddUnit(value.trim())
) {
const currentItems =
form.getFieldValue([
"sections",
field.name,
"items",
]);
currentItems[itemField.name].unit =
value.trim();
form.setFieldValue(
["sections", field.name, "items"],
currentItems
);
}
}}
/>
</div>
</>
)}
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'quantity']}
className="mb-0"
>
<InputNumber
placeholder="数量"
min={0}
className="w-full"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'price']}
className="mb-0"
>
<InputNumber
placeholder="单价 (NT$)"
min={0}
className="w-full"
prefix="NT$"
/>
</Form.Item>
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => remove(field.name)}
className="flex items-center justify-center"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'price']}
className="mb-0"
>
<InputNumber
placeholder="单价"
min={0}
className="w-full"
/>
</Form.Item>
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => remove(field.name)}
className="flex items-center justify-center"
/>
</div>
</Card>
))}
</div>
<div className="flex items-center">
<Text type="secondary">小计: NT${subtotal.toLocaleString()}</Text>
</div>
</Card>
);
})}
<Button
type="dashed"
onClick={() => add({
@@ -241,17 +331,24 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
</Form.List>
);
}
// 计算总金额
const total = (items || []).reduce((sum, item) => {
return sum + (item.quantity * item.price || 0);
}, 0);
return (
<div className="space-y-1">
<div>
{(items || []).map((item, index) => (
<div key={index} className="flex justify-between text-sm">
<span className="text-gray-600">{item.name}</span>
<span className="text-gray-500">
{item.quantity} {item.unit} × ¥{item.price}
<div key={index} className="flex justify-start text-sm">
<span >{item.name}</span>
<span className=" ml-2">
{item.quantity} {item.unit} × NT${item.price.toLocaleString()}
</span>
</div>
))}
<Divider className="my-2" />
<Text strong>总金额: NT${total.toLocaleString()}</Text>
</div>
);
},
@@ -325,8 +422,8 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
];
return (
<div className="p-6 bg-gray-50">
<div className="bg-white rounded-lg shadow-sm mb-6 p-4">
<div className="p-6 ">
<div className=" 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
@@ -341,8 +438,11 @@ const SectionsManagement = ({ activeType = 'quotation', typeList }) => {
</div>
</div>
<div className="bg-white rounded-lg shadow-sm">
<Form form={form}>
<div className=" rounded-lg shadow-sm">
<Form
form={form}
onValuesChange={handleValuesChange}
>
<Table
scroll={{ x: 1200 }}
columns={columns}