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