@tbox.cn/app-module-member 0.8.6 → 0.9.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.
- package/dist/{chunk-T4SYPQA5.js → chunk-EPQEF43P.js} +16 -0
- package/dist/{chunk-KEBILLQ5.js → chunk-QWGRWD5C.js} +2 -7
- package/dist/client/index.js +1 -1
- package/dist/index.js +2 -2
- package/dist/{member-QFCIYILN.css → member-372B74DY.css} +11 -5
- package/dist/server/index.d.ts +80 -80
- package/dist/server/index.js +1 -1
- package/package.json +4 -4
- package/src/client/cards/member-login-cta/index.tsx +2 -2
- package/src/client/styles/member.css +11 -5
- package/src/server/index.ts +20 -0
- package/tbox.module.json +2 -0
- package/tests/enrollment.test.ts +1 -1
- package/tests/ports-resolve.test.ts +1 -1
- package/tests/preference-memory.test.ts +2 -2
- package/tests/service.test.ts +3 -3
- package/tests/snapshot-service.test.ts +75 -0
- package/tests/status.test.ts +1 -1
- package/dist/login-mascot-5D4X6YZ7.jpg +0 -0
- package/src/client/assets/login-mascot.jpg +0 -0
- package/src/client/assets.d.ts +0 -5
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/server/index.ts
|
|
2
2
|
import { loadModuleSkills, withCardEmissionHint, withEarlyExecution } from "@tbox.cn/app-sdk/server";
|
|
3
|
+
import { MEMBER_SNAPSHOT_SERVICE } from "@tbox.cn/app-contracts-mall";
|
|
3
4
|
|
|
4
5
|
// src/server/cards/member-info/meta.ts
|
|
5
6
|
import { memberInfoCardDataSchema } from "@tbox.cn/app-contracts-mall";
|
|
@@ -1550,6 +1551,21 @@ var serverModule = {
|
|
|
1550
1551
|
ctx.cardActions.register(action);
|
|
1551
1552
|
}
|
|
1552
1553
|
ctx.services.register("member.subject-binding", createSubjectBinding(ctx));
|
|
1554
|
+
ctx.services.register(
|
|
1555
|
+
MEMBER_SNAPSHOT_SERVICE,
|
|
1556
|
+
async (reqCtx) => {
|
|
1557
|
+
const [account, benefits, enrollment] = await Promise.all([
|
|
1558
|
+
resolveMemberAccountPort(reqCtx, ctx),
|
|
1559
|
+
resolveMemberBenefitsPort(reqCtx, ctx),
|
|
1560
|
+
resolveMemberEnrollmentPort(reqCtx, ctx).catch(() => null)
|
|
1561
|
+
]);
|
|
1562
|
+
return {
|
|
1563
|
+
getAccount: (userId) => account.getAccount(userId),
|
|
1564
|
+
queryPoints: (userId) => benefits.queryPoints(userId),
|
|
1565
|
+
...enrollment?.enrollUrl ? { enrollUrl: enrollment.enrollUrl } : {}
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
);
|
|
1553
1569
|
}
|
|
1554
1570
|
};
|
|
1555
1571
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/client/index.ts
|
|
2
|
-
import "./member-
|
|
2
|
+
import "./member-372B74DY.css";
|
|
3
3
|
|
|
4
4
|
// src/client/cards/member-info/index.tsx
|
|
5
5
|
import { CalendarBlank, Phone, Tag, UserCircle } from "@phosphor-icons/react";
|
|
@@ -696,11 +696,6 @@ var member_enrollment_cta_default = MemberEnrollmentCtaCard;
|
|
|
696
696
|
import { useRef as useRef5, useState as useState6 } from "react";
|
|
697
697
|
import { ArrowSquareOut as ArrowSquareOut2, WarningCircle as WarningCircle3 } from "@phosphor-icons/react";
|
|
698
698
|
import { sendCardAction as sendCardAction5 } from "@tbox.cn/app-sdk/client";
|
|
699
|
-
|
|
700
|
-
// src/client/assets/login-mascot.jpg
|
|
701
|
-
var login_mascot_default = "./login-mascot-5D4X6YZ7.jpg";
|
|
702
|
-
|
|
703
|
-
// src/client/cards/member-login-cta/index.tsx
|
|
704
699
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
705
700
|
function MemberLoginCtaCard(props) {
|
|
706
701
|
const { data, cardId, isHistory } = props;
|
|
@@ -721,7 +716,7 @@ function MemberLoginCtaCard(props) {
|
|
|
721
716
|
/* @__PURE__ */ jsx8("path", { d: "M40 122 c12,-8 20,2 11,9" })
|
|
722
717
|
] }),
|
|
723
718
|
/* @__PURE__ */ jsx8("span", { className: "member-login-cta__ground", "aria-hidden": "true" }),
|
|
724
|
-
/* @__PURE__ */ jsx8("
|
|
719
|
+
/* @__PURE__ */ jsx8("span", { className: "member-login-cta__mascot", "aria-hidden": "true" }),
|
|
725
720
|
/* @__PURE__ */ jsx8("span", { className: "member-login-cta__grain", "aria-hidden": "true" })
|
|
726
721
|
] }),
|
|
727
722
|
/* @__PURE__ */ jsx8("svg", { className: "member-login-cta__tear", viewBox: "0 0 390 16", preserveAspectRatio: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M0,16 L390,16 L390,6 L358,10 L330,4 L298,11 L266,5 L236,12 L204,6 L174,12 L144,6 L112,13 L82,7 L52,14 L24,8 L0,12 Z" }) }),
|
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-EPQEF43P.js";
|
|
11
11
|
import {
|
|
12
12
|
clientModule
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-QWGRWD5C.js";
|
|
14
14
|
export {
|
|
15
15
|
InMemoryMemberService,
|
|
16
16
|
clientModule,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
* module-member 客户端域样式(0.4.0 D1/D2;头注二轮评审修正)。
|
|
3
|
-
* 视觉源:mall-vis 双演示(MembershipMessageCard/MembershipInviteBanner 金系);域色矩阵对照 docs/
|
|
3
|
+
* 视觉源:mall-vis 双演示(MembershipMessageCard/MembershipInviteBanner 金系);域色矩阵对照 docs/reference/templates.md(视觉体系与域色矩阵)。
|
|
4
4
|
* 基线(D2):本仓库统一 750 设计稿 2x——源码 px 经 rootValue 100 转 rem,渲染折半(375 下 1px 源码 = 0.5px 物理)。
|
|
5
5
|
* POC membership 源按 web 物理 px 直觉作稿(如 avatar 76px——该值在 POC 同款 rootValue 100 管线下渲染折半为 38px,
|
|
6
6
|
* 非设计意图),故本文件按 750 稿基线恢复意图:关键尺寸 ×2 于源值(76→152),其余(卡距/字阶 24/26/34/44)按
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
/* ===== 域变量 ===== */
|
|
15
15
|
.member-card {
|
|
16
|
-
--member-accent: #b45f06;
|
|
16
|
+
--member-accent: var(--tbox-domain-member-accent, #b45f06);
|
|
17
17
|
--member-accent-strong: #b45f06;
|
|
18
18
|
--member-label: #a3925f;
|
|
19
19
|
--member-accent-soft: #fff6e0;
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
--member-warning-light: var(--tbox-warning-light, #fff4e0);
|
|
24
24
|
--member-muted: var(--tbox-text-secondary, #82745e);
|
|
25
25
|
--member-faint: var(--tbox-text-muted, #a69a83);
|
|
26
|
-
--member-border: #ecdec2;
|
|
26
|
+
--member-border: var(--tbox-domain-member-border, #ecdec2);
|
|
27
27
|
--member-bg-subtle: #fff8eb;
|
|
28
|
-
--member-surface: #fffdf8;
|
|
28
|
+
--member-surface: var(--tbox-domain-member-surface, #fffdf8);
|
|
29
29
|
--member-accent-deep: #8c6a2f;
|
|
30
30
|
--member-accent-deep-bg: #f9f1df;
|
|
31
31
|
--member-accent-border: #ecdec2;
|
|
@@ -1597,8 +1597,14 @@
|
|
|
1597
1597
|
bottom: 4PX;
|
|
1598
1598
|
z-index: 2;
|
|
1599
1599
|
width: 132PX;
|
|
1600
|
-
|
|
1600
|
+
aspect-ratio: 200 / 194; /* 资产契约 200×194,等比缩放 */
|
|
1601
1601
|
transform: translateX(-50%);
|
|
1602
|
+
/* 素材变量链(主题品牌资产轨 A1 级联修复):元素只消费不声明(声明会截断主题覆写继承),
|
|
1603
|
+
兜底 = 中立渐变(零品牌资产——B2),主题包经 html[data-theme] 段覆写 --tbox-asset-member-mascot */
|
|
1604
|
+
background-image: var(--tbox-asset-member-mascot, linear-gradient(135deg, #fff8eb, #fffdf8));
|
|
1605
|
+
background-size: contain;
|
|
1606
|
+
background-repeat: no-repeat;
|
|
1607
|
+
background-position: center bottom;
|
|
1602
1608
|
/* 顶部淡入:图片上沿伸进天光区,不化开就是一条横切的硬边 */
|
|
1603
1609
|
-webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 22%, #000 100%);
|
|
1604
1610
|
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 22%, #000 100%);
|
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,14 +185,14 @@ declare const memberCards: {
|
|
|
185
185
|
text: zod.ZodOptional<zod.ZodString>;
|
|
186
186
|
}, "strip", zod.ZodTypeAny, {
|
|
187
187
|
kind: "toast" | "miniapp" | "dialog";
|
|
188
|
+
title?: string | undefined;
|
|
188
189
|
url?: string | undefined;
|
|
189
190
|
text?: string | undefined;
|
|
190
|
-
title?: string | undefined;
|
|
191
191
|
}, {
|
|
192
192
|
kind: "toast" | "miniapp" | "dialog";
|
|
193
|
+
title?: string | undefined;
|
|
193
194
|
url?: string | undefined;
|
|
194
195
|
text?: string | undefined;
|
|
195
|
-
title?: string | undefined;
|
|
196
196
|
}>>;
|
|
197
197
|
}, "strip", zod.ZodTypeAny, {
|
|
198
198
|
name: string;
|
|
@@ -200,9 +200,9 @@ declare const memberCards: {
|
|
|
200
200
|
description?: string | undefined;
|
|
201
201
|
action?: {
|
|
202
202
|
kind: "toast" | "miniapp" | "dialog";
|
|
203
|
+
title?: string | undefined;
|
|
203
204
|
url?: string | undefined;
|
|
204
205
|
text?: string | undefined;
|
|
205
|
-
title?: string | undefined;
|
|
206
206
|
} | undefined;
|
|
207
207
|
iconUrl?: string | undefined;
|
|
208
208
|
}, {
|
|
@@ -211,9 +211,9 @@ declare const memberCards: {
|
|
|
211
211
|
description?: string | undefined;
|
|
212
212
|
action?: {
|
|
213
213
|
kind: "toast" | "miniapp" | "dialog";
|
|
214
|
+
title?: string | undefined;
|
|
214
215
|
url?: string | undefined;
|
|
215
216
|
text?: string | undefined;
|
|
216
|
-
title?: string | undefined;
|
|
217
217
|
} | undefined;
|
|
218
218
|
iconUrl?: string | undefined;
|
|
219
219
|
}>, "many">>;
|
|
@@ -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,9 +254,9 @@ declare const memberCards: {
|
|
|
254
254
|
description?: string | undefined;
|
|
255
255
|
action?: {
|
|
256
256
|
kind: "toast" | "miniapp" | "dialog";
|
|
257
|
+
title?: string | undefined;
|
|
257
258
|
url?: string | undefined;
|
|
258
259
|
text?: string | undefined;
|
|
259
|
-
title?: string | undefined;
|
|
260
260
|
} | undefined;
|
|
261
261
|
iconUrl?: string | undefined;
|
|
262
262
|
}[] | 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,9 +291,9 @@ declare const memberCards: {
|
|
|
291
291
|
description?: string | undefined;
|
|
292
292
|
action?: {
|
|
293
293
|
kind: "toast" | "miniapp" | "dialog";
|
|
294
|
+
title?: string | undefined;
|
|
294
295
|
url?: string | undefined;
|
|
295
296
|
text?: string | undefined;
|
|
296
|
-
title?: string | undefined;
|
|
297
297
|
} | undefined;
|
|
298
298
|
iconUrl?: string | undefined;
|
|
299
299
|
}[] | 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,15 +390,15 @@ declare const memberCards: {
|
|
|
390
390
|
required: zod.ZodBoolean;
|
|
391
391
|
url: zod.ZodOptional<zod.ZodString>;
|
|
392
392
|
}, "strip", zod.ZodTypeAny, {
|
|
393
|
+
title: string;
|
|
393
394
|
required: boolean;
|
|
394
395
|
version: string;
|
|
395
|
-
title: string;
|
|
396
396
|
consentId: string;
|
|
397
397
|
url?: string | undefined;
|
|
398
398
|
}, {
|
|
399
|
+
title: string;
|
|
399
400
|
required: boolean;
|
|
400
401
|
version: string;
|
|
401
|
-
title: string;
|
|
402
402
|
consentId: string;
|
|
403
403
|
url?: string | undefined;
|
|
404
404
|
}>, "many">;
|
|
@@ -415,12 +415,11 @@ 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: "required" | "unavailable" | "authorized";
|
|
420
421
|
mobileMasked?: string | undefined;
|
|
421
422
|
};
|
|
422
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
423
|
-
formVersion: string;
|
|
424
423
|
fields: {
|
|
425
424
|
type: "date" | "text" | "tel" | "select";
|
|
426
425
|
required: boolean;
|
|
@@ -431,22 +430,22 @@ declare const memberCards: {
|
|
|
431
430
|
prefill?: string | undefined;
|
|
432
431
|
placeholder?: string | undefined;
|
|
433
432
|
}[];
|
|
433
|
+
formVersion: string;
|
|
434
434
|
consents: {
|
|
435
|
+
title: string;
|
|
435
436
|
required: boolean;
|
|
436
437
|
version: string;
|
|
437
|
-
title: string;
|
|
438
438
|
consentId: string;
|
|
439
439
|
url?: string | undefined;
|
|
440
440
|
}[];
|
|
441
441
|
manualNotice?: string | undefined;
|
|
442
442
|
}, {
|
|
443
443
|
userId: string;
|
|
444
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
444
445
|
authorization: {
|
|
445
446
|
status: "required" | "unavailable" | "authorized";
|
|
446
447
|
mobileMasked?: string | undefined;
|
|
447
448
|
};
|
|
448
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
449
|
-
formVersion: string;
|
|
450
449
|
fields: {
|
|
451
450
|
type: "date" | "text" | "tel" | "select";
|
|
452
451
|
required: boolean;
|
|
@@ -457,10 +456,11 @@ declare const memberCards: {
|
|
|
457
456
|
prefill?: string | undefined;
|
|
458
457
|
placeholder?: string | undefined;
|
|
459
458
|
}[];
|
|
459
|
+
formVersion: string;
|
|
460
460
|
consents: {
|
|
461
|
+
title: string;
|
|
461
462
|
required: boolean;
|
|
462
463
|
version: string;
|
|
463
|
-
title: string;
|
|
464
464
|
consentId: string;
|
|
465
465
|
url?: string | undefined;
|
|
466
466
|
}[];
|
|
@@ -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,14 +623,14 @@ declare const serverModule: {
|
|
|
623
623
|
text: zod.ZodOptional<zod.ZodString>;
|
|
624
624
|
}, "strip", zod.ZodTypeAny, {
|
|
625
625
|
kind: "toast" | "miniapp" | "dialog";
|
|
626
|
+
title?: string | undefined;
|
|
626
627
|
url?: string | undefined;
|
|
627
628
|
text?: string | undefined;
|
|
628
|
-
title?: string | undefined;
|
|
629
629
|
}, {
|
|
630
630
|
kind: "toast" | "miniapp" | "dialog";
|
|
631
|
+
title?: string | undefined;
|
|
631
632
|
url?: string | undefined;
|
|
632
633
|
text?: string | undefined;
|
|
633
|
-
title?: string | undefined;
|
|
634
634
|
}>>;
|
|
635
635
|
}, "strip", zod.ZodTypeAny, {
|
|
636
636
|
name: string;
|
|
@@ -638,9 +638,9 @@ declare const serverModule: {
|
|
|
638
638
|
description?: string | undefined;
|
|
639
639
|
action?: {
|
|
640
640
|
kind: "toast" | "miniapp" | "dialog";
|
|
641
|
+
title?: string | undefined;
|
|
641
642
|
url?: string | undefined;
|
|
642
643
|
text?: string | undefined;
|
|
643
|
-
title?: string | undefined;
|
|
644
644
|
} | undefined;
|
|
645
645
|
iconUrl?: string | undefined;
|
|
646
646
|
}, {
|
|
@@ -649,9 +649,9 @@ declare const serverModule: {
|
|
|
649
649
|
description?: string | undefined;
|
|
650
650
|
action?: {
|
|
651
651
|
kind: "toast" | "miniapp" | "dialog";
|
|
652
|
+
title?: string | undefined;
|
|
652
653
|
url?: string | undefined;
|
|
653
654
|
text?: string | undefined;
|
|
654
|
-
title?: string | undefined;
|
|
655
655
|
} | undefined;
|
|
656
656
|
iconUrl?: string | undefined;
|
|
657
657
|
}>, "many">>;
|
|
@@ -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,9 +692,9 @@ declare const serverModule: {
|
|
|
692
692
|
description?: string | undefined;
|
|
693
693
|
action?: {
|
|
694
694
|
kind: "toast" | "miniapp" | "dialog";
|
|
695
|
+
title?: string | undefined;
|
|
695
696
|
url?: string | undefined;
|
|
696
697
|
text?: string | undefined;
|
|
697
|
-
title?: string | undefined;
|
|
698
698
|
} | undefined;
|
|
699
699
|
iconUrl?: string | undefined;
|
|
700
700
|
}[] | 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,9 +729,9 @@ declare const serverModule: {
|
|
|
729
729
|
description?: string | undefined;
|
|
730
730
|
action?: {
|
|
731
731
|
kind: "toast" | "miniapp" | "dialog";
|
|
732
|
+
title?: string | undefined;
|
|
732
733
|
url?: string | undefined;
|
|
733
734
|
text?: string | undefined;
|
|
734
|
-
title?: string | undefined;
|
|
735
735
|
} | undefined;
|
|
736
736
|
iconUrl?: string | undefined;
|
|
737
737
|
}[] | 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,15 +828,15 @@ declare const serverModule: {
|
|
|
828
828
|
required: zod.ZodBoolean;
|
|
829
829
|
url: zod.ZodOptional<zod.ZodString>;
|
|
830
830
|
}, "strip", zod.ZodTypeAny, {
|
|
831
|
+
title: string;
|
|
831
832
|
required: boolean;
|
|
832
833
|
version: string;
|
|
833
|
-
title: string;
|
|
834
834
|
consentId: string;
|
|
835
835
|
url?: string | undefined;
|
|
836
836
|
}, {
|
|
837
|
+
title: string;
|
|
837
838
|
required: boolean;
|
|
838
839
|
version: string;
|
|
839
|
-
title: string;
|
|
840
840
|
consentId: string;
|
|
841
841
|
url?: string | undefined;
|
|
842
842
|
}>, "many">;
|
|
@@ -853,12 +853,11 @@ 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: "required" | "unavailable" | "authorized";
|
|
858
859
|
mobileMasked?: string | undefined;
|
|
859
860
|
};
|
|
860
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
861
|
-
formVersion: string;
|
|
862
861
|
fields: {
|
|
863
862
|
type: "date" | "text" | "tel" | "select";
|
|
864
863
|
required: boolean;
|
|
@@ -869,22 +868,22 @@ declare const serverModule: {
|
|
|
869
868
|
prefill?: string | undefined;
|
|
870
869
|
placeholder?: string | undefined;
|
|
871
870
|
}[];
|
|
871
|
+
formVersion: string;
|
|
872
872
|
consents: {
|
|
873
|
+
title: string;
|
|
873
874
|
required: boolean;
|
|
874
875
|
version: string;
|
|
875
|
-
title: string;
|
|
876
876
|
consentId: string;
|
|
877
877
|
url?: string | undefined;
|
|
878
878
|
}[];
|
|
879
879
|
manualNotice?: string | undefined;
|
|
880
880
|
}, {
|
|
881
881
|
userId: string;
|
|
882
|
+
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
882
883
|
authorization: {
|
|
883
884
|
status: "required" | "unavailable" | "authorized";
|
|
884
885
|
mobileMasked?: string | undefined;
|
|
885
886
|
};
|
|
886
|
-
state: "unknown" | "active" | "not_enrolled" | "closed";
|
|
887
|
-
formVersion: string;
|
|
888
887
|
fields: {
|
|
889
888
|
type: "date" | "text" | "tel" | "select";
|
|
890
889
|
required: boolean;
|
|
@@ -895,10 +894,11 @@ declare const serverModule: {
|
|
|
895
894
|
prefill?: string | undefined;
|
|
896
895
|
placeholder?: string | undefined;
|
|
897
896
|
}[];
|
|
897
|
+
formVersion: string;
|
|
898
898
|
consents: {
|
|
899
|
+
title: string;
|
|
899
900
|
required: boolean;
|
|
900
901
|
version: string;
|
|
901
|
-
title: string;
|
|
902
902
|
consentId: string;
|
|
903
903
|
url?: string | undefined;
|
|
904
904
|
}[];
|
|
@@ -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.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "商圈会员模块:会员账户、会员卡、积分流水与入会流程(codegen 源)。",
|
|
6
6
|
"exports": {
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@tbox.cn/app-sdk": "0.
|
|
22
|
-
"@tbox.cn/app-contracts": "0.
|
|
23
|
-
"@tbox.cn/app-contracts-mall": "0.
|
|
21
|
+
"@tbox.cn/app-sdk": "0.20.0",
|
|
22
|
+
"@tbox.cn/app-contracts": "0.11.0",
|
|
23
|
+
"@tbox.cn/app-contracts-mall": "0.11.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"zod": "3.25.76",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
import { useRef, useState } from 'react';
|
|
11
11
|
import { ArrowSquareOut, WarningCircle } from '@phosphor-icons/react';
|
|
12
12
|
import { sendCardAction } from '@tbox.cn/app-sdk/client';
|
|
13
|
-
import mascotUrl from '../../assets/login-mascot.jpg';
|
|
14
13
|
import type { MemberLoginCtaCardData } from '@tbox.cn/app-contracts-mall';
|
|
15
14
|
|
|
16
15
|
export function MemberLoginCtaCard(props: {
|
|
@@ -42,7 +41,8 @@ export function MemberLoginCtaCard(props: {
|
|
|
42
41
|
</svg>
|
|
43
42
|
{/* 地面光斑:把角色钉在台面上,否则它像浮在纸上 */}
|
|
44
43
|
<span className="member-login-cta__ground" aria-hidden="true" />
|
|
45
|
-
|
|
44
|
+
{/* 素材变量链(主题轨 T-2.3):装饰主视觉走 CSS background,主题包经 --tbox-asset-member-mascot 覆写 */}
|
|
45
|
+
<span className="member-login-cta__mascot" aria-hidden="true" />
|
|
46
46
|
<span className="member-login-cta__grain" aria-hidden="true" />
|
|
47
47
|
</div>
|
|
48
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
* module-member 客户端域样式(0.4.0 D1/D2;头注二轮评审修正)。
|
|
3
|
-
* 视觉源:mall-vis 双演示(MembershipMessageCard/MembershipInviteBanner 金系);域色矩阵对照 docs/
|
|
3
|
+
* 视觉源:mall-vis 双演示(MembershipMessageCard/MembershipInviteBanner 金系);域色矩阵对照 docs/reference/templates.md(视觉体系与域色矩阵)。
|
|
4
4
|
* 基线(D2):本仓库统一 750 设计稿 2x——源码 px 经 rootValue 100 转 rem,渲染折半(375 下 1px 源码 = 0.5px 物理)。
|
|
5
5
|
* POC membership 源按 web 物理 px 直觉作稿(如 avatar 76px——该值在 POC 同款 rootValue 100 管线下渲染折半为 38px,
|
|
6
6
|
* 非设计意图),故本文件按 750 稿基线恢复意图:关键尺寸 ×2 于源值(76→152),其余(卡距/字阶 24/26/34/44)按
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
/* ===== 域变量 ===== */
|
|
15
15
|
.member-card {
|
|
16
|
-
--member-accent: #b45f06;
|
|
16
|
+
--member-accent: var(--tbox-domain-member-accent, #b45f06);
|
|
17
17
|
--member-accent-strong: #b45f06;
|
|
18
18
|
--member-label: #a3925f;
|
|
19
19
|
--member-accent-soft: #fff6e0;
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
--member-warning-light: var(--tbox-warning-light, #fff4e0);
|
|
24
24
|
--member-muted: var(--tbox-text-secondary, #82745e);
|
|
25
25
|
--member-faint: var(--tbox-text-muted, #a69a83);
|
|
26
|
-
--member-border: #ecdec2;
|
|
26
|
+
--member-border: var(--tbox-domain-member-border, #ecdec2);
|
|
27
27
|
--member-bg-subtle: #fff8eb;
|
|
28
|
-
--member-surface: #fffdf8;
|
|
28
|
+
--member-surface: var(--tbox-domain-member-surface, #fffdf8);
|
|
29
29
|
--member-accent-deep: #8c6a2f;
|
|
30
30
|
--member-accent-deep-bg: #f9f1df;
|
|
31
31
|
--member-accent-border: #ecdec2;
|
|
@@ -1597,8 +1597,14 @@
|
|
|
1597
1597
|
bottom: 4PX;
|
|
1598
1598
|
z-index: 2;
|
|
1599
1599
|
width: 132PX;
|
|
1600
|
-
|
|
1600
|
+
aspect-ratio: 200 / 194; /* 资产契约 200×194,等比缩放 */
|
|
1601
1601
|
transform: translateX(-50%);
|
|
1602
|
+
/* 素材变量链(主题品牌资产轨 A1 级联修复):元素只消费不声明(声明会截断主题覆写继承),
|
|
1603
|
+
兜底 = 中立渐变(零品牌资产——B2),主题包经 html[data-theme] 段覆写 --tbox-asset-member-mascot */
|
|
1604
|
+
background-image: var(--tbox-asset-member-mascot, linear-gradient(135deg, #fff8eb, #fffdf8));
|
|
1605
|
+
background-size: contain;
|
|
1606
|
+
background-repeat: no-repeat;
|
|
1607
|
+
background-position: center bottom;
|
|
1602
1608
|
/* 顶部淡入:图片上沿伸进天光区,不化开就是一条横切的硬边 */
|
|
1603
1609
|
-webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 22%, #000 100%);
|
|
1604
1610
|
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 22%, #000 100%);
|
package/src/server/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ServerContext, ServerModule } from '@tbox.cn/app-sdk/server';
|
|
2
2
|
import { loadModuleSkills, withCardEmissionHint, withEarlyExecution } from '@tbox.cn/app-sdk/server';
|
|
3
3
|
import type { RequestContext } from '@tbox.cn/app-contracts';
|
|
4
|
+
import { MEMBER_SNAPSHOT_SERVICE, type MemberSnapshotPort } from '@tbox.cn/app-contracts-mall';
|
|
4
5
|
import memberInfoMeta from './cards/member-info/meta';
|
|
5
6
|
import memberCardSummaryMeta from './cards/member-card-summary/meta';
|
|
6
7
|
import memberPointUsageListMeta from './cards/member-point-usage-list/meta';
|
|
@@ -153,5 +154,24 @@ export const serverModule = {
|
|
|
153
154
|
// 015 D9:主体绑定(promotion acquire 消费;ctx.services 跨模块 resolveService)
|
|
154
155
|
ctx.services.register('member.subject-binding', createSubjectBinding(ctx));
|
|
155
156
|
|
|
157
|
+
// 会员快览工厂(member.snapshot,W3-3):首页联单面板跨模块消费面
|
|
158
|
+
// (账户/授权三态 + 积分 + 入会引导)。三槽组装——enrollment 槽 fail-soft
|
|
159
|
+
// (缺席不拖垮账户/积分主面);工厂运行期执行(注册期纯净铁律)。
|
|
160
|
+
ctx.services.register(
|
|
161
|
+
MEMBER_SNAPSHOT_SERVICE,
|
|
162
|
+
async (reqCtx: RequestContext): Promise<MemberSnapshotPort> => {
|
|
163
|
+
const [account, benefits, enrollment] = await Promise.all([
|
|
164
|
+
resolveMemberAccountPort(reqCtx, ctx),
|
|
165
|
+
resolveMemberBenefitsPort(reqCtx, ctx),
|
|
166
|
+
resolveMemberEnrollmentPort(reqCtx, ctx).catch(() => null),
|
|
167
|
+
]);
|
|
168
|
+
return {
|
|
169
|
+
getAccount: (userId: string) => account.getAccount(userId),
|
|
170
|
+
queryPoints: (userId: string) => benefits.queryPoints(userId),
|
|
171
|
+
...(enrollment?.enrollUrl ? { enrollUrl: enrollment.enrollUrl } : {}),
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
|
|
156
176
|
},
|
|
157
177
|
} satisfies ServerModule;
|
package/tbox.module.json
CHANGED
package/tests/enrollment.test.ts
CHANGED
|
@@ -20,7 +20,7 @@ const state = createInMemoryStateStore();
|
|
|
20
20
|
const ctxFake = { state } as never;
|
|
21
21
|
const actions = createMemberActions(ctxFake, async () => member);
|
|
22
22
|
const reqCtx = (userId = 'u_1'): RequestContext =>
|
|
23
|
-
({ identity: { userId, source: '
|
|
23
|
+
({ identity: { userId, source: 'local' }, attributes: { mall: { miniAppId: 'app', mallId: 'mall-1', subjectId: 's1' } } }) as never;
|
|
24
24
|
|
|
25
25
|
describe('入会链:授权 → 预填 → 提交 → 刷新', () => {
|
|
26
26
|
it('阶段 1:request-alipay-authorization 返回 authorization effect(resultActionId 指向回调动作)', async () => {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
|
|
20
20
|
function requestContext(mallId = 'mall-demo', token = 'user-token'): RequestContext {
|
|
21
21
|
return {
|
|
22
|
-
identity: { userId: 'u_1001', source: '
|
|
22
|
+
identity: { userId: 'u_1001', source: 'local' },
|
|
23
23
|
credentials: { provider: 'dev', token },
|
|
24
24
|
attributes: { mall: { miniAppId: 'demo-app', mallId } },
|
|
25
25
|
};
|
|
@@ -7,7 +7,7 @@ function authenticatedContext(userId = 'user-1', mallId = 'mall-1') {
|
|
|
7
7
|
const memory = createInMemoryMemoryStore();
|
|
8
8
|
const ctx = createServerContext({ memory });
|
|
9
9
|
const reqCtx = {
|
|
10
|
-
identity: { userId, source: '
|
|
10
|
+
identity: { userId, source: 'local' as const },
|
|
11
11
|
attributes: { mall: { mallId, miniAppId: 'app-1', subjectId: 'subject-1' } },
|
|
12
12
|
};
|
|
13
13
|
return { ctx, memory, reqCtx };
|
|
@@ -63,7 +63,7 @@ describe('会员偏好长期记忆', () => {
|
|
|
63
63
|
'intent',
|
|
64
64
|
{ content: '我常带娃来玩' },
|
|
65
65
|
disabled,
|
|
66
|
-
{ identity: { userId: 'user-1', source: '
|
|
66
|
+
{ identity: { userId: 'user-1', source: 'local' as const } },
|
|
67
67
|
);
|
|
68
68
|
expect(disabledResult.text).toContain('暂不可用');
|
|
69
69
|
});
|
package/tests/service.test.ts
CHANGED
|
@@ -53,7 +53,7 @@ function memberPortsOf(getStub: () => Promise<MemberService>): import('../src/se
|
|
|
53
53
|
|
|
54
54
|
function requestContext(mallId = 'mall-demo', token = 'user-token', provider = 'dev'): RequestContext {
|
|
55
55
|
return {
|
|
56
|
-
identity: { userId: 'u_1001', source: '
|
|
56
|
+
identity: { userId: 'u_1001', source: 'local' },
|
|
57
57
|
credentials: { provider, token },
|
|
58
58
|
attributes: { mall: { miniAppId: 'demo-app', mallId } },
|
|
59
59
|
};
|
|
@@ -363,7 +363,7 @@ describe('module-member 槽位轴工具链', () => {
|
|
|
363
363
|
// 上下文统一化:userId 来自运行身份(reqCtx.identity.userId)不再经 LLM 传参——
|
|
364
364
|
// 数值形态字符串由 requestContext 的 userId 承载(注入面关闭后该用例锁「字符串不数值化」)
|
|
365
365
|
const numericCtx = createToolExecContext({
|
|
366
|
-
identity: { userId: '17000001019327925', source: '
|
|
366
|
+
identity: { userId: '17000001019327925', source: 'local' },
|
|
367
367
|
attributes: { mall: { miniAppId: 'demo-app', mallId: 'mall-demo' } },
|
|
368
368
|
});
|
|
369
369
|
const tool = ctx.tools.resolve('queryMemberInfo') as unknown as { execute(input: unknown, execCtx?: ToolExecContextLike): Promise<Record<string, unknown>> };
|
|
@@ -529,7 +529,7 @@ describe('module-member 槽位轴工具链', () => {
|
|
|
529
529
|
});
|
|
530
530
|
|
|
531
531
|
describe('createMemberHandler 查询路径门禁(意图与工具路径一致:不再对非 active 态答「积分 0」)', () => {
|
|
532
|
-
const handlerReqCtx = (source: '
|
|
532
|
+
const handlerReqCtx = (source: 'local' | 'anonymous' = 'local'): RequestContext =>
|
|
533
533
|
({
|
|
534
534
|
identity: { userId: 'u_1001', source },
|
|
535
535
|
attributes: { mall: { miniAppId: 'demo-app', mallId: 'mall-demo' } },
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* member.snapshot 快览服务回归(W3-3 单一模板统一化):
|
|
3
|
+
* register 注册三槽组装工厂——账户/积分主面透传,enrollment 槽 fail-soft
|
|
4
|
+
* (缺席/失败不拖垮主面,enrollUrl 缺省)。
|
|
5
|
+
*/
|
|
6
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
7
|
+
|
|
8
|
+
vi.mock('../src/server/ports', async (importOriginal) => {
|
|
9
|
+
const actual = await importOriginal<typeof import('../src/server/ports')>();
|
|
10
|
+
return {
|
|
11
|
+
...actual,
|
|
12
|
+
resolveMemberAccountPort: vi.fn(),
|
|
13
|
+
resolveMemberBenefitsPort: vi.fn(),
|
|
14
|
+
resolveMemberEnrollmentPort: vi.fn(),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
import type { RequestContext } from '@tbox.cn/app-contracts';
|
|
19
|
+
import type { MemberSnapshotPort } from '@tbox.cn/app-contracts-mall';
|
|
20
|
+
import { MEMBER_SNAPSHOT_SERVICE } from '@tbox.cn/app-contracts-mall';
|
|
21
|
+
import { createServerContext } from '@tbox.cn/app-sdk/server';
|
|
22
|
+
import { serverModule } from '../src/server/index';
|
|
23
|
+
import {
|
|
24
|
+
resolveMemberAccountPort,
|
|
25
|
+
resolveMemberBenefitsPort,
|
|
26
|
+
resolveMemberEnrollmentPort,
|
|
27
|
+
} from '../src/server/ports';
|
|
28
|
+
|
|
29
|
+
const makeReqCtx = () =>
|
|
30
|
+
({
|
|
31
|
+
identity: { userId: 'u_1', source: 'local' },
|
|
32
|
+
conversationId: 'conv_snapshot',
|
|
33
|
+
attributes: { mall: { miniAppId: 'app', mallId: 'mall-1' } },
|
|
34
|
+
}) as unknown as RequestContext;
|
|
35
|
+
|
|
36
|
+
describe('member.snapshot 快览工厂(register 注册,运行期解析)', () => {
|
|
37
|
+
it('register 注册工厂;三槽主面透传 + enrollUrl 透传', async () => {
|
|
38
|
+
const ctx = createServerContext();
|
|
39
|
+
serverModule.register(ctx);
|
|
40
|
+
const factory = ctx.resolveService<(reqCtx: RequestContext) => Promise<MemberSnapshotPort>>(
|
|
41
|
+
MEMBER_SNAPSHOT_SERVICE,
|
|
42
|
+
);
|
|
43
|
+
expect(factory).toBeTypeOf('function');
|
|
44
|
+
|
|
45
|
+
const getAccount = vi.fn(async () => ({ authState: 'authenticated', state: 'active' }));
|
|
46
|
+
const queryPoints = vi.fn(async () => ({ balance: '100' }));
|
|
47
|
+
vi.mocked(resolveMemberAccountPort).mockResolvedValue({ getAccount } as never);
|
|
48
|
+
vi.mocked(resolveMemberBenefitsPort).mockResolvedValue({ queryPoints } as never);
|
|
49
|
+
vi.mocked(resolveMemberEnrollmentPort).mockResolvedValue({ enrollUrl: 'https://enroll.example' } as never);
|
|
50
|
+
|
|
51
|
+
const port = await factory!(makeReqCtx());
|
|
52
|
+
await port.getAccount('u_1');
|
|
53
|
+
await port.queryPoints('u_1');
|
|
54
|
+
expect(getAccount).toHaveBeenCalledWith('u_1');
|
|
55
|
+
expect(queryPoints).toHaveBeenCalledWith('u_1');
|
|
56
|
+
expect(port.enrollUrl).toBe('https://enroll.example');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('enrollment 槽失败 fail-soft:enrollUrl 缺席,账户/积分主面存活', async () => {
|
|
60
|
+
const ctx = createServerContext();
|
|
61
|
+
serverModule.register(ctx);
|
|
62
|
+
const factory = ctx.resolveService<(reqCtx: RequestContext) => Promise<MemberSnapshotPort>>(
|
|
63
|
+
MEMBER_SNAPSHOT_SERVICE,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const getAccount = vi.fn(async () => ({ authState: 'authenticated', state: 'not_enrolled' }));
|
|
67
|
+
vi.mocked(resolveMemberAccountPort).mockResolvedValue({ getAccount } as never);
|
|
68
|
+
vi.mocked(resolveMemberBenefitsPort).mockResolvedValue({ queryPoints: vi.fn() } as never);
|
|
69
|
+
vi.mocked(resolveMemberEnrollmentPort).mockRejectedValue(new Error('enrollment down'));
|
|
70
|
+
|
|
71
|
+
const port = await factory!(makeReqCtx());
|
|
72
|
+
await expect(port.getAccount('u_1')).resolves.toMatchObject({ state: 'not_enrolled' });
|
|
73
|
+
expect(port.enrollUrl).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
});
|
package/tests/status.test.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { RequestContext } from '@tbox.cn/app-contracts';
|
|
|
7
7
|
import type { ServerContext } from '@tbox.cn/app-sdk/server';
|
|
8
8
|
import { resolveMemberStatus, MEMBER_QUERY_NOTICES } from '../src/server/status';
|
|
9
9
|
|
|
10
|
-
const reqCtx = (source: '
|
|
10
|
+
const reqCtx = (source: 'local' | 'anonymous' = 'local'): RequestContext =>
|
|
11
11
|
({
|
|
12
12
|
identity: { userId: 'u_1001', source },
|
|
13
13
|
attributes: { mall: { miniAppId: 'demo-app', mallId: 'mall-demo' } },
|
|
Binary file
|
|
Binary file
|