@tbox.cn/app-contracts-mall 0.1.1 → 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.
Files changed (78) hide show
  1. package/README.md +16 -2
  2. package/dist/alipay-activity/cards.d.ts +305 -0
  3. package/dist/assembly.d.ts +54 -0
  4. package/dist/chunk-KIZD6FZ2.js +43 -0
  5. package/dist/deployment.d.ts +42 -0
  6. package/dist/domain/activity.d.ts +64 -0
  7. package/dist/domain/coupon.d.ts +2 -0
  8. package/dist/domain/entitlement.d.ts +53 -0
  9. package/dist/domain/offer.d.ts +111 -0
  10. package/dist/domain/operation.d.ts +22 -0
  11. package/dist/domain/parking.d.ts +195 -12
  12. package/dist/domain/points.d.ts +3 -2
  13. package/dist/domain/shopping-guide.d.ts +201 -0
  14. package/dist/guard.d.ts +50 -0
  15. package/dist/index.d.ts +22 -2
  16. package/dist/member/cards.d.ts +940 -0
  17. package/dist/parking/cards.d.ts +1271 -0
  18. package/dist/promotion/cards.d.ts +2529 -0
  19. package/dist/query-context.d.ts +47 -0
  20. package/dist/runtime.d.ts +20 -0
  21. package/dist/runtime.js +1281 -0
  22. package/dist/scope.d.ts +76 -0
  23. package/dist/server/index.d.ts +11 -0
  24. package/dist/server/index.js +80 -0
  25. package/dist/server/mall-context.d.ts +24 -0
  26. package/dist/server/mall-control-plane.d.ts +8 -0
  27. package/dist/server/request-credentials.d.ts +22 -0
  28. package/dist/services/customer-service.d.ts +11 -0
  29. package/dist/services/mall-info.d.ts +26 -0
  30. package/dist/services/member.d.ts +243 -9
  31. package/dist/services/parking.d.ts +105 -12
  32. package/dist/services/promotion.d.ts +100 -4
  33. package/dist/services/shopping-guide.d.ts +97 -0
  34. package/dist/shared/cards.d.ts +42 -0
  35. package/dist/shopping-guide/cards.d.ts +7039 -0
  36. package/package.json +19 -8
  37. package/src/alipay-activity/cards.ts +66 -0
  38. package/src/assembly.ts +103 -0
  39. package/src/deployment.ts +44 -0
  40. package/src/domain/activity.ts +66 -0
  41. package/src/domain/coupon.ts +3 -0
  42. package/src/domain/entitlement.ts +56 -0
  43. package/src/domain/offer.ts +120 -0
  44. package/src/domain/operation.ts +40 -0
  45. package/src/domain/parking.ts +206 -12
  46. package/src/domain/points.ts +3 -2
  47. package/src/domain/shopping-guide.ts +242 -0
  48. package/src/guard.ts +48 -0
  49. package/src/index.ts +22 -2
  50. package/src/member/cards.ts +209 -0
  51. package/src/parking/cards.ts +233 -0
  52. package/src/promotion/cards.ts +290 -0
  53. package/src/query-context.ts +81 -0
  54. package/src/runtime.ts +41 -0
  55. package/src/scope.ts +92 -0
  56. package/src/server/index.ts +11 -0
  57. package/src/server/mall-context.ts +39 -0
  58. package/src/server/mall-control-plane.ts +56 -0
  59. package/src/server/request-credentials.ts +43 -0
  60. package/src/service-slots.json +23 -0
  61. package/src/services/customer-service.ts +12 -0
  62. package/src/services/mall-info.ts +31 -0
  63. package/src/services/member.ts +354 -9
  64. package/src/services/parking.ts +161 -11
  65. package/src/services/promotion.ts +124 -4
  66. package/src/services/shopping-guide.ts +138 -0
  67. package/src/shared/cards.ts +25 -0
  68. package/src/shopping-guide/cards.ts +438 -0
  69. package/tests/assembly-validate-scope.test.ts +132 -0
  70. package/tests/cards.test.ts +586 -0
  71. package/tests/context-unification.test.ts +73 -0
  72. package/tests/mall-control-plane.test.ts +86 -0
  73. package/tests/member-status.test.ts +197 -0
  74. package/tests/query-context.test.ts +111 -0
  75. package/tests/request-credentials.test.ts +38 -0
  76. package/tests/resolve-primitives.test.ts +55 -0
  77. package/tests/service-slots.test.ts +78 -0
  78. package/tsconfig.json +1 -1
