jch-config-editor 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,542 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useEffect, useState } from "react";
3
- import { Form, Input, InputNumber, Select, Switch, Collapse, Button, Empty, Tabs, Space, Divider, ColorPicker, Tag, Modal, } from "antd";
4
- import { PlusOutlined, DeleteOutlined, ArrowUpOutlined, ArrowDownOutlined, CopyOutlined, EditOutlined, } from "@ant-design/icons";
5
- import { useEditorStore } from "../../store/editorStore";
6
- import { nanoid } from "nanoid";
7
- const { Panel } = Collapse;
8
- const { TabPane } = Tabs;
9
- const { Option } = Select;
10
- const { TextArea } = Input;
11
- // TEXT 物料编辑器
12
- const TextMaterialEditor = ({ material, onSave, bindCodes = [], dataOptions = [], }) => {
13
- const textMaterial = material;
14
- const content = textMaterial.content || {};
15
- const [formData, setFormData] = useState({
16
- label: content.label || "",
17
- value: content.value || "",
18
- valueSourceCode: content.valueSourceCode || "",
19
- unit: content.unit || "",
20
- decimals: content.decimals ?? 2,
21
- labelFontSize: content.labelStyle?.fontSize || 14,
22
- labelFontWeight: content.labelStyle?.fontWeight || "bold",
23
- labelColor: content.labelStyle?.color || "#262626",
24
- valueFontSize: content.valueStyle?.fontSize || 14,
25
- valueFontWeight: content.valueStyle?.fontWeight || "normal",
26
- valueColor: content.valueStyle?.color || "#1890ff",
27
- });
28
- useEffect(() => {
29
- setFormData({
30
- label: content.label || "",
31
- value: content.value || "",
32
- valueSourceCode: content.valueSourceCode || "",
33
- unit: content.unit || "",
34
- decimals: content.decimals ?? 2,
35
- labelFontSize: content.labelStyle?.fontSize || 14,
36
- labelFontWeight: content.labelStyle?.fontWeight || "bold",
37
- labelColor: content.labelStyle?.color || "#262626",
38
- valueFontSize: content.valueStyle?.fontSize || 14,
39
- valueFontWeight: content.valueStyle?.fontWeight || "normal",
40
- valueColor: content.valueStyle?.color || "#1890ff",
41
- });
42
- }, [material.id]);
43
- const handleChange = (field, value) => {
44
- setFormData((prev) => ({ ...prev, [field]: value }));
45
- };
46
- // 当选择值来源时,自动从数据选项中获取单位
47
- const handleValueSourceChange = (code) => {
48
- const selectedOption = dataOptions.find((opt) => opt.paramsCode === code);
49
- const autoUnit = selectedOption?.paramsUnit || "";
50
- setFormData((prev) => ({
51
- ...prev,
52
- valueSourceCode: code,
53
- unit: autoUnit,
54
- value: selectedOption?.["value"] || "",
55
- }));
56
- // 延迟保存以确保状态更新
57
- setTimeout(() => {
58
- onSave({
59
- content: {
60
- ...content,
61
- valueSourceCode: code,
62
- value: selectedOption?.["value"] || "",
63
- unit: autoUnit,
64
- },
65
- });
66
- }, 0);
67
- };
68
- const handleSave = () => {
69
- onSave({
70
- content: {
71
- ...content,
72
- label: formData.label,
73
- value: formData.value,
74
- valueSourceCode: formData.valueSourceCode,
75
- unit: formData.unit,
76
- decimals: formData.decimals,
77
- labelStyle: {
78
- fontSize: formData.labelFontSize,
79
- fontWeight: formData.labelFontWeight,
80
- color: formData.labelColor,
81
- },
82
- valueStyle: {
83
- fontSize: formData.valueFontSize,
84
- fontWeight: formData.valueFontWeight,
85
- color: formData.valueColor,
86
- },
87
- },
88
- });
89
- };
90
- // 筛选出已绑定的数据选项
91
- const boundDataOptions = dataOptions.filter((opt) => bindCodes.includes(opt.paramsCode));
92
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(Divider, { style: { marginTop: 0 }, children: "\u6587\u672C\u5185\u5BB9" }), _jsxs(Form, { layout: "vertical", children: [_jsx(Form.Item, { label: "\u6807\u7B7E\u6587\u672C (label)", children: _jsx(Input, { value: formData.label, onChange: (e) => handleChange("label", e.target.value), onBlur: handleSave, placeholder: "\u8F93\u5165\u6807\u7B7E\u6587\u672C" }) }), _jsx(Form.Item, { label: "\u503C\u6765\u6E90", help: "\u4ECE\u7ED1\u5B9A\u7684\u6570\u636E\u4E2D\u9009\u62E9\u5B57\u6BB5\uFF0C\u4F18\u5148\u7EA7\u9AD8\u4E8E\u624B\u52A8\u8F93\u5165\u7684\u503C", children: _jsx(Select, { value: formData.valueSourceCode || undefined, onChange: handleValueSourceChange, placeholder: "\u9009\u62E9\u6570\u636E\u5B57\u6BB5\uFF08\u53EF\u9009\uFF09", allowClear: true, style: { width: "100%" }, fieldNames: {
93
- value: "paramsCode",
94
- label: "paramsName",
95
- }, options: boundDataOptions }) }), _jsx(Form.Item, { label: formData.valueSourceCode ? "默认值(备用)" : "值文本", help: formData.valueSourceCode
96
- ? "已绑定数据源,实际值将来自数据字段,此处仅设置无数据时的备用显示"
97
- : "手动输入显示的值", children: _jsx(Input, { value: formData.value, onChange: (e) => handleChange("value", e.target.value), onBlur: handleSave, placeholder: formData.valueSourceCode
98
- ? "数据字段无值时显示此备用值"
99
- : "输入值文本", disabled: !!formData.valueSourceCode, variant: formData.valueSourceCode ? "filled" : undefined }) }), _jsx(Form.Item, { label: "\u5355\u4F4D", help: "\u4F18\u5148\u4ECE\u7ED1\u5B9A\u6570\u636E\u81EA\u52A8\u83B7\u53D6\uFF0C\u4E5F\u53EF\u624B\u52A8\u8F93\u5165", children: _jsx(Input, { value: formData.unit, onChange: (e) => handleChange("unit", e.target.value), onBlur: handleSave, placeholder: "\u5355\u4F4D\uFF08\u5982\u00B0C\u3001%\u3001MPa\u7B49\uFF09", suffix: formData.valueSourceCode && boundDataOptions.length > 0 ? (_jsx(Tag, { color: "blue", style: { marginRight: -8 }, children: "\u81EA\u52A8" })) : null }) }), _jsx(Form.Item, { label: "\u4FDD\u7559\u5C0F\u6570\u4F4D", help: "\u6570\u503C\u683C\u5F0F\u5316\u65F6\u4FDD\u7559\u7684\u5C0F\u6570\u4F4D\u6570\uFF0C-1\u8868\u793A\u4E0D\u683C\u5F0F\u5316", children: _jsx(InputNumber, { value: formData.decimals, onChange: (v) => handleChange("decimals", v ?? 2), onBlur: handleSave, min: -1, max: 10, style: { width: "100%" } }) })] }), _jsx(Divider, { children: "\u6807\u7B7E\u6837\u5F0F" }), _jsxs(Form, { layout: "vertical", children: [_jsxs(Space, { children: [_jsx(Form.Item, { label: "\u5B57\u4F53\u5927\u5C0F", children: _jsx(InputNumber, { value: formData.labelFontSize, onChange: (v) => handleChange("labelFontSize", v || 14), onBlur: handleSave, min: 8, max: 72 }) }), _jsx(Form.Item, { label: "\u5B57\u4F53\u7C97\u7EC6", children: _jsxs(Select, { value: formData.labelFontWeight, onChange: (v) => {
100
- handleChange("labelFontWeight", v);
101
- setTimeout(handleSave, 0);
102
- }, style: { width: 100 }, children: [_jsx(Option, { value: "normal", children: "\u6B63\u5E38" }), _jsx(Option, { value: "bold", children: "\u7C97\u4F53" })] }) })] }), _jsx(Form.Item, { label: "\u6587\u5B57\u989C\u8272", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ColorPicker, { value: formData.labelColor, onChange: (color) => handleChange("labelColor", color.toHexString()), onChangeComplete: () => handleSave() }), _jsx(Input, { value: formData.labelColor, onChange: (e) => handleChange("labelColor", e.target.value), onBlur: handleSave, placeholder: "#262626", style: { width: 100 } })] }) })] }), _jsx(Divider, { children: "\u503C\u6837\u5F0F" }), _jsxs(Form, { layout: "vertical", children: [_jsxs(Space, { children: [_jsx(Form.Item, { label: "\u5B57\u4F53\u5927\u5C0F", children: _jsx(InputNumber, { value: formData.valueFontSize, onChange: (v) => handleChange("valueFontSize", v || 14), onBlur: handleSave, min: 8, max: 72 }) }), _jsx(Form.Item, { label: "\u5B57\u4F53\u7C97\u7EC6", children: _jsxs(Select, { value: formData.valueFontWeight, onChange: (v) => {
103
- handleChange("valueFontWeight", v);
104
- setTimeout(handleSave, 0);
105
- }, style: { width: 100 }, children: [_jsx(Option, { value: "normal", children: "\u6B63\u5E38" }), _jsx(Option, { value: "bold", children: "\u7C97\u4F53" })] }) })] }), _jsx(Form.Item, { label: "\u6587\u5B57\u989C\u8272", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ColorPicker, { value: formData.valueColor, onChange: (color) => handleChange("valueColor", color.toHexString()), onChangeComplete: () => handleSave() }), _jsx(Input, { value: formData.valueColor, onChange: (e) => handleChange("valueColor", e.target.value), onBlur: handleSave, placeholder: "#1890ff", style: { width: 100 } })] }) })] })] }));
106
- };
107
- // IMAGE 物料编辑器
108
- const ImageMaterialEditor = ({ material, onSave, }) => {
109
- const [formData, setFormData] = useState({
110
- name: material.name,
111
- src: material.src || "",
112
- });
113
- useEffect(() => {
114
- setFormData({
115
- name: material.name,
116
- src: material.src || "",
117
- });
118
- }, [material.id]);
119
- const handleChange = (field, value) => {
120
- setFormData((prev) => ({ ...prev, [field]: value }));
121
- };
122
- const handleSave = () => {
123
- onSave({
124
- name: formData.name,
125
- src: formData.src,
126
- });
127
- };
128
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(Divider, { style: { marginTop: 0 }, children: "\u56FE\u7247\u5C5E\u6027" }), _jsxs(Form, { layout: "vertical", children: [_jsx(Form.Item, { label: "\u56FE\u7247\u540D\u79F0", children: _jsx(Input, { value: formData.name, onChange: (e) => handleChange("name", e.target.value), onBlur: handleSave }) }), _jsx(Form.Item, { label: "\u56FE\u7247\u5730\u5740 (src)", children: _jsx(TextArea, { value: formData.src, onChange: (e) => handleChange("src", e.target.value), onBlur: handleSave, rows: 4, placeholder: "\u8F93\u5165\u56FE\u7247 URL \u6216 Data URI" }) })] })] }));
129
- };
130
- // LINE 物料编辑器
131
- const LineMaterialEditor = ({ material, onSave, }) => {
132
- const lineConfig = material.config || {};
133
- const [formData, setFormData] = useState({
134
- lineWeight: lineConfig.lineWeight || lineConfig.thickness || 2,
135
- color: lineConfig.color || "#262626",
136
- lineType: lineConfig.lineType || "solid",
137
- startX: lineConfig.startX ?? 0,
138
- startY: lineConfig.startY ?? 0,
139
- endX: lineConfig.endX ?? 100,
140
- endY: lineConfig.endY ?? 0,
141
- });
142
- useEffect(() => {
143
- setFormData({
144
- lineWeight: lineConfig.lineWeight || lineConfig.thickness || 2,
145
- color: lineConfig.color || "#262626",
146
- lineType: lineConfig.lineType || "solid",
147
- startX: lineConfig.startX ?? 0,
148
- startY: lineConfig.startY ?? 0,
149
- endX: lineConfig.endX ?? 100,
150
- endY: lineConfig.endY ?? 0,
151
- });
152
- }, [material.id]);
153
- // 立即保存,使用新的配置值
154
- const handleSaveWithValues = (newValues) => {
155
- const newFormData = { ...formData, ...newValues };
156
- setFormData(newFormData);
157
- // 保留原有配置,更新所有属性
158
- onSave({
159
- config: {
160
- ...lineConfig,
161
- thickness: newFormData.lineWeight,
162
- lineWeight: newFormData.lineWeight,
163
- color: newFormData.color,
164
- lineType: newFormData.lineType,
165
- startX: newFormData.startX,
166
- startY: newFormData.startY,
167
- endX: newFormData.endX,
168
- endY: newFormData.endY,
169
- },
170
- });
171
- };
172
- // 线型选项
173
- const lineTypeOptions = [
174
- { value: "solid", label: "实线", desc: "连续实线" },
175
- { value: "dashed", label: "虚线", desc: "长划间隔" },
176
- { value: "center", label: "点画线(中心线)", desc: "长点-短点交替" },
177
- { value: "phantom", label: "假想线", desc: "长划-双点交替" },
178
- { value: "dot", label: "点线", desc: "密集点状" },
179
- { value: "dash-dot", label: "画点线", desc: "长划-点交替" },
180
- ];
181
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(Divider, { style: { marginTop: 0 }, children: "\u7EBF\u6761\u5C5E\u6027" }), _jsxs(Form, { layout: "vertical", children: [_jsx(Form.Item, { label: "\u7EBF\u578B", help: "\u9009\u62E9\u7EBF\u6761\u6837\u5F0F", children: _jsx(Select, { value: formData.lineType, onChange: (v) => handleSaveWithValues({ lineType: v }), children: lineTypeOptions.map((opt) => (_jsx(Option, { value: opt.value, children: _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { children: opt.label }), _jsx("span", { className: "text-xs text-gray-400", children: opt.desc })] }) }, opt.value))) }) }), _jsx(Form.Item, { label: "\u7EBF\u5BBD\uFF08\u50CF\u7D20\uFF09", children: _jsx(InputNumber, { value: formData.lineWeight, onChange: (v) => handleSaveWithValues({ lineWeight: v || 2 }), min: 1, max: 20, style: { width: 120 } }) }), _jsx(Form.Item, { label: "\u989C\u8272", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ColorPicker, { value: formData.color, onChange: (color) => handleSaveWithValues({ color: color.toHexString() }) }), _jsx(Input, { value: formData.color, onChange: (e) => handleSaveWithValues({ color: e.target.value }), placeholder: "#d9d9d9", style: { width: 100 } })] }) })] }), _jsx(Divider, { children: "\u8D77\u6B62\u4F4D\u7F6E\uFF08\u76F8\u5BF9\u8282\u70B9\uFF09" }), _jsxs(Form, { layout: "vertical", children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(Form.Item, { label: "\u8D77\u70B9 X", className: "mb-2", children: _jsx(InputNumber, { value: formData.startX, onChange: (v) => handleSaveWithValues({ startX: v ?? 0 }), style: { width: '100%' } }) }), _jsx(Form.Item, { label: "\u8D77\u70B9 Y", className: "mb-2", children: _jsx(InputNumber, { value: formData.startY, onChange: (v) => handleSaveWithValues({ startY: v ?? 0 }), style: { width: '100%' } }) }), _jsx(Form.Item, { label: "\u7EC8\u70B9 X", className: "mb-2", children: _jsx(InputNumber, { value: formData.endX, onChange: (v) => handleSaveWithValues({ endX: v ?? 100 }), style: { width: '100%' } }) }), _jsx(Form.Item, { label: "\u7EC8\u70B9 Y", className: "mb-2", children: _jsx(InputNumber, { value: formData.endY, onChange: (v) => handleSaveWithValues({ endY: v ?? 0 }), style: { width: '100%' } }) })] }), _jsx(Form.Item, { label: "\u5FEB\u901F\u5BF9\u9F50", className: "mt-4", children: _jsxs(Space, { children: [_jsx(Button, { size: "small", onClick: () => {
182
- // 水平对齐:保持起点不变,终点Y与起点相同
183
- handleSaveWithValues({ endY: formData.startY });
184
- }, title: "\u5C06\u7EBF\u6761\u53D8\u4E3A\u6C34\u5E73\u7EBF", children: "\u6C34\u5E73" }), _jsx(Button, { size: "small", onClick: () => {
185
- // 垂直对齐:保持起点不变,终点X与起点相同
186
- handleSaveWithValues({ endX: formData.startX });
187
- }, title: "\u5C06\u7EBF\u6761\u53D8\u4E3A\u5782\u76F4\u7EBF", children: "\u5782\u76F4" }), _jsx(Button, { size: "small", onClick: () => {
188
- // 交换起点和终点
189
- handleSaveWithValues({
190
- startX: formData.endX,
191
- startY: formData.endY,
192
- endX: formData.startX,
193
- endY: formData.startY,
194
- });
195
- }, title: "\u4EA4\u6362\u8D77\u70B9\u548C\u7EC8\u70B9", children: "\u53CD\u5411" })] }) })] })] }));
196
- };
197
- const GroupNodeStatusEditor = ({ node, updateNode, materials, }) => {
198
- // 获取可用的物料列表(排除群组类型)
199
- const availableMaterials = materials.filter(m => m.type !== 'CUSTOM' || !m.config?.nodes);
200
- // 更新子节点的状态列表
201
- const handleUpdateChildStatusList = (childId, newStatusList) => {
202
- const newChildren = node.children?.map(child => {
203
- if (child.id === childId) {
204
- return {
205
- ...child,
206
- contentInfo: {
207
- ...child.contentInfo,
208
- statusList: newStatusList,
209
- },
210
- };
211
- }
212
- return child;
213
- });
214
- updateNode(node.id, {
215
- children: newChildren,
216
- });
217
- };
218
- // 添加状态到子节点
219
- const handleAddChildStatus = (childId) => {
220
- const child = node.children?.find(c => c.id === childId);
221
- if (!child)
222
- return;
223
- const newStatus = {
224
- id: nanoid(),
225
- name: `状态${child.contentInfo.statusList.length + 1}`,
226
- expression: child.contentInfo.statusList.length === 0 ? 'return true;' : 'return false;',
227
- material: { ...availableMaterials[0], id: nanoid() },
228
- bindCodes: [],
229
- };
230
- handleUpdateChildStatusList(childId, [...child.contentInfo.statusList, newStatus]);
231
- };
232
- // 删除子节点的状态
233
- const handleDeleteChildStatus = (childId, statusId) => {
234
- const child = node.children?.find(c => c.id === childId);
235
- if (!child)
236
- return;
237
- const newStatusList = child.contentInfo.statusList.filter(s => s.id !== statusId);
238
- handleUpdateChildStatusList(childId, newStatusList);
239
- };
240
- // 更新子节点的某个状态
241
- const handleUpdateChildStatus = (childId, statusId, updates) => {
242
- const child = node.children?.find(c => c.id === childId);
243
- if (!child)
244
- return;
245
- const newStatusList = child.contentInfo.statusList.map(s => {
246
- if (s.id === statusId) {
247
- return { ...s, ...updates };
248
- }
249
- return s;
250
- });
251
- handleUpdateChildStatusList(childId, newStatusList);
252
- };
253
- // 移动子节点状态
254
- const handleMoveChildStatus = (childId, statusId, direction) => {
255
- const child = node.children?.find(c => c.id === childId);
256
- if (!child)
257
- return;
258
- const index = child.contentInfo.statusList.findIndex(s => s.id === statusId);
259
- if (index === -1)
260
- return;
261
- const newStatusList = [...child.contentInfo.statusList];
262
- if (direction === 'up' && index > 0) {
263
- [newStatusList[index], newStatusList[index - 1]] = [newStatusList[index - 1], newStatusList[index]];
264
- }
265
- else if (direction === 'down' && index < newStatusList.length - 1) {
266
- [newStatusList[index], newStatusList[index + 1]] = [newStatusList[index + 1], newStatusList[index]];
267
- }
268
- handleUpdateChildStatusList(childId, newStatusList);
269
- };
270
- // 更换子节点状态的物料
271
- const handleChangeChildStatusMaterial = (childId, statusId, materialId) => {
272
- const selectedMaterial = materials.find(m => m.id === materialId);
273
- if (!selectedMaterial)
274
- return;
275
- handleUpdateChildStatus(childId, statusId, {
276
- material: { ...selectedMaterial, id: nanoid() },
277
- });
278
- };
279
- return (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg mb-4", children: _jsxs("div", { className: "text-sm text-blue-700", children: [_jsx("strong", { children: "\u7FA4\u7EC4\u8282\u70B9" }), "\uFF1A\u4E3A\u6BCF\u4E2A\u5B50\u8282\u70B9\u914D\u7F6E\u591A\u4E2A\u72B6\u6001\u548C\u7ED1\u5B9A"] }) }), _jsx(Collapse, { ghost: true, children: node.children?.map((child, childIndex) => (_jsx(Panel, { header: _jsxs("div", { className: "flex items-center justify-between w-full pr-4", children: [_jsxs("span", { className: "font-medium text-sm", children: ["\u5B50\u8282\u70B9 ", childIndex + 1] }), _jsxs(Tag, { color: "blue", style: { fontSize: '12px', padding: '0 4px' }, children: [child.contentInfo.statusList.length, " \u4E2A\u72B6\u6001"] })] }), children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex justify-between items-center mb-3", children: [_jsx("span", { className: "text-sm text-gray-600", children: "\u72B6\u6001\u5217\u8868" }), _jsx(Button, { type: "primary", size: "small", icon: _jsx(PlusOutlined, {}), onClick: () => handleAddChildStatus(child.id), children: "\u6DFB\u52A0\u72B6\u6001" })] }), child.contentInfo.statusList.length === 0 ? (_jsx("div", { className: "text-center text-gray-400 py-4 bg-gray-50 rounded-lg", children: "\u6682\u65E0\u72B6\u6001\uFF0C\u70B9\u51FB\u4E0A\u65B9\u6309\u94AE\u6DFB\u52A0" })) : (_jsx(Collapse, { ghost: true, children: child.contentInfo.statusList.map((status, statusIndex) => (_jsx(Panel, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-gray-400 w-5", children: statusIndex + 1 }), _jsx("span", { className: "font-medium", children: status.name }), _jsx(Tag, { color: "default", className: "text-xs", children: status.material.type })] }), extra: _jsxs(Space, { size: "small", onClick: (e) => e.stopPropagation(), children: [_jsx(Button, { type: "text", size: "small", icon: _jsx(ArrowUpOutlined, {}), disabled: statusIndex === 0, onClick: (e) => {
280
- e.stopPropagation();
281
- handleMoveChildStatus(child.id, status.id, 'up');
282
- } }), _jsx(Button, { type: "text", size: "small", icon: _jsx(ArrowDownOutlined, {}), disabled: statusIndex === child.contentInfo.statusList.length - 1, onClick: (e) => {
283
- e.stopPropagation();
284
- handleMoveChildStatus(child.id, status.id, 'down');
285
- } }), _jsx(Button, { type: "text", size: "small", danger: true, icon: _jsx(DeleteOutlined, {}), onClick: (e) => {
286
- e.stopPropagation();
287
- handleDeleteChildStatus(child.id, status.id);
288
- } })] }), children: _jsxs(Form, { layout: "vertical", children: [_jsx(Form.Item, { label: "\u72B6\u6001\u540D\u79F0", children: _jsx(Input, { value: status.name, onChange: (e) => handleUpdateChildStatus(child.id, status.id, { name: e.target.value }), placeholder: "\u8F93\u5165\u72B6\u6001\u540D\u79F0" }) }), _jsx(Form.Item, { label: "\u6267\u884C\u8868\u8FBE\u5F0F", help: "\u8FD4\u56DE true \u65F6\u6FC0\u6D3B\u6B64\u72B6\u6001\uFF0C\u53EF\u4F7F\u7528 data \u53D8\u91CF\u8BBF\u95EE\u7ED1\u5B9A\u6570\u636E", children: _jsx(TextArea, { value: status.expression, onChange: (e) => handleUpdateChildStatus(child.id, status.id, { expression: e.target.value }), rows: 3, placeholder: "return true;" }) }), _jsx(Form.Item, { label: "\u7ED1\u5B9A\u6570\u636E\u6E90 (bindCodes)", children: _jsx(Select, { mode: "tags", value: status.bindCodes || [], onChange: (value) => handleUpdateChildStatus(child.id, status.id, { bindCodes: value }), placeholder: "\u8F93\u5165\u6570\u636E\u6E90 code", tokenSeparators: [",", " "] }) }), _jsx(Form.Item, { label: "\u66F4\u6362\u7269\u6599", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { color: "blue", children: status.material.name }), _jsx(Tag, { color: "default", children: status.material.type }), _jsx(Select, { placeholder: "\u9009\u62E9\u65B0\u7269\u6599", style: { width: 150 }, value: undefined, onChange: (value) => value && handleChangeChildStatusMaterial(child.id, status.id, value), options: availableMaterials.map(m => ({
289
- value: m.id,
290
- label: `${m.name} (${m.type})`,
291
- })) })] }) }), _jsx(Divider, { style: { margin: '12px 0' } }), _jsxs("div", { className: "bg-gray-50 rounded-lg p-3 border border-gray-200", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u7269\u6599\u5C5E\u6027" }), _jsx(Tag, { children: status.material.name })] }), _jsx(MaterialPropertyEditor, { material: status.material, onSave: (updates) => {
292
- const newMaterial = { ...status.material, ...updates };
293
- handleUpdateChildStatus(child.id, status.id, { material: newMaterial });
294
- } })] })] }) }, status.id))) }))] }) }, child.id))) })] }));
295
- };
296
- // 统一的物料编辑器
297
- const MaterialPropertyEditor = ({ material, onSave, bindCodes, dataOptions, }) => {
298
- switch (material.type) {
299
- case "TEXT":
300
- return (_jsx(TextMaterialEditor, { material: material, onSave: onSave, bindCodes: bindCodes, dataOptions: dataOptions }));
301
- case "IMAGE":
302
- return _jsx(ImageMaterialEditor, { material: material, onSave: onSave });
303
- case "LINE":
304
- return _jsx(LineMaterialEditor, { material: material, onSave: onSave });
305
- default:
306
- return (_jsx("div", { className: "text-center text-gray-400 py-8", children: "\u6682\u4E0D\u652F\u6301\u7F16\u8F91\u6B64\u7C7B\u578B\u7684\u7269\u6599" }));
307
- }
308
- };
309
- // ==================== 主面板组件 ====================
310
- export const PropertyPanel = ({ defaultTestData, }) => {
311
- const { nodes, selectedNodeId, updateNode, updateNodeStyle, updateNodeControl, updateNodeContent, materials, // 物料库,用于创建状态时选择物料
312
- addStatus, removeStatus, updateStatus, selectedStatusId, selectStatus, } = useEditorStore();
313
- const [form] = Form.useForm();
314
- const [activeTab, setActiveTab] = useState("basic");
315
- const [materialModalVisible, setMaterialModalVisible] = useState(false);
316
- const [editingStatusId, setEditingStatusId] = useState(null);
317
- const [editingExpressions, setEditingExpressions] = useState({});
318
- // 使用 useMemo 获取选中的节点
319
- const selectedNode = React.useMemo(() => {
320
- return nodes.find((n) => n.id === selectedNodeId);
321
- }, [nodes, selectedNodeId]);
322
- // 获取当前节点的状态列表
323
- const currentStatusList = selectedNode?.contentInfo.statusList || [];
324
- // 获取当前选中的状态
325
- const selectedStatus = React.useMemo(() => {
326
- if (!selectedNode || !selectedStatusId)
327
- return null;
328
- return (selectedNode.contentInfo.statusList.find((s) => s.id === selectedStatusId) || null);
329
- }, [selectedNode, selectedStatusId]);
330
- // 表单值变化时更新节点
331
- const handleValuesChange = (changedValues, _allValues) => {
332
- if (!selectedNodeId)
333
- return;
334
- if (changedValues.normalStyle) {
335
- updateNodeStyle(selectedNodeId, changedValues.normalStyle);
336
- }
337
- if (changedValues.name !== undefined) {
338
- updateNode(selectedNodeId, { name: changedValues.name });
339
- }
340
- if (changedValues.controlInfo) {
341
- updateNodeControl(selectedNodeId, changedValues.controlInfo);
342
- }
343
- };
344
- // 当选中节点变化时,重置表单
345
- useEffect(() => {
346
- if (selectedNode) {
347
- form.setFieldsValue({
348
- name: selectedNode.name,
349
- normalStyle: {
350
- width: 100,
351
- height: 100,
352
- x: 0,
353
- y: 0,
354
- padding: 8,
355
- background: "transparent",
356
- borderRadius: 0,
357
- opacity: 1,
358
- ...selectedNode.normalStyle,
359
- },
360
- controlInfo: {
361
- isDraggable: true,
362
- isClickable: true,
363
- isResizable: true,
364
- isSelectable: true,
365
- ...selectedNode.controlInfo,
366
- },
367
- });
368
- // 取消选中状态
369
- selectStatus(null);
370
- }
371
- }, [selectedNode?.id, form, selectStatus]);
372
- // ========== 状态管理 ==========
373
- // 添加状态
374
- const handleAddStatus = () => {
375
- if (!selectedNodeId || !selectedNode)
376
- return;
377
- // 打开物料选择弹窗
378
- setEditingStatusId("new");
379
- setMaterialModalVisible(true);
380
- };
381
- // 从物料库选择物料创建状态
382
- const handleSelectMaterialForStatus = (material) => {
383
- if (!selectedNodeId || !selectedNode)
384
- return;
385
- const newStatus = {
386
- id: nanoid(),
387
- name: `${material.name}_状态${currentStatusList.length + 1}`,
388
- expression: currentStatusList.length === 0 ? "return true;" : "return false;",
389
- material: { ...material, id: nanoid() }, // 复制物料并生成新ID
390
- bindCodes: [],
391
- };
392
- if (editingStatusId === "new") {
393
- // 添加新状态
394
- const newStatusList = [...currentStatusList, newStatus];
395
- updateNodeContent(selectedNodeId, {
396
- statusList: newStatusList,
397
- });
398
- }
399
- else if (editingStatusId) {
400
- // 更新现有状态的物料
401
- const newStatusList = currentStatusList.map((s) => {
402
- if (s.id === editingStatusId) {
403
- return { ...s, material: { ...material, id: nanoid() } };
404
- }
405
- return s;
406
- });
407
- updateNodeContent(selectedNodeId, { statusList: newStatusList });
408
- }
409
- setMaterialModalVisible(false);
410
- setEditingStatusId(null);
411
- };
412
- // 删除状态
413
- const handleDeleteStatus = (statusId) => {
414
- if (!selectedNodeId || !selectedNode)
415
- return;
416
- const newStatusList = selectedNode.contentInfo.statusList?.filter((s) => s.id !== statusId) ||
417
- [];
418
- updateNodeContent(selectedNodeId, { statusList: newStatusList });
419
- if (selectedStatusId === statusId) {
420
- selectStatus(null);
421
- }
422
- };
423
- // 更新状态
424
- const handleUpdateStatus = (statusId, updates) => {
425
- if (!selectedNodeId || !selectedNode)
426
- return;
427
- const newStatusList = selectedNode.contentInfo.statusList?.map((s) => {
428
- if (s.id === statusId) {
429
- return { ...s, ...updates };
430
- }
431
- return s;
432
- }) || [];
433
- updateNodeContent(selectedNodeId, { statusList: newStatusList });
434
- };
435
- // 复制状态
436
- const handleCopyStatus = (status) => {
437
- if (!selectedNodeId || !selectedNode)
438
- return;
439
- const newStatus = {
440
- ...status,
441
- id: nanoid(),
442
- name: `${status.name}_复制`,
443
- expression: "return false;",
444
- };
445
- const newStatusList = [...currentStatusList, newStatus];
446
- updateNodeContent(selectedNodeId, { statusList: newStatusList });
447
- };
448
- // 移动状态
449
- const handleMoveStatus = (statusId, direction) => {
450
- if (!selectedNodeId || !selectedNode)
451
- return;
452
- const index = currentStatusList.findIndex((s) => s.id === statusId);
453
- if (index === -1)
454
- return;
455
- const newStatusList = [...currentStatusList];
456
- if (direction === "up" && index > 0) {
457
- [newStatusList[index], newStatusList[index - 1]] = [
458
- newStatusList[index - 1],
459
- newStatusList[index],
460
- ];
461
- }
462
- else if (direction === "down" && index < newStatusList.length - 1) {
463
- [newStatusList[index], newStatusList[index + 1]] = [
464
- newStatusList[index + 1],
465
- newStatusList[index],
466
- ];
467
- }
468
- updateNodeContent(selectedNodeId, { statusList: newStatusList });
469
- };
470
- // 更改状态的物料
471
- const handleChangeStatusMaterial = (statusId) => {
472
- setEditingStatusId(statusId);
473
- setMaterialModalVisible(true);
474
- };
475
- // 更新状态绑定物料的属性
476
- const handleUpdateStatusMaterial = (statusId, updates) => {
477
- if (!selectedNodeId || !selectedNode)
478
- return;
479
- const newStatusList = currentStatusList.map((s) => {
480
- if (s.id === statusId) {
481
- return {
482
- ...s,
483
- material: { ...s.material, ...updates },
484
- };
485
- }
486
- return s;
487
- });
488
- updateNodeContent(selectedNodeId, {
489
- statusList: newStatusList,
490
- });
491
- };
492
- if (!selectedNode) {
493
- return (_jsx("div", { className: "h-full flex items-center justify-center bg-white border-l border-gray-200", children: _jsx(Empty, { description: "\u8BF7\u9009\u62E9\u4E00\u4E2A\u8282\u70B9" }) }));
494
- }
495
- return (_jsxs("div", { className: "h-full flex flex-col bg-white border-l border-gray-200", children: [_jsxs("div", { className: "p-4 border-b border-gray-200", children: [_jsx("h3", { className: "text-lg font-semibold text-gray-800", children: "\u5C5E\u6027\u9762\u677F" }), _jsx("p", { className: "text-sm text-gray-500", children: "\u7F16\u8F91\u9009\u4E2D\u8282\u70B9\u7684\u5C5E\u6027" })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-4", children: _jsxs(Tabs, { activeKey: activeTab, onChange: setActiveTab, children: [_jsx(TabPane, { tab: "\u57FA\u7840", children: _jsxs(Form, { form: form, layout: "vertical", onValuesChange: handleValuesChange, initialValues: {
496
- name: selectedNode.name,
497
- }, children: [_jsx(Form.Item, { label: "\u8282\u70B9\u540D\u79F0", name: "name", children: _jsx(Input, { placeholder: "\u8F93\u5165\u8282\u70B9\u540D\u79F0" }) }), _jsxs(Collapse, { ghost: true, defaultActiveKey: ["position", "size", "style"], children: [_jsx(Panel, { header: "\u4F4D\u7F6E", children: _jsxs(Space, { children: [_jsx(Form.Item, { label: "X", name: ["normalStyle", "x"], children: _jsx(InputNumber, {}) }), _jsx(Form.Item, { label: "Y", name: ["normalStyle", "y"], children: _jsx(InputNumber, {}) })] }) }, "position"), _jsx(Panel, { header: "\u5C3A\u5BF8", children: _jsxs(Space, { children: [_jsx(Form.Item, { label: "\u5BBD\u5EA6", name: ["normalStyle", "width"], children: _jsx(InputNumber, { min: 10 }) }), _jsx(Form.Item, { label: "\u9AD8\u5EA6", name: ["normalStyle", "height"], children: _jsx(InputNumber, { min: 10 }) })] }) }, "size"), _jsxs(Panel, { header: "\u6837\u5F0F", children: [_jsx(Form.Item, { label: "\u80CC\u666F\u8272", name: ["normalStyle", "background"], children: _jsx(Input, { placeholder: "transparent, #fff, url(...)" }) }), _jsx(Form.Item, { label: "\u5185\u8FB9\u8DDD", name: ["normalStyle", "padding"], children: _jsx(InputNumber, { min: 0 }) }), _jsx(Form.Item, { label: "\u5706\u89D2", name: ["normalStyle", "borderRadius"], children: _jsx(InputNumber, { min: 0 }) }), _jsx(Form.Item, { label: "\u7F29\u653E\u6BD4\u4F8B", name: ["normalStyle", "scale"], help: "\u7B49\u6BD4\u7F29\u653E\u8282\u70B9\u7684\u5BBD\u9AD8", children: _jsx(InputNumber, { min: 0.1, max: 5, step: 0.1 }) }), _jsx(Form.Item, { label: "\u900F\u660E\u5EA6", name: ["normalStyle", "opacity"], children: _jsx(InputNumber, { min: 0, max: 1, step: 0.1 }) }), _jsx(Form.Item, { label: "\u5C42\u7EA7", name: ["normalStyle", "zIndex"], children: _jsx(InputNumber, {}) })] }, "style")] })] }) }, "basic"), _jsx(TabPane, { tab: "\u72B6\u6001", children: selectedNode.type === 'group' && selectedNode.children ? (_jsx(GroupNodeStatusEditor, { node: selectedNode, updateNode: updateNode, materials: materials })) : (_jsxs("div", { className: "mb-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsxs("span", { className: "font-medium", children: ["\u72B6\u6001\u5217\u8868", _jsx(Tag, { color: "blue", className: "ml-2", children: currentStatusList.length })] }), _jsx(Button, { type: "primary", size: "small", icon: _jsx(PlusOutlined, {}), onClick: handleAddStatus, children: "\u6DFB\u52A0\u72B6\u6001" })] }), _jsx("p", { className: "text-xs text-gray-500 mb-3", children: "\u8282\u70B9\u6839\u636E\u72B6\u6001\u8868\u8FBE\u5F0F\u8BA1\u7B97\u7ED3\u679C\u663E\u793A\u5BF9\u5E94\u7269\u6599\uFF0C\u7B2C\u4E00\u4E2A\u8FD4\u56DE true \u7684\u72B6\u6001\u4E3A\u5F53\u524D\u72B6\u6001" }), currentStatusList.length > 0 && (_jsxs("div", { className: "mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg", children: [_jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { children: [_jsx("span", { className: "text-sm text-gray-600", children: "\u5F53\u524D\u72B6\u6001:" }), _jsx("span", { className: "ml-2 text-sm font-medium text-blue-600", children: "\u7531\u8868\u8FBE\u5F0F\u81EA\u52A8\u8BA1\u7B97" }), _jsx("span", { className: "ml-2 text-xs text-gray-400", children: "(\u8FD4\u56DE true \u7684\u7B2C\u4E00\u4E2A\u72B6\u6001)" })] }) }), _jsx("div", { className: "mt-2 text-xs text-gray-500", children: "\u63D0\u793A: \u4F7F\u7528\u753B\u5E03\u5DE5\u5177\u680F\u7684\"\u6570\u636E\u6A21\u62DF\"\u6309\u94AE\u53EF\u4EE5\u6D4B\u8BD5\u72B6\u6001\u8868\u8FBE\u5F0F" })] })), currentStatusList.length === 0 ? (_jsx("div", { className: "text-center text-gray-400 py-4 bg-gray-50 rounded-lg", children: "\u6682\u65E0\u72B6\u6001\uFF0C\u70B9\u51FB\u4E0A\u65B9\u6309\u94AE\u6DFB\u52A0" })) : (_jsx(Collapse, { ghost: true, children: currentStatusList.map((status, index) => (_jsx(Panel, { header: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-gray-400 w-5", children: index + 1 }), _jsx("span", { className: "font-medium", children: status.name }), _jsx(Tag, { color: "default", className: "text-xs", children: status.material.type })] }), extra: _jsxs(Space, { size: "small", onClick: (e) => e.stopPropagation(), children: [_jsx(Button, { type: "text", size: "small", icon: _jsx(ArrowUpOutlined, {}), disabled: index === 0, onClick: (e) => {
498
- e.stopPropagation();
499
- handleMoveStatus(status.id, "up");
500
- } }), _jsx(Button, { type: "text", size: "small", icon: _jsx(ArrowDownOutlined, {}), disabled: index === currentStatusList.length - 1, onClick: (e) => {
501
- e.stopPropagation();
502
- handleMoveStatus(status.id, "down");
503
- } }), _jsx(Button, { type: "text", size: "small", icon: _jsx(CopyOutlined, {}), onClick: (e) => {
504
- e.stopPropagation();
505
- handleCopyStatus(status);
506
- } }), _jsx(Button, { type: "text", size: "small", danger: true, icon: _jsx(DeleteOutlined, {}), onClick: (e) => {
507
- e.stopPropagation();
508
- handleDeleteStatus(status.id);
509
- } })] }), children: _jsxs(Form, { layout: "vertical", children: [_jsx(Form.Item, { label: "\u72B6\u6001\u540D\u79F0", children: _jsx(Input, { value: status.name, onChange: (e) => handleUpdateStatus(status.id, {
510
- name: e.target.value,
511
- }), placeholder: "\u8F93\u5165\u72B6\u6001\u540D\u79F0" }) }), _jsx(Form.Item, { label: "\u6267\u884C\u8868\u8FBE\u5F0F", help: "\u8FD4\u56DE true \u65F6\u6FC0\u6D3B\u6B64\u72B6\u6001\uFF0C\u53EF\u4F7F\u7528 data \u53D8\u91CF\u8BBF\u95EE\u7ED1\u5B9A\u6570\u636E", children: _jsx(TextArea, { value: editingExpressions[status.id] ?? status.expression, onChange: (e) => setEditingExpressions((prev) => ({
512
- ...prev,
513
- [status.id]: e.target.value,
514
- })), onBlur: (e) => {
515
- handleUpdateStatus(status.id, {
516
- expression: e.target.value,
517
- });
518
- setEditingExpressions((prev) => {
519
- const newState = { ...prev };
520
- delete newState[status.id];
521
- return newState;
522
- });
523
- }, rows: 3, placeholder: "return true;" }) }), _jsx(Form.Item, { label: "\u7ED1\u5B9A\u6570\u636E\u6E90 (bindCodes)", children: _jsx(Select, { mode: "tags", value: status.bindCodes || [], onChange: (value) => handleUpdateStatus(status.id, {
524
- bindCodes: value,
525
- }), placeholder: "\u8F93\u5165\u6570\u636E\u6E90 code", tokenSeparators: [",", " "], fieldNames: {
526
- value: "paramsCode",
527
- label: "paramsName",
528
- }, options: defaultTestData }) }), _jsx(Form.Item, { label: "\u7ED1\u5B9A\u7269\u6599", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { color: "blue", children: status.material.name }), _jsx(Tag, { color: "default", children: status.material.type }), _jsx(Button, { type: "link", size: "small", icon: _jsx(EditOutlined, {}), onClick: () => handleChangeStatusMaterial(status.id), children: "\u66F4\u6362\u7269\u6599" })] }) }), _jsx(Divider, { style: { margin: "12px 0" } }), _jsxs("div", { className: "bg-gray-50 rounded-lg p-3 border border-gray-200", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsx("span", { className: "text-sm font-medium", children: "\u7269\u6599\u5C5E\u6027" }), _jsx(Tag, { children: status.material.name })] }), _jsx(MaterialPropertyEditor, { material: status.material, onSave: (updates) => handleUpdateStatusMaterial(status.id, updates), bindCodes: status.bindCodes || [], dataOptions: defaultTestData || [] })] })] }) }, status.id))) }))] })) }, "status"), _jsx(TabPane, { tab: "\u63A7\u5236", children: _jsxs(Form, { form: form, layout: "vertical", onValuesChange: handleValuesChange, children: [_jsx(Form.Item, { label: "\u53EF\u62D6\u62FD", name: ["controlInfo", "isDraggable"], valuePropName: "checked", children: _jsx(Switch, {}) }), _jsx(Form.Item, { label: "\u53EF\u70B9\u51FB", name: ["controlInfo", "isClickable"], valuePropName: "checked", children: _jsx(Switch, {}) }), _jsx(Form.Item, { label: "\u53EF\u8C03\u6574\u5927\u5C0F", name: ["controlInfo", "isResizable"], valuePropName: "checked", children: _jsx(Switch, {}) }), _jsx(Form.Item, { label: "\u53EF\u9009\u4E2D", name: ["controlInfo", "isSelectable"], valuePropName: "checked", children: _jsx(Switch, {}) })] }) }, "control")] }) }), _jsx("div", { className: "p-3 border-t border-gray-200 bg-gray-50", children: _jsxs("div", { className: "text-xs text-gray-500", children: [_jsxs("div", { children: ["\u8282\u70B9 ID: ", selectedNode.id.slice(0, 8), "..."] }), _jsxs("div", { children: ["\u72B6\u6001\u6570: ", currentStatusList.length] })] }) }), _jsx(Modal, { title: "\u9009\u62E9\u7269\u6599", open: materialModalVisible, onCancel: () => {
529
- setMaterialModalVisible(false);
530
- setEditingStatusId(null);
531
- }, footer: null, width: 600, children: _jsx("div", { className: "max-h-[400px] overflow-y-auto", children: _jsxs(Collapse, { ghost: true, defaultActiveKey: ["basic", "device", "text", "line"], children: [_jsx(Panel, { header: "\u57FA\u7840\u5F62\u72B6", children: _jsx("div", { className: "grid grid-cols-4 gap-2", children: materials
532
- .filter((m) => ["矩形", "圆形", "圆角矩形"].includes(m.name))
533
- .map((material) => (_jsxs("div", { className: "border rounded-lg p-2 cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all text-center", onClick: () => handleSelectMaterialForStatus(material), children: [_jsx("div", { className: "w-12 h-12 mx-auto mb-1 flex items-center justify-center", children: material.src ? (_jsx("img", { src: material.src, alt: material.name, className: "w-10 h-10 object-contain" })) : (_jsx("span", { className: "text-xs", children: material.name[0] })) }), _jsx("span", { className: "text-xs", children: material.name })] }, material.id))) }) }, "basic"), _jsx(Panel, { header: "\u8BBE\u5907\u56FE\u6807", children: _jsx("div", { className: "grid grid-cols-4 gap-2", children: materials
534
- .filter((m) => ["阀门", "泵", "罐体"].includes(m.name) ||
535
- (m.type === "IMAGE" &&
536
- !["矩形", "圆形", "圆角矩形"].includes(m.name)))
537
- .map((material) => (_jsxs("div", { className: "border rounded-lg p-2 cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all text-center", onClick: () => handleSelectMaterialForStatus(material), children: [_jsx("div", { className: "w-12 h-12 mx-auto mb-1 flex items-center justify-center", children: material.src ? (_jsx("img", { src: material.src, alt: material.name, className: "w-10 h-10 object-contain" })) : (_jsx("span", { className: "text-xs", children: material.name[0] })) }), _jsx("span", { className: "text-xs", children: material.name })] }, material.id))) }) }, "device"), _jsx(Panel, { header: "\u6587\u672C", children: _jsx("div", { className: "grid grid-cols-4 gap-2", children: materials
538
- .filter((m) => m.type === "TEXT")
539
- .map((material) => (_jsxs("div", { className: "border rounded-lg p-2 cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all text-center", onClick: () => handleSelectMaterialForStatus(material), children: [_jsx("div", { className: "w-12 h-12 mx-auto mb-1 flex items-center justify-center bg-gray-100 rounded", children: _jsx("span", { className: "text-lg font-bold text-gray-500", children: "T" }) }), _jsx("span", { className: "text-xs", children: material.name })] }, material.id))) }) }, "text"), _jsx(Panel, { header: "\u7EBF\u6761", children: _jsx("div", { className: "grid grid-cols-4 gap-2", children: materials
540
- .filter((m) => m.type === "LINE")
541
- .map((material) => (_jsxs("div", { className: "border rounded-lg p-2 cursor-pointer hover:border-blue-500 hover:bg-blue-50 transition-all text-center", onClick: () => handleSelectMaterialForStatus(material), children: [_jsx("div", { className: "w-12 h-12 mx-auto mb-1 flex items-center justify-center bg-gray-100 rounded", children: _jsx("div", { className: "w-8 h-0.5 bg-gray-400" }) }), _jsx("span", { className: "text-xs", children: material.name })] }, material.id))) }) }, "line")] }) }) })] }));
542
- };