sa2kit 1.6.57 → 1.6.58

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 (145) hide show
  1. package/dist/AliyunOSSProvider-KSYW2IOG.js +15 -0
  2. package/dist/{AliyunOSSProvider-2FARPAQD.js.map → AliyunOSSProvider-KSYW2IOG.js.map} +1 -1
  3. package/dist/AliyunOSSProvider-TBK3G7YK.mjs +6 -0
  4. package/dist/{AliyunOSSProvider-UMVGVBDJ.mjs.map → AliyunOSSProvider-TBK3G7YK.mjs.map} +1 -1
  5. package/dist/LocalStorageProvider-2DGYRQAB.mjs +6 -0
  6. package/dist/{LocalStorageProvider-PYOHETJV.mjs.map → LocalStorageProvider-2DGYRQAB.mjs.map} +1 -1
  7. package/dist/LocalStorageProvider-SSRW3ZJW.js +15 -0
  8. package/dist/{LocalStorageProvider-JQF5WK5H.js.map → LocalStorageProvider-SSRW3ZJW.js.map} +1 -1
  9. package/dist/UniversalFileService-336GFY6N.mjs +6 -0
  10. package/dist/{UniversalFileService-TNYKO6JN.mjs.map → UniversalFileService-336GFY6N.mjs.map} +1 -1
  11. package/dist/UniversalFileService-J6ET6KZK.js +15 -0
  12. package/dist/{UniversalFileService-RBV6EN5J.js.map → UniversalFileService-J6ET6KZK.js.map} +1 -1
  13. package/dist/calendar/index.js +11 -11
  14. package/dist/calendar/index.mjs +4 -4
  15. package/dist/chunk-25OFOKNF.js +171 -0
  16. package/dist/chunk-25OFOKNF.js.map +1 -0
  17. package/dist/chunk-3DXPQ4YV.mjs +165 -0
  18. package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
  19. package/dist/{chunk-4VJQZSPU.mjs → chunk-3NHAT7D4.mjs} +3 -4
  20. package/dist/chunk-3NHAT7D4.mjs.map +1 -0
  21. package/dist/{chunk-3JW4X3AC.mjs → chunk-622Y6LTH.mjs} +3 -3
  22. package/dist/{chunk-3JW4X3AC.mjs.map → chunk-622Y6LTH.mjs.map} +1 -1
  23. package/dist/chunk-CIVO4R6N.mjs +37 -0
  24. package/dist/chunk-CIVO4R6N.mjs.map +1 -0
  25. package/dist/{chunk-6BJ76BYC.mjs → chunk-EGJPS7OL.mjs} +3 -3
  26. package/dist/{chunk-6BJ76BYC.mjs.map → chunk-EGJPS7OL.mjs.map} +1 -1
  27. package/dist/{chunk-U7AQC2Z7.js → chunk-EKIOJEJK.js} +1179 -2002
  28. package/dist/chunk-EKIOJEJK.js.map +1 -0
  29. package/dist/{chunk-53WLQ22S.js → chunk-EOWTOG7Y.js} +6 -6
  30. package/dist/{chunk-53WLQ22S.js.map → chunk-EOWTOG7Y.js.map} +1 -1
  31. package/dist/chunk-HDMIOOZY.mjs +546 -0
  32. package/dist/chunk-HDMIOOZY.mjs.map +1 -0
  33. package/dist/{chunk-MZKATHB7.js → chunk-HHVDOIPV.js} +4 -4
  34. package/dist/{chunk-MZKATHB7.js.map → chunk-HHVDOIPV.js.map} +1 -1
  35. package/dist/chunk-HJ6MH7J7.js +552 -0
  36. package/dist/chunk-HJ6MH7J7.js.map +1 -0
  37. package/dist/chunk-KH6RQ4J5.js +28 -0
  38. package/dist/chunk-KH6RQ4J5.js.map +1 -0
  39. package/dist/{chunk-35CXIK5Y.js → chunk-NCOXT7SK.js} +11 -11
  40. package/dist/{chunk-35CXIK5Y.js.map → chunk-NCOXT7SK.js.map} +1 -1
  41. package/dist/chunk-NZZZUMMX.mjs +784 -0
  42. package/dist/chunk-NZZZUMMX.mjs.map +1 -0
  43. package/dist/{chunk-OBIPI4GU.mjs → chunk-OFYBMMWT.mjs} +4 -4
  44. package/dist/{chunk-OBIPI4GU.mjs.map → chunk-OFYBMMWT.mjs.map} +1 -1
  45. package/dist/{chunk-W2NCOORK.js → chunk-PVLLRDUT.js} +951 -145
  46. package/dist/chunk-PVLLRDUT.js.map +1 -0
  47. package/dist/chunk-Q5EDCKQA.js +336 -0
  48. package/dist/chunk-Q5EDCKQA.js.map +1 -0
  49. package/dist/{chunk-6NMIKAE7.mjs → chunk-SNBILYSH.mjs} +5 -5
  50. package/dist/{chunk-6NMIKAE7.mjs.map → chunk-SNBILYSH.mjs.map} +1 -1
  51. package/dist/{chunk-IPY26RQH.js → chunk-UVHPCLP6.js} +5 -5
  52. package/dist/{chunk-IPY26RQH.js.map → chunk-UVHPCLP6.js.map} +1 -1
  53. package/dist/{chunk-V6BXO6ZS.mjs → chunk-WGD2NBVR.mjs} +835 -38
  54. package/dist/chunk-WGD2NBVR.mjs.map +1 -0
  55. package/dist/{chunk-HYZ5C6FY.mjs → chunk-WS3QZYBI.mjs} +1175 -1996
  56. package/dist/chunk-WS3QZYBI.mjs.map +1 -0
  57. package/dist/{chunk-UR5TU4MW.mjs → chunk-XLR6QUDR.mjs} +3 -3
  58. package/dist/{chunk-UR5TU4MW.mjs.map → chunk-XLR6QUDR.mjs.map} +1 -1
  59. package/dist/chunk-YMS6BPXS.js +807 -0
  60. package/dist/chunk-YMS6BPXS.js.map +1 -0
  61. package/dist/chunk-YOTQG4NP.mjs +314 -0
  62. package/dist/chunk-YOTQG4NP.mjs.map +1 -0
  63. package/dist/chunk-ZGVB35L2.mjs +25 -0
  64. package/dist/chunk-ZGVB35L2.mjs.map +1 -0
  65. package/dist/chunk-ZRAW3HXA.js +43 -0
  66. package/dist/chunk-ZRAW3HXA.js.map +1 -0
  67. package/dist/{chunk-4XXIBWCO.js → chunk-ZRWED7Q6.js} +66 -66
  68. package/dist/{chunk-4XXIBWCO.js.map → chunk-ZRWED7Q6.js.map} +1 -1
  69. package/dist/{chunk-DVENFCQY.js → chunk-ZWQJSZEY.js} +4 -5
  70. package/dist/chunk-ZWQJSZEY.js.map +1 -0
  71. package/dist/components/index.js +104 -104
  72. package/dist/components/index.mjs +4 -4
  73. package/dist/index.js +146 -148
  74. package/dist/index.js.map +1 -1
  75. package/dist/index.mjs +8 -11
  76. package/dist/index.mjs.map +1 -1
  77. package/dist/logger/index.js +7 -7
  78. package/dist/logger/index.mjs +1 -4
  79. package/dist/mikuFusionGame/index.js +4 -4
  80. package/dist/mikuFusionGame/index.mjs +3 -3
  81. package/dist/portfolio/index.js +10 -10
  82. package/dist/portfolio/index.mjs +5 -5
  83. package/dist/showmasterpiece/db/index.js +42 -42
  84. package/dist/showmasterpiece/db/index.mjs +1 -1
  85. package/dist/showmasterpiece/index.js +143 -144
  86. package/dist/showmasterpiece/index.js.map +1 -1
  87. package/dist/showmasterpiece/index.mjs +7 -9
  88. package/dist/showmasterpiece/index.mjs.map +1 -1
  89. package/dist/showmasterpiece/logic/index.js +19 -19
  90. package/dist/showmasterpiece/logic/index.mjs +2 -2
  91. package/dist/showmasterpiece/server/index.js +42 -42
  92. package/dist/showmasterpiece/server/index.mjs +1 -1
  93. package/dist/showmasterpiece/ui/web/index.js +34 -34
  94. package/dist/showmasterpiece/ui/web/index.mjs +6 -6
  95. package/dist/universalExport/server/index.js +2 -4
  96. package/dist/universalExport/server/index.js.map +1 -1
  97. package/dist/universalExport/server/index.mjs +1 -3
  98. package/dist/universalExport/server/index.mjs.map +1 -1
  99. package/dist/universalFile/index.js +6 -9
  100. package/dist/universalFile/index.js.map +1 -1
  101. package/dist/universalFile/index.mjs +1 -5
  102. package/dist/universalFile/index.mjs.map +1 -1
  103. package/dist/universalFile/server/index.js +31 -64
  104. package/dist/universalFile/server/index.js.map +1 -1
  105. package/dist/universalFile/server/index.mjs +7 -42
  106. package/dist/universalFile/server/index.mjs.map +1 -1
  107. package/dist/utils/index.js +11 -11
  108. package/dist/utils/index.mjs +2 -2
  109. package/package.json +1 -1
  110. package/dist/AliyunOSSProvider-2FARPAQD.js +0 -15
  111. package/dist/AliyunOSSProvider-UMVGVBDJ.mjs +0 -9
  112. package/dist/LocalStorageProvider-JQF5WK5H.js +0 -15
  113. package/dist/LocalStorageProvider-PYOHETJV.mjs +0 -9
  114. package/dist/UniversalFileService-RBV6EN5J.js +0 -15
  115. package/dist/UniversalFileService-TNYKO6JN.mjs +0 -9
  116. package/dist/chunk-4NFOSCM6.js +0 -34
  117. package/dist/chunk-4NFOSCM6.js.map +0 -1
  118. package/dist/chunk-4VJQZSPU.mjs.map +0 -1
  119. package/dist/chunk-6AHYPPUP.js +0 -344
  120. package/dist/chunk-6AHYPPUP.js.map +0 -1
  121. package/dist/chunk-76V7EKBX.mjs +0 -796
  122. package/dist/chunk-76V7EKBX.mjs.map +0 -1
  123. package/dist/chunk-ACLOJXXE.js +0 -195
  124. package/dist/chunk-ACLOJXXE.js.map +0 -1
  125. package/dist/chunk-AEXPAH7Z.mjs +0 -32
  126. package/dist/chunk-AEXPAH7Z.mjs.map +0 -1
  127. package/dist/chunk-CFGX3EKK.js +0 -560
  128. package/dist/chunk-CFGX3EKK.js.map +0 -1
  129. package/dist/chunk-D2HXMGXS.js +0 -46
  130. package/dist/chunk-D2HXMGXS.js.map +0 -1
  131. package/dist/chunk-DVENFCQY.js.map +0 -1
  132. package/dist/chunk-HYZ5C6FY.mjs.map +0 -1
  133. package/dist/chunk-K7WNCB4V.mjs +0 -554
  134. package/dist/chunk-K7WNCB4V.mjs.map +0 -1
  135. package/dist/chunk-L4ZYBFB2.mjs +0 -44
  136. package/dist/chunk-L4ZYBFB2.mjs.map +0 -1
  137. package/dist/chunk-M4HGHTIC.js +0 -820
  138. package/dist/chunk-M4HGHTIC.js.map +0 -1
  139. package/dist/chunk-PXWDQFWV.mjs +0 -192
  140. package/dist/chunk-PXWDQFWV.mjs.map +0 -1
  141. package/dist/chunk-U7AQC2Z7.js.map +0 -1
  142. package/dist/chunk-V6BXO6ZS.mjs.map +0 -1
  143. package/dist/chunk-VTGPHE4Z.mjs +0 -322
  144. package/dist/chunk-VTGPHE4Z.mjs.map +0 -1
  145. package/dist/chunk-W2NCOORK.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { __esm, __require, __export, __toCommonJS } from './chunk-WMJKH4XE.mjs';
1
+ import { __esm, __export, __toCommonJS } from './chunk-WMJKH4XE.mjs';
2
2
  import React, { createContext, useState, useCallback, useEffect, useContext } from 'react';
3
3
 
4
4
  // src/showmasterpiece/services/masterpiecesService.ts
@@ -672,178 +672,348 @@ var init_masterpiecesConfigService = __esm({
672
672
  };
673
673
  }
674
674
  });