@@ -0,0 +1,1281 @@
1
+ import {
2
+ MALL_SCOPE_KEY,
3
+ extractMallScope,
4
+ mallScopeOf,
5
+ mallScopeSchema,
6
+ mallSlot,
7
+ parseMallScope,
8
+ readLoginMallId
9
+ } from "./chunk-KIZD6FZ2.js";
10
+
11
+ // src/query-context.ts
12
+ function mallScopeOrEmpty(reqCtx) {
13
+ return extractMallScope(reqCtx) ?? { miniAppId: "", mallId: "" };
14
+ }
15
+ function mallSubjectIdOf(reqCtx) {
16
+ return reqCtx.identity && reqCtx.identity.source !== "anonymous" ? reqCtx.identity.userId : void 0;
17
+ }
18
+ function withMallScopeFromQuery(reqCtx, query, opts) {
19
+ const text = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
20
+ const mallId = text(query["mallId"]);
21
+ if (!mallId) return reqCtx;
22
+ const miniAppId = text(query["miniAppId"]) ?? text(opts?.miniAppId);
23
+ return {
24
+ ...reqCtx,
25
+ attributes: {
26
+ ...reqCtx.attributes,
27
+ [MALL_SCOPE_KEY]: miniAppId ? { mallId, miniAppId } : { mallId }
28
+ }
29
+ };
30
+ }
31
+ function toMallQueryContext(reqCtx) {
32
+ const subjectId = mallSubjectIdOf(reqCtx);
33
+ return {
34
+ scope: mallScopeOrEmpty(reqCtx),
35
+ ...subjectId ? { subjectId } : {},
36
+ requestContext: reqCtx
37
+ };
38
+ }
39
+
40
+ // src/assembly.ts
41
+ var AUTH_LOGIN_SERVICE = "auth.alipay-login";
42
+ function isValidMallShape(attributes) {
43
+ const mall = attributes[MALL_SCOPE_KEY];
44
+ if (!mall || typeof mall !== "object") return true;
45
+ const mallId = mall.mallId;
46
+ return typeof mallId === "string" && mallId.length > 0;
47
+ }
48
+ function createMallRuntimeAssembly(controlPlane) {
49
+ return {
50
+ extractScopeKey(ctx) {
51
+ const scope = extractMallScope(ctx);
52
+ return scope?.mallId ?? "";
53
+ },
54
+ validateScope(attributes) {
55
+ const ok = isValidMallShape(attributes);
56
+ if (!ok) {
57
+ console.error(
58
+ "[MALL] HELLO context \u5F62\u72B6\u975E\u6CD5\uFF08\u9700 mall.mallId \u975E\u7A7A\u2014\u2014URL \u53C2\u6570 ?mallId=\uFF1BminiAppId \u53EF\u9009\uFF09"
59
+ );
60
+ }
61
+ return ok;
62
+ },
63
+ buildScope(attributes) {
64
+ const scope = parseMallScope(attributes);
65
+ if (!scope) return {};
66
+ return {
67
+ mallId: scope.mallId,
68
+ ...scope.miniAppId !== void 0 ? { miniAppId: scope.miniAppId } : {}
69
+ };
70
+ },
71
+ extractMallScope,
72
+ controlPlane
73
+ };
74
+ }
75
+ function createMallContextValidator() {
76
+ return isValidMallShape;
77
+ }
78
+
79
+ // src/services/member.ts
80
+ var MEMBER_ACCOUNT_SERVICE = "member.account";
81
+ var MEMBER_PROFILE_SERVICE = "member.profile";
82
+ var MEMBER_CARD_SERVICE = "member.card";
83
+ var MEMBER_BENEFITS_SERVICE = "member.benefits";
84
+ var MEMBER_ENROLLMENT_SERVICE = "member.enrollment";
85
+ function classifyMemberOutcome(identity, account) {
86
+ if (identity?.source === "anonymous") return "unauthenticated";
87
+ if (!account) return "unknown";
88
+ if (account.authState === "unauthenticated") return "unauthenticated";
89
+ return account.state;
90
+ }
91
+ function externalMemberRefOf(account) {
92
+ return account.primaryMallCardNo ?? account.memberRef;
93
+ }
94
+ var MEMBER_GATE_NOTICES = {
95
+ unauthenticated: "\u8BF7\u5148\u767B\u5F55\u540E\u518D\u4F7F\u7528\u8BE5\u670D\u52A1",
96
+ not_enrolled: "\u5B8C\u6210\u5165\u4F1A\u540E\u5373\u53EF\u4F7F\u7528\u8BE5\u670D\u52A1",
97
+ closed: "\u91CD\u65B0\u5165\u4F1A\u540E\u53EF\u6062\u590D\u4F7F\u7528\u8BE5\u670D\u52A1"
98
+ };
99
+ function memberGateCardOf(userId, status) {
100
+ const { outcome } = status;
101
+ if (outcome === "unauthenticated") {
102
+ const loginUrl = status.loginUrl?.trim() || void 0;
103
+ return {
104
+ cardType: "member-login-cta",
105
+ data: { title: "\u767B\u5F55\u540E\u7EE7\u7EED", ...loginUrl ? { loginUrl } : {} },
106
+ // note 契约(W7,2026-09-01):主体+动作(模型据此答话转述——「点击卡片登录」)
107
+ note: "\u672A\u767B\u5F55 \xB7 \u70B9\u51FB\u5361\u7247\u767B\u5F55"
108
+ };
109
+ }
110
+ if (outcome !== "not_enrolled" && outcome !== "closed") return void 0;
111
+ if (!userId) return void 0;
112
+ const enrollUrl = status.enrollUrl?.trim() || void 0;
113
+ return {
114
+ cardType: "member-enrollment-cta",
115
+ data: {
116
+ userId,
117
+ authState: "authenticated",
118
+ state: outcome,
119
+ title: "\u5165\u4F1A\u540E\u7EE7\u7EED",
120
+ ...enrollUrl ? { enrollUrl } : {}
121
+ },
122
+ note: outcome === "not_enrolled" ? "\u672A\u5165\u4F1A \xB7 \u70B9\u51FB\u5361\u7247\u5B8C\u6210\u5165\u4F1A" : "\u5DF2\u9000\u4F1A \xB7 \u70B9\u51FB\u5361\u7247\u91CD\u65B0\u5165\u4F1A"
123
+ };
124
+ }
125
+ async function resolveMemberGate(factory, reqCtx) {
126
+ if (!factory) return void 0;
127
+ let status;
128
+ try {
129
+ status = await factory(reqCtx);
130
+ } catch {
131
+ return void 0;
132
+ }
133
+ const { outcome } = status;
134
+ if (outcome !== "unauthenticated" && outcome !== "not_enrolled" && outcome !== "closed") {
135
+ return void 0;
136
+ }
137
+ const card = memberGateCardOf(reqCtx.identity?.userId ?? "", status);
138
+ return {
139
+ notice: MEMBER_GATE_NOTICES[outcome],
140
+ ...card ? { card } : {}
141
+ };
142
+ }
143
+
144
+ // src/services/parking.ts
145
+ var PARKING_QUERY_SERVICE = "parking.query";
146
+ var PARKING_PAYMENT_SERVICE = "parking.payment";
147
+ var PARKING_VEHICLE_SERVICE = "parking.vehicle";
148
+
149
+ // src/services/promotion.ts
150
+ var PROMOTION_OFFERS_SERVICE = "promotion.offers";
151
+ var PROMOTION_ENTITLEMENTS_SERVICE = "promotion.entitlements";
152
+ var PROMOTION_ACTIVITIES_SERVICE = "promotion.activities";
153
+ var PROMOTION_ACQUISITION_SERVICE = "promotion.acquisition";
154
+ var PROMOTION_ACTIVITY_ROUTING_POLICY = "promotion.activity-routing";
155
+
156
+ // src/services/shopping-guide.ts
157
+ var SHOPPING_CATALOG_SERVICE = "shopping-guide.catalog";
158
+ var SHOPPING_SHOPS_SERVICE = "shopping-guide.shops";
159
+ var SHOPPING_CATEGORIES_SERVICE = "shopping-guide.categories";
160
+ var SHOPPING_DIRECTORY_SERVICE = "shopping-guide.directory";
161
+
162
+ // src/services/mall-info.ts
163
+ var MALL_INFO_SERVICE = "mall.info";
164
+
165
+ // src/guard.ts
166
+ import { z } from "zod";
167
+ var mallLocationSchema = z.object({
168
+ latitude: z.string().min(1),
169
+ longitude: z.string().min(1),
170
+ mallId: z.string().optional(),
171
+ name: z.string().optional()
172
+ });
173
+ function parseMallLocation(raw) {
174
+ if (!raw || typeof raw !== "object") return void 0;
175
+ const result = mallLocationSchema.safeParse(raw);
176
+ return result.success ? result.data : void 0;
177
+ }
178
+ var mallUserRefSchema = z.object({
179
+ userId: z.string().min(1),
180
+ subjectId: z.string().optional()
181
+ });
182
+ function parseMallUserRef(raw) {
183
+ if (!raw || typeof raw !== "object") return void 0;
184
+ const result = mallUserRefSchema.safeParse(raw);
185
+ return result.success ? result.data : void 0;
186
+ }
187
+
188
+ // src/shopping-guide/cards.ts
189
+ import { z as z3 } from "zod";
190
+
191
+ // src/shared/cards.ts
192
+ import { z as z2 } from "zod";
193
+ var actionDraftSchema = z2.discriminatedUnion("kind", [
194
+ z2.object({
195
+ kind: z2.literal("send"),
196
+ label: z2.string().min(1),
197
+ /** 发给服务端 AI 的完整指令(可含隐藏上下文如 merchantId);缺省用 label */
198
+ value: z2.string().optional(),
199
+ /** 用户气泡展示文本(有值时 sendMessage 走 visible=false 隐藏,只展示此文本为气泡副本);
200
+ * 缺省则 visible=true,直接展示 value/label */
201
+ visibleValue: z2.string().optional()
202
+ }),
203
+ z2.object({ kind: z2.literal("link"), label: z2.string().min(1), url: z2.string().min(1) })
204
+ ]);
205
+
206
+ // src/shopping-guide/cards.ts
207
+ var httpsUrlSchema = z3.string().regex(/^https:\/\//).max(2048);
208
+ var isoDateTimeSchema = z3.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/);
209
+ var moneySchema = z3.object({
210
+ currency: z3.literal("CNY"),
211
+ amountMinor: z3.number().int().min(0),
212
+ display: z3.string().min(1)
213
+ });
214
+ var priceSummarySchema = z3.object({
215
+ sale: moneySchema.optional(),
216
+ original: moneySchema.optional(),
217
+ promotion: moneySchema.optional()
218
+ });
219
+ var evidenceSchema = z3.object({
220
+ code: z3.string().min(1),
221
+ label: z3.string().min(1),
222
+ value: z3.string().optional(),
223
+ observedAt: isoDateTimeSchema,
224
+ expiresAt: isoDateTimeSchema.optional(),
225
+ sourceKind: z3.enum(["catalog", "merchant", "mall", "policy"])
226
+ });
227
+ var reasonItemSchema = z3.object({ code: z3.string().min(1), label: z3.string().min(1) });
228
+ var merchantLocationSchema = z3.object({
229
+ buildingName: z3.string().optional(),
230
+ floorName: z3.string().optional(),
231
+ unitName: z3.string().optional(),
232
+ displayText: z3.string().min(1),
233
+ poiId: z3.string().optional()
234
+ });
235
+ var shopLocationSchema = merchantLocationSchema;
236
+ var merchantStatusSchema = z3.object({
237
+ code: z3.enum(["enabled", "disabled", "unknown"]),
238
+ label: z3.string().min(1),
239
+ observedAt: isoDateTimeSchema
240
+ });
241
+ var shopStatusSchema = merchantStatusSchema;
242
+ var pageInfoSchema = z3.object({
243
+ page: z3.number().int().min(1),
244
+ // max 200(0.7.5 放宽,原 100):品牌导览常驻入口经 port 直调 pageSize=200 一次拉全量,
245
+ // provider 回显值入 pageInfo 需过卡 schema(card-emitter safeParse);向后兼容(旧值域 ⊂ 新值域)
246
+ pageSize: z3.number().int().min(1).max(200),
247
+ total: z3.number().int().min(0),
248
+ hasMore: z3.boolean()
249
+ });
250
+ var refinementSchema = z3.object({ label: z3.string().min(1), queryText: z3.string().min(1) });
251
+ var shopCouponSchema = z3.object({
252
+ name: z3.string().min(1),
253
+ imageUrl: httpsUrlSchema.optional(),
254
+ description: z3.string().optional(),
255
+ faceValue: z3.number().optional(),
256
+ salePrice: z3.number().optional(),
257
+ applicableCategories: z3.array(z3.string()).optional(),
258
+ validHours: z3.number().optional(),
259
+ usageTimeText: z3.string().optional(),
260
+ purchaseUrl: z3.string().max(2048).optional(),
261
+ freeCouponClaimMode: z3.enum(["DIRECT", "REDIRECT"]).optional(),
262
+ offerRef: z3.string().min(1).optional()
263
+ });
264
+ var productListCardDataSchema = z3.object({
265
+ context: z3.enum(["recommendation", "search", "similar", "history"]),
266
+ summary: z3.string().optional(),
267
+ items: z3.array(
268
+ z3.object({
269
+ productId: z3.string().min(1),
270
+ name: z3.string().min(1),
271
+ imageUrl: httpsUrlSchema.optional(),
272
+ brand: z3.string().optional(),
273
+ categoryPath: z3.array(z3.string()),
274
+ price: priceSummarySchema,
275
+ availability: z3.object({
276
+ status: z3.enum(["in_stock", "out_of_stock", "limited", "unknown"]),
277
+ label: z3.string(),
278
+ marketable: z3.boolean(),
279
+ observedAt: isoDateTimeSchema
280
+ }),
281
+ merchant: z3.object({
282
+ merchantId: z3.string(),
283
+ name: z3.string(),
284
+ location: merchantLocationSchema.optional()
285
+ }),
286
+ badges: z3.array(z3.string()),
287
+ reasons: z3.array(reasonItemSchema).optional(),
288
+ evidence: z3.array(evidenceSchema).optional(),
289
+ caveats: z3.array(z3.string()),
290
+ itemActions: z3.array(actionDraftSchema)
291
+ })
292
+ ),
293
+ noResultsReason: z3.string().optional(),
294
+ pageInfo: pageInfoSchema.optional(),
295
+ refinements: z3.array(refinementSchema)
296
+ });
297
+ var shopListCardDataSchema = z3.object({
298
+ context: z3.enum(["recommendation", "search"]),
299
+ /** mall scope 透传:供客户端侧边栏详情 HTTP 请求携带 mallId 与 miniAppId(工具执行时注入) */
300
+ mallId: z3.string().optional(),
301
+ /** 小程序 appId(miniAppId 唯一真值透传;HTTP /shop-detail 鉴权用) */
302
+ miniAppId: z3.string().optional(),
303
+ summary: z3.string().optional(),
304
+ categoryTabs: z3.array(z3.object({ code: z3.string(), name: z3.string() })).optional(),
305
+ items: z3.array(
306
+ z3.object({
307
+ merchantId: z3.string(),
308
+ name: z3.string(),
309
+ logoUrl: httpsUrlSchema.optional(),
310
+ coverUrl: httpsUrlSchema.optional(),
311
+ brand: z3.string().optional(),
312
+ businessCategories: z3.array(z3.string()),
313
+ location: merchantLocationSchema,
314
+ status: merchantStatusSchema,
315
+ contactInfo: z3.array(z3.object({ channel: z3.string(), value: z3.string() })).optional(),
316
+ services: z3.array(z3.string()),
317
+ promotionFacts: z3.array(z3.string()),
318
+ reasons: z3.array(reasonItemSchema).optional(),
319
+ evidence: z3.array(evidenceSchema).optional(),
320
+ itemActions: z3.array(actionDraftSchema),
321
+ /** 门店关联优惠券(列表卡透传,供点击下钻时直接展示,避免二次请求) */
322
+ coupons: z3.array(shopCouponSchema).optional()
323
+ })
324
+ ),
325
+ noResultsReason: z3.string().optional(),
326
+ pageInfo: pageInfoSchema.optional(),
327
+ refinements: z3.array(refinementSchema)
328
+ });
329
+ var merchantListCardDataSchema = shopListCardDataSchema;
330
+ var productDetailCardDataSchema = z3.object({
331
+ productId: z3.string().min(1),
332
+ name: z3.string().min(1),
333
+ description: z3.string().optional(),
334
+ imageUrls: z3.array(httpsUrlSchema),
335
+ brand: z3.string().optional(),
336
+ categoryPath: z3.array(z3.string()),
337
+ price: priceSummarySchema,
338
+ availability: z3.object({
339
+ status: z3.enum(["in_stock", "out_of_stock", "limited", "unknown"]),
340
+ label: z3.string(),
341
+ marketable: z3.boolean(),
342
+ observedAt: isoDateTimeSchema
343
+ }),
344
+ merchant: z3.object({
345
+ merchantId: z3.string(),
346
+ name: z3.string(),
347
+ location: merchantLocationSchema.optional()
348
+ }),
349
+ attributes: z3.array(z3.object({ name: z3.string(), value: z3.string() })),
350
+ promotionFacts: z3.array(z3.string()),
351
+ evidence: z3.array(evidenceSchema),
352
+ humanGuideAvailable: z3.boolean(),
353
+ itemActions: z3.array(actionDraftSchema)
354
+ });
355
+ var shopDetailCardDataSchema = z3.object({
356
+ merchantId: z3.string(),
357
+ name: z3.string(),
358
+ /** mall scope 透传:供客户端 Sheet 后台 detail HTTP 请求携带(工具执行时注入,与 shop-list 同源) */
359
+ mallId: z3.string().optional(),
360
+ /** 小程序 appId(miniAppId 唯一真值透传;HTTP /shop-detail 鉴权用) */
361
+ miniAppId: z3.string().optional(),
362
+ logoUrl: httpsUrlSchema.optional(),
363
+ coverUrls: z3.array(httpsUrlSchema),
364
+ brand: z3.string().optional(),
365
+ businessCategories: z3.array(z3.string()),
366
+ location: merchantLocationSchema,
367
+ status: merchantStatusSchema,
368
+ description: z3.string().optional(),
369
+ contactInfo: z3.array(z3.object({ channel: z3.string(), value: z3.string() })).optional(),
370
+ services: z3.array(z3.string()),
371
+ promotionFacts: z3.array(z3.string()),
372
+ /** 门店关联优惠券列表(来自 couponList;name/imageUrl/faceValue/salePrice/applicableCategories/validHours) */
373
+ coupons: z3.array(shopCouponSchema).optional(),
374
+ evidence: z3.array(evidenceSchema),
375
+ itemActions: z3.array(actionDraftSchema)
376
+ });
377
+ var merchantDetailCardDataSchema = shopDetailCardDataSchema;
378
+ var categoryListCardDataSchema = z3.object({
379
+ categories: z3.array(
380
+ z3.object({
381
+ code: z3.string().min(1),
382
+ name: z3.string().min(1),
383
+ description: z3.string().optional(),
384
+ /** 类目图标 URL;undefined 时前端展示默认图标 */
385
+ iconUrl: httpsUrlSchema.optional(),
386
+ merchantCount: z3.number().int().min(0),
387
+ subCategories: z3.array(z3.object({ code: z3.string(), name: z3.string(), merchantCount: z3.number().int().min(0) })).optional(),
388
+ /** 0.3.2 D4:类别条目动作(send 合成话术/外链) */
389
+ itemActions: z3.array(actionDraftSchema).optional()
390
+ })
391
+ ),
392
+ /** 商场楼栋-楼层结构(与 mall-directory 同语义子集,供 category-list 卡片展示楼层导航) */
393
+ buildings: z3.array(
394
+ z3.object({
395
+ buildingCode: z3.string(),
396
+ buildingName: z3.string(),
397
+ floors: z3.array(
398
+ z3.object({
399
+ floorCode: z3.string(),
400
+ floorName: z3.string(),
401
+ businessCategories: z3.array(z3.string()),
402
+ merchantCount: z3.number().int().min(0),
403
+ /** 楼层条目动作(send:查看该楼层门店列表) */
404
+ itemActions: z3.array(actionDraftSchema).optional()
405
+ })
406
+ )
407
+ })
408
+ ).optional(),
409
+ observedAt: isoDateTimeSchema
410
+ });
411
+ var productComparisonCardDataSchema = z3.object({
412
+ products: z3.array(
413
+ z3.object({
414
+ productId: z3.string().min(1),
415
+ name: z3.string().min(1),
416
+ imageUrl: httpsUrlSchema.optional(),
417
+ brand: z3.string().optional(),
418
+ price: priceSummarySchema,
419
+ availability: z3.object({
420
+ status: z3.enum(["in_stock", "out_of_stock", "limited", "unknown"]),
421
+ label: z3.string(),
422
+ marketable: z3.boolean(),
423
+ observedAt: isoDateTimeSchema
424
+ }),
425
+ merchant: z3.object({ merchantId: z3.string(), name: z3.string() }),
426
+ attributes: z3.array(z3.object({ name: z3.string(), value: z3.string() })),
427
+ caveats: z3.array(z3.string())
428
+ })
429
+ ),
430
+ /** 0.3.2 D4:刷新截止时间(ISO);到期后渲染端禁用全部条目交互 */
431
+ refreshRequiredAt: isoDateTimeSchema.optional(),
432
+ observedAt: isoDateTimeSchema
433
+ });
434
+ var mallDirectoryCardDataSchema = z3.object({
435
+ mallId: z3.string(),
436
+ mallName: z3.string(),
437
+ buildings: z3.array(
438
+ z3.object({
439
+ buildingCode: z3.string(),
440
+ buildingName: z3.string(),
441
+ floors: z3.array(
442
+ z3.object({
443
+ floorCode: z3.string(),
444
+ floorName: z3.string(),
445
+ businessCategories: z3.array(z3.string()),
446
+ merchantCount: z3.number().int().min(0),
447
+ /** 0.3.2 D4:楼层条目动作(send:查看楼层门店) */
448
+ itemActions: z3.array(actionDraftSchema).optional()
449
+ })
450
+ )
451
+ })
452
+ ),
453
+ observedAt: isoDateTimeSchema
454
+ });
455
+ var nearbyMallListCardDataSchema = z3.object({
456
+ query: z3.string().optional(),
457
+ malls: z3.array(
458
+ z3.object({
459
+ mallId: z3.string(),
460
+ name: z3.string(),
461
+ address: z3.string(),
462
+ distanceKm: z3.number().min(0).optional(),
463
+ status: z3.object({ code: z3.enum(["open", "closed", "unknown"]), label: z3.string() }),
464
+ itemActions: z3.array(actionDraftSchema)
465
+ })
466
+ )
467
+ });
468
+ var customerServiceFaqCardDataSchema = z3.object({
469
+ query: z3.string().min(1),
470
+ faqs: z3.array(
471
+ z3.object({
472
+ question: z3.string().min(1),
473
+ answer: z3.string().min(1),
474
+ category: z3.string().optional(),
475
+ relevanceScore: z3.number().min(0).max(1),
476
+ /** 0.3.2 D4:答案参考外链(openLink) */
477
+ referenceUrl: httpsUrlSchema.optional()
478
+ })
479
+ ),
480
+ /** 客服电话(015:deployment.malls 经 mall-directory 服务注入;缺省不渲染拨打条目) */
481
+ contactPhone: z3.string().min(1).optional(),
482
+ noResultsReason: z3.string().optional()
483
+ });
484
+ var humanGuideListCardDataSchema = z3.object({
485
+ merchantId: z3.string(),
486
+ merchantName: z3.string(),
487
+ guides: z3.array(
488
+ z3.object({
489
+ guideId: z3.string(),
490
+ name: z3.string(),
491
+ title: z3.string().optional(),
492
+ avatarUrl: httpsUrlSchema.optional(),
493
+ contactInfo: z3.array(z3.object({ channel: z3.string(), value: z3.string() })).optional(),
494
+ available: z3.boolean(),
495
+ itemActions: z3.array(actionDraftSchema)
496
+ })
497
+ )
498
+ });
499
+ var locationHandoffCardDataSchema = z3.object({
500
+ merchantId: z3.string(),
501
+ merchantName: z3.string(),
502
+ location: merchantLocationSchema,
503
+ mapUrl: httpsUrlSchema.optional(),
504
+ navigation: z3.object({
505
+ provider: z3.enum(["amap", "builtin"]),
506
+ launchParams: z3.record(z3.string(), z3.string()).optional()
507
+ }).optional(),
508
+ itemActions: z3.array(actionDraftSchema)
509
+ });
510
+ var recommendMerchantsCardDataSchema = z3.object({
511
+ summary: z3.string().optional(),
512
+ /** 类目筛选 Tab(来自 list-categories;有值时渲染 Tab 栏) */
513
+ categoryTabs: z3.array(
514
+ z3.object({
515
+ code: z3.string(),
516
+ name: z3.string()
517
+ })
518
+ ).optional(),
519
+ items: z3.array(
520
+ z3.object({
521
+ merchantId: z3.string(),
522
+ name: z3.string(),
523
+ logoUrl: httpsUrlSchema.optional(),
524
+ coverUrl: httpsUrlSchema.optional(),
525
+ brand: z3.string().optional(),
526
+ businessCategories: z3.array(z3.string()),
527
+ location: merchantLocationSchema,
528
+ status: merchantStatusSchema,
529
+ description: z3.string().optional(),
530
+ contactInfo: z3.array(z3.object({ channel: z3.string(), value: z3.string() })).optional(),
531
+ services: z3.array(z3.string()).optional(),
532
+ /** 营业时间/经营状态文本(如 "10:00营业"),来自知识库 经营状态 字段 */
533
+ operatingStatus: z3.string().optional(),
534
+ /** 评分(如 "4.8"),来自知识库 评分 字段 */
535
+ rating: z3.string().optional(),
536
+ /** 人均消费文本(如 "¥202"),来自知识库 人均消费 字段(分为单位时自动格式化) */
537
+ avgSpend: z3.string().optional(),
538
+ promotionFacts: z3.array(z3.string()),
539
+ itemActions: z3.array(actionDraftSchema)
540
+ })
541
+ ),
542
+ noResultsReason: z3.string().optional(),
543
+ observedAt: isoDateTimeSchema
544
+ });
545
+ var shoppingGuideCardDataSchemas = {
546
+ "product-list": productListCardDataSchema,
547
+ "product-detail": productDetailCardDataSchema,
548
+ "shop-list": shopListCardDataSchema,
549
+ "shop-detail": shopDetailCardDataSchema,
550
+ "category-list": categoryListCardDataSchema,
551
+ "product-comparison": productComparisonCardDataSchema,
552
+ "mall-directory": mallDirectoryCardDataSchema,
553
+ "nearby-mall-list": nearbyMallListCardDataSchema,
554
+ "customer-service-faq": customerServiceFaqCardDataSchema,
555
+ "human-guide-list": humanGuideListCardDataSchema,
556
+ "location-handoff": locationHandoffCardDataSchema,
557
+ "recommend-merchants": recommendMerchantsCardDataSchema
558
+ };
559
+
560
+ // src/member/cards.ts
561
+ import { z as z4 } from "zod";
562
+ var memberAuthStateSchema = z4.enum(["authenticated", "unauthenticated"]);
563
+ var memberStateSchema = z4.enum(["unknown", "active", "not_enrolled", "closed"]);
564
+ var MEMBER_PREFERENCE_VALUES = [
565
+ "\u6211\u5E38\u6765\u4E70\u8863\u670D",
566
+ "\u6211\u5E38\u5E26\u5A03\u6765\u73A9",
567
+ "\u6211\u5E38\u6765\u5403\u7F8E\u98DF"
568
+ ];
569
+ var memberPreferenceValueSchema = z4.enum(MEMBER_PREFERENCE_VALUES);
570
+ var MEMBER_PREFERENCE_PROMPTS = MEMBER_PREFERENCE_VALUES.map((value) => ({ value, query: value }));
571
+ var MEMBER_PREFERENCE_RECOMMENDATION_QUERIES = {
572
+ "\u6211\u5E38\u6765\u4E70\u8863\u670D": "\u63A8\u8350\u9002\u5408\u8D2D\u4E70\u7684\u670D\u88C5\u95E8\u5E97\u548C\u5546\u54C1",
573
+ "\u6211\u5E38\u5E26\u5A03\u6765\u73A9": "\u63A8\u8350\u9002\u5408\u5E26\u5A03\u7684\u4EB2\u5B50\u5A31\u4E50\u95E8\u5E97",
574
+ "\u6211\u5E38\u6765\u5403\u7F8E\u98DF": "\u63A8\u8350\u503C\u5F97\u53BB\u7684\u9910\u996E\u7F8E\u98DF\u95E8\u5E97"
575
+ };
576
+ var memberInfoCardDataSchema = z4.object({
577
+ userId: z4.string().min(1),
578
+ authState: memberAuthStateSchema,
579
+ state: memberStateSchema,
580
+ displayName: z4.string().optional(),
581
+ avatarUrl: z4.string().optional(),
582
+ contactDisplay: z4.string().optional(),
583
+ memberRef: z4.string().optional(),
584
+ registeredAt: z4.string().optional(),
585
+ labels: z4.array(z4.object({ labelRef: z4.string(), name: z4.string() }))
586
+ });
587
+ var memberCardSummaryCardDataSchema = z4.object({
588
+ userId: z4.string().min(1),
589
+ cardRef: z4.string(),
590
+ cardDisplay: z4.string(),
591
+ status: z4.enum(["active", "inactive", "frozen", "expired", "unknown"]),
592
+ levelName: z4.string().optional(),
593
+ availablePoints: z4.number().int().min(0),
594
+ cardImageUrl: z4.string().optional(),
595
+ pointsRuleImageUrl: z4.string().url().optional(),
596
+ pointsRuleContent: z4.string().min(1).max(2e4).optional(),
597
+ pointsUrl: z4.string().url().optional(),
598
+ presentation: z4.object({
599
+ variant: z4.enum(["blue", "silver", "gold", "black"]),
600
+ labelsEmbedded: z4.boolean().optional()
601
+ }).optional(),
602
+ progress: z4.object({
603
+ daySpentCents: z4.number().int().min(0),
604
+ yearSpentCents: z4.number().int().min(0),
605
+ percent: z4.number().min(0).max(100),
606
+ message: z4.string().min(1).max(256)
607
+ }).optional(),
608
+ benefits: z4.array(z4.object({
609
+ benefitRef: z4.string().min(1),
610
+ name: z4.string().min(1).max(128),
611
+ iconUrl: z4.string().url().optional(),
612
+ description: z4.string().min(1).max(128).optional(),
613
+ action: z4.object({
614
+ kind: z4.enum(["miniapp", "dialog", "toast"]),
615
+ url: z4.string().url().optional(),
616
+ title: z4.string().min(1).max(128).optional(),
617
+ text: z4.string().min(1).max(2048).optional()
618
+ }).optional()
619
+ })).max(20).optional(),
620
+ /** 入会后偏好引导;首批固定三项,保留数组形态便于后续扩展。 */
621
+ preferencePrompts: z4.array(z4.object({
622
+ value: memberPreferenceValueSchema,
623
+ query: z4.string().min(1).max(128)
624
+ })).max(8).optional()
625
+ });
626
+ var memberPointUsageListCardDataSchema = z4.object({
627
+ userId: z4.string().min(1),
628
+ balance: z4.number().int(),
629
+ membershipLabel: z4.string().optional(),
630
+ items: z4.array(
631
+ z4.object({
632
+ usageRecordRef: z4.string(),
633
+ title: z4.string(),
634
+ amount: z4.string(),
635
+ usedAt: z4.string().optional(),
636
+ description: z4.string().optional()
637
+ })
638
+ ),
639
+ total: z4.number().int().min(0)
640
+ });
641
+ var memberEnrollmentFormCardDataSchema = z4.object({
642
+ userId: z4.string().min(1),
643
+ state: memberStateSchema,
644
+ /** 表单版本(幂等键组成部分) */
645
+ formVersion: z4.string().min(1),
646
+ /** 表单字段(readOnly = 授权预填锁定;prefill = 预填值) */
647
+ fields: z4.array(
648
+ z4.object({
649
+ fieldId: z4.string(),
650
+ label: z4.string(),
651
+ type: z4.enum(["text", "tel", "select", "date"]),
652
+ required: z4.boolean(),
653
+ readOnly: z4.boolean().optional(),
654
+ prefill: z4.string().optional(),
655
+ placeholder: z4.string().optional(),
656
+ options: z4.array(z4.string()).optional()
657
+ })
658
+ ),
659
+ /** 隐私/条款同意项(required 必勾) */
660
+ consents: z4.array(
661
+ z4.object({
662
+ consentId: z4.string(),
663
+ version: z4.string(),
664
+ title: z4.string(),
665
+ required: z4.boolean(),
666
+ url: z4.string().optional()
667
+ })
668
+ ),
669
+ /** 支付宝授权状态(required → 渲染授权按钮;authorized → mobile 预填 readOnly) */
670
+ authorization: z4.object({
671
+ status: z4.enum(["required", "authorized", "unavailable"]),
672
+ mobileMasked: z4.string().optional()
673
+ }),
674
+ /** 手动填写模式提示(授权不可用降级) */
675
+ manualNotice: z4.string().optional()
676
+ });
677
+ var memberEnrollmentStatusCardDataSchema = z4.object({
678
+ userId: z4.string().min(1),
679
+ attemptRef: z4.string().optional(),
680
+ state: z4.enum(["pending_confirmation", "confirmation_timeout", "active", "failed"]),
681
+ memberRef: z4.string().optional(),
682
+ message: z4.string().optional()
683
+ });
684
+ var memberEnrollmentCtaCardDataSchema = z4.object({
685
+ userId: z4.string().min(1),
686
+ authState: z4.literal("authenticated"),
687
+ state: z4.enum(["not_enrolled", "closed"]),
688
+ /**
689
+ * alipays:// 深链,由部署配置注入;**可选透传素材**——出卡不依赖它,
690
+ * 壳能力(getLoginState/openGate)缺席时兜底 openLink 用,未配置恒出卡(无此字段)
691
+ */
692
+ enrollUrl: z4.string().min(1).refine((value) => value.startsWith("alipays://") || value.startsWith("https://"), {
693
+ message: "enrollUrl must use alipays:// or https://"
694
+ }).optional(),
695
+ title: z4.string().optional(),
696
+ subtitle: z4.string().optional(),
697
+ /**
698
+ * 入会权益提示列表(工具层注入通用文案;不得包含折扣/免费停车等未经系统确认的承诺)。
699
+ * 缺省不展示,由渲染层按有无决定是否渲染区块。
700
+ */
701
+ perks: z4.array(z4.string()).optional()
702
+ });
703
+ var memberLoginCtaCardDataSchema = z4.object({
704
+ /**
705
+ * 商场小程序登录页深链,由部署配置注入;**可选透传素材**——出卡不依赖它,
706
+ * 壳能力(getLoginState)缺席时兜底 openLink 用,未配置恒出卡(无此字段)
707
+ */
708
+ loginUrl: z4.string().min(1).refine((value) => value.startsWith("alipays://") || value.startsWith("https://"), {
709
+ message: "loginUrl must use alipays:// or https://"
710
+ }).optional(),
711
+ title: z4.string().optional()
712
+ });
713
+ var memberCardDataSchemas = {
714
+ "member-info": memberInfoCardDataSchema,
715
+ "member-card-summary": memberCardSummaryCardDataSchema,
716
+ "member-point-usage-list": memberPointUsageListCardDataSchema,
717
+ "member-enrollment-form": memberEnrollmentFormCardDataSchema,
718
+ "member-enrollment-status": memberEnrollmentStatusCardDataSchema,
719
+ "member-enrollment-cta": memberEnrollmentCtaCardDataSchema,
720
+ "member-login-cta": memberLoginCtaCardDataSchema
721
+ };
722
+
723
+ // src/promotion/cards.ts
724
+ import { z as z6 } from "zod";
725
+
726
+ // src/alipay-activity/cards.ts
727
+ import { z as z5 } from "zod";
728
+ var bumpInVoucherSchema = z5.object({
729
+ prizeId: z5.string(),
730
+ voucherName: z5.string(),
731
+ voucherType: z5.string(),
732
+ reductionAmount: z5.string(),
733
+ thresholdAmountText: z5.string(),
734
+ unit: z5.string(),
735
+ merchantName: z5.string(),
736
+ merchantLogo: z5.string().optional(),
737
+ itemLogo: z5.string().optional()
738
+ });
739
+ var bumpInActStatusSchema = z5.enum([
740
+ "NOT_START",
741
+ "INIT",
742
+ "PROCESSING",
743
+ "FINISH",
744
+ "RECEIVED"
745
+ ]);
746
+ var promotionBumpInActivityCardDataSchema = z5.object({
747
+ activityRef: z5.string(),
748
+ title: z5.string(),
749
+ mainTitle: z5.string().optional(),
750
+ coverUrl: z5.string().optional(),
751
+ /** 联单活动全幅背景图 URL(与 coverUrl 互斥;backgroundUrl 存在时头部采用全幅覆盖布局) */
752
+ backgroundUrl: z5.string().optional(),
753
+ /** 左上角活动类型胶囊标签,如"碰一下联单" */
754
+ tagLabel: z5.string().optional(),
755
+ cardLogoUrl: z5.string().optional(),
756
+ actStatus: bumpInActStatusSchema,
757
+ totalProgress: z5.string().optional(),
758
+ currentProgress: z5.string().optional(),
759
+ progressUnit: z5.string().optional(),
760
+ startAtText: z5.string().optional(),
761
+ endAtText: z5.string().optional(),
762
+ description: z5.string().optional(),
763
+ vouchers: z5.array(bumpInVoucherSchema),
764
+ mode: z5.enum(["detail", "banner"]).default("detail"),
765
+ /** bar(线性进度条,默认)| steps(圆形步骤节点,适合联单任务) */
766
+ progressStyle: z5.enum(["bar", "steps"]).default("bar"),
767
+ /** 参与步骤(联单活动 guide.steps;banner 模式用于渲染步骤进度节点) */
768
+ steps: z5.array(z5.object({ title: z5.string(), description: z5.string().optional() })).optional()
769
+ });
770
+
771
+ // src/promotion/cards.ts
772
+ var imageUrlSchema = z6.string().max(2048).optional();
773
+ var freeCouponClaimModeSchema = z6.enum(["DIRECT", "REDIRECT"]);
774
+ var offerSummarySchema = z6.object({
775
+ offerRef: z6.string().min(1),
776
+ title: z6.string().min(1),
777
+ subtitle: z6.string().optional(),
778
+ offerType: z6.enum(["COUPON", "BUNDLE", "PROMOTION", "ACTIVITY", "GROUPON"]),
779
+ /** 主 facet 一句话(如「满 100 减 20」) */
780
+ benefitText: z6.string().optional(),
781
+ /** 使用门槛(如「满 300 元可用」) */
782
+ thresholdText: z6.string().optional(),
783
+ /**
784
+ * 券的**售价**展示,与 benefitText 是两回事——后者说优惠内容,这里说买这张券要花多少。
785
+ * 免费券给「免费」,付费券给「¥28.8」。文案由 provider 直接给:各厂商币种、小数位与
786
+ * 「免费/0 元」措辞不一,客户端不做数值运算也不反解金额。
787
+ */
788
+ priceText: z6.string().optional(),
789
+ /** 划线原价(如「¥38.8」)。与 priceText 成对出现才有意义,单独给不渲染。 */
790
+ originalPriceText: z6.string().optional(),
791
+ /** 折扣角标(如「7.5折」)。同样是 provider 直出文案,不由前端拿两个价格算。 */
792
+ discountLabel: z6.string().optional(),
793
+ /**
794
+ * 领取按钮文案:免费券「领取」、付费券「抢购」。由 provider 给而非前端按 priceText
795
+ * 猜——「免费」的写法各家不同,猜错就把付费券写成领取。缺省回落「领取」。
796
+ */
797
+ claimActionLabel: z6.string().optional(),
798
+ purchaseUrl: z6.string().max(2048).optional(),
799
+ freeCouponClaimMode: freeCouponClaimModeSchema.optional(),
800
+ /**
801
+ * 下面三条供**列表内的详情浮层**渲染——浮层就地展开,没有二次请求可拉,
802
+ * 需要的信息必须随列表一起下发。厂商不给就不渲染对应区块。
803
+ */
804
+ stockText: z6.string().optional(),
805
+ usageNoticeText: z6.string().optional(),
806
+ guaranteeText: z6.string().optional(),
807
+ usageSceneText: z6.string().optional(),
808
+ usageTimeText: z6.string().optional(),
809
+ claimTimeText: z6.string().optional(),
810
+ usageRuleText: z6.string().optional(),
811
+ /** 可领取(availability.status === 'AVAILABLE') */
812
+ claimable: z6.boolean(),
813
+ availabilityStatus: z6.enum(["AVAILABLE", "UNAVAILABLE", "REQUIRES_ACTION", "UNKNOWN"]).optional(),
814
+ validityText: z6.string().optional(),
815
+ imageUrl: imageUrlSchema,
816
+ /** 0.3.2 D4:条目动作(send:查看详情) */
817
+ itemActions: z6.array(actionDraftSchema).optional(),
818
+ tags: z6.array(z6.string())
819
+ });
820
+ var promotionOfferListCardDataSchema = z6.object({
821
+ presentation: z6.enum(["offer", "promotion", "coupon", "recommendation"]).optional(),
822
+ mode: z6.enum(["search", "claimable", "recommend"]),
823
+ /** 客户端默认展示 4 条;传入正整数可覆盖该上限。 */
824
+ maxItems: z6.number().int().positive().optional(),
825
+ summary: z6.string().optional(),
826
+ items: z6.array(offerSummarySchema),
827
+ noResultsReason: z6.string().optional(),
828
+ nextCursor: z6.string().optional()
829
+ });
830
+ var promotionOfferDetailCardDataSchema = z6.object({
831
+ presentation: z6.enum(["offer", "promotion", "promotion-guide", "coupon", "package"]).optional(),
832
+ offerRef: z6.string().min(1),
833
+ title: z6.string().min(1),
834
+ offerType: z6.enum(["COUPON", "BUNDLE", "PROMOTION", "ACTIVITY", "GROUPON"]),
835
+ subtitle: z6.string().optional(),
836
+ description: z6.string().optional(),
837
+ imageUrl: imageUrlSchema,
838
+ benefitText: z6.string().optional(),
839
+ thresholdText: z6.string().optional(),
840
+ validityText: z6.string().optional(),
841
+ /** 售价三件套,语义同 offerSummary(provider 直出文案,前端不做运算) */
842
+ priceText: z6.string().optional(),
843
+ originalPriceText: z6.string().optional(),
844
+ discountLabel: z6.string().optional(),
845
+ claimActionLabel: z6.string().optional(),
846
+ purchaseUrl: z6.string().max(2048).optional(),
847
+ /** 剩余库存文案(如「剩余:29」);厂商不给就不展示,别拿 0 当「售罄」用 */
848
+ stockText: z6.string().optional(),
849
+ usageNoticeText: z6.string().optional(),
850
+ /** 核销场景(如「万铺小二核销」)——告诉用户这张券在哪、怎么用掉 */
851
+ usageSceneText: z6.string().optional(),
852
+ usageTimeText: z6.string().optional(),
853
+ claimTimeText: z6.string().optional(),
854
+ usageRuleText: z6.string().optional(),
855
+ guaranteeText: z6.string().optional(),
856
+ /** 使用规则/参与步骤 */
857
+ rules: z6.array(z6.string()),
858
+ participationMode: z6.enum([
859
+ "AUTOMATIC_DISCOUNT",
860
+ "CLAIM_THEN_PURCHASE",
861
+ "REGISTER_THEN_ATTEND",
862
+ "GROUP_PURCHASE",
863
+ "UNKNOWN"
864
+ ]).optional(),
865
+ steps: z6.array(z6.object({ title: z6.string(), description: z6.string().optional() })).optional(),
866
+ requirements: z6.array(z6.string()).optional(),
867
+ notice: z6.string().optional(),
868
+ /** 厂商可提供时展示适用门店;可选以兼容历史卡数据。 */
869
+ stores: z6.array(z6.object({
870
+ storeId: z6.string().min(1),
871
+ storeName: z6.string().min(1),
872
+ businessName: z6.string().optional(),
873
+ address: z6.string().optional(),
874
+ floor: z6.string().optional()
875
+ })).optional(),
876
+ bundleItems: z6.array(z6.object({ name: z6.string(), quantity: z6.number().int().positive() })).optional(),
877
+ /** 领取动作是否可用(未登录会员/不可用 → false + unavailableReason) */
878
+ claimable: z6.boolean(),
879
+ unavailableReason: z6.string().optional(),
880
+ caveats: z6.array(z6.string())
881
+ });
882
+ var promotionEntitlementListCardDataSchema = z6.object({
883
+ mallId: z6.string().optional(),
884
+ miniAppId: z6.string().optional(),
885
+ /** 客户端默认展示 4 条;传入正整数可覆盖该上限。 */
886
+ maxItems: z6.number().int().positive().optional(),
887
+ items: z6.array(
888
+ z6.object({
889
+ entitlementRef: z6.string().min(1),
890
+ title: z6.string().min(1),
891
+ imageUrl: imageUrlSchema,
892
+ entitlementType: z6.enum(["COUPON", "BUNDLE", "PROMOTION", "ACTIVITY", "GROUPON"]),
893
+ status: z6.enum(["EFFECTIVE", "USED", "EXPIRED", "INVALID", "UNKNOWN"]),
894
+ codeMasked: z6.string().optional(),
895
+ code: z6.string().optional(),
896
+ qrCodeEnabled: z6.boolean().optional(),
897
+ benefitText: z6.string().optional(),
898
+ thresholdText: z6.string().optional(),
899
+ usageNotice: z6.string().optional(),
900
+ guaranteeText: z6.string().optional(),
901
+ usageSceneText: z6.string().optional(),
902
+ usageTimeText: z6.string().optional(),
903
+ claimTimeText: z6.string().optional(),
904
+ usageRuleText: z6.string().optional(),
905
+ validityText: z6.string().optional(),
906
+ validUntilText: z6.string().optional(),
907
+ /** 0.3.2 D4:条目动作(send:查看详情) */
908
+ itemActions: z6.array(actionDraftSchema).optional(),
909
+ stores: z6.array(z6.object({
910
+ storeId: z6.string(),
911
+ storeName: z6.string(),
912
+ businessName: z6.string().optional(),
913
+ imageUrl: imageUrlSchema,
914
+ address: z6.string().optional(),
915
+ floor: z6.string().optional(),
916
+ latitude: z6.number().optional(),
917
+ longitude: z6.number().optional()
918
+ })).optional()
919
+ })
920
+ ),
921
+ noResultsReason: z6.string().optional(),
922
+ nextCursor: z6.string().optional()
923
+ });
924
+ var promotionActivityCategoryListCardDataSchema = z6.object({
925
+ items: z6.array(
926
+ z6.object({
927
+ categoryId: z6.string().min(1),
928
+ name: z6.string().min(1),
929
+ parentId: z6.string().optional(),
930
+ itemActions: z6.array(actionDraftSchema).optional()
931
+ })
932
+ ),
933
+ noResultsReason: z6.string().optional()
934
+ });
935
+ var promotionBestDealCardDataSchema = z6.object({
936
+ authoritative: z6.boolean(),
937
+ originalAmountCents: z6.number().int().min(0),
938
+ savingsCents: z6.number().int().min(0).optional(),
939
+ expectedPayCents: z6.number().int().min(0).optional(),
940
+ appliedOfferRefs: z6.array(z6.string()),
941
+ candidates: z6.array(offerSummarySchema).optional(),
942
+ message: z6.string().optional()
943
+ });
944
+ var promotionActivityListCardDataSchema = z6.object({
945
+ items: z6.array(
946
+ z6.object({
947
+ activityRef: z6.string().min(1),
948
+ title: z6.string().min(1),
949
+ subtitle: z6.string().optional(),
950
+ coverUrl: imageUrlSchema,
951
+ registrationRequired: z6.boolean(),
952
+ jumpOnly: z6.boolean().optional(),
953
+ jumpLabel: z6.string().min(1).optional(),
954
+ remainingQuota: z6.number().int().min(0).optional(),
955
+ periodText: z6.string().optional(),
956
+ categoryName: z6.string().optional(),
957
+ availabilityStatus: z6.enum(["AVAILABLE", "FULL", "ENDED", "UPCOMING", "UNKNOWN"]).optional(),
958
+ itemActions: z6.array(actionDraftSchema).optional()
959
+ })
960
+ ),
961
+ noResultsReason: z6.string().optional(),
962
+ nextCursor: z6.string().optional()
963
+ });
964
+ var promotionActivityDetailCardDataSchema = z6.object({
965
+ presentation: z6.enum(["detail", "schedule", "guide"]).optional(),
966
+ activityRef: z6.string().min(1),
967
+ title: z6.string().min(1),
968
+ subtitle: z6.string().optional(),
969
+ categoryName: z6.string().optional(),
970
+ description: z6.string().optional(),
971
+ coverUrl: imageUrlSchema,
972
+ periodText: z6.string().optional(),
973
+ location: z6.string().optional(),
974
+ registrationRequired: z6.boolean(),
975
+ jumpOnly: z6.boolean().optional(),
976
+ jumpLabel: z6.string().min(1).optional(),
977
+ /** 需报名时直达厂商支付宝小程序活动详情;由客户端 openLink 本地处理。 */
978
+ registrationUrl: z6.string().max(2048).optional(),
979
+ remainingQuota: z6.number().int().min(0).optional(),
980
+ sessions: z6.array(
981
+ z6.object({
982
+ sessionRef: z6.string(),
983
+ title: z6.string(),
984
+ startText: z6.string(),
985
+ endText: z6.string().optional(),
986
+ location: z6.string().optional(),
987
+ remainingQuota: z6.number().int().min(0).optional(),
988
+ status: z6.enum(["OPEN", "FULL", "CLOSED", "UNKNOWN"])
989
+ })
990
+ ),
991
+ guideSteps: z6.array(z6.string()),
992
+ guideItems: z6.array(z6.object({ title: z6.string(), description: z6.string().optional() })).optional(),
993
+ conditions: z6.array(z6.string()),
994
+ notice: z6.string().optional()
995
+ });
996
+ var promotionCardDataSchemas = {
997
+ "promotion-offer-list": promotionOfferListCardDataSchema,
998
+ "promotion-offer-detail": promotionOfferDetailCardDataSchema,
999
+ "promotion-entitlement-list": promotionEntitlementListCardDataSchema,
1000
+ "promotion-activity-category-list": promotionActivityCategoryListCardDataSchema,
1001
+ "promotion-best-deal": promotionBestDealCardDataSchema,
1002
+ "promotion-activity-list": promotionActivityListCardDataSchema,
1003
+ "promotion-activity-detail": promotionActivityDetailCardDataSchema
1004
+ };
1005
+
1006
+ // src/parking/cards.ts
1007
+ import { z as z7 } from "zod";
1008
+ var parkingOrderInfoSchema = z7.object({
1009
+ /** 停车秒数 */
1010
+ staySecond: z7.number().int().nonnegative().optional(),
1011
+ /** 停车费,单位分 */
1012
+ parkingFee: z7.number().int().nonnegative().optional(),
1013
+ /** 车牌绑定状态 */
1014
+ bindingStatus: z7.number().int().optional(),
1015
+ /** 车牌 */
1016
+ plateNumber: z7.string().min(1).optional(),
1017
+ /** 1=在场缴费,2=逃费/欠费 */
1018
+ orderType: z7.number().int(),
1019
+ /** 车场侧订单号 */
1020
+ spParkingOrderId: z7.string().min(1).optional(),
1021
+ /** 车场 ID(协议定 string) */
1022
+ parkingId: z7.string().min(1),
1023
+ /** 入场时间 */
1024
+ entranceTime: z7.string().min(1).optional(),
1025
+ /** 逗号分隔的能力枚举,如 "LEVEL_DISCOUNT,POINT_DISCOUNT,COUPON" */
1026
+ supportDiscount: z7.string().min(1).optional()
1027
+ });
1028
+ var parkingPaymentCardDataSchema = z7.object({
1029
+ quoteRef: z7.string().min(1),
1030
+ plateNo: z7.string().min(1),
1031
+ entryAtText: z7.string().optional(),
1032
+ durationText: z7.string().optional(),
1033
+ /** 费用明细(label + 金额字符串) */
1034
+ feeItems: z7.array(z7.object({ name: z7.string(), amountText: z7.string() })),
1035
+ totalText: z7.string(),
1036
+ discountText: z7.string().optional(),
1037
+ payableText: z7.string(),
1038
+ /** 当前请求主体的会员状态;旧历史卡可缺省。 */
1039
+ membership: z7.object({
1040
+ state: z7.enum(["unauthenticated", "unknown", "active", "not_enrolled", "closed", "unavailable"]),
1041
+ availablePoints: z7.number().int().min(0).optional()
1042
+ }).optional(),
1043
+ /** 服务端归一化后的支付入口;客户端不解析权益标题。 */
1044
+ paymentOptions: z7.object({
1045
+ direct: z7.object({
1046
+ /** 已应用积分时 Provider 未必能预览无积分金额;缺省时客户端不得提前承诺金额。 */
1047
+ payableText: z7.string().optional(),
1048
+ benefitRefs: z7.array(z7.string())
1049
+ }),
1050
+ points: z7.discriminatedUnion("kind", [
1051
+ z7.object({
1052
+ kind: z7.literal("exact"),
1053
+ pointsToUse: z7.number().int().positive(),
1054
+ payableText: z7.string(),
1055
+ benefitRefs: z7.array(z7.string()).min(1)
1056
+ }),
1057
+ z7.object({
1058
+ kind: z7.literal("requires_reprice"),
1059
+ title: z7.string().min(1),
1060
+ benefitRefs: z7.array(z7.string()).min(1)
1061
+ })
1062
+ ]).optional()
1063
+ }).optional(),
1064
+ /** 已生效权益 */
1065
+ appliedBenefits: z7.array(
1066
+ z7.object({
1067
+ benefitRef: z7.string(),
1068
+ title: z7.string(),
1069
+ discountText: z7.string().optional()
1070
+ })
1071
+ ),
1072
+ /** 可变更权益(reprice 候选;autoSelected 预勾选) */
1073
+ selectableBenefits: z7.array(
1074
+ z7.object({
1075
+ benefitRef: z7.string(),
1076
+ title: z7.string(),
1077
+ autoSelected: z7.boolean(),
1078
+ description: z7.string().optional(),
1079
+ /** 权益类型(券 / 积分抵扣 / 等级权益);客户端据此分组与判定互斥,不得从标题猜测 */
1080
+ kind: z7.enum(["points", "discount", "coupon", "other"]).optional(),
1081
+ /** 预估优惠金额文案(本地展示用;权威金额以 reprice 回填为准) */
1082
+ discountText: z7.string().optional(),
1083
+ /**
1084
+ * 与本权益互斥的类型。三类优惠默认可叠加,互斥是厂商按券配置的例外——
1085
+ * 标记 ['points'] 表示该券不可与积分抵扣叠加。判定双向生效。
1086
+ */
1087
+ exclusiveWithKinds: z7.array(z7.enum(["points", "discount", "coupon"])).optional()
1088
+ })
1089
+ ),
1090
+ /** 乐观锁(提交校验;过期 → 提示重新查询) */
1091
+ revision: z7.number().int().min(1),
1092
+ caveats: z7.array(z7.string()),
1093
+ /**
1094
+ * 支付交接包:客户端卡据 kind 调壳 tbox 能力收款——
1095
+ * kind:'pay' → openParkingPay(传 orderInfo,壳跳确认页/收银台);kind:'unpaid' → openParkingUnpaidOrder(传 orderNo)。
1096
+ * 缺省 = 走内部 confirm-payment(line)支付链。
1097
+ */
1098
+ payHandoff: z7.object({
1099
+ kind: z7.enum(["pay", "unpaid"]),
1100
+ parkingStoreId: z7.string().min(1).optional(),
1101
+ orderInfo: parkingOrderInfoSchema.optional(),
1102
+ orderNo: z7.string().min(1).optional()
1103
+ }).optional(),
1104
+ /**
1105
+ * 支付进度(缺省 = 未发起):一经写入这张报价单即终结,按钮恒置灰。
1106
+ * 报价是一次性的(token singleUse + revision 乐观锁),发起支付后不可再提交。
1107
+ */
1108
+ settlement: z7.object({
1109
+ state: z7.enum(["paying", "paid", "failed"]),
1110
+ text: z7.string().min(1)
1111
+ }).optional()
1112
+ });
1113
+ var parkingPaymentResultCardDataSchema = z7.object({
1114
+ paymentRef: z7.string().min(1),
1115
+ plateNo: z7.string(),
1116
+ status: z7.enum(["PAID", "CANCELLED", "UNKNOWN"]),
1117
+ amountText: z7.string().optional(),
1118
+ message: z7.string(),
1119
+ /** 失败/取消:可重新发起(重新查询报价) */
1120
+ retryable: z7.boolean().optional(),
1121
+ /** 离场时限提醒(PAID:缴费后免费离场窗口,超时重新计费) */
1122
+ leaveNotice: z7.string().optional(),
1123
+ /** 回执明细(车牌 / 停车时长 / 缴费时间等,服务端已格式化) */
1124
+ details: z7.array(z7.object({ label: z7.string(), value: z7.string() })).optional()
1125
+ });
1126
+ var parkingPaymentRecordsCardDataSchema = z7.object({
1127
+ items: z7.array(
1128
+ z7.object({
1129
+ recordRef: z7.string().min(1),
1130
+ plateNo: z7.string(),
1131
+ amountText: z7.string(),
1132
+ paidAtText: z7.string(),
1133
+ status: z7.enum(["PAID", "REFUNDED", "CLOSED", "UNKNOWN"]),
1134
+ statusText: z7.string().optional(),
1135
+ parkName: z7.string().optional(),
1136
+ plazaName: z7.string().optional(),
1137
+ /** 展开态字段(entry/exit/单号脱敏) */
1138
+ entryAtText: z7.string().optional(),
1139
+ exitAtText: z7.string().optional(),
1140
+ payOrderNoMasked: z7.string().optional(),
1141
+ orderCompleted: z7.boolean().optional(),
1142
+ invoiceEligible: z7.boolean().optional(),
1143
+ invoiceIssued: z7.boolean().optional()
1144
+ })
1145
+ ),
1146
+ total: z7.number().int().min(0),
1147
+ hasMore: z7.boolean(),
1148
+ /** 厂商口径 caveats(厂商事实,7 条并入) */
1149
+ caveats: z7.array(z7.string()),
1150
+ /** 详情加载、开票提交等动作反馈 */
1151
+ message: z7.string().optional()
1152
+ });
1153
+ var parkingVehicleManagementCardDataSchema = z7.object({
1154
+ bound: z7.array(z7.object({
1155
+ vehicleRef: z7.string(),
1156
+ plateNo: z7.string(),
1157
+ parked: z7.boolean().optional()
1158
+ })),
1159
+ message: z7.string().optional(),
1160
+ /**
1161
+ * 会员状态(缺省 = 未探测):仅 not_enrolled 才展示入会引导。
1162
+ * 与 parking-payment 的 membership 同源,避免两张卡对同一用户给出不同判断。
1163
+ */
1164
+ membership: z7.object({
1165
+ state: z7.enum(["unauthenticated", "unknown", "active", "not_enrolled", "closed", "unavailable"])
1166
+ }).optional()
1167
+ });
1168
+ var PARKING_PLATE_PATTERN = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-HJ-NP-Z][A-HJ-NP-Z](?:[A-HJ-NP-Z0-9]{6}|[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳])$/;
1169
+ var parkingInfoCardDataSchema = z7.object({
1170
+ kind: z7.enum(["chargeRules", "benefitPolicy", "vehicleLocation"]),
1171
+ title: z7.string().min(1),
1172
+ entries: z7.array(z7.object({ label: z7.string(), value: z7.string() }))
1173
+ });
1174
+ var parkingCardDataSchemas = {
1175
+ "parking-payment": parkingPaymentCardDataSchema,
1176
+ "parking-payment-result": parkingPaymentResultCardDataSchema,
1177
+ "parking-payment-records": parkingPaymentRecordsCardDataSchema,
1178
+ "parking-vehicle-management": parkingVehicleManagementCardDataSchema,
1179
+ "parking-info": parkingInfoCardDataSchema
1180
+ };
1181
+ export {
1182
+ AUTH_LOGIN_SERVICE,
1183
+ MALL_INFO_SERVICE,
1184
+ MALL_SCOPE_KEY,
1185
+ MEMBER_ACCOUNT_SERVICE,
1186
+ MEMBER_BENEFITS_SERVICE,
1187
+ MEMBER_CARD_SERVICE,
1188
+ MEMBER_ENROLLMENT_SERVICE,
1189
+ MEMBER_PREFERENCE_PROMPTS,
1190
+ MEMBER_PREFERENCE_RECOMMENDATION_QUERIES,
1191
+ MEMBER_PREFERENCE_VALUES,
1192
+ MEMBER_PROFILE_SERVICE,
1193
+ PARKING_PAYMENT_SERVICE,
1194
+ PARKING_PLATE_PATTERN,
1195
+ PARKING_QUERY_SERVICE,
1196
+ PARKING_VEHICLE_SERVICE,
1197
+ PROMOTION_ACQUISITION_SERVICE,
1198
+ PROMOTION_ACTIVITIES_SERVICE,
1199
+ PROMOTION_ACTIVITY_ROUTING_POLICY,
1200
+ PROMOTION_ENTITLEMENTS_SERVICE,
1201
+ PROMOTION_OFFERS_SERVICE,
1202
+ SHOPPING_CATALOG_SERVICE,
1203
+ SHOPPING_CATEGORIES_SERVICE,
1204
+ SHOPPING_DIRECTORY_SERVICE,
1205
+ SHOPPING_SHOPS_SERVICE,
1206
+ actionDraftSchema,
1207
+ categoryListCardDataSchema,
1208
+ classifyMemberOutcome,
1209
+ createMallContextValidator,
1210
+ createMallRuntimeAssembly,
1211
+ customerServiceFaqCardDataSchema,
1212
+ evidenceSchema,
1213
+ externalMemberRefOf,
1214
+ extractMallScope,
1215
+ httpsUrlSchema,
1216
+ humanGuideListCardDataSchema,
1217
+ isoDateTimeSchema,
1218
+ locationHandoffCardDataSchema,
1219
+ mallDirectoryCardDataSchema,
1220
+ mallLocationSchema,
1221
+ mallScopeOf,
1222
+ mallScopeOrEmpty,
1223
+ mallScopeSchema,
1224
+ mallSlot,
1225
+ mallSubjectIdOf,
1226
+ mallUserRefSchema,
1227
+ memberAuthStateSchema,
1228
+ memberCardDataSchemas,
1229
+ memberCardSummaryCardDataSchema,
1230
+ memberEnrollmentCtaCardDataSchema,
1231
+ memberEnrollmentFormCardDataSchema,
1232
+ memberEnrollmentStatusCardDataSchema,
1233
+ memberGateCardOf,
1234
+ memberInfoCardDataSchema,
1235
+ memberLoginCtaCardDataSchema,
1236
+ memberPointUsageListCardDataSchema,
1237
+ memberPreferenceValueSchema,
1238
+ memberStateSchema,
1239
+ merchantDetailCardDataSchema,
1240
+ merchantListCardDataSchema,
1241
+ merchantLocationSchema,
1242
+ merchantStatusSchema,
1243
+ moneySchema,
1244
+ nearbyMallListCardDataSchema,
1245
+ pageInfoSchema,
1246
+ parkingCardDataSchemas,
1247
+ parkingInfoCardDataSchema,
1248
+ parkingOrderInfoSchema,
1249
+ parkingPaymentCardDataSchema,
1250
+ parkingPaymentRecordsCardDataSchema,
1251
+ parkingPaymentResultCardDataSchema,
1252
+ parkingVehicleManagementCardDataSchema,
1253
+ parseMallLocation,
1254
+ parseMallScope,
1255
+ parseMallUserRef,
1256
+ priceSummarySchema,
1257
+ productComparisonCardDataSchema,
1258
+ productDetailCardDataSchema,
1259
+ productListCardDataSchema,
1260
+ promotionActivityCategoryListCardDataSchema,
1261
+ promotionActivityDetailCardDataSchema,
1262
+ promotionActivityListCardDataSchema,
1263
+ promotionBestDealCardDataSchema,
1264
+ promotionBumpInActivityCardDataSchema,
1265
+ promotionCardDataSchemas,
1266
+ promotionEntitlementListCardDataSchema,
1267
+ promotionOfferDetailCardDataSchema,
1268
+ promotionOfferListCardDataSchema,
1269
+ readLoginMallId,
1270
+ reasonItemSchema,
1271
+ recommendMerchantsCardDataSchema,
1272
+ refinementSchema,
1273
+ resolveMemberGate,
1274
+ shopDetailCardDataSchema,
1275
+ shopListCardDataSchema,
1276
+ shopLocationSchema,
1277
+ shopStatusSchema,
1278
+ shoppingGuideCardDataSchemas,
1279
+ toMallQueryContext,
1280
+ withMallScopeFromQuery
1281
+ };