@tbox.cn/app-module-member 0.9.1 → 0.9.3
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/{chunk-K4VM7JZT.js → chunk-ALVM7SOF.js} +9 -6
- package/dist/{chunk-34PVJEKH.js → chunk-GMHJMLRV.js} +5 -4
- package/dist/client/index.js +1 -1
- package/dist/index.js +2 -2
- package/dist/server/index.d.ts +76 -76
- package/dist/server/index.js +1 -1
- package/package.json +4 -4
- package/src/client/components/ImageWithFallback.tsx +2 -1
- package/src/server/cards/member-card-summary/meta.ts +4 -4
- package/src/server/cards/member-card-summary/samples.ts +16 -7
- package/tests/samples.test.ts +35 -0
|
@@ -28,11 +28,14 @@ function cardFace(from, to) {
|
|
|
28
28
|
const marks = '<rect x="58" y="52" width="210" height="42" rx="8" fill="%23000000" opacity="0.14"/><rect x="58" y="130" width="132" height="26" rx="6" fill="%23000000" opacity="0.10"/>';
|
|
29
29
|
return `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="672" height="347"><defs><linearGradient id="f" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="%23${from}"/><stop offset="1" stop-color="%23${to}"/></linearGradient></defs><rect width="672" height="347" fill="url(%23f)"/><circle cx="548" cy="60" r="150" fill="%23ffffff" opacity="0.16"/>` + marks + "</svg>";
|
|
30
30
|
}
|
|
31
|
+
var BLACK_CARD_IMAGE = "https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*c7obRqceNlYAAAAAR0AAAAgAegitAQ/fmt.webp";
|
|
31
32
|
var FACE = {
|
|
32
|
-
blue:
|
|
33
|
-
silver:
|
|
33
|
+
blue: "https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*FrvURLH4UywAAAAARFAAAAgAegitAQ/fmt.webp",
|
|
34
|
+
silver: "https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*Zby2R6FBuFwAAAAASwAAAAgAegitAQ/fmt.webp",
|
|
35
|
+
// gold 配浅金 SVG:恢复真实厂商世代叠字后金卡是浅底深字,黑金深图配金档=深字压深底不可读;
|
|
36
|
+
// 待世代规格(1344×694+透明边)浅金素材重制后再换平台 CDN 图。
|
|
34
37
|
gold: cardFace("f9ecca", "e3c283"),
|
|
35
|
-
black:
|
|
38
|
+
black: BLACK_CARD_IMAGE
|
|
36
39
|
};
|
|
37
40
|
var POINTS_RULE_IMAGE = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="750" height="1600"><rect width="750" height="1600" fill="%23fffdf8"/><rect x="60" y="80" width="380" height="44" rx="10" fill="%23e2c78f"/><rect x="60" y="180" width="630" height="24" rx="8" fill="%23ece7dd"/><rect x="60" y="230" width="560" height="24" rx="8" fill="%23ece7dd"/><rect x="60" y="280" width="610" height="24" rx="8" fill="%23ece7dd"/><rect x="60" y="700" width="630" height="24" rx="8" fill="%23ece7dd"/><rect x="60" y="1500" width="400" height="24" rx="8" fill="%23ece7dd"/></svg>';
|
|
38
41
|
var ICON_COLORS = {
|
|
@@ -288,12 +291,12 @@ var meta2 = {
|
|
|
288
291
|
sampleData: {
|
|
289
292
|
userId: "u_1001",
|
|
290
293
|
cardRef: "card:u_1001",
|
|
291
|
-
cardDisplay: "\
|
|
294
|
+
cardDisplay: "\u9ED1\u5361\u4F1A\u5458",
|
|
292
295
|
status: "active",
|
|
293
296
|
availablePoints: 860,
|
|
294
|
-
cardImageUrl:
|
|
297
|
+
cardImageUrl: BLACK_CARD_IMAGE,
|
|
295
298
|
pointsRuleImageUrl: "https://assets.example.com/member/points-rule.jpg",
|
|
296
|
-
presentation: { variant: "
|
|
299
|
+
presentation: { variant: "black", labelsEmbedded: true },
|
|
297
300
|
progress: {
|
|
298
301
|
daySpentCents: 12345,
|
|
299
302
|
yearSpentCents: 5e5,
|
|
@@ -5,12 +5,13 @@ import "./member-372B74DY.css";
|
|
|
5
5
|
import { CalendarBlank, Phone, Tag, UserCircle } from "@phosphor-icons/react";
|
|
6
6
|
|
|
7
7
|
// src/client/components/ImageWithFallback.tsx
|
|
8
|
-
import { useState } from "react";
|
|
8
|
+
import { useEffect, useState } from "react";
|
|
9
9
|
import { ImageSquare } from "@phosphor-icons/react";
|
|
10
10
|
import { jsx } from "react/jsx-runtime";
|
|
11
11
|
function ImageWithFallback(props) {
|
|
12
12
|
const { src, alt, className, size = 40, loading = "lazy", fallback } = props;
|
|
13
13
|
const [failed, setFailed] = useState(false);
|
|
14
|
+
useEffect(() => setFailed(false), [src]);
|
|
14
15
|
if (!src || failed) {
|
|
15
16
|
return /* @__PURE__ */ jsx("div", { className: `img-fallback ${className ?? ""}`.trim(), "aria-label": alt, role: "img", children: fallback ?? /* @__PURE__ */ jsx(ImageSquare, { weight: "duotone", size: Math.round(size * 0.45) }) });
|
|
16
17
|
}
|
|
@@ -103,7 +104,7 @@ function MemberInfoCard(props) {
|
|
|
103
104
|
var member_info_default = MemberInfoCard;
|
|
104
105
|
|
|
105
106
|
// src/client/cards/member-card-summary/index.tsx
|
|
106
|
-
import { useEffect, useMemo, useRef, useState as useState2 } from "react";
|
|
107
|
+
import { useEffect as useEffect2, useMemo, useRef, useState as useState2 } from "react";
|
|
107
108
|
import { createPortal } from "react-dom";
|
|
108
109
|
import { X } from "@phosphor-icons/react";
|
|
109
110
|
import { markSelfRendering, sendCardAction } from "@tbox.cn/app-agent-sdk-client";
|
|
@@ -158,7 +159,7 @@ function MemberCardSummaryCard(props) {
|
|
|
158
159
|
const pointsRuleTriggerRef = useRef(null);
|
|
159
160
|
const pointsRuleCloseRef = useRef(null);
|
|
160
161
|
const pointsRuleCloseTimerRef = useRef();
|
|
161
|
-
|
|
162
|
+
useEffect2(() => {
|
|
162
163
|
if (!pointsRuleOpen) return;
|
|
163
164
|
const previousOverflow = document.body.style.overflow;
|
|
164
165
|
document.body.style.overflow = "hidden";
|
|
@@ -173,7 +174,7 @@ function MemberCardSummaryCard(props) {
|
|
|
173
174
|
window.removeEventListener("keydown", onKeyDown);
|
|
174
175
|
};
|
|
175
176
|
}, [pointsRuleOpen]);
|
|
176
|
-
|
|
177
|
+
useEffect2(() => () => {
|
|
177
178
|
window.clearTimeout(pointsRuleCloseTimerRef.current);
|
|
178
179
|
window.clearTimeout(benefitActionCloseTimerRef.current);
|
|
179
180
|
}, []);
|
package/dist/client/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
resolveMemberEnrollmentPort,
|
|
8
8
|
resolveMemberProfilePort,
|
|
9
9
|
serverModule
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ALVM7SOF.js";
|
|
11
11
|
import {
|
|
12
12
|
clientModule
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GMHJMLRV.js";
|
|
14
14
|
export {
|
|
15
15
|
InMemoryMemberService,
|
|
16
16
|
clientModule,
|
package/dist/server/index.d.ts
CHANGED
|
@@ -103,19 +103,19 @@ declare const memberCards: {
|
|
|
103
103
|
labelRef: zod.ZodString;
|
|
104
104
|
name: zod.ZodString;
|
|
105
105
|
}, "strip", zod.ZodTypeAny, {
|
|
106
|
-
name: string;
|
|
107
106
|
labelRef: string;
|
|
108
|
-
}, {
|
|
109
107
|
name: string;
|
|
108
|
+
}, {
|
|
110
109
|
labelRef: string;
|
|
110
|
+
name: string;
|
|
111
111
|
}>, "many">;
|
|
112
112
|
}, "strip", zod.ZodTypeAny, {
|
|
113
113
|
userId: string;
|
|
114
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
115
114
|
authState: "authenticated" | "unauthenticated";
|
|
115
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
116
116
|
labels: {
|
|
117
|
-
name: string;
|
|
118
117
|
labelRef: string;
|
|
118
|
+
name: string;
|
|
119
119
|
}[];
|
|
120
120
|
displayName?: string | undefined;
|
|
121
121
|
avatarUrl?: string | undefined;
|
|
@@ -124,11 +124,11 @@ declare const memberCards: {
|
|
|
124
124
|
registeredAt?: string | undefined;
|
|
125
125
|
}, {
|
|
126
126
|
userId: string;
|
|
127
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
128
127
|
authState: "authenticated" | "unauthenticated";
|
|
128
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
129
129
|
labels: {
|
|
130
|
-
name: string;
|
|
131
130
|
labelRef: string;
|
|
131
|
+
name: string;
|
|
132
132
|
}[];
|
|
133
133
|
displayName?: string | undefined;
|
|
134
134
|
avatarUrl?: string | undefined;
|
|
@@ -185,13 +185,13 @@ declare const memberCards: {
|
|
|
185
185
|
text: zod.ZodOptional<zod.ZodString>;
|
|
186
186
|
}, "strip", zod.ZodTypeAny, {
|
|
187
187
|
kind: "toast" | "miniapp" | "dialog";
|
|
188
|
-
url?: string | undefined;
|
|
189
188
|
title?: string | undefined;
|
|
189
|
+
url?: string | undefined;
|
|
190
190
|
text?: string | undefined;
|
|
191
191
|
}, {
|
|
192
192
|
kind: "toast" | "miniapp" | "dialog";
|
|
193
|
-
url?: string | undefined;
|
|
194
193
|
title?: string | undefined;
|
|
194
|
+
url?: string | undefined;
|
|
195
195
|
text?: string | undefined;
|
|
196
196
|
}>>;
|
|
197
197
|
}, "strip", zod.ZodTypeAny, {
|
|
@@ -200,8 +200,8 @@ declare const memberCards: {
|
|
|
200
200
|
description?: string | undefined;
|
|
201
201
|
action?: {
|
|
202
202
|
kind: "toast" | "miniapp" | "dialog";
|
|
203
|
-
url?: string | undefined;
|
|
204
203
|
title?: string | undefined;
|
|
204
|
+
url?: string | undefined;
|
|
205
205
|
text?: string | undefined;
|
|
206
206
|
} | undefined;
|
|
207
207
|
iconUrl?: string | undefined;
|
|
@@ -211,8 +211,8 @@ declare const memberCards: {
|
|
|
211
211
|
description?: string | undefined;
|
|
212
212
|
action?: {
|
|
213
213
|
kind: "toast" | "miniapp" | "dialog";
|
|
214
|
-
url?: string | undefined;
|
|
215
214
|
title?: string | undefined;
|
|
215
|
+
url?: string | undefined;
|
|
216
216
|
text?: string | undefined;
|
|
217
217
|
} | undefined;
|
|
218
218
|
iconUrl?: string | undefined;
|
|
@@ -228,8 +228,8 @@ declare const memberCards: {
|
|
|
228
228
|
query: string;
|
|
229
229
|
}>, "many">>;
|
|
230
230
|
}, "strip", zod.ZodTypeAny, {
|
|
231
|
-
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
232
231
|
userId: string;
|
|
232
|
+
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
233
233
|
cardRef: string;
|
|
234
234
|
cardDisplay: string;
|
|
235
235
|
availablePoints: number;
|
|
@@ -254,8 +254,8 @@ declare const memberCards: {
|
|
|
254
254
|
description?: string | undefined;
|
|
255
255
|
action?: {
|
|
256
256
|
kind: "toast" | "miniapp" | "dialog";
|
|
257
|
-
url?: string | undefined;
|
|
258
257
|
title?: string | undefined;
|
|
258
|
+
url?: string | undefined;
|
|
259
259
|
text?: string | undefined;
|
|
260
260
|
} | undefined;
|
|
261
261
|
iconUrl?: string | undefined;
|
|
@@ -265,8 +265,8 @@ declare const memberCards: {
|
|
|
265
265
|
query: string;
|
|
266
266
|
}[] | undefined;
|
|
267
267
|
}, {
|
|
268
|
-
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
269
268
|
userId: string;
|
|
269
|
+
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
270
270
|
cardRef: string;
|
|
271
271
|
cardDisplay: string;
|
|
272
272
|
availablePoints: number;
|
|
@@ -291,8 +291,8 @@ declare const memberCards: {
|
|
|
291
291
|
description?: string | undefined;
|
|
292
292
|
action?: {
|
|
293
293
|
kind: "toast" | "miniapp" | "dialog";
|
|
294
|
-
url?: string | undefined;
|
|
295
294
|
title?: string | undefined;
|
|
295
|
+
url?: string | undefined;
|
|
296
296
|
text?: string | undefined;
|
|
297
297
|
} | undefined;
|
|
298
298
|
iconUrl?: string | undefined;
|
|
@@ -313,42 +313,42 @@ declare const memberCards: {
|
|
|
313
313
|
usedAt: zod.ZodOptional<zod.ZodString>;
|
|
314
314
|
description: zod.ZodOptional<zod.ZodString>;
|
|
315
315
|
}, "strip", zod.ZodTypeAny, {
|
|
316
|
-
title: string;
|
|
317
316
|
usageRecordRef: string;
|
|
317
|
+
title: string;
|
|
318
318
|
amount: string;
|
|
319
|
-
description?: string | undefined;
|
|
320
319
|
usedAt?: string | undefined;
|
|
320
|
+
description?: string | undefined;
|
|
321
321
|
}, {
|
|
322
|
-
title: string;
|
|
323
322
|
usageRecordRef: string;
|
|
323
|
+
title: string;
|
|
324
324
|
amount: string;
|
|
325
|
-
description?: string | undefined;
|
|
326
325
|
usedAt?: string | undefined;
|
|
326
|
+
description?: string | undefined;
|
|
327
327
|
}>, "many">;
|
|
328
328
|
total: zod.ZodNumber;
|
|
329
329
|
}, "strip", zod.ZodTypeAny, {
|
|
330
330
|
userId: string;
|
|
331
|
-
|
|
331
|
+
balance: number;
|
|
332
332
|
items: {
|
|
333
|
-
title: string;
|
|
334
333
|
usageRecordRef: string;
|
|
334
|
+
title: string;
|
|
335
335
|
amount: string;
|
|
336
|
-
description?: string | undefined;
|
|
337
336
|
usedAt?: string | undefined;
|
|
337
|
+
description?: string | undefined;
|
|
338
338
|
}[];
|
|
339
|
-
|
|
339
|
+
total: number;
|
|
340
340
|
membershipLabel?: string | undefined;
|
|
341
341
|
}, {
|
|
342
342
|
userId: string;
|
|
343
|
-
|
|
343
|
+
balance: number;
|
|
344
344
|
items: {
|
|
345
|
-
title: string;
|
|
346
345
|
usageRecordRef: string;
|
|
346
|
+
title: string;
|
|
347
347
|
amount: string;
|
|
348
|
-
description?: string | undefined;
|
|
349
348
|
usedAt?: string | undefined;
|
|
349
|
+
description?: string | undefined;
|
|
350
350
|
}[];
|
|
351
|
-
|
|
351
|
+
total: number;
|
|
352
352
|
membershipLabel?: string | undefined;
|
|
353
353
|
}>>;
|
|
354
354
|
readonly 'member-enrollment-form': _tbox_cn_app_contracts.CardMeta<zod.ZodObject<{
|
|
@@ -390,14 +390,14 @@ declare const memberCards: {
|
|
|
390
390
|
required: zod.ZodBoolean;
|
|
391
391
|
url: zod.ZodOptional<zod.ZodString>;
|
|
392
392
|
}, "strip", zod.ZodTypeAny, {
|
|
393
|
-
required: boolean;
|
|
394
393
|
title: string;
|
|
394
|
+
required: boolean;
|
|
395
395
|
version: string;
|
|
396
396
|
consentId: string;
|
|
397
397
|
url?: string | undefined;
|
|
398
398
|
}, {
|
|
399
|
-
required: boolean;
|
|
400
399
|
title: string;
|
|
400
|
+
required: boolean;
|
|
401
401
|
version: string;
|
|
402
402
|
consentId: string;
|
|
403
403
|
url?: string | undefined;
|
|
@@ -415,6 +415,7 @@ declare const memberCards: {
|
|
|
415
415
|
manualNotice: zod.ZodOptional<zod.ZodString>;
|
|
416
416
|
}, "strip", zod.ZodTypeAny, {
|
|
417
417
|
userId: string;
|
|
418
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
418
419
|
authorization: {
|
|
419
420
|
status: "unavailable" | "required" | "authorized";
|
|
420
421
|
mobileMasked?: string | undefined;
|
|
@@ -429,11 +430,10 @@ declare const memberCards: {
|
|
|
429
430
|
prefill?: string | undefined;
|
|
430
431
|
placeholder?: string | undefined;
|
|
431
432
|
}[];
|
|
432
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
433
433
|
formVersion: string;
|
|
434
434
|
consents: {
|
|
435
|
-
required: boolean;
|
|
436
435
|
title: string;
|
|
436
|
+
required: boolean;
|
|
437
437
|
version: string;
|
|
438
438
|
consentId: string;
|
|
439
439
|
url?: string | undefined;
|
|
@@ -441,6 +441,7 @@ declare const memberCards: {
|
|
|
441
441
|
manualNotice?: string | undefined;
|
|
442
442
|
}, {
|
|
443
443
|
userId: string;
|
|
444
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
444
445
|
authorization: {
|
|
445
446
|
status: "unavailable" | "required" | "authorized";
|
|
446
447
|
mobileMasked?: string | undefined;
|
|
@@ -455,11 +456,10 @@ declare const memberCards: {
|
|
|
455
456
|
prefill?: string | undefined;
|
|
456
457
|
placeholder?: string | undefined;
|
|
457
458
|
}[];
|
|
458
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
459
459
|
formVersion: string;
|
|
460
460
|
consents: {
|
|
461
|
-
required: boolean;
|
|
462
461
|
title: string;
|
|
462
|
+
required: boolean;
|
|
463
463
|
version: string;
|
|
464
464
|
consentId: string;
|
|
465
465
|
url?: string | undefined;
|
|
@@ -474,15 +474,15 @@ declare const memberCards: {
|
|
|
474
474
|
message: zod.ZodOptional<zod.ZodString>;
|
|
475
475
|
}, "strip", zod.ZodTypeAny, {
|
|
476
476
|
userId: string;
|
|
477
|
-
state: "
|
|
478
|
-
message?: string | undefined;
|
|
477
|
+
state: "active" | "failed" | "pending_confirmation" | "confirmation_timeout";
|
|
479
478
|
memberRef?: string | undefined;
|
|
479
|
+
message?: string | undefined;
|
|
480
480
|
attemptRef?: string | undefined;
|
|
481
481
|
}, {
|
|
482
482
|
userId: string;
|
|
483
|
-
state: "
|
|
484
|
-
message?: string | undefined;
|
|
483
|
+
state: "active" | "failed" | "pending_confirmation" | "confirmation_timeout";
|
|
485
484
|
memberRef?: string | undefined;
|
|
485
|
+
message?: string | undefined;
|
|
486
486
|
attemptRef?: string | undefined;
|
|
487
487
|
}>>;
|
|
488
488
|
readonly 'member-enrollment-cta': _tbox_cn_app_contracts.CardMeta<zod.ZodObject<{
|
|
@@ -495,16 +495,16 @@ declare const memberCards: {
|
|
|
495
495
|
perks: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
|
|
496
496
|
}, "strip", zod.ZodTypeAny, {
|
|
497
497
|
userId: string;
|
|
498
|
-
state: "not_enrolled" | "closed";
|
|
499
498
|
authState: "authenticated";
|
|
499
|
+
state: "not_enrolled" | "closed";
|
|
500
500
|
title?: string | undefined;
|
|
501
501
|
subtitle?: string | undefined;
|
|
502
502
|
enrollUrl?: string | undefined;
|
|
503
503
|
perks?: string[] | undefined;
|
|
504
504
|
}, {
|
|
505
505
|
userId: string;
|
|
506
|
-
state: "not_enrolled" | "closed";
|
|
507
506
|
authState: "authenticated";
|
|
507
|
+
state: "not_enrolled" | "closed";
|
|
508
508
|
title?: string | undefined;
|
|
509
509
|
subtitle?: string | undefined;
|
|
510
510
|
enrollUrl?: string | undefined;
|
|
@@ -541,19 +541,19 @@ declare const serverModule: {
|
|
|
541
541
|
labelRef: zod.ZodString;
|
|
542
542
|
name: zod.ZodString;
|
|
543
543
|
}, "strip", zod.ZodTypeAny, {
|
|
544
|
-
name: string;
|
|
545
544
|
labelRef: string;
|
|
546
|
-
}, {
|
|
547
545
|
name: string;
|
|
546
|
+
}, {
|
|
548
547
|
labelRef: string;
|
|
548
|
+
name: string;
|
|
549
549
|
}>, "many">;
|
|
550
550
|
}, "strip", zod.ZodTypeAny, {
|
|
551
551
|
userId: string;
|
|
552
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
553
552
|
authState: "authenticated" | "unauthenticated";
|
|
553
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
554
554
|
labels: {
|
|
555
|
-
name: string;
|
|
556
555
|
labelRef: string;
|
|
556
|
+
name: string;
|
|
557
557
|
}[];
|
|
558
558
|
displayName?: string | undefined;
|
|
559
559
|
avatarUrl?: string | undefined;
|
|
@@ -562,11 +562,11 @@ declare const serverModule: {
|
|
|
562
562
|
registeredAt?: string | undefined;
|
|
563
563
|
}, {
|
|
564
564
|
userId: string;
|
|
565
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
566
565
|
authState: "authenticated" | "unauthenticated";
|
|
566
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
567
567
|
labels: {
|
|
568
|
-
name: string;
|
|
569
568
|
labelRef: string;
|
|
569
|
+
name: string;
|
|
570
570
|
}[];
|
|
571
571
|
displayName?: string | undefined;
|
|
572
572
|
avatarUrl?: string | undefined;
|
|
@@ -623,13 +623,13 @@ declare const serverModule: {
|
|
|
623
623
|
text: zod.ZodOptional<zod.ZodString>;
|
|
624
624
|
}, "strip", zod.ZodTypeAny, {
|
|
625
625
|
kind: "toast" | "miniapp" | "dialog";
|
|
626
|
-
url?: string | undefined;
|
|
627
626
|
title?: string | undefined;
|
|
627
|
+
url?: string | undefined;
|
|
628
628
|
text?: string | undefined;
|
|
629
629
|
}, {
|
|
630
630
|
kind: "toast" | "miniapp" | "dialog";
|
|
631
|
-
url?: string | undefined;
|
|
632
631
|
title?: string | undefined;
|
|
632
|
+
url?: string | undefined;
|
|
633
633
|
text?: string | undefined;
|
|
634
634
|
}>>;
|
|
635
635
|
}, "strip", zod.ZodTypeAny, {
|
|
@@ -638,8 +638,8 @@ declare const serverModule: {
|
|
|
638
638
|
description?: string | undefined;
|
|
639
639
|
action?: {
|
|
640
640
|
kind: "toast" | "miniapp" | "dialog";
|
|
641
|
-
url?: string | undefined;
|
|
642
641
|
title?: string | undefined;
|
|
642
|
+
url?: string | undefined;
|
|
643
643
|
text?: string | undefined;
|
|
644
644
|
} | undefined;
|
|
645
645
|
iconUrl?: string | undefined;
|
|
@@ -649,8 +649,8 @@ declare const serverModule: {
|
|
|
649
649
|
description?: string | undefined;
|
|
650
650
|
action?: {
|
|
651
651
|
kind: "toast" | "miniapp" | "dialog";
|
|
652
|
-
url?: string | undefined;
|
|
653
652
|
title?: string | undefined;
|
|
653
|
+
url?: string | undefined;
|
|
654
654
|
text?: string | undefined;
|
|
655
655
|
} | undefined;
|
|
656
656
|
iconUrl?: string | undefined;
|
|
@@ -666,8 +666,8 @@ declare const serverModule: {
|
|
|
666
666
|
query: string;
|
|
667
667
|
}>, "many">>;
|
|
668
668
|
}, "strip", zod.ZodTypeAny, {
|
|
669
|
-
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
670
669
|
userId: string;
|
|
670
|
+
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
671
671
|
cardRef: string;
|
|
672
672
|
cardDisplay: string;
|
|
673
673
|
availablePoints: number;
|
|
@@ -692,8 +692,8 @@ declare const serverModule: {
|
|
|
692
692
|
description?: string | undefined;
|
|
693
693
|
action?: {
|
|
694
694
|
kind: "toast" | "miniapp" | "dialog";
|
|
695
|
-
url?: string | undefined;
|
|
696
695
|
title?: string | undefined;
|
|
696
|
+
url?: string | undefined;
|
|
697
697
|
text?: string | undefined;
|
|
698
698
|
} | undefined;
|
|
699
699
|
iconUrl?: string | undefined;
|
|
@@ -703,8 +703,8 @@ declare const serverModule: {
|
|
|
703
703
|
query: string;
|
|
704
704
|
}[] | undefined;
|
|
705
705
|
}, {
|
|
706
|
-
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
707
706
|
userId: string;
|
|
707
|
+
status: "unknown" | "active" | "inactive" | "frozen" | "expired";
|
|
708
708
|
cardRef: string;
|
|
709
709
|
cardDisplay: string;
|
|
710
710
|
availablePoints: number;
|
|
@@ -729,8 +729,8 @@ declare const serverModule: {
|
|
|
729
729
|
description?: string | undefined;
|
|
730
730
|
action?: {
|
|
731
731
|
kind: "toast" | "miniapp" | "dialog";
|
|
732
|
-
url?: string | undefined;
|
|
733
732
|
title?: string | undefined;
|
|
733
|
+
url?: string | undefined;
|
|
734
734
|
text?: string | undefined;
|
|
735
735
|
} | undefined;
|
|
736
736
|
iconUrl?: string | undefined;
|
|
@@ -751,42 +751,42 @@ declare const serverModule: {
|
|
|
751
751
|
usedAt: zod.ZodOptional<zod.ZodString>;
|
|
752
752
|
description: zod.ZodOptional<zod.ZodString>;
|
|
753
753
|
}, "strip", zod.ZodTypeAny, {
|
|
754
|
-
title: string;
|
|
755
754
|
usageRecordRef: string;
|
|
755
|
+
title: string;
|
|
756
756
|
amount: string;
|
|
757
|
-
description?: string | undefined;
|
|
758
757
|
usedAt?: string | undefined;
|
|
758
|
+
description?: string | undefined;
|
|
759
759
|
}, {
|
|
760
|
-
title: string;
|
|
761
760
|
usageRecordRef: string;
|
|
761
|
+
title: string;
|
|
762
762
|
amount: string;
|
|
763
|
-
description?: string | undefined;
|
|
764
763
|
usedAt?: string | undefined;
|
|
764
|
+
description?: string | undefined;
|
|
765
765
|
}>, "many">;
|
|
766
766
|
total: zod.ZodNumber;
|
|
767
767
|
}, "strip", zod.ZodTypeAny, {
|
|
768
768
|
userId: string;
|
|
769
|
-
|
|
769
|
+
balance: number;
|
|
770
770
|
items: {
|
|
771
|
-
title: string;
|
|
772
771
|
usageRecordRef: string;
|
|
772
|
+
title: string;
|
|
773
773
|
amount: string;
|
|
774
|
-
description?: string | undefined;
|
|
775
774
|
usedAt?: string | undefined;
|
|
775
|
+
description?: string | undefined;
|
|
776
776
|
}[];
|
|
777
|
-
|
|
777
|
+
total: number;
|
|
778
778
|
membershipLabel?: string | undefined;
|
|
779
779
|
}, {
|
|
780
780
|
userId: string;
|
|
781
|
-
|
|
781
|
+
balance: number;
|
|
782
782
|
items: {
|
|
783
|
-
title: string;
|
|
784
783
|
usageRecordRef: string;
|
|
784
|
+
title: string;
|
|
785
785
|
amount: string;
|
|
786
|
-
description?: string | undefined;
|
|
787
786
|
usedAt?: string | undefined;
|
|
787
|
+
description?: string | undefined;
|
|
788
788
|
}[];
|
|
789
|
-
|
|
789
|
+
total: number;
|
|
790
790
|
membershipLabel?: string | undefined;
|
|
791
791
|
}>>;
|
|
792
792
|
readonly 'member-enrollment-form': _tbox_cn_app_contracts.CardMeta<zod.ZodObject<{
|
|
@@ -828,14 +828,14 @@ declare const serverModule: {
|
|
|
828
828
|
required: zod.ZodBoolean;
|
|
829
829
|
url: zod.ZodOptional<zod.ZodString>;
|
|
830
830
|
}, "strip", zod.ZodTypeAny, {
|
|
831
|
-
required: boolean;
|
|
832
831
|
title: string;
|
|
832
|
+
required: boolean;
|
|
833
833
|
version: string;
|
|
834
834
|
consentId: string;
|
|
835
835
|
url?: string | undefined;
|
|
836
836
|
}, {
|
|
837
|
-
required: boolean;
|
|
838
837
|
title: string;
|
|
838
|
+
required: boolean;
|
|
839
839
|
version: string;
|
|
840
840
|
consentId: string;
|
|
841
841
|
url?: string | undefined;
|
|
@@ -853,6 +853,7 @@ declare const serverModule: {
|
|
|
853
853
|
manualNotice: zod.ZodOptional<zod.ZodString>;
|
|
854
854
|
}, "strip", zod.ZodTypeAny, {
|
|
855
855
|
userId: string;
|
|
856
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
856
857
|
authorization: {
|
|
857
858
|
status: "unavailable" | "required" | "authorized";
|
|
858
859
|
mobileMasked?: string | undefined;
|
|
@@ -867,11 +868,10 @@ declare const serverModule: {
|
|
|
867
868
|
prefill?: string | undefined;
|
|
868
869
|
placeholder?: string | undefined;
|
|
869
870
|
}[];
|
|
870
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
871
871
|
formVersion: string;
|
|
872
872
|
consents: {
|
|
873
|
-
required: boolean;
|
|
874
873
|
title: string;
|
|
874
|
+
required: boolean;
|
|
875
875
|
version: string;
|
|
876
876
|
consentId: string;
|
|
877
877
|
url?: string | undefined;
|
|
@@ -879,6 +879,7 @@ declare const serverModule: {
|
|
|
879
879
|
manualNotice?: string | undefined;
|
|
880
880
|
}, {
|
|
881
881
|
userId: string;
|
|
882
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
882
883
|
authorization: {
|
|
883
884
|
status: "unavailable" | "required" | "authorized";
|
|
884
885
|
mobileMasked?: string | undefined;
|
|
@@ -893,11 +894,10 @@ declare const serverModule: {
|
|
|
893
894
|
prefill?: string | undefined;
|
|
894
895
|
placeholder?: string | undefined;
|
|
895
896
|
}[];
|
|
896
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
897
897
|
formVersion: string;
|
|
898
898
|
consents: {
|
|
899
|
-
required: boolean;
|
|
900
899
|
title: string;
|
|
900
|
+
required: boolean;
|
|
901
901
|
version: string;
|
|
902
902
|
consentId: string;
|
|
903
903
|
url?: string | undefined;
|
|
@@ -912,15 +912,15 @@ declare const serverModule: {
|
|
|
912
912
|
message: zod.ZodOptional<zod.ZodString>;
|
|
913
913
|
}, "strip", zod.ZodTypeAny, {
|
|
914
914
|
userId: string;
|
|
915
|
-
state: "
|
|
916
|
-
message?: string | undefined;
|
|
915
|
+
state: "active" | "failed" | "pending_confirmation" | "confirmation_timeout";
|
|
917
916
|
memberRef?: string | undefined;
|
|
917
|
+
message?: string | undefined;
|
|
918
918
|
attemptRef?: string | undefined;
|
|
919
919
|
}, {
|
|
920
920
|
userId: string;
|
|
921
|
-
state: "
|
|
922
|
-
message?: string | undefined;
|
|
921
|
+
state: "active" | "failed" | "pending_confirmation" | "confirmation_timeout";
|
|
923
922
|
memberRef?: string | undefined;
|
|
923
|
+
message?: string | undefined;
|
|
924
924
|
attemptRef?: string | undefined;
|
|
925
925
|
}>>;
|
|
926
926
|
readonly 'member-enrollment-cta': _tbox_cn_app_contracts.CardMeta<zod.ZodObject<{
|
|
@@ -933,16 +933,16 @@ declare const serverModule: {
|
|
|
933
933
|
perks: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
|
|
934
934
|
}, "strip", zod.ZodTypeAny, {
|
|
935
935
|
userId: string;
|
|
936
|
-
state: "not_enrolled" | "closed";
|
|
937
936
|
authState: "authenticated";
|
|
937
|
+
state: "not_enrolled" | "closed";
|
|
938
938
|
title?: string | undefined;
|
|
939
939
|
subtitle?: string | undefined;
|
|
940
940
|
enrollUrl?: string | undefined;
|
|
941
941
|
perks?: string[] | undefined;
|
|
942
942
|
}, {
|
|
943
943
|
userId: string;
|
|
944
|
-
state: "not_enrolled" | "closed";
|
|
945
944
|
authState: "authenticated";
|
|
945
|
+
state: "not_enrolled" | "closed";
|
|
946
946
|
title?: string | undefined;
|
|
947
947
|
subtitle?: string | undefined;
|
|
948
948
|
enrollUrl?: string | undefined;
|
package/dist/server/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbox.cn/app-module-member",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "商圈会员模块:会员账户、会员卡、积分流水与入会流程(codegen 源)。",
|
|
6
6
|
"exports": {
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@tbox.cn/app-contracts": "0.12.0",
|
|
22
|
-
"@tbox.cn/app-contracts-mall": "0.12.
|
|
23
|
-
"@tbox.cn/app-agent-sdk-client": "0.1.
|
|
24
|
-
"@tbox.cn/app-agent-sdk-server": "0.1.
|
|
22
|
+
"@tbox.cn/app-contracts-mall": "0.12.1",
|
|
23
|
+
"@tbox.cn/app-agent-sdk-client": "0.1.1",
|
|
24
|
+
"@tbox.cn/app-agent-sdk-server": "0.1.1"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"zod": "3.25.76",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 图片 + 加载失败占位(0.4.0 D6:模块自持 ~20 行,禁跨模块依赖/基元封顶不破)。
|
|
3
3
|
* 源:POC shopping-guide 占位语义。src 缺省或加载失败 → 图标占位。
|
|
4
4
|
*/
|
|
5
|
-
import { useState } from 'react';
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
6
|
import type { ReactNode } from 'react';
|
|
7
7
|
import { ImageSquare } from '@phosphor-icons/react';
|
|
8
8
|
|
|
@@ -18,6 +18,7 @@ export function ImageWithFallback(props: {
|
|
|
18
18
|
}) {
|
|
19
19
|
const { src, alt, className, size = 40, loading = 'lazy', fallback } = props;
|
|
20
20
|
const [failed, setFailed] = useState(false);
|
|
21
|
+
useEffect(() => setFailed(false), [src]);
|
|
21
22
|
if (!src || failed) {
|
|
22
23
|
return (
|
|
23
24
|
<div className={`img-fallback ${className ?? ''}`.trim()} aria-label={alt} role="img">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CardMeta } from '@tbox.cn/app-contracts';
|
|
2
2
|
import { memberCardSummaryCardDataSchema } from '@tbox.cn/app-contracts-mall';
|
|
3
|
-
import { samples } from './samples';
|
|
3
|
+
import { BLACK_CARD_IMAGE, samples } from './samples';
|
|
4
4
|
|
|
5
5
|
const meta: CardMeta<typeof memberCardSummaryCardDataSchema> = {
|
|
6
6
|
cardType: 'member-card-summary',
|
|
@@ -10,12 +10,12 @@ const meta: CardMeta<typeof memberCardSummaryCardDataSchema> = {
|
|
|
10
10
|
sampleData: {
|
|
11
11
|
userId: 'u_1001',
|
|
12
12
|
cardRef: 'card:u_1001',
|
|
13
|
-
cardDisplay: '
|
|
13
|
+
cardDisplay: '黑卡会员',
|
|
14
14
|
status: 'active',
|
|
15
15
|
availablePoints: 860,
|
|
16
|
-
cardImageUrl:
|
|
16
|
+
cardImageUrl: BLACK_CARD_IMAGE,
|
|
17
17
|
pointsRuleImageUrl: 'https://assets.example.com/member/points-rule.jpg',
|
|
18
|
-
presentation: { variant: '
|
|
18
|
+
presentation: { variant: 'black', labelsEmbedded: true },
|
|
19
19
|
progress: {
|
|
20
20
|
daySpentCents: 12_345,
|
|
21
21
|
yearSpentCents: 500_000,
|
|
@@ -7,17 +7,21 @@
|
|
|
7
7
|
* - 视觉等价的输入合并为一格,note 列全合并口径;
|
|
8
8
|
* - 样本即契约:data 必须 dataSchema 校验通过且无 shape 外键(tests/samples.test.ts 双断言)。
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
10
|
+
* 素材边界(规范真源 = 厂商中立门禁:禁厂商租户字样/标识/深链——平台 CDN 演示素材不在禁列):
|
|
11
|
+
* - 卡面底图:平台 CDN 演示素材(mdn.alipayobjects.com,预览/截图保真)。样本只服务预览,
|
|
12
|
+
* 运行时素材恒由 provider 下发(mock 发 dynamic face 与真实厂商集成同构,见 provider-mock
|
|
13
|
+
* member);gold 档保留内联 SVG 作浅金占位;
|
|
12
14
|
* - 权益图标:内联 SVG 按变体分色——验证的是「图标配色压不压得住卡面底色」与四列网格
|
|
13
15
|
* 换行(低两档 14 项、高两档 15 项的数量差异照实铺),不是图标的图案还原度
|
|
14
16
|
* (真实图标由 provider 运行时下发;图案语义兜底归组件内 ImageWithFallback);
|
|
15
|
-
* - 卡图/图标的外链失败分支刻意保留 example.com
|
|
17
|
+
* - 卡图/图标的外链失败分支刻意保留 example.com 占位(该分支本身是合法预览态);
|
|
18
|
+
* - 白名单由 tests/samples.test.ts 断言收口:卡面 URL 仅允许 mdn.alipayobjects.com /
|
|
19
|
+
* example.com / data:image/svg+xml,厂商租户素材回潜即 fail。
|
|
16
20
|
*/
|
|
17
21
|
import type { CardSample } from '@tbox.cn/app-contracts';
|
|
18
22
|
import type { MemberCardSummaryCardData } from '@tbox.cn/app-contracts-mall';
|
|
19
23
|
|
|
20
|
-
/**
|
|
24
|
+
/** 内联卡面底图:金档占位(浅底深字,与模块叠字配色配对)。 */
|
|
21
25
|
function cardFace(from: string, to: string): string {
|
|
22
26
|
// 真实卡图恒自带卡名与「我的积分」字样(labelsEmbedded 恒 true),前端只叠积分数字。
|
|
23
27
|
// 两块半透明色块代表那两行字的占位——不写真文字是为了不依赖 SVG 内的中文字体,
|
|
@@ -36,11 +40,16 @@ function cardFace(from: string, to: string): string {
|
|
|
36
40
|
+ '</svg>';
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
export const BLACK_CARD_IMAGE
|
|
44
|
+
= 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*c7obRqceNlYAAAAAR0AAAAgAegitAQ/fmt.webp';
|
|
45
|
+
|
|
39
46
|
const FACE = {
|
|
40
|
-
blue:
|
|
41
|
-
silver:
|
|
47
|
+
blue: 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*FrvURLH4UywAAAAARFAAAAgAegitAQ/fmt.webp',
|
|
48
|
+
silver: 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*Zby2R6FBuFwAAAAASwAAAAgAegitAQ/fmt.webp',
|
|
49
|
+
// gold 配浅金 SVG:恢复真实厂商世代叠字后金卡是浅底深字,黑金深图配金档=深字压深底不可读;
|
|
50
|
+
// 待世代规格(1344×694+透明边)浅金素材重制后再换平台 CDN 图。
|
|
42
51
|
gold: cardFace('f9ecca', 'e3c283'),
|
|
43
|
-
black:
|
|
52
|
+
black: BLACK_CARD_IMAGE,
|
|
44
53
|
};
|
|
45
54
|
|
|
46
55
|
/** 积分规则长图占位(弹层内容):只需一张有高度的图验证弹层滚动与关闭 */
|
package/tests/samples.test.ts
CHANGED
|
@@ -44,6 +44,41 @@ describe('member samples 双断言(样本即契约)', () => {
|
|
|
44
44
|
expect(Math.min(...counts.filter((n) => n >= 10))).toBe(14);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
it('卡面素材白名单:平台 CDN 演示素材 / example.com 失败分支 / 内联 SVG(厂商租户素材回潜即 fail)', () => {
|
|
48
|
+
const allowed = (url: string) =>
|
|
49
|
+
url.startsWith('https://mdn.alipayobjects.com/')
|
|
50
|
+
|| url.startsWith('https://assets.example.com/')
|
|
51
|
+
|| url.startsWith('data:image/svg+xml');
|
|
52
|
+
for (const s of meta.samples ?? []) {
|
|
53
|
+
const url = (s.data as { cardImageUrl?: string }).cardImageUrl;
|
|
54
|
+
if (url) expect(allowed(url), s.label).toBe(true);
|
|
55
|
+
}
|
|
56
|
+
const initial = (meta.sampleData as { cardImageUrl?: string }).cardImageUrl;
|
|
57
|
+
if (initial) expect(allowed(initial), '初始态').toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('初始态深卡配对:black 变体配深底卡图(恢复真实厂商世代叠字后浅金字压深底可读)', () => {
|
|
61
|
+
const data = meta.sampleData as { presentation?: { variant?: string }; cardImageUrl?: string };
|
|
62
|
+
expect(data.presentation?.variant).toBe('black');
|
|
63
|
+
expect(data.cardImageUrl).toBe(
|
|
64
|
+
'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*c7obRqceNlYAAAAAR0AAAAgAegitAQ/fmt.webp',
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('蓝卡、银卡、黑卡样本使用各自指定卡面', () => {
|
|
69
|
+
const expected = {
|
|
70
|
+
blue: 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*FrvURLH4UywAAAAARFAAAAgAegitAQ/fmt.webp',
|
|
71
|
+
silver: 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*Zby2R6FBuFwAAAAASwAAAAgAegitAQ/fmt.webp',
|
|
72
|
+
black: 'https://mdn.alipayobjects.com/huamei_b00jk5/afts/img/A*c7obRqceNlYAAAAAR0AAAAgAegitAQ/fmt.webp',
|
|
73
|
+
} as const;
|
|
74
|
+
for (const [variant, cardImageUrl] of Object.entries(expected)) {
|
|
75
|
+
const sample = (meta.samples ?? []).find(
|
|
76
|
+
(item) => (item.data as { presentation?: { variant?: string } }).presentation?.variant === variant,
|
|
77
|
+
);
|
|
78
|
+
expect((sample?.data as { cardImageUrl?: string } | undefined)?.cardImageUrl).toBe(cardImageUrl);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
47
82
|
it('素材中立:权益图标全部为内联 SVG 分色占位或 example.com 占位', () => {
|
|
48
83
|
const serialized = JSON.stringify(meta.samples ?? []);
|
|
49
84
|
expect(serialized).toContain('data:image/svg+xml');
|