675
-
676
- // src/showmasterpiece/services/cartHistoryService.ts
677
- var CART_HISTORY_STORAGE_KEY_BASE, CART_HISTORY_STORAGE_KEY, CartHistoryService, getCartHistory, updateBookingStatus, deleteHistoryRecord, clearUserHistory, getAllHistory, getStatistics, saveCartHistory;
678
- var init_cartHistoryService = __esm({
679
- "src/showmasterpiece/services/cartHistoryService.ts"() {
680
- CART_HISTORY_STORAGE_KEY_BASE = "showmasterpiece_cart_history";
681
- CART_HISTORY_STORAGE_KEY = CART_HISTORY_STORAGE_KEY_BASE;
682
- CartHistoryService = class {
683
- /**
684
- * 生成唯一ID
685
- */
686
- // static generateId(): string {
687
- // return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
688
- // }
689
- /**
690
- * 获取用户购物车历史记录
691
- *
692
- * @param qqNumber 用户QQ号
693
- * @param phoneNumber 用户手机号
694
- * @returns 购物车历史记录
695
- */
696
- static async getCartHistory(qqNumber, phoneNumber) {
675
+ var useMasterpiecesConfig;
676
+ var init_useMasterpiecesConfig = __esm({
677
+ "src/showmasterpiece/logic/hooks/useMasterpiecesConfig.ts"() {
678
+ init_masterpiecesConfigService();
679
+ useMasterpiecesConfig = () => {
680
+ const [config, setConfig] = useState(null);
681
+ const [collections, setCollections] = useState([]);
682
+ const [categories, setCategories] = useState([]);
683
+ const [tags, setTags] = useState([]);
684
+ const [loading, setLoading] = useState(true);
685
+ const [error, setError] = useState(null);
686
+ const [refreshCounter, setRefreshCounter] = useState(0);
687
+ useEffect(() => {
688
+ loadData();
689
+ }, []);
690
+ const loadData = async () => {
691
+ console.log("\u{1F504} [Hook] \u5F00\u59CB\u52A0\u8F7D\u6570\u636E...");
697
692
  try {
698
- const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
699
- if (historyData) {
700
- const allHistory = JSON.parse(historyData);
701
- const userHistory = allHistory.filter(
702
- (record) => record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
703
- );
704
- const processedHistory = userHistory.map((record) => ({
705
- ...record,
706
- submittedAt: new Date(record.submittedAt),
707
- items: record.items.map((item) => ({
708
- ...item,
709
- addedAt: new Date(item.addedAt)
710
- }))
711
- }));
712
- processedHistory.sort((a, b) => b.submittedAt.getTime() - a.submittedAt.getTime());
713
- return {
714
- records: processedHistory,
715
- totalRecords: processedHistory.length
716
- };
693
+ setLoading(true);
694
+ setError(null);
695
+ console.log("\u{1F4E1} [Hook] \u5E76\u884C\u8BF7\u6C42\u6240\u6709\u6570\u636E...");
696
+ const timestamp = Date.now();
697
+ const [configData, collectionsResponse, categoriesData, tagsData] = await Promise.all([
698
+ getConfig(),
699
+ fetch(`/api/showmasterpiece/collections?_t=${timestamp}&nocache=true&includeImages=true`, {
700
+ headers: {
701
+ "Cache-Control": "no-cache",
702
+ "Pragma": "no-cache"
703
+ }
704
+ }).then((r) => r.json()),
705
+ getCategories(),
706
+ getTags()
707
+ ]);
708
+ const collectionsData = collectionsResponse.data || [];
709
+ console.log("\u2705 [Hook] \u6570\u636E\u52A0\u8F7D\u5B8C\u6210:", {
710
+ \u914D\u7F6E: configData ? "\u5DF2\u52A0\u8F7D" : "\u672A\u52A0\u8F7D",
711
+ \u753B\u96C6\u6570\u91CF: collectionsData.length,
712
+ \u5206\u7C7B\u6570\u91CF: categoriesData.length,
713
+ \u6807\u7B7E\u6570\u91CF: tagsData.length
714
+ });
715
+ if (collectionsData.length > 0) {
716
+ console.log("\u{1F4DA} [Hook] \u753B\u96C6\u8BE6\u60C5:");
717
+ collectionsData.forEach((collection, index) => {
718
+ console.log(` ${index + 1}. ${collection.title} - \u4F5C\u54C1\u6570\u91CF: ${collection.pages.length}`);
719
+ if (collection.pages.length > 0) {
720
+ collection.pages.forEach((page, pageIndex) => {
721
+ console.log(` ${pageIndex + 1}. ${page.title} (ID: ${page.id})`);
722
+ });
723
+ }
724
+ });
717
725
  }
718
- } catch (error) {
719
- console.error("\u8BFB\u53D6\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
720
- }
721
- return {
722
- records: [],
723
- totalRecords: 0
724
- };
725
- }
726
- /**
727
- * 保存购物车历史记录
728
- *
729
- * @param historyItem 历史记录项
730
- */
731
- static async saveCartHistory(historyItem) {
732
- try {
733
- const generateId = () => `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
734
- const newHistoryItem = {
735
- ...historyItem,
736
- id: generateId(),
737
- submittedAt: /* @__PURE__ */ new Date()
726
+ setConfig(configData);
727
+ setCollections(collectionsData);
728
+ setCategories(categoriesData);
729
+ setTags(tagsData);
730
+ console.log("\u{1F4BE} [Hook] \u72B6\u6001\u66F4\u65B0\u5B8C\u6210");
731
+ return {
732
+ config: configData,
733
+ collections: collectionsData,
734
+ // 这里已经是提取后的数组数据
735
+ categories: categoriesData,
736
+ tags: tagsData
738
737
  };
739
- const existingData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
740
- const allHistory = existingData ? JSON.parse(existingData) : [];
741
- allHistory.push(newHistoryItem);
742
- localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
743
- console.log("\u2705 \u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u4FDD\u5B58\u6210\u529F:", {
744
- id: newHistoryItem.id,
745
- qqNumber: newHistoryItem.qqNumber,
746
- itemCount: newHistoryItem.items.length
738
+ } catch (err) {
739
+ console.error("\u274C [Hook] \u52A0\u8F7D\u6570\u636E\u5931\u8D25:", err);
740
+ console.error("\u9519\u8BEF\u8BE6\u60C5:", {
741
+ message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
742
+ stack: err instanceof Error ? err.stack : void 0
747
743
  });
748
- return newHistoryItem;
749
- } catch (error) {
750
- console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
751
- throw new Error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
744
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
745
+ throw err;
746
+ } finally {
747
+ setLoading(false);
748
+ console.log("\u{1F3C1} [Hook] \u6570\u636E\u52A0\u8F7D\u6D41\u7A0B\u7ED3\u675F");
752
749
  }
753
- }
754
- /**
755
- * 更新预订状态
756
- *
757
- * @param qqNumber 用户QQ号
758
- * @param phoneNumber 用户手机号
759
- * @param historyId 历史记录ID
760
- * @param status 新状态
761
- * @param bookingIds 预订ID列表
762
- */
763
- static async updateBookingStatus(qqNumber, phoneNumber, historyId, status, bookingIds) {
764
- try {
765
- const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
766
- if (historyData) {
767
- const allHistory = JSON.parse(historyData);
768
- const recordIndex = allHistory.findIndex(
769
- (record) => record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
770
- );
771
- if (recordIndex !== -1) {
772
- const record = allHistory[recordIndex];
773
- if (!record) {
774
- return;
775
- }
776
- record.status = status;
777
- if (bookingIds) {
778
- record.bookingIds = bookingIds;
779
- }
780
- localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
781
- console.log("\u2705 \u9884\u8BA2\u72B6\u6001\u66F4\u65B0\u6210\u529F:", {
782
- historyId,
783
- status,
784
- bookingIds
785
- });
750
+ };
751
+ const handleApiError = (error2, operation) => {
752
+ if (error2 instanceof Error) {
753
+ if (error2.message.includes("413") || error2.message.includes("\u592A\u5927")) {
754
+ throw new Error("\u56FE\u7247\u6587\u4EF6\u8FC7\u5927\uFF0C\u8BF7\u4F7F\u7528\u538B\u7F29\u540E\u7684\u56FE\u7247");
755
+ }
756
+ if (error2.message.includes("401")) {
757
+ throw new Error("\u6CA1\u6709\u6743\u9650\u6267\u884C\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u5148\u767B\u5F55");
758
+ }
759
+ if (error2.message.includes("404") || error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728")) {
760
+ throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
761
+ }
762
+ if (error2.message.includes("409")) {
763
+ if (error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728") || error2.message.includes("\u5DF2\u88AB\u5220\u9664")) {
764
+ throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
786
765
  }
766
+ throw new Error(error2.message);
787
767
  }
788
- } catch (error) {
789
- console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
790
- throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
768
+ throw new Error(`${operation}\u5931\u8D25\uFF1A${error2.message}`);
791
769
  }
792
- }
793
- /**
794
- * 删除历史记录
795
- *
796
- * @param qqNumber 用户QQ号
797
- * @param phoneNumber 用户手机号
798
- * @param historyId 历史记录ID
799
- */
800
- static async deleteHistoryRecord(qqNumber, phoneNumber, historyId) {
770
+ throw new Error(`${operation}\u5931\u8D25\uFF1A\u672A\u77E5\u9519\u8BEF`);
771
+ };
772
+ const handleUpdateConfig = async (configData) => {
801
773
  try {
802
- const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
803
- if (historyData) {
804
- const allHistory = JSON.parse(historyData);
805
- const filteredHistory = allHistory.filter(
806
- (record) => !(record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
807
- );
808
- localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
809
- console.log("\u2705 \u5386\u53F2\u8BB0\u5F55\u5220\u9664\u6210\u529F:", { historyId });
810
- }
811
- } catch (error) {
812
- console.error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
813
- throw new Error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
774
+ const updatedConfig = await updateConfig(configData);
775
+ setConfig(updatedConfig);
776
+ } catch (err) {
777
+ handleApiError(err, "\u66F4\u65B0\u914D\u7F6E");
814
778
  }
815
- }
816
- /**
817
- * 清空用户所有历史记录
818
- *
819
- * @param qqNumber 用户QQ号
820
- * @param phoneNumber 用户手机号
821
- */
822
- static async clearUserHistory(qqNumber, phoneNumber) {
779
+ };
780
+ const handleResetConfig = async () => {
823
781
  try {
824
- const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
825
- if (historyData) {
826
- const allHistory = JSON.parse(historyData);
827
- const filteredHistory = allHistory.filter(
828
- (record) => !(record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
829
- );
830
- localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
831
- console.log("\u2705 \u7528\u6237\u5386\u53F2\u8BB0\u5F55\u6E05\u7A7A\u6210\u529F:", { qqNumber, phoneNumber });
832
- }
833
- } catch (error) {
834
- console.error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
835
- throw new Error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
782
+ const resetConfigData = await resetConfig();
783
+ setConfig(resetConfigData);
784
+ } catch (err) {
785
+ handleApiError(err, "\u91CD\u7F6E\u914D\u7F6E");
836
786
  }
837
- }
838
- /**
839
- * 获取所有历史记录(管理员功能)
840
- */
841
- static async getAllHistory() {
842
- try {
787
+ };
788
+ const handleCreateCollection = async (collectionData) => {
789
+ try {
790
+ const newCollection = await createCollection(collectionData);
791
+ await loadData();
792
+ } catch (err) {
793
+ handleApiError(err, "\u521B\u5EFA\u753B\u96C6");
794
+ }
795
+ };
796
+ const handleUpdateCollection = async (id, collectionData) => {
797
+ try {
798
+ const updatedCollection = await updateCollection(id, collectionData);
799
+ await loadData();
800
+ } catch (err) {
801
+ handleApiError(err, "\u66F4\u65B0\u753B\u96C6");
802
+ }
803
+ };
804
+ const handleDeleteCollection = async (id) => {
805
+ try {
806
+ await deleteCollection(id);
807
+ await loadData();
808
+ } catch (err) {
809
+ handleApiError(err, "\u5220\u9664\u753B\u96C6");
810
+ }
811
+ };
812
+ const handleAddArtworkToCollection = async (collectionId, artworkData) => {
813
+ console.log("\u{1F3AF} [Hook] \u5F00\u59CB\u6DFB\u52A0\u4F5C\u54C1\u5230\u753B\u96C6:", {
814
+ collectionId,
815
+ title: artworkData.title,
816
+ number: artworkData.number,
817
+ imageSize: artworkData.image ? `${artworkData.image.length} chars` : "null",
818
+ description: artworkData.description?.substring(0, 50) + (artworkData.description && artworkData.description.length > 50 ? "..." : "")
819
+ });
820
+ try {
821
+ console.log("\u{1F4DE} [Hook] \u8C03\u7528API\u670D\u52A1...");
822
+ const newArtwork = await addArtworkToCollection(collectionId, artworkData);
823
+ console.log("\u2705 [Hook] API\u8C03\u7528\u6210\u529F\uFF0C\u8FD4\u56DE\u4F5C\u54C1:", {
824
+ id: newArtwork.id,
825
+ title: newArtwork.title,
826
+ number: newArtwork.number
827
+ });
828
+ console.log("\u{1F504} [Hook] \u91CD\u65B0\u52A0\u8F7D\u6570\u636E\u4EE5\u786E\u4FDD\u4E0E\u6570\u636E\u5E93\u5B8C\u5168\u540C\u6B65...");
829
+ const reloadedData = await loadData();
830
+ console.log("\u2705 [Hook] \u6570\u636E\u91CD\u65B0\u52A0\u8F7D\u5B8C\u6210");
831
+ await new Promise((resolve) => setTimeout(resolve, 50));
832
+ const targetCollection = reloadedData.collections.find((c) => c.id === collectionId);
833
+ if (targetCollection) {
834
+ const newArtworkInCollection = targetCollection.pages.find((p) => p.id === newArtwork.id);
835
+ if (newArtworkInCollection) {
836
+ console.log("\u2705 [Hook] \u9A8C\u8BC1\u6210\u529F\uFF1A\u65B0\u4F5C\u54C1\u5DF2\u5728\u753B\u96C6\u4E2D", {
837
+ artworkId: newArtwork.id,
838
+ collectionId,
839
+ artworkTitle: newArtworkInCollection.title
840
+ });
841
+ } else {
842
+ console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u65B0\u4F5C\u54C1\u4E0D\u5728\u91CD\u65B0\u52A0\u8F7D\u7684\u6570\u636E\u4E2D", {
843
+ expectedArtworkId: newArtwork.id,
844
+ collectionId,
845
+ currentArtworks: targetCollection.pages.map((p) => ({ id: p.id, title: p.title }))
846
+ });
847
+ console.log("\u{1F504} [Hook] \u518D\u6B21\u5C1D\u8BD5\u91CD\u65B0\u52A0\u8F7D\u6570\u636E...");
848
+ await loadData();
849
+ }
850
+ } else {
851
+ console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u627E\u4E0D\u5230\u76EE\u6807\u753B\u96C6", {
852
+ collectionId,
853
+ availableCollections: reloadedData.collections.map((c) => ({ id: c.id, title: c.title }))
854
+ });
855
+ }
856
+ console.log("\u{1F389} [Hook] \u5F3A\u5236\u66F4\u65B0\u72B6\u6001\u4EE5\u786E\u4FDDUI\u540C\u6B65...");
857
+ setCollections([...reloadedData.collections]);
858
+ setRefreshCounter((prev) => prev + 1);
859
+ console.log("\u{1F525} [Hook] \u89E6\u53D1\u5F3A\u5236\u91CD\u65B0\u6E32\u67D3");
860
+ } catch (err) {
861
+ console.error("\u274C [Hook] \u6DFB\u52A0\u4F5C\u54C1\u5931\u8D25:", err);
862
+ console.error("\u9519\u8BEF\u8BE6\u60C5:", {
863
+ message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
864
+ collectionId,
865
+ artworkTitle: artworkData.title
866
+ });
867
+ handleApiError(err, "\u6DFB\u52A0\u4F5C\u54C1");
868
+ }
869
+ };
870
+ const handleUpdateArtwork = async (collectionId, artworkId, artworkData) => {
871
+ try {
872
+ const updatedArtwork = await updateArtwork(collectionId, artworkId, artworkData);
873
+ await loadData();
874
+ } catch (err) {
875
+ handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1");
876
+ }
877
+ };
878
+ const handleDeleteArtwork = async (collectionId, artworkId) => {
879
+ try {
880
+ await deleteArtwork(collectionId, artworkId);
881
+ await loadData();
882
+ } catch (err) {
883
+ handleApiError(err, "\u5220\u9664\u4F5C\u54C1");
884
+ }
885
+ };
886
+ const handleMoveArtworkUp = async (collectionId, artworkId) => {
887
+ try {
888
+ await moveArtworkUp(collectionId, artworkId);
889
+ await updateCollectionArtworks(collectionId);
890
+ } catch (err) {
891
+ handleApiError(err, "\u4E0A\u79FB\u4F5C\u54C1");
892
+ }
893
+ };
894
+ const handleMoveArtworkDown = async (collectionId, artworkId) => {
895
+ try {
896
+ await moveArtworkDown(collectionId, artworkId);
897
+ await updateCollectionArtworks(collectionId);
898
+ } catch (err) {
899
+ handleApiError(err, "\u4E0B\u79FB\u4F5C\u54C1");
900
+ }
901
+ };
902
+ const handleUpdateArtworkOrder = async (collectionId, artworkOrders) => {
903
+ try {
904
+ await updateArtworkOrder(collectionId, artworkOrders);
905
+ await updateCollectionArtworks(collectionId);
906
+ } catch (err) {
907
+ handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1\u987A\u5E8F");
908
+ }
909
+ };
910
+ const updateCollectionArtworks = async (collectionId) => {
911
+ try {
912
+ const updatedArtworks = await getArtworksByCollection(collectionId);
913
+ setCollections(
914
+ (prevCollections) => prevCollections.map(
915
+ (collection) => collection.id === collectionId ? { ...collection, pages: updatedArtworks } : collection
916
+ )
917
+ );
918
+ } catch (err) {
919
+ console.error("\u66F4\u65B0\u753B\u96C6\u4F5C\u54C1\u6570\u636E\u5931\u8D25:", err);
920
+ await loadData();
921
+ }
922
+ };
923
+ const handleMoveCollectionUp = async (collectionId) => {
924
+ try {
925
+ await moveCollectionUp(collectionId);
926
+ await updateCollectionsData();
927
+ } catch (err) {
928
+ handleApiError(err, "\u4E0A\u79FB\u753B\u96C6");
929
+ }
930
+ };
931
+ const handleMoveCollectionDown = async (collectionId) => {
932
+ try {
933
+ await moveCollectionDown(collectionId);
934
+ await updateCollectionsData();
935
+ } catch (err) {
936
+ handleApiError(err, "\u4E0B\u79FB\u753B\u96C6");
937
+ }
938
+ };
939
+ const handleUpdateCollectionOrder = async (collectionOrders) => {
940
+ try {
941
+ await updateCollectionOrder(collectionOrders);
942
+ await updateCollectionsData();
943
+ } catch (err) {
944
+ handleApiError(err, "\u66F4\u65B0\u753B\u96C6\u987A\u5E8F");
945
+ }
946
+ };
947
+ const updateCollectionsData = async () => {
948
+ try {
949
+ const updatedCollections = await getAllCollections();
950
+ setCollections(updatedCollections);
951
+ } catch (err) {
952
+ console.error("\u66F4\u65B0\u753B\u96C6\u6570\u636E\u5931\u8D25:", err);
953
+ await loadData();
954
+ }
955
+ };
956
+ return {
957
+ // 数据
958
+ config,
959
+ collections,
960
+ categories,
961
+ tags,
962
+ loading,
963
+ error,
964
+ refreshCounter,
965
+ // 方法
966
+ updateConfig: handleUpdateConfig,
967
+ resetConfig: handleResetConfig,
968
+ createCollection: handleCreateCollection,
969
+ updateCollection: handleUpdateCollection,
970
+ deleteCollection: handleDeleteCollection,
971
+ addArtworkToCollection: handleAddArtworkToCollection,
972
+ updateArtwork: handleUpdateArtwork,
973
+ deleteArtwork: handleDeleteArtwork,
974
+ // 新增:作品排序方法
975
+ moveArtworkUp: handleMoveArtworkUp,
976
+ moveArtworkDown: handleMoveArtworkDown,
977
+ updateArtworkOrder: handleUpdateArtworkOrder,
978
+ // 新增:画集排序方法
979
+ moveCollectionUp: handleMoveCollectionUp,
980
+ moveCollectionDown: handleMoveCollectionDown,
981
+ updateCollectionOrder: handleUpdateCollectionOrder,
982
+ refreshData: loadData
983
+ };
984
+ };
985
+ }
986
+ });
987
+
988
+ // src/showmasterpiece/services/cartHistoryService.ts
989
+ var CART_HISTORY_STORAGE_KEY_BASE, CART_HISTORY_STORAGE_KEY, CartHistoryService, getCartHistory, updateBookingStatus, deleteHistoryRecord, clearUserHistory, getAllHistory, getStatistics, saveCartHistory;
990
+ var init_cartHistoryService = __esm({
991
+ "src/showmasterpiece/services/cartHistoryService.ts"() {
992
+ CART_HISTORY_STORAGE_KEY_BASE = "showmasterpiece_cart_history";
993
+ CART_HISTORY_STORAGE_KEY = CART_HISTORY_STORAGE_KEY_BASE;
994
+ CartHistoryService = class {
995
+ /**
996
+ * 生成唯一ID
997
+ */
998
+ // static generateId(): string {
999
+ // return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1000
+ // }
1001
+ /**
1002
+ * 获取用户购物车历史记录
1003
+ *
1004
+ * @param qqNumber 用户QQ号
1005
+ * @param phoneNumber 用户手机号
1006
+ * @returns 购物车历史记录
1007
+ */
1008
+ static async getCartHistory(qqNumber, phoneNumber) {
1009
+ try {
843
1010
  const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
844
1011
  if (historyData) {
845
1012
  const allHistory = JSON.parse(historyData);
846
- return allHistory.map((record) => ({
1013
+ const userHistory = allHistory.filter(
1014
+ (record) => record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
1015
+ );
1016
+ const processedHistory = userHistory.map((record) => ({
847
1017
  ...record,
848
1018
  submittedAt: new Date(record.submittedAt),
849
1019
  items: record.items.map((item) => ({
@@ -851,27 +1021,169 @@ var init_cartHistoryService = __esm({
851
1021
  addedAt: new Date(item.addedAt)
852
1022
  }))
853
1023
  }));
1024
+ processedHistory.sort((a, b) => b.submittedAt.getTime() - a.submittedAt.getTime());
1025
+ return {
1026
+ records: processedHistory,
1027
+ totalRecords: processedHistory.length
1028
+ };
854
1029
  }
855
1030
  } catch (error) {
856
- console.error("\u8BFB\u53D6\u6240\u6709\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
1031
+ console.error("\u8BFB\u53D6\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
857
1032
  }
858
- return [];
1033
+ return {
1034
+ records: [],
1035
+ totalRecords: 0
1036
+ };
859
1037
  }
860
1038
  /**
861
- * 获取统计数据
1039
+ * 保存购物车历史记录
1040
+ *
1041
+ * @param historyItem 历史记录项
862
1042
  */
863
- static async getStatistics() {
1043
+ static async saveCartHistory(historyItem) {
864
1044
  try {
865
- const allHistory = await this.getAllHistory();
866
- const totalRecords = allHistory.length;
867
- const uniqueUsers = new Set(
868
- allHistory.map((record) => `${record.qqNumber}_${record.phoneNumber}`)
869
- );
870
- const totalUsers = uniqueUsers.size;
871
- let totalItems = 0;
872
- let totalRevenue = 0;
873
- allHistory.forEach((record) => {
874
- totalItems += record.totalQuantity;
1045
+ const generateId = () => `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1046
+ const newHistoryItem = {
1047
+ ...historyItem,
1048
+ id: generateId(),
1049
+ submittedAt: /* @__PURE__ */ new Date()
1050
+ };
1051
+ const existingData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
1052
+ const allHistory = existingData ? JSON.parse(existingData) : [];
1053
+ allHistory.push(newHistoryItem);
1054
+ localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
1055
+ console.log("\u2705 \u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u4FDD\u5B58\u6210\u529F:", {
1056
+ id: newHistoryItem.id,
1057
+ qqNumber: newHistoryItem.qqNumber,
1058
+ itemCount: newHistoryItem.items.length
1059
+ });
1060
+ return newHistoryItem;
1061
+ } catch (error) {
1062
+ console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
1063
+ throw new Error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
1064
+ }
1065
+ }
1066
+ /**
1067
+ * 更新预订状态
1068
+ *
1069
+ * @param qqNumber 用户QQ号
1070
+ * @param phoneNumber 用户手机号
1071
+ * @param historyId 历史记录ID
1072
+ * @param status 新状态
1073
+ * @param bookingIds 预订ID列表
1074
+ */
1075
+ static async updateBookingStatus(qqNumber, phoneNumber, historyId, status, bookingIds) {
1076
+ try {
1077
+ const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
1078
+ if (historyData) {
1079
+ const allHistory = JSON.parse(historyData);
1080
+ const recordIndex = allHistory.findIndex(
1081
+ (record) => record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
1082
+ );
1083
+ if (recordIndex !== -1) {
1084
+ const record = allHistory[recordIndex];
1085
+ if (!record) {
1086
+ return;
1087
+ }
1088
+ record.status = status;
1089
+ if (bookingIds) {
1090
+ record.bookingIds = bookingIds;
1091
+ }
1092
+ localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
1093
+ console.log("\u2705 \u9884\u8BA2\u72B6\u6001\u66F4\u65B0\u6210\u529F:", {
1094
+ historyId,
1095
+ status,
1096
+ bookingIds
1097
+ });
1098
+ }
1099
+ }
1100
+ } catch (error) {
1101
+ console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
1102
+ throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
1103
+ }
1104
+ }
1105
+ /**
1106
+ * 删除历史记录
1107
+ *
1108
+ * @param qqNumber 用户QQ号
1109
+ * @param phoneNumber 用户手机号
1110
+ * @param historyId 历史记录ID
1111
+ */
1112
+ static async deleteHistoryRecord(qqNumber, phoneNumber, historyId) {
1113
+ try {
1114
+ const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
1115
+ if (historyData) {
1116
+ const allHistory = JSON.parse(historyData);
1117
+ const filteredHistory = allHistory.filter(
1118
+ (record) => !(record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
1119
+ );
1120
+ localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
1121
+ console.log("\u2705 \u5386\u53F2\u8BB0\u5F55\u5220\u9664\u6210\u529F:", { historyId });
1122
+ }
1123
+ } catch (error) {
1124
+ console.error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
1125
+ throw new Error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
1126
+ }
1127
+ }
1128
+ /**
1129
+ * 清空用户所有历史记录
1130
+ *
1131
+ * @param qqNumber 用户QQ号
1132
+ * @param phoneNumber 用户手机号
1133
+ */
1134
+ static async clearUserHistory(qqNumber, phoneNumber) {
1135
+ try {
1136
+ const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
1137
+ if (historyData) {
1138
+ const allHistory = JSON.parse(historyData);
1139
+ const filteredHistory = allHistory.filter(
1140
+ (record) => !(record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
1141
+ );
1142
+ localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
1143
+ console.log("\u2705 \u7528\u6237\u5386\u53F2\u8BB0\u5F55\u6E05\u7A7A\u6210\u529F:", { qqNumber, phoneNumber });
1144
+ }
1145
+ } catch (error) {
1146
+ console.error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
1147
+ throw new Error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
1148
+ }
1149
+ }
1150
+ /**
1151
+ * 获取所有历史记录(管理员功能)
1152
+ */
1153
+ static async getAllHistory() {
1154
+ try {
1155
+ const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
1156
+ if (historyData) {
1157
+ const allHistory = JSON.parse(historyData);
1158
+ return allHistory.map((record) => ({
1159
+ ...record,
1160
+ submittedAt: new Date(record.submittedAt),
1161
+ items: record.items.map((item) => ({
1162
+ ...item,
1163
+ addedAt: new Date(item.addedAt)
1164
+ }))
1165
+ }));
1166
+ }
1167
+ } catch (error) {
1168
+ console.error("\u8BFB\u53D6\u6240\u6709\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
1169
+ }
1170
+ return [];
1171
+ }
1172
+ /**
1173
+ * 获取统计数据
1174
+ */
1175
+ static async getStatistics() {
1176
+ try {
1177
+ const allHistory = await this.getAllHistory();
1178
+ const totalRecords = allHistory.length;
1179
+ const uniqueUsers = new Set(
1180
+ allHistory.map((record) => `${record.qqNumber}_${record.phoneNumber}`)
1181
+ );
1182
+ const totalUsers = uniqueUsers.size;
1183
+ let totalItems = 0;
1184
+ let totalRevenue = 0;
1185
+ allHistory.forEach((record) => {
1186
+ totalItems += record.totalQuantity;
875
1187
  totalRevenue += record.totalPrice;
876
1188
  });
877
1189
  return {
@@ -1162,1891 +1474,758 @@ var init_cartService = __esm({
1162
1474
  };
1163
1475
  }
1164
1476
  });
1165
-
1166
- // src/showmasterpiece/services/bookingService.ts
1167
- var BookingService, createBooking, getBookings, getBooking, updateBooking, deleteBooking, getBookableCollections;
1168
- var init_bookingService = __esm({
1169
- "src/showmasterpiece/services/bookingService.ts"() {
1170
- BookingService = class {
1171
- /**
1172
- * 创建新预订
1173
- *
1174
- * @param data 预订数据
1175
- * @returns 创建的预订信息
1176
- */
1177
- static async createBooking(data) {
1178
- const response = await fetch(this.BASE_URL, {
1179
- method: "POST",
1180
- headers: {
1181
- "Content-Type": "application/json"
1182
- },
1183
- body: JSON.stringify(data)
1184
- });
1185
- if (!response.ok) {
1186
- const error = await response.json().catch(() => ({ message: "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25" }));
1187
- throw new Error(error.message || "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25");
1188
- }
1189
- return response.json();
1190
- }
1191
- /**
1192
- * 获取预订列表
1193
- *
1194
- * @param params 查询参数
1195
- * @returns 预订列表和分页信息
1196
- */
1197
- static async getBookings(params = {}) {
1198
- const searchParams = new URLSearchParams();
1199
- if (params.collectionId) {
1200
- searchParams.append("collectionId", params.collectionId.toString());
1201
- }
1202
- if (params.qqNumber) {
1203
- searchParams.append("qqNumber", params.qqNumber);
1204
- }
1205
- if (params.phoneNumber) {
1206
- searchParams.append("phoneNumber", params.phoneNumber);
1207
- }
1208
- if (params.status) {
1209
- searchParams.append("status", params.status);
1210
- }
1211
- if (params.page) {
1212
- searchParams.append("page", params.page.toString());
1213
- }
1214
- if (params.limit) {
1215
- searchParams.append("limit", params.limit.toString());
1216
- }
1217
- const url = `${this.BASE_URL}?${searchParams.toString()}`;
1218
- const response = await fetch(url);
1219
- if (!response.ok) {
1220
- const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25" }));
1221
- throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25");
1222
- }
1223
- return response.json();
1224
- }
1225
- /**
1226
- * 获取单个预订详情
1227
- *
1228
- * @param id 预订ID
1229
- * @returns 预订详情
1230
- */
1231
- static async getBooking(id) {
1232
- const response = await fetch(`${this.BASE_URL}/${id}`);
1233
- if (!response.ok) {
1234
- const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25" }));
1235
- throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25");
1236
- }
1237
- return response.json();
1238
- }
1239
- /**
1240
- * 更新预订状态
1241
- *
1242
- * @param id 预订ID
1243
- * @param data 更新数据
1244
- * @returns 更新后的预订信息
1245
- */
1246
- static async updateBooking(id, data) {
1247
- const response = await fetch(`${this.BASE_URL}/${id}`, {
1248
- method: "PUT",
1249
- headers: {
1250
- "Content-Type": "application/json"
1251
- },
1252
- body: JSON.stringify(data)
1253
- });
1254
- if (!response.ok) {
1255
- const error = await response.json().catch(() => ({ message: "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25" }));
1256
- throw new Error(error.message || "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25");
1257
- }
1258
- return response.json();
1259
- }
1260
- /**
1261
- * 删除预订
1262
- *
1263
- * @param id 预订ID
1264
- */
1265
- static async deleteBooking(id) {
1266
- const response = await fetch(`${this.BASE_URL}/${id}`, {
1267
- method: "DELETE"
1268
- });
1269
- if (!response.ok) {
1270
- const error = await response.json().catch(() => ({ message: "\u5220\u9664\u9884\u8BA2\u5931\u8D25" }));
1271
- throw new Error(error.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
1272
- }
1273
- }
1274
- /**
1275
- * 获取可预订的画集列表
1276
- *
1277
- * @returns 画集简略信息列表
1278
- */
1279
- static async getBookableCollections() {
1280
- const url = `${this.BASE_URL}/collections`;
1281
- console.log("\u{1F4E1} [BookingService] \u83B7\u53D6\u53EF\u9884\u8BA2\u753B\u96C6:", { url });
1282
- const response = await fetch(url);
1283
- if (!response.ok) {
1284
- const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25" }));
1285
- throw new Error(error.message || "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25");
1286
- }
1287
- const data = await response.json();
1288
- if (data.success && Array.isArray(data.data)) {
1289
- console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6`);
1290
- return data.data;
1291
- }
1292
- if (Array.isArray(data)) {
1293
- console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6 (\u517C\u5BB9\u683C\u5F0F)`);
1294
- return data;
1295
- }
1296
- throw new Error("API\u54CD\u5E94\u683C\u5F0F\u9519\u8BEF");
1477
+ function useCart(userId) {
1478
+ const [state, setState] = useState({
1479
+ cart: {
1480
+ items: [],
1481
+ totalQuantity: 0,
1482
+ totalPrice: 0
1483
+ },
1484
+ loading: false,
1485
+ error: void 0,
1486
+ isCartOpen: false
1487
+ });
1488
+ const loadCart = useCallback(async () => {
1489
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1490
+ try {
1491
+ const cartData = await getCart(userId);
1492
+ setState((prev) => ({
1493
+ ...prev,
1494
+ cart: cartData,
1495
+ loading: false
1496
+ }));
1497
+ } catch (error) {
1498
+ console.error("\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25:", error);
1499
+ setState((prev) => ({
1500
+ ...prev,
1501
+ loading: false,
1502
+ error: error instanceof Error ? error.message : "\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25"
1503
+ }));
1504
+ }
1505
+ }, [userId]);
1506
+ const addItemToCart = useCallback(async (request) => {
1507
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1508
+ try {
1509
+ const updatedCart = await addToCart(request);
1510
+ setState((prev) => ({
1511
+ ...prev,
1512
+ cart: updatedCart,
1513
+ loading: false
1514
+ }));
1515
+ notifyCartUpdate();
1516
+ } catch (error) {
1517
+ console.error("\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25:", error);
1518
+ setState((prev) => ({
1519
+ ...prev,
1520
+ loading: false,
1521
+ error: error instanceof Error ? error.message : "\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25"
1522
+ }));
1523
+ }
1524
+ }, [userId]);
1525
+ const updateItemQuantity = useCallback(async (collectionId, quantity) => {
1526
+ if (quantity <= 0) {
1527
+ await removeItemFromCart(collectionId);
1528
+ return;
1529
+ }
1530
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1531
+ try {
1532
+ const request = {
1533
+ userId,
1534
+ collectionId,
1535
+ quantity
1536
+ };
1537
+ const updatedCart = await updateCartItem(request);
1538
+ setState((prev) => ({
1539
+ ...prev,
1540
+ cart: updatedCart,
1541
+ loading: false
1542
+ }));
1543
+ notifyCartUpdate();
1544
+ } catch (error) {
1545
+ console.error("\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25:", error);
1546
+ setState((prev) => ({
1547
+ ...prev,
1548
+ loading: false,
1549
+ error: error instanceof Error ? error.message : "\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25"
1550
+ }));
1551
+ }
1552
+ }, [userId]);
1553
+ const removeItemFromCart = useCallback(async (collectionId) => {
1554
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1555
+ try {
1556
+ const request = {
1557
+ userId,
1558
+ collectionId
1559
+ };
1560
+ const updatedCart = await removeFromCart(request);
1561
+ setState((prev) => ({
1562
+ ...prev,
1563
+ cart: updatedCart,
1564
+ loading: false
1565
+ }));
1566
+ notifyCartUpdate();
1567
+ } catch (error) {
1568
+ console.error("\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25:", error);
1569
+ setState((prev) => ({
1570
+ ...prev,
1571
+ loading: false,
1572
+ error: error instanceof Error ? error.message : "\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25"
1573
+ }));
1574
+ }
1575
+ }, [userId]);
1576
+ const clearCartItems = useCallback(async () => {
1577
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1578
+ try {
1579
+ await clearCart(userId);
1580
+ setState((prev) => ({
1581
+ ...prev,
1582
+ cart: { items: [], totalQuantity: 0, totalPrice: 0 },
1583
+ loading: false
1584
+ }));
1585
+ notifyCartUpdate();
1586
+ } catch (error) {
1587
+ console.error("\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25:", error);
1588
+ setState((prev) => ({
1589
+ ...prev,
1590
+ loading: false,
1591
+ error: error instanceof Error ? error.message : "\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25"
1592
+ }));
1593
+ }
1594
+ }, [userId]);
1595
+ const checkoutCart = useCallback(async (qqNumber, phoneNumber, notes, pickupMethod = "") => {
1596
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1597
+ try {
1598
+ const request = {
1599
+ qqNumber,
1600
+ phoneNumber,
1601
+ items: state.cart.items.map((item) => ({
1602
+ collectionId: item.collectionId,
1603
+ quantity: item.quantity
1604
+ })),
1605
+ notes,
1606
+ pickupMethod
1607
+ };
1608
+ const result = await batchBooking(request, state.cart);
1609
+ if (result.successCount > 0) {
1610
+ await clearCartItems();
1297
1611
  }
1298
- };
1299
- BookingService.BASE_URL = "/api/showmasterpiece/bookings";
1300
- createBooking = (data) => {
1301
- return BookingService.createBooking(data);
1302
- };
1303
- getBookings = (params) => {
1304
- return BookingService.getBookings(params);
1305
- };
1306
- getBooking = (id) => {
1307
- return BookingService.getBooking(id);
1308
- };
1309
- updateBooking = (id, data) => {
1310
- return BookingService.updateBooking(id, data);
1311
- };
1312
- deleteBooking = (id) => {
1313
- return BookingService.deleteBooking(id);
1314
- };
1315
- getBookableCollections = () => {
1316
- return BookingService.getBookableCollections();
1612
+ setState((prev) => ({ ...prev, loading: false }));
1613
+ return result;
1614
+ } catch (error) {
1615
+ console.error("\u6279\u91CF\u9884\u8BA2\u5931\u8D25:", error);
1616
+ setState((prev) => ({
1617
+ ...prev,
1618
+ loading: false,
1619
+ error: error instanceof Error ? error.message : "\u6279\u91CF\u9884\u8BA2\u5931\u8D25"
1620
+ }));
1621
+ throw error;
1622
+ }
1623
+ }, [state.cart.items, clearCartItems]);
1624
+ const openCart = useCallback(() => {
1625
+ setState((prev) => ({ ...prev, isCartOpen: true }));
1626
+ }, []);
1627
+ const closeCart = useCallback(() => {
1628
+ setState((prev) => ({ ...prev, isCartOpen: false }));
1629
+ }, []);
1630
+ const clearError = useCallback(() => {
1631
+ setState((prev) => ({ ...prev, error: void 0 }));
1632
+ }, []);
1633
+ useEffect(() => {
1634
+ if (userId) {
1635
+ loadCart();
1636
+ }
1637
+ }, [userId, loadCart]);
1638
+ return {
1639
+ // 状态
1640
+ cart: state.cart,
1641
+ loading: state.loading,
1642
+ error: state.error,
1643
+ isCartOpen: state.isCartOpen,
1644
+ // 操作方法
1645
+ loadCart,
1646
+ addItemToCart,
1647
+ updateItemQuantity,
1648
+ removeItemFromCart,
1649
+ clearCartItems,
1650
+ checkoutCart,
1651
+ openCart,
1652
+ closeCart,
1653
+ clearError
1654
+ };
1655
+ }
1656
+ var cartUpdateEvents, CART_UPDATE_EVENT, notifyCartUpdate;
1657
+ var init_useCart = __esm({
1658
+ "src/showmasterpiece/logic/hooks/useCart.ts"() {
1659
+ init_cartService();
1660
+ cartUpdateEvents = new EventTarget();
1661
+ CART_UPDATE_EVENT = "cart-updated";
1662
+ notifyCartUpdate = () => {
1663
+ cartUpdateEvents.dispatchEvent(new Event(CART_UPDATE_EVENT));
1317
1664
  };
1318
1665
  }
1319
1666
  });
1320
1667
 
1321
- // src/showmasterpiece/services/bookingAdminService.ts
1322
- var BookingAdminService, getAllBookings, getBookingStats, forceRefreshAllBookings, forceRefreshBookingStats, updateBookingStatus2, deleteBooking2, exportBookings;
1323
- var init_bookingAdminService = __esm({
1324
- "src/showmasterpiece/services/bookingAdminService.ts"() {
1325
- BookingAdminService = class {
1668
+ // src/showmasterpiece/services/bookingService.ts
1669
+ var BookingService, createBooking, getBookings, getBooking, updateBooking, deleteBooking, getBookableCollections;
1670
+ var init_bookingService = __esm({
1671
+ "src/showmasterpiece/services/bookingService.ts"() {
1672
+ BookingService = class {
1326
1673
  /**
1327
- * 获取所有预订数据
1674
+ * 创建新预订
1675
+ *
1676
+ * @param data 预订数据
1677
+ * @returns 创建的预订信息
1328
1678
  */
1329
- static async getAllBookings(params) {
1330
- try {
1331
- const timestamp = Date.now();
1332
- const randomId = Math.random().toString(36).substring(7);
1333
- const searchParams = new URLSearchParams();
1334
- searchParams.append("t", timestamp.toString());
1335
- searchParams.append("forceRefresh", randomId);
1336
- if (params?.qqNumber) {
1337
- searchParams.append("qqNumber", params.qqNumber);
1338
- }
1339
- if (params?.phoneNumber) {
1340
- searchParams.append("phoneNumber", params.phoneNumber);
1341
- }
1342
- if (params?.status && params.status !== "all") {
1343
- searchParams.append("status", params.status);
1344
- }
1345
- const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
1346
- method: "GET",
1347
- cache: "no-store",
1348
- headers: {
1349
- "Cache-Control": "no-cache, no-store, must-revalidate",
1350
- "Pragma": "no-cache",
1351
- "Expires": "0",
1352
- "X-Requested-With": "XMLHttpRequest"
1353
- }
1354
- });
1355
- if (!response.ok) {
1356
- throw new Error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
1357
- }
1358
- const data = await response.json();
1359
- return data.bookings || [];
1360
- } catch (error) {
1361
- console.error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
1362
- throw error;
1679
+ static async createBooking(data) {
1680
+ const response = await fetch(this.BASE_URL, {
1681
+ method: "POST",
1682
+ headers: {
1683
+ "Content-Type": "application/json"
1684
+ },
1685
+ body: JSON.stringify(data)
1686
+ });
1687
+ if (!response.ok) {
1688
+ const error = await response.json().catch(() => ({ message: "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25" }));
1689
+ throw new Error(error.message || "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25");
1363
1690
  }
1691
+ return response.json();
1364
1692
  }
1365
1693
  /**
1366
- * 强制刷新获取所有预订数据(绕过所有缓存)
1694
+ * 获取预订列表
1695
+ *
1696
+ * @param params 查询参数
1697
+ * @returns 预订列表和分页信息
1367
1698
  */
1368
- static async forceRefreshAllBookings(params) {
1369
- try {
1370
- console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u9884\u8BA2\u6570\u636E...");
1371
- const timestamp = Date.now();
1372
- const randomId = Math.random().toString(36).substring(7);
1373
- const searchParams = new URLSearchParams();
1374
- searchParams.append("t", timestamp.toString());
1375
- searchParams.append("forceRefresh", randomId);
1376
- if (params?.qqNumber) {
1377
- searchParams.append("qqNumber", params.qqNumber);
1378
- }
1379
- if (params?.phoneNumber) {
1380
- searchParams.append("phoneNumber", params.phoneNumber);
1381
- }
1382
- if (params?.status && params.status !== "all") {
1383
- searchParams.append("status", params.status);
1384
- }
1385
- const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
1386
- method: "GET",
1387
- cache: "no-store",
1388
- headers: {
1389
- "Cache-Control": "no-cache, no-store, must-revalidate",
1390
- "Pragma": "no-cache",
1391
- "Expires": "0",
1392
- "X-Requested-With": "XMLHttpRequest",
1393
- "X-Force-Refresh": "true"
1394
- }
1395
- });
1396
- if (!response.ok) {
1397
- throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
1398
- }
1399
- const data = await response.json();
1400
- console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0API\u54CD\u5E94:", {
1401
- bookingsCount: data.bookings?.length || 0,
1402
- timestamp: data._timestamp,
1403
- refreshType: data._refreshType
1404
- });
1405
- return data.bookings || [];
1406
- } catch (error) {
1407
- console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
1408
- throw error;
1699
+ static async getBookings(params = {}) {
1700
+ const searchParams = new URLSearchParams();
1701
+ if (params.collectionId) {
1702
+ searchParams.append("collectionId", params.collectionId.toString());
1703
+ }
1704
+ if (params.qqNumber) {
1705
+ searchParams.append("qqNumber", params.qqNumber);
1706
+ }
1707
+ if (params.phoneNumber) {
1708
+ searchParams.append("phoneNumber", params.phoneNumber);
1709
+ }
1710
+ if (params.status) {
1711
+ searchParams.append("status", params.status);
1712
+ }
1713
+ if (params.page) {
1714
+ searchParams.append("page", params.page.toString());
1715
+ }
1716
+ if (params.limit) {
1717
+ searchParams.append("limit", params.limit.toString());
1718
+ }
1719
+ const url = `${this.BASE_URL}?${searchParams.toString()}`;
1720
+ const response = await fetch(url);
1721
+ if (!response.ok) {
1722
+ const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25" }));
1723
+ throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25");
1409
1724
  }
1725
+ return response.json();
1410
1726
  }
1411
1727
  /**
1412
- * 获取预订统计信息
1728
+ * 获取单个预订详情
1729
+ *
1730
+ * @param id 预订ID
1731
+ * @returns 预订详情
1413
1732
  */
1414
- static async getBookingStats(params) {
1415
- try {
1416
- const timestamp = Date.now();
1417
- const randomId = Math.random().toString(36).substring(7);
1418
- const searchParams = new URLSearchParams();
1419
- searchParams.append("t", timestamp.toString());
1420
- searchParams.append("forceRefresh", randomId);
1421
- if (params?.qqNumber) {
1422
- searchParams.append("qqNumber", params.qqNumber);
1423
- }
1424
- if (params?.phoneNumber) {
1425
- searchParams.append("phoneNumber", params.phoneNumber);
1426
- }
1427
- if (params?.status && params.status !== "all") {
1428
- searchParams.append("status", params.status);
1429
- }
1430
- const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
1431
- method: "GET",
1432
- cache: "no-store",
1433
- headers: {
1434
- "Cache-Control": "no-cache, no-store, must-revalidate",
1435
- "Pragma": "no-cache",
1436
- "Expires": "0",
1437
- "X-Requested-With": "XMLHttpRequest"
1438
- }
1439
- });
1440
- if (!response.ok) {
1441
- throw new Error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
1442
- }
1443
- const data = await response.json();
1444
- return data.stats || {
1445
- totalBookings: 0,
1446
- pendingBookings: 0,
1447
- confirmedBookings: 0,
1448
- completedBookings: 0,
1449
- cancelledBookings: 0,
1450
- totalQuantity: 0,
1451
- totalRevenue: 0,
1452
- totalAmount: 0,
1453
- todayBookings: 0,
1454
- weekBookings: 0
1455
- };
1456
- } catch (error) {
1457
- console.error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
1458
- throw error;
1733
+ static async getBooking(id) {
1734
+ const response = await fetch(`${this.BASE_URL}/${id}`);
1735
+ if (!response.ok) {
1736
+ const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25" }));
1737
+ throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25");
1459
1738
  }
1739
+ return response.json();
1460
1740
  }
1461
1741
  /**
1462
- * 强制刷新获取预订统计信息(绕过所有缓存)
1742
+ * 更新预订状态
1743
+ *
1744
+ * @param id 预订ID
1745
+ * @param data 更新数据
1746
+ * @returns 更新后的预订信息
1463
1747
  */
1464
- static async forceRefreshBookingStats(params) {
1465
- try {
1466
- console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F...");
1467
- const timestamp = Date.now();
1468
- const randomId = Math.random().toString(36).substring(7);
1469
- const searchParams = new URLSearchParams();
1470
- searchParams.append("t", timestamp.toString());
1471
- searchParams.append("forceRefresh", randomId);
1472
- if (params?.qqNumber) {
1473
- searchParams.append("qqNumber", params.qqNumber);
1474
- }
1475
- if (params?.phoneNumber) {
1476
- searchParams.append("phoneNumber", params.phoneNumber);
1477
- }
1478
- if (params?.status && params.status !== "all") {
1479
- searchParams.append("status", params.status);
1480
- }
1481
- const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
1482
- method: "GET",
1483
- cache: "no-store",
1484
- headers: {
1485
- "Cache-Control": "no-cache, no-store, must-revalidate",
1486
- "Pragma": "no-cache",
1487
- "Expires": "0",
1488
- "X-Requested-With": "XMLHttpRequest",
1489
- "X-Force-Refresh": "true"
1490
- }
1491
- });
1492
- if (!response.ok) {
1493
- throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
1494
- }
1495
- const data = await response.json();
1496
- console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0\u7EDF\u8BA1\u4FE1\u606F\u54CD\u5E94:", {
1497
- stats: data.stats,
1498
- timestamp: data._timestamp,
1499
- refreshType: data._refreshType
1500
- });
1501
- return data.stats || {
1502
- totalBookings: 0,
1503
- pendingBookings: 0,
1504
- confirmedBookings: 0,
1505
- completedBookings: 0,
1506
- cancelledBookings: 0,
1507
- totalQuantity: 0,
1508
- totalRevenue: 0,
1509
- totalAmount: 0,
1510
- todayBookings: 0,
1511
- weekBookings: 0
1512
- };
1513
- } catch (error) {
1514
- console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
1515
- throw error;
1748
+ static async updateBooking(id, data) {
1749
+ const response = await fetch(`${this.BASE_URL}/${id}`, {
1750
+ method: "PUT",
1751
+ headers: {
1752
+ "Content-Type": "application/json"
1753
+ },
1754
+ body: JSON.stringify(data)
1755
+ });
1756
+ if (!response.ok) {
1757
+ const error = await response.json().catch(() => ({ message: "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25" }));
1758
+ throw new Error(error.message || "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25");
1516
1759
  }
1760
+ return response.json();
1517
1761
  }
1518
1762
  /**
1519
- * 更新预订状态
1763
+ * 删除预订
1764
+ *
1765
+ * @param id 预订ID
1520
1766
  */
1521
- static async updateBookingStatus(bookingId, status, adminNotes) {
1522
- try {
1523
- const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}/status`, {
1524
- method: "PUT",
1525
- headers: {
1526
- "Content-Type": "application/json"
1527
- },
1528
- body: JSON.stringify({ status, adminNotes })
1529
- });
1530
- if (!response.ok) {
1531
- throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
1532
- }
1533
- } catch (error) {
1534
- console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
1535
- throw error;
1767
+ static async deleteBooking(id) {
1768
+ const response = await fetch(`${this.BASE_URL}/${id}`, {
1769
+ method: "DELETE"
1770
+ });
1771
+ if (!response.ok) {
1772
+ const error = await response.json().catch(() => ({ message: "\u5220\u9664\u9884\u8BA2\u5931\u8D25" }));
1773
+ throw new Error(error.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
1536
1774
  }
1537
1775
  }
1538
1776
  /**
1539
- * 删除预订
1777
+ * 获取可预订的画集列表
1778
+ *
1779
+ * @returns 画集简略信息列表
1540
1780
  */
1541
- static async deleteBooking(bookingId) {
1781
+ static async getBookableCollections() {
1782
+ const url = `${this.BASE_URL}/collections`;
1783
+ console.log("\u{1F4E1} [BookingService] \u83B7\u53D6\u53EF\u9884\u8BA2\u753B\u96C6:", { url });
1784
+ const response = await fetch(url);
1785
+ if (!response.ok) {
1786
+ const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25" }));
1787
+ throw new Error(error.message || "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25");
1788
+ }
1789
+ const data = await response.json();
1790
+ if (data.success && Array.isArray(data.data)) {
1791
+ console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6`);
1792
+ return data.data;
1793
+ }
1794
+ if (Array.isArray(data)) {
1795
+ console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6 (\u517C\u5BB9\u683C\u5F0F)`);
1796
+ return data;
1797
+ }
1798
+ throw new Error("API\u54CD\u5E94\u683C\u5F0F\u9519\u8BEF");
1799
+ }
1800
+ };
1801
+ BookingService.BASE_URL = "/api/showmasterpiece/bookings";
1802
+ createBooking = (data) => {
1803
+ return BookingService.createBooking(data);
1804
+ };
1805
+ getBookings = (params) => {
1806
+ return BookingService.getBookings(params);
1807
+ };
1808
+ getBooking = (id) => {
1809
+ return BookingService.getBooking(id);
1810
+ };
1811
+ updateBooking = (id, data) => {
1812
+ return BookingService.updateBooking(id, data);
1813
+ };
1814
+ deleteBooking = (id) => {
1815
+ return BookingService.deleteBooking(id);
1816
+ };
1817
+ getBookableCollections = () => {
1818
+ return BookingService.getBookableCollections();
1819
+ };
1820
+ }
1821
+ });
1822
+ function useBooking(_props = {}) {
1823
+ const [state, setState] = useState({
1824
+ collections: [],
1825
+ loading: false,
1826
+ error: void 0,
1827
+ submitting: false,
1828
+ submitted: false
1829
+ });
1830
+ const loadCollections = useCallback(async () => {
1831
+ setState((prev) => ({ ...prev, loading: true, error: void 0 }));
1832
+ try {
1833
+ console.log("\u{1F504} [useBooking] \u52A0\u8F7D\u753B\u96C6\u5217\u8868...");
1834
+ const collections = await getBookableCollections();
1835
+ setState((prev) => ({
1836
+ ...prev,
1837
+ collections,
1838
+ loading: false
1839
+ }));
1840
+ } catch (error) {
1841
+ console.error("\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25:", error);
1842
+ setState((prev) => ({
1843
+ ...prev,
1844
+ loading: false,
1845
+ error: error instanceof Error ? error.message : "\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25"
1846
+ }));
1847
+ }
1848
+ }, []);
1849
+ const submitBooking = useCallback(async (formData) => {
1850
+ setState((prev) => ({ ...prev, submitting: true, error: void 0 }));
1851
+ try {
1852
+ const bookingData = {
1853
+ collectionId: formData.collectionId,
1854
+ qqNumber: formData.qqNumber,
1855
+ phoneNumber: formData.phoneNumber.trim(),
1856
+ quantity: formData.quantity,
1857
+ notes: formData.notes || void 0
1858
+ };
1859
+ await createBooking(bookingData);
1860
+ setState((prev) => ({
1861
+ ...prev,
1862
+ submitting: false,
1863
+ submitted: true
1864
+ }));
1865
+ } catch (error) {
1866
+ console.error("\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25:", error);
1867
+ setState((prev) => ({
1868
+ ...prev,
1869
+ submitting: false,
1870
+ error: error instanceof Error ? error.message : "\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25"
1871
+ }));
1872
+ }
1873
+ }, []);
1874
+ const resetSubmission = useCallback(() => {
1875
+ setState((prev) => ({
1876
+ ...prev,
1877
+ submitted: false,
1878
+ error: void 0
1879
+ }));
1880
+ }, []);
1881
+ const clearError = useCallback(() => {
1882
+ setState((prev) => ({ ...prev, error: void 0 }));
1883
+ }, []);
1884
+ useEffect(() => {
1885
+ loadCollections();
1886
+ }, [loadCollections]);
1887
+ return {
1888
+ // 状态
1889
+ collections: state.collections,
1890
+ loading: state.loading,
1891
+ error: state.error,
1892
+ submitting: state.submitting,
1893
+ submitted: state.submitted,
1894
+ // 操作方法
1895
+ loadCollections,
1896
+ submitBooking,
1897
+ resetSubmission,
1898
+ clearError
1899
+ };
1900
+ }
1901
+ function useBookingForm() {
1902
+ const [formData, setFormData] = useState({
1903
+ collectionId: 0,
1904
+ qqNumber: "",
1905
+ phoneNumber: "",
1906
+ quantity: 1,
1907
+ notes: ""
1908
+ });
1909
+ const [errors, setErrors] = useState({});
1910
+ const updateField = useCallback((field, value) => {
1911
+ setFormData((prev) => ({ ...prev, [field]: value }));
1912
+ if (errors[field]) {
1913
+ setErrors((prev) => ({ ...prev, [field]: void 0 }));
1914
+ }
1915
+ }, [errors]);
1916
+ const validateForm = useCallback(() => {
1917
+ const newErrors = {};
1918
+ if (!formData.collectionId) {
1919
+ newErrors.collectionId = "\u8BF7\u9009\u62E9\u8981\u9884\u8BA2\u7684\u753B\u96C6";
1920
+ }
1921
+ if (!formData.qqNumber.trim()) {
1922
+ newErrors.qqNumber = "\u8BF7\u8F93\u5165QQ\u53F7";
1923
+ } else if (!/^\d{5,11}$/.test(formData.qqNumber.trim())) {
1924
+ newErrors.qqNumber = "QQ\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
1925
+ }
1926
+ if (formData.phoneNumber.trim()) {
1927
+ const phoneRegex = /^1[3-9]\d{9}$/;
1928
+ if (!phoneRegex.test(formData.phoneNumber.trim())) {
1929
+ newErrors.phoneNumber = "\u624B\u673A\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
1930
+ }
1931
+ }
1932
+ if (!formData.quantity || formData.quantity < 1) {
1933
+ newErrors.quantity = "\u9884\u8BA2\u6570\u91CF\u5FC5\u987B\u5927\u4E8E0";
1934
+ }
1935
+ setErrors(newErrors);
1936
+ return Object.keys(newErrors).length === 0;
1937
+ }, [formData]);
1938
+ const resetForm = useCallback(() => {
1939
+ setFormData({
1940
+ collectionId: 0,
1941
+ qqNumber: "",
1942
+ phoneNumber: "",
1943
+ quantity: 1,
1944
+ notes: ""
1945
+ });
1946
+ setErrors({});
1947
+ }, []);
1948
+ return {
1949
+ formData,
1950
+ errors,
1951
+ updateField,
1952
+ validateForm,
1953
+ resetForm
1954
+ };
1955
+ }
1956
+ var init_useBooking = __esm({
1957
+ "src/showmasterpiece/logic/hooks/useBooking.ts"() {
1958
+ init_bookingService();
1959
+ }
1960
+ });
1961
+
1962
+ // src/showmasterpiece/services/bookingAdminService.ts
1963
+ var BookingAdminService, getAllBookings, getBookingStats, forceRefreshAllBookings, forceRefreshBookingStats, updateBookingStatus2, deleteBooking2, exportBookings;
1964
+ var init_bookingAdminService = __esm({
1965
+ "src/showmasterpiece/services/bookingAdminService.ts"() {
1966
+ BookingAdminService = class {
1967
+ /**
1968
+ * 获取所有预订数据
1969
+ */
1970
+ static async getAllBookings(params) {
1542
1971
  try {
1543
- const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}`, {
1544
- method: "DELETE",
1972
+ const timestamp = Date.now();
1973
+ const randomId = Math.random().toString(36).substring(7);
1974
+ const searchParams = new URLSearchParams();
1975
+ searchParams.append("t", timestamp.toString());
1976
+ searchParams.append("forceRefresh", randomId);
1977
+ if (params?.qqNumber) {
1978
+ searchParams.append("qqNumber", params.qqNumber);
1979
+ }
1980
+ if (params?.phoneNumber) {
1981
+ searchParams.append("phoneNumber", params.phoneNumber);
1982
+ }
1983
+ if (params?.status && params.status !== "all") {
1984
+ searchParams.append("status", params.status);
1985
+ }
1986
+ const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
1987
+ method: "GET",
1988
+ cache: "no-store",
1545
1989
  headers: {
1546
- "Content-Type": "application/json"
1990
+ "Cache-Control": "no-cache, no-store, must-revalidate",
1991
+ "Pragma": "no-cache",
1992
+ "Expires": "0",
1993
+ "X-Requested-With": "XMLHttpRequest"
1547
1994
  }
1548
1995
  });
1549
1996
  if (!response.ok) {
1550
- const errorData = await response.json().catch(() => ({}));
1551
- throw new Error(errorData.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
1997
+ throw new Error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
1552
1998
  }
1553
- console.log("\u2705 \u9884\u8BA2\u5220\u9664\u6210\u529F:", { bookingId });
1999
+ const data = await response.json();
2000
+ return data.bookings || [];
1554
2001
  } catch (error) {
1555
- console.error("\u5220\u9664\u9884\u8BA2\u5931\u8D25:", error);
2002
+ console.error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
1556
2003
  throw error;
1557
2004
  }
1558
2005
  }
1559
2006
  /**
1560
- * 导出预订数据
2007
+ * 强制刷新获取所有预订数据(绕过所有缓存)
1561
2008
  */
1562
- static async exportBookings(format = "csv") {
2009
+ static async forceRefreshAllBookings(params) {
1563
2010
  try {
1564
- const response = await fetch(`/api/showmasterpiece/bookings/admin/export?format=${format}`);
2011
+ console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u9884\u8BA2\u6570\u636E...");
2012
+ const timestamp = Date.now();
2013
+ const randomId = Math.random().toString(36).substring(7);
2014
+ const searchParams = new URLSearchParams();
2015
+ searchParams.append("t", timestamp.toString());
2016
+ searchParams.append("forceRefresh", randomId);
2017
+ if (params?.qqNumber) {
2018
+ searchParams.append("qqNumber", params.qqNumber);
2019
+ }
2020
+ if (params?.phoneNumber) {
2021
+ searchParams.append("phoneNumber", params.phoneNumber);
2022
+ }
2023
+ if (params?.status && params.status !== "all") {
2024
+ searchParams.append("status", params.status);
2025
+ }
2026
+ const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
2027
+ method: "GET",
2028
+ cache: "no-store",
2029
+ headers: {
2030
+ "Cache-Control": "no-cache, no-store, must-revalidate",
2031
+ "Pragma": "no-cache",
2032
+ "Expires": "0",
2033
+ "X-Requested-With": "XMLHttpRequest",
2034
+ "X-Force-Refresh": "true"
2035
+ }
2036
+ });
1565
2037
  if (!response.ok) {
1566
- throw new Error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25");
2038
+ throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
1567
2039
  }
1568
- return await response.blob();
2040
+ const data = await response.json();
2041
+ console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0API\u54CD\u5E94:", {
2042
+ bookingsCount: data.bookings?.length || 0,
2043
+ timestamp: data._timestamp,
2044
+ refreshType: data._refreshType
2045
+ });
2046
+ return data.bookings || [];
1569
2047
  } catch (error) {
1570
- console.error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
2048
+ console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
1571
2049
  throw error;
1572
2050
  }
1573
2051
  }
1574
- };
1575
- getAllBookings = BookingAdminService.getAllBookings;
1576
- getBookingStats = BookingAdminService.getBookingStats;
1577
- forceRefreshAllBookings = BookingAdminService.forceRefreshAllBookings;
1578
- forceRefreshBookingStats = BookingAdminService.forceRefreshBookingStats;
1579
- updateBookingStatus2 = BookingAdminService.updateBookingStatus;
1580
- deleteBooking2 = BookingAdminService.deleteBooking;
1581
- exportBookings = BookingAdminService.exportBookings;
1582
- }
1583
- });
1584
-
1585
- // src/services/universalFile/config/index.ts
1586
- async function createFileServiceConfig(customConfig) {
1587
- const configManager = new FileServiceConfigManager(customConfig);
1588
- await configManager.loadAliyunOSSFromEnv();
1589
- await configManager.loadAliyunCDNFromEnv();
1590
- await configManager.loadAliyunOSSFromConfigManager();
1591
- return configManager;
1592
- }
1593
- var DEFAULT_CONFIG, FileServiceConfigManager;
1594
- var init_config = __esm({
1595
- "src/services/universalFile/config/index.ts"() {
1596
- if (typeof window === "undefined") {
1597
- try {
1598
- __require("dotenv").config({ path: __require("path").join(process.cwd(), ".env.local") });
1599
- } catch (error) {
1600
- console.warn("\u26A0\uFE0F [ConfigManager] \u65E0\u6CD5\u52A0\u8F7D.env.local\u6587\u4EF6:", error);
1601
- }
1602
- }
1603
- DEFAULT_CONFIG = {
1604
- defaultStorage: "aliyun-oss",
1605
- // 修改默认存储为OSS
1606
- storageProviders: {
1607
- "local": {
1608
- type: "local",
1609
- enabled: false,
1610
- // 默认禁用本地存储
1611
- rootPath: process.env.FILE_STORAGE_PATH || "uploads",
1612
- baseUrl: process.env.FILE_BASE_URL || "/uploads"
1613
- },
1614
- "aliyun-oss": {
1615
- type: "aliyun-oss",
1616
- enabled: true,
1617
- // 默认启用OSS
1618
- region: "",
1619
- bucket: "",
1620
- accessKeyId: "",
1621
- accessKeySecret: ""
1622
- },
1623
- "aws-s3": {
1624
- type: "aws-s3",
1625
- enabled: false
1626
- },
1627
- "qcloud-cos": {
1628
- type: "qcloud-cos",
1629
- enabled: false
1630
- }
1631
- },
1632
- defaultCDN: "none",
1633
- cdnProviders: {
1634
- "none": {
1635
- type: "none",
1636
- enabled: false
1637
- },
1638
- "aliyun-cdn": {
1639
- type: "aliyun-cdn",
1640
- enabled: false,
1641
- domain: "",
1642
- accessKeyId: "",
1643
- accessKeySecret: ""
1644
- },
1645
- "aws-cloudfront": {
1646
- type: "aws-cloudfront",
1647
- enabled: false
1648
- },
1649
- "qcloud-cdn": {
1650
- type: "qcloud-cdn",
1651
- enabled: false
1652
- }
1653
- },
1654
- maxFileSize: parseInt(process.env.MAX_FILE_SIZE || "104857600"),
1655
- // 100MB
1656
- allowedMimeTypes: [
1657
- // 图片类型
1658
- "image/jpeg",
1659
- "image/png",
1660
- "image/gif",
1661
- "image/webp",
1662
- "image/svg+xml",
1663
- // 音频类型
1664
- "audio/mpeg",
1665
- "audio/wav",
1666
- "audio/ogg",
1667
- "audio/mp4",
1668
- "audio/aac",
1669
- // 视频类型
1670
- "video/mp4",
1671
- "video/avi",
1672
- "video/mov",
1673
- "video/webm",
1674
- "video/mkv",
1675
- // 文档类型
1676
- "application/pdf",
1677
- "text/plain",
1678
- "application/json",
1679
- "application/javascript",
1680
- "text/css",
1681
- "text/html",
1682
- "text/markdown",
1683
- // 压缩文件
1684
- "application/zip",
1685
- "application/x-zip-compressed",
1686
- "application/x-rar-compressed",
1687
- "application/x-7z-compressed",
1688
- // 3D模型文件
1689
- "application/octet-stream",
1690
- // PMD/PMX文件
1691
- "model/gltf+json",
1692
- "model/gltf-binary"
1693
- ],
1694
- enableProcessing: process.env.ENABLE_FILE_PROCESSING === "true",
1695
- processingQueueSize: parseInt(process.env.PROCESSING_QUEUE_SIZE || "10"),
1696
- cache: {
1697
- metadataTTL: parseInt(process.env.METADATA_CACHE_TTL || "3600"),
1698
- // 1小时
1699
- urlTTL: parseInt(process.env.URL_CACHE_TTL || "1800")
1700
- // 30分钟
1701
- }
1702
- };
1703
- FileServiceConfigManager = class {
1704
- constructor(customConfig) {
1705
- this.config = this.mergeConfig(DEFAULT_CONFIG, customConfig);
1706
- this.validateConfig();
1707
- }
1708
- /**
1709
- * 获取完整配置
1710
- */
1711
- getConfig() {
1712
- return { ...this.config };
1713
- }
1714
- /**
1715
- * 获取存储提供者配置
1716
- */
1717
- getStorageConfig(type) {
1718
- return this.config.storageProviders[type];
1719
- }
1720
- /**
1721
- * 获取CDN提供者配置
1722
- */
1723
- getCDNConfig(type) {
1724
- return this.config.cdnProviders[type];
1725
- }
1726
- /**
1727
- * 更新配置
1728
- */
1729
- updateConfig(updates) {
1730
- this.config = this.mergeConfig(this.config, updates);
1731
- this.validateConfig();
1732
- }
1733
- /**
1734
- * 启用存储提供者
1735
- */
1736
- enableStorageProvider(type, config) {
1737
- if (this.config.storageProviders[type]) {
1738
- this.config.storageProviders[type] = {
1739
- ...this.config.storageProviders[type],
1740
- ...config,
1741
- enabled: true
1742
- };
1743
- }
1744
- }
1745
- /**
1746
- * 禁用存储提供者
1747
- */
1748
- disableStorageProvider(type) {
1749
- if (this.config.storageProviders[type]) {
1750
- this.config.storageProviders[type].enabled = false;
1751
- }
1752
- }
1753
2052
  /**
1754
- * 启用CDN提供者
2053
+ * 获取预订统计信息
1755
2054
  */
1756
- enableCDNProvider(type, config) {
1757
- if (this.config.cdnProviders[type]) {
1758
- this.config.cdnProviders[type] = {
1759
- ...this.config.cdnProviders[type],
1760
- ...config,
1761
- enabled: true
2055
+ static async getBookingStats(params) {
2056
+ try {
2057
+ const timestamp = Date.now();
2058
+ const randomId = Math.random().toString(36).substring(7);
2059
+ const searchParams = new URLSearchParams();
2060
+ searchParams.append("t", timestamp.toString());
2061
+ searchParams.append("forceRefresh", randomId);
2062
+ if (params?.qqNumber) {
2063
+ searchParams.append("qqNumber", params.qqNumber);
2064
+ }
2065
+ if (params?.phoneNumber) {
2066
+ searchParams.append("phoneNumber", params.phoneNumber);
2067
+ }
2068
+ if (params?.status && params.status !== "all") {
2069
+ searchParams.append("status", params.status);
2070
+ }
2071
+ const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
2072
+ method: "GET",
2073
+ cache: "no-store",
2074
+ headers: {
2075
+ "Cache-Control": "no-cache, no-store, must-revalidate",
2076
+ "Pragma": "no-cache",
2077
+ "Expires": "0",
2078
+ "X-Requested-With": "XMLHttpRequest"
2079
+ }
2080
+ });
2081
+ if (!response.ok) {
2082
+ throw new Error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
2083
+ }
2084
+ const data = await response.json();
2085
+ return data.stats || {
2086
+ totalBookings: 0,
2087
+ pendingBookings: 0,
2088
+ confirmedBookings: 0,
2089
+ completedBookings: 0,
2090
+ cancelledBookings: 0,
2091
+ totalQuantity: 0,
2092
+ totalRevenue: 0,
2093
+ totalAmount: 0,
2094
+ todayBookings: 0,
2095
+ weekBookings: 0
1762
2096
  };
1763
- this.config.defaultCDN = type;
2097
+ } catch (error) {
2098
+ console.error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
2099
+ throw error;
1764
2100
  }
1765
2101
  }
1766
2102
  /**
1767
- * 禁用CDN提供者
2103
+ * 强制刷新获取预订统计信息(绕过所有缓存)
1768
2104
  */
1769
- disableCDNProvider(type) {
1770
- if (this.config.cdnProviders[type]) {
1771
- this.config.cdnProviders[type].enabled = false;
1772
- if (this.config.defaultCDN === type) {
1773
- this.config.defaultCDN = "none";
2105
+ static async forceRefreshBookingStats(params) {
2106
+ try {
2107
+ console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F...");
2108
+ const timestamp = Date.now();
2109
+ const randomId = Math.random().toString(36).substring(7);
2110
+ const searchParams = new URLSearchParams();
2111
+ searchParams.append("t", timestamp.toString());
2112
+ searchParams.append("forceRefresh", randomId);
2113
+ if (params?.qqNumber) {
2114
+ searchParams.append("qqNumber", params.qqNumber);
1774
2115
  }
1775
- }
1776
- }
1777
- /**
1778
- * 从环境变量加载阿里云OSS配置
1779
- */
1780
- loadAliyunOSSFromEnv() {
1781
- const config = {
1782
- region: process.env.ALIYUN_OSS_REGION,
1783
- bucket: process.env.ALIYUN_OSS_BUCKET,
1784
- accessKeyId: process.env.ALIYUN_OSS_ACCESS_KEY_ID,
1785
- accessKeySecret: process.env.ALIYUN_OSS_ACCESS_KEY_SECRET,
1786
- customDomain: process.env.ALIYUN_OSS_CUSTOM_DOMAIN,
1787
- secure: process.env.ALIYUN_OSS_SECURE === "true",
1788
- internal: process.env.ALIYUN_OSS_INTERNAL === "true"
1789
- };
1790
- console.log("\u{1F50D} [ConfigManager] \u963F\u91CC\u4E91OSS\u914D\u7F6E:", {
1791
- region: config.region,
1792
- bucket: config.bucket,
1793
- accessKeyId: config.accessKeyId ? "***" : "\u672A\u8BBE\u7F6E",
1794
- accessKeySecret: config.accessKeySecret ? "***" : "\u672A\u8BBE\u7F6E",
1795
- customDomain: config.customDomain || "\u672A\u8BBE\u7F6E"
1796
- });
1797
- if (config.region && config.bucket && config.accessKeyId && config.accessKeySecret) {
1798
- this.enableStorageProvider("aliyun-oss", config);
1799
- this.config.defaultStorage = "aliyun-oss";
1800
- console.log("\u2705 [ConfigManager] \u4ECE\u73AF\u5883\u53D8\u91CF\u52A0\u8F7D\u963F\u91CC\u4E91OSS\u914D\u7F6E\u6210\u529F");
1801
- } else {
1802
- console.warn("\u26A0\uFE0F [ConfigManager] \u963F\u91CC\u4E91OSS\u73AF\u5883\u53D8\u91CF\u914D\u7F6E\u4E0D\u5B8C\u6574");
1803
- }
1804
- }
1805
- /**
1806
- * 从配置管理模块加载阿里云OSS配置
1807
- */
1808
- async loadAliyunOSSFromConfigManager() {
1809
- return;
1810
- }
1811
- /**
1812
- * 从环境变量加载阿里云CDN配置
1813
- */
1814
- loadAliyunCDNFromEnv() {
1815
- const config = {
1816
- domain: process.env.ALIYUN_CDN_DOMAIN,
1817
- accessKeyId: process.env.ALIYUN_CDN_ACCESS_KEY_ID,
1818
- accessKeySecret: process.env.ALIYUN_CDN_ACCESS_KEY_SECRET,
1819
- region: process.env.ALIYUN_CDN_REGION
1820
- };
1821
- if (config.domain && config.accessKeyId && config.accessKeySecret) {
1822
- this.enableCDNProvider("aliyun-cdn", config);
1823
- console.log("\u2705 [ConfigManager] \u4ECE\u73AF\u5883\u53D8\u91CF\u52A0\u8F7D\u963F\u91CC\u4E91CDN\u914D\u7F6E\u6210\u529F");
1824
- } else {
1825
- console.log("\u2139\uFE0F [ConfigManager] \u963F\u91CC\u4E91CDN\u672A\u914D\u7F6E\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u5B58\u50A8\u65B9\u5F0F");
1826
- }
1827
- }
1828
- /**
1829
- * 验证配置有效性
1830
- */
1831
- validateConfig() {
1832
- const defaultStorageConfig = this.config.storageProviders[this.config.defaultStorage];
1833
- if (!defaultStorageConfig || !defaultStorageConfig.enabled) {
1834
- console.warn(`\u26A0\uFE0F [ConfigManager] \u9ED8\u8BA4\u5B58\u50A8\u63D0\u4F9B\u8005 ${this.config.defaultStorage} \u672A\u542F\u7528`);
1835
- }
1836
- if (this.config.maxFileSize <= 0) {
1837
- throw new Error("\u6587\u4EF6\u5927\u5C0F\u9650\u5236\u5FC5\u987B\u5927\u4E8E0");
1838
- }
1839
- if (this.config.processingQueueSize <= 0) {
1840
- throw new Error("\u5904\u7406\u961F\u5217\u5927\u5C0F\u5FC5\u987B\u5927\u4E8E0");
1841
- }
1842
- if (this.config.cache.metadataTTL <= 0 || this.config.cache.urlTTL <= 0) {
1843
- throw new Error("\u7F13\u5B58TTL\u5FC5\u987B\u5927\u4E8E0");
1844
- }
1845
- }
1846
- /**
1847
- * 合并配置
1848
- */
1849
- mergeConfig(base, override) {
1850
- if (!override) return { ...base };
1851
- return {
1852
- ...base,
1853
- ...override,
1854
- storageProviders: {
1855
- ...base.storageProviders,
1856
- ...override.storageProviders || {}
1857
- },
1858
- cdnProviders: {
1859
- ...base.cdnProviders,
1860
- ...override.cdnProviders || {}
1861
- },
1862
- cache: {
1863
- ...base.cache,
1864
- ...override.cache || {}
2116
+ if (params?.phoneNumber) {
2117
+ searchParams.append("phoneNumber", params.phoneNumber);
1865
2118
  }
1866
- };
1867
- }
1868
- };
1869
- }
1870
- });
1871
-
1872
- // src/showmasterpiece/services/fileService.ts
1873
- async function getShowmasterpieceOSSConfig() {
1874
- try {
1875
- console.log("\u{1F3A8} [ShowMasterpiece] \u5C1D\u8BD5\u4ECE\u72EC\u7ACB\u914D\u7F6E\u8BFB\u53D6OSS\u914D\u7F6E...");
1876
- const environment = process.env.NODE_ENV === "production" ? "production" : "development";
1877
- console.log(`\u{1F3A8} [ShowMasterpiece] \u5F53\u524D\u73AF\u5883: ${environment}`);
1878
- if (typeof window !== "undefined") {
1879
- console.log("\u{1F310} [ShowMasterpiece] \u5BA2\u6237\u7AEF\u73AF\u5883\uFF0C\u901A\u8FC7API\u8BFB\u53D6\u914D\u7F6E");
1880
- const configKeys = "ALIYUN_OSS_REGION,ALIYUN_OSS_BUCKET,ALIYUN_OSS_ACCESS_KEY_ID,ALIYUN_OSS_ACCESS_KEY_SECRET,ALIYUN_OSS_CUSTOM_DOMAIN,ALIYUN_OSS_SECURE,ALIYUN_OSS_INTERNAL";
1881
- const response = await fetch(`/api/showmasterpiece/config/items?environment=${environment}&keys=${configKeys}`);
1882
- if (!response.ok) {
1883
- console.warn("\u26A0\uFE0F [ShowMasterpiece] \u8BFB\u53D6\u72EC\u7ACB\u914D\u7F6EAPI\u5931\u8D25:", response.status);
1884
- return null;
1885
- }
1886
- const data = await response.json();
1887
- if (!data.success || !data.items) {
1888
- console.warn("\u26A0\uFE0F [ShowMasterpiece] \u72EC\u7ACB\u914D\u7F6EAPI\u54CD\u5E94\u5F02\u5E38:", data);
1889
- return null;
1890
- }
1891
- const configMap = {};
1892
- data.items.forEach((item) => {
1893
- if (item.value) {
1894
- configMap[item.key] = item.value;
1895
- }
1896
- });
1897
- const ossConfig = {
1898
- region: configMap["ALIYUN_OSS_REGION"],
1899
- bucket: configMap["ALIYUN_OSS_BUCKET"],
1900
- accessKeyId: configMap["ALIYUN_OSS_ACCESS_KEY_ID"],
1901
- accessKeySecret: configMap["ALIYUN_OSS_ACCESS_KEY_SECRET"],
1902
- customDomain: configMap["ALIYUN_OSS_CUSTOM_DOMAIN"],
1903
- secure: configMap["ALIYUN_OSS_SECURE"] === "true",
1904
- internal: configMap["ALIYUN_OSS_INTERNAL"] === "true"
1905
- };
1906
- console.log("\u{1F3A8} [ShowMasterpiece] \u72EC\u7ACB\u914D\u7F6E\u8BFB\u53D6\u7ED3\u679C:", {
1907
- region: ossConfig.region || "\u672A\u914D\u7F6E",
1908
- bucket: ossConfig.bucket || "\u672A\u914D\u7F6E",
1909
- accessKeyId: ossConfig.accessKeyId ? "***" : "\u672A\u914D\u7F6E",
1910
- accessKeySecret: ossConfig.accessKeySecret ? "***" : "\u672A\u914D\u7F6E",
1911
- customDomain: ossConfig.customDomain || "\u672A\u914D\u7F6E",
1912
- secure: ossConfig.secure,
1913
- internal: ossConfig.internal
1914
- });
1915
- if (ossConfig.region && ossConfig.bucket && ossConfig.accessKeyId && ossConfig.accessKeySecret) {
1916
- console.log("\u2705 [ShowMasterpiece] \u72EC\u7ACB\u914D\u7F6E\u5B8C\u6574\uFF0C\u5C06\u4F7F\u7528\u72EC\u7ACBOSS\u914D\u7F6E");
1917
- return ossConfig;
1918
- } else {
1919
- console.log("\u26A0\uFE0F [ShowMasterpiece] \u72EC\u7ACB\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u5C06\u56DE\u9000\u5230\u516C\u5171\u914D\u7F6E");
1920
- console.log("\u{1F50D} [ShowMasterpiece] \u7F3A\u5931\u914D\u7F6E\u9879:", {
1921
- region: !ossConfig.region,
1922
- bucket: !ossConfig.bucket,
1923
- accessKeyId: !ossConfig.accessKeyId,
1924
- accessKeySecret: !ossConfig.accessKeySecret
1925
- });
1926
- return null;
1927
- }
1928
- } else {
1929
- console.log("\u{1F5A5}\uFE0F [ShowMasterpiece] \u670D\u52A1\u5668\u7AEF\u73AF\u5883\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\u56DE\u9000");
1930
- return null;
1931
- }
1932
- } catch (error) {
1933
- console.warn("\u26A0\uFE0F [ShowMasterpiece] \u8BFB\u53D6\u72EC\u7ACB\u914D\u7F6E\u5931\u8D25:", error);
1934
- return null;
1935
- }
1936
- }
1937
- async function getCachedConfigManager() {
1938
- if (!cachedConfigManager) {
1939
- const showmasterpieceOSSConfig = await getShowmasterpieceOSSConfig();
1940
- if (showmasterpieceOSSConfig) {
1941
- console.log("\u{1F3A8} [ShowMasterpiece] \u4F7F\u7528\u72EC\u7ACBOSS\u914D\u7F6E\u521B\u5EFA\u914D\u7F6E\u7BA1\u7406\u5668");
1942
- cachedConfigManager = await createFileServiceConfig({
1943
- defaultStorage: "aliyun-oss",
1944
- storageProviders: {
1945
- "local": {
1946
- type: "local",
1947
- enabled: false,
1948
- rootPath: "uploads",
1949
- baseUrl: "/uploads"
1950
- },
1951
- "aliyun-oss": {
1952
- type: "aliyun-oss",
1953
- enabled: true,
1954
- ...showmasterpieceOSSConfig
1955
- },
1956
- "aws-s3": {
1957
- type: "aws-s3",
1958
- enabled: false
1959
- },
1960
- "qcloud-cos": {
1961
- type: "qcloud-cos",
1962
- enabled: false
2119
+ if (params?.status && params.status !== "all") {
2120
+ searchParams.append("status", params.status);
1963
2121
  }
1964
- }
1965
- });
1966
- } else {
1967
- console.log("\u{1F3A8} [ShowMasterpiece] \u72EC\u7ACB\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");
1968
- cachedConfigManager = await createFileServiceConfig({
1969
- defaultStorage: "local",
1970
- // 默认使用本地存储
1971
- storageProviders: {
1972
- "local": {
1973
- type: "local",
1974
- enabled: true,
1975
- rootPath: "uploads",
1976
- baseUrl: "/uploads"
1977
- },
1978
- "aliyun-oss": {
1979
- type: "aliyun-oss",
1980
- enabled: false
1981
- // 如果独立配置失败,禁用OSS
1982
- },
1983
- "aws-s3": {
1984
- type: "aws-s3",
1985
- enabled: false
1986
- },
1987
- "qcloud-cos": {
1988
- type: "qcloud-cos",
1989
- enabled: false
2122
+ const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
2123
+ method: "GET",
2124
+ cache: "no-store",
2125
+ headers: {
2126
+ "Cache-Control": "no-cache, no-store, must-revalidate",
2127
+ "Pragma": "no-cache",
2128
+ "Expires": "0",
2129
+ "X-Requested-With": "XMLHttpRequest",
2130
+ "X-Force-Refresh": "true"
2131
+ }
2132
+ });
2133
+ if (!response.ok) {
2134
+ throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
1990
2135
  }
1991
- }
1992
- });
1993
- }
1994
- }
1995
- return cachedConfigManager;
1996
- }
1997
- async function getShowMasterpieceFileConfig() {
1998
- const configManager = await getCachedConfigManager();
1999
- const config = configManager.getConfig();
2000
- const ossConfig = config.storageProviders["aliyun-oss"];
2001
- if (ossConfig && ossConfig.enabled) {
2002
- console.log("\u2705 [ShowMasterpiece] \u4F7F\u7528\u963F\u91CC\u4E91OSS\u5B58\u50A8");
2003
- return configManager;
2004
- } else {
2005
- console.log("\u2139\uFE0F [ShowMasterpiece] OSS\u672A\u914D\u7F6E\uFF0C\u4F7F\u7528\u672C\u5730\u5B58\u50A8");
2006
- return configManager;
2007
- }
2008
- }
2009
- async function uploadArtworkImage(file, collectionId) {
2010
- console.log("\u{1F3A8} [ShowMasterpiece] \u5F00\u59CB\u4E0A\u4F20\u4F5C\u54C1\u56FE\u7247:", file.name);
2011
- const formData = new FormData();
2012
- formData.append("file", file);
2013
- formData.append("moduleId", "showmasterpiece");
2014
- formData.append("businessId", collectionId ? `collection-${collectionId}` : "artwork");
2015
- const timestamp = Date.now();
2016
- const randomId = Math.random().toString(36).substr(2, 9);
2017
- const extension = file.name.split(".").pop()?.toLowerCase() || "jpg";
2018
- const basePath = collectionId ? `showmasterpiece/collection-${collectionId}` : "showmasterpiece/artwork";
2019
- formData.append("folderPath", `${basePath}/${timestamp}_${randomId}.${extension}`);
2020
- formData.append("needsProcessing", "true");
2021
- const response = await fetch("/api/universal-file/upload", {
2022
- method: "POST",
2023
- body: formData
2024
- });
2025
- if (!response.ok) {
2026
- const errorData = await response.json();
2027
- throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
2028
- }
2029
- const result = await response.json();
2030
- if (!result.success) {
2031
- throw new Error(result.error || "\u4E0A\u4F20\u5931\u8D25");
2032
- }
2033
- console.log("\u2705 [ShowMasterpiece] \u4F5C\u54C1\u56FE\u7247\u4E0A\u4F20\u6210\u529F:", {
2034
- fileId: result.data.fileId,
2035
- accessUrl: result.data.accessUrl
2036
- });
2037
- return {
2038
- fileId: result.data.fileId,
2039
- accessUrl: result.data.accessUrl
2040
- };
2041
- }
2042
- async function getArtworkImageUrl(fileId) {
2043
- console.log("\u{1F517} [ShowMasterpiece] \u83B7\u53D6\u4F5C\u54C1\u56FE\u7247URL:", fileId);
2044
- const response = await fetch(`/api/universal-file/${fileId}`);
2045
- if (!response.ok) {
2046
- throw new Error(`\u83B7\u53D6\u6587\u4EF6URL\u5931\u8D25: HTTP ${response.status}`);
2047
- }
2048
- const result = await response.json();
2049
- if (!result.success) {
2050
- throw new Error(result.error || "\u83B7\u53D6\u6587\u4EF6URL\u5931\u8D25");
2051
- }
2052
- return result.data.accessUrl;
2053
- }
2054
- async function shouldUseUniversalFileService() {
2055
- try {
2056
- const configManager = await getCachedConfigManager();
2057
- const config = configManager.getConfig();
2058
- const ossConfig = config.storageProviders["aliyun-oss"];
2059
- if (ossConfig && ossConfig.enabled) {
2060
- return true;
2061
- }
2062
- return true;
2063
- } catch (error) {
2064
- console.warn("\u26A0\uFE0F [ShowMasterpiece] \u68C0\u67E5\u6587\u4EF6\u670D\u52A1\u914D\u7F6E\u5931\u8D25:", error);
2065
- return false;
2066
- }
2067
- }
2068
- async function getStorageModeDisplayName() {
2069
- const shouldUse = await shouldUseUniversalFileService();
2070
- if (shouldUse) {
2071
- const configManager = await getCachedConfigManager();
2072
- const config = configManager.getConfig();
2073
- const ossConfig = config.storageProviders["aliyun-oss"];
2074
- if (ossConfig && ossConfig.enabled) {
2075
- return "\u963F\u91CC\u4E91OSS + CDN (\u72EC\u7ACB\u914D\u7F6E)";
2076
- } else {
2077
- return "\u672C\u5730\u5B58\u50A8 + \u6587\u4EF6\u670D\u52A1";
2078
- }
2079
- } else {
2080
- return "Base64\u6570\u636E\u5E93\u5B58\u50A8";
2081
- }
2082
- }
2083
- function clearConfigCache() {
2084
- console.log("\u{1F9F9} [ShowMasterpiece] \u6E05\u9664\u914D\u7F6E\u7F13\u5B58");
2085
- cachedConfigManager = null;
2086
- }
2087
- async function refreshFileServiceConfig() {
2088
- console.log("\u{1F504} [ShowMasterpiece] \u5F3A\u5236\u5237\u65B0\u6587\u4EF6\u670D\u52A1\u914D\u7F6E");
2089
- clearConfigCache();
2090
- const configManager = await getCachedConfigManager();
2091
- if (typeof window === "undefined") {
2092
- try {
2093
- const config = configManager.getConfig();
2094
- const ossConfig = config?.storageProviders?.["aliyun-oss"];
2095
- if (ossConfig && ossConfig.enabled) {
2096
- console.log("\u{1F504} [ShowMasterpiece] \u91CD\u65B0\u521D\u59CB\u5316OSS Provider\u4EE5\u5E94\u7528\u65B0\u914D\u7F6E");
2097
- const { UniversalFileService } = await import('./UniversalFileService-TNYKO6JN.mjs');
2098
- const fileService = new UniversalFileService(config);
2099
- await fileService.initialize();
2100
- await fileService.reinitializeStorageProviders?.();
2101
- }
2102
- } catch (error) {
2103
- console.warn("\u26A0\uFE0F [ShowMasterpiece] \u91CD\u65B0\u521D\u59CB\u5316Provider\u5931\u8D25:", error);
2104
- }
2105
- }
2106
- return configManager;
2107
- }
2108
- var cachedConfigManager;
2109
- var init_fileService = __esm({
2110
- "src/showmasterpiece/services/fileService.ts"() {
2111
- init_config();
2112
- cachedConfigManager = null;
2113
- }
2114
- });
2115
-
2116
- // src/showmasterpiece/services/exportConfig.ts
2117
- var BOOKING_EXPORT_FIELDS, DEFAULT_BOOKING_EXPORT_CONFIG;
2118
- var init_exportConfig = __esm({
2119
- "src/showmasterpiece/services/exportConfig.ts"() {
2120
- BOOKING_EXPORT_FIELDS = [
2121
- {
2122
- key: "id",
2123
- label: "\u9884\u8BA2ID",
2124
- type: "number",
2125
- enabled: true,
2126
- required: true,
2127
- description: "\u9884\u8BA2\u8BB0\u5F55\u7684\u552F\u4E00\u6807\u8BC6",
2128
- alignment: "center"
2129
- },
2130
- {
2131
- key: "collectionId",
2132
- label: "\u753B\u96C6ID",
2133
- type: "number",
2134
- enabled: true,
2135
- required: true,
2136
- description: "\u753B\u96C6\u7684\u552F\u4E00\u6807\u8BC6",
2137
- alignment: "center"
2138
- },
2139
- {
2140
- key: "qqNumber",
2141
- label: "QQ\u53F7",
2142
- type: "string",
2143
- enabled: true,
2144
- required: false,
2145
- description: "\u7528\u6237\u7684QQ\u53F7\u7801",
2146
- alignment: "left"
2147
- },
2148
- {
2149
- key: "phoneNumber",
2150
- label: "\u624B\u673A\u53F7",
2151
- type: "string",
2152
- enabled: true,
2153
- required: false,
2154
- description: "\u7528\u6237\u7684\u624B\u673A\u53F7\u7801",
2155
- alignment: "left"
2156
- },
2157
- {
2158
- key: "collectionTitle",
2159
- label: "\u753B\u96C6\u6807\u9898",
2160
- type: "string",
2161
- enabled: true,
2162
- required: true,
2163
- description: "\u9884\u8BA2\u7684\u753B\u96C6\u6807\u9898",
2164
- alignment: "left"
2165
- },
2166
- {
2167
- key: "collectionNumber",
2168
- label: "\u753B\u96C6\u7F16\u53F7",
2169
- type: "string",
2170
- enabled: true,
2171
- required: true,
2172
- description: "\u753B\u96C6\u7684\u7F16\u53F7",
2173
- alignment: "left"
2174
- },
2175
- {
2176
- key: "collectionPrice",
2177
- label: "\u753B\u96C6\u4EF7\u683C",
2178
- type: "number",
2179
- enabled: true,
2180
- required: true,
2181
- description: "\u753B\u96C6\u7684\u4EF7\u683C",
2182
- alignment: "right",
2183
- formatter: (value) => `\xA5${Number(value).toFixed(2)}`
2184
- },
2185
- {
2186
- key: "status",
2187
- label: "\u9884\u8BA2\u72B6\u6001",
2188
- type: "string",
2189
- enabled: true,
2190
- required: true,
2191
- description: "\u9884\u8BA2\u7684\u5F53\u524D\u72B6\u6001",
2192
- alignment: "center",
2193
- formatter: (value) => {
2194
- const statusMap = {
2195
- pending: "\u5F85\u786E\u8BA4",
2196
- confirmed: "\u5DF2\u786E\u8BA4",
2197
- completed: "\u5DF2\u5B8C\u6210",
2198
- cancelled: "\u5DF2\u53D6\u6D88"
2136
+ const data = await response.json();
2137
+ console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0\u7EDF\u8BA1\u4FE1\u606F\u54CD\u5E94:", {
2138
+ stats: data.stats,
2139
+ timestamp: data._timestamp,
2140
+ refreshType: data._refreshType
2141
+ });
2142
+ return data.stats || {
2143
+ totalBookings: 0,
2144
+ pendingBookings: 0,
2145
+ confirmedBookings: 0,
2146
+ completedBookings: 0,
2147
+ cancelledBookings: 0,
2148
+ totalQuantity: 0,
2149
+ totalRevenue: 0,
2150
+ totalAmount: 0,
2151
+ todayBookings: 0,
2152
+ weekBookings: 0
2199
2153
  };
2200
- return statusMap[value] || value;
2201
- }
2202
- },
2203
- {
2204
- key: "quantity",
2205
- label: "\u9884\u8BA2\u6570\u91CF",
2206
- type: "number",
2207
- enabled: true,
2208
- required: true,
2209
- description: "\u9884\u8BA2\u7684\u6570\u91CF",
2210
- alignment: "center"
2211
- },
2212
- {
2213
- key: "price",
2214
- label: "\u5355\u4EF7",
2215
- type: "number",
2216
- enabled: true,
2217
- required: true,
2218
- description: "\u5355\u4E2A\u753B\u96C6\u7684\u4EF7\u683C",
2219
- alignment: "right",
2220
- formatter: (value) => `\xA5${Number(value).toFixed(2)}`
2221
- },
2222
- {
2223
- key: "totalPrice",
2224
- label: "\u603B\u4EF7\u683C",
2225
- type: "number",
2226
- enabled: true,
2227
- required: true,
2228
- description: "\u603B\u4EF7\u683C\uFF08\u5355\u4EF7 \xD7 \u6570\u91CF\uFF09",
2229
- alignment: "right",
2230
- formatter: (value) => `\xA5${Number(value).toFixed(2)}`
2231
- },
2232
- {
2233
- key: "notes",
2234
- label: "\u7528\u6237\u5907\u6CE8",
2235
- type: "string",
2236
- enabled: true,
2237
- required: false,
2238
- description: "\u7528\u6237\u63D0\u4EA4\u7684\u5907\u6CE8\u4FE1\u606F",
2239
- alignment: "left"
2240
- },
2241
- {
2242
- key: "pickupMethod",
2243
- label: "\u9886\u53D6\u65B9\u5F0F",
2244
- type: "string",
2245
- enabled: true,
2246
- required: false,
2247
- description: "\u7528\u6237\u9009\u62E9\u7684\u9886\u53D6\u65B9\u5F0F",
2248
- alignment: "left"
2249
- },
2250
- {
2251
- key: "adminNotes",
2252
- label: "\u7BA1\u7406\u5458\u5907\u6CE8",
2253
- type: "string",
2254
- enabled: true,
2255
- required: false,
2256
- description: "\u7BA1\u7406\u5458\u6DFB\u52A0\u7684\u5907\u6CE8\u4FE1\u606F",
2257
- alignment: "left"
2258
- },
2259
- {
2260
- key: "createdAt",
2261
- label: "\u521B\u5EFA\u65F6\u95F4",
2262
- type: "date",
2263
- enabled: true,
2264
- required: true,
2265
- description: "\u9884\u8BA2\u521B\u5EFA\u7684\u65F6\u95F4",
2266
- alignment: "center",
2267
- formatter: (value) => {
2268
- if (!value) return "";
2269
- const date = new Date(value);
2270
- return date.toLocaleString("zh-CN");
2271
- }
2272
- },
2273
- {
2274
- key: "updatedAt",
2275
- label: "\u66F4\u65B0\u65F6\u95F4",
2276
- type: "date",
2277
- enabled: true,
2278
- required: true,
2279
- description: "\u9884\u8BA2\u6700\u540E\u66F4\u65B0\u7684\u65F6\u95F4",
2280
- alignment: "center",
2281
- formatter: (value) => {
2282
- if (!value) return "";
2283
- const date = new Date(value);
2284
- return date.toLocaleString("zh-CN");
2285
- }
2286
- },
2287
- {
2288
- key: "confirmedAt",
2289
- label: "\u786E\u8BA4\u65F6\u95F4",
2290
- type: "date",
2291
- enabled: true,
2292
- required: false,
2293
- description: "\u9884\u8BA2\u786E\u8BA4\u7684\u65F6\u95F4",
2294
- alignment: "center",
2295
- formatter: (value) => {
2296
- if (!value) return "";
2297
- const date = new Date(value);
2298
- return date.toLocaleString("zh-CN");
2299
- }
2300
- },
2301
- {
2302
- key: "completedAt",
2303
- label: "\u5B8C\u6210\u65F6\u95F4",
2304
- type: "date",
2305
- enabled: true,
2306
- required: false,
2307
- description: "\u9884\u8BA2\u5B8C\u6210\u7684\u65F6\u95F4",
2308
- alignment: "center",
2309
- formatter: (value) => {
2310
- if (!value) return "";
2311
- const date = new Date(value);
2312
- return date.toLocaleString("zh-CN");
2313
- }
2314
- },
2315
- {
2316
- key: "cancelledAt",
2317
- label: "\u53D6\u6D88\u65F6\u95F4",
2318
- type: "date",
2319
- enabled: true,
2320
- required: false,
2321
- description: "\u9884\u8BA2\u53D6\u6D88\u7684\u65F6\u95F4",
2322
- alignment: "center",
2323
- formatter: (value) => {
2324
- if (!value) return "";
2325
- const date = new Date(value);
2326
- return date.toLocaleString("zh-CN");
2327
- }
2328
- },
2329
- {
2330
- key: "userTotalPrice",
2331
- label: "\u7528\u6237\u603B\u4EF7",
2332
- type: "number",
2333
- enabled: false,
2334
- // 默认不启用,需要勾选才启用
2335
- required: false,
2336
- description: "\u6839\u636EQQ\u53F7\u548C\u624B\u673A\u53F7\u7EDF\u4E00\u5339\u914D\u7684\u8BE5\u7528\u6237\u6240\u6709\u9884\u8BA2\u5546\u54C1\u7684\u603B\u4EF7\u683C",
2337
- alignment: "right",
2338
- formatter: (value) => `\xA5${Number(value || 0).toFixed(2)}`
2339
- }
2340
- ];
2341
- DEFAULT_BOOKING_EXPORT_CONFIG = {
2342
- id: "default_booking_export",
2343
- name: "\u9884\u8BA2\u4FE1\u606F\u5BFC\u51FA",
2344
- description: "\u5BFC\u51FA\u6240\u6709\u9884\u8BA2\u4FE1\u606F\u4E3AExcel\u683C\u5F0F\uFF0C\u652F\u6301QQ\u53F7\u548C\u624B\u673A\u53F7\u5408\u5E76\u5355\u5143\u683C",
2345
- format: "excel",
2346
- fields: BOOKING_EXPORT_FIELDS,
2347
- grouping: {
2348
- enabled: true,
2349
- fields: [
2350
- {
2351
- key: "phoneNumber",
2352
- label: "\u624B\u673A\u53F7",
2353
- mode: "merge",
2354
- valueProcessing: "first",
2355
- showGroupHeader: false,
2356
- mergeCells: true
2357
- },
2358
- {
2359
- key: "qqNumber",
2360
- label: "QQ\u53F7",
2361
- mode: "merge",
2362
- valueProcessing: "first",
2363
- showGroupHeader: false,
2364
- mergeCells: true
2365
- },
2366
- {
2367
- key: "userTotalPrice",
2368
- label: "\u7528\u6237\u603B\u4EF7",
2369
- mode: "merge",
2370
- valueProcessing: "first",
2371
- showGroupHeader: false,
2372
- mergeCells: true
2373
- }
2374
- ],
2375
- preserveOrder: true,
2376
- nullValueHandling: "separate"
2377
- },
2378
- fileNameTemplate: "\u9884\u8BA2\u4FE1\u606F_{date}",
2379
- includeHeader: true,
2380
- delimiter: ",",
2381
- encoding: "utf-8",
2382
- addBOM: true,
2383
- maxRows: void 0,
2384
- createdAt: /* @__PURE__ */ new Date(),
2385
- updatedAt: /* @__PURE__ */ new Date(),
2386
- moduleId: "showmasterpiece",
2387
- businessId: "bookings"
2388
- };
2389
- }
2390
- });
2391
-
2392
- // src/showmasterpiece/services/index.ts
2393
- var init_services = __esm({
2394
- "src/showmasterpiece/services/index.ts"() {
2395
- init_masterpiecesService();
2396
- init_masterpiecesConfigService();
2397
- init_cartService();
2398
- init_bookingService();
2399
- init_bookingAdminService();
2400
- init_cartHistoryService();
2401
- init_fileService();
2402
- init_exportConfig();
2403
- }
2404
- });
2405
- var useMasterpiecesConfig;
2406
- var init_useMasterpiecesConfig = __esm({
2407
- "src/showmasterpiece/logic/hooks/useMasterpiecesConfig.ts"() {
2408
- init_services();
2409
- useMasterpiecesConfig = () => {
2410
- const [config, setConfig] = useState(null);
2411
- const [collections, setCollections] = useState([]);
2412
- const [categories, setCategories] = useState([]);
2413
- const [tags, setTags] = useState([]);
2414
- const [loading, setLoading] = useState(true);
2415
- const [error, setError] = useState(null);
2416
- const [refreshCounter, setRefreshCounter] = useState(0);
2417
- useEffect(() => {
2418
- loadData();
2419
- }, []);
2420
- const loadData = async () => {
2421
- console.log("\u{1F504} [Hook] \u5F00\u59CB\u52A0\u8F7D\u6570\u636E...");
2422
- try {
2423
- setLoading(true);
2424
- setError(null);
2425
- console.log("\u{1F4E1} [Hook] \u5E76\u884C\u8BF7\u6C42\u6240\u6709\u6570\u636E...");
2426
- const timestamp = Date.now();
2427
- const [configData, collectionsResponse, categoriesData, tagsData] = await Promise.all([
2428
- getConfig(),
2429
- fetch(`/api/showmasterpiece/collections?_t=${timestamp}&nocache=true&includeImages=true`, {
2430
- headers: {
2431
- "Cache-Control": "no-cache",
2432
- "Pragma": "no-cache"
2433
- }
2434
- }).then((r) => r.json()),
2435
- getCategories(),
2436
- getTags()
2437
- ]);
2438
- const collectionsData = collectionsResponse.data || [];
2439
- console.log("\u2705 [Hook] \u6570\u636E\u52A0\u8F7D\u5B8C\u6210:", {
2440
- \u914D\u7F6E: configData ? "\u5DF2\u52A0\u8F7D" : "\u672A\u52A0\u8F7D",
2441
- \u753B\u96C6\u6570\u91CF: collectionsData.length,
2442
- \u5206\u7C7B\u6570\u91CF: categoriesData.length,
2443
- \u6807\u7B7E\u6570\u91CF: tagsData.length
2444
- });
2445
- if (collectionsData.length > 0) {
2446
- console.log("\u{1F4DA} [Hook] \u753B\u96C6\u8BE6\u60C5:");
2447
- collectionsData.forEach((collection, index) => {
2448
- console.log(` ${index + 1}. ${collection.title} - \u4F5C\u54C1\u6570\u91CF: ${collection.pages.length}`);
2449
- if (collection.pages.length > 0) {
2450
- collection.pages.forEach((page, pageIndex) => {
2451
- console.log(` ${pageIndex + 1}. ${page.title} (ID: ${page.id})`);
2452
- });
2453
- }
2454
- });
2455
- }
2456
- setConfig(configData);
2457
- setCollections(collectionsData);
2458
- setCategories(categoriesData);
2459
- setTags(tagsData);
2460
- console.log("\u{1F4BE} [Hook] \u72B6\u6001\u66F4\u65B0\u5B8C\u6210");
2461
- return {
2462
- config: configData,
2463
- collections: collectionsData,
2464
- // 这里已经是提取后的数组数据
2465
- categories: categoriesData,
2466
- tags: tagsData
2467
- };
2468
- } catch (err) {
2469
- console.error("\u274C [Hook] \u52A0\u8F7D\u6570\u636E\u5931\u8D25:", err);
2470
- console.error("\u9519\u8BEF\u8BE6\u60C5:", {
2471
- message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
2472
- stack: err instanceof Error ? err.stack : void 0
2473
- });
2474
- setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
2475
- throw err;
2476
- } finally {
2477
- setLoading(false);
2478
- console.log("\u{1F3C1} [Hook] \u6570\u636E\u52A0\u8F7D\u6D41\u7A0B\u7ED3\u675F");
2479
- }
2480
- };
2481
- const handleApiError = (error2, operation) => {
2482
- if (error2 instanceof Error) {
2483
- if (error2.message.includes("413") || error2.message.includes("\u592A\u5927")) {
2484
- throw new Error("\u56FE\u7247\u6587\u4EF6\u8FC7\u5927\uFF0C\u8BF7\u4F7F\u7528\u538B\u7F29\u540E\u7684\u56FE\u7247");
2485
- }
2486
- if (error2.message.includes("401")) {
2487
- throw new Error("\u6CA1\u6709\u6743\u9650\u6267\u884C\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u5148\u767B\u5F55");
2488
- }
2489
- if (error2.message.includes("404") || error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728")) {
2490
- throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
2491
- }
2492
- if (error2.message.includes("409")) {
2493
- if (error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728") || error2.message.includes("\u5DF2\u88AB\u5220\u9664")) {
2494
- throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
2495
- }
2496
- throw new Error(error2.message);
2497
- }
2498
- throw new Error(`${operation}\u5931\u8D25\uFF1A${error2.message}`);
2499
- }
2500
- throw new Error(`${operation}\u5931\u8D25\uFF1A\u672A\u77E5\u9519\u8BEF`);
2501
- };
2502
- const handleUpdateConfig = async (configData) => {
2503
- try {
2504
- const updatedConfig = await updateConfig(configData);
2505
- setConfig(updatedConfig);
2506
- } catch (err) {
2507
- handleApiError(err, "\u66F4\u65B0\u914D\u7F6E");
2508
- }
2509
- };
2510
- const handleResetConfig = async () => {
2511
- try {
2512
- const resetConfigData = await resetConfig();
2513
- setConfig(resetConfigData);
2514
- } catch (err) {
2515
- handleApiError(err, "\u91CD\u7F6E\u914D\u7F6E");
2516
- }
2517
- };
2518
- const handleCreateCollection = async (collectionData) => {
2519
- try {
2520
- const newCollection = await createCollection(collectionData);
2521
- await loadData();
2522
- } catch (err) {
2523
- handleApiError(err, "\u521B\u5EFA\u753B\u96C6");
2524
- }
2525
- };
2526
- const handleUpdateCollection = async (id, collectionData) => {
2527
- try {
2528
- const updatedCollection = await updateCollection(id, collectionData);
2529
- await loadData();
2530
- } catch (err) {
2531
- handleApiError(err, "\u66F4\u65B0\u753B\u96C6");
2532
- }
2533
- };
2534
- const handleDeleteCollection = async (id) => {
2535
- try {
2536
- await deleteCollection(id);
2537
- await loadData();
2538
- } catch (err) {
2539
- handleApiError(err, "\u5220\u9664\u753B\u96C6");
2540
- }
2541
- };
2542
- const handleAddArtworkToCollection = async (collectionId, artworkData) => {
2543
- console.log("\u{1F3AF} [Hook] \u5F00\u59CB\u6DFB\u52A0\u4F5C\u54C1\u5230\u753B\u96C6:", {
2544
- collectionId,
2545
- title: artworkData.title,
2546
- number: artworkData.number,
2547
- imageSize: artworkData.image ? `${artworkData.image.length} chars` : "null",
2548
- description: artworkData.description?.substring(0, 50) + (artworkData.description && artworkData.description.length > 50 ? "..." : "")
2549
- });
2550
- try {
2551
- console.log("\u{1F4DE} [Hook] \u8C03\u7528API\u670D\u52A1...");
2552
- const newArtwork = await addArtworkToCollection(collectionId, artworkData);
2553
- console.log("\u2705 [Hook] API\u8C03\u7528\u6210\u529F\uFF0C\u8FD4\u56DE\u4F5C\u54C1:", {
2554
- id: newArtwork.id,
2555
- title: newArtwork.title,
2556
- number: newArtwork.number
2557
- });
2558
- console.log("\u{1F504} [Hook] \u91CD\u65B0\u52A0\u8F7D\u6570\u636E\u4EE5\u786E\u4FDD\u4E0E\u6570\u636E\u5E93\u5B8C\u5168\u540C\u6B65...");
2559
- const reloadedData = await loadData();
2560
- console.log("\u2705 [Hook] \u6570\u636E\u91CD\u65B0\u52A0\u8F7D\u5B8C\u6210");
2561
- await new Promise((resolve) => setTimeout(resolve, 50));
2562
- const targetCollection = reloadedData.collections.find((c) => c.id === collectionId);
2563
- if (targetCollection) {
2564
- const newArtworkInCollection = targetCollection.pages.find((p) => p.id === newArtwork.id);
2565
- if (newArtworkInCollection) {
2566
- console.log("\u2705 [Hook] \u9A8C\u8BC1\u6210\u529F\uFF1A\u65B0\u4F5C\u54C1\u5DF2\u5728\u753B\u96C6\u4E2D", {
2567
- artworkId: newArtwork.id,
2568
- collectionId,
2569
- artworkTitle: newArtworkInCollection.title
2570
- });
2571
- } else {
2572
- console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u65B0\u4F5C\u54C1\u4E0D\u5728\u91CD\u65B0\u52A0\u8F7D\u7684\u6570\u636E\u4E2D", {
2573
- expectedArtworkId: newArtwork.id,
2574
- collectionId,
2575
- currentArtworks: targetCollection.pages.map((p) => ({ id: p.id, title: p.title }))
2576
- });
2577
- console.log("\u{1F504} [Hook] \u518D\u6B21\u5C1D\u8BD5\u91CD\u65B0\u52A0\u8F7D\u6570\u636E...");
2578
- await loadData();
2579
- }
2580
- } else {
2581
- console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u627E\u4E0D\u5230\u76EE\u6807\u753B\u96C6", {
2582
- collectionId,
2583
- availableCollections: reloadedData.collections.map((c) => ({ id: c.id, title: c.title }))
2584
- });
2585
- }
2586
- console.log("\u{1F389} [Hook] \u5F3A\u5236\u66F4\u65B0\u72B6\u6001\u4EE5\u786E\u4FDDUI\u540C\u6B65...");
2587
- setCollections([...reloadedData.collections]);
2588
- setRefreshCounter((prev) => prev + 1);
2589
- console.log("\u{1F525} [Hook] \u89E6\u53D1\u5F3A\u5236\u91CD\u65B0\u6E32\u67D3");
2590
- } catch (err) {
2591
- console.error("\u274C [Hook] \u6DFB\u52A0\u4F5C\u54C1\u5931\u8D25:", err);
2592
- console.error("\u9519\u8BEF\u8BE6\u60C5:", {
2593
- message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
2594
- collectionId,
2595
- artworkTitle: artworkData.title
2596
- });
2597
- handleApiError(err, "\u6DFB\u52A0\u4F5C\u54C1");
2598
- }
2599
- };
2600
- const handleUpdateArtwork = async (collectionId, artworkId, artworkData) => {
2601
- try {
2602
- const updatedArtwork = await updateArtwork(collectionId, artworkId, artworkData);
2603
- await loadData();
2604
- } catch (err) {
2605
- handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1");
2606
- }
2607
- };
2608
- const handleDeleteArtwork = async (collectionId, artworkId) => {
2609
- try {
2610
- await deleteArtwork(collectionId, artworkId);
2611
- await loadData();
2612
- } catch (err) {
2613
- handleApiError(err, "\u5220\u9664\u4F5C\u54C1");
2614
- }
2615
- };
2616
- const handleMoveArtworkUp = async (collectionId, artworkId) => {
2617
- try {
2618
- await moveArtworkUp(collectionId, artworkId);
2619
- await updateCollectionArtworks(collectionId);
2620
- } catch (err) {
2621
- handleApiError(err, "\u4E0A\u79FB\u4F5C\u54C1");
2622
- }
2623
- };
2624
- const handleMoveArtworkDown = async (collectionId, artworkId) => {
2625
- try {
2626
- await moveArtworkDown(collectionId, artworkId);
2627
- await updateCollectionArtworks(collectionId);
2628
- } catch (err) {
2629
- handleApiError(err, "\u4E0B\u79FB\u4F5C\u54C1");
2630
- }
2631
- };
2632
- const handleUpdateArtworkOrder = async (collectionId, artworkOrders) => {
2633
- try {
2634
- await updateArtworkOrder(collectionId, artworkOrders);
2635
- await updateCollectionArtworks(collectionId);
2636
- } catch (err) {
2637
- handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1\u987A\u5E8F");
2638
- }
2639
- };
2640
- const updateCollectionArtworks = async (collectionId) => {
2641
- try {
2642
- const updatedArtworks = await getArtworksByCollection(collectionId);
2643
- setCollections(
2644
- (prevCollections) => prevCollections.map(
2645
- (collection) => collection.id === collectionId ? { ...collection, pages: updatedArtworks } : collection
2646
- )
2647
- );
2648
- } catch (err) {
2649
- console.error("\u66F4\u65B0\u753B\u96C6\u4F5C\u54C1\u6570\u636E\u5931\u8D25:", err);
2650
- await loadData();
2651
- }
2652
- };
2653
- const handleMoveCollectionUp = async (collectionId) => {
2654
- try {
2655
- await moveCollectionUp(collectionId);
2656
- await updateCollectionsData();
2657
- } catch (err) {
2658
- handleApiError(err, "\u4E0A\u79FB\u753B\u96C6");
2659
- }
2660
- };
2661
- const handleMoveCollectionDown = async (collectionId) => {
2662
- try {
2663
- await moveCollectionDown(collectionId);
2664
- await updateCollectionsData();
2665
- } catch (err) {
2666
- handleApiError(err, "\u4E0B\u79FB\u753B\u96C6");
2667
- }
2668
- };
2669
- const handleUpdateCollectionOrder = async (collectionOrders) => {
2670
- try {
2671
- await updateCollectionOrder(collectionOrders);
2672
- await updateCollectionsData();
2673
- } catch (err) {
2674
- handleApiError(err, "\u66F4\u65B0\u753B\u96C6\u987A\u5E8F");
2675
- }
2676
- };
2677
- const updateCollectionsData = async () => {
2678
- try {
2679
- const updatedCollections = await getAllCollections();
2680
- setCollections(updatedCollections);
2681
- } catch (err) {
2682
- console.error("\u66F4\u65B0\u753B\u96C6\u6570\u636E\u5931\u8D25:", err);
2683
- await loadData();
2684
- }
2685
- };
2686
- return {
2687
- // 数据
2688
- config,
2689
- collections,
2690
- categories,
2691
- tags,
2692
- loading,
2693
- error,
2694
- refreshCounter,
2695
- // 方法
2696
- updateConfig: handleUpdateConfig,
2697
- resetConfig: handleResetConfig,
2698
- createCollection: handleCreateCollection,
2699
- updateCollection: handleUpdateCollection,
2700
- deleteCollection: handleDeleteCollection,
2701
- addArtworkToCollection: handleAddArtworkToCollection,
2702
- updateArtwork: handleUpdateArtwork,
2703
- deleteArtwork: handleDeleteArtwork,
2704
- // 新增:作品排序方法
2705
- moveArtworkUp: handleMoveArtworkUp,
2706
- moveArtworkDown: handleMoveArtworkDown,
2707
- updateArtworkOrder: handleUpdateArtworkOrder,
2708
- // 新增:画集排序方法
2709
- moveCollectionUp: handleMoveCollectionUp,
2710
- moveCollectionDown: handleMoveCollectionDown,
2711
- updateCollectionOrder: handleUpdateCollectionOrder,
2712
- refreshData: loadData
2713
- };
2714
- };
2715
- }
2716
- });
2717
- function useCart(userId) {
2718
- const [state, setState] = useState({
2719
- cart: {
2720
- items: [],
2721
- totalQuantity: 0,
2722
- totalPrice: 0
2723
- },
2724
- loading: false,
2725
- error: void 0,
2726
- isCartOpen: false
2727
- });
2728
- const loadCart = useCallback(async () => {
2729
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2730
- try {
2731
- const cartData = await getCart(userId);
2732
- setState((prev) => ({
2733
- ...prev,
2734
- cart: cartData,
2735
- loading: false
2736
- }));
2737
- } catch (error) {
2738
- console.error("\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25:", error);
2739
- setState((prev) => ({
2740
- ...prev,
2741
- loading: false,
2742
- error: error instanceof Error ? error.message : "\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25"
2743
- }));
2744
- }
2745
- }, [userId]);
2746
- const addItemToCart = useCallback(async (request) => {
2747
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2748
- try {
2749
- const updatedCart = await addToCart(request);
2750
- setState((prev) => ({
2751
- ...prev,
2752
- cart: updatedCart,
2753
- loading: false
2754
- }));
2755
- notifyCartUpdate();
2756
- } catch (error) {
2757
- console.error("\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25:", error);
2758
- setState((prev) => ({
2759
- ...prev,
2760
- loading: false,
2761
- error: error instanceof Error ? error.message : "\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25"
2762
- }));
2763
- }
2764
- }, [userId]);
2765
- const updateItemQuantity = useCallback(async (collectionId, quantity) => {
2766
- if (quantity <= 0) {
2767
- await removeItemFromCart(collectionId);
2768
- return;
2769
- }
2770
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2771
- try {
2772
- const request = {
2773
- userId,
2774
- collectionId,
2775
- quantity
2776
- };
2777
- const updatedCart = await updateCartItem(request);
2778
- setState((prev) => ({
2779
- ...prev,
2780
- cart: updatedCart,
2781
- loading: false
2782
- }));
2783
- notifyCartUpdate();
2784
- } catch (error) {
2785
- console.error("\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25:", error);
2786
- setState((prev) => ({
2787
- ...prev,
2788
- loading: false,
2789
- error: error instanceof Error ? error.message : "\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25"
2790
- }));
2791
- }
2792
- }, [userId]);
2793
- const removeItemFromCart = useCallback(async (collectionId) => {
2794
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2795
- try {
2796
- const request = {
2797
- userId,
2798
- collectionId
2799
- };
2800
- const updatedCart = await removeFromCart(request);
2801
- setState((prev) => ({
2802
- ...prev,
2803
- cart: updatedCart,
2804
- loading: false
2805
- }));
2806
- notifyCartUpdate();
2807
- } catch (error) {
2808
- console.error("\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25:", error);
2809
- setState((prev) => ({
2810
- ...prev,
2811
- loading: false,
2812
- error: error instanceof Error ? error.message : "\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25"
2813
- }));
2814
- }
2815
- }, [userId]);
2816
- const clearCartItems = useCallback(async () => {
2817
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2818
- try {
2819
- await clearCart(userId);
2820
- setState((prev) => ({
2821
- ...prev,
2822
- cart: { items: [], totalQuantity: 0, totalPrice: 0 },
2823
- loading: false
2824
- }));
2825
- notifyCartUpdate();
2826
- } catch (error) {
2827
- console.error("\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25:", error);
2828
- setState((prev) => ({
2829
- ...prev,
2830
- loading: false,
2831
- error: error instanceof Error ? error.message : "\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25"
2832
- }));
2833
- }
2834
- }, [userId]);
2835
- const checkoutCart = useCallback(async (qqNumber, phoneNumber, notes, pickupMethod = "") => {
2836
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2837
- try {
2838
- const request = {
2839
- qqNumber,
2840
- phoneNumber,
2841
- items: state.cart.items.map((item) => ({
2842
- collectionId: item.collectionId,
2843
- quantity: item.quantity
2844
- })),
2845
- notes,
2846
- pickupMethod
2847
- };
2848
- const result = await batchBooking(request, state.cart);
2849
- if (result.successCount > 0) {
2850
- await clearCartItems();
2154
+ } catch (error) {
2155
+ console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
2156
+ throw error;
2157
+ }
2851
2158
  }
2852
- setState((prev) => ({ ...prev, loading: false }));
2853
- return result;
2854
- } catch (error) {
2855
- console.error("\u6279\u91CF\u9884\u8BA2\u5931\u8D25:", error);
2856
- setState((prev) => ({
2857
- ...prev,
2858
- loading: false,
2859
- error: error instanceof Error ? error.message : "\u6279\u91CF\u9884\u8BA2\u5931\u8D25"
2860
- }));
2861
- throw error;
2862
- }
2863
- }, [state.cart.items, clearCartItems]);
2864
- const openCart = useCallback(() => {
2865
- setState((prev) => ({ ...prev, isCartOpen: true }));
2866
- }, []);
2867
- const closeCart = useCallback(() => {
2868
- setState((prev) => ({ ...prev, isCartOpen: false }));
2869
- }, []);
2870
- const clearError = useCallback(() => {
2871
- setState((prev) => ({ ...prev, error: void 0 }));
2872
- }, []);
2873
- useEffect(() => {
2874
- if (userId) {
2875
- loadCart();
2876
- }
2877
- }, [userId, loadCart]);
2878
- return {
2879
- // 状态
2880
- cart: state.cart,
2881
- loading: state.loading,
2882
- error: state.error,
2883
- isCartOpen: state.isCartOpen,
2884
- // 操作方法
2885
- loadCart,
2886
- addItemToCart,
2887
- updateItemQuantity,
2888
- removeItemFromCart,
2889
- clearCartItems,
2890
- checkoutCart,
2891
- openCart,
2892
- closeCart,
2893
- clearError
2894
- };
2895
- }
2896
- var cartUpdateEvents, CART_UPDATE_EVENT, notifyCartUpdate;
2897
- var init_useCart = __esm({
2898
- "src/showmasterpiece/logic/hooks/useCart.ts"() {
2899
- init_services();
2900
- cartUpdateEvents = new EventTarget();
2901
- CART_UPDATE_EVENT = "cart-updated";
2902
- notifyCartUpdate = () => {
2903
- cartUpdateEvents.dispatchEvent(new Event(CART_UPDATE_EVENT));
2904
- };
2905
- }
2906
- });
2907
- function useBooking(_props = {}) {
2908
- const [state, setState] = useState({
2909
- collections: [],
2910
- loading: false,
2911
- error: void 0,
2912
- submitting: false,
2913
- submitted: false
2914
- });
2915
- const loadCollections = useCallback(async () => {
2916
- setState((prev) => ({ ...prev, loading: true, error: void 0 }));
2917
- try {
2918
- console.log("\u{1F504} [useBooking] \u52A0\u8F7D\u753B\u96C6\u5217\u8868...");
2919
- const collections = await getBookableCollections();
2920
- setState((prev) => ({
2921
- ...prev,
2922
- collections,
2923
- loading: false
2924
- }));
2925
- } catch (error) {
2926
- console.error("\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25:", error);
2927
- setState((prev) => ({
2928
- ...prev,
2929
- loading: false,
2930
- error: error instanceof Error ? error.message : "\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25"
2931
- }));
2932
- }
2933
- }, []);
2934
- const submitBooking = useCallback(async (formData) => {
2935
- setState((prev) => ({ ...prev, submitting: true, error: void 0 }));
2936
- try {
2937
- const bookingData = {
2938
- collectionId: formData.collectionId,
2939
- qqNumber: formData.qqNumber,
2940
- phoneNumber: formData.phoneNumber.trim(),
2941
- quantity: formData.quantity,
2942
- notes: formData.notes || void 0
2943
- };
2944
- await createBooking(bookingData);
2945
- setState((prev) => ({
2946
- ...prev,
2947
- submitting: false,
2948
- submitted: true
2949
- }));
2950
- } catch (error) {
2951
- console.error("\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25:", error);
2952
- setState((prev) => ({
2953
- ...prev,
2954
- submitting: false,
2955
- error: error instanceof Error ? error.message : "\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25"
2956
- }));
2957
- }
2958
- }, []);
2959
- const resetSubmission = useCallback(() => {
2960
- setState((prev) => ({
2961
- ...prev,
2962
- submitted: false,
2963
- error: void 0
2964
- }));
2965
- }, []);
2966
- const clearError = useCallback(() => {
2967
- setState((prev) => ({ ...prev, error: void 0 }));
2968
- }, []);
2969
- useEffect(() => {
2970
- loadCollections();
2971
- }, [loadCollections]);
2972
- return {
2973
- // 状态
2974
- collections: state.collections,
2975
- loading: state.loading,
2976
- error: state.error,
2977
- submitting: state.submitting,
2978
- submitted: state.submitted,
2979
- // 操作方法
2980
- loadCollections,
2981
- submitBooking,
2982
- resetSubmission,
2983
- clearError
2984
- };
2985
- }
2986
- function useBookingForm() {
2987
- const [formData, setFormData] = useState({
2988
- collectionId: 0,
2989
- qqNumber: "",
2990
- phoneNumber: "",
2991
- quantity: 1,
2992
- notes: ""
2993
- });
2994
- const [errors, setErrors] = useState({});
2995
- const updateField = useCallback((field, value) => {
2996
- setFormData((prev) => ({ ...prev, [field]: value }));
2997
- if (errors[field]) {
2998
- setErrors((prev) => ({ ...prev, [field]: void 0 }));
2999
- }
3000
- }, [errors]);
3001
- const validateForm = useCallback(() => {
3002
- const newErrors = {};
3003
- if (!formData.collectionId) {
3004
- newErrors.collectionId = "\u8BF7\u9009\u62E9\u8981\u9884\u8BA2\u7684\u753B\u96C6";
3005
- }
3006
- if (!formData.qqNumber.trim()) {
3007
- newErrors.qqNumber = "\u8BF7\u8F93\u5165QQ\u53F7";
3008
- } else if (!/^\d{5,11}$/.test(formData.qqNumber.trim())) {
3009
- newErrors.qqNumber = "QQ\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
3010
- }
3011
- if (formData.phoneNumber.trim()) {
3012
- const phoneRegex = /^1[3-9]\d{9}$/;
3013
- if (!phoneRegex.test(formData.phoneNumber.trim())) {
3014
- newErrors.phoneNumber = "\u624B\u673A\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
2159
+ /**
2160
+ * 更新预订状态
2161
+ */
2162
+ static async updateBookingStatus(bookingId, status, adminNotes) {
2163
+ try {
2164
+ const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}/status`, {
2165
+ method: "PUT",
2166
+ headers: {
2167
+ "Content-Type": "application/json"
2168
+ },
2169
+ body: JSON.stringify({ status, adminNotes })
2170
+ });
2171
+ if (!response.ok) {
2172
+ throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
2173
+ }
2174
+ } catch (error) {
2175
+ console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
2176
+ throw error;
2177
+ }
3015
2178
  }
3016
- }
3017
- if (!formData.quantity || formData.quantity < 1) {
3018
- newErrors.quantity = "\u9884\u8BA2\u6570\u91CF\u5FC5\u987B\u5927\u4E8E0";
3019
- }
3020
- setErrors(newErrors);
3021
- return Object.keys(newErrors).length === 0;
3022
- }, [formData]);
3023
- const resetForm = useCallback(() => {
3024
- setFormData({
3025
- collectionId: 0,
3026
- qqNumber: "",
3027
- phoneNumber: "",
3028
- quantity: 1,
3029
- notes: ""
3030
- });
3031
- setErrors({});
3032
- }, []);
3033
- return {
3034
- formData,
3035
- errors,
3036
- updateField,
3037
- validateForm,
3038
- resetForm
3039
- };
3040
- }
3041
- var init_useBooking = __esm({
3042
- "src/showmasterpiece/logic/hooks/useBooking.ts"() {
3043
- init_services();
2179
+ /**
2180
+ * 删除预订
2181
+ */
2182
+ static async deleteBooking(bookingId) {
2183
+ try {
2184
+ const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}`, {
2185
+ method: "DELETE",
2186
+ headers: {
2187
+ "Content-Type": "application/json"
2188
+ }
2189
+ });
2190
+ if (!response.ok) {
2191
+ const errorData = await response.json().catch(() => ({}));
2192
+ throw new Error(errorData.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
2193
+ }
2194
+ console.log("\u2705 \u9884\u8BA2\u5220\u9664\u6210\u529F:", { bookingId });
2195
+ } catch (error) {
2196
+ console.error("\u5220\u9664\u9884\u8BA2\u5931\u8D25:", error);
2197
+ throw error;
2198
+ }
2199
+ }
2200
+ /**
2201
+ * 导出预订数据
2202
+ */
2203
+ static async exportBookings(format = "csv") {
2204
+ try {
2205
+ const response = await fetch(`/api/showmasterpiece/bookings/admin/export?format=${format}`);
2206
+ if (!response.ok) {
2207
+ throw new Error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25");
2208
+ }
2209
+ return await response.blob();
2210
+ } catch (error) {
2211
+ console.error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
2212
+ throw error;
2213
+ }
2214
+ }
2215
+ };
2216
+ getAllBookings = BookingAdminService.getAllBookings;
2217
+ getBookingStats = BookingAdminService.getBookingStats;
2218
+ forceRefreshAllBookings = BookingAdminService.forceRefreshAllBookings;
2219
+ forceRefreshBookingStats = BookingAdminService.forceRefreshBookingStats;
2220
+ updateBookingStatus2 = BookingAdminService.updateBookingStatus;
2221
+ deleteBooking2 = BookingAdminService.deleteBooking;
2222
+ exportBookings = BookingAdminService.exportBookings;
3044
2223
  }
3045
2224
  });
3046
2225
  var useBookingAdmin;
3047
2226
  var init_useBookingAdmin = __esm({
3048
2227
  "src/showmasterpiece/logic/hooks/useBookingAdmin.ts"() {
3049
- init_services();
2228
+ init_bookingAdminService();
3050
2229
  useBookingAdmin = () => {
3051
2230
  const [bookings, setBookings] = useState([]);
3052
2231
  const [stats, setStats] = useState({
@@ -3366,7 +2545,7 @@ var CartContext, CartProvider;
3366
2545
  var init_CartContext = __esm({
3367
2546
  "src/showmasterpiece/logic/contexts/CartContext.tsx"() {
3368
2547
  "use client";
3369
- init_services();
2548
+ init_cartService();
3370
2549
  init_hooks();
3371
2550
  CartContext = createContext(void 0);
3372
2551
  CartProvider = ({ children, userId }) => {
@@ -3517,6 +2696,6 @@ var init_CartContext = __esm({
3517
2696
  }
3518
2697
  });
3519
2698
 
3520
- export { BOOKING_EXPORT_FIELDS, BookingAdminService, BookingService, CART_UPDATE_EVENT, CartHistoryService, CartProvider, CartService, DEFAULT_BOOKING_EXPORT_CONFIG, MasterpiecesService, addArtworkToCollection, addToCart, batchBooking, cartUpdateEvents, clearCart, clearConfigCache, clearUserHistory, createBooking, createCategory, createCollection, deleteArtwork, deleteBooking, deleteBooking2, deleteCollection, deleteHistoryRecord, exportBookings, forceRefreshAllBookings, forceRefreshBookingStats, getAllBookings, getAllCollections, getAllHistory, getArtworkImageUrl, getArtworksByCollection, getBookableCollections, getBooking, getBookingStats, getBookings, getCart, getCartHistory, getCategories, getCollectionsOverview, getConfig, getMasterpieces, getShowMasterpieceFileConfig, getStatistics, getStorageModeDisplayName, getTags, init_CartContext, init_hooks, init_services, moveArtwork, moveArtworkDown, moveArtworkUp, moveCollection, moveCollectionDown, moveCollectionUp, notifyCartUpdate, refreshFileServiceConfig, removeFromCart, resetConfig, saveCartHistory, shouldUseUniversalFileService, updateArtwork, updateArtworkOrder, updateBooking, updateBookingStatus, updateBookingStatus2, updateCartItem, updateCollection, updateCollectionOrder, updateConfig, uploadArtworkImage, useBooking, useBookingAdmin, useBookingForm, useCart, useCartContext, useDeadlinePopup, useMasterpieces, useMasterpiecesConfig };
3521
- //# sourceMappingURL=chunk-HYZ5C6FY.mjs.map
3522
- //# sourceMappingURL=chunk-HYZ5C6FY.mjs.map
2699
+ export { BookingAdminService, BookingService, CART_UPDATE_EVENT, CartHistoryService, CartProvider, CartService, MasterpiecesService, addArtworkToCollection, addToCart, batchBooking, cartUpdateEvents, clearCart, clearUserHistory, createBooking, createCategory, createCollection, deleteArtwork, deleteBooking, deleteBooking2, deleteCollection, deleteHistoryRecord, exportBookings, forceRefreshAllBookings, forceRefreshBookingStats, getAllBookings, getAllCollections, getAllHistory, getArtworksByCollection, getBookableCollections, getBooking, getBookingStats, getBookings, getCart, getCartHistory, getCategories, getCollectionsOverview, getConfig, getMasterpieces, getStatistics, getTags, init_CartContext, init_bookingAdminService, init_bookingService, init_cartHistoryService, init_cartService, init_hooks, init_masterpiecesConfigService, init_masterpiecesService, moveArtwork, moveArtworkDown, moveArtworkUp, moveCollection, moveCollectionDown, moveCollectionUp, notifyCartUpdate, removeFromCart, resetConfig, saveCartHistory, updateArtwork, updateArtworkOrder, updateBooking, updateBookingStatus, updateBookingStatus2, updateCartItem, updateCollection, updateCollectionOrder, updateConfig, useBooking, useBookingAdmin, useBookingForm, useCart, useCartContext, useDeadlinePopup, useMasterpieces, useMasterpiecesConfig };
2700
+ //# sourceMappingURL=chunk-WS3QZYBI.mjs.map
2701
+ //# sourceMappingURL=chunk-WS3QZYBI.mjs.map