sa2kit 1.6.52 → 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.
- package/dist/AliyunOSSProvider-KSYW2IOG.js +15 -0
- package/dist/{AliyunOSSProvider-2FARPAQD.js.map → AliyunOSSProvider-KSYW2IOG.js.map} +1 -1
- package/dist/AliyunOSSProvider-TBK3G7YK.mjs +6 -0
- package/dist/{AliyunOSSProvider-UMVGVBDJ.mjs.map → AliyunOSSProvider-TBK3G7YK.mjs.map} +1 -1
- package/dist/LocalStorageProvider-2DGYRQAB.mjs +6 -0
- package/dist/{LocalStorageProvider-PYOHETJV.mjs.map → LocalStorageProvider-2DGYRQAB.mjs.map} +1 -1
- package/dist/LocalStorageProvider-SSRW3ZJW.js +15 -0
- package/dist/{LocalStorageProvider-JQF5WK5H.js.map → LocalStorageProvider-SSRW3ZJW.js.map} +1 -1
- package/dist/UniversalFileService-336GFY6N.mjs +6 -0
- package/dist/{UniversalFileService-TNYKO6JN.mjs.map → UniversalFileService-336GFY6N.mjs.map} +1 -1
- package/dist/UniversalFileService-J6ET6KZK.js +15 -0
- package/dist/{UniversalFileService-RBV6EN5J.js.map → UniversalFileService-J6ET6KZK.js.map} +1 -1
- package/dist/booking-BXtkG2ns.d.mts +386 -0
- package/dist/booking-BXtkG2ns.d.ts +386 -0
- package/dist/bookingAdminService-B2QDjSHJ.d.ts +193 -0
- package/dist/bookingAdminService-Dmg7dC6V.d.mts +193 -0
- package/dist/calendar/index.js +11 -11
- package/dist/calendar/index.mjs +4 -4
- package/dist/cart-CcZ7rQyG.d.mts +176 -0
- package/dist/cart-D3o67Q3H.d.ts +176 -0
- package/dist/chunk-25OFOKNF.js +171 -0
- package/dist/chunk-25OFOKNF.js.map +1 -0
- package/dist/chunk-3DXPQ4YV.mjs +165 -0
- package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
- package/dist/{chunk-4VJQZSPU.mjs → chunk-3NHAT7D4.mjs} +3 -4
- package/dist/chunk-3NHAT7D4.mjs.map +1 -0
- package/dist/{chunk-3JW4X3AC.mjs → chunk-622Y6LTH.mjs} +3 -3
- package/dist/{chunk-3JW4X3AC.mjs.map → chunk-622Y6LTH.mjs.map} +1 -1
- package/dist/chunk-ANKVXRPY.mjs +30 -0
- package/dist/chunk-ANKVXRPY.mjs.map +1 -0
- package/dist/chunk-CIVO4R6N.mjs +37 -0
- package/dist/chunk-CIVO4R6N.mjs.map +1 -0
- package/dist/{chunk-IZOIVYOW.js → chunk-DENROXAE.js} +2 -2
- package/dist/{chunk-IZOIVYOW.js.map → chunk-DENROXAE.js.map} +1 -1
- package/dist/{chunk-6BJ76BYC.mjs → chunk-EGJPS7OL.mjs} +3 -3
- package/dist/{chunk-6BJ76BYC.mjs.map → chunk-EGJPS7OL.mjs.map} +1 -1
- package/dist/chunk-EKIOJEJK.js +2719 -0
- package/dist/chunk-EKIOJEJK.js.map +1 -0
- package/dist/chunk-EOWTOG7Y.js +119 -0
- package/dist/chunk-EOWTOG7Y.js.map +1 -0
- package/dist/chunk-HDMIOOZY.mjs +546 -0
- package/dist/chunk-HDMIOOZY.mjs.map +1 -0
- package/dist/{chunk-MZKATHB7.js → chunk-HHVDOIPV.js} +4 -4
- package/dist/{chunk-MZKATHB7.js.map → chunk-HHVDOIPV.js.map} +1 -1
- package/dist/chunk-HJ6MH7J7.js +552 -0
- package/dist/chunk-HJ6MH7J7.js.map +1 -0
- package/dist/chunk-KH6RQ4J5.js +28 -0
- package/dist/chunk-KH6RQ4J5.js.map +1 -0
- package/dist/{chunk-GFVAIT6Y.mjs → chunk-MFG2Y6UR.mjs} +2 -2
- package/dist/{chunk-GFVAIT6Y.mjs.map → chunk-MFG2Y6UR.mjs.map} +1 -1
- package/dist/{chunk-35CXIK5Y.js → chunk-NCOXT7SK.js} +11 -11
- package/dist/{chunk-35CXIK5Y.js.map → chunk-NCOXT7SK.js.map} +1 -1
- package/dist/chunk-NZZZUMMX.mjs +784 -0
- package/dist/chunk-NZZZUMMX.mjs.map +1 -0
- package/dist/{chunk-OBIPI4GU.mjs → chunk-OFYBMMWT.mjs} +4 -4
- package/dist/{chunk-OBIPI4GU.mjs.map → chunk-OFYBMMWT.mjs.map} +1 -1
- package/dist/chunk-PVLLRDUT.js +6944 -0
- package/dist/chunk-PVLLRDUT.js.map +1 -0
- package/dist/chunk-Q5EDCKQA.js +336 -0
- package/dist/chunk-Q5EDCKQA.js.map +1 -0
- package/dist/{chunk-SHY424RZ.mjs → chunk-SNBILYSH.mjs} +6 -6
- package/dist/{chunk-SHY424RZ.mjs.map → chunk-SNBILYSH.mjs.map} +1 -1
- package/dist/chunk-TJZDPOO7.js +34 -0
- package/dist/chunk-TJZDPOO7.js.map +1 -0
- package/dist/{chunk-7JN25DJB.js → chunk-UVHPCLP6.js} +14 -14
- package/dist/{chunk-7JN25DJB.js.map → chunk-UVHPCLP6.js.map} +1 -1
- package/dist/chunk-WGD2NBVR.mjs +6904 -0
- package/dist/chunk-WGD2NBVR.mjs.map +1 -0
- package/dist/chunk-WS3QZYBI.mjs +2701 -0
- package/dist/chunk-WS3QZYBI.mjs.map +1 -0
- package/dist/chunk-XLR6QUDR.mjs +113 -0
- package/dist/chunk-XLR6QUDR.mjs.map +1 -0
- package/dist/chunk-YMS6BPXS.js +807 -0
- package/dist/chunk-YMS6BPXS.js.map +1 -0
- package/dist/chunk-YOTQG4NP.mjs +314 -0
- package/dist/chunk-YOTQG4NP.mjs.map +1 -0
- package/dist/chunk-ZGVB35L2.mjs +25 -0
- package/dist/chunk-ZGVB35L2.mjs.map +1 -0
- package/dist/chunk-ZRAW3HXA.js +43 -0
- package/dist/chunk-ZRAW3HXA.js.map +1 -0
- package/dist/{chunk-4XXIBWCO.js → chunk-ZRWED7Q6.js} +66 -66
- package/dist/{chunk-4XXIBWCO.js.map → chunk-ZRWED7Q6.js.map} +1 -1
- package/dist/{chunk-DVENFCQY.js → chunk-ZWQJSZEY.js} +4 -5
- package/dist/chunk-ZWQJSZEY.js.map +1 -0
- package/dist/components/index.js +104 -104
- package/dist/components/index.mjs +4 -4
- package/dist/index.js +146 -148
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -11
- package/dist/index.mjs.map +1 -1
- package/dist/logger/index.js +7 -7
- package/dist/logger/index.mjs +1 -4
- package/dist/mikuFusionGame/index.js +4 -4
- package/dist/mikuFusionGame/index.mjs +3 -3
- package/dist/portfolio/index.js +10 -10
- package/dist/portfolio/index.mjs +5 -5
- package/dist/showmasterpiece/db/index.d.mts +3028 -0
- package/dist/showmasterpiece/db/index.d.ts +3028 -0
- package/dist/showmasterpiece/db/index.js +179 -0
- package/dist/showmasterpiece/db/index.js.map +1 -0
- package/dist/showmasterpiece/db/index.mjs +6 -0
- package/dist/showmasterpiece/db/index.mjs.map +1 -0
- package/dist/showmasterpiece/index.d.mts +10 -1729
- package/dist/showmasterpiece/index.d.ts +10 -1729
- package/dist/showmasterpiece/index.js +439 -9659
- package/dist/showmasterpiece/index.js.map +1 -1
- package/dist/showmasterpiece/index.mjs +12 -9633
- package/dist/showmasterpiece/index.mjs.map +1 -1
- package/dist/showmasterpiece/logic/index.d.mts +372 -0
- package/dist/showmasterpiece/logic/index.d.ts +372 -0
- package/dist/showmasterpiece/logic/index.js +91 -0
- package/dist/showmasterpiece/logic/index.js.map +1 -0
- package/dist/showmasterpiece/logic/index.mjs +6 -0
- package/dist/showmasterpiece/logic/index.mjs.map +1 -0
- package/dist/showmasterpiece/server/index.d.mts +3 -2704
- package/dist/showmasterpiece/server/index.d.ts +3 -2704
- package/dist/showmasterpiece/server/index.js +43 -43
- package/dist/showmasterpiece/server/index.mjs +2 -2
- package/dist/showmasterpiece/ui/miniapp/index.d.mts +86 -0
- package/dist/showmasterpiece/ui/miniapp/index.d.ts +86 -0
- package/dist/showmasterpiece/ui/miniapp/index.js +196 -0
- package/dist/showmasterpiece/ui/miniapp/index.js.map +1 -0
- package/dist/showmasterpiece/ui/miniapp/index.mjs +183 -0
- package/dist/showmasterpiece/ui/miniapp/index.mjs.map +1 -0
- package/dist/showmasterpiece/ui/web/index.d.mts +600 -0
- package/dist/showmasterpiece/ui/web/index.d.ts +600 -0
- package/dist/showmasterpiece/ui/web/index.js +131 -0
- package/dist/showmasterpiece/ui/web/index.js.map +1 -0
- package/dist/showmasterpiece/ui/web/index.mjs +14 -0
- package/dist/showmasterpiece/ui/web/index.mjs.map +1 -0
- package/dist/universalExport/server/index.js +2 -4
- package/dist/universalExport/server/index.js.map +1 -1
- package/dist/universalExport/server/index.mjs +1 -3
- package/dist/universalExport/server/index.mjs.map +1 -1
- package/dist/universalFile/index.js +6 -9
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +1 -5
- package/dist/universalFile/index.mjs.map +1 -1
- package/dist/universalFile/server/index.js +5852 -291
- package/dist/universalFile/server/index.js.map +1 -1
- package/dist/universalFile/server/index.mjs +5764 -8
- package/dist/universalFile/server/index.mjs.map +1 -1
- package/dist/utils/index.js +11 -11
- package/dist/utils/index.mjs +2 -2
- package/package.json +26 -1
- package/dist/AliyunOSSProvider-2FARPAQD.js +0 -15
- package/dist/AliyunOSSProvider-UMVGVBDJ.mjs +0 -9
- package/dist/LocalStorageProvider-JQF5WK5H.js +0 -15
- package/dist/LocalStorageProvider-PYOHETJV.mjs +0 -9
- package/dist/UniversalFileService-RBV6EN5J.js +0 -15
- package/dist/UniversalFileService-TNYKO6JN.mjs +0 -9
- package/dist/chunk-4NFOSCM6.js +0 -34
- package/dist/chunk-4NFOSCM6.js.map +0 -1
- package/dist/chunk-4VJQZSPU.mjs.map +0 -1
- package/dist/chunk-6AHYPPUP.js +0 -344
- package/dist/chunk-6AHYPPUP.js.map +0 -1
- package/dist/chunk-76V7EKBX.mjs +0 -796
- package/dist/chunk-76V7EKBX.mjs.map +0 -1
- package/dist/chunk-ACLOJXXE.js +0 -195
- package/dist/chunk-ACLOJXXE.js.map +0 -1
- package/dist/chunk-AEXPAH7Z.mjs +0 -32
- package/dist/chunk-AEXPAH7Z.mjs.map +0 -1
- package/dist/chunk-CFGX3EKK.js +0 -560
- package/dist/chunk-CFGX3EKK.js.map +0 -1
- package/dist/chunk-D2HXMGXS.js +0 -46
- package/dist/chunk-D2HXMGXS.js.map +0 -1
- package/dist/chunk-DVENFCQY.js.map +0 -1
- package/dist/chunk-K7WNCB4V.mjs +0 -554
- package/dist/chunk-K7WNCB4V.mjs.map +0 -1
- package/dist/chunk-L4ZYBFB2.mjs +0 -44
- package/dist/chunk-L4ZYBFB2.mjs.map +0 -1
- package/dist/chunk-M4HGHTIC.js +0 -820
- package/dist/chunk-M4HGHTIC.js.map +0 -1
- package/dist/chunk-PKKIDPXE.mjs +0 -5797
- package/dist/chunk-PKKIDPXE.mjs.map +0 -1
- package/dist/chunk-PXWDQFWV.mjs +0 -192
- package/dist/chunk-PXWDQFWV.mjs.map +0 -1
- package/dist/chunk-TSTBLX6B.js +0 -5888
- package/dist/chunk-TSTBLX6B.js.map +0 -1
- package/dist/chunk-VTGPHE4Z.mjs +0 -322
- package/dist/chunk-VTGPHE4Z.mjs.map +0 -1
- package/dist/popupConfig-BznThU1O.d.mts +0 -330
- package/dist/popupConfig-BznThU1O.d.ts +0 -330
- package/dist/showmasterpiece/migration/index.d.mts +0 -120
- package/dist/showmasterpiece/migration/index.d.ts +0 -120
- package/dist/showmasterpiece/migration/index.js +0 -595
- package/dist/showmasterpiece/migration/index.js.map +0 -1
- package/dist/showmasterpiece/migration/index.mjs +0 -589
- package/dist/showmasterpiece/migration/index.mjs.map +0 -1
- package/dist/showmasterpiece/scripts/index.d.mts +0 -28
- package/dist/showmasterpiece/scripts/index.d.ts +0 -28
- package/dist/showmasterpiece/scripts/index.js +0 -327
- package/dist/showmasterpiece/scripts/index.js.map +0 -1
- package/dist/showmasterpiece/scripts/index.mjs +0 -325
- package/dist/showmasterpiece/scripts/index.mjs.map +0 -1
|
@@ -0,0 +1,2701 @@
|
|
|
1
|
+
import { __esm, __export, __toCommonJS } from './chunk-WMJKH4XE.mjs';
|
|
2
|
+
import React, { createContext, useState, useCallback, useEffect, useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
// src/showmasterpiece/services/masterpiecesService.ts
|
|
5
|
+
var getMasterpieces, MasterpiecesService;
|
|
6
|
+
var init_masterpiecesService = __esm({
|
|
7
|
+
"src/showmasterpiece/services/masterpiecesService.ts"() {
|
|
8
|
+
getMasterpieces = async () => {
|
|
9
|
+
const response = await fetch("/api/showmasterpiece/collections");
|
|
10
|
+
if (!response.ok) {
|
|
11
|
+
throw new Error("\u83B7\u53D6\u753B\u96C6\u5931\u8D25");
|
|
12
|
+
}
|
|
13
|
+
return await response.json();
|
|
14
|
+
};
|
|
15
|
+
MasterpiecesService = class {
|
|
16
|
+
/**
|
|
17
|
+
* 获取所有画集
|
|
18
|
+
*
|
|
19
|
+
* 从后端API获取所有可用的画集数据。
|
|
20
|
+
* 返回的数据包含完整的画集信息和作品页面。
|
|
21
|
+
*
|
|
22
|
+
* @returns Promise<ArtCollection[]> 所有画集的数组
|
|
23
|
+
* @throws {Error} 当API请求失败时抛出错误
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* try {
|
|
28
|
+
* const collections = await MasterpiecesService.getAllCollections();
|
|
29
|
+
* console.log(`共加载了 ${collections.length} 个画集`);
|
|
30
|
+
* } catch (error) {
|
|
31
|
+
* console.error('加载失败:', error.message);
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
static async getAllCollections() {
|
|
36
|
+
const response = await fetch("/api/showmasterpiece/collections");
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw new Error("\u83B7\u53D6\u753B\u96C6\u5931\u8D25");
|
|
39
|
+
}
|
|
40
|
+
const payload = await response.json();
|
|
41
|
+
const collections = Array.isArray(payload) ? payload : payload?.collections ?? payload?.data ?? [];
|
|
42
|
+
if (!Array.isArray(collections)) {
|
|
43
|
+
throw new Error("\u753B\u96C6\u6570\u636E\u683C\u5F0F\u4E0D\u6B63\u786E");
|
|
44
|
+
}
|
|
45
|
+
return collections;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 根据ID获取特定画集
|
|
49
|
+
*
|
|
50
|
+
* 通过画集ID获取单个画集的详细信息。
|
|
51
|
+
* 内部实现是先获取所有画集,然后筛选出指定ID的画集。
|
|
52
|
+
*
|
|
53
|
+
* @param id - 画集的唯一标识符
|
|
54
|
+
* @returns Promise<ArtCollection | null> 找到的画集对象,如果不存在则返回null
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const collection = await MasterpiecesService.getCollectionById(1);
|
|
59
|
+
* if (collection) {
|
|
60
|
+
* console.log(`找到画集: ${collection.title}`);
|
|
61
|
+
* } else {
|
|
62
|
+
* console.log('画集不存在');
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
static async getCollectionById(id) {
|
|
67
|
+
const collections = await this.getAllCollections();
|
|
68
|
+
return collections.find((c) => c.id === id) || null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 搜索画集
|
|
72
|
+
*
|
|
73
|
+
* 根据关键词在画集的多个字段中进行搜索,包括:
|
|
74
|
+
* - 画集标题
|
|
75
|
+
* - 艺术家姓名
|
|
76
|
+
* - 画集描述
|
|
77
|
+
* - 画集分类
|
|
78
|
+
* - 画集标签
|
|
79
|
+
*
|
|
80
|
+
* 搜索是大小写不敏感的,支持部分匹配。
|
|
81
|
+
*
|
|
82
|
+
* @param query - 搜索关键词
|
|
83
|
+
* @returns Promise<ArtCollection[]> 匹配的画集数组
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // 搜索包含"山水"的画集
|
|
88
|
+
* const results = await MasterpiecesService.searchCollections('山水');
|
|
89
|
+
* console.log(`找到 ${results.length} 个相关画集`);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
static async searchCollections(query) {
|
|
93
|
+
const collections = await this.getAllCollections();
|
|
94
|
+
const searchTerm = query.toLowerCase();
|
|
95
|
+
return collections.filter(
|
|
96
|
+
(collection) => collection.title.toLowerCase().includes(searchTerm) || collection.number.toLowerCase().includes(searchTerm) || collection.description.toLowerCase().includes(searchTerm) || collection.category && collection.category.toLowerCase().includes(searchTerm) || collection.tags && collection.tags.some((tag) => tag.toLowerCase().includes(searchTerm))
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 根据分类获取画集
|
|
101
|
+
*
|
|
102
|
+
* 获取属于指定分类的所有画集。
|
|
103
|
+
* 支持特殊值 'all' 来获取所有画集。
|
|
104
|
+
*
|
|
105
|
+
* @param category - 分类名称,或 'all' 表示所有分类
|
|
106
|
+
* @returns Promise<ArtCollection[]> 该分类下的画集数组
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // 获取油画分类的画集
|
|
111
|
+
* const paintings = await MasterpiecesService.getCollectionsByCategory('油画');
|
|
112
|
+
*
|
|
113
|
+
* // 获取所有画集
|
|
114
|
+
* const allCollections = await MasterpiecesService.getCollectionsByCategory('all');
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
static async getCollectionsByCategory(category) {
|
|
118
|
+
const collections = await this.getAllCollections();
|
|
119
|
+
if (category === "all") {
|
|
120
|
+
return collections;
|
|
121
|
+
}
|
|
122
|
+
return collections.filter((collection) => collection.category === category);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 获取推荐画集
|
|
126
|
+
*
|
|
127
|
+
* 基于简单的推荐算法获取推荐的画集。
|
|
128
|
+
* 当前算法:优先选择已发布的画集,按作品数量降序排列。
|
|
129
|
+
*
|
|
130
|
+
* @param limit - 返回的推荐画集数量,默认为3个
|
|
131
|
+
* @returns Promise<ArtCollection[]> 推荐的画集数组
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* // 获取3个推荐画集
|
|
136
|
+
* const recommended = await MasterpiecesService.getRecommendedCollections();
|
|
137
|
+
*
|
|
138
|
+
* // 获取5个推荐画集
|
|
139
|
+
* const moreRecommended = await MasterpiecesService.getRecommendedCollections(5);
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
static async getRecommendedCollections(limit = 3) {
|
|
143
|
+
const collections = await this.getAllCollections();
|
|
144
|
+
return collections.filter((collection) => collection.isPublished !== false).sort((a, b) => b.pages.length - a.pages.length).slice(0, limit);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 获取所有可用分类
|
|
148
|
+
*
|
|
149
|
+
* 从后端API获取所有已定义的画集分类列表。
|
|
150
|
+
* 用于构建分类筛选器和下拉菜单。
|
|
151
|
+
*
|
|
152
|
+
* @returns Promise<Array<{ name: string; description?: string | null }>> 分类名称数组
|
|
153
|
+
* @throws {Error} 当API请求失败时抛出错误
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const categories = await MasterpiecesService.getCategories();
|
|
158
|
+
* console.log('可用分类:', categories);
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
static async getCategories() {
|
|
162
|
+
const response = await fetch("/api/showmasterpiece/categories");
|
|
163
|
+
if (!response.ok) {
|
|
164
|
+
throw new Error("\u83B7\u53D6\u5206\u7C7B\u5931\u8D25");
|
|
165
|
+
}
|
|
166
|
+
const payload = await response.json();
|
|
167
|
+
return Array.isArray(payload) ? payload : payload?.data ?? [];
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 获取所有可用标签
|
|
171
|
+
*
|
|
172
|
+
* 从后端API获取所有已定义的画集标签列表。
|
|
173
|
+
* 用于构建标签筛选器和标签云。
|
|
174
|
+
*
|
|
175
|
+
* @returns Promise<string[]> 标签名称数组
|
|
176
|
+
* @throws {Error} 当API请求失败时抛出错误
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const tags = await MasterpiecesService.getTags();
|
|
181
|
+
* console.log('可用标签:', tags);
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
static async getTags() {
|
|
185
|
+
const response = await fetch("/api/showmasterpiece/tags");
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
throw new Error("\u83B7\u53D6\u6807\u7B7E\u5931\u8D25");
|
|
188
|
+
}
|
|
189
|
+
return await response.json();
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
var collectionsCache, collectionsCacheTime, COLLECTIONS_CACHE_DURATION, useMasterpieces;
|
|
195
|
+
var init_useMasterpieces = __esm({
|
|
196
|
+
"src/showmasterpiece/logic/hooks/useMasterpieces.ts"() {
|
|
197
|
+
init_masterpiecesService();
|
|
198
|
+
collectionsCache = null;
|
|
199
|
+
collectionsCacheTime = 0;
|
|
200
|
+
COLLECTIONS_CACHE_DURATION = 3 * 60 * 1e3;
|
|
201
|
+
useMasterpieces = () => {
|
|
202
|
+
const [collections, setCollections] = useState([]);
|
|
203
|
+
const [selectedCollection, setSelectedCollection] = useState(null);
|
|
204
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
205
|
+
const [loading, setLoading] = useState(false);
|
|
206
|
+
const [error, setError] = useState(null);
|
|
207
|
+
const loadCollections = useCallback(async (forceRefresh = false) => {
|
|
208
|
+
try {
|
|
209
|
+
const now = Date.now();
|
|
210
|
+
if (!forceRefresh && collectionsCache && now - collectionsCacheTime < COLLECTIONS_CACHE_DURATION) {
|
|
211
|
+
setCollections(collectionsCache);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
setLoading(true);
|
|
215
|
+
setError(null);
|
|
216
|
+
const data = await MasterpiecesService.getAllCollections();
|
|
217
|
+
collectionsCache = data;
|
|
218
|
+
collectionsCacheTime = now;
|
|
219
|
+
setCollections(data);
|
|
220
|
+
} catch (err) {
|
|
221
|
+
setError("\u52A0\u8F7D\u753B\u96C6\u5931\u8D25");
|
|
222
|
+
console.error("Error loading collections:", err);
|
|
223
|
+
} finally {
|
|
224
|
+
setLoading(false);
|
|
225
|
+
}
|
|
226
|
+
}, []);
|
|
227
|
+
const selectCollection = useCallback((collection) => {
|
|
228
|
+
setSelectedCollection(collection);
|
|
229
|
+
setCurrentPage(0);
|
|
230
|
+
}, []);
|
|
231
|
+
const nextPage = useCallback(() => {
|
|
232
|
+
if (selectedCollection && currentPage < selectedCollection.pages.length - 1) {
|
|
233
|
+
setCurrentPage((prev) => prev + 1);
|
|
234
|
+
}
|
|
235
|
+
}, [selectedCollection, currentPage]);
|
|
236
|
+
const prevPage = useCallback(() => {
|
|
237
|
+
if (currentPage > 0) {
|
|
238
|
+
setCurrentPage((prev) => prev - 1);
|
|
239
|
+
}
|
|
240
|
+
}, [currentPage]);
|
|
241
|
+
const goToPage = useCallback((pageIndex) => {
|
|
242
|
+
if (selectedCollection && pageIndex >= 0 && pageIndex < selectedCollection.pages.length) {
|
|
243
|
+
setCurrentPage(pageIndex);
|
|
244
|
+
}
|
|
245
|
+
}, [selectedCollection]);
|
|
246
|
+
const backToGallery = useCallback(() => {
|
|
247
|
+
setSelectedCollection(null);
|
|
248
|
+
setCurrentPage(0);
|
|
249
|
+
}, []);
|
|
250
|
+
const searchCollections = useCallback(async (query) => {
|
|
251
|
+
try {
|
|
252
|
+
setLoading(true);
|
|
253
|
+
setError(null);
|
|
254
|
+
const data = await MasterpiecesService.searchCollections(query);
|
|
255
|
+
setCollections(data);
|
|
256
|
+
} catch (err) {
|
|
257
|
+
setError("\u641C\u7D22\u5931\u8D25");
|
|
258
|
+
console.error("Error searching collections:", err);
|
|
259
|
+
} finally {
|
|
260
|
+
setLoading(false);
|
|
261
|
+
}
|
|
262
|
+
}, []);
|
|
263
|
+
const getCurrentArtwork = useCallback(() => {
|
|
264
|
+
if (!selectedCollection || !selectedCollection.pages[currentPage]) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
return selectedCollection.pages[currentPage];
|
|
268
|
+
}, [selectedCollection, currentPage]);
|
|
269
|
+
const canGoNext = selectedCollection ? currentPage < selectedCollection.pages.length - 1 : false;
|
|
270
|
+
const canGoPrev = currentPage > 0;
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
loadCollections();
|
|
273
|
+
}, [loadCollections]);
|
|
274
|
+
return {
|
|
275
|
+
// === 状态数据 ===
|
|
276
|
+
/** 所有画集数据 */
|
|
277
|
+
collections,
|
|
278
|
+
/** 当前选中的画集 */
|
|
279
|
+
selectedCollection,
|
|
280
|
+
/** 当前页面索引 */
|
|
281
|
+
currentPage,
|
|
282
|
+
/** 加载状态 */
|
|
283
|
+
loading,
|
|
284
|
+
/** 错误信息 */
|
|
285
|
+
error,
|
|
286
|
+
// === 计算属性 ===
|
|
287
|
+
/** 获取当前作品的方法 */
|
|
288
|
+
getCurrentArtwork,
|
|
289
|
+
/** 是否可以下一页 */
|
|
290
|
+
canGoNext,
|
|
291
|
+
/** 是否可以上一页 */
|
|
292
|
+
canGoPrev,
|
|
293
|
+
// === 操作方法 ===
|
|
294
|
+
/** 选择画集 */
|
|
295
|
+
selectCollection,
|
|
296
|
+
/** 下一页 */
|
|
297
|
+
nextPage,
|
|
298
|
+
/** 上一页 */
|
|
299
|
+
prevPage,
|
|
300
|
+
/** 跳转到指定页 */
|
|
301
|
+
goToPage,
|
|
302
|
+
/** 返回画集列表 */
|
|
303
|
+
backToGallery,
|
|
304
|
+
/** 搜索画集 */
|
|
305
|
+
searchCollections,
|
|
306
|
+
/** 加载画集数据 */
|
|
307
|
+
loadCollections
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// src/showmasterpiece/services/masterpiecesConfigService.ts
|
|
314
|
+
async function getCollectionsOverview() {
|
|
315
|
+
const response = await fetch("/api/showmasterpiece/collections?overview=true");
|
|
316
|
+
if (!response.ok) {
|
|
317
|
+
throw new Error("\u83B7\u53D6\u753B\u96C6\u6982\u89C8\u5931\u8D25");
|
|
318
|
+
}
|
|
319
|
+
return response.json();
|
|
320
|
+
}
|
|
321
|
+
var configCache, configCacheTime, CONFIG_CACHE_DURATION, getConfig, updateConfig, resetConfig, getAllCollections, createCollection, updateCollection, deleteCollection, updateCollectionOrder, moveCollection, moveCollectionUp, moveCollectionDown, addArtworkToCollection, updateArtwork, deleteArtwork, getArtworksByCollection, updateArtworkOrder, moveArtwork, moveArtworkUp, moveArtworkDown, getCategories, createCategory, getTags;
|
|
322
|
+
var init_masterpiecesConfigService = __esm({
|
|
323
|
+
"src/showmasterpiece/services/masterpiecesConfigService.ts"() {
|
|
324
|
+
configCache = null;
|
|
325
|
+
configCacheTime = 0;
|
|
326
|
+
CONFIG_CACHE_DURATION = 5 * 60 * 1e3;
|
|
327
|
+
getConfig = async () => {
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
if (configCache && now - configCacheTime < CONFIG_CACHE_DURATION) {
|
|
330
|
+
return configCache;
|
|
331
|
+
}
|
|
332
|
+
const response = await fetch("/api/showmasterpiece/config");
|
|
333
|
+
if (!response.ok) {
|
|
334
|
+
throw new Error("\u83B7\u53D6\u914D\u7F6E\u5931\u8D25");
|
|
335
|
+
}
|
|
336
|
+
const config = await response.json();
|
|
337
|
+
configCache = config;
|
|
338
|
+
configCacheTime = now;
|
|
339
|
+
return config;
|
|
340
|
+
};
|
|
341
|
+
updateConfig = async (configData) => {
|
|
342
|
+
const response = await fetch("/api/showmasterpiece/config", {
|
|
343
|
+
method: "PUT",
|
|
344
|
+
headers: {
|
|
345
|
+
"Content-Type": "application/json"
|
|
346
|
+
},
|
|
347
|
+
body: JSON.stringify(configData)
|
|
348
|
+
});
|
|
349
|
+
if (!response.ok) {
|
|
350
|
+
throw new Error("\u66F4\u65B0\u914D\u7F6E\u5931\u8D25");
|
|
351
|
+
}
|
|
352
|
+
const updatedConfig = await response.json();
|
|
353
|
+
configCache = updatedConfig;
|
|
354
|
+
configCacheTime = Date.now();
|
|
355
|
+
return updatedConfig;
|
|
356
|
+
};
|
|
357
|
+
resetConfig = async () => {
|
|
358
|
+
const response = await fetch("/api/showmasterpiece/config", {
|
|
359
|
+
method: "DELETE"
|
|
360
|
+
});
|
|
361
|
+
if (!response.ok) {
|
|
362
|
+
throw new Error("\u91CD\u7F6E\u914D\u7F6E\u5931\u8D25");
|
|
363
|
+
}
|
|
364
|
+
const resetConfigData = await response.json();
|
|
365
|
+
configCache = resetConfigData;
|
|
366
|
+
configCacheTime = Date.now();
|
|
367
|
+
return resetConfigData;
|
|
368
|
+
};
|
|
369
|
+
getAllCollections = async () => {
|
|
370
|
+
console.log("\u{1F4E1} [\u670D\u52A1] \u5F00\u59CB\u83B7\u53D6\u6240\u6709\u753B\u96C6...");
|
|
371
|
+
try {
|
|
372
|
+
const timestamp = (/* @__PURE__ */ new Date()).getTime();
|
|
373
|
+
const response = await fetch(`/api/showmasterpiece/collections?_t=${timestamp}`, {
|
|
374
|
+
method: "GET",
|
|
375
|
+
headers: {
|
|
376
|
+
"Cache-Control": "no-cache",
|
|
377
|
+
"Pragma": "no-cache"
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
console.log("\u{1F4E1} [\u670D\u52A1] \u753B\u96C6\u8BF7\u6C42\u54CD\u5E94\u72B6\u6001:", response.status);
|
|
381
|
+
if (!response.ok) {
|
|
382
|
+
const errorText = await response.text();
|
|
383
|
+
console.error("\u274C [\u670D\u52A1] \u83B7\u53D6\u753B\u96C6\u5931\u8D25:", {
|
|
384
|
+
status: response.status,
|
|
385
|
+
statusText: response.statusText,
|
|
386
|
+
error: errorText
|
|
387
|
+
});
|
|
388
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
389
|
+
}
|
|
390
|
+
const payload = await response.json();
|
|
391
|
+
const collections = Array.isArray(payload) ? payload : payload?.collections ?? payload?.data ?? [];
|
|
392
|
+
if (!Array.isArray(collections)) {
|
|
393
|
+
throw new Error("\u753B\u96C6\u6570\u636E\u683C\u5F0F\u4E0D\u6B63\u786E");
|
|
394
|
+
}
|
|
395
|
+
console.log("\u2705 [\u670D\u52A1] \u753B\u96C6\u6570\u636E\u83B7\u53D6\u6210\u529F:", {
|
|
396
|
+
count: collections.length,
|
|
397
|
+
titles: collections.map((c) => c.title)
|
|
398
|
+
});
|
|
399
|
+
return collections;
|
|
400
|
+
} catch (error) {
|
|
401
|
+
console.error("\u274C [\u670D\u52A1] \u83B7\u53D6\u753B\u96C6\u6570\u636E\u5931\u8D25:", error);
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
createCollection = async (collectionData) => {
|
|
406
|
+
const requestBody = collectionData;
|
|
407
|
+
const response = await fetch("/api/showmasterpiece/collections", {
|
|
408
|
+
method: "POST",
|
|
409
|
+
headers: {
|
|
410
|
+
"Content-Type": "application/json"
|
|
411
|
+
},
|
|
412
|
+
body: JSON.stringify(requestBody)
|
|
413
|
+
});
|
|
414
|
+
if (!response.ok) {
|
|
415
|
+
if (response.status === 413) {
|
|
416
|
+
throw new Error("\u56FE\u7247\u6587\u4EF6\u592A\u5927\uFF0C\u8BF7\u9009\u62E9\u66F4\u5C0F\u7684\u56FE\u7247\u6216\u7B49\u5F85\u56FE\u7247\u538B\u7F29\u5B8C\u6210\u540E\u91CD\u8BD5");
|
|
417
|
+
}
|
|
418
|
+
throw new Error("\u521B\u5EFA\u753B\u96C6\u5931\u8D25");
|
|
419
|
+
}
|
|
420
|
+
return await response.json();
|
|
421
|
+
};
|
|
422
|
+
updateCollection = async (id, collectionData) => {
|
|
423
|
+
const response = await fetch(`/api/showmasterpiece/collections/${id}`, {
|
|
424
|
+
method: "PUT",
|
|
425
|
+
headers: {
|
|
426
|
+
"Content-Type": "application/json"
|
|
427
|
+
},
|
|
428
|
+
body: JSON.stringify(collectionData)
|
|
429
|
+
});
|
|
430
|
+
if (!response.ok) {
|
|
431
|
+
if (response.status === 413) {
|
|
432
|
+
throw new Error("\u56FE\u7247\u6587\u4EF6\u592A\u5927\uFF0C\u8BF7\u9009\u62E9\u66F4\u5C0F\u7684\u56FE\u7247\u6216\u7B49\u5F85\u56FE\u7247\u538B\u7F29\u5B8C\u6210\u540E\u91CD\u8BD5");
|
|
433
|
+
}
|
|
434
|
+
throw new Error("\u66F4\u65B0\u753B\u96C6\u5931\u8D25");
|
|
435
|
+
}
|
|
436
|
+
return await response.json();
|
|
437
|
+
};
|
|
438
|
+
deleteCollection = async (id) => {
|
|
439
|
+
const url = new URL(`/api/showmasterpiece/collections/${id}`, window.location.origin);
|
|
440
|
+
const response = await fetch(url.toString(), {
|
|
441
|
+
method: "DELETE"
|
|
442
|
+
});
|
|
443
|
+
if (!response.ok) {
|
|
444
|
+
const errorData = await response.json().catch(() => ({}));
|
|
445
|
+
throw new Error(errorData.error || "\u5220\u9664\u753B\u96C6\u5931\u8D25");
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
updateCollectionOrder = async (collectionOrders) => {
|
|
449
|
+
const response = await fetch("/api/showmasterpiece/collections?action=reorder", {
|
|
450
|
+
method: "PATCH",
|
|
451
|
+
headers: {
|
|
452
|
+
"Content-Type": "application/json"
|
|
453
|
+
},
|
|
454
|
+
body: JSON.stringify({ collectionOrders })
|
|
455
|
+
});
|
|
456
|
+
if (!response.ok) {
|
|
457
|
+
const error = await response.json();
|
|
458
|
+
throw new Error(error.error || "\u66F4\u65B0\u753B\u96C6\u987A\u5E8F\u5931\u8D25");
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
moveCollection = async (collectionId, targetOrder) => {
|
|
462
|
+
const response = await fetch("/api/showmasterpiece/collections?action=move", {
|
|
463
|
+
method: "PATCH",
|
|
464
|
+
headers: {
|
|
465
|
+
"Content-Type": "application/json"
|
|
466
|
+
},
|
|
467
|
+
body: JSON.stringify({ collectionId, targetOrder })
|
|
468
|
+
});
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
const error = await response.json();
|
|
471
|
+
throw new Error(error.error || "\u79FB\u52A8\u753B\u96C6\u5931\u8D25");
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
moveCollectionUp = async (collectionId) => {
|
|
475
|
+
const response = await fetch("/api/showmasterpiece/collections?action=up", {
|
|
476
|
+
method: "PATCH",
|
|
477
|
+
headers: {
|
|
478
|
+
"Content-Type": "application/json"
|
|
479
|
+
},
|
|
480
|
+
body: JSON.stringify({ collectionId })
|
|
481
|
+
});
|
|
482
|
+
if (!response.ok) {
|
|
483
|
+
const error = await response.json();
|
|
484
|
+
throw new Error(error.error || "\u4E0A\u79FB\u753B\u96C6\u5931\u8D25");
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
moveCollectionDown = async (collectionId) => {
|
|
488
|
+
const response = await fetch("/api/showmasterpiece/collections?action=down", {
|
|
489
|
+
method: "PATCH",
|
|
490
|
+
headers: {
|
|
491
|
+
"Content-Type": "application/json"
|
|
492
|
+
},
|
|
493
|
+
body: JSON.stringify({ collectionId })
|
|
494
|
+
});
|
|
495
|
+
if (!response.ok) {
|
|
496
|
+
const error = await response.json();
|
|
497
|
+
throw new Error(error.error || "\u4E0B\u79FB\u753B\u96C6\u5931\u8D25");
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
addArtworkToCollection = async (collectionId, artworkData) => {
|
|
501
|
+
console.log("\u{1F310} [\u670D\u52A1] \u5F00\u59CB\u53D1\u9001\u4F5C\u54C1\u521B\u5EFA\u8BF7\u6C42:", {
|
|
502
|
+
collectionId,
|
|
503
|
+
title: artworkData.title,
|
|
504
|
+
number: artworkData.number,
|
|
505
|
+
imageSize: artworkData.image ? `${artworkData.image.length} chars` : "null"
|
|
506
|
+
});
|
|
507
|
+
const requestBody = JSON.stringify(artworkData);
|
|
508
|
+
console.log("\u{1F4E6} [\u670D\u52A1] \u8BF7\u6C42\u4F53\u5927\u5C0F:", `${requestBody.length} chars (${(requestBody.length / 1024).toFixed(1)} KB)`);
|
|
509
|
+
try {
|
|
510
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks`, {
|
|
511
|
+
method: "POST",
|
|
512
|
+
headers: {
|
|
513
|
+
"Content-Type": "application/json"
|
|
514
|
+
},
|
|
515
|
+
body: requestBody
|
|
516
|
+
});
|
|
517
|
+
console.log("\u{1F4E1} [\u670D\u52A1] \u6536\u5230HTTP\u54CD\u5E94:", {
|
|
518
|
+
status: response.status,
|
|
519
|
+
statusText: response.statusText,
|
|
520
|
+
contentLength: response.headers.get("content-length"),
|
|
521
|
+
contentType: response.headers.get("content-type")
|
|
522
|
+
});
|
|
523
|
+
if (!response.ok) {
|
|
524
|
+
const errorText = await response.text();
|
|
525
|
+
console.error("\u274C [\u670D\u52A1] HTTP\u8BF7\u6C42\u5931\u8D25:", {
|
|
526
|
+
status: response.status,
|
|
527
|
+
statusText: response.statusText,
|
|
528
|
+
errorText: errorText.substring(0, 200)
|
|
529
|
+
});
|
|
530
|
+
if (response.status === 413) {
|
|
531
|
+
throw new Error("\u56FE\u7247\u6587\u4EF6\u592A\u5927\uFF0C\u8BF7\u9009\u62E9\u66F4\u5C0F\u7684\u56FE\u7247\u6216\u7B49\u5F85\u56FE\u7247\u538B\u7F29\u5B8C\u6210\u540E\u91CD\u8BD5");
|
|
532
|
+
}
|
|
533
|
+
throw new Error(`\u6DFB\u52A0\u4F5C\u54C1\u5931\u8D25: ${response.status} ${response.statusText}`);
|
|
534
|
+
}
|
|
535
|
+
const result = await response.json();
|
|
536
|
+
console.log("\u2705 [\u670D\u52A1] \u4F5C\u54C1\u521B\u5EFA\u6210\u529F:", {
|
|
537
|
+
id: result.id,
|
|
538
|
+
title: result.title,
|
|
539
|
+
number: result.number
|
|
540
|
+
});
|
|
541
|
+
return result;
|
|
542
|
+
} catch (error) {
|
|
543
|
+
console.error("\u274C [\u670D\u52A1] \u8BF7\u6C42\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:", error);
|
|
544
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
545
|
+
throw new Error("\u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u540E\u91CD\u8BD5");
|
|
546
|
+
}
|
|
547
|
+
throw error;
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
updateArtwork = async (collectionId, artworkId, artworkData) => {
|
|
551
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks/${artworkId}`, {
|
|
552
|
+
method: "PUT",
|
|
553
|
+
headers: {
|
|
554
|
+
"Content-Type": "application/json"
|
|
555
|
+
},
|
|
556
|
+
body: JSON.stringify(artworkData)
|
|
557
|
+
});
|
|
558
|
+
if (!response.ok) {
|
|
559
|
+
if (response.status === 413) {
|
|
560
|
+
throw new Error("\u56FE\u7247\u6587\u4EF6\u592A\u5927\uFF0C\u8BF7\u9009\u62E9\u66F4\u5C0F\u7684\u56FE\u7247\u6216\u7B49\u5F85\u56FE\u7247\u538B\u7F29\u5B8C\u6210\u540E\u91CD\u8BD5");
|
|
561
|
+
}
|
|
562
|
+
throw new Error("\u66F4\u65B0\u4F5C\u54C1\u5931\u8D25");
|
|
563
|
+
}
|
|
564
|
+
return await response.json();
|
|
565
|
+
};
|
|
566
|
+
deleteArtwork = async (collectionId, artworkId) => {
|
|
567
|
+
const url = new URL(`/api/showmasterpiece/collections/${collectionId}/artworks/${artworkId}`, window.location.origin);
|
|
568
|
+
const response = await fetch(url.toString(), {
|
|
569
|
+
method: "DELETE"
|
|
570
|
+
});
|
|
571
|
+
if (!response.ok) {
|
|
572
|
+
const errorData = await response.json().catch(() => ({}));
|
|
573
|
+
throw new Error(errorData.error || "\u5220\u9664\u4F5C\u54C1\u5931\u8D25");
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
getArtworksByCollection = async (collectionId) => {
|
|
577
|
+
const timestamp = (/* @__PURE__ */ new Date()).getTime();
|
|
578
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks?_t=${timestamp}`, {
|
|
579
|
+
headers: {
|
|
580
|
+
"Cache-Control": "no-cache",
|
|
581
|
+
"Pragma": "no-cache"
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
if (!response.ok) {
|
|
585
|
+
throw new Error("\u83B7\u53D6\u4F5C\u54C1\u5217\u8868\u5931\u8D25");
|
|
586
|
+
}
|
|
587
|
+
return await response.json();
|
|
588
|
+
};
|
|
589
|
+
updateArtworkOrder = async (collectionId, artworkOrders) => {
|
|
590
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks?action=reorder`, {
|
|
591
|
+
method: "PATCH",
|
|
592
|
+
headers: {
|
|
593
|
+
"Content-Type": "application/json"
|
|
594
|
+
},
|
|
595
|
+
body: JSON.stringify({ artworkOrders })
|
|
596
|
+
});
|
|
597
|
+
if (!response.ok) {
|
|
598
|
+
const error = await response.json();
|
|
599
|
+
throw new Error(error.error || "\u66F4\u65B0\u4F5C\u54C1\u987A\u5E8F\u5931\u8D25");
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
moveArtwork = async (collectionId, artworkId, targetOrder) => {
|
|
603
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks?action=move`, {
|
|
604
|
+
method: "PATCH",
|
|
605
|
+
headers: {
|
|
606
|
+
"Content-Type": "application/json"
|
|
607
|
+
},
|
|
608
|
+
body: JSON.stringify({ artworkId, targetOrder })
|
|
609
|
+
});
|
|
610
|
+
if (!response.ok) {
|
|
611
|
+
const error = await response.json();
|
|
612
|
+
throw new Error(error.error || "\u79FB\u52A8\u4F5C\u54C1\u5931\u8D25");
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
moveArtworkUp = async (collectionId, artworkId) => {
|
|
616
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks?action=up`, {
|
|
617
|
+
method: "PATCH",
|
|
618
|
+
headers: {
|
|
619
|
+
"Content-Type": "application/json"
|
|
620
|
+
},
|
|
621
|
+
body: JSON.stringify({ artworkId })
|
|
622
|
+
});
|
|
623
|
+
if (!response.ok) {
|
|
624
|
+
const error = await response.json();
|
|
625
|
+
throw new Error(error.error || "\u4E0A\u79FB\u4F5C\u54C1\u5931\u8D25");
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
moveArtworkDown = async (collectionId, artworkId) => {
|
|
629
|
+
const response = await fetch(`/api/showmasterpiece/collections/${collectionId}/artworks?action=down`, {
|
|
630
|
+
method: "PATCH",
|
|
631
|
+
headers: {
|
|
632
|
+
"Content-Type": "application/json"
|
|
633
|
+
},
|
|
634
|
+
body: JSON.stringify({ artworkId })
|
|
635
|
+
});
|
|
636
|
+
if (!response.ok) {
|
|
637
|
+
const error = await response.json();
|
|
638
|
+
throw new Error(error.error || "\u4E0B\u79FB\u4F5C\u54C1\u5931\u8D25");
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
getCategories = async () => {
|
|
642
|
+
const response = await fetch("/api/showmasterpiece/categories");
|
|
643
|
+
if (!response.ok) {
|
|
644
|
+
throw new Error("\u83B7\u53D6\u5206\u7C7B\u5931\u8D25");
|
|
645
|
+
}
|
|
646
|
+
const payload = await response.json();
|
|
647
|
+
const categories = Array.isArray(payload) ? payload : payload?.data ?? [];
|
|
648
|
+
if (!Array.isArray(categories)) {
|
|
649
|
+
throw new Error("\u5206\u7C7B\u6570\u636E\u683C\u5F0F\u4E0D\u6B63\u786E");
|
|
650
|
+
}
|
|
651
|
+
return categories;
|
|
652
|
+
};
|
|
653
|
+
createCategory = async (name, description) => {
|
|
654
|
+
const response = await fetch("/api/showmasterpiece/categories", {
|
|
655
|
+
method: "POST",
|
|
656
|
+
headers: {
|
|
657
|
+
"Content-Type": "application/json"
|
|
658
|
+
},
|
|
659
|
+
body: JSON.stringify({ name, description })
|
|
660
|
+
});
|
|
661
|
+
if (!response.ok) {
|
|
662
|
+
const error = await response.json().catch(() => ({}));
|
|
663
|
+
throw new Error(error.error || "\u521B\u5EFA\u5206\u7C7B\u5931\u8D25");
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
getTags = async () => {
|
|
667
|
+
const response = await fetch("/api/showmasterpiece/tags");
|
|
668
|
+
if (!response.ok) {
|
|
669
|
+
throw new Error("\u83B7\u53D6\u6807\u7B7E\u5931\u8D25");
|
|
670
|
+
}
|
|
671
|
+
return await response.json();
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
var useMasterpiecesConfig;
|
|
676
|
+
var init_useMasterpiecesConfig = __esm({
|
|
677
|
+
"src/showmasterpiece/logic/hooks/useMasterpiecesConfig.ts"() {
|
|
678
|
+
init_masterpiecesConfigService();
|
|
679
|
+
useMasterpiecesConfig = () => {
|
|
680
|
+
const [config, setConfig] = useState(null);
|
|
681
|
+
const [collections, setCollections] = useState([]);
|
|
682
|
+
const [categories, setCategories] = useState([]);
|
|
683
|
+
const [tags, setTags] = useState([]);
|
|
684
|
+
const [loading, setLoading] = useState(true);
|
|
685
|
+
const [error, setError] = useState(null);
|
|
686
|
+
const [refreshCounter, setRefreshCounter] = useState(0);
|
|
687
|
+
useEffect(() => {
|
|
688
|
+
loadData();
|
|
689
|
+
}, []);
|
|
690
|
+
const loadData = async () => {
|
|
691
|
+
console.log("\u{1F504} [Hook] \u5F00\u59CB\u52A0\u8F7D\u6570\u636E...");
|
|
692
|
+
try {
|
|
693
|
+
setLoading(true);
|
|
694
|
+
setError(null);
|
|
695
|
+
console.log("\u{1F4E1} [Hook] \u5E76\u884C\u8BF7\u6C42\u6240\u6709\u6570\u636E...");
|
|
696
|
+
const timestamp = Date.now();
|
|
697
|
+
const [configData, collectionsResponse, categoriesData, tagsData] = await Promise.all([
|
|
698
|
+
getConfig(),
|
|
699
|
+
fetch(`/api/showmasterpiece/collections?_t=${timestamp}&nocache=true&includeImages=true`, {
|
|
700
|
+
headers: {
|
|
701
|
+
"Cache-Control": "no-cache",
|
|
702
|
+
"Pragma": "no-cache"
|
|
703
|
+
}
|
|
704
|
+
}).then((r) => r.json()),
|
|
705
|
+
getCategories(),
|
|
706
|
+
getTags()
|
|
707
|
+
]);
|
|
708
|
+
const collectionsData = collectionsResponse.data || [];
|
|
709
|
+
console.log("\u2705 [Hook] \u6570\u636E\u52A0\u8F7D\u5B8C\u6210:", {
|
|
710
|
+
\u914D\u7F6E: configData ? "\u5DF2\u52A0\u8F7D" : "\u672A\u52A0\u8F7D",
|
|
711
|
+
\u753B\u96C6\u6570\u91CF: collectionsData.length,
|
|
712
|
+
\u5206\u7C7B\u6570\u91CF: categoriesData.length,
|
|
713
|
+
\u6807\u7B7E\u6570\u91CF: tagsData.length
|
|
714
|
+
});
|
|
715
|
+
if (collectionsData.length > 0) {
|
|
716
|
+
console.log("\u{1F4DA} [Hook] \u753B\u96C6\u8BE6\u60C5:");
|
|
717
|
+
collectionsData.forEach((collection, index) => {
|
|
718
|
+
console.log(` ${index + 1}. ${collection.title} - \u4F5C\u54C1\u6570\u91CF: ${collection.pages.length}`);
|
|
719
|
+
if (collection.pages.length > 0) {
|
|
720
|
+
collection.pages.forEach((page, pageIndex) => {
|
|
721
|
+
console.log(` ${pageIndex + 1}. ${page.title} (ID: ${page.id})`);
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
setConfig(configData);
|
|
727
|
+
setCollections(collectionsData);
|
|
728
|
+
setCategories(categoriesData);
|
|
729
|
+
setTags(tagsData);
|
|
730
|
+
console.log("\u{1F4BE} [Hook] \u72B6\u6001\u66F4\u65B0\u5B8C\u6210");
|
|
731
|
+
return {
|
|
732
|
+
config: configData,
|
|
733
|
+
collections: collectionsData,
|
|
734
|
+
// 这里已经是提取后的数组数据
|
|
735
|
+
categories: categoriesData,
|
|
736
|
+
tags: tagsData
|
|
737
|
+
};
|
|
738
|
+
} catch (err) {
|
|
739
|
+
console.error("\u274C [Hook] \u52A0\u8F7D\u6570\u636E\u5931\u8D25:", err);
|
|
740
|
+
console.error("\u9519\u8BEF\u8BE6\u60C5:", {
|
|
741
|
+
message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
|
|
742
|
+
stack: err instanceof Error ? err.stack : void 0
|
|
743
|
+
});
|
|
744
|
+
setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
|
|
745
|
+
throw err;
|
|
746
|
+
} finally {
|
|
747
|
+
setLoading(false);
|
|
748
|
+
console.log("\u{1F3C1} [Hook] \u6570\u636E\u52A0\u8F7D\u6D41\u7A0B\u7ED3\u675F");
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
const handleApiError = (error2, operation) => {
|
|
752
|
+
if (error2 instanceof Error) {
|
|
753
|
+
if (error2.message.includes("413") || error2.message.includes("\u592A\u5927")) {
|
|
754
|
+
throw new Error("\u56FE\u7247\u6587\u4EF6\u8FC7\u5927\uFF0C\u8BF7\u4F7F\u7528\u538B\u7F29\u540E\u7684\u56FE\u7247");
|
|
755
|
+
}
|
|
756
|
+
if (error2.message.includes("401")) {
|
|
757
|
+
throw new Error("\u6CA1\u6709\u6743\u9650\u6267\u884C\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u5148\u767B\u5F55");
|
|
758
|
+
}
|
|
759
|
+
if (error2.message.includes("404") || error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728")) {
|
|
760
|
+
throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
|
|
761
|
+
}
|
|
762
|
+
if (error2.message.includes("409")) {
|
|
763
|
+
if (error2.message.includes("\u753B\u96C6\u4E0D\u5B58\u5728") || error2.message.includes("\u5DF2\u88AB\u5220\u9664")) {
|
|
764
|
+
throw new Error("\u753B\u96C6\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
|
|
765
|
+
}
|
|
766
|
+
throw new Error(error2.message);
|
|
767
|
+
}
|
|
768
|
+
throw new Error(`${operation}\u5931\u8D25\uFF1A${error2.message}`);
|
|
769
|
+
}
|
|
770
|
+
throw new Error(`${operation}\u5931\u8D25\uFF1A\u672A\u77E5\u9519\u8BEF`);
|
|
771
|
+
};
|
|
772
|
+
const handleUpdateConfig = async (configData) => {
|
|
773
|
+
try {
|
|
774
|
+
const updatedConfig = await updateConfig(configData);
|
|
775
|
+
setConfig(updatedConfig);
|
|
776
|
+
} catch (err) {
|
|
777
|
+
handleApiError(err, "\u66F4\u65B0\u914D\u7F6E");
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
const handleResetConfig = async () => {
|
|
781
|
+
try {
|
|
782
|
+
const resetConfigData = await resetConfig();
|
|
783
|
+
setConfig(resetConfigData);
|
|
784
|
+
} catch (err) {
|
|
785
|
+
handleApiError(err, "\u91CD\u7F6E\u914D\u7F6E");
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
const handleCreateCollection = async (collectionData) => {
|
|
789
|
+
try {
|
|
790
|
+
const newCollection = await createCollection(collectionData);
|
|
791
|
+
await loadData();
|
|
792
|
+
} catch (err) {
|
|
793
|
+
handleApiError(err, "\u521B\u5EFA\u753B\u96C6");
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
const handleUpdateCollection = async (id, collectionData) => {
|
|
797
|
+
try {
|
|
798
|
+
const updatedCollection = await updateCollection(id, collectionData);
|
|
799
|
+
await loadData();
|
|
800
|
+
} catch (err) {
|
|
801
|
+
handleApiError(err, "\u66F4\u65B0\u753B\u96C6");
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
const handleDeleteCollection = async (id) => {
|
|
805
|
+
try {
|
|
806
|
+
await deleteCollection(id);
|
|
807
|
+
await loadData();
|
|
808
|
+
} catch (err) {
|
|
809
|
+
handleApiError(err, "\u5220\u9664\u753B\u96C6");
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const handleAddArtworkToCollection = async (collectionId, artworkData) => {
|
|
813
|
+
console.log("\u{1F3AF} [Hook] \u5F00\u59CB\u6DFB\u52A0\u4F5C\u54C1\u5230\u753B\u96C6:", {
|
|
814
|
+
collectionId,
|
|
815
|
+
title: artworkData.title,
|
|
816
|
+
number: artworkData.number,
|
|
817
|
+
imageSize: artworkData.image ? `${artworkData.image.length} chars` : "null",
|
|
818
|
+
description: artworkData.description?.substring(0, 50) + (artworkData.description && artworkData.description.length > 50 ? "..." : "")
|
|
819
|
+
});
|
|
820
|
+
try {
|
|
821
|
+
console.log("\u{1F4DE} [Hook] \u8C03\u7528API\u670D\u52A1...");
|
|
822
|
+
const newArtwork = await addArtworkToCollection(collectionId, artworkData);
|
|
823
|
+
console.log("\u2705 [Hook] API\u8C03\u7528\u6210\u529F\uFF0C\u8FD4\u56DE\u4F5C\u54C1:", {
|
|
824
|
+
id: newArtwork.id,
|
|
825
|
+
title: newArtwork.title,
|
|
826
|
+
number: newArtwork.number
|
|
827
|
+
});
|
|
828
|
+
console.log("\u{1F504} [Hook] \u91CD\u65B0\u52A0\u8F7D\u6570\u636E\u4EE5\u786E\u4FDD\u4E0E\u6570\u636E\u5E93\u5B8C\u5168\u540C\u6B65...");
|
|
829
|
+
const reloadedData = await loadData();
|
|
830
|
+
console.log("\u2705 [Hook] \u6570\u636E\u91CD\u65B0\u52A0\u8F7D\u5B8C\u6210");
|
|
831
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
832
|
+
const targetCollection = reloadedData.collections.find((c) => c.id === collectionId);
|
|
833
|
+
if (targetCollection) {
|
|
834
|
+
const newArtworkInCollection = targetCollection.pages.find((p) => p.id === newArtwork.id);
|
|
835
|
+
if (newArtworkInCollection) {
|
|
836
|
+
console.log("\u2705 [Hook] \u9A8C\u8BC1\u6210\u529F\uFF1A\u65B0\u4F5C\u54C1\u5DF2\u5728\u753B\u96C6\u4E2D", {
|
|
837
|
+
artworkId: newArtwork.id,
|
|
838
|
+
collectionId,
|
|
839
|
+
artworkTitle: newArtworkInCollection.title
|
|
840
|
+
});
|
|
841
|
+
} else {
|
|
842
|
+
console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u65B0\u4F5C\u54C1\u4E0D\u5728\u91CD\u65B0\u52A0\u8F7D\u7684\u6570\u636E\u4E2D", {
|
|
843
|
+
expectedArtworkId: newArtwork.id,
|
|
844
|
+
collectionId,
|
|
845
|
+
currentArtworks: targetCollection.pages.map((p) => ({ id: p.id, title: p.title }))
|
|
846
|
+
});
|
|
847
|
+
console.log("\u{1F504} [Hook] \u518D\u6B21\u5C1D\u8BD5\u91CD\u65B0\u52A0\u8F7D\u6570\u636E...");
|
|
848
|
+
await loadData();
|
|
849
|
+
}
|
|
850
|
+
} else {
|
|
851
|
+
console.error("\u274C [Hook] \u9A8C\u8BC1\u5931\u8D25\uFF1A\u627E\u4E0D\u5230\u76EE\u6807\u753B\u96C6", {
|
|
852
|
+
collectionId,
|
|
853
|
+
availableCollections: reloadedData.collections.map((c) => ({ id: c.id, title: c.title }))
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
console.log("\u{1F389} [Hook] \u5F3A\u5236\u66F4\u65B0\u72B6\u6001\u4EE5\u786E\u4FDDUI\u540C\u6B65...");
|
|
857
|
+
setCollections([...reloadedData.collections]);
|
|
858
|
+
setRefreshCounter((prev) => prev + 1);
|
|
859
|
+
console.log("\u{1F525} [Hook] \u89E6\u53D1\u5F3A\u5236\u91CD\u65B0\u6E32\u67D3");
|
|
860
|
+
} catch (err) {
|
|
861
|
+
console.error("\u274C [Hook] \u6DFB\u52A0\u4F5C\u54C1\u5931\u8D25:", err);
|
|
862
|
+
console.error("\u9519\u8BEF\u8BE6\u60C5:", {
|
|
863
|
+
message: err instanceof Error ? err.message : "\u672A\u77E5\u9519\u8BEF",
|
|
864
|
+
collectionId,
|
|
865
|
+
artworkTitle: artworkData.title
|
|
866
|
+
});
|
|
867
|
+
handleApiError(err, "\u6DFB\u52A0\u4F5C\u54C1");
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
const handleUpdateArtwork = async (collectionId, artworkId, artworkData) => {
|
|
871
|
+
try {
|
|
872
|
+
const updatedArtwork = await updateArtwork(collectionId, artworkId, artworkData);
|
|
873
|
+
await loadData();
|
|
874
|
+
} catch (err) {
|
|
875
|
+
handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1");
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
const handleDeleteArtwork = async (collectionId, artworkId) => {
|
|
879
|
+
try {
|
|
880
|
+
await deleteArtwork(collectionId, artworkId);
|
|
881
|
+
await loadData();
|
|
882
|
+
} catch (err) {
|
|
883
|
+
handleApiError(err, "\u5220\u9664\u4F5C\u54C1");
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
const handleMoveArtworkUp = async (collectionId, artworkId) => {
|
|
887
|
+
try {
|
|
888
|
+
await moveArtworkUp(collectionId, artworkId);
|
|
889
|
+
await updateCollectionArtworks(collectionId);
|
|
890
|
+
} catch (err) {
|
|
891
|
+
handleApiError(err, "\u4E0A\u79FB\u4F5C\u54C1");
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
const handleMoveArtworkDown = async (collectionId, artworkId) => {
|
|
895
|
+
try {
|
|
896
|
+
await moveArtworkDown(collectionId, artworkId);
|
|
897
|
+
await updateCollectionArtworks(collectionId);
|
|
898
|
+
} catch (err) {
|
|
899
|
+
handleApiError(err, "\u4E0B\u79FB\u4F5C\u54C1");
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
const handleUpdateArtworkOrder = async (collectionId, artworkOrders) => {
|
|
903
|
+
try {
|
|
904
|
+
await updateArtworkOrder(collectionId, artworkOrders);
|
|
905
|
+
await updateCollectionArtworks(collectionId);
|
|
906
|
+
} catch (err) {
|
|
907
|
+
handleApiError(err, "\u66F4\u65B0\u4F5C\u54C1\u987A\u5E8F");
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const updateCollectionArtworks = async (collectionId) => {
|
|
911
|
+
try {
|
|
912
|
+
const updatedArtworks = await getArtworksByCollection(collectionId);
|
|
913
|
+
setCollections(
|
|
914
|
+
(prevCollections) => prevCollections.map(
|
|
915
|
+
(collection) => collection.id === collectionId ? { ...collection, pages: updatedArtworks } : collection
|
|
916
|
+
)
|
|
917
|
+
);
|
|
918
|
+
} catch (err) {
|
|
919
|
+
console.error("\u66F4\u65B0\u753B\u96C6\u4F5C\u54C1\u6570\u636E\u5931\u8D25:", err);
|
|
920
|
+
await loadData();
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
const handleMoveCollectionUp = async (collectionId) => {
|
|
924
|
+
try {
|
|
925
|
+
await moveCollectionUp(collectionId);
|
|
926
|
+
await updateCollectionsData();
|
|
927
|
+
} catch (err) {
|
|
928
|
+
handleApiError(err, "\u4E0A\u79FB\u753B\u96C6");
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
const handleMoveCollectionDown = async (collectionId) => {
|
|
932
|
+
try {
|
|
933
|
+
await moveCollectionDown(collectionId);
|
|
934
|
+
await updateCollectionsData();
|
|
935
|
+
} catch (err) {
|
|
936
|
+
handleApiError(err, "\u4E0B\u79FB\u753B\u96C6");
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
const handleUpdateCollectionOrder = async (collectionOrders) => {
|
|
940
|
+
try {
|
|
941
|
+
await updateCollectionOrder(collectionOrders);
|
|
942
|
+
await updateCollectionsData();
|
|
943
|
+
} catch (err) {
|
|
944
|
+
handleApiError(err, "\u66F4\u65B0\u753B\u96C6\u987A\u5E8F");
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
const updateCollectionsData = async () => {
|
|
948
|
+
try {
|
|
949
|
+
const updatedCollections = await getAllCollections();
|
|
950
|
+
setCollections(updatedCollections);
|
|
951
|
+
} catch (err) {
|
|
952
|
+
console.error("\u66F4\u65B0\u753B\u96C6\u6570\u636E\u5931\u8D25:", err);
|
|
953
|
+
await loadData();
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
return {
|
|
957
|
+
// 数据
|
|
958
|
+
config,
|
|
959
|
+
collections,
|
|
960
|
+
categories,
|
|
961
|
+
tags,
|
|
962
|
+
loading,
|
|
963
|
+
error,
|
|
964
|
+
refreshCounter,
|
|
965
|
+
// 方法
|
|
966
|
+
updateConfig: handleUpdateConfig,
|
|
967
|
+
resetConfig: handleResetConfig,
|
|
968
|
+
createCollection: handleCreateCollection,
|
|
969
|
+
updateCollection: handleUpdateCollection,
|
|
970
|
+
deleteCollection: handleDeleteCollection,
|
|
971
|
+
addArtworkToCollection: handleAddArtworkToCollection,
|
|
972
|
+
updateArtwork: handleUpdateArtwork,
|
|
973
|
+
deleteArtwork: handleDeleteArtwork,
|
|
974
|
+
// 新增:作品排序方法
|
|
975
|
+
moveArtworkUp: handleMoveArtworkUp,
|
|
976
|
+
moveArtworkDown: handleMoveArtworkDown,
|
|
977
|
+
updateArtworkOrder: handleUpdateArtworkOrder,
|
|
978
|
+
// 新增:画集排序方法
|
|
979
|
+
moveCollectionUp: handleMoveCollectionUp,
|
|
980
|
+
moveCollectionDown: handleMoveCollectionDown,
|
|
981
|
+
updateCollectionOrder: handleUpdateCollectionOrder,
|
|
982
|
+
refreshData: loadData
|
|
983
|
+
};
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
|
|
988
|
+
// src/showmasterpiece/services/cartHistoryService.ts
|
|
989
|
+
var CART_HISTORY_STORAGE_KEY_BASE, CART_HISTORY_STORAGE_KEY, CartHistoryService, getCartHistory, updateBookingStatus, deleteHistoryRecord, clearUserHistory, getAllHistory, getStatistics, saveCartHistory;
|
|
990
|
+
var init_cartHistoryService = __esm({
|
|
991
|
+
"src/showmasterpiece/services/cartHistoryService.ts"() {
|
|
992
|
+
CART_HISTORY_STORAGE_KEY_BASE = "showmasterpiece_cart_history";
|
|
993
|
+
CART_HISTORY_STORAGE_KEY = CART_HISTORY_STORAGE_KEY_BASE;
|
|
994
|
+
CartHistoryService = class {
|
|
995
|
+
/**
|
|
996
|
+
* 生成唯一ID
|
|
997
|
+
*/
|
|
998
|
+
// static generateId(): string {
|
|
999
|
+
// return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
1000
|
+
// }
|
|
1001
|
+
/**
|
|
1002
|
+
* 获取用户购物车历史记录
|
|
1003
|
+
*
|
|
1004
|
+
* @param qqNumber 用户QQ号
|
|
1005
|
+
* @param phoneNumber 用户手机号
|
|
1006
|
+
* @returns 购物车历史记录
|
|
1007
|
+
*/
|
|
1008
|
+
static async getCartHistory(qqNumber, phoneNumber) {
|
|
1009
|
+
try {
|
|
1010
|
+
const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1011
|
+
if (historyData) {
|
|
1012
|
+
const allHistory = JSON.parse(historyData);
|
|
1013
|
+
const userHistory = allHistory.filter(
|
|
1014
|
+
(record) => record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
|
|
1015
|
+
);
|
|
1016
|
+
const processedHistory = userHistory.map((record) => ({
|
|
1017
|
+
...record,
|
|
1018
|
+
submittedAt: new Date(record.submittedAt),
|
|
1019
|
+
items: record.items.map((item) => ({
|
|
1020
|
+
...item,
|
|
1021
|
+
addedAt: new Date(item.addedAt)
|
|
1022
|
+
}))
|
|
1023
|
+
}));
|
|
1024
|
+
processedHistory.sort((a, b) => b.submittedAt.getTime() - a.submittedAt.getTime());
|
|
1025
|
+
return {
|
|
1026
|
+
records: processedHistory,
|
|
1027
|
+
totalRecords: processedHistory.length
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
console.error("\u8BFB\u53D6\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1032
|
+
}
|
|
1033
|
+
return {
|
|
1034
|
+
records: [],
|
|
1035
|
+
totalRecords: 0
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* 保存购物车历史记录
|
|
1040
|
+
*
|
|
1041
|
+
* @param historyItem 历史记录项
|
|
1042
|
+
*/
|
|
1043
|
+
static async saveCartHistory(historyItem) {
|
|
1044
|
+
try {
|
|
1045
|
+
const generateId = () => `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
1046
|
+
const newHistoryItem = {
|
|
1047
|
+
...historyItem,
|
|
1048
|
+
id: generateId(),
|
|
1049
|
+
submittedAt: /* @__PURE__ */ new Date()
|
|
1050
|
+
};
|
|
1051
|
+
const existingData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1052
|
+
const allHistory = existingData ? JSON.parse(existingData) : [];
|
|
1053
|
+
allHistory.push(newHistoryItem);
|
|
1054
|
+
localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
|
|
1055
|
+
console.log("\u2705 \u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u4FDD\u5B58\u6210\u529F:", {
|
|
1056
|
+
id: newHistoryItem.id,
|
|
1057
|
+
qqNumber: newHistoryItem.qqNumber,
|
|
1058
|
+
itemCount: newHistoryItem.items.length
|
|
1059
|
+
});
|
|
1060
|
+
return newHistoryItem;
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1063
|
+
throw new Error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* 更新预订状态
|
|
1068
|
+
*
|
|
1069
|
+
* @param qqNumber 用户QQ号
|
|
1070
|
+
* @param phoneNumber 用户手机号
|
|
1071
|
+
* @param historyId 历史记录ID
|
|
1072
|
+
* @param status 新状态
|
|
1073
|
+
* @param bookingIds 预订ID列表
|
|
1074
|
+
*/
|
|
1075
|
+
static async updateBookingStatus(qqNumber, phoneNumber, historyId, status, bookingIds) {
|
|
1076
|
+
try {
|
|
1077
|
+
const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1078
|
+
if (historyData) {
|
|
1079
|
+
const allHistory = JSON.parse(historyData);
|
|
1080
|
+
const recordIndex = allHistory.findIndex(
|
|
1081
|
+
(record) => record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber
|
|
1082
|
+
);
|
|
1083
|
+
if (recordIndex !== -1) {
|
|
1084
|
+
const record = allHistory[recordIndex];
|
|
1085
|
+
if (!record) {
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
record.status = status;
|
|
1089
|
+
if (bookingIds) {
|
|
1090
|
+
record.bookingIds = bookingIds;
|
|
1091
|
+
}
|
|
1092
|
+
localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
|
|
1093
|
+
console.log("\u2705 \u9884\u8BA2\u72B6\u6001\u66F4\u65B0\u6210\u529F:", {
|
|
1094
|
+
historyId,
|
|
1095
|
+
status,
|
|
1096
|
+
bookingIds
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
} catch (error) {
|
|
1101
|
+
console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
|
|
1102
|
+
throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* 删除历史记录
|
|
1107
|
+
*
|
|
1108
|
+
* @param qqNumber 用户QQ号
|
|
1109
|
+
* @param phoneNumber 用户手机号
|
|
1110
|
+
* @param historyId 历史记录ID
|
|
1111
|
+
*/
|
|
1112
|
+
static async deleteHistoryRecord(qqNumber, phoneNumber, historyId) {
|
|
1113
|
+
try {
|
|
1114
|
+
const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1115
|
+
if (historyData) {
|
|
1116
|
+
const allHistory = JSON.parse(historyData);
|
|
1117
|
+
const filteredHistory = allHistory.filter(
|
|
1118
|
+
(record) => !(record.id === historyId && record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
|
|
1119
|
+
);
|
|
1120
|
+
localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
|
|
1121
|
+
console.log("\u2705 \u5386\u53F2\u8BB0\u5F55\u5220\u9664\u6210\u529F:", { historyId });
|
|
1122
|
+
}
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
console.error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1125
|
+
throw new Error("\u5220\u9664\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* 清空用户所有历史记录
|
|
1130
|
+
*
|
|
1131
|
+
* @param qqNumber 用户QQ号
|
|
1132
|
+
* @param phoneNumber 用户手机号
|
|
1133
|
+
*/
|
|
1134
|
+
static async clearUserHistory(qqNumber, phoneNumber) {
|
|
1135
|
+
try {
|
|
1136
|
+
const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1137
|
+
if (historyData) {
|
|
1138
|
+
const allHistory = JSON.parse(historyData);
|
|
1139
|
+
const filteredHistory = allHistory.filter(
|
|
1140
|
+
(record) => !(record.qqNumber === qqNumber && record.phoneNumber === phoneNumber)
|
|
1141
|
+
);
|
|
1142
|
+
localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(filteredHistory));
|
|
1143
|
+
console.log("\u2705 \u7528\u6237\u5386\u53F2\u8BB0\u5F55\u6E05\u7A7A\u6210\u529F:", { qqNumber, phoneNumber });
|
|
1144
|
+
}
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
console.error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1147
|
+
throw new Error("\u6E05\u7A7A\u7528\u6237\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* 获取所有历史记录(管理员功能)
|
|
1152
|
+
*/
|
|
1153
|
+
static async getAllHistory() {
|
|
1154
|
+
try {
|
|
1155
|
+
const historyData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1156
|
+
if (historyData) {
|
|
1157
|
+
const allHistory = JSON.parse(historyData);
|
|
1158
|
+
return allHistory.map((record) => ({
|
|
1159
|
+
...record,
|
|
1160
|
+
submittedAt: new Date(record.submittedAt),
|
|
1161
|
+
items: record.items.map((item) => ({
|
|
1162
|
+
...item,
|
|
1163
|
+
addedAt: new Date(item.addedAt)
|
|
1164
|
+
}))
|
|
1165
|
+
}));
|
|
1166
|
+
}
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
console.error("\u8BFB\u53D6\u6240\u6709\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1169
|
+
}
|
|
1170
|
+
return [];
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* 获取统计数据
|
|
1174
|
+
*/
|
|
1175
|
+
static async getStatistics() {
|
|
1176
|
+
try {
|
|
1177
|
+
const allHistory = await this.getAllHistory();
|
|
1178
|
+
const totalRecords = allHistory.length;
|
|
1179
|
+
const uniqueUsers = new Set(
|
|
1180
|
+
allHistory.map((record) => `${record.qqNumber}_${record.phoneNumber}`)
|
|
1181
|
+
);
|
|
1182
|
+
const totalUsers = uniqueUsers.size;
|
|
1183
|
+
let totalItems = 0;
|
|
1184
|
+
let totalRevenue = 0;
|
|
1185
|
+
allHistory.forEach((record) => {
|
|
1186
|
+
totalItems += record.totalQuantity;
|
|
1187
|
+
totalRevenue += record.totalPrice;
|
|
1188
|
+
});
|
|
1189
|
+
return {
|
|
1190
|
+
totalRecords,
|
|
1191
|
+
totalUsers,
|
|
1192
|
+
totalItems,
|
|
1193
|
+
totalRevenue
|
|
1194
|
+
};
|
|
1195
|
+
} catch (error) {
|
|
1196
|
+
console.error("\u83B7\u53D6\u7EDF\u8BA1\u6570\u636E\u5931\u8D25:", error);
|
|
1197
|
+
return {
|
|
1198
|
+
totalRecords: 0,
|
|
1199
|
+
totalUsers: 0,
|
|
1200
|
+
totalItems: 0,
|
|
1201
|
+
totalRevenue: 0
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
getCartHistory = CartHistoryService.getCartHistory;
|
|
1207
|
+
updateBookingStatus = CartHistoryService.updateBookingStatus;
|
|
1208
|
+
deleteHistoryRecord = CartHistoryService.deleteHistoryRecord;
|
|
1209
|
+
clearUserHistory = CartHistoryService.clearUserHistory;
|
|
1210
|
+
getAllHistory = CartHistoryService.getAllHistory;
|
|
1211
|
+
getStatistics = CartHistoryService.getStatistics;
|
|
1212
|
+
saveCartHistory = async (historyItem) => {
|
|
1213
|
+
try {
|
|
1214
|
+
const generateId = () => `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
1215
|
+
const newHistoryItem = {
|
|
1216
|
+
...historyItem,
|
|
1217
|
+
id: generateId(),
|
|
1218
|
+
submittedAt: /* @__PURE__ */ new Date()
|
|
1219
|
+
};
|
|
1220
|
+
const existingData = localStorage.getItem(CART_HISTORY_STORAGE_KEY);
|
|
1221
|
+
const allHistory = existingData ? JSON.parse(existingData) : [];
|
|
1222
|
+
allHistory.push(newHistoryItem);
|
|
1223
|
+
localStorage.setItem(CART_HISTORY_STORAGE_KEY, JSON.stringify(allHistory));
|
|
1224
|
+
console.log("\u2705 \u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u4FDD\u5B58\u6210\u529F:", {
|
|
1225
|
+
id: newHistoryItem.id,
|
|
1226
|
+
qqNumber: newHistoryItem.qqNumber,
|
|
1227
|
+
itemCount: newHistoryItem.items.length
|
|
1228
|
+
});
|
|
1229
|
+
return newHistoryItem;
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1232
|
+
throw new Error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25");
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
// src/showmasterpiece/services/cartService.ts
|
|
1239
|
+
var CART_STORAGE_KEY, CartService, getCart, addToCart, updateCartItem, removeFromCart, clearCart, batchBooking;
|
|
1240
|
+
var init_cartService = __esm({
|
|
1241
|
+
"src/showmasterpiece/services/cartService.ts"() {
|
|
1242
|
+
init_cartHistoryService();
|
|
1243
|
+
CART_STORAGE_KEY = "showmasterpiece_cart";
|
|
1244
|
+
CartService = class {
|
|
1245
|
+
/**
|
|
1246
|
+
* 获取购物车数据
|
|
1247
|
+
*
|
|
1248
|
+
* @param userId 用户ID
|
|
1249
|
+
* @returns 购物车数据
|
|
1250
|
+
*/
|
|
1251
|
+
static async getCart(userId) {
|
|
1252
|
+
try {
|
|
1253
|
+
const storageKey = `${CART_STORAGE_KEY}_${userId}`;
|
|
1254
|
+
const cartData = localStorage.getItem(storageKey);
|
|
1255
|
+
if (cartData) {
|
|
1256
|
+
const parsed = JSON.parse(cartData);
|
|
1257
|
+
if (parsed.items) {
|
|
1258
|
+
parsed.items = parsed.items.map((item) => ({
|
|
1259
|
+
...item,
|
|
1260
|
+
addedAt: new Date(item.addedAt)
|
|
1261
|
+
}));
|
|
1262
|
+
}
|
|
1263
|
+
return parsed;
|
|
1264
|
+
}
|
|
1265
|
+
} catch (error) {
|
|
1266
|
+
console.error("\u8BFB\u53D6\u8D2D\u7269\u8F66\u6570\u636E\u5931\u8D25:", error);
|
|
1267
|
+
}
|
|
1268
|
+
return {
|
|
1269
|
+
items: [],
|
|
1270
|
+
totalQuantity: 0,
|
|
1271
|
+
totalPrice: 0
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* 保存购物车数据到本地存储
|
|
1276
|
+
*
|
|
1277
|
+
* @param userId 用户ID
|
|
1278
|
+
* @param cart 购物车数据
|
|
1279
|
+
*/
|
|
1280
|
+
static saveCart(userId, cart) {
|
|
1281
|
+
try {
|
|
1282
|
+
const storageKey = `${CART_STORAGE_KEY}_${userId}`;
|
|
1283
|
+
localStorage.setItem(storageKey, JSON.stringify(cart));
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u6570\u636E\u5931\u8D25:", error);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* 计算购物车总数量和总价格
|
|
1290
|
+
*
|
|
1291
|
+
* @param items 购物车商品项
|
|
1292
|
+
* @returns 总数量和总价格
|
|
1293
|
+
*/
|
|
1294
|
+
static calculateTotals(items) {
|
|
1295
|
+
let totalQuantity = 0;
|
|
1296
|
+
let totalPrice = 0;
|
|
1297
|
+
items.forEach((item) => {
|
|
1298
|
+
totalQuantity += item.quantity;
|
|
1299
|
+
const itemPrice = (item.collection.price || 0) * item.quantity;
|
|
1300
|
+
totalPrice += itemPrice;
|
|
1301
|
+
});
|
|
1302
|
+
return { totalQuantity, totalPrice };
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* 添加商品到购物车
|
|
1306
|
+
*
|
|
1307
|
+
* @param data 添加商品数据
|
|
1308
|
+
* @returns 更新后的购物车数据
|
|
1309
|
+
*/
|
|
1310
|
+
static async addToCart(data) {
|
|
1311
|
+
const { userId, collectionId, quantity, collection } = data;
|
|
1312
|
+
const cart = await this.getCart(userId);
|
|
1313
|
+
const existingItemIndex = cart.items.findIndex((item) => item.collectionId === collectionId);
|
|
1314
|
+
if (existingItemIndex >= 0) {
|
|
1315
|
+
const existingItem = cart.items[existingItemIndex];
|
|
1316
|
+
if (existingItem) {
|
|
1317
|
+
existingItem.quantity += quantity;
|
|
1318
|
+
}
|
|
1319
|
+
} else {
|
|
1320
|
+
if (collection) {
|
|
1321
|
+
cart.items.push({
|
|
1322
|
+
collectionId,
|
|
1323
|
+
collection,
|
|
1324
|
+
quantity,
|
|
1325
|
+
addedAt: /* @__PURE__ */ new Date()
|
|
1326
|
+
});
|
|
1327
|
+
} else {
|
|
1328
|
+
cart.items.push({
|
|
1329
|
+
collectionId,
|
|
1330
|
+
collection: {
|
|
1331
|
+
id: collectionId,
|
|
1332
|
+
title: `\u753B\u96C6${collectionId}`,
|
|
1333
|
+
// 临时标题,实际应该从画集数据中获取
|
|
1334
|
+
number: "\u672A\u77E5\u7F16\u53F7",
|
|
1335
|
+
coverImage: "",
|
|
1336
|
+
description: "",
|
|
1337
|
+
pages: [],
|
|
1338
|
+
category: "\u753B\u96C6",
|
|
1339
|
+
tags: [],
|
|
1340
|
+
isPublished: true,
|
|
1341
|
+
price: 0
|
|
1342
|
+
},
|
|
1343
|
+
quantity,
|
|
1344
|
+
addedAt: /* @__PURE__ */ new Date()
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
const { totalQuantity, totalPrice } = this.calculateTotals(cart.items);
|
|
1349
|
+
cart.totalQuantity = totalQuantity;
|
|
1350
|
+
cart.totalPrice = totalPrice;
|
|
1351
|
+
this.saveCart(userId, cart);
|
|
1352
|
+
return cart;
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* 更新购物车商品数量
|
|
1356
|
+
*
|
|
1357
|
+
* @param data 更新商品数据
|
|
1358
|
+
* @returns 更新后的购物车数据
|
|
1359
|
+
*/
|
|
1360
|
+
static async updateCartItem(data) {
|
|
1361
|
+
const { userId, collectionId, quantity } = data;
|
|
1362
|
+
const cart = await this.getCart(userId);
|
|
1363
|
+
const itemIndex = cart.items.findIndex((item) => item.collectionId === collectionId);
|
|
1364
|
+
if (itemIndex >= 0) {
|
|
1365
|
+
if (quantity <= 0) {
|
|
1366
|
+
cart.items.splice(itemIndex, 1);
|
|
1367
|
+
} else {
|
|
1368
|
+
const item = cart.items[itemIndex];
|
|
1369
|
+
if (item) {
|
|
1370
|
+
item.quantity = quantity;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
const { totalQuantity, totalPrice } = this.calculateTotals(cart.items);
|
|
1374
|
+
cart.totalQuantity = totalQuantity;
|
|
1375
|
+
cart.totalPrice = totalPrice;
|
|
1376
|
+
this.saveCart(userId, cart);
|
|
1377
|
+
}
|
|
1378
|
+
return cart;
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* 从购物车移除商品
|
|
1382
|
+
*
|
|
1383
|
+
* @param data 移除商品数据
|
|
1384
|
+
* @returns 更新后的购物车数据
|
|
1385
|
+
*/
|
|
1386
|
+
static async removeFromCart(data) {
|
|
1387
|
+
const { userId, collectionId } = data;
|
|
1388
|
+
const cart = await this.getCart(userId);
|
|
1389
|
+
cart.items = cart.items.filter((item) => item.collectionId !== collectionId);
|
|
1390
|
+
const { totalQuantity, totalPrice } = this.calculateTotals(cart.items);
|
|
1391
|
+
cart.totalQuantity = totalQuantity;
|
|
1392
|
+
cart.totalPrice = totalPrice;
|
|
1393
|
+
this.saveCart(userId, cart);
|
|
1394
|
+
return cart;
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* 清空购物车
|
|
1398
|
+
*
|
|
1399
|
+
* @param userId 用户ID
|
|
1400
|
+
* @returns 清空后的购物车数据
|
|
1401
|
+
*/
|
|
1402
|
+
static async clearCart(userId) {
|
|
1403
|
+
const emptyCart = {
|
|
1404
|
+
items: [],
|
|
1405
|
+
totalQuantity: 0,
|
|
1406
|
+
totalPrice: 0
|
|
1407
|
+
};
|
|
1408
|
+
this.saveCart(userId, emptyCart);
|
|
1409
|
+
return emptyCart;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* 批量预订购物车中的商品
|
|
1413
|
+
*
|
|
1414
|
+
* @param data 批量预订数据
|
|
1415
|
+
* @param cart 当前购物车数据(用于保存历史记录)
|
|
1416
|
+
* @returns 预订结果
|
|
1417
|
+
*/
|
|
1418
|
+
static async batchBooking(data, cart) {
|
|
1419
|
+
const requestData = {
|
|
1420
|
+
...data
|
|
1421
|
+
};
|
|
1422
|
+
console.log("\u{1F6D2} [CartService] \u6279\u91CF\u9884\u8BA2:", { data });
|
|
1423
|
+
const response = await fetch(this.BOOKING_URL, {
|
|
1424
|
+
method: "POST",
|
|
1425
|
+
headers: {
|
|
1426
|
+
"Content-Type": "application/json"
|
|
1427
|
+
},
|
|
1428
|
+
body: JSON.stringify(requestData)
|
|
1429
|
+
});
|
|
1430
|
+
if (!response.ok) {
|
|
1431
|
+
const error = await response.json().catch(() => ({ message: "\u6279\u91CF\u9884\u8BA2\u5931\u8D25" }));
|
|
1432
|
+
throw new Error(error.message || "\u6279\u91CF\u9884\u8BA2\u5931\u8D25");
|
|
1433
|
+
}
|
|
1434
|
+
const result = await response.json();
|
|
1435
|
+
if (result.successCount > 0 && cart) {
|
|
1436
|
+
try {
|
|
1437
|
+
await saveCartHistory({
|
|
1438
|
+
qqNumber: data.qqNumber,
|
|
1439
|
+
phoneNumber: data.phoneNumber,
|
|
1440
|
+
items: cart.items,
|
|
1441
|
+
totalQuantity: cart.totalQuantity,
|
|
1442
|
+
totalPrice: cart.totalPrice,
|
|
1443
|
+
notes: data.notes,
|
|
1444
|
+
pickupMethod: data.pickupMethod,
|
|
1445
|
+
status: "pending",
|
|
1446
|
+
bookingIds: result.bookingIds,
|
|
1447
|
+
submittedAt: /* @__PURE__ */ new Date()
|
|
1448
|
+
});
|
|
1449
|
+
} catch (error) {
|
|
1450
|
+
console.error("\u4FDD\u5B58\u8D2D\u7269\u8F66\u5386\u53F2\u8BB0\u5F55\u5931\u8D25:", error);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
return result;
|
|
1454
|
+
}
|
|
1455
|
+
};
|
|
1456
|
+
CartService.BOOKING_URL = "/api/showmasterpiece/bookings/batch";
|
|
1457
|
+
getCart = (userId) => {
|
|
1458
|
+
return CartService.getCart(userId);
|
|
1459
|
+
};
|
|
1460
|
+
addToCart = (data) => {
|
|
1461
|
+
return CartService.addToCart(data);
|
|
1462
|
+
};
|
|
1463
|
+
updateCartItem = (data) => {
|
|
1464
|
+
return CartService.updateCartItem(data);
|
|
1465
|
+
};
|
|
1466
|
+
removeFromCart = (data) => {
|
|
1467
|
+
return CartService.removeFromCart(data);
|
|
1468
|
+
};
|
|
1469
|
+
clearCart = (userId) => {
|
|
1470
|
+
return CartService.clearCart(userId);
|
|
1471
|
+
};
|
|
1472
|
+
batchBooking = (data, cart) => {
|
|
1473
|
+
return CartService.batchBooking(data, cart);
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
});
|
|
1477
|
+
function useCart(userId) {
|
|
1478
|
+
const [state, setState] = useState({
|
|
1479
|
+
cart: {
|
|
1480
|
+
items: [],
|
|
1481
|
+
totalQuantity: 0,
|
|
1482
|
+
totalPrice: 0
|
|
1483
|
+
},
|
|
1484
|
+
loading: false,
|
|
1485
|
+
error: void 0,
|
|
1486
|
+
isCartOpen: false
|
|
1487
|
+
});
|
|
1488
|
+
const loadCart = useCallback(async () => {
|
|
1489
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1490
|
+
try {
|
|
1491
|
+
const cartData = await getCart(userId);
|
|
1492
|
+
setState((prev) => ({
|
|
1493
|
+
...prev,
|
|
1494
|
+
cart: cartData,
|
|
1495
|
+
loading: false
|
|
1496
|
+
}));
|
|
1497
|
+
} catch (error) {
|
|
1498
|
+
console.error("\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
1499
|
+
setState((prev) => ({
|
|
1500
|
+
...prev,
|
|
1501
|
+
loading: false,
|
|
1502
|
+
error: error instanceof Error ? error.message : "\u52A0\u8F7D\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
1503
|
+
}));
|
|
1504
|
+
}
|
|
1505
|
+
}, [userId]);
|
|
1506
|
+
const addItemToCart = useCallback(async (request) => {
|
|
1507
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1508
|
+
try {
|
|
1509
|
+
const updatedCart = await addToCart(request);
|
|
1510
|
+
setState((prev) => ({
|
|
1511
|
+
...prev,
|
|
1512
|
+
cart: updatedCart,
|
|
1513
|
+
loading: false
|
|
1514
|
+
}));
|
|
1515
|
+
notifyCartUpdate();
|
|
1516
|
+
} catch (error) {
|
|
1517
|
+
console.error("\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
1518
|
+
setState((prev) => ({
|
|
1519
|
+
...prev,
|
|
1520
|
+
loading: false,
|
|
1521
|
+
error: error instanceof Error ? error.message : "\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
1522
|
+
}));
|
|
1523
|
+
}
|
|
1524
|
+
}, [userId]);
|
|
1525
|
+
const updateItemQuantity = useCallback(async (collectionId, quantity) => {
|
|
1526
|
+
if (quantity <= 0) {
|
|
1527
|
+
await removeItemFromCart(collectionId);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1531
|
+
try {
|
|
1532
|
+
const request = {
|
|
1533
|
+
userId,
|
|
1534
|
+
collectionId,
|
|
1535
|
+
quantity
|
|
1536
|
+
};
|
|
1537
|
+
const updatedCart = await updateCartItem(request);
|
|
1538
|
+
setState((prev) => ({
|
|
1539
|
+
...prev,
|
|
1540
|
+
cart: updatedCart,
|
|
1541
|
+
loading: false
|
|
1542
|
+
}));
|
|
1543
|
+
notifyCartUpdate();
|
|
1544
|
+
} catch (error) {
|
|
1545
|
+
console.error("\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
1546
|
+
setState((prev) => ({
|
|
1547
|
+
...prev,
|
|
1548
|
+
loading: false,
|
|
1549
|
+
error: error instanceof Error ? error.message : "\u66F4\u65B0\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
1550
|
+
}));
|
|
1551
|
+
}
|
|
1552
|
+
}, [userId]);
|
|
1553
|
+
const removeItemFromCart = useCallback(async (collectionId) => {
|
|
1554
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1555
|
+
try {
|
|
1556
|
+
const request = {
|
|
1557
|
+
userId,
|
|
1558
|
+
collectionId
|
|
1559
|
+
};
|
|
1560
|
+
const updatedCart = await removeFromCart(request);
|
|
1561
|
+
setState((prev) => ({
|
|
1562
|
+
...prev,
|
|
1563
|
+
cart: updatedCart,
|
|
1564
|
+
loading: false
|
|
1565
|
+
}));
|
|
1566
|
+
notifyCartUpdate();
|
|
1567
|
+
} catch (error) {
|
|
1568
|
+
console.error("\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25:", error);
|
|
1569
|
+
setState((prev) => ({
|
|
1570
|
+
...prev,
|
|
1571
|
+
loading: false,
|
|
1572
|
+
error: error instanceof Error ? error.message : "\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664\u5931\u8D25"
|
|
1573
|
+
}));
|
|
1574
|
+
}
|
|
1575
|
+
}, [userId]);
|
|
1576
|
+
const clearCartItems = useCallback(async () => {
|
|
1577
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1578
|
+
try {
|
|
1579
|
+
await clearCart(userId);
|
|
1580
|
+
setState((prev) => ({
|
|
1581
|
+
...prev,
|
|
1582
|
+
cart: { items: [], totalQuantity: 0, totalPrice: 0 },
|
|
1583
|
+
loading: false
|
|
1584
|
+
}));
|
|
1585
|
+
notifyCartUpdate();
|
|
1586
|
+
} catch (error) {
|
|
1587
|
+
console.error("\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
1588
|
+
setState((prev) => ({
|
|
1589
|
+
...prev,
|
|
1590
|
+
loading: false,
|
|
1591
|
+
error: error instanceof Error ? error.message : "\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
1592
|
+
}));
|
|
1593
|
+
}
|
|
1594
|
+
}, [userId]);
|
|
1595
|
+
const checkoutCart = useCallback(async (qqNumber, phoneNumber, notes, pickupMethod = "") => {
|
|
1596
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1597
|
+
try {
|
|
1598
|
+
const request = {
|
|
1599
|
+
qqNumber,
|
|
1600
|
+
phoneNumber,
|
|
1601
|
+
items: state.cart.items.map((item) => ({
|
|
1602
|
+
collectionId: item.collectionId,
|
|
1603
|
+
quantity: item.quantity
|
|
1604
|
+
})),
|
|
1605
|
+
notes,
|
|
1606
|
+
pickupMethod
|
|
1607
|
+
};
|
|
1608
|
+
const result = await batchBooking(request, state.cart);
|
|
1609
|
+
if (result.successCount > 0) {
|
|
1610
|
+
await clearCartItems();
|
|
1611
|
+
}
|
|
1612
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
1613
|
+
return result;
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
console.error("\u6279\u91CF\u9884\u8BA2\u5931\u8D25:", error);
|
|
1616
|
+
setState((prev) => ({
|
|
1617
|
+
...prev,
|
|
1618
|
+
loading: false,
|
|
1619
|
+
error: error instanceof Error ? error.message : "\u6279\u91CF\u9884\u8BA2\u5931\u8D25"
|
|
1620
|
+
}));
|
|
1621
|
+
throw error;
|
|
1622
|
+
}
|
|
1623
|
+
}, [state.cart.items, clearCartItems]);
|
|
1624
|
+
const openCart = useCallback(() => {
|
|
1625
|
+
setState((prev) => ({ ...prev, isCartOpen: true }));
|
|
1626
|
+
}, []);
|
|
1627
|
+
const closeCart = useCallback(() => {
|
|
1628
|
+
setState((prev) => ({ ...prev, isCartOpen: false }));
|
|
1629
|
+
}, []);
|
|
1630
|
+
const clearError = useCallback(() => {
|
|
1631
|
+
setState((prev) => ({ ...prev, error: void 0 }));
|
|
1632
|
+
}, []);
|
|
1633
|
+
useEffect(() => {
|
|
1634
|
+
if (userId) {
|
|
1635
|
+
loadCart();
|
|
1636
|
+
}
|
|
1637
|
+
}, [userId, loadCart]);
|
|
1638
|
+
return {
|
|
1639
|
+
// 状态
|
|
1640
|
+
cart: state.cart,
|
|
1641
|
+
loading: state.loading,
|
|
1642
|
+
error: state.error,
|
|
1643
|
+
isCartOpen: state.isCartOpen,
|
|
1644
|
+
// 操作方法
|
|
1645
|
+
loadCart,
|
|
1646
|
+
addItemToCart,
|
|
1647
|
+
updateItemQuantity,
|
|
1648
|
+
removeItemFromCart,
|
|
1649
|
+
clearCartItems,
|
|
1650
|
+
checkoutCart,
|
|
1651
|
+
openCart,
|
|
1652
|
+
closeCart,
|
|
1653
|
+
clearError
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
var cartUpdateEvents, CART_UPDATE_EVENT, notifyCartUpdate;
|
|
1657
|
+
var init_useCart = __esm({
|
|
1658
|
+
"src/showmasterpiece/logic/hooks/useCart.ts"() {
|
|
1659
|
+
init_cartService();
|
|
1660
|
+
cartUpdateEvents = new EventTarget();
|
|
1661
|
+
CART_UPDATE_EVENT = "cart-updated";
|
|
1662
|
+
notifyCartUpdate = () => {
|
|
1663
|
+
cartUpdateEvents.dispatchEvent(new Event(CART_UPDATE_EVENT));
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
});
|
|
1667
|
+
|
|
1668
|
+
// src/showmasterpiece/services/bookingService.ts
|
|
1669
|
+
var BookingService, createBooking, getBookings, getBooking, updateBooking, deleteBooking, getBookableCollections;
|
|
1670
|
+
var init_bookingService = __esm({
|
|
1671
|
+
"src/showmasterpiece/services/bookingService.ts"() {
|
|
1672
|
+
BookingService = class {
|
|
1673
|
+
/**
|
|
1674
|
+
* 创建新预订
|
|
1675
|
+
*
|
|
1676
|
+
* @param data 预订数据
|
|
1677
|
+
* @returns 创建的预订信息
|
|
1678
|
+
*/
|
|
1679
|
+
static async createBooking(data) {
|
|
1680
|
+
const response = await fetch(this.BASE_URL, {
|
|
1681
|
+
method: "POST",
|
|
1682
|
+
headers: {
|
|
1683
|
+
"Content-Type": "application/json"
|
|
1684
|
+
},
|
|
1685
|
+
body: JSON.stringify(data)
|
|
1686
|
+
});
|
|
1687
|
+
if (!response.ok) {
|
|
1688
|
+
const error = await response.json().catch(() => ({ message: "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25" }));
|
|
1689
|
+
throw new Error(error.message || "\u521B\u5EFA\u9884\u8BA2\u5931\u8D25");
|
|
1690
|
+
}
|
|
1691
|
+
return response.json();
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* 获取预订列表
|
|
1695
|
+
*
|
|
1696
|
+
* @param params 查询参数
|
|
1697
|
+
* @returns 预订列表和分页信息
|
|
1698
|
+
*/
|
|
1699
|
+
static async getBookings(params = {}) {
|
|
1700
|
+
const searchParams = new URLSearchParams();
|
|
1701
|
+
if (params.collectionId) {
|
|
1702
|
+
searchParams.append("collectionId", params.collectionId.toString());
|
|
1703
|
+
}
|
|
1704
|
+
if (params.qqNumber) {
|
|
1705
|
+
searchParams.append("qqNumber", params.qqNumber);
|
|
1706
|
+
}
|
|
1707
|
+
if (params.phoneNumber) {
|
|
1708
|
+
searchParams.append("phoneNumber", params.phoneNumber);
|
|
1709
|
+
}
|
|
1710
|
+
if (params.status) {
|
|
1711
|
+
searchParams.append("status", params.status);
|
|
1712
|
+
}
|
|
1713
|
+
if (params.page) {
|
|
1714
|
+
searchParams.append("page", params.page.toString());
|
|
1715
|
+
}
|
|
1716
|
+
if (params.limit) {
|
|
1717
|
+
searchParams.append("limit", params.limit.toString());
|
|
1718
|
+
}
|
|
1719
|
+
const url = `${this.BASE_URL}?${searchParams.toString()}`;
|
|
1720
|
+
const response = await fetch(url);
|
|
1721
|
+
if (!response.ok) {
|
|
1722
|
+
const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25" }));
|
|
1723
|
+
throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u5217\u8868\u5931\u8D25");
|
|
1724
|
+
}
|
|
1725
|
+
return response.json();
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* 获取单个预订详情
|
|
1729
|
+
*
|
|
1730
|
+
* @param id 预订ID
|
|
1731
|
+
* @returns 预订详情
|
|
1732
|
+
*/
|
|
1733
|
+
static async getBooking(id) {
|
|
1734
|
+
const response = await fetch(`${this.BASE_URL}/${id}`);
|
|
1735
|
+
if (!response.ok) {
|
|
1736
|
+
const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25" }));
|
|
1737
|
+
throw new Error(error.message || "\u83B7\u53D6\u9884\u8BA2\u8BE6\u60C5\u5931\u8D25");
|
|
1738
|
+
}
|
|
1739
|
+
return response.json();
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* 更新预订状态
|
|
1743
|
+
*
|
|
1744
|
+
* @param id 预订ID
|
|
1745
|
+
* @param data 更新数据
|
|
1746
|
+
* @returns 更新后的预订信息
|
|
1747
|
+
*/
|
|
1748
|
+
static async updateBooking(id, data) {
|
|
1749
|
+
const response = await fetch(`${this.BASE_URL}/${id}`, {
|
|
1750
|
+
method: "PUT",
|
|
1751
|
+
headers: {
|
|
1752
|
+
"Content-Type": "application/json"
|
|
1753
|
+
},
|
|
1754
|
+
body: JSON.stringify(data)
|
|
1755
|
+
});
|
|
1756
|
+
if (!response.ok) {
|
|
1757
|
+
const error = await response.json().catch(() => ({ message: "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25" }));
|
|
1758
|
+
throw new Error(error.message || "\u66F4\u65B0\u9884\u8BA2\u5931\u8D25");
|
|
1759
|
+
}
|
|
1760
|
+
return response.json();
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* 删除预订
|
|
1764
|
+
*
|
|
1765
|
+
* @param id 预订ID
|
|
1766
|
+
*/
|
|
1767
|
+
static async deleteBooking(id) {
|
|
1768
|
+
const response = await fetch(`${this.BASE_URL}/${id}`, {
|
|
1769
|
+
method: "DELETE"
|
|
1770
|
+
});
|
|
1771
|
+
if (!response.ok) {
|
|
1772
|
+
const error = await response.json().catch(() => ({ message: "\u5220\u9664\u9884\u8BA2\u5931\u8D25" }));
|
|
1773
|
+
throw new Error(error.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* 获取可预订的画集列表
|
|
1778
|
+
*
|
|
1779
|
+
* @returns 画集简略信息列表
|
|
1780
|
+
*/
|
|
1781
|
+
static async getBookableCollections() {
|
|
1782
|
+
const url = `${this.BASE_URL}/collections`;
|
|
1783
|
+
console.log("\u{1F4E1} [BookingService] \u83B7\u53D6\u53EF\u9884\u8BA2\u753B\u96C6:", { url });
|
|
1784
|
+
const response = await fetch(url);
|
|
1785
|
+
if (!response.ok) {
|
|
1786
|
+
const error = await response.json().catch(() => ({ message: "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25" }));
|
|
1787
|
+
throw new Error(error.message || "\u83B7\u53D6\u753B\u96C6\u5217\u8868\u5931\u8D25");
|
|
1788
|
+
}
|
|
1789
|
+
const data = await response.json();
|
|
1790
|
+
if (data.success && Array.isArray(data.data)) {
|
|
1791
|
+
console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6`);
|
|
1792
|
+
return data.data;
|
|
1793
|
+
}
|
|
1794
|
+
if (Array.isArray(data)) {
|
|
1795
|
+
console.log(`\u2705 [BookingService] \u83B7\u53D6\u5230 ${data.length} \u4E2A\u53EF\u9884\u8BA2\u753B\u96C6 (\u517C\u5BB9\u683C\u5F0F)`);
|
|
1796
|
+
return data;
|
|
1797
|
+
}
|
|
1798
|
+
throw new Error("API\u54CD\u5E94\u683C\u5F0F\u9519\u8BEF");
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
BookingService.BASE_URL = "/api/showmasterpiece/bookings";
|
|
1802
|
+
createBooking = (data) => {
|
|
1803
|
+
return BookingService.createBooking(data);
|
|
1804
|
+
};
|
|
1805
|
+
getBookings = (params) => {
|
|
1806
|
+
return BookingService.getBookings(params);
|
|
1807
|
+
};
|
|
1808
|
+
getBooking = (id) => {
|
|
1809
|
+
return BookingService.getBooking(id);
|
|
1810
|
+
};
|
|
1811
|
+
updateBooking = (id, data) => {
|
|
1812
|
+
return BookingService.updateBooking(id, data);
|
|
1813
|
+
};
|
|
1814
|
+
deleteBooking = (id) => {
|
|
1815
|
+
return BookingService.deleteBooking(id);
|
|
1816
|
+
};
|
|
1817
|
+
getBookableCollections = () => {
|
|
1818
|
+
return BookingService.getBookableCollections();
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
});
|
|
1822
|
+
function useBooking(_props = {}) {
|
|
1823
|
+
const [state, setState] = useState({
|
|
1824
|
+
collections: [],
|
|
1825
|
+
loading: false,
|
|
1826
|
+
error: void 0,
|
|
1827
|
+
submitting: false,
|
|
1828
|
+
submitted: false
|
|
1829
|
+
});
|
|
1830
|
+
const loadCollections = useCallback(async () => {
|
|
1831
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
1832
|
+
try {
|
|
1833
|
+
console.log("\u{1F504} [useBooking] \u52A0\u8F7D\u753B\u96C6\u5217\u8868...");
|
|
1834
|
+
const collections = await getBookableCollections();
|
|
1835
|
+
setState((prev) => ({
|
|
1836
|
+
...prev,
|
|
1837
|
+
collections,
|
|
1838
|
+
loading: false
|
|
1839
|
+
}));
|
|
1840
|
+
} catch (error) {
|
|
1841
|
+
console.error("\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25:", error);
|
|
1842
|
+
setState((prev) => ({
|
|
1843
|
+
...prev,
|
|
1844
|
+
loading: false,
|
|
1845
|
+
error: error instanceof Error ? error.message : "\u52A0\u8F7D\u753B\u96C6\u5217\u8868\u5931\u8D25"
|
|
1846
|
+
}));
|
|
1847
|
+
}
|
|
1848
|
+
}, []);
|
|
1849
|
+
const submitBooking = useCallback(async (formData) => {
|
|
1850
|
+
setState((prev) => ({ ...prev, submitting: true, error: void 0 }));
|
|
1851
|
+
try {
|
|
1852
|
+
const bookingData = {
|
|
1853
|
+
collectionId: formData.collectionId,
|
|
1854
|
+
qqNumber: formData.qqNumber,
|
|
1855
|
+
phoneNumber: formData.phoneNumber.trim(),
|
|
1856
|
+
quantity: formData.quantity,
|
|
1857
|
+
notes: formData.notes || void 0
|
|
1858
|
+
};
|
|
1859
|
+
await createBooking(bookingData);
|
|
1860
|
+
setState((prev) => ({
|
|
1861
|
+
...prev,
|
|
1862
|
+
submitting: false,
|
|
1863
|
+
submitted: true
|
|
1864
|
+
}));
|
|
1865
|
+
} catch (error) {
|
|
1866
|
+
console.error("\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25:", error);
|
|
1867
|
+
setState((prev) => ({
|
|
1868
|
+
...prev,
|
|
1869
|
+
submitting: false,
|
|
1870
|
+
error: error instanceof Error ? error.message : "\u63D0\u4EA4\u9884\u8BA2\u5931\u8D25"
|
|
1871
|
+
}));
|
|
1872
|
+
}
|
|
1873
|
+
}, []);
|
|
1874
|
+
const resetSubmission = useCallback(() => {
|
|
1875
|
+
setState((prev) => ({
|
|
1876
|
+
...prev,
|
|
1877
|
+
submitted: false,
|
|
1878
|
+
error: void 0
|
|
1879
|
+
}));
|
|
1880
|
+
}, []);
|
|
1881
|
+
const clearError = useCallback(() => {
|
|
1882
|
+
setState((prev) => ({ ...prev, error: void 0 }));
|
|
1883
|
+
}, []);
|
|
1884
|
+
useEffect(() => {
|
|
1885
|
+
loadCollections();
|
|
1886
|
+
}, [loadCollections]);
|
|
1887
|
+
return {
|
|
1888
|
+
// 状态
|
|
1889
|
+
collections: state.collections,
|
|
1890
|
+
loading: state.loading,
|
|
1891
|
+
error: state.error,
|
|
1892
|
+
submitting: state.submitting,
|
|
1893
|
+
submitted: state.submitted,
|
|
1894
|
+
// 操作方法
|
|
1895
|
+
loadCollections,
|
|
1896
|
+
submitBooking,
|
|
1897
|
+
resetSubmission,
|
|
1898
|
+
clearError
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
function useBookingForm() {
|
|
1902
|
+
const [formData, setFormData] = useState({
|
|
1903
|
+
collectionId: 0,
|
|
1904
|
+
qqNumber: "",
|
|
1905
|
+
phoneNumber: "",
|
|
1906
|
+
quantity: 1,
|
|
1907
|
+
notes: ""
|
|
1908
|
+
});
|
|
1909
|
+
const [errors, setErrors] = useState({});
|
|
1910
|
+
const updateField = useCallback((field, value) => {
|
|
1911
|
+
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
1912
|
+
if (errors[field]) {
|
|
1913
|
+
setErrors((prev) => ({ ...prev, [field]: void 0 }));
|
|
1914
|
+
}
|
|
1915
|
+
}, [errors]);
|
|
1916
|
+
const validateForm = useCallback(() => {
|
|
1917
|
+
const newErrors = {};
|
|
1918
|
+
if (!formData.collectionId) {
|
|
1919
|
+
newErrors.collectionId = "\u8BF7\u9009\u62E9\u8981\u9884\u8BA2\u7684\u753B\u96C6";
|
|
1920
|
+
}
|
|
1921
|
+
if (!formData.qqNumber.trim()) {
|
|
1922
|
+
newErrors.qqNumber = "\u8BF7\u8F93\u5165QQ\u53F7";
|
|
1923
|
+
} else if (!/^\d{5,11}$/.test(formData.qqNumber.trim())) {
|
|
1924
|
+
newErrors.qqNumber = "QQ\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
|
|
1925
|
+
}
|
|
1926
|
+
if (formData.phoneNumber.trim()) {
|
|
1927
|
+
const phoneRegex = /^1[3-9]\d{9}$/;
|
|
1928
|
+
if (!phoneRegex.test(formData.phoneNumber.trim())) {
|
|
1929
|
+
newErrors.phoneNumber = "\u624B\u673A\u53F7\u683C\u5F0F\u4E0D\u6B63\u786E";
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
if (!formData.quantity || formData.quantity < 1) {
|
|
1933
|
+
newErrors.quantity = "\u9884\u8BA2\u6570\u91CF\u5FC5\u987B\u5927\u4E8E0";
|
|
1934
|
+
}
|
|
1935
|
+
setErrors(newErrors);
|
|
1936
|
+
return Object.keys(newErrors).length === 0;
|
|
1937
|
+
}, [formData]);
|
|
1938
|
+
const resetForm = useCallback(() => {
|
|
1939
|
+
setFormData({
|
|
1940
|
+
collectionId: 0,
|
|
1941
|
+
qqNumber: "",
|
|
1942
|
+
phoneNumber: "",
|
|
1943
|
+
quantity: 1,
|
|
1944
|
+
notes: ""
|
|
1945
|
+
});
|
|
1946
|
+
setErrors({});
|
|
1947
|
+
}, []);
|
|
1948
|
+
return {
|
|
1949
|
+
formData,
|
|
1950
|
+
errors,
|
|
1951
|
+
updateField,
|
|
1952
|
+
validateForm,
|
|
1953
|
+
resetForm
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
var init_useBooking = __esm({
|
|
1957
|
+
"src/showmasterpiece/logic/hooks/useBooking.ts"() {
|
|
1958
|
+
init_bookingService();
|
|
1959
|
+
}
|
|
1960
|
+
});
|
|
1961
|
+
|
|
1962
|
+
// src/showmasterpiece/services/bookingAdminService.ts
|
|
1963
|
+
var BookingAdminService, getAllBookings, getBookingStats, forceRefreshAllBookings, forceRefreshBookingStats, updateBookingStatus2, deleteBooking2, exportBookings;
|
|
1964
|
+
var init_bookingAdminService = __esm({
|
|
1965
|
+
"src/showmasterpiece/services/bookingAdminService.ts"() {
|
|
1966
|
+
BookingAdminService = class {
|
|
1967
|
+
/**
|
|
1968
|
+
* 获取所有预订数据
|
|
1969
|
+
*/
|
|
1970
|
+
static async getAllBookings(params) {
|
|
1971
|
+
try {
|
|
1972
|
+
const timestamp = Date.now();
|
|
1973
|
+
const randomId = Math.random().toString(36).substring(7);
|
|
1974
|
+
const searchParams = new URLSearchParams();
|
|
1975
|
+
searchParams.append("t", timestamp.toString());
|
|
1976
|
+
searchParams.append("forceRefresh", randomId);
|
|
1977
|
+
if (params?.qqNumber) {
|
|
1978
|
+
searchParams.append("qqNumber", params.qqNumber);
|
|
1979
|
+
}
|
|
1980
|
+
if (params?.phoneNumber) {
|
|
1981
|
+
searchParams.append("phoneNumber", params.phoneNumber);
|
|
1982
|
+
}
|
|
1983
|
+
if (params?.status && params.status !== "all") {
|
|
1984
|
+
searchParams.append("status", params.status);
|
|
1985
|
+
}
|
|
1986
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
|
|
1987
|
+
method: "GET",
|
|
1988
|
+
cache: "no-store",
|
|
1989
|
+
headers: {
|
|
1990
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
1991
|
+
"Pragma": "no-cache",
|
|
1992
|
+
"Expires": "0",
|
|
1993
|
+
"X-Requested-With": "XMLHttpRequest"
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
if (!response.ok) {
|
|
1997
|
+
throw new Error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
|
|
1998
|
+
}
|
|
1999
|
+
const data = await response.json();
|
|
2000
|
+
return data.bookings || [];
|
|
2001
|
+
} catch (error) {
|
|
2002
|
+
console.error("\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
|
|
2003
|
+
throw error;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* 强制刷新获取所有预订数据(绕过所有缓存)
|
|
2008
|
+
*/
|
|
2009
|
+
static async forceRefreshAllBookings(params) {
|
|
2010
|
+
try {
|
|
2011
|
+
console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u9884\u8BA2\u6570\u636E...");
|
|
2012
|
+
const timestamp = Date.now();
|
|
2013
|
+
const randomId = Math.random().toString(36).substring(7);
|
|
2014
|
+
const searchParams = new URLSearchParams();
|
|
2015
|
+
searchParams.append("t", timestamp.toString());
|
|
2016
|
+
searchParams.append("forceRefresh", randomId);
|
|
2017
|
+
if (params?.qqNumber) {
|
|
2018
|
+
searchParams.append("qqNumber", params.qqNumber);
|
|
2019
|
+
}
|
|
2020
|
+
if (params?.phoneNumber) {
|
|
2021
|
+
searchParams.append("phoneNumber", params.phoneNumber);
|
|
2022
|
+
}
|
|
2023
|
+
if (params?.status && params.status !== "all") {
|
|
2024
|
+
searchParams.append("status", params.status);
|
|
2025
|
+
}
|
|
2026
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
|
|
2027
|
+
method: "GET",
|
|
2028
|
+
cache: "no-store",
|
|
2029
|
+
headers: {
|
|
2030
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
2031
|
+
"Pragma": "no-cache",
|
|
2032
|
+
"Expires": "0",
|
|
2033
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
2034
|
+
"X-Force-Refresh": "true"
|
|
2035
|
+
}
|
|
2036
|
+
});
|
|
2037
|
+
if (!response.ok) {
|
|
2038
|
+
throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25");
|
|
2039
|
+
}
|
|
2040
|
+
const data = await response.json();
|
|
2041
|
+
console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0API\u54CD\u5E94:", {
|
|
2042
|
+
bookingsCount: data.bookings?.length || 0,
|
|
2043
|
+
timestamp: data._timestamp,
|
|
2044
|
+
refreshType: data._refreshType
|
|
2045
|
+
});
|
|
2046
|
+
return data.bookings || [];
|
|
2047
|
+
} catch (error) {
|
|
2048
|
+
console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
|
|
2049
|
+
throw error;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
/**
|
|
2053
|
+
* 获取预订统计信息
|
|
2054
|
+
*/
|
|
2055
|
+
static async getBookingStats(params) {
|
|
2056
|
+
try {
|
|
2057
|
+
const timestamp = Date.now();
|
|
2058
|
+
const randomId = Math.random().toString(36).substring(7);
|
|
2059
|
+
const searchParams = new URLSearchParams();
|
|
2060
|
+
searchParams.append("t", timestamp.toString());
|
|
2061
|
+
searchParams.append("forceRefresh", randomId);
|
|
2062
|
+
if (params?.qqNumber) {
|
|
2063
|
+
searchParams.append("qqNumber", params.qqNumber);
|
|
2064
|
+
}
|
|
2065
|
+
if (params?.phoneNumber) {
|
|
2066
|
+
searchParams.append("phoneNumber", params.phoneNumber);
|
|
2067
|
+
}
|
|
2068
|
+
if (params?.status && params.status !== "all") {
|
|
2069
|
+
searchParams.append("status", params.status);
|
|
2070
|
+
}
|
|
2071
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin?${searchParams.toString()}`, {
|
|
2072
|
+
method: "GET",
|
|
2073
|
+
cache: "no-store",
|
|
2074
|
+
headers: {
|
|
2075
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
2076
|
+
"Pragma": "no-cache",
|
|
2077
|
+
"Expires": "0",
|
|
2078
|
+
"X-Requested-With": "XMLHttpRequest"
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
2081
|
+
if (!response.ok) {
|
|
2082
|
+
throw new Error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
|
|
2083
|
+
}
|
|
2084
|
+
const data = await response.json();
|
|
2085
|
+
return data.stats || {
|
|
2086
|
+
totalBookings: 0,
|
|
2087
|
+
pendingBookings: 0,
|
|
2088
|
+
confirmedBookings: 0,
|
|
2089
|
+
completedBookings: 0,
|
|
2090
|
+
cancelledBookings: 0,
|
|
2091
|
+
totalQuantity: 0,
|
|
2092
|
+
totalRevenue: 0,
|
|
2093
|
+
totalAmount: 0,
|
|
2094
|
+
todayBookings: 0,
|
|
2095
|
+
weekBookings: 0
|
|
2096
|
+
};
|
|
2097
|
+
} catch (error) {
|
|
2098
|
+
console.error("\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
|
|
2099
|
+
throw error;
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* 强制刷新获取预订统计信息(绕过所有缓存)
|
|
2104
|
+
*/
|
|
2105
|
+
static async forceRefreshBookingStats(params) {
|
|
2106
|
+
try {
|
|
2107
|
+
console.log("\u{1F504} \u4F7F\u7528\u5F3A\u5236\u5237\u65B0API\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F...");
|
|
2108
|
+
const timestamp = Date.now();
|
|
2109
|
+
const randomId = Math.random().toString(36).substring(7);
|
|
2110
|
+
const searchParams = new URLSearchParams();
|
|
2111
|
+
searchParams.append("t", timestamp.toString());
|
|
2112
|
+
searchParams.append("forceRefresh", randomId);
|
|
2113
|
+
if (params?.qqNumber) {
|
|
2114
|
+
searchParams.append("qqNumber", params.qqNumber);
|
|
2115
|
+
}
|
|
2116
|
+
if (params?.phoneNumber) {
|
|
2117
|
+
searchParams.append("phoneNumber", params.phoneNumber);
|
|
2118
|
+
}
|
|
2119
|
+
if (params?.status && params.status !== "all") {
|
|
2120
|
+
searchParams.append("status", params.status);
|
|
2121
|
+
}
|
|
2122
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin/refresh?${searchParams.toString()}`, {
|
|
2123
|
+
method: "GET",
|
|
2124
|
+
cache: "no-store",
|
|
2125
|
+
headers: {
|
|
2126
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
2127
|
+
"Pragma": "no-cache",
|
|
2128
|
+
"Expires": "0",
|
|
2129
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
2130
|
+
"X-Force-Refresh": "true"
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2133
|
+
if (!response.ok) {
|
|
2134
|
+
throw new Error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25");
|
|
2135
|
+
}
|
|
2136
|
+
const data = await response.json();
|
|
2137
|
+
console.log("\u{1F504} \u5F3A\u5236\u5237\u65B0\u7EDF\u8BA1\u4FE1\u606F\u54CD\u5E94:", {
|
|
2138
|
+
stats: data.stats,
|
|
2139
|
+
timestamp: data._timestamp,
|
|
2140
|
+
refreshType: data._refreshType
|
|
2141
|
+
});
|
|
2142
|
+
return data.stats || {
|
|
2143
|
+
totalBookings: 0,
|
|
2144
|
+
pendingBookings: 0,
|
|
2145
|
+
confirmedBookings: 0,
|
|
2146
|
+
completedBookings: 0,
|
|
2147
|
+
cancelledBookings: 0,
|
|
2148
|
+
totalQuantity: 0,
|
|
2149
|
+
totalRevenue: 0,
|
|
2150
|
+
totalAmount: 0,
|
|
2151
|
+
todayBookings: 0,
|
|
2152
|
+
weekBookings: 0
|
|
2153
|
+
};
|
|
2154
|
+
} catch (error) {
|
|
2155
|
+
console.error("\u5F3A\u5236\u5237\u65B0\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:", error);
|
|
2156
|
+
throw error;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* 更新预订状态
|
|
2161
|
+
*/
|
|
2162
|
+
static async updateBookingStatus(bookingId, status, adminNotes) {
|
|
2163
|
+
try {
|
|
2164
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}/status`, {
|
|
2165
|
+
method: "PUT",
|
|
2166
|
+
headers: {
|
|
2167
|
+
"Content-Type": "application/json"
|
|
2168
|
+
},
|
|
2169
|
+
body: JSON.stringify({ status, adminNotes })
|
|
2170
|
+
});
|
|
2171
|
+
if (!response.ok) {
|
|
2172
|
+
throw new Error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25");
|
|
2173
|
+
}
|
|
2174
|
+
} catch (error) {
|
|
2175
|
+
console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", error);
|
|
2176
|
+
throw error;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* 删除预订
|
|
2181
|
+
*/
|
|
2182
|
+
static async deleteBooking(bookingId) {
|
|
2183
|
+
try {
|
|
2184
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin/${bookingId}`, {
|
|
2185
|
+
method: "DELETE",
|
|
2186
|
+
headers: {
|
|
2187
|
+
"Content-Type": "application/json"
|
|
2188
|
+
}
|
|
2189
|
+
});
|
|
2190
|
+
if (!response.ok) {
|
|
2191
|
+
const errorData = await response.json().catch(() => ({}));
|
|
2192
|
+
throw new Error(errorData.message || "\u5220\u9664\u9884\u8BA2\u5931\u8D25");
|
|
2193
|
+
}
|
|
2194
|
+
console.log("\u2705 \u9884\u8BA2\u5220\u9664\u6210\u529F:", { bookingId });
|
|
2195
|
+
} catch (error) {
|
|
2196
|
+
console.error("\u5220\u9664\u9884\u8BA2\u5931\u8D25:", error);
|
|
2197
|
+
throw error;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* 导出预订数据
|
|
2202
|
+
*/
|
|
2203
|
+
static async exportBookings(format = "csv") {
|
|
2204
|
+
try {
|
|
2205
|
+
const response = await fetch(`/api/showmasterpiece/bookings/admin/export?format=${format}`);
|
|
2206
|
+
if (!response.ok) {
|
|
2207
|
+
throw new Error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25");
|
|
2208
|
+
}
|
|
2209
|
+
return await response.blob();
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
console.error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25:", error);
|
|
2212
|
+
throw error;
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
};
|
|
2216
|
+
getAllBookings = BookingAdminService.getAllBookings;
|
|
2217
|
+
getBookingStats = BookingAdminService.getBookingStats;
|
|
2218
|
+
forceRefreshAllBookings = BookingAdminService.forceRefreshAllBookings;
|
|
2219
|
+
forceRefreshBookingStats = BookingAdminService.forceRefreshBookingStats;
|
|
2220
|
+
updateBookingStatus2 = BookingAdminService.updateBookingStatus;
|
|
2221
|
+
deleteBooking2 = BookingAdminService.deleteBooking;
|
|
2222
|
+
exportBookings = BookingAdminService.exportBookings;
|
|
2223
|
+
}
|
|
2224
|
+
});
|
|
2225
|
+
var useBookingAdmin;
|
|
2226
|
+
var init_useBookingAdmin = __esm({
|
|
2227
|
+
"src/showmasterpiece/logic/hooks/useBookingAdmin.ts"() {
|
|
2228
|
+
init_bookingAdminService();
|
|
2229
|
+
useBookingAdmin = () => {
|
|
2230
|
+
const [bookings, setBookings] = useState([]);
|
|
2231
|
+
const [stats, setStats] = useState({
|
|
2232
|
+
totalBookings: 0,
|
|
2233
|
+
pendingBookings: 0,
|
|
2234
|
+
confirmedBookings: 0,
|
|
2235
|
+
completedBookings: 0,
|
|
2236
|
+
cancelledBookings: 0,
|
|
2237
|
+
totalQuantity: 0,
|
|
2238
|
+
totalRevenue: 0,
|
|
2239
|
+
totalAmount: 0,
|
|
2240
|
+
todayBookings: 0,
|
|
2241
|
+
weekBookings: 0
|
|
2242
|
+
});
|
|
2243
|
+
const [loading, setLoading] = useState(true);
|
|
2244
|
+
const [error, setError] = useState(void 0);
|
|
2245
|
+
const [searchParams, setSearchParams] = useState({});
|
|
2246
|
+
const fetchBookings = useCallback(async (params) => {
|
|
2247
|
+
try {
|
|
2248
|
+
setLoading(true);
|
|
2249
|
+
setError(void 0);
|
|
2250
|
+
const queryParams = params || searchParams;
|
|
2251
|
+
console.log("\u{1F504} \u5F00\u59CB\u83B7\u53D6\u9884\u8BA2\u6570\u636E...", {
|
|
2252
|
+
searchParams: queryParams
|
|
2253
|
+
});
|
|
2254
|
+
const [bookingsData, statsData] = await Promise.all([
|
|
2255
|
+
getAllBookings(queryParams),
|
|
2256
|
+
getBookingStats(queryParams)
|
|
2257
|
+
]);
|
|
2258
|
+
console.log("\u2705 \u83B7\u53D6\u5230\u9884\u8BA2\u6570\u636E:", {
|
|
2259
|
+
bookingsCount: bookingsData.length,
|
|
2260
|
+
stats: statsData,
|
|
2261
|
+
searchParams: queryParams,
|
|
2262
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2263
|
+
});
|
|
2264
|
+
setBookings(bookingsData);
|
|
2265
|
+
setStats(statsData);
|
|
2266
|
+
} catch (err) {
|
|
2267
|
+
const errorMessage = err instanceof Error ? err.message : "\u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25";
|
|
2268
|
+
setError(errorMessage);
|
|
2269
|
+
console.error("\u274C \u83B7\u53D6\u9884\u8BA2\u6570\u636E\u5931\u8D25:", err);
|
|
2270
|
+
} finally {
|
|
2271
|
+
setLoading(false);
|
|
2272
|
+
}
|
|
2273
|
+
}, [searchParams]);
|
|
2274
|
+
const searchBookings = useCallback(async (params) => {
|
|
2275
|
+
setSearchParams(params);
|
|
2276
|
+
await fetchBookings(params);
|
|
2277
|
+
}, [fetchBookings]);
|
|
2278
|
+
const clearSearch = useCallback(async () => {
|
|
2279
|
+
const emptyParams = {};
|
|
2280
|
+
setSearchParams(emptyParams);
|
|
2281
|
+
await fetchBookings(emptyParams);
|
|
2282
|
+
}, [fetchBookings]);
|
|
2283
|
+
const updateBookingStatus3 = useCallback(async (id, status, adminNotes) => {
|
|
2284
|
+
try {
|
|
2285
|
+
setError(void 0);
|
|
2286
|
+
console.log("\u5F00\u59CB\u66F4\u65B0\u9884\u8BA2\u72B6\u6001:", { id, status, adminNotes });
|
|
2287
|
+
await updateBookingStatus2(id, status, adminNotes);
|
|
2288
|
+
console.log("\u9884\u8BA2\u72B6\u6001\u66F4\u65B0\u6210\u529F");
|
|
2289
|
+
await fetchBookings();
|
|
2290
|
+
} catch (err) {
|
|
2291
|
+
const errorMessage = err instanceof Error ? err.message : "\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25";
|
|
2292
|
+
setError(errorMessage);
|
|
2293
|
+
console.error("\u66F4\u65B0\u9884\u8BA2\u72B6\u6001\u5931\u8D25:", err);
|
|
2294
|
+
throw err;
|
|
2295
|
+
}
|
|
2296
|
+
}, [fetchBookings]);
|
|
2297
|
+
const deleteBooking3 = useCallback(async (id) => {
|
|
2298
|
+
try {
|
|
2299
|
+
setError(void 0);
|
|
2300
|
+
console.log("\u5F00\u59CB\u5220\u9664\u9884\u8BA2:", { id });
|
|
2301
|
+
await deleteBooking2(id);
|
|
2302
|
+
console.log("\u9884\u8BA2\u5220\u9664\u6210\u529F");
|
|
2303
|
+
await fetchBookings();
|
|
2304
|
+
} catch (err) {
|
|
2305
|
+
const errorMessage = err instanceof Error ? err.message : "\u5220\u9664\u9884\u8BA2\u5931\u8D25";
|
|
2306
|
+
setError(errorMessage);
|
|
2307
|
+
console.error("\u5220\u9664\u9884\u8BA2\u5931\u8D25:", err);
|
|
2308
|
+
throw err;
|
|
2309
|
+
}
|
|
2310
|
+
}, [fetchBookings]);
|
|
2311
|
+
const exportBookings2 = useCallback(async (format = "csv") => {
|
|
2312
|
+
try {
|
|
2313
|
+
setError(void 0);
|
|
2314
|
+
console.log("\u5F00\u59CB\u5BFC\u51FA\u9884\u8BA2\u6570\u636E:", { format });
|
|
2315
|
+
const blob = await exportBookings(format);
|
|
2316
|
+
const url = window.URL.createObjectURL(blob);
|
|
2317
|
+
const link = document.createElement("a");
|
|
2318
|
+
link.href = url;
|
|
2319
|
+
link.download = `\u9884\u8BA2\u4FE1\u606F_${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.${format}`;
|
|
2320
|
+
document.body.appendChild(link);
|
|
2321
|
+
link.click();
|
|
2322
|
+
document.body.removeChild(link);
|
|
2323
|
+
window.URL.revokeObjectURL(url);
|
|
2324
|
+
console.log("\u9884\u8BA2\u6570\u636E\u5BFC\u51FA\u6210\u529F");
|
|
2325
|
+
} catch (err) {
|
|
2326
|
+
const errorMessage = err instanceof Error ? err.message : "\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25";
|
|
2327
|
+
setError(errorMessage);
|
|
2328
|
+
console.error("\u5BFC\u51FA\u9884\u8BA2\u6570\u636E\u5931\u8D25:", err);
|
|
2329
|
+
throw err;
|
|
2330
|
+
}
|
|
2331
|
+
}, []);
|
|
2332
|
+
const refreshData = useCallback(async () => {
|
|
2333
|
+
await fetchBookings();
|
|
2334
|
+
}, [fetchBookings]);
|
|
2335
|
+
const clearError = useCallback(() => {
|
|
2336
|
+
setError(void 0);
|
|
2337
|
+
}, []);
|
|
2338
|
+
useEffect(() => {
|
|
2339
|
+
fetchBookings();
|
|
2340
|
+
}, []);
|
|
2341
|
+
return {
|
|
2342
|
+
bookings,
|
|
2343
|
+
stats,
|
|
2344
|
+
loading,
|
|
2345
|
+
error,
|
|
2346
|
+
searchParams,
|
|
2347
|
+
refreshData,
|
|
2348
|
+
searchBookings,
|
|
2349
|
+
clearSearch,
|
|
2350
|
+
updateBookingStatus: updateBookingStatus3,
|
|
2351
|
+
deleteBooking: deleteBooking3,
|
|
2352
|
+
exportBookings: exportBookings2,
|
|
2353
|
+
clearError
|
|
2354
|
+
};
|
|
2355
|
+
};
|
|
2356
|
+
}
|
|
2357
|
+
});
|
|
2358
|
+
function useDeadlinePopup(businessModule = "showmasterpiece", businessScene = "cart_checkout") {
|
|
2359
|
+
const [state, setState] = useState({
|
|
2360
|
+
configs: [],
|
|
2361
|
+
loading: false,
|
|
2362
|
+
error: null,
|
|
2363
|
+
hasPopup: false
|
|
2364
|
+
});
|
|
2365
|
+
const [dismissedPopups, setDismissedPopups] = useState(/* @__PURE__ */ new Set());
|
|
2366
|
+
const checkPopups = useCallback(async (currentTime) => {
|
|
2367
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
2368
|
+
try {
|
|
2369
|
+
const response = await fetch("/api/showmasterpiece/popup-configs/check", {
|
|
2370
|
+
method: "POST",
|
|
2371
|
+
headers: {
|
|
2372
|
+
"Content-Type": "application/json"
|
|
2373
|
+
},
|
|
2374
|
+
body: JSON.stringify({
|
|
2375
|
+
businessModule,
|
|
2376
|
+
businessScene,
|
|
2377
|
+
currentTime: (currentTime || /* @__PURE__ */ new Date()).toISOString()
|
|
2378
|
+
})
|
|
2379
|
+
});
|
|
2380
|
+
if (!response.ok) {
|
|
2381
|
+
throw new Error("\u68C0\u67E5\u5F39\u7A97\u914D\u7F6E\u5931\u8D25");
|
|
2382
|
+
}
|
|
2383
|
+
const result = await response.json();
|
|
2384
|
+
const configs = result.configs || [];
|
|
2385
|
+
const activeConfigs = configs.filter((config) => !dismissedPopups.has(config.id));
|
|
2386
|
+
setState((prev) => ({
|
|
2387
|
+
...prev,
|
|
2388
|
+
configs: activeConfigs,
|
|
2389
|
+
loading: false,
|
|
2390
|
+
hasPopup: activeConfigs.length > 0
|
|
2391
|
+
}));
|
|
2392
|
+
console.log(`\u{1F514} [useDeadlinePopup] \u68C0\u67E5\u5230 ${activeConfigs.length} \u4E2A\u9700\u8981\u663E\u793A\u7684\u5F39\u7A97`);
|
|
2393
|
+
return activeConfigs;
|
|
2394
|
+
} catch (error) {
|
|
2395
|
+
console.error("\u274C [useDeadlinePopup] \u68C0\u67E5\u5F39\u7A97\u5931\u8D25:", error);
|
|
2396
|
+
setState((prev) => ({
|
|
2397
|
+
...prev,
|
|
2398
|
+
loading: false,
|
|
2399
|
+
error: error instanceof Error ? error.message : "\u68C0\u67E5\u5F39\u7A97\u5931\u8D25",
|
|
2400
|
+
configs: [],
|
|
2401
|
+
hasPopup: false
|
|
2402
|
+
}));
|
|
2403
|
+
return [];
|
|
2404
|
+
}
|
|
2405
|
+
}, [businessModule, businessScene, dismissedPopups]);
|
|
2406
|
+
const closePopup = useCallback((configId) => {
|
|
2407
|
+
setDismissedPopups((prev) => /* @__PURE__ */ new Set([...prev, configId]));
|
|
2408
|
+
setState((prev) => {
|
|
2409
|
+
const remainingConfigs = prev.configs.filter((config) => config.id !== configId);
|
|
2410
|
+
return {
|
|
2411
|
+
...prev,
|
|
2412
|
+
configs: remainingConfigs,
|
|
2413
|
+
hasPopup: remainingConfigs.length > 0
|
|
2414
|
+
};
|
|
2415
|
+
});
|
|
2416
|
+
console.log(`\u2705 [useDeadlinePopup] \u5F39\u7A97\u5DF2\u5173\u95ED:`, configId);
|
|
2417
|
+
}, []);
|
|
2418
|
+
const confirmPopup = useCallback((configId) => {
|
|
2419
|
+
console.log(`\u2705 [useDeadlinePopup] \u5F39\u7A97\u5DF2\u786E\u8BA4:`, configId);
|
|
2420
|
+
closePopup(configId);
|
|
2421
|
+
}, [closePopup]);
|
|
2422
|
+
const cancelPopup = useCallback((configId) => {
|
|
2423
|
+
console.log(`\u274C [useDeadlinePopup] \u5F39\u7A97\u5DF2\u53D6\u6D88:`, configId);
|
|
2424
|
+
closePopup(configId);
|
|
2425
|
+
}, [closePopup]);
|
|
2426
|
+
const temporaryClosePopup = useCallback((configId) => {
|
|
2427
|
+
setState((prev) => {
|
|
2428
|
+
const remainingConfigs = prev.configs.filter((config) => config.id !== configId);
|
|
2429
|
+
return {
|
|
2430
|
+
...prev,
|
|
2431
|
+
configs: remainingConfigs,
|
|
2432
|
+
hasPopup: remainingConfigs.length > 0
|
|
2433
|
+
};
|
|
2434
|
+
});
|
|
2435
|
+
console.log(`\u23F8\uFE0F [useDeadlinePopup] \u5F39\u7A97\u4E34\u65F6\u5173\u95ED:`, configId);
|
|
2436
|
+
}, []);
|
|
2437
|
+
const resetDismissedPopups = useCallback(() => {
|
|
2438
|
+
setDismissedPopups(/* @__PURE__ */ new Set());
|
|
2439
|
+
console.log("\u{1F504} [useDeadlinePopup] \u5DF2\u91CD\u7F6E\u5F39\u7A97\u5173\u95ED\u8BB0\u5F55");
|
|
2440
|
+
}, []);
|
|
2441
|
+
const triggerCheck = useCallback(async (currentTime) => {
|
|
2442
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
2443
|
+
try {
|
|
2444
|
+
const response = await fetch("/api/showmasterpiece/popup-configs/check", {
|
|
2445
|
+
method: "POST",
|
|
2446
|
+
headers: {
|
|
2447
|
+
"Content-Type": "application/json"
|
|
2448
|
+
},
|
|
2449
|
+
body: JSON.stringify({
|
|
2450
|
+
businessModule,
|
|
2451
|
+
businessScene,
|
|
2452
|
+
currentTime: (currentTime || /* @__PURE__ */ new Date()).toISOString()
|
|
2453
|
+
})
|
|
2454
|
+
});
|
|
2455
|
+
if (!response.ok) {
|
|
2456
|
+
throw new Error("\u68C0\u67E5\u5F39\u7A97\u914D\u7F6E\u5931\u8D25");
|
|
2457
|
+
}
|
|
2458
|
+
const result = await response.json();
|
|
2459
|
+
const configs = result.configs || [];
|
|
2460
|
+
const activeConfigs = configs.filter((config) => {
|
|
2461
|
+
if (config.blockProcess) {
|
|
2462
|
+
return true;
|
|
2463
|
+
} else {
|
|
2464
|
+
return !dismissedPopups.has(config.id);
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
setState((prev) => ({
|
|
2468
|
+
...prev,
|
|
2469
|
+
configs: activeConfigs,
|
|
2470
|
+
loading: false,
|
|
2471
|
+
hasPopup: activeConfigs.length > 0
|
|
2472
|
+
}));
|
|
2473
|
+
console.log(`\u{1F514} [useDeadlinePopup] \u624B\u52A8\u68C0\u67E5\u5230 ${activeConfigs.length} \u4E2A\u9700\u8981\u663E\u793A\u7684\u5F39\u7A97\uFF08\u963B\u65AD\u5F39\u7A97\u4E0D\u53D7dismissedPopups\u9650\u5236\uFF09`);
|
|
2474
|
+
return activeConfigs;
|
|
2475
|
+
} catch (error) {
|
|
2476
|
+
console.error("\u274C [useDeadlinePopup] \u624B\u52A8\u68C0\u67E5\u5F39\u7A97\u5931\u8D25:", error);
|
|
2477
|
+
setState((prev) => ({
|
|
2478
|
+
...prev,
|
|
2479
|
+
loading: false,
|
|
2480
|
+
error: error instanceof Error ? error.message : "\u68C0\u67E5\u5F39\u7A97\u5931\u8D25",
|
|
2481
|
+
configs: [],
|
|
2482
|
+
hasPopup: false
|
|
2483
|
+
}));
|
|
2484
|
+
return [];
|
|
2485
|
+
}
|
|
2486
|
+
}, [businessModule, businessScene, dismissedPopups]);
|
|
2487
|
+
return {
|
|
2488
|
+
...state,
|
|
2489
|
+
checkPopups,
|
|
2490
|
+
closePopup,
|
|
2491
|
+
confirmPopup,
|
|
2492
|
+
cancelPopup,
|
|
2493
|
+
temporaryClosePopup,
|
|
2494
|
+
resetDismissedPopups,
|
|
2495
|
+
triggerCheck
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
var init_useDeadlinePopup = __esm({
|
|
2499
|
+
"src/showmasterpiece/logic/hooks/useDeadlinePopup.ts"() {
|
|
2500
|
+
"use client";
|
|
2501
|
+
}
|
|
2502
|
+
});
|
|
2503
|
+
var useCartContext;
|
|
2504
|
+
var init_useCartContext = __esm({
|
|
2505
|
+
"src/showmasterpiece/logic/hooks/useCartContext.ts"() {
|
|
2506
|
+
"use client";
|
|
2507
|
+
useCartContext = () => {
|
|
2508
|
+
let CartContext2;
|
|
2509
|
+
try {
|
|
2510
|
+
const contextModule = (init_CartContext(), __toCommonJS(CartContext_exports));
|
|
2511
|
+
CartContext2 = contextModule.CartContext;
|
|
2512
|
+
} catch (error) {
|
|
2513
|
+
throw new Error("Failed to load CartContext. Make sure CartProvider is properly set up.");
|
|
2514
|
+
}
|
|
2515
|
+
const context = useContext(CartContext2);
|
|
2516
|
+
if (context === void 0) {
|
|
2517
|
+
throw new Error("useCartContext must be used within a CartProvider");
|
|
2518
|
+
}
|
|
2519
|
+
return context;
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
});
|
|
2523
|
+
|
|
2524
|
+
// src/showmasterpiece/logic/hooks/index.ts
|
|
2525
|
+
var init_hooks = __esm({
|
|
2526
|
+
"src/showmasterpiece/logic/hooks/index.ts"() {
|
|
2527
|
+
init_useMasterpieces();
|
|
2528
|
+
init_useMasterpiecesConfig();
|
|
2529
|
+
init_useCart();
|
|
2530
|
+
init_useBooking();
|
|
2531
|
+
init_useBookingAdmin();
|
|
2532
|
+
init_useDeadlinePopup();
|
|
2533
|
+
init_useCartContext();
|
|
2534
|
+
init_useDeadlinePopup();
|
|
2535
|
+
}
|
|
2536
|
+
});
|
|
2537
|
+
|
|
2538
|
+
// src/showmasterpiece/logic/contexts/CartContext.tsx
|
|
2539
|
+
var CartContext_exports = {};
|
|
2540
|
+
__export(CartContext_exports, {
|
|
2541
|
+
CartContext: () => CartContext,
|
|
2542
|
+
CartProvider: () => CartProvider
|
|
2543
|
+
});
|
|
2544
|
+
var CartContext, CartProvider;
|
|
2545
|
+
var init_CartContext = __esm({
|
|
2546
|
+
"src/showmasterpiece/logic/contexts/CartContext.tsx"() {
|
|
2547
|
+
"use client";
|
|
2548
|
+
init_cartService();
|
|
2549
|
+
init_hooks();
|
|
2550
|
+
CartContext = createContext(void 0);
|
|
2551
|
+
CartProvider = ({ children, userId }) => {
|
|
2552
|
+
const [state, setState] = useState({
|
|
2553
|
+
cart: {
|
|
2554
|
+
items: [],
|
|
2555
|
+
totalQuantity: 0,
|
|
2556
|
+
totalPrice: 0
|
|
2557
|
+
},
|
|
2558
|
+
loading: false,
|
|
2559
|
+
error: void 0,
|
|
2560
|
+
refreshCart: async () => {
|
|
2561
|
+
},
|
|
2562
|
+
addToCart: async () => {
|
|
2563
|
+
},
|
|
2564
|
+
updateCartItem: async () => {
|
|
2565
|
+
},
|
|
2566
|
+
removeFromCart: async () => {
|
|
2567
|
+
},
|
|
2568
|
+
batchBooking: async () => ({ successCount: 0, failCount: 0, bookingIds: [], failures: [] }),
|
|
2569
|
+
clearCart: async () => {
|
|
2570
|
+
}
|
|
2571
|
+
});
|
|
2572
|
+
const refreshCart = useCallback(async () => {
|
|
2573
|
+
if (!userId) return;
|
|
2574
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2575
|
+
try {
|
|
2576
|
+
const cartData = await getCart(userId);
|
|
2577
|
+
setState((prev) => ({
|
|
2578
|
+
...prev,
|
|
2579
|
+
cart: cartData,
|
|
2580
|
+
loading: false
|
|
2581
|
+
}));
|
|
2582
|
+
} catch (error) {
|
|
2583
|
+
console.error("\u5237\u65B0\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
2584
|
+
setState((prev) => ({
|
|
2585
|
+
...prev,
|
|
2586
|
+
loading: false,
|
|
2587
|
+
error: error instanceof Error ? error.message : "\u5237\u65B0\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
2588
|
+
}));
|
|
2589
|
+
}
|
|
2590
|
+
}, [userId]);
|
|
2591
|
+
const addToCartWithEvent = useCallback(async (request) => {
|
|
2592
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2593
|
+
try {
|
|
2594
|
+
console.log("\u{1F6D2} [CartContext] \u6DFB\u52A0\u5230\u8D2D\u7269\u8F66:", { request, userId });
|
|
2595
|
+
await addToCart({ ...request, userId });
|
|
2596
|
+
await refreshCart();
|
|
2597
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
2598
|
+
} catch (error) {
|
|
2599
|
+
console.error("\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
2600
|
+
setState((prev) => ({
|
|
2601
|
+
...prev,
|
|
2602
|
+
loading: false,
|
|
2603
|
+
error: error instanceof Error ? error.message : "\u6DFB\u52A0\u5230\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
2604
|
+
}));
|
|
2605
|
+
}
|
|
2606
|
+
}, [refreshCart, userId]);
|
|
2607
|
+
const updateCartItemWithEvent = useCallback(async (request) => {
|
|
2608
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2609
|
+
try {
|
|
2610
|
+
console.log("\u{1F522} [CartContext] \u66F4\u65B0\u8D2D\u7269\u8F66\u6570\u91CF:", { request, userId });
|
|
2611
|
+
await updateCartItem({ ...request, userId });
|
|
2612
|
+
await refreshCart();
|
|
2613
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
2614
|
+
} catch (error) {
|
|
2615
|
+
console.error("\u66F4\u65B0\u8D2D\u7269\u8F66\u6570\u91CF\u5931\u8D25:", error);
|
|
2616
|
+
setState((prev) => ({
|
|
2617
|
+
...prev,
|
|
2618
|
+
loading: false,
|
|
2619
|
+
error: error instanceof Error ? error.message : "\u66F4\u65B0\u8D2D\u7269\u8F66\u6570\u91CF\u5931\u8D25"
|
|
2620
|
+
}));
|
|
2621
|
+
}
|
|
2622
|
+
}, [refreshCart, userId]);
|
|
2623
|
+
const removeFromCartWithEvent = useCallback(async (request) => {
|
|
2624
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2625
|
+
try {
|
|
2626
|
+
console.log("\u{1F5D1}\uFE0F [CartContext] \u79FB\u9664\u5546\u54C1:", { request, userId });
|
|
2627
|
+
await removeFromCart({ ...request, userId });
|
|
2628
|
+
await refreshCart();
|
|
2629
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
2630
|
+
} catch (error) {
|
|
2631
|
+
console.error("\u79FB\u9664\u5546\u54C1\u5931\u8D25:", error);
|
|
2632
|
+
setState((prev) => ({
|
|
2633
|
+
...prev,
|
|
2634
|
+
loading: false,
|
|
2635
|
+
error: error instanceof Error ? error.message : "\u79FB\u9664\u5546\u54C1\u5931\u8D25"
|
|
2636
|
+
}));
|
|
2637
|
+
}
|
|
2638
|
+
}, [refreshCart, userId]);
|
|
2639
|
+
const batchBookingWithEvent = useCallback(async (request) => {
|
|
2640
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2641
|
+
try {
|
|
2642
|
+
console.log("\u{1F4CB} [CartContext] \u6279\u91CF\u9884\u8BA2:", { request, userId });
|
|
2643
|
+
const result = await batchBooking(request, state.cart);
|
|
2644
|
+
await refreshCart();
|
|
2645
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
2646
|
+
return result;
|
|
2647
|
+
} catch (error) {
|
|
2648
|
+
console.error("\u6279\u91CF\u9884\u8BA2\u5931\u8D25:", error);
|
|
2649
|
+
setState((prev) => ({
|
|
2650
|
+
...prev,
|
|
2651
|
+
loading: false,
|
|
2652
|
+
error: error instanceof Error ? error.message : "\u6279\u91CF\u9884\u8BA2\u5931\u8D25"
|
|
2653
|
+
}));
|
|
2654
|
+
throw error;
|
|
2655
|
+
}
|
|
2656
|
+
}, [refreshCart, userId, state.cart]);
|
|
2657
|
+
const clearCartWithEvent = useCallback(async () => {
|
|
2658
|
+
setState((prev) => ({ ...prev, loading: true, error: void 0 }));
|
|
2659
|
+
try {
|
|
2660
|
+
console.log("\u{1F5D1}\uFE0F [CartContext] \u6E05\u7A7A\u8D2D\u7269\u8F66:", { userId });
|
|
2661
|
+
await clearCart(userId);
|
|
2662
|
+
await refreshCart();
|
|
2663
|
+
setState((prev) => ({ ...prev, loading: false }));
|
|
2664
|
+
} catch (error) {
|
|
2665
|
+
console.error("\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25:", error);
|
|
2666
|
+
setState((prev) => ({
|
|
2667
|
+
...prev,
|
|
2668
|
+
loading: false,
|
|
2669
|
+
error: error instanceof Error ? error.message : "\u6E05\u7A7A\u8D2D\u7269\u8F66\u5931\u8D25"
|
|
2670
|
+
}));
|
|
2671
|
+
}
|
|
2672
|
+
}, [refreshCart, userId]);
|
|
2673
|
+
useEffect(() => {
|
|
2674
|
+
refreshCart();
|
|
2675
|
+
}, [refreshCart]);
|
|
2676
|
+
useEffect(() => {
|
|
2677
|
+
const handleCartUpdate = () => {
|
|
2678
|
+
refreshCart();
|
|
2679
|
+
};
|
|
2680
|
+
cartUpdateEvents.addEventListener(CART_UPDATE_EVENT, handleCartUpdate);
|
|
2681
|
+
return () => {
|
|
2682
|
+
cartUpdateEvents.removeEventListener(CART_UPDATE_EVENT, handleCartUpdate);
|
|
2683
|
+
};
|
|
2684
|
+
}, [refreshCart]);
|
|
2685
|
+
const contextValue = {
|
|
2686
|
+
...state,
|
|
2687
|
+
refreshCart,
|
|
2688
|
+
addToCart: addToCartWithEvent,
|
|
2689
|
+
updateCartItem: updateCartItemWithEvent,
|
|
2690
|
+
removeFromCart: removeFromCartWithEvent,
|
|
2691
|
+
batchBooking: batchBookingWithEvent,
|
|
2692
|
+
clearCart: clearCartWithEvent
|
|
2693
|
+
};
|
|
2694
|
+
return /* @__PURE__ */ React.createElement(CartContext.Provider, { value: contextValue }, children);
|
|
2695
|
+
};
|
|
2696
|
+
}
|
|
2697
|
+
});
|
|
2698
|
+
|
|
2699
|
+
export { BookingAdminService, BookingService, CART_UPDATE_EVENT, CartHistoryService, CartProvider, CartService, MasterpiecesService, addArtworkToCollection, addToCart, batchBooking, cartUpdateEvents, clearCart, clearUserHistory, createBooking, createCategory, createCollection, deleteArtwork, deleteBooking, deleteBooking2, deleteCollection, deleteHistoryRecord, exportBookings, forceRefreshAllBookings, forceRefreshBookingStats, getAllBookings, getAllCollections, getAllHistory, getArtworksByCollection, getBookableCollections, getBooking, getBookingStats, getBookings, getCart, getCartHistory, getCategories, getCollectionsOverview, getConfig, getMasterpieces, getStatistics, getTags, init_CartContext, init_bookingAdminService, init_bookingService, init_cartHistoryService, init_cartService, init_hooks, init_masterpiecesConfigService, init_masterpiecesService, moveArtwork, moveArtworkDown, moveArtworkUp, moveCollection, moveCollectionDown, moveCollectionUp, notifyCartUpdate, removeFromCart, resetConfig, saveCartHistory, updateArtwork, updateArtworkOrder, updateBooking, updateBookingStatus, updateBookingStatus2, updateCartItem, updateCollection, updateCollectionOrder, updateConfig, useBooking, useBookingAdmin, useBookingForm, useCart, useCartContext, useDeadlinePopup, useMasterpieces, useMasterpiecesConfig };
|
|
2700
|
+
//# sourceMappingURL=chunk-WS3QZYBI.mjs.map
|
|
2701
|
+
//# sourceMappingURL=chunk-WS3QZYBI.mjs.map
|