@quantabit/membership-sdk 1.0.0

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.
@@ -0,0 +1,550 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@quantabit/sdk-config'), require('react')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@quantabit/sdk-config', 'react'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.QbitMembership = {}, global.sdkConfig, global.React));
5
+ })(this, (function (exports, sdkConfig, React) { 'use strict';
6
+
7
+ /**
8
+ * Membership SDK - API 客户端
9
+ * 会员卡系统后端接口封装
10
+ *
11
+ * 使用 BaseApiClient 基类,继承统一的配置、认证、错误处理
12
+ */
13
+
14
+
15
+ /**
16
+ * 会员卡 API 客户端
17
+ */
18
+ class MembershipApiClient extends sdkConfig.BaseApiClient {
19
+ constructor(config = {}) {
20
+ super('/membership', config);
21
+ }
22
+
23
+ // ============ 会员卡查询 ============
24
+
25
+ /**
26
+ * 获取当前用户的会员卡
27
+ */
28
+ async getMyCard() {
29
+ return this.get('/card');
30
+ }
31
+
32
+ /**
33
+ * 获取所有会员卡类型
34
+ */
35
+ async getCards() {
36
+ return this.get('/cards');
37
+ }
38
+
39
+ /**
40
+ * 获取会员卡详情
41
+ * @param {string} cardId - 会员卡 ID
42
+ */
43
+ async getCardDetail(cardId) {
44
+ return this.get(`/cards/${cardId}`);
45
+ }
46
+
47
+ // ============ 会员卡操作 ============
48
+
49
+ /**
50
+ * 使用积分兑换会员卡
51
+ * @param {string} cardType - 卡片类型 (basic/silver/gold/platinum)
52
+ * @param {number} points - 积分数量
53
+ */
54
+ async redeemWithPoints(cardType, points) {
55
+ return this.post('/redeem', {
56
+ cardType,
57
+ points
58
+ });
59
+ }
60
+
61
+ /**
62
+ * 延长会员卡有效期
63
+ * @param {string} cardId - 会员卡 ID
64
+ * @param {number} months - 延长月数
65
+ */
66
+ async extendCard(cardId, months) {
67
+ return this.post(`/cards/${cardId}/extend`, {
68
+ months
69
+ });
70
+ }
71
+
72
+ /**
73
+ * 升级会员卡
74
+ * @param {string} cardId - 会员卡 ID
75
+ * @param {string} targetType - 目标卡片类型
76
+ */
77
+ async upgradeCard(cardId, targetType) {
78
+ return this.post(`/cards/${cardId}/upgrade`, {
79
+ target_type: targetType
80
+ });
81
+ }
82
+
83
+ // ============ 权益管理 ============
84
+
85
+ /**
86
+ * 获取卡片权益列表
87
+ * @param {string} cardType - 卡片类型
88
+ */
89
+ async getBenefits(cardType) {
90
+ return this.get(`/cards/${cardType}/benefits`);
91
+ }
92
+
93
+ /**
94
+ * 使用权益
95
+ * @param {string} benefitId - 权益 ID
96
+ */
97
+ async useBenefit(benefitId) {
98
+ return this.post(`/benefits/${benefitId}/use`);
99
+ }
100
+
101
+ /**
102
+ * 获取权益使用记录
103
+ * @param {Object} params - 查询参数
104
+ */
105
+ async getBenefitHistory(params = {}) {
106
+ return this.get('/benefits/history', params);
107
+ }
108
+ }
109
+
110
+ // 创建默认实例
111
+ const membershipApi = new MembershipApiClient();
112
+
113
+ /**
114
+ * Membership SDK - React Hooks
115
+ * 会员卡 React 钩子
116
+ */
117
+
118
+
119
+ /**
120
+ * 获取当前用户的会员卡信息
121
+ */
122
+ function useMembershipCard() {
123
+ const [card, setCard] = React.useState(null);
124
+ const [loading, setLoading] = React.useState(true);
125
+ const [error, setError] = React.useState(null);
126
+ const fetchCard = React.useCallback(async () => {
127
+ setLoading(true);
128
+ setError(null);
129
+ try {
130
+ const result = await membershipApi.getMyCard();
131
+ setCard(result.data || result);
132
+ } catch (err) {
133
+ setError(err.message);
134
+ } finally {
135
+ setLoading(false);
136
+ }
137
+ }, []);
138
+ React.useEffect(() => {
139
+ fetchCard();
140
+ }, [fetchCard]);
141
+ return {
142
+ card,
143
+ loading,
144
+ error,
145
+ refresh: fetchCard
146
+ };
147
+ }
148
+
149
+ /**
150
+ * 获取所有可用的会员卡类型
151
+ */
152
+ function useMembershipCards() {
153
+ const [cards, setCards] = React.useState([]);
154
+ const [loading, setLoading] = React.useState(true);
155
+ const [error, setError] = React.useState(null);
156
+ const fetchCards = React.useCallback(async () => {
157
+ setLoading(true);
158
+ try {
159
+ const result = await membershipApi.getCards();
160
+ setCards(result.data || []);
161
+ } catch (err) {
162
+ setError(err.message);
163
+ } finally {
164
+ setLoading(false);
165
+ }
166
+ }, []);
167
+ React.useEffect(() => {
168
+ fetchCards();
169
+ }, [fetchCards]);
170
+ return {
171
+ cards,
172
+ loading,
173
+ error,
174
+ refresh: fetchCards
175
+ };
176
+ }
177
+
178
+ /**
179
+ * 会员卡权益管理
180
+ * @param {string} cardType - 卡片类型
181
+ */
182
+ function useBenefits(cardType) {
183
+ const [benefits, setBenefits] = React.useState([]);
184
+ const [loading, setLoading] = React.useState(false);
185
+ const [error, setError] = React.useState(null);
186
+ const fetchBenefits = React.useCallback(async () => {
187
+ if (!cardType) return;
188
+ setLoading(true);
189
+ try {
190
+ const result = await membershipApi.getBenefits(cardType);
191
+ setBenefits(result.data || []);
192
+ } catch (err) {
193
+ setError(err.message);
194
+ } finally {
195
+ setLoading(false);
196
+ }
197
+ }, [cardType]);
198
+ const useBenefit = React.useCallback(async benefitId => {
199
+ const result = await membershipApi.useBenefit(benefitId);
200
+ await fetchBenefits();
201
+ return result;
202
+ }, [fetchBenefits]);
203
+ React.useEffect(() => {
204
+ fetchBenefits();
205
+ }, [fetchBenefits]);
206
+ return {
207
+ benefits,
208
+ loading,
209
+ error,
210
+ useBenefit,
211
+ refresh: fetchBenefits
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Membership SDK - 国际化
217
+ * 会员卡系统多语言支持
218
+ */
219
+
220
+ const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];
221
+ const messages = {
222
+ zh: {
223
+ membershipCard: '会员卡',
224
+ cardType: {
225
+ basic: '基础会员',
226
+ silver: '银卡会员',
227
+ gold: '金卡会员',
228
+ platinum: '铂金会员'
229
+ },
230
+ validUntil: '有效期至',
231
+ points: '积分',
232
+ use: '使用',
233
+ noBenefits: '暂无可用权益',
234
+ redeem: '兑换',
235
+ upgrade: '升级',
236
+ extend: '续期',
237
+ benefits: '会员权益',
238
+ history: '使用记录',
239
+ loading: '加载中...',
240
+ expired: '已过期',
241
+ active: '有效',
242
+ frozen: '已冻结'
243
+ },
244
+ en: {
245
+ membershipCard: 'Membership Card',
246
+ cardType: {
247
+ basic: 'Basic',
248
+ silver: 'Silver',
249
+ gold: 'Gold',
250
+ platinum: 'Platinum'
251
+ },
252
+ validUntil: 'Valid until',
253
+ points: 'Points',
254
+ use: 'Use',
255
+ noBenefits: 'No benefits available',
256
+ redeem: 'Redeem',
257
+ upgrade: 'Upgrade',
258
+ extend: 'Extend',
259
+ benefits: 'Benefits',
260
+ history: 'History',
261
+ loading: 'Loading...',
262
+ expired: 'Expired',
263
+ active: 'Active',
264
+ frozen: 'Frozen'
265
+ },
266
+ ja: {
267
+ membershipCard: 'メンバーシップカード',
268
+ cardType: {
269
+ basic: 'ベーシック',
270
+ silver: 'シルバー',
271
+ gold: 'ゴールド',
272
+ platinum: 'プラチナ'
273
+ },
274
+ validUntil: '有効期限',
275
+ points: 'ポイント',
276
+ use: '使用',
277
+ noBenefits: '利用可能な特典はありません',
278
+ redeem: '交換',
279
+ upgrade: 'アップグレード',
280
+ extend: '延長',
281
+ benefits: '特典',
282
+ history: '履歴',
283
+ loading: '読み込み中...',
284
+ expired: '期限切れ',
285
+ active: '有効',
286
+ frozen: '凍結'
287
+ },
288
+ ko: {
289
+ membershipCard: '멤버십 카드',
290
+ cardType: {
291
+ basic: '기본',
292
+ silver: '실버',
293
+ gold: '골드',
294
+ platinum: '플래티넘'
295
+ },
296
+ validUntil: '유효 기한',
297
+ points: '포인트',
298
+ use: '사용',
299
+ noBenefits: '사용 가능한 혜택이 없습니다',
300
+ redeem: '교환',
301
+ upgrade: '업그레이드',
302
+ extend: '연장',
303
+ benefits: '혜택',
304
+ history: '기록',
305
+ loading: '로딩 중...',
306
+ expired: '만료',
307
+ active: '활성',
308
+ frozen: '동결'
309
+ }
310
+ };
311
+
312
+ // 当前语言
313
+ let currentLanguage = 'zh';
314
+
315
+ /**
316
+ * 设置语言
317
+ * @param {string} lang - 语言代码
318
+ */
319
+ function setLanguage(lang) {
320
+ if (SUPPORTED_LANGUAGES.includes(lang)) {
321
+ currentLanguage = lang;
322
+ }
323
+ }
324
+
325
+ /**
326
+ * 获取当前语言
327
+ * @returns {string}
328
+ */
329
+ function getLanguage() {
330
+ return currentLanguage;
331
+ }
332
+
333
+ /**
334
+ * 翻译函数
335
+ * @param {string} key - 翻译键,支持点号路径(如 'cardType.gold')
336
+ * @param {Object} params - 插值参数
337
+ * @returns {string}
338
+ */
339
+ function t(key, params = {}) {
340
+ const lang = messages[currentLanguage] || messages.zh;
341
+
342
+ // 支持点号路径访问
343
+ const keys = key.split('.');
344
+ let value = lang;
345
+ for (const k of keys) {
346
+ value = value?.[k];
347
+ if (value === undefined) break;
348
+ }
349
+ if (typeof value !== 'string') {
350
+ // 回退到中文
351
+ value = lang;
352
+ for (const k of keys) {
353
+ value = value?.[k];
354
+ if (value === undefined) break;
355
+ }
356
+ }
357
+ if (typeof value !== 'string') return key;
358
+
359
+ // 简单插值替换
360
+ return value.replace(/\{(\w+)\}/g, (_, k) => params[k] ?? '');
361
+ }
362
+
363
+ // 监听全局语言变更事件
364
+ if (typeof window !== 'undefined') {
365
+ window.addEventListener('qbit-did:language-change', e => {
366
+ if (e.detail?.language) {
367
+ setLanguage(e.detail.language);
368
+ }
369
+ });
370
+ }
371
+
372
+ /**
373
+ * Membership SDK - 会员卡组件
374
+ * 支持 i18n 国际化
375
+ */
376
+
377
+
378
+ /**
379
+ * 会员卡类型对应的渐变色配置
380
+ */
381
+ const CARD_GRADIENTS = {
382
+ basic: {
383
+ from: '#6b7280',
384
+ to: '#4b5563',
385
+ label: '🪪'
386
+ },
387
+ silver: {
388
+ from: '#94a3b8',
389
+ to: '#64748b',
390
+ label: '🥈'
391
+ },
392
+ gold: {
393
+ from: '#f59e0b',
394
+ to: '#d97706',
395
+ label: '🥇'
396
+ },
397
+ platinum: {
398
+ from: '#a855f7',
399
+ to: '#7c3aed',
400
+ label: '💎'
401
+ }
402
+ };
403
+
404
+ /**
405
+ * 会员卡展示组件
406
+ * @param {Object} props
407
+ * @param {Object} props.card - 会员卡数据
408
+ * @param {Function} props.onClick - 点击回调
409
+ */
410
+ function MembershipCard({
411
+ card,
412
+ onClick
413
+ }) {
414
+ if (!card) return null;
415
+ const gradient = CARD_GRADIENTS[card.type] || CARD_GRADIENTS.basic;
416
+ return /*#__PURE__*/React.createElement("div", {
417
+ className: "eco-membership-card",
418
+ style: {
419
+ background: `linear-gradient(135deg, ${gradient.from}, ${gradient.to})`,
420
+ borderRadius: '16px',
421
+ padding: '24px',
422
+ color: '#fff',
423
+ cursor: onClick ? 'pointer' : 'default',
424
+ position: 'relative',
425
+ overflow: 'hidden',
426
+ minHeight: '180px'
427
+ },
428
+ onClick: () => onClick?.(card)
429
+ }, /*#__PURE__*/React.createElement("div", {
430
+ style: {
431
+ position: 'absolute',
432
+ top: '16px',
433
+ right: '20px',
434
+ fontSize: '32px',
435
+ opacity: 0.3
436
+ }
437
+ }, gradient.label), /*#__PURE__*/React.createElement("div", {
438
+ style: {
439
+ fontSize: '12px',
440
+ letterSpacing: '2px',
441
+ textTransform: 'uppercase',
442
+ opacity: 0.8
443
+ }
444
+ }, t('membershipCard')), /*#__PURE__*/React.createElement("div", {
445
+ style: {
446
+ fontSize: '20px',
447
+ fontWeight: 'bold',
448
+ marginTop: '8px',
449
+ textTransform: 'uppercase'
450
+ }
451
+ }, t(`cardType.${card.type}`) || card.type), /*#__PURE__*/React.createElement("div", {
452
+ style: {
453
+ marginTop: '24px',
454
+ fontSize: '16px'
455
+ }
456
+ }, card.userName), /*#__PURE__*/React.createElement("div", {
457
+ style: {
458
+ display: 'flex',
459
+ justifyContent: 'space-between',
460
+ marginTop: '16px',
461
+ fontSize: '12px',
462
+ opacity: 0.8
463
+ }
464
+ }, /*#__PURE__*/React.createElement("span", null, t('validUntil'), ": ", card.expiryDate), /*#__PURE__*/React.createElement("span", null, card.points, " ", t('points'))));
465
+ }
466
+
467
+ /**
468
+ * 会员权益列表组件
469
+ * @param {Object} props
470
+ * @param {Array} props.benefits - 权益列表
471
+ * @param {Function} props.onUseBenefit - 使用权益回调
472
+ */
473
+ function BenefitList({
474
+ benefits = [],
475
+ onUseBenefit
476
+ }) {
477
+ if (!benefits.length) {
478
+ return /*#__PURE__*/React.createElement("div", {
479
+ className: "eco-empty"
480
+ }, t('noBenefits'));
481
+ }
482
+ return /*#__PURE__*/React.createElement("div", {
483
+ className: "eco-benefit-list"
484
+ }, benefits.map(benefit => /*#__PURE__*/React.createElement("div", {
485
+ key: benefit.id,
486
+ className: "eco-benefit-item",
487
+ style: {
488
+ display: 'flex',
489
+ justifyContent: 'space-between',
490
+ alignItems: 'center',
491
+ padding: '12px 16px',
492
+ borderBottom: '1px solid #f0f0f0'
493
+ }
494
+ }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
495
+ style: {
496
+ fontWeight: 500
497
+ }
498
+ }, benefit.name), /*#__PURE__*/React.createElement("div", {
499
+ style: {
500
+ fontSize: '12px',
501
+ color: '#999'
502
+ }
503
+ }, benefit.description)), benefit.available && /*#__PURE__*/React.createElement("button", {
504
+ className: "eco-btn eco-btn-sm",
505
+ onClick: () => onUseBenefit?.(benefit.id)
506
+ }, t('use')))));
507
+ }
508
+
509
+ /**
510
+ * @quantabit/membership-sdk
511
+ *
512
+ * QuantaBit Membership SDK
513
+ *
514
+ * Provides reusable membership card features:
515
+ * - Membership card display & management
516
+ * - Points-based card redemption
517
+ * - Card upgrade & extension
518
+ * - Benefit management & usage
519
+ */
520
+
521
+ // ============ Types ============
522
+ const CardType = {
523
+ BASIC: 'basic',
524
+ SILVER: 'silver',
525
+ GOLD: 'gold',
526
+ PLATINUM: 'platinum'
527
+ };
528
+ const CardStatus = {
529
+ ACTIVE: 'active',
530
+ EXPIRED: 'expired',
531
+ FROZEN: 'frozen'
532
+ };
533
+
534
+ exports.BenefitList = BenefitList;
535
+ exports.CardStatus = CardStatus;
536
+ exports.CardType = CardType;
537
+ exports.MembershipApiClient = MembershipApiClient;
538
+ exports.MembershipCard = MembershipCard;
539
+ exports.SUPPORTED_LANGUAGES = SUPPORTED_LANGUAGES;
540
+ exports.getLanguage = getLanguage;
541
+ exports.membershipApi = membershipApi;
542
+ exports.messages = messages;
543
+ exports.setLanguage = setLanguage;
544
+ exports.t = t;
545
+ exports.useBenefits = useBenefits;
546
+ exports.useMembershipCard = useMembershipCard;
547
+ exports.useMembershipCards = useMembershipCards;
548
+
549
+ }));
550
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/services/membershipApi.js","../src/hooks/useMembership.js","../src/i18n/index.js","../src/components/Membership.jsx","../src/index.js"],"sourcesContent":["/**\n * Membership SDK - API 客户端\n * 会员卡系统后端接口封装\n * \n * 使用 BaseApiClient 基类,继承统一的配置、认证、错误处理\n */\n\nimport { BaseApiClient } from '@quantabit/sdk-config';\n\n/**\n * 会员卡 API 客户端\n */\nexport class MembershipApiClient extends BaseApiClient {\n constructor(config = {}) {\n super('/membership', config);\n }\n\n // ============ 会员卡查询 ============\n\n /**\n * 获取当前用户的会员卡\n */\n async getMyCard() {\n return this.get('/card');\n }\n\n /**\n * 获取所有会员卡类型\n */\n async getCards() {\n return this.get('/cards');\n }\n\n /**\n * 获取会员卡详情\n * @param {string} cardId - 会员卡 ID\n */\n async getCardDetail(cardId) {\n return this.get(`/cards/${cardId}`);\n }\n\n // ============ 会员卡操作 ============\n\n /**\n * 使用积分兑换会员卡\n * @param {string} cardType - 卡片类型 (basic/silver/gold/platinum)\n * @param {number} points - 积分数量\n */\n async redeemWithPoints(cardType, points) {\n return this.post('/redeem', { cardType, points });\n }\n\n /**\n * 延长会员卡有效期\n * @param {string} cardId - 会员卡 ID\n * @param {number} months - 延长月数\n */\n async extendCard(cardId, months) {\n return this.post(`/cards/${cardId}/extend`, { months });\n }\n\n /**\n * 升级会员卡\n * @param {string} cardId - 会员卡 ID\n * @param {string} targetType - 目标卡片类型\n */\n async upgradeCard(cardId, targetType) {\n return this.post(`/cards/${cardId}/upgrade`, { target_type: targetType });\n }\n\n // ============ 权益管理 ============\n\n /**\n * 获取卡片权益列表\n * @param {string} cardType - 卡片类型\n */\n async getBenefits(cardType) {\n return this.get(`/cards/${cardType}/benefits`);\n }\n\n /**\n * 使用权益\n * @param {string} benefitId - 权益 ID\n */\n async useBenefit(benefitId) {\n return this.post(`/benefits/${benefitId}/use`);\n }\n\n /**\n * 获取权益使用记录\n * @param {Object} params - 查询参数\n */\n async getBenefitHistory(params = {}) {\n return this.get('/benefits/history', params);\n }\n}\n\n// 创建默认实例\nexport const membershipApi = new MembershipApiClient();\n\nexport default membershipApi;\n","/**\n * Membership SDK - React Hooks\n * 会员卡 React 钩子\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { membershipApi } from '../services/membershipApi';\n\n/**\n * 获取当前用户的会员卡信息\n */\nexport function useMembershipCard() {\n const [card, setCard] = useState(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n\n const fetchCard = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await membershipApi.getMyCard();\n setCard(result.data || result);\n } catch (err) {\n setError(err.message);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchCard();\n }, [fetchCard]);\n\n return { card, loading, error, refresh: fetchCard };\n}\n\n/**\n * 获取所有可用的会员卡类型\n */\nexport function useMembershipCards() {\n const [cards, setCards] = useState([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n\n const fetchCards = useCallback(async () => {\n setLoading(true);\n try {\n const result = await membershipApi.getCards();\n setCards(result.data || []);\n } catch (err) {\n setError(err.message);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchCards();\n }, [fetchCards]);\n\n return { cards, loading, error, refresh: fetchCards };\n}\n\n/**\n * 会员卡权益管理\n * @param {string} cardType - 卡片类型\n */\nexport function useBenefits(cardType) {\n const [benefits, setBenefits] = useState([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState(null);\n\n const fetchBenefits = useCallback(async () => {\n if (!cardType) return;\n setLoading(true);\n try {\n const result = await membershipApi.getBenefits(cardType);\n setBenefits(result.data || []);\n } catch (err) {\n setError(err.message);\n } finally {\n setLoading(false);\n }\n }, [cardType]);\n\n const useBenefit = useCallback(async (benefitId) => {\n const result = await membershipApi.useBenefit(benefitId);\n await fetchBenefits();\n return result;\n }, [fetchBenefits]);\n\n useEffect(() => {\n fetchBenefits();\n }, [fetchBenefits]);\n\n return { benefits, loading, error, useBenefit, refresh: fetchBenefits };\n}\n","/**\n * Membership SDK - 国际化\n * 会员卡系统多语言支持\n */\n\nexport const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];\n\nexport const messages = {\n zh: {\n membershipCard: '会员卡',\n cardType: {\n basic: '基础会员',\n silver: '银卡会员',\n gold: '金卡会员',\n platinum: '铂金会员',\n },\n validUntil: '有效期至',\n points: '积分',\n use: '使用',\n noBenefits: '暂无可用权益',\n redeem: '兑换',\n upgrade: '升级',\n extend: '续期',\n benefits: '会员权益',\n history: '使用记录',\n loading: '加载中...',\n expired: '已过期',\n active: '有效',\n frozen: '已冻结',\n },\n en: {\n membershipCard: 'Membership Card',\n cardType: {\n basic: 'Basic',\n silver: 'Silver',\n gold: 'Gold',\n platinum: 'Platinum',\n },\n validUntil: 'Valid until',\n points: 'Points',\n use: 'Use',\n noBenefits: 'No benefits available',\n redeem: 'Redeem',\n upgrade: 'Upgrade',\n extend: 'Extend',\n benefits: 'Benefits',\n history: 'History',\n loading: 'Loading...',\n expired: 'Expired',\n active: 'Active',\n frozen: 'Frozen',\n },\n ja: {\n membershipCard: 'メンバーシップカード',\n cardType: {\n basic: 'ベーシック',\n silver: 'シルバー',\n gold: 'ゴールド',\n platinum: 'プラチナ',\n },\n validUntil: '有効期限',\n points: 'ポイント',\n use: '使用',\n noBenefits: '利用可能な特典はありません',\n redeem: '交換',\n upgrade: 'アップグレード',\n extend: '延長',\n benefits: '特典',\n history: '履歴',\n loading: '読み込み中...',\n expired: '期限切れ',\n active: '有効',\n frozen: '凍結',\n },\n ko: {\n membershipCard: '멤버십 카드',\n cardType: {\n basic: '기본',\n silver: '실버',\n gold: '골드',\n platinum: '플래티넘',\n },\n validUntil: '유효 기한',\n points: '포인트',\n use: '사용',\n noBenefits: '사용 가능한 혜택이 없습니다',\n redeem: '교환',\n upgrade: '업그레이드',\n extend: '연장',\n benefits: '혜택',\n history: '기록',\n loading: '로딩 중...',\n expired: '만료',\n active: '활성',\n frozen: '동결',\n },\n};\n\n// 当前语言\nlet currentLanguage = 'zh';\n\n/**\n * 设置语言\n * @param {string} lang - 语言代码\n */\nexport function setLanguage(lang) {\n if (SUPPORTED_LANGUAGES.includes(lang)) {\n currentLanguage = lang;\n }\n}\n\n/**\n * 获取当前语言\n * @returns {string}\n */\nexport function getLanguage() {\n return currentLanguage;\n}\n\n/**\n * 翻译函数\n * @param {string} key - 翻译键,支持点号路径(如 'cardType.gold')\n * @param {Object} params - 插值参数\n * @returns {string}\n */\nexport function t(key, params = {}) {\n const lang = messages[currentLanguage] || messages.zh;\n \n // 支持点号路径访问\n const keys = key.split('.');\n let value = lang;\n for (const k of keys) {\n value = value?.[k];\n if (value === undefined) break;\n }\n \n if (typeof value !== 'string') {\n // 回退到中文\n value = lang;\n for (const k of keys) {\n value = value?.[k];\n if (value === undefined) break;\n }\n }\n \n if (typeof value !== 'string') return key;\n \n // 简单插值替换\n return value.replace(/\\{(\\w+)\\}/g, (_, k) => params[k] ?? '');\n}\n\n// 监听全局语言变更事件\nif (typeof window !== 'undefined') {\n window.addEventListener('qbit-did:language-change', (e) => {\n if (e.detail?.language) {\n setLanguage(e.detail.language);\n }\n });\n}\n","/**\n * Membership SDK - 会员卡组件\n * 支持 i18n 国际化\n */\n\nimport React from 'react';\nimport { t } from '../i18n';\n\n/**\n * 会员卡类型对应的渐变色配置\n */\nconst CARD_GRADIENTS = {\n basic: { from: '#6b7280', to: '#4b5563', label: '🪪' },\n silver: { from: '#94a3b8', to: '#64748b', label: '🥈' },\n gold: { from: '#f59e0b', to: '#d97706', label: '🥇' },\n platinum: { from: '#a855f7', to: '#7c3aed', label: '💎' },\n};\n\n/**\n * 会员卡展示组件\n * @param {Object} props\n * @param {Object} props.card - 会员卡数据\n * @param {Function} props.onClick - 点击回调\n */\nexport function MembershipCard({ card, onClick }) {\n if (!card) return null;\n\n const gradient = CARD_GRADIENTS[card.type] || CARD_GRADIENTS.basic;\n\n return (\n <div\n className=\"eco-membership-card\"\n style={{\n background: `linear-gradient(135deg, ${gradient.from}, ${gradient.to})`,\n borderRadius: '16px',\n padding: '24px',\n color: '#fff',\n cursor: onClick ? 'pointer' : 'default',\n position: 'relative',\n overflow: 'hidden',\n minHeight: '180px',\n }}\n onClick={() => onClick?.(card)}\n >\n <div style={{ position: 'absolute', top: '16px', right: '20px', fontSize: '32px', opacity: 0.3 }}>\n {gradient.label}\n </div>\n <div style={{ fontSize: '12px', letterSpacing: '2px', textTransform: 'uppercase', opacity: 0.8 }}>\n {t('membershipCard')}\n </div>\n <div style={{ fontSize: '20px', fontWeight: 'bold', marginTop: '8px', textTransform: 'uppercase' }}>\n {t(`cardType.${card.type}`) || card.type}\n </div>\n <div style={{ marginTop: '24px', fontSize: '16px' }}>\n {card.userName}\n </div>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '16px', fontSize: '12px', opacity: 0.8 }}>\n <span>{t('validUntil')}: {card.expiryDate}</span>\n <span>{card.points} {t('points')}</span>\n </div>\n </div>\n );\n}\n\n/**\n * 会员权益列表组件\n * @param {Object} props\n * @param {Array} props.benefits - 权益列表\n * @param {Function} props.onUseBenefit - 使用权益回调\n */\nexport function BenefitList({ benefits = [], onUseBenefit }) {\n if (!benefits.length) {\n return <div className=\"eco-empty\">{t('noBenefits')}</div>;\n }\n\n return (\n <div className=\"eco-benefit-list\">\n {benefits.map((benefit) => (\n <div key={benefit.id} className=\"eco-benefit-item\" style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n borderBottom: '1px solid #f0f0f0',\n }}>\n <div>\n <div style={{ fontWeight: 500 }}>{benefit.name}</div>\n <div style={{ fontSize: '12px', color: '#999' }}>{benefit.description}</div>\n </div>\n {benefit.available && (\n <button\n className=\"eco-btn eco-btn-sm\"\n onClick={() => onUseBenefit?.(benefit.id)}\n >\n {t('use')}\n </button>\n )}\n </div>\n ))}\n </div>\n );\n}\n","/**\n * @quantabit/membership-sdk\n * \n * QuantaBit Membership SDK\n * \n * Provides reusable membership card features:\n * - Membership card display & management\n * - Points-based card redemption\n * - Card upgrade & extension\n * - Benefit management & usage\n */\n\n// ============ Types ============\nexport const CardType = {\n BASIC: 'basic',\n SILVER: 'silver',\n GOLD: 'gold',\n PLATINUM: 'platinum',\n};\n\nexport const CardStatus = {\n ACTIVE: 'active',\n EXPIRED: 'expired',\n FROZEN: 'frozen',\n};\n\n// ============ Services ============\nexport { MembershipApiClient, membershipApi } from './services/membershipApi';\n\n// ============ Hooks ============\nexport { useMembershipCard, useMembershipCards, useBenefits } from './hooks/useMembership';\n\n// ============ Components ============\nexport { MembershipCard, BenefitList } from './components/Membership';\n\n// ============ i18n ============\nexport {\n messages,\n SUPPORTED_LANGUAGES,\n setLanguage,\n getLanguage,\n t,\n} from './i18n';\n\n// ============ Styles ============\nimport './styles/membership.css';\n"],"names":["MembershipApiClient","BaseApiClient","constructor","config","getMyCard","get","getCards","getCardDetail","cardId","redeemWithPoints","cardType","points","post","extendCard","months","upgradeCard","targetType","target_type","getBenefits","useBenefit","benefitId","getBenefitHistory","params","membershipApi","useMembershipCard","card","setCard","useState","loading","setLoading","error","setError","fetchCard","useCallback","result","data","err","message","useEffect","refresh","useMembershipCards","cards","setCards","fetchCards","useBenefits","benefits","setBenefits","fetchBenefits","SUPPORTED_LANGUAGES","messages","zh","membershipCard","basic","silver","gold","platinum","validUntil","use","noBenefits","redeem","upgrade","extend","history","expired","active","frozen","en","ja","ko","currentLanguage","setLanguage","lang","includes","getLanguage","t","key","keys","split","value","k","undefined","replace","_","window","addEventListener","e","detail","language","CARD_GRADIENTS","from","to","label","MembershipCard","onClick","gradient","type","React","createElement","className","style","background","borderRadius","padding","color","cursor","position","overflow","minHeight","top","right","fontSize","opacity","letterSpacing","textTransform","fontWeight","marginTop","userName","display","justifyContent","expiryDate","BenefitList","onUseBenefit","length","map","benefit","id","alignItems","borderBottom","name","description","available","CardType","BASIC","SILVER","GOLD","PLATINUM","CardStatus","ACTIVE","EXPIRED","FROZEN"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .eco-membership-card{box-shadow:0 8px 32px rgba(0,0,0,.15);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;transition:transform .3s ease,box-shadow .3s ease}.eco-membership-card:hover{box-shadow:0 12px 40px rgba(0,0,0,.2);transform:translateY(-2px)}.eco-benefit-list{border:1px solid #f0f0f0;border-radius:12px;overflow:hidden}.eco-benefit-item{transition:background-color .2s ease}.eco-benefit-item:hover{background-color:#fafafa}.eco-benefit-item:last-child{border-bottom:none}.eco-btn{align-items:center;background:linear-gradient(135deg,#6366f1,#8b5cf6);border:none;border-radius:6px;color:#fff;cursor:pointer;display:inline-flex;font-size:13px;font-weight:500;justify-content:center;padding:6px 16px;transition:all .2s ease}.eco-btn:hover{opacity:.9;transform:translateY(-1px)}.eco-btn-sm{font-size:12px;padding:4px 12px}.eco-empty{color:#999;font-size:14px;padding:32px 16px;text-align:center}