sa2kit 1.6.69 → 1.6.72
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/dist/festivalCard/core/index.d.mts +1 -1
- package/dist/festivalCard/core/index.d.ts +1 -1
- package/dist/festivalCard/core/index.js +4 -2
- package/dist/festivalCard/core/index.js.map +1 -1
- package/dist/festivalCard/core/index.mjs +4 -2
- package/dist/festivalCard/core/index.mjs.map +1 -1
- package/dist/festivalCard/index.d.mts +3 -3
- package/dist/festivalCard/index.d.ts +3 -3
- package/dist/festivalCard/index.js +220 -119
- package/dist/festivalCard/index.js.map +1 -1
- package/dist/festivalCard/index.mjs +219 -120
- package/dist/festivalCard/index.mjs.map +1 -1
- package/dist/festivalCard/miniapp/index.d.mts +3 -3
- package/dist/festivalCard/miniapp/index.d.ts +3 -3
- package/dist/festivalCard/miniapp/index.js +51 -15
- package/dist/festivalCard/miniapp/index.js.map +1 -1
- package/dist/festivalCard/miniapp/index.mjs +51 -15
- package/dist/festivalCard/miniapp/index.mjs.map +1 -1
- package/dist/festivalCard/routes/index.d.mts +44 -0
- package/dist/festivalCard/routes/index.d.ts +44 -0
- package/dist/festivalCard/routes/index.js +268 -0
- package/dist/festivalCard/routes/index.js.map +1 -0
- package/dist/festivalCard/routes/index.mjs +263 -0
- package/dist/festivalCard/routes/index.mjs.map +1 -0
- package/dist/festivalCard/server/index.d.mts +1 -1
- package/dist/festivalCard/server/index.d.ts +1 -1
- package/dist/festivalCard/web/index.d.mts +18 -4
- package/dist/festivalCard/web/index.d.ts +18 -4
- package/dist/festivalCard/web/index.js +220 -119
- package/dist/festivalCard/web/index.js.map +1 -1
- package/dist/festivalCard/web/index.mjs +219 -120
- package/dist/festivalCard/web/index.mjs.map +1 -1
- package/dist/{festivalCardService-uSg0oNuD.d.mts → festivalCardService-CqBTVC6x.d.mts} +3 -1
- package/dist/{festivalCardService-C0fhTezx.d.ts → festivalCardService-iFKu0k9q.d.ts} +3 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +220 -119
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -120
- package/dist/index.mjs.map +1 -1
- package/dist/{types-B-tjQTGi.d.mts → types-D2WetAPc.d.mts} +8 -1
- package/dist/{types-B-tjQTGi.d.ts → types-D2WetAPc.d.ts} +8 -1
- package/package.json +6 -1
|
@@ -61,7 +61,8 @@ var DEFAULT_FESTIVAL_CARD_CONFIG = {
|
|
|
61
61
|
src: "https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80",
|
|
62
62
|
fit: "cover",
|
|
63
63
|
borderRadius: 16,
|
|
64
|
-
alt: "holiday"
|
|
64
|
+
alt: "holiday",
|
|
65
|
+
isBackground: false
|
|
65
66
|
}
|
|
66
67
|
]
|
|
67
68
|
},
|
|
@@ -120,7 +121,8 @@ var DEFAULT_FESTIVAL_CARD_CONFIG = {
|
|
|
120
121
|
src: "https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80",
|
|
121
122
|
fit: "cover",
|
|
122
123
|
borderRadius: 14,
|
|
123
|
-
alt: "gift"
|
|
124
|
+
alt: "gift",
|
|
125
|
+
isBackground: false
|
|
124
126
|
},
|
|
125
127
|
{
|
|
126
128
|
id: "p3-text-1",
|
|
@@ -186,9 +188,10 @@ var useFestivalCardConfig = (options) => {
|
|
|
186
188
|
const [loading, setLoading] = React3.useState(Boolean(options?.fetchConfig));
|
|
187
189
|
const [saving, setSaving] = React3.useState(false);
|
|
188
190
|
React3.useEffect(() => {
|
|
189
|
-
|
|
191
|
+
const fetchConfig = options?.fetchConfig;
|
|
192
|
+
if (!fetchConfig) return;
|
|
190
193
|
let active = true;
|
|
191
|
-
void
|
|
194
|
+
void fetchConfig().then((value) => {
|
|
192
195
|
if (!active) return;
|
|
193
196
|
setConfig(normalizeFestivalCardConfig(value));
|
|
194
197
|
}).finally(() => {
|
|
@@ -197,16 +200,17 @@ var useFestivalCardConfig = (options) => {
|
|
|
197
200
|
return () => {
|
|
198
201
|
active = false;
|
|
199
202
|
};
|
|
200
|
-
}, [options]);
|
|
203
|
+
}, [options?.fetchConfig]);
|
|
201
204
|
const save = React3.useCallback(async () => {
|
|
202
|
-
|
|
205
|
+
const onSave = options?.onSave;
|
|
206
|
+
if (!onSave) return;
|
|
203
207
|
setSaving(true);
|
|
204
208
|
try {
|
|
205
|
-
await
|
|
209
|
+
await onSave(config);
|
|
206
210
|
} finally {
|
|
207
211
|
setSaving(false);
|
|
208
212
|
}
|
|
209
|
-
}, [config, options]);
|
|
213
|
+
}, [config, options?.onSave]);
|
|
210
214
|
return React3.useMemo(
|
|
211
215
|
() => ({
|
|
212
216
|
config,
|
|
@@ -220,6 +224,7 @@ var useFestivalCardConfig = (options) => {
|
|
|
220
224
|
};
|
|
221
225
|
var elementStyle = (element) => ({
|
|
222
226
|
position: "absolute",
|
|
227
|
+
zIndex: 2,
|
|
223
228
|
left: `${element.x}%`,
|
|
224
229
|
top: `${element.y}%`,
|
|
225
230
|
width: `${element.width ?? 70}%`,
|
|
@@ -262,22 +267,23 @@ var renderElement = (element) => {
|
|
|
262
267
|
);
|
|
263
268
|
};
|
|
264
269
|
var FestivalCardPageRenderer = ({ page }) => {
|
|
270
|
+
const backgroundElement = page.elements.find(
|
|
271
|
+
(element) => element.type === "image" && Boolean(element.isBackground)
|
|
272
|
+
);
|
|
273
|
+
const foregroundElements = page.elements.filter((element) => !(element.type === "image" && element.isBackground));
|
|
265
274
|
return /* @__PURE__ */ React3__default.default.createElement(
|
|
266
275
|
"div",
|
|
267
276
|
{
|
|
277
|
+
className: "relative h-full w-full overflow-hidden rounded-2xl",
|
|
268
278
|
style: {
|
|
269
|
-
position: "relative",
|
|
270
|
-
width: "100%",
|
|
271
|
-
height: "100%",
|
|
272
|
-
overflow: "hidden",
|
|
273
|
-
borderRadius: 16,
|
|
274
279
|
backgroundColor: page.background?.color || "#0f172a",
|
|
275
|
-
backgroundImage: page.background?.image ? `url(${page.background.image})` : void 0,
|
|
280
|
+
backgroundImage: backgroundElement ? `url(${backgroundElement.src})` : page.background?.image ? `url(${page.background.image})` : void 0,
|
|
276
281
|
backgroundSize: "cover",
|
|
277
282
|
backgroundPosition: "center"
|
|
278
283
|
}
|
|
279
284
|
},
|
|
280
|
-
|
|
285
|
+
/* @__PURE__ */ React3__default.default.createElement("div", { className: "absolute inset-0 bg-slate-950/20" }),
|
|
286
|
+
foregroundElements.map(renderElement)
|
|
281
287
|
);
|
|
282
288
|
};
|
|
283
289
|
|
|
@@ -291,100 +297,31 @@ var FestivalCardBook3D = ({ config, className }) => {
|
|
|
291
297
|
return /* @__PURE__ */ React3__default.default.createElement("div", { className }, /* @__PURE__ */ React3__default.default.createElement(
|
|
292
298
|
"div",
|
|
293
299
|
{
|
|
300
|
+
className: "w-full min-h-[560px] rounded-3xl p-6 shadow-2xl shadow-slate-900/50",
|
|
294
301
|
style: {
|
|
295
|
-
|
|
296
|
-
minHeight: 560,
|
|
297
|
-
borderRadius: 24,
|
|
298
|
-
padding: 24,
|
|
299
|
-
background: `linear-gradient(145deg, ${normalized.background?.colorA || "#0c1a34"} 0%, ${normalized.background?.colorB || "#1f4f8a"} 100%)`,
|
|
300
|
-
boxShadow: "0 26px 70px rgba(2, 6, 23, 0.45)"
|
|
302
|
+
background: `linear-gradient(145deg, ${normalized.background?.colorA || "#0c1a34"} 0%, ${normalized.background?.colorB || "#1f4f8a"} 100%)`
|
|
301
303
|
}
|
|
302
304
|
},
|
|
303
|
-
/* @__PURE__ */ React3__default.default.createElement(
|
|
304
|
-
|
|
305
|
-
{
|
|
306
|
-
style: {
|
|
307
|
-
marginBottom: 14,
|
|
308
|
-
color: "#f8fafc",
|
|
309
|
-
fontSize: 14,
|
|
310
|
-
opacity: 0.9,
|
|
311
|
-
textAlign: "center"
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
normalized.coverTitle || "Festival Card",
|
|
315
|
-
" \xB7 \u7B2C ",
|
|
316
|
-
currentPage + 1,
|
|
317
|
-
" / ",
|
|
318
|
-
pages.length,
|
|
319
|
-
" \u9875"
|
|
320
|
-
),
|
|
321
|
-
/* @__PURE__ */ React3__default.default.createElement("div", { style: { perspective: 1400, width: "100%", maxWidth: 920, margin: "0 auto" } }, /* @__PURE__ */ React3__default.default.createElement(
|
|
305
|
+
/* @__PURE__ */ React3__default.default.createElement("div", { className: "mx-auto w-full max-w-5xl text-center text-slate-100" }, /* @__PURE__ */ React3__default.default.createElement("h3", { className: "mb-4 text-lg font-semibold" }, normalized.coverTitle || "Festival Card")),
|
|
306
|
+
/* @__PURE__ */ React3__default.default.createElement("div", { className: "mx-auto w-full max-w-5xl" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "relative h-[460px]" }, pages.map((page, index) => /* @__PURE__ */ React3__default.default.createElement(
|
|
322
307
|
"div",
|
|
323
308
|
{
|
|
309
|
+
key: page.id,
|
|
310
|
+
className: "absolute inset-0 transition-opacity duration-500 ease-out",
|
|
324
311
|
style: {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
transformStyle: "preserve-3d"
|
|
312
|
+
opacity: index === currentPage ? 1 : 0,
|
|
313
|
+
pointerEvents: index === currentPage ? "auto" : "none"
|
|
328
314
|
}
|
|
329
315
|
},
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
return /* @__PURE__ */ React3__default.default.createElement(
|
|
334
|
-
"div",
|
|
335
|
-
{
|
|
336
|
-
key: page.id,
|
|
337
|
-
style: {
|
|
338
|
-
position: "absolute",
|
|
339
|
-
inset: 0,
|
|
340
|
-
transformStyle: "preserve-3d",
|
|
341
|
-
transformOrigin: "left center",
|
|
342
|
-
transform: `rotateY(${isFlipped ? -170 : 0}deg)`,
|
|
343
|
-
transition: "transform 600ms cubic-bezier(0.2, 0.8, 0.2, 1)",
|
|
344
|
-
zIndex
|
|
345
|
-
}
|
|
346
|
-
},
|
|
347
|
-
/* @__PURE__ */ React3__default.default.createElement(
|
|
348
|
-
"div",
|
|
349
|
-
{
|
|
350
|
-
style: {
|
|
351
|
-
position: "absolute",
|
|
352
|
-
inset: 0,
|
|
353
|
-
backfaceVisibility: "hidden"
|
|
354
|
-
}
|
|
355
|
-
},
|
|
356
|
-
/* @__PURE__ */ React3__default.default.createElement(FestivalCardPageRenderer, { page })
|
|
357
|
-
),
|
|
358
|
-
/* @__PURE__ */ React3__default.default.createElement(
|
|
359
|
-
"div",
|
|
360
|
-
{
|
|
361
|
-
style: {
|
|
362
|
-
position: "absolute",
|
|
363
|
-
inset: 0,
|
|
364
|
-
transform: "rotateY(180deg)",
|
|
365
|
-
backfaceVisibility: "hidden",
|
|
366
|
-
borderRadius: 16,
|
|
367
|
-
background: "#0f172a"
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
)
|
|
371
|
-
);
|
|
372
|
-
})
|
|
373
|
-
)),
|
|
374
|
-
/* @__PURE__ */ React3__default.default.createElement("div", { style: { display: "flex", justifyContent: "center", gap: 12, marginTop: 18 } }, /* @__PURE__ */ React3__default.default.createElement(
|
|
316
|
+
/* @__PURE__ */ React3__default.default.createElement(FestivalCardPageRenderer, { page })
|
|
317
|
+
)))),
|
|
318
|
+
/* @__PURE__ */ React3__default.default.createElement("div", { className: "mt-5 flex justify-center gap-3" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
375
319
|
"button",
|
|
376
320
|
{
|
|
377
321
|
type: "button",
|
|
378
322
|
disabled: !canPrev,
|
|
379
323
|
onClick: () => setCurrentPage((p) => Math.max(0, p - 1)),
|
|
380
|
-
|
|
381
|
-
border: "none",
|
|
382
|
-
borderRadius: 999,
|
|
383
|
-
padding: "9px 16px",
|
|
384
|
-
fontSize: 14,
|
|
385
|
-
cursor: canPrev ? "pointer" : "not-allowed",
|
|
386
|
-
opacity: canPrev ? 1 : 0.4
|
|
387
|
-
}
|
|
324
|
+
className: "rounded-full bg-white px-5 py-2 text-sm font-medium text-slate-900 disabled:cursor-not-allowed disabled:opacity-45"
|
|
388
325
|
},
|
|
389
326
|
"\u4E0A\u4E00\u9875"
|
|
390
327
|
), /* @__PURE__ */ React3__default.default.createElement(
|
|
@@ -393,14 +330,7 @@ var FestivalCardBook3D = ({ config, className }) => {
|
|
|
393
330
|
type: "button",
|
|
394
331
|
disabled: !canNext,
|
|
395
332
|
onClick: () => setCurrentPage((p) => Math.min(pages.length - 1, p + 1)),
|
|
396
|
-
|
|
397
|
-
border: "none",
|
|
398
|
-
borderRadius: 999,
|
|
399
|
-
padding: "9px 16px",
|
|
400
|
-
fontSize: 14,
|
|
401
|
-
cursor: canNext ? "pointer" : "not-allowed",
|
|
402
|
-
opacity: canNext ? 1 : 0.4
|
|
403
|
-
}
|
|
333
|
+
className: "rounded-full bg-sky-300 px-5 py-2 text-sm font-medium text-slate-900 disabled:cursor-not-allowed disabled:opacity-45"
|
|
404
334
|
},
|
|
405
335
|
"\u4E0B\u4E00\u9875"
|
|
406
336
|
))
|
|
@@ -411,7 +341,7 @@ var FestivalCardBook3D = ({ config, className }) => {
|
|
|
411
341
|
autoPlay: normalized.backgroundMusic.autoPlay,
|
|
412
342
|
loop: normalized.backgroundMusic.loop,
|
|
413
343
|
controls: true,
|
|
414
|
-
|
|
344
|
+
className: "mt-3 w-full"
|
|
415
345
|
}
|
|
416
346
|
) : null);
|
|
417
347
|
};
|
|
@@ -453,16 +383,17 @@ var FestivalCardConfigEditor = ({ value, onChange }) => {
|
|
|
453
383
|
)
|
|
454
384
|
});
|
|
455
385
|
};
|
|
456
|
-
return /* @__PURE__ */ React3__default.default.createElement("div", {
|
|
386
|
+
return /* @__PURE__ */ React3__default.default.createElement("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 text-slate-900 shadow-sm" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "grid gap-3" }, /* @__PURE__ */ React3__default.default.createElement("label", { className: "grid gap-1.5" }, /* @__PURE__ */ React3__default.default.createElement("span", { className: "text-sm font-medium text-slate-700" }, "\u9875\u9762\u6570\u91CF"), /* @__PURE__ */ React3__default.default.createElement(
|
|
457
387
|
"input",
|
|
458
388
|
{
|
|
459
389
|
type: "number",
|
|
460
390
|
min: 1,
|
|
461
391
|
max: 12,
|
|
462
392
|
value: value.pages.length,
|
|
463
|
-
onChange: (event) => onChange(resizeFestivalCardPages(value, Number(event.target.value)))
|
|
393
|
+
onChange: (event) => onChange(resizeFestivalCardPages(value, Number(event.target.value))),
|
|
394
|
+
className: "rounded-lg border border-slate-300 bg-white px-3 py-2 text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
464
395
|
}
|
|
465
|
-
)), /* @__PURE__ */ React3__default.default.createElement("label", {
|
|
396
|
+
)), /* @__PURE__ */ React3__default.default.createElement("label", { className: "grid gap-1.5" }, /* @__PURE__ */ React3__default.default.createElement("span", { className: "text-sm font-medium text-slate-700" }, "\u80CC\u666F\u97F3\u4E50 URL"), /* @__PURE__ */ React3__default.default.createElement(
|
|
466
397
|
"input",
|
|
467
398
|
{
|
|
468
399
|
type: "url",
|
|
@@ -473,9 +404,18 @@ var FestivalCardConfigEditor = ({ value, onChange }) => {
|
|
|
473
404
|
...value.backgroundMusic,
|
|
474
405
|
src: event.target.value
|
|
475
406
|
}
|
|
476
|
-
})
|
|
407
|
+
}),
|
|
408
|
+
className: "rounded-lg border border-slate-300 bg-white px-3 py-2 text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
477
409
|
}
|
|
478
|
-
)), /* @__PURE__ */ React3__default.default.createElement("label", {
|
|
410
|
+
)), /* @__PURE__ */ React3__default.default.createElement("label", { className: "grid gap-1.5" }, /* @__PURE__ */ React3__default.default.createElement("span", { className: "text-sm font-medium text-slate-700" }, "\u7F16\u8F91\u9875\u9762"), /* @__PURE__ */ React3__default.default.createElement(
|
|
411
|
+
"select",
|
|
412
|
+
{
|
|
413
|
+
value: activePageIndex,
|
|
414
|
+
onChange: (event) => setActivePageIndex(Number(event.target.value)),
|
|
415
|
+
className: "rounded-lg border border-slate-300 bg-white px-3 py-2 text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
416
|
+
},
|
|
417
|
+
pageOptions.map((index) => /* @__PURE__ */ React3__default.default.createElement("option", { key: index, value: index }, "\u7B2C ", index + 1, " \u9875"))
|
|
418
|
+
))), canEditPage ? /* @__PURE__ */ React3__default.default.createElement("div", { className: "mt-4" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "mb-3 flex gap-2" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
479
419
|
"button",
|
|
480
420
|
{
|
|
481
421
|
type: "button",
|
|
@@ -484,7 +424,8 @@ var FestivalCardConfigEditor = ({ value, onChange }) => {
|
|
|
484
424
|
pages: value.pages.map(
|
|
485
425
|
(p, index) => index === activePageIndex ? { ...p, elements: [...p.elements, createTextElement(index)] } : p
|
|
486
426
|
)
|
|
487
|
-
})
|
|
427
|
+
}),
|
|
428
|
+
className: "rounded-lg bg-slate-900 px-3 py-2 text-sm font-medium text-white"
|
|
488
429
|
},
|
|
489
430
|
"+ \u6587\u5B57"
|
|
490
431
|
), /* @__PURE__ */ React3__default.default.createElement(
|
|
@@ -496,27 +437,38 @@ var FestivalCardConfigEditor = ({ value, onChange }) => {
|
|
|
496
437
|
pages: value.pages.map(
|
|
497
438
|
(p, index) => index === activePageIndex ? { ...p, elements: [...p.elements, createImageElement(index)] } : p
|
|
498
439
|
)
|
|
499
|
-
})
|
|
440
|
+
}),
|
|
441
|
+
className: "rounded-lg bg-sky-600 px-3 py-2 text-sm font-medium text-white"
|
|
500
442
|
},
|
|
501
443
|
"+ \u56FE\u7247"
|
|
502
|
-
)), /* @__PURE__ */ React3__default.default.createElement("div", {
|
|
444
|
+
)), /* @__PURE__ */ React3__default.default.createElement("div", { className: "grid max-h-[340px] gap-2.5 overflow-auto pr-1" }, (page?.elements ?? []).map((element) => /* @__PURE__ */ React3__default.default.createElement("div", { key: element.id, className: "rounded-xl border border-slate-200 bg-slate-50 p-3" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "mb-2 text-xs font-semibold tracking-wide text-slate-500" }, element.type.toUpperCase()), element.type === "text" ? /* @__PURE__ */ React3__default.default.createElement(
|
|
503
445
|
"textarea",
|
|
504
446
|
{
|
|
505
447
|
value: element.content,
|
|
506
448
|
onChange: (event) => updateElement(element.id, { content: event.target.value }),
|
|
507
449
|
rows: 3,
|
|
508
|
-
|
|
450
|
+
className: "w-full rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
509
451
|
}
|
|
510
|
-
) : /* @__PURE__ */ React3__default.default.createElement(
|
|
452
|
+
) : /* @__PURE__ */ React3__default.default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
511
453
|
"input",
|
|
512
454
|
{
|
|
513
455
|
type: "url",
|
|
514
456
|
value: element.src,
|
|
515
457
|
onChange: (event) => updateElement(element.id, { src: event.target.value }),
|
|
516
|
-
|
|
458
|
+
className: "w-full rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
459
|
+
}
|
|
460
|
+
), /* @__PURE__ */ React3__default.default.createElement("label", { className: "inline-flex items-center gap-2 text-sm text-slate-700" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
461
|
+
"input",
|
|
462
|
+
{
|
|
463
|
+
type: "checkbox",
|
|
464
|
+
checked: Boolean(element.isBackground),
|
|
465
|
+
onChange: (event) => updateElement(element.id, { isBackground: event.target.checked }),
|
|
466
|
+
className: "h-4 w-4 rounded border-slate-300 text-sky-600"
|
|
517
467
|
}
|
|
518
|
-
))))) : null);
|
|
468
|
+
), "\u4F5C\u4E3A\u672C\u9875\u80CC\u666F\u56FE")))))) : null);
|
|
519
469
|
};
|
|
470
|
+
|
|
471
|
+
// src/festivalCard/components/FestivalCardStudio.tsx
|
|
520
472
|
var FestivalCardStudio = ({ initialConfig, fetchConfig, onSave }) => {
|
|
521
473
|
const { config, setConfig, loading, save, saving } = useFestivalCardConfig({
|
|
522
474
|
initialConfig: normalizeFestivalCardConfig(initialConfig),
|
|
@@ -524,18 +476,135 @@ var FestivalCardStudio = ({ initialConfig, fetchConfig, onSave }) => {
|
|
|
524
476
|
onSave
|
|
525
477
|
});
|
|
526
478
|
if (loading) return /* @__PURE__ */ React3__default.default.createElement("div", null, "\u52A0\u8F7D\u4E2D...");
|
|
527
|
-
return /* @__PURE__ */ React3__default.default.createElement("div", {
|
|
479
|
+
return /* @__PURE__ */ React3__default.default.createElement("div", { className: "grid gap-4 lg:grid-cols-[1.45fr_1fr]" }, /* @__PURE__ */ React3__default.default.createElement(FestivalCardBook3D, { config, className: "h-full" }), /* @__PURE__ */ React3__default.default.createElement("div", null, /* @__PURE__ */ React3__default.default.createElement(FestivalCardConfigEditor, { value: config, onChange: setConfig }), onSave ? /* @__PURE__ */ React3__default.default.createElement(
|
|
528
480
|
"button",
|
|
529
481
|
{
|
|
530
482
|
type: "button",
|
|
531
483
|
onClick: () => void save(),
|
|
532
484
|
disabled: saving,
|
|
533
|
-
|
|
485
|
+
className: "mt-3 w-full rounded-lg bg-slate-900 px-4 py-2.5 text-sm font-medium text-white disabled:opacity-60"
|
|
534
486
|
},
|
|
535
487
|
saving ? "\u4FDD\u5B58\u4E2D..." : "\u4FDD\u5B58\u914D\u7F6E"
|
|
536
488
|
) : null));
|
|
537
489
|
};
|
|
538
490
|
|
|
491
|
+
// src/festivalCard/components/FestivalCardConfigPage.tsx
|
|
492
|
+
var FestivalCardConfigPage = ({
|
|
493
|
+
apiBase = "/api/festivalCard",
|
|
494
|
+
cardId,
|
|
495
|
+
mainPagePath = "/festivalCard"
|
|
496
|
+
}) => {
|
|
497
|
+
const [list, setList] = React3.useState([]);
|
|
498
|
+
const [selectedId, setSelectedId] = React3.useState(cardId || "default-festival-card");
|
|
499
|
+
const parseListResponse2 = (data) => {
|
|
500
|
+
if (!data || typeof data !== "object") return [];
|
|
501
|
+
const payload = data.data;
|
|
502
|
+
if (!Array.isArray(payload)) return [];
|
|
503
|
+
return payload.filter((item) => Boolean(item && typeof item === "object" && typeof item.id === "string")).map((item) => ({ id: item.id, name: item.name }));
|
|
504
|
+
};
|
|
505
|
+
const parseConfigResponse2 = (data) => {
|
|
506
|
+
if (!data || typeof data !== "object") return normalizeFestivalCardConfig();
|
|
507
|
+
const payload = data.data;
|
|
508
|
+
if (!payload || typeof payload !== "object") return normalizeFestivalCardConfig();
|
|
509
|
+
return normalizeFestivalCardConfig(payload);
|
|
510
|
+
};
|
|
511
|
+
const reloadList = React3.useCallback(async () => {
|
|
512
|
+
const response = await fetch(apiBase, { cache: "no-store" });
|
|
513
|
+
const data = await response.json();
|
|
514
|
+
setList(parseListResponse2(data));
|
|
515
|
+
}, [apiBase]);
|
|
516
|
+
React3.useEffect(() => {
|
|
517
|
+
void reloadList();
|
|
518
|
+
}, [reloadList]);
|
|
519
|
+
const fetchConfig = async () => {
|
|
520
|
+
const response = await fetch(`${apiBase}/${encodeURIComponent(selectedId)}`, { cache: "no-store" });
|
|
521
|
+
const data = await response.json();
|
|
522
|
+
return parseConfigResponse2(data);
|
|
523
|
+
};
|
|
524
|
+
const saveConfig = async (config) => {
|
|
525
|
+
await fetch(`${apiBase}/${encodeURIComponent(selectedId)}`, {
|
|
526
|
+
method: "PUT",
|
|
527
|
+
headers: { "Content-Type": "application/json" },
|
|
528
|
+
body: JSON.stringify({ config })
|
|
529
|
+
});
|
|
530
|
+
await reloadList();
|
|
531
|
+
};
|
|
532
|
+
const createNew = async () => {
|
|
533
|
+
const name = window.prompt("\u8BF7\u8F93\u5165\u65B0\u5361\u7247\u540D\u79F0");
|
|
534
|
+
if (!name) return;
|
|
535
|
+
const id = `festival-${Date.now()}`;
|
|
536
|
+
const config = normalizeFestivalCardConfig({
|
|
537
|
+
id,
|
|
538
|
+
name
|
|
539
|
+
});
|
|
540
|
+
await fetch(`${apiBase}/${encodeURIComponent(id)}`, {
|
|
541
|
+
method: "PUT",
|
|
542
|
+
headers: { "Content-Type": "application/json" },
|
|
543
|
+
body: JSON.stringify({ config })
|
|
544
|
+
});
|
|
545
|
+
setSelectedId(id);
|
|
546
|
+
await reloadList();
|
|
547
|
+
};
|
|
548
|
+
const mainLink = React3.useMemo(() => `${mainPagePath}?cardId=${encodeURIComponent(selectedId)}`, [mainPagePath, selectedId]);
|
|
549
|
+
return /* @__PURE__ */ React3__default.default.createElement("div", { className: "grid gap-3" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "flex flex-wrap items-center gap-2" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
550
|
+
"select",
|
|
551
|
+
{
|
|
552
|
+
value: selectedId,
|
|
553
|
+
onChange: (event) => setSelectedId(event.target.value),
|
|
554
|
+
className: "min-w-[200px] rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 outline-none focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
|
555
|
+
},
|
|
556
|
+
list.map((item) => /* @__PURE__ */ React3__default.default.createElement("option", { key: item.id, value: item.id }, item.name || item.id))
|
|
557
|
+
), /* @__PURE__ */ React3__default.default.createElement("button", { type: "button", onClick: () => void createNew(), className: "rounded-lg bg-slate-900 px-3 py-2 text-sm font-medium text-white" }, "\u65B0\u5EFA\u5361\u7247"), /* @__PURE__ */ React3__default.default.createElement("a", { href: mainLink, className: "rounded-lg border border-sky-200 bg-sky-50 px-3 py-2 text-sm text-sky-700" }, "\u6253\u5F00\u4E3B\u9875\u9762")), /* @__PURE__ */ React3__default.default.createElement(FestivalCardStudio, { fetchConfig, onSave: saveConfig }));
|
|
558
|
+
};
|
|
559
|
+
var isSummary = (value) => {
|
|
560
|
+
if (!value || typeof value !== "object") return false;
|
|
561
|
+
return typeof value.id === "string";
|
|
562
|
+
};
|
|
563
|
+
var parseListResponse = (data) => {
|
|
564
|
+
if (!data || typeof data !== "object") return [];
|
|
565
|
+
const payload = data.data;
|
|
566
|
+
if (!Array.isArray(payload)) return [];
|
|
567
|
+
return payload.filter(isSummary).map((item) => ({ id: item.id, name: item.name }));
|
|
568
|
+
};
|
|
569
|
+
var parseConfigResponse = (data) => {
|
|
570
|
+
if (!data || typeof data !== "object") return null;
|
|
571
|
+
const payload = data.data;
|
|
572
|
+
if (!payload || typeof payload !== "object") return null;
|
|
573
|
+
if (!Array.isArray(payload.pages)) return null;
|
|
574
|
+
return payload;
|
|
575
|
+
};
|
|
576
|
+
var FestivalCardManagedPage = ({
|
|
577
|
+
apiBase = "/api/festivalCard",
|
|
578
|
+
cardId,
|
|
579
|
+
configPagePath = "/festivalCard/config"
|
|
580
|
+
}) => {
|
|
581
|
+
const [currentCardId, setCurrentCardId] = React3.useState(cardId || "");
|
|
582
|
+
const [config, setConfig] = React3.useState(null);
|
|
583
|
+
const [loading, setLoading] = React3.useState(true);
|
|
584
|
+
React3.useEffect(() => {
|
|
585
|
+
const fetchList = async () => {
|
|
586
|
+
const response = await fetch(apiBase, { cache: "no-store" });
|
|
587
|
+
const data = await response.json();
|
|
588
|
+
const items = parseListResponse(data);
|
|
589
|
+
const first = items[0];
|
|
590
|
+
if (!currentCardId && first) {
|
|
591
|
+
setCurrentCardId(first.id);
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
void fetchList();
|
|
595
|
+
}, [apiBase, currentCardId]);
|
|
596
|
+
React3.useEffect(() => {
|
|
597
|
+
if (!currentCardId) return;
|
|
598
|
+
setLoading(true);
|
|
599
|
+
void fetch(`${apiBase}/${encodeURIComponent(currentCardId)}`, { cache: "no-store" }).then((res) => res.json()).then((data) => setConfig(parseConfigResponse(data))).finally(() => setLoading(false));
|
|
600
|
+
}, [apiBase, currentCardId]);
|
|
601
|
+
const configLink = React3.useMemo(() => {
|
|
602
|
+
if (!currentCardId) return configPagePath;
|
|
603
|
+
return `${configPagePath}?cardId=${encodeURIComponent(currentCardId)}`;
|
|
604
|
+
}, [configPagePath, currentCardId]);
|
|
605
|
+
return /* @__PURE__ */ React3__default.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "flex justify-end" }, /* @__PURE__ */ React3__default.default.createElement("a", { href: configLink, className: "rounded-lg border border-slate-700 bg-slate-900 px-3 py-1.5 text-sm text-sky-300" }, "\u8FDB\u5165\u914D\u7F6E\u9875")), /* @__PURE__ */ React3__default.default.createElement("div", null, loading || !config ? /* @__PURE__ */ React3__default.default.createElement("div", { className: "py-12 text-center text-slate-400" }, "\u52A0\u8F7D\u4E2D...") : /* @__PURE__ */ React3__default.default.createElement(FestivalCardBook3D, { config })));
|
|
606
|
+
};
|
|
607
|
+
|
|
539
608
|
// src/festivalCard/server/db.ts
|
|
540
609
|
var dbAdapter = null;
|
|
541
610
|
var getFestivalCardDb = () => dbAdapter;
|
|
@@ -545,6 +614,16 @@ var FestivalCardService = class {
|
|
|
545
614
|
constructor(options) {
|
|
546
615
|
this.db = options?.db || getFestivalCardDb();
|
|
547
616
|
}
|
|
617
|
+
async listConfigs() {
|
|
618
|
+
if (!this.db) {
|
|
619
|
+
return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
|
|
620
|
+
}
|
|
621
|
+
if (this.db.listConfigs) {
|
|
622
|
+
const list = await this.db.listConfigs();
|
|
623
|
+
return list.length > 0 ? list : [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
|
|
624
|
+
}
|
|
625
|
+
return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
|
|
626
|
+
}
|
|
548
627
|
async getConfig(cardId = "default-festival-card") {
|
|
549
628
|
if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;
|
|
550
629
|
const config = await this.db.getConfig(cardId);
|
|
@@ -556,21 +635,43 @@ var FestivalCardService = class {
|
|
|
556
635
|
await this.db.saveConfig(cardId, normalized);
|
|
557
636
|
return normalized;
|
|
558
637
|
}
|
|
638
|
+
async deleteConfig(cardId) {
|
|
639
|
+
if (!this.db?.deleteConfig) return;
|
|
640
|
+
await this.db.deleteConfig(cardId);
|
|
641
|
+
}
|
|
559
642
|
};
|
|
560
643
|
var memoryStore = /* @__PURE__ */ new Map();
|
|
644
|
+
var defaultId = DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card";
|
|
645
|
+
if (!memoryStore.has(defaultId)) {
|
|
646
|
+
memoryStore.set(defaultId, DEFAULT_FESTIVAL_CARD_CONFIG);
|
|
647
|
+
}
|
|
561
648
|
var createInMemoryFestivalCardDb = () => ({
|
|
649
|
+
listConfigs() {
|
|
650
|
+
return Promise.resolve(
|
|
651
|
+
Array.from(memoryStore.entries()).map(([id, config]) => ({
|
|
652
|
+
id,
|
|
653
|
+
name: config.name || id
|
|
654
|
+
}))
|
|
655
|
+
);
|
|
656
|
+
},
|
|
562
657
|
getConfig(id) {
|
|
563
658
|
return Promise.resolve(memoryStore.get(id) || null);
|
|
564
659
|
},
|
|
565
660
|
saveConfig(id, config) {
|
|
566
661
|
memoryStore.set(id, config);
|
|
567
662
|
return Promise.resolve();
|
|
663
|
+
},
|
|
664
|
+
deleteConfig(id) {
|
|
665
|
+
memoryStore.delete(id);
|
|
666
|
+
return Promise.resolve();
|
|
568
667
|
}
|
|
569
668
|
});
|
|
570
669
|
|
|
571
670
|
exports.DEFAULT_FESTIVAL_CARD_CONFIG = DEFAULT_FESTIVAL_CARD_CONFIG;
|
|
572
671
|
exports.FestivalCardBook3D = FestivalCardBook3D;
|
|
573
672
|
exports.FestivalCardConfigEditor = FestivalCardConfigEditor;
|
|
673
|
+
exports.FestivalCardConfigPage = FestivalCardConfigPage;
|
|
674
|
+
exports.FestivalCardManagedPage = FestivalCardManagedPage;
|
|
574
675
|
exports.FestivalCardPageRenderer = FestivalCardPageRenderer;
|
|
575
676
|
exports.FestivalCardService = FestivalCardService;
|
|
576
677
|
exports.FestivalCardStudio = FestivalCardStudio;
|