bi-sdk-react 0.0.71 → 0.0.73

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bi-sdk-react",
3
- "version": "0.0.71",
3
+ "version": "0.0.73",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/umd/js/bi-sdk.umd.min.js",
@@ -107,6 +107,24 @@ const Toolbar: React.FC<{
107
107
  margin: "0 -24px",
108
108
  },
109
109
  }}
110
+ modalRender={(node) => (
111
+ <div
112
+ onClick={(e) => {
113
+ e.stopPropagation();
114
+ }}
115
+ onMouseDown={(e) => {
116
+ e.stopPropagation();
117
+ }}
118
+ onMouseUp={(e) => {
119
+ e.stopPropagation();
120
+ }}
121
+ onPointerDown={(e) => {
122
+ e.stopPropagation();
123
+ }}
124
+ >
125
+ {node}
126
+ </div>
127
+ )}
110
128
  footer={
111
129
  <Space>
112
130
  <Button
@@ -158,7 +176,11 @@ const Toolbar: React.FC<{
158
176
  }}
159
177
  />
160
178
  </Modal>
161
- <ToolbarWrap>
179
+ <ToolbarWrap
180
+ onClick={(e) => {
181
+ e.stopPropagation();
182
+ }}
183
+ >
162
184
  {!!ancestors?.length ? (
163
185
  <Dropdown
164
186
  placement="topLeft"
@@ -1,9 +1,27 @@
1
1
  import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
2
- import React, { useContext, useEffect, useMemo, useRef } from "react";
2
+ import {
3
+ Card,
4
+ CheckboxOptionType,
5
+ Empty,
6
+ Flex,
7
+ Input,
8
+ Modal,
9
+ Pagination,
10
+ Radio,
11
+ Space,
12
+ Typography,
13
+ } from "antd";
14
+ import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
3
15
  import styled from "styled-components";
4
16
  import { PageContext } from "../context/PageContext";
5
17
  import { IconFont } from "../icon/IconFont";
6
- import { PluginType } from "../typing";
18
+ import {
19
+ ExampleItemType,
20
+ FetchType,
21
+ PluginType,
22
+ SchemaItemType,
23
+ TemplateItemType,
24
+ } from "../typing";
7
25
  import { uuid } from "../utils";
8
26
  import { PaneHeader } from "./PaneHeader";
9
27
 
@@ -51,6 +69,237 @@ const Root = styled.div`
51
69
  }
52
70
  `;
53
71
 
72
+ const EmptyImage = () => (
73
+ <svg
74
+ height="132"
75
+ version="1.1"
76
+ viewBox="0 0 148 132"
77
+ width="148"
78
+ xmlns="http://www.w3.org/2000/svg"
79
+ style={{
80
+ height: 80,
81
+ background: "#f5f5f5",
82
+ }}
83
+ >
84
+ <g node-id="23">
85
+ <path
86
+ d="M 116.04 26.83 L 95.88 26.83 L 95.88 19.15 C 95.88 18.62 95.45 18.19 94.92 18.19 L 88.20 18.19 C 87.67 18.19 87.24 18.62 87.24 19.15 L 87.24 26.83 L 56.52 26.83 L 56.52 19.15 C 56.52 18.62 56.09 18.19 55.56 18.19 L 48.84 18.19 C 48.31 18.19 47.88 18.62 47.88 19.15 L 47.88 26.83 L 27.72 26.83 C 26.70 26.83 25.72 27.24 25.00 27.96 C 24.28 28.68 23.88 29.65 23.88 30.67 L 23.88 110.35 C 23.88 111.37 24.28 112.35 25.00 113.07 C 25.72 113.79 26.70 114.19 27.72 114.19 L 116.04 114.19 C 117.06 114.20 118.04 113.79 118.76 113.07 C 119.48 112.35 119.88 111.37 119.88 110.36 L 119.88 30.67 C 119.88 29.65 119.48 28.67 118.76 27.95 C 118.04 27.23 117.06 26.83 116.04 26.83 Z"
87
+ fill="#e2e5f1"
88
+ fill-opacity="0.8"
89
+ fill-rule="nonzero"
90
+ group-id="1"
91
+ id="路径_2309"
92
+ node-id="3"
93
+ stroke="none"
94
+ target-height="96.005135"
95
+ target-width="96.00427"
96
+ target-x="23.878815"
97
+ target-y="18.189949"
98
+ />
99
+ </g>
100
+ <g node-id="24">
101
+ <path
102
+ d="M 29.95 122.53 L 27.74 118.71 L 46.79 107.71 L 49.00 111.53 Z M 54.50 99.05 L 16.39 121.05 L -0.00 92.66 L 38.10 70.66 L 54.49 99.05 Z M 21.46 95.65 L 17.57 110.02 C 17.54 110.12 17.55 110.23 17.61 110.31 C 17.66 110.40 17.74 110.47 17.84 110.50 L 20.30 111.15 C 20.40 111.18 20.51 111.16 20.60 111.11 C 20.69 111.06 20.76 110.98 20.79 110.88 L 23.91 99.34 L 31.57 101.37 C 31.68 101.40 31.78 101.39 31.87 101.33 C 31.96 101.28 32.03 101.19 32.05 101.10 L 37.43 81.25 C 37.46 81.15 37.45 81.04 37.39 80.95 C 37.34 80.86 37.25 80.80 37.15 80.77 L 34.69 80.13 C 34.48 80.07 34.27 80.20 34.21 80.40 L 29.60 97.41 L 21.94 95.38 C 21.84 95.36 21.73 95.37 21.65 95.43 C 21.55 95.47 21.49 95.56 21.46 95.66 Z"
103
+ fill="#417aff"
104
+ fill-opacity="0.8"
105
+ fill-rule="nonzero"
106
+ group-id="2"
107
+ id="联合_14"
108
+ node-id="4"
109
+ stroke="none"
110
+ target-height="51.876953"
111
+ target-width="54.5"
112
+ target-x="-0.00390625"
113
+ target-y="70.657715"
114
+ />
115
+ </g>
116
+ <g node-id="25">
117
+ <path
118
+ d="M 88.93 34.73 C 88.93 34.73 117.73 48.02 115.10 55.87 C 112.47 63.72 103.24 56.85 107.78 52.26 C 112.31 47.68 124.85 52.02 124.81 67.98 C 124.77 83.93 115.74 105.47 74.82 116.65"
119
+ fill="none"
120
+ group-id="3"
121
+ id="路径_2313"
122
+ node-id="5"
123
+ stroke="#c2c8d8"
124
+ stroke-dasharray="2 2"
125
+ stroke-linecap="butt"
126
+ stroke-opacity="0.8"
127
+ stroke-width="1"
128
+ target-height="81.921974"
129
+ target-width="50.02726"
130
+ target-x="74.82369"
131
+ target-y="34.732864"
132
+ />
133
+ </g>
134
+ <g node-id="26">
135
+ <g node-id="36">
136
+ <g node-id="38">
137
+ <path
138
+ d="M 142.32 93.93 C 139.32 93.93 136.89 91.50 136.89 88.49 C 136.89 85.49 139.32 83.06 142.32 83.06 C 145.33 83.06 147.76 85.49 147.76 88.49 C 147.74 91.49 145.32 93.91 142.32 93.93 Z M 142.32 84.92 C 140.35 84.92 138.76 86.52 138.76 88.49 C 138.76 90.46 140.35 92.06 142.32 92.06 C 144.29 92.06 145.89 90.46 145.89 88.49 C 145.88 86.53 144.29 84.94 142.32 84.92 Z"
139
+ fill="#a4bfff"
140
+ fill-opacity="0.8"
141
+ fill-rule="nonzero"
142
+ group-id="4,14,16"
143
+ id="路径_2292"
144
+ node-id="8"
145
+ stroke="none"
146
+ target-height="10.873993"
147
+ target-width="10.873993"
148
+ target-x="136.8869"
149
+ target-y="83.056"
150
+ />
151
+ </g>
152
+ </g>
153
+ </g>
154
+ <g node-id="27">
155
+ <g node-id="37">
156
+ <g node-id="39">
157
+ <path
158
+ d="M 24.03 49.65 L 15.77 41.38 L 24.03 33.12 L 32.30 41.38 Z M 18.66 41.38 L 24.11 46.84 L 29.57 41.38 L 24.11 35.92 Z"
159
+ fill="#c2c8d8"
160
+ fill-opacity="0.8"
161
+ fill-rule="nonzero"
162
+ group-id="5,15,17"
163
+ id="路径_2294"
164
+ node-id="11"
165
+ stroke="none"
166
+ target-height="16.531982"
167
+ target-width="16.531982"
168
+ target-x="15.768982"
169
+ target-y="33.115997"
170
+ />
171
+ </g>
172
+ </g>
173
+ </g>
174
+ <g node-id="28">
175
+ <path
176
+ d="M 60.87 132.43 C 60.31 132.43 59.87 131.98 59.87 131.43 L 59.87 127.81 L 56.25 127.81 C 55.70 127.81 55.25 127.36 55.25 126.81 L 55.25 125.72 C 55.25 125.17 55.70 124.72 56.25 124.72 L 59.87 124.72 L 59.87 121.11 C 59.87 120.55 60.31 120.11 60.87 120.11 L 61.95 120.11 C 62.50 120.11 62.95 120.55 62.95 121.11 L 62.95 124.72 L 66.57 124.72 C 67.12 124.72 67.57 125.17 67.57 125.72 L 67.57 126.81 C 67.57 127.36 67.12 127.81 66.57 127.81 L 62.95 127.81 L 62.95 131.43 C 62.95 131.98 62.50 132.43 61.95 132.43 Z"
177
+ fill="#c2c8d8"
178
+ fill-opacity="0.8"
179
+ fill-rule="nonzero"
180
+ group-id="6"
181
+ id="联合_16"
182
+ node-id="12"
183
+ stroke="none"
184
+ target-height="12.322006"
185
+ target-width="12.319"
186
+ target-x="55.247986"
187
+ target-y="120.106995"
188
+ />
189
+ </g>
190
+ <g node-id="29">
191
+ <path
192
+ d="M 9.55 20.92 C 9.00 20.92 8.55 20.47 8.55 19.92 L 8.55 17.36 L 6.00 17.36 C 5.44 17.36 5.00 16.92 5.00 16.36 L 5.00 15.99 C 5.00 15.44 5.44 14.99 6.00 14.99 L 8.55 14.99 L 8.55 12.44 C 8.55 11.88 9.00 11.44 9.55 11.44 L 9.92 11.44 C 10.48 11.44 10.92 11.88 10.92 12.44 L 10.92 14.99 L 13.48 14.99 C 14.03 14.99 14.48 15.44 14.48 15.99 L 14.48 16.36 C 14.48 16.91 14.03 17.36 13.48 17.36 L 10.92 17.36 L 10.92 19.92 C 10.92 20.47 10.48 20.92 9.92 20.92 Z"
193
+ fill="#417aff"
194
+ fill-opacity="0"
195
+ fill-rule="nonzero"
196
+ group-id="7"
197
+ id="联合_17"
198
+ node-id="13"
199
+ stroke="none"
200
+ target-height="9.483"
201
+ target-width="9.483"
202
+ target-x="4.9959717"
203
+ target-y="11.435974"
204
+ />
205
+ </g>
206
+ <g node-id="30">
207
+ <path
208
+ d="M 94.70 28.55 C 91.61 31.22 88.07 33.31 84.23 34.72 C 81.19 35.89 77.81 37.03 74.50 36.67 C 72.71 36.48 70.99 35.89 69.46 34.94 C 67.45 33.45 65.68 31.67 64.19 29.66 C 63.27 28.56 62.28 28.70 61.16 29.47 C 60.46 29.95 60.14 31.27 59.52 31.64 C 58.72 32.12 58.08 31.82 58.36 30.67 C 58.75 29.08 61.51 27.88 62.94 27.74 C 62.89 25.08 65.70 21.30 67.79 19.89 C 75.73 14.53 85.75 18.26 91.90 24.45 C 92.18 24.72 95.36 27.95 94.70 28.55 Z"
209
+ fill="#697391"
210
+ fill-opacity="0.8"
211
+ fill-rule="nonzero"
212
+ group-id="8"
213
+ id="路径_2314"
214
+ node-id="14"
215
+ stroke="none"
216
+ target-height="22.502167"
217
+ target-width="37.280975"
218
+ target-x="58.082336"
219
+ target-y="14.527588"
220
+ />
221
+ </g>
222
+ <g node-id="31">
223
+ <path
224
+ d="M 126.97 51.55 C 125.23 50.94 123.61 50.03 122.19 48.85 C 120.95 47.97 119.94 46.82 119.23 45.48 C 118.90 44.74 118.74 43.93 118.77 43.12 C 118.90 42.00 119.19 40.90 119.64 39.87 C 119.86 39.26 119.59 38.90 119.03 38.63 C 118.69 38.47 118.09 38.64 117.81 38.48 C 117.45 38.28 117.42 37.97 117.93 37.81 C 118.64 37.60 119.73 38.42 120.11 38.94 C 121.46 38.42 122.96 38.47 124.28 39.07 C 128.17 40.96 128.97 45.72 127.94 49.52 C 127.90 49.69 127.35 51.67 126.97 51.55 Z"
225
+ fill="#697391"
226
+ fill-opacity="0.8"
227
+ fill-rule="nonzero"
228
+ group-id="9"
229
+ id="路径_2316"
230
+ node-id="15"
231
+ stroke="none"
232
+ target-height="14.066719"
233
+ target-width="11.554443"
234
+ target-x="117.418564"
235
+ target-y="37.602352"
236
+ />
237
+ </g>
238
+ <g node-id="32">
239
+ <path
240
+ d="M 88.52 10.94 C 87.19 10.59 85.93 10.00 84.81 9.21 C 83.88 8.67 83.11 7.90 82.56 6.97 C 82.32 6.46 82.22 5.91 82.26 5.35 C 82.40 4.55 82.67 3.78 83.05 3.07 C 83.25 2.64 83.03 2.40 82.60 2.24 C 82.33 2.13 81.86 2.27 81.64 2.17 C 81.36 2.04 81.34 1.82 81.75 1.70 C 82.32 1.53 83.17 2.06 83.45 2.42 C 84.51 2.02 85.68 2.01 86.75 2.38 C 89.78 3.58 90.28 6.85 89.35 9.51 C 89.31 9.63 88.82 11.02 88.52 10.94 Z"
241
+ fill="#697391"
242
+ fill-opacity="0"
243
+ fill-rule="nonzero"
244
+ group-id="10"
245
+ id="路径_2317"
246
+ node-id="16"
247
+ stroke="none"
248
+ target-height="9.480836"
249
+ target-width="8.940781"
250
+ target-x="81.3402"
251
+ target-y="1.5345681"
252
+ />
253
+ </g>
254
+ <g node-id="33">
255
+ <path
256
+ d="M 110.05 85.50 C 111.54 83.78 112.70 81.80 113.49 79.67 C 114.27 77.97 114.64 76.11 114.57 74.25 C 114.47 73.25 114.14 72.29 113.61 71.44 C 112.78 70.32 111.79 69.33 110.67 68.51 C 110.06 68.00 110.13 67.44 110.56 66.82 C 110.83 66.43 111.57 66.24 111.77 65.90 C 112.04 65.46 111.87 65.10 111.23 65.25 C 110.34 65.47 109.68 67.02 109.60 67.81 C 108.11 67.78 106.01 69.35 105.22 70.51 C 102.24 74.93 104.32 80.51 107.76 83.94 C 107.92 84.09 109.72 85.87 110.05 85.50 Z"
257
+ fill="#697391"
258
+ fill-opacity="0"
259
+ fill-rule="nonzero"
260
+ group-id="11"
261
+ id="路径_2318"
262
+ node-id="17"
263
+ stroke="none"
264
+ target-height="20.767654"
265
+ target-width="12.403198"
266
+ target-x="102.238434"
267
+ target-y="65.100204"
268
+ />
269
+ </g>
270
+ <g node-id="34">
271
+ <path
272
+ d="M 104.48 112.46 C 105.55 112.38 106.59 112.11 107.56 111.66 C 108.38 111.36 109.12 110.87 109.72 110.22 C 110.01 109.86 110.22 109.43 110.33 108.97 C 110.42 108.32 110.42 107.67 110.33 107.02 C 110.30 106.65 110.51 106.49 110.86 106.43 C 111.07 106.39 111.38 106.57 111.56 106.52 C 111.79 106.47 111.86 106.29 111.59 106.13 C 111.23 105.91 110.50 106.20 110.21 106.44 C 109.53 105.94 108.68 105.74 107.86 105.88 C 105.40 106.36 104.24 108.90 104.24 111.18 C 104.24 111.28 104.25 112.47 104.48 112.46 Z"
273
+ fill="#697391"
274
+ fill-opacity="0"
275
+ fill-rule="nonzero"
276
+ group-id="12"
277
+ id="路径_2319"
278
+ node-id="18"
279
+ stroke="none"
280
+ target-height="6.72332"
281
+ target-width="7.620468"
282
+ target-x="104.23713"
283
+ target-y="105.74457"
284
+ />
285
+ </g>
286
+ <path
287
+ d="M 80.35 75.78 L 88.84 67.29 L 93.08 71.53 L 84.59 80.02 Z M 51.88 71.04 L 56.12 66.80 L 64.61 75.28 L 60.36 79.52 Z M 69.48 73.29 L 69.48 61.29 L 75.48 61.29 L 75.48 73.29 Z"
288
+ fill="#ffffff"
289
+ fill-opacity="0.8"
290
+ fill-rule="nonzero"
291
+ group-id="13"
292
+ id="联合_21"
293
+ node-id="19"
294
+ stroke="none"
295
+ target-height="18.728516"
296
+ target-width="41.197266"
297
+ target-x="51.88086"
298
+ target-y="61.29297"
299
+ />
300
+ </svg>
301
+ );
302
+
54
303
  const PluginTile: React.FC<{ plugin: PluginType }> = ({ plugin }) => {
55
304
  const ref: React.RefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
56
305
 
@@ -88,8 +337,262 @@ const PluginTile: React.FC<{ plugin: PluginType }> = ({ plugin }) => {
88
337
  );
89
338
  };
90
339
 
340
+ const cloneItem = (node: SchemaItemType): SchemaItemType => {
341
+ const newNode = { ...node, id: uuid() };
342
+
343
+ if (node.children) {
344
+ if (Array.isArray(node.children)) {
345
+ newNode.children = node.children.map(cloneItem);
346
+ } else {
347
+ const newChildren: Record<string, SchemaItemType[]> = {};
348
+ Object.keys(node.children).forEach((key) => {
349
+ newChildren[key] = (node.children as Record<string, SchemaItemType[]>)[
350
+ key
351
+ ].map(cloneItem);
352
+ });
353
+ newNode.children = newChildren;
354
+ }
355
+ }
356
+ return newNode;
357
+ };
358
+
359
+ const ExampleItem: React.FC<{
360
+ data: Omit<ExampleItemType, "item">;
361
+ fetch: FetchType;
362
+ }> = ({ data, fetch }) => {
363
+ const ref: React.RefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
364
+ const [item, setItem] = useState<ExampleItemType | null>(null);
365
+
366
+ const fetchDetail = async () => {
367
+ const res = await fetch?.exampleDetail?.(data.id);
368
+ setItem(res!);
369
+ };
370
+
371
+ /**
372
+ * 注册拖拽源:仅在设计模式下启用
373
+ */
374
+ useEffect(() => {
375
+ if (!item) {
376
+ return;
377
+ }
378
+ const el = ref.current;
379
+ if (!el) return;
380
+ const cleanup = draggable({
381
+ element: el,
382
+ getInitialData: () => {
383
+ const e = cloneItem(JSON.parse(JSON.stringify(item.item || {})));
384
+ return {
385
+ id: e.id,
386
+ data: e,
387
+ };
388
+ },
389
+ canDrag: () => true,
390
+ onDragStart: () => {},
391
+ onDrop: () => {},
392
+ });
393
+ return () => cleanup();
394
+ }, [item]);
395
+
396
+ useEffect(() => {
397
+ if (!data.id) return;
398
+ fetchDetail();
399
+ }, [data.id]);
400
+
401
+ return (
402
+ <div className="drag-move" ref={ref}>
403
+ <Card
404
+ size="small"
405
+ key={data.id}
406
+ cover={data.cover || <EmptyImage />}
407
+ variant="outlined"
408
+ style={{ cursor: "move" }}
409
+ >
410
+ <Card.Meta
411
+ title={data.name}
412
+ description={
413
+ <Typography.Text
414
+ ellipsis={{ tooltip: data.description || "暂无描述" }}
415
+ style={{ color: "var(--ant-color-text-description)" }}
416
+ >
417
+ {data.description}
418
+ </Typography.Text>
419
+ }
420
+ />
421
+ </Card>
422
+ </div>
423
+ );
424
+ };
425
+
426
+ const ExampleList: React.FC<{ fetch: FetchType }> = ({ fetch }) => {
427
+ const [total, setTotal] = useState(-1);
428
+ const [page, setPage] = useState(1);
429
+ const [size, setSize] = useState(20);
430
+ const [keyword, setKeyword] = useState("");
431
+ const [list, setList] = useState<Omit<ExampleItemType, "item">[]>([]);
432
+
433
+ const fetchList = async () => {
434
+ const res = await fetch.exampleList?.(page, size, keyword);
435
+ if (Array.isArray(res)) {
436
+ setList(res);
437
+ setTotal(-1);
438
+ } else if (typeof res === "object") {
439
+ setList(res.list || []);
440
+ setTotal(res.total);
441
+ }
442
+ };
443
+
444
+ useEffect(() => {
445
+ fetchList();
446
+ }, [page, size, keyword]);
447
+
448
+ return (
449
+ <Flex vertical={true} gap={12} style={{ height: "100%" }}>
450
+ <Input.Search
451
+ size="small"
452
+ value={keyword}
453
+ placeholder="输入关键字检索"
454
+ onChange={(e) => setKeyword(e.target.value)}
455
+ />
456
+ <Space orientation="vertical" style={{ flex: "auto", overflow: "auto" }}>
457
+ {list.map((item) => (
458
+ <ExampleItem key={item.id} data={item} fetch={fetch} />
459
+ ))}
460
+ </Space>
461
+ {total >= 0 && (
462
+ <Pagination
463
+ align="center"
464
+ size="small"
465
+ current={page}
466
+ pageSize={size}
467
+ total={total}
468
+ hideOnSinglePage={true}
469
+ onChange={(page, pageSize) => {
470
+ setPage(page);
471
+ setSize(pageSize);
472
+ }}
473
+ />
474
+ )}
475
+ </Flex>
476
+ );
477
+ };
478
+
479
+ const TemplateItem: React.FC<{
480
+ data: Omit<TemplateItemType, "schema">;
481
+ fetch: FetchType;
482
+ }> = ({ data, fetch }) => {
483
+ const [item, setItem] = useState<TemplateItemType | null>(null);
484
+ const { schema, setSchema } = useContext(PageContext);
485
+
486
+ const fetchDetail = async () => {
487
+ const res = await fetch?.templateDetail?.(data.id);
488
+ setItem(res!);
489
+ };
490
+
491
+ const handleClick = () => {
492
+ if (!item?.schema) {
493
+ return;
494
+ }
495
+ const next = JSON.parse(JSON.stringify(item.schema));
496
+ if (schema.items.length === 0) {
497
+ setSchema(next);
498
+ } else {
499
+ Modal.confirm({
500
+ title: "提示",
501
+ content: "确认加载该模板页面,加载后会替换现有页面内容。",
502
+ okText: "确认",
503
+ cancelText: "取消",
504
+ onOk() {
505
+ setSchema(next);
506
+ },
507
+ });
508
+ }
509
+ };
510
+
511
+ useEffect(() => {
512
+ if (!data.id) return;
513
+ fetchDetail();
514
+ }, [data.id]);
515
+
516
+ return (
517
+ <Card
518
+ size="small"
519
+ key={data.id}
520
+ cover={data.cover || <EmptyImage />}
521
+ variant="outlined"
522
+ style={{ cursor: "pointer" }}
523
+ onClick={handleClick}
524
+ >
525
+ <Card.Meta
526
+ title={data.name}
527
+ description={
528
+ <Typography.Text
529
+ ellipsis={{ tooltip: data.description || "暂无描述" }}
530
+ style={{ color: "var(--ant-color-text-description)" }}
531
+ >
532
+ {data.description}
533
+ </Typography.Text>
534
+ }
535
+ />
536
+ </Card>
537
+ );
538
+ };
539
+
540
+ const TemplateList: React.FC<{ fetch: FetchType }> = ({ fetch }) => {
541
+ const [total, setTotal] = useState(-1);
542
+ const [page, setPage] = useState(1);
543
+ const [size, setSize] = useState(20);
544
+ const [keyword, setKeyword] = useState("");
545
+ const [list, setList] = useState<Omit<TemplateItemType, "schema">[]>([]);
546
+
547
+ const fetchList = async () => {
548
+ const res = await fetch.templateList?.(page, size, keyword);
549
+ if (Array.isArray(res)) {
550
+ setList(res);
551
+ setTotal(-1);
552
+ } else if (typeof res === "object") {
553
+ setList(res.list || []);
554
+ setTotal(res.total);
555
+ }
556
+ };
557
+
558
+ useEffect(() => {
559
+ fetchList();
560
+ }, [page, size, keyword]);
561
+
562
+ return (
563
+ <Flex vertical={true} gap={12} style={{ height: "100%" }}>
564
+ <Input.Search
565
+ size="small"
566
+ value={keyword}
567
+ placeholder="输入关键字检索"
568
+ onChange={(e) => setKeyword(e.target.value)}
569
+ />
570
+ <Space orientation="vertical" style={{ flex: "auto", overflow: "auto" }}>
571
+ {list.map((item) => (
572
+ <TemplateItem key={item.id} data={item} fetch={fetch} />
573
+ ))}
574
+ </Space>
575
+ {total >= 0 && (
576
+ <Pagination
577
+ align="center"
578
+ size="small"
579
+ current={page}
580
+ pageSize={size}
581
+ total={total}
582
+ hideOnSinglePage={true}
583
+ onChange={(page, pageSize) => {
584
+ setPage(page);
585
+ setSize(pageSize);
586
+ }}
587
+ />
588
+ )}
589
+ </Flex>
590
+ );
591
+ };
592
+
91
593
  export const ComponentPanel: React.FC = () => {
92
- const { plugins } = useContext(PageContext);
594
+ const { plugins, fetch } = useContext(PageContext);
595
+ const [tab, setTab] = useState("component");
93
596
  const grouped = useMemo(() => {
94
597
  const grouped: { group: string; items: PluginType[] }[] = [];
95
598
  plugins.forEach((item) => {
@@ -99,20 +602,64 @@ export const ComponentPanel: React.FC = () => {
99
602
  });
100
603
  return grouped;
101
604
  }, [plugins]);
605
+
606
+ const headerOptions: CheckboxOptionType<string>[] = useMemo(() => {
607
+ const options = [
608
+ {
609
+ label: "组件",
610
+ value: "component",
611
+ },
612
+ ];
613
+ if (fetch?.exampleList && fetch?.exampleDetail) {
614
+ options.push({
615
+ label: "片段",
616
+ value: "chunk",
617
+ });
618
+ }
619
+ if (fetch?.templateList && fetch?.templateDetail) {
620
+ options.push({
621
+ label: "模板",
622
+ value: "template",
623
+ });
624
+ }
625
+ return options;
626
+ }, [
627
+ fetch?.exampleList,
628
+ fetch?.exampleDetail,
629
+ fetch?.templateList,
630
+ fetch?.templateDetail,
631
+ ]);
102
632
  return (
103
633
  <Root className="component-panel">
104
- <PaneHeader title="组件库" />
634
+ <PaneHeader
635
+ title={
636
+ headerOptions.length === 1 ? (
637
+ headerOptions[0].label
638
+ ) : (
639
+ <Radio.Group
640
+ size="small"
641
+ optionType="button"
642
+ value={tab}
643
+ options={headerOptions}
644
+ onChange={(e) => setTab(e.target.value)}
645
+ />
646
+ )
647
+ }
648
+ />
105
649
  <div className="body beautified_scrollbar">
106
- {grouped.map((group) => (
107
- <div className="plugin-group" key={group.group}>
108
- <div className="group-title">{group.group}</div>
109
- <div className="plugin-list">
110
- {group.items.map((item) => (
111
- <PluginTile key={item.key} plugin={item} />
112
- ))}
650
+ {tab === "component" &&
651
+ grouped.map((group) => (
652
+ <div className="plugin-group" key={group.group}>
653
+ <div className="group-title">{group.group}</div>
654
+ <div className="plugin-list">
655
+ {group.items.map((item) => (
656
+ <PluginTile key={item.key} plugin={item} />
657
+ ))}
658
+ </div>
113
659
  </div>
114
- </div>
115
- ))}
660
+ ))}
661
+ {tab === "chunk" && fetch && <ExampleList fetch={fetch} />}
662
+ {tab === "template" && fetch && <TemplateList fetch={fetch} />}
116
663
  </div>
117
664
  </Root>
118
665
  );
@@ -1,11 +1,11 @@
1
- import React from 'react'
2
- import styled from 'styled-components'
1
+ import React from "react";
2
+ import styled from "styled-components";
3
3
 
4
4
  export type PaneHeaderProps = {
5
- title?: string
6
- extra?: React.ReactNode
7
- style?: React.CSSProperties
8
- }
5
+ title?: React.ReactNode;
6
+ extra?: React.ReactNode;
7
+ style?: React.CSSProperties;
8
+ };
9
9
 
10
10
  const Header = styled.div`
11
11
  width: 100%;
@@ -23,13 +23,17 @@ const Header = styled.div`
23
23
  .extra {
24
24
  line-height: 32px;
25
25
  }
26
- `
26
+ `;
27
27
 
28
- export const PaneHeader: React.FC<PaneHeaderProps> = ({ title = '', extra, style = {} }) => {
28
+ export const PaneHeader: React.FC<PaneHeaderProps> = ({
29
+ title = "",
30
+ extra,
31
+ style = {},
32
+ }) => {
29
33
  return (
30
34
  <Header className="pane-header" style={style}>
31
35
  <span className="title">{title}</span>
32
36
  <div className="extra">{extra}</div>
33
37
  </Header>
34
- )
35
- }
38
+ );
39
+ };