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