@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.
@@ -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: cardFace("dce8fb", "aecdf5"),
33
- silver: cardFace("eef1f7", "c4cddf"),
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: cardFace("1b1e26", "4a412c")
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: "\u91D1\u5361\u4F1A\u5458",
294
+ cardDisplay: "\u9ED1\u5361\u4F1A\u5458",
292
295
  status: "active",
293
296
  availablePoints: 860,
294
- cardImageUrl: "https://assets.example.com/member/gold-card.png",
297
+ cardImageUrl: BLACK_CARD_IMAGE,
295
298
  pointsRuleImageUrl: "https://assets.example.com/member/points-rule.jpg",
296
- presentation: { variant: "gold", labelsEmbedded: true },
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
- useEffect(() => {
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
- useEffect(() => () => {
177
+ useEffect2(() => () => {
177
178
  window.clearTimeout(pointsRuleCloseTimerRef.current);
178
179
  window.clearTimeout(benefitActionCloseTimerRef.current);
179
180
  }, []);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clientModule
3
- } from "../chunk-34PVJEKH.js";
3
+ } from "../chunk-GMHJMLRV.js";
4
4
  export {
5
5
  clientModule
6
6
  };
package/dist/index.js CHANGED
@@ -7,10 +7,10 @@ import {
7
7
  resolveMemberEnrollmentPort,
8
8
  resolveMemberProfilePort,
9
9
  serverModule
10
- } from "./chunk-K4VM7JZT.js";
10
+ } from "./chunk-ALVM7SOF.js";
11
11
  import {
12
12
  clientModule
13
- } from "./chunk-34PVJEKH.js";
13
+ } from "./chunk-GMHJMLRV.js";
14
14
  export {
15
15
  InMemoryMemberService,
16
16
  clientModule,
@@ -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
- total: number;
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
- balance: number;
339
+ total: number;
340
340
  membershipLabel?: string | undefined;
341
341
  }, {
342
342
  userId: string;
343
- total: number;
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
- balance: number;
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: "failed" | "active" | "pending_confirmation" | "confirmation_timeout";
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: "failed" | "active" | "pending_confirmation" | "confirmation_timeout";
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
- total: number;
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
- balance: number;
777
+ total: number;
778
778
  membershipLabel?: string | undefined;
779
779
  }, {
780
780
  userId: string;
781
- total: number;
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
- balance: number;
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: "failed" | "active" | "pending_confirmation" | "confirmation_timeout";
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: "failed" | "active" | "pending_confirmation" | "confirmation_timeout";
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;
@@ -7,7 +7,7 @@ import {
7
7
  resolveMemberEnrollmentPort,
8
8
  resolveMemberProfilePort,
9
9
  serverModule
10
- } from "../chunk-K4VM7JZT.js";
10
+ } from "../chunk-ALVM7SOF.js";
11
11
  export {
12
12
  InMemoryMemberService,
13
13
  memberCards,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tbox.cn/app-module-member",
3
- "version": "0.9.1",
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.0",
23
- "@tbox.cn/app-agent-sdk-client": "0.1.0",
24
- "@tbox.cn/app-agent-sdk-server": "0.1.0"
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: 'https://assets.example.com/member/gold-card.png',
16
+ cardImageUrl: BLACK_CARD_IMAGE,
17
17
  pointsRuleImageUrl: 'https://assets.example.com/member/points-rule.jpg',
18
- presentation: { variant: 'gold', labelsEmbedded: true },
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
- * 素材中立化(画廊时期权益图标指向厂商 CDN,模块样本按仓库铁律净化):
11
- * - 卡面底图/积分规则长图:无网络依赖的内联 SVG data URI(画廊原实现随行);
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
- /** 卡面底图:底色随 variant 走(前三档浅底深字、black 深底浅字——与模块 CSS 叠字色配对) */
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: cardFace('dce8fb', 'aecdf5'),
41
- silver: cardFace('eef1f7', 'c4cddf'),
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: cardFace('1b1e26', '4a412c'),
52
+ black: BLACK_CARD_IMAGE,
44
53
  };
45
54
 
46
55
  /** 积分规则长图占位(弹层内容):只需一张有高度的图验证弹层滚动与关闭 */
@@ -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');