@yaoxiu/marketing-dsl 2.4.0 → 2.6.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.
@@ -699,7 +699,12 @@ var sections4 = [
699
699
  {
700
700
  t: "note",
701
701
  tone: "info",
702
- text: "**\u76EE\u524D\u5DF2\u6CE8\u518C\u7684\u6570\u636E\u6E90**\uFF1A`shopAchievements`\uFF08\u5E97\u94FA\u6210\u679C\u7EDF\u8BA1\uFF0C\u8FD4\u56DE\u9879\u5B57\u6BB5 `v` \u52A8\u8BCD / `n` \u6570\u5B57 / `u` \u5355\u4F4D / `l` \u8BF4\u660E\uFF0C\u793A\u4F8B \u2462\u2463 \u7684\u6210\u679C\u683C\u5B50\u7528\u7684\u5C31\u662F\u5B83\uFF09\u3001`listRenewTiers`\uFF08\u7EED\u8D39\u4EF7\u683C\u6863\u4F4D\uFF0C\u5B57\u6BB5 `key` / `p` / `price` / `per` / `flag` / `hot` / `url`\uFF0C\u89C1\u793A\u4F8B \u2462\uFF09\u3002\u8981\u65B0\u7684\u627E\u524D\u7AEF\u767B\u8BB0\u3002"
702
+ text: "**\u76EE\u524D\u5DF2\u6CE8\u518C\u7684\u6570\u636E\u6E90**\uFF1A`userStatistics`\uFF08\u7528\u6237\u6570\u636E\u7EDF\u8BA1\uFF0C\u8FD4\u56DE\u4E00\u4E2A**\u6241\u5E73\u5BF9\u8C61**\u800C\u4E0D\u662F\u6570\u7EC4\uFF0C\u5B57\u6BB5\u540D\u5C31\u662F\u540E\u7AEF\u7684 snake_case\uFF0C\u5982 `move_success_count` \u7D2F\u8BA1\u642C\u5BB6\u6210\u529F\u6570 / `balance` \u642C\u5BB6\u6B21\u6570\u4F59\u989D / `ai_optimize_count` AI \u81EA\u52A8\u4F18\u5316\u6B21\u6570 / `white_image_fill_count` \u8865\u767D\u5E95\u56FE\u6B21\u6570\uFF0C\u793A\u4F8B \u2462\u2463 \u7684\u6210\u679C\u683C\u5B50\u7528\u7684\u5C31\u662F\u5B83\uFF09\u3001`listRenewTiers`\uFF08\u7EED\u8D39\u4EF7\u683C\u6863\u4F4D**\u6570\u7EC4**\uFF0C\u9879\u5B57\u6BB5 `key` / `p` / `price` / `per` / `flag` / `hot` / `url`\uFF0C\u89C1\u793A\u4F8B \u2462\uFF09\u3002\u8981\u65B0\u7684\u627E\u524D\u7AEF\u767B\u8BB0\u3002"
703
+ },
704
+ {
705
+ t: "note",
706
+ tone: "warn",
707
+ text: '**\u8FD4\u56DE\u6241\u5E73\u5BF9\u8C61\u7684\u6570\u636E\u6E90\uFF08\u5982 `userStatistics`\uFF09\u4E0D\u80FD\u7528 `repeat` \u7684 `bind` \u904D\u5386**\uFF0C\u683C\u5B50\u53EA\u80FD\u4E00\u4E2A\u4E2A\u5199\uFF0C\u6BCF\u683C\u76F4\u63A5\u63D2\u503C `{{ stat.move_success_count }}`\u3002\u4E5F\u4E0D\u8981\u8BD5\u56FE\u5728 `data` \u7684\u5199\u6B7B\u6570\u7EC4\u91CC\u585E `{{ }}` \u518D\u9760 `bind` \u5C55\u5F00 \u2014\u2014 `data` \u91CC\u7684\u9759\u6001\u503C\u539F\u6837\u5B58\uFF0C`{{ }}` \u53EA\u5728\u6E32\u67D3\u8282\u70B9\u65F6\u6C42\u503C\u4E00\u6B21\uFF0C`{{ item.n }}` \u6C42\u51FA\u6765\u662F\u5B57\u7B26\u4E32 `"{{ stat.xxx }}"`\uFF0C**\u4E0D\u4F1A\u4E8C\u6B21\u6C42\u503C**\uFF0C\u9875\u9762\u4E0A\u4F1A\u539F\u6837\u663E\u793A\u8FD9\u4E00\u4E32\u82B1\u62EC\u53F7\u3002'
703
708
  },
704
709
  {
705
710
  t: "p",
@@ -1669,7 +1674,8 @@ var changelog = [
1669
1674
  "`zIndex` \u73B0\u5728\u4F1A\u81EA\u52A8\u5E26\u4E0A\u5B9A\u4F4D\u65B9\u5F0F\uFF1A`z-index` \u5BF9\u9759\u6001\u5143\u7D20\u662F\u6B7B\u58F0\u660E\uFF0C\u5199\u4E86\u4E0D\u751F\u6548\u3002\u6D41\u5F0F\u6392\u7248\u91CC\u9760\u8D1F `marginTop` \u5F80\u4E0A\u76D6\u7684\u5757\uFF08\u5982\u538B\u4F4F\u7EA2\u5934\u4E0B\u6CBF\u7684\u767D\u8272\u4E3B\u4F53\uFF09\u5FC5\u987B\u6709\u5C42\u7EA7\u624D\u76D6\u5F97\u4F4F\uFF0C\u914D\u4E86 `zIndex` \u5373\u53EF\uFF0C\u4E0D\u7528\uFF08\u4E5F\u6CA1\u6CD5\uFF09\u53E6\u914D `position`",
1670
1675
  "\u3010\u4FEE\u590D\u3011\u5F39\u51FA\u7B2C\u4E8C\u5C42\u5F39\u7A97\uFF08\u5982\u4E8C\u6B21\u633D\u7559\uFF09\u518D\u5173\u6389\u65F6\uFF0C\u4E0B\u5C42\u5F39\u7A97\u7684\u906E\u7F69\u5165\u573A\u52A8\u753B\u4F1A\u91CD\u64AD\u4E00\u904D\uFF0C\u80CC\u666F\u300C\u95EA\u300D\u4E00\u4E0B\u91CD\u65B0\u6DE1\u5165\u3002\u73B0\u5DF2\u4FEE\u6B63\uFF0C\u914D\u7F6E\u5199\u6CD5\u4E0D\u7528\u6539",
1671
1676
  "\u3010\u4FEE\u590D\u3011\u5207\u89C6\u56FE / \u5207 tab / `visibleWhen` \u7FFB\u8F6C\u65F6\uFF0C\u9875\u9762\u4E0A\u6B63\u5728\u8DD1\u7684\u5FAA\u73AF\u52A8\u753B\u4F1A\u5168\u90E8\u91CD\u5934\u64AD\u4E00\u904D\u3002\u73B0\u5DF2\u4FEE\u6B63",
1672
- "`hoverStyle` \u91CC\u7684 `{{ }}` \u53EA\u5728\u9996\u5C4F\u6C42\u503C\u4E00\u6B21\uFF0C\u4E4B\u540E\u4E0D\u968F state \u53D8\u5316\u2014\u2014\u8981\u8DDF\u7740\u72B6\u6001\u53D8\u7684\u6837\u5F0F\u5199\u5728 `style` \u91CC\uFF08\u90A3\u6761\u8DEF\u5F84\u6BCF\u5E27\u90FD\u4F1A\u91CD\u7B97\uFF09"
1677
+ "`hoverStyle` \u91CC\u7684 `{{ }}` \u53EA\u5728\u9996\u5C4F\u6C42\u503C\u4E00\u6B21\uFF0C\u4E4B\u540E\u4E0D\u968F state \u53D8\u5316\u2014\u2014\u8981\u8DDF\u7740\u72B6\u6001\u53D8\u7684\u6837\u5F0F\u5199\u5728 `style` \u91CC\uFF08\u90A3\u6761\u8DEF\u5F84\u6BCF\u5E27\u90FD\u4F1A\u91CD\u7B97\uFF09",
1678
+ "\u65B0\u589E\u793A\u4F8B \u246C \u642C\u5BB6\u6B21\u6570\u5C06\u5C3D\uFF1A\u989D\u5EA6\u8FDB\u5EA6\u6761\u7684\u6807\u51C6\u5199\u6CD5\uFF08\u5916\u5C42 flex \u5F53\u8F68\u9053 + \u5185\u5C42 box \u5F53\u586B\u5145\u6761 + `width` \u5199\u6210\u63D2\u503C\u8868\u8FBE\u5F0F\u73B0\u7B97\u767E\u5206\u6BD4\uFF09\uFF0C\u8981\u753B\u4EFB\u4F55\u6BD4\u4F8B\u6761\u90FD\u6284\u8FD9\u4EFD\u3002\u6CE8\u610F\u5B83\u7684\u603B\u989D\u5EA6\u662F\u8FD0\u8425\u624B\u586B\u7684\u2014\u2014\u7EDF\u8BA1\u63A5\u53E3\u76EE\u524D\u53EA\u6709\u4F59\u989D\u3001\u6CA1\u6709\u603B\u989D\u5EA6\uFF0C\u5957\u9910\u989D\u5EA6\u53D8\u4E86\u5FC5\u987B\u624B\u52A8\u6539\u7269\u6599"
1673
1679
  ]
1674
1680
  },
1675
1681
  {
@@ -1783,7 +1789,7 @@ var meta_default = meta;
1783
1789
 
1784
1790
  // src/docs/examples/renew-expire.ts
1785
1791
  var ORANGE = "linear-gradient(90deg,#ff7a00,#faad14)";
1786
- var achieveCell = {
1792
+ var achieveCell = (verb, field, unit, label) => ({
1787
1793
  type: "flex",
1788
1794
  style: {
1789
1795
  direction: "column",
@@ -1805,7 +1811,7 @@ var achieveCell = {
1805
1811
  children: [
1806
1812
  {
1807
1813
  type: "text",
1808
- content: "{{ item.v }}",
1814
+ content: verb,
1809
1815
  style: {
1810
1816
  fontSize: 11.5,
1811
1817
  fontWeight: "600",
@@ -1815,23 +1821,23 @@ var achieveCell = {
1815
1821
  },
1816
1822
  {
1817
1823
  type: "text",
1818
- content: "{{ item.n }}",
1824
+ content: `{{ stat.${field} }}`,
1819
1825
  style: { fontSize: 20, fontWeight: "800", lineHeight: 1.1, color: "#ffffff" }
1820
1826
  },
1821
1827
  {
1822
1828
  type: "text",
1823
- content: "{{ item.u }}",
1829
+ content: ` ${unit}`,
1824
1830
  style: { fontSize: 12, lineHeight: 1.1, color: "rgba(255,255,255,0.92)" }
1825
1831
  }
1826
1832
  ]
1827
1833
  },
1828
1834
  {
1829
1835
  type: "text",
1830
- content: "{{ item.l }}",
1836
+ content: label,
1831
1837
  style: { fontSize: 11.5, lineHeight: 1.35, color: "rgba(255,255,255,0.72)" }
1832
1838
  }
1833
1839
  ]
1834
- };
1840
+ });
1835
1841
  var loseRow = {
1836
1842
  type: "flex",
1837
1843
  style: { align: "center", gap: 8, padding: "8px 0" },
@@ -1951,9 +1957,9 @@ var renewExpire = {
1951
1957
  style: { radius: 18 }
1952
1958
  },
1953
1959
  data: {
1954
- // 成果格子同样走数据源(字段 v / n / u / l 与 achieveCell 模板对应),
1955
- // 后端返回几格就渲染几格
1956
- achieve: { $source: "shopAchievements" },
1960
+ // 成果格子同样走数据源。userStatistics 返回扁平对象,字段名是后端的 snake_case,
1961
+ // 下面四格各自直接插值 {{ stat.xxx }}(扁平对象没法 bind 遍历,见文件头注释)
1962
+ stat: { $source: "userStatistics" },
1957
1963
  lose: [
1958
1964
  { b: "\u6279\u91CF\u642C\u5BB6\u4E0A\u8D27", t: "\u5230\u671F\u540E\u65E0\u6CD5\u7EE7\u7EED\u4E0A\u8D27" },
1959
1965
  { b: "6 \u9879\u81EA\u52A8\u7ECF\u8425\u4EFB\u52A1", t: "\u767D\u5E95\u56FE / \u77ED\u6807\u9898\u8865\u9F50\u3001\u4F4E\u6548\u54C1\u8BCA\u65AD\u4F18\u5316" },
@@ -1991,10 +1997,20 @@ var renewExpire = {
1991
1997
  }
1992
1998
  },
1993
1999
  {
1994
- type: "repeat",
1995
- bind: "achieve",
2000
+ // 四格并列写死(扁平对象没法 bind 遍历),flex + wrap 排成 2×2
2001
+ type: "flex",
1996
2002
  style: { gap: 9, wrap: true },
1997
- template: achieveCell
2003
+ children: [
2004
+ achieveCell("\u5DF2\u4E0A\u67B6", "move_success_count", "\u4E2A", "\u7D2F\u8BA1\u642C\u5BB6\u6210\u529F"),
2005
+ achieveCell("\u8FD0\u884C", "operate_task_count", "\u9879", "\u81EA\u52A8\u7ECF\u8425\u4EFB\u52A1"),
2006
+ achieveCell(
2007
+ "\u5DF2\u8865\u9F50",
2008
+ "white_image_fill_count",
2009
+ "\u5F20",
2010
+ "\u767D\u5E95\u56FE \xB7 \u5408\u89C4\u53EF\u62A5\u6D3B\u52A8"
2011
+ ),
2012
+ achieveCell("\u5B8C\u6210", "ai_optimize_count", "\u6B21", "AI \u81EA\u52A8\u4F18\u5316")
2013
+ ]
1998
2014
  }
1999
2015
  ]
2000
2016
  },
@@ -2131,7 +2147,7 @@ var cdSeparator = (content) => ({
2131
2147
  content,
2132
2148
  style: { fontSize: 13, fontWeight: "800", color: "rgba(255,255,255,0.7)" }
2133
2149
  });
2134
- var achieveCell2 = {
2150
+ var achieveCell2 = (verb, field, unit, label) => ({
2135
2151
  type: "flex",
2136
2152
  style: {
2137
2153
  direction: "column",
@@ -2151,7 +2167,7 @@ var achieveCell2 = {
2151
2167
  children: [
2152
2168
  {
2153
2169
  type: "text",
2154
- content: "{{ item.v }}",
2170
+ content: verb,
2155
2171
  style: {
2156
2172
  fontSize: 11.5,
2157
2173
  fontWeight: "600",
@@ -2161,23 +2177,23 @@ var achieveCell2 = {
2161
2177
  },
2162
2178
  {
2163
2179
  type: "text",
2164
- content: "{{ item.n }}",
2180
+ content: `{{ stat.${field} }}`,
2165
2181
  style: { fontSize: 20, fontWeight: "800", lineHeight: 1.1, color: "#ffffff" }
2166
2182
  },
2167
2183
  {
2168
2184
  type: "text",
2169
- content: "{{ item.u }}",
2185
+ content: ` ${unit}`,
2170
2186
  style: { fontSize: 12, lineHeight: 1.1, color: "rgba(255,255,255,0.92)" }
2171
2187
  }
2172
2188
  ]
2173
2189
  },
2174
2190
  {
2175
2191
  type: "text",
2176
- content: "{{ item.l }}",
2192
+ content: label,
2177
2193
  style: { fontSize: 11.5, lineHeight: 1.35, color: "rgba(255,255,255,0.72)" }
2178
2194
  }
2179
2195
  ]
2180
- };
2196
+ });
2181
2197
  var loseRow2 = {
2182
2198
  type: "flex",
2183
2199
  style: { align: "flex-start", gap: 10, padding: "7px 0" },
@@ -2316,9 +2332,10 @@ var lastDay = {
2316
2332
  },
2317
2333
  data: {
2318
2334
  // 成果格子的数字是**实时统计**,写死就会跟店铺实际情况对不上 —— 走后端数据源。
2319
- // $source 填的是宿主注册过的数据源名(不是接口地址),返回项的字段
2320
- // v / n / u / l 与下面 achieveCell 模板里的 {{ item.x }} 一一对应。
2321
- achieve: { $source: "shopAchievements" },
2335
+ // $source 填的是宿主注册过的数据源名(不是接口地址)。
2336
+ // userStatistics 返回一个扁平对象,字段名就是后端的 snake_case,
2337
+ // 下面四格各自直接插值 {{ stat.xxx }}(见文件头注释:扁平对象没法 bind 遍历)。
2338
+ stat: { $source: "userStatistics" },
2322
2339
  lose: [
2323
2340
  {
2324
2341
  b: "118 \u4E2A\u5546\u54C1\u7684\u5168\u90E8\u4F18\u5316\u8BB0\u5F55",
@@ -2409,10 +2426,25 @@ var lastDay = {
2409
2426
  }
2410
2427
  },
2411
2428
  {
2412
- type: "repeat",
2413
- bind: "achieve",
2429
+ // 四格并列写死(扁平对象没法 bind 遍历),flex + wrap 排成 2×2
2430
+ type: "flex",
2414
2431
  style: { gap: 9, wrap: true, marginTop: 14 },
2415
- template: achieveCell2
2432
+ children: [
2433
+ achieveCell2("\u5DF2\u4E0A\u67B6", "move_success_count", "\u4E2A", "\u7D2F\u8BA1\u642C\u5BB6\u6210\u529F"),
2434
+ achieveCell2(
2435
+ "\u8FD0\u884C",
2436
+ "operate_task_count",
2437
+ "\u9879",
2438
+ "\u7ECF\u8425\u4EFB\u52A1\uFF08\u5546\u54C1\u4F18\u5316/\u6D41\u91CF\u589E\u957F\uFF09"
2439
+ ),
2440
+ achieveCell2(
2441
+ "\u5DF2\u8865\u9F50",
2442
+ "white_image_fill_count",
2443
+ "\u5F20",
2444
+ "\u767D\u5E95\u56FE \xB7 \u5408\u89C4\u53EF\u62A5\u6D3B\u52A8"
2445
+ ),
2446
+ achieveCell2("\u5B8C\u6210", "ai_optimize_count", "\u6B21", "AI \u81EA\u52A8\u4F18\u5316")
2447
+ ]
2416
2448
  },
2417
2449
  // ===== 分格倒计时 + 厘秒逐帧动画 =====
2418
2450
  {
@@ -4562,6 +4594,437 @@ var giftRedPacket = {
4562
4594
  };
4563
4595
  var gift_red_packet_default = giftRedPacket;
4564
4596
 
4597
+ // src/docs/examples/quota-low.ts
4598
+ var ORANGE4 = "linear-gradient(90deg,#ff7a00,#faad14)";
4599
+ var USED = "{{ total - user.collectCount }}";
4600
+ var achieveCell3 = (verb, value, unit, label) => ({
4601
+ type: "flex",
4602
+ style: {
4603
+ direction: "column",
4604
+ width: "calc(50% - 5px)",
4605
+ background: "rgba(255,255,255,0.16)",
4606
+ borderWidth: 1,
4607
+ borderStyle: "solid",
4608
+ borderColor: "rgba(255,255,255,0.2)",
4609
+ radius: 10,
4610
+ padding: "10px 13px",
4611
+ gap: 3
4612
+ },
4613
+ children: [
4614
+ {
4615
+ // lineHeight 必须显式给,否则 20px 数字的默认行高会把格子撑高
4616
+ type: "flex",
4617
+ style: { align: "baseline", gap: 3, height: 22 },
4618
+ children: [
4619
+ {
4620
+ type: "text",
4621
+ content: verb,
4622
+ style: {
4623
+ fontSize: 11.5,
4624
+ fontWeight: "600",
4625
+ lineHeight: 1.1,
4626
+ color: "rgba(255,255,255,0.92)"
4627
+ }
4628
+ },
4629
+ {
4630
+ type: "text",
4631
+ content: value,
4632
+ style: { fontSize: 20, fontWeight: "800", lineHeight: 1.1, color: "#ffffff" }
4633
+ },
4634
+ {
4635
+ type: "text",
4636
+ content: ` ${unit}`,
4637
+ style: { fontSize: 12, lineHeight: 1.1, color: "rgba(255,255,255,0.92)" }
4638
+ }
4639
+ ]
4640
+ },
4641
+ {
4642
+ type: "text",
4643
+ content: label,
4644
+ style: { fontSize: 11.5, lineHeight: 1.35, color: "rgba(255,255,255,0.72)" }
4645
+ }
4646
+ ]
4647
+ });
4648
+ var loseRow3 = {
4649
+ type: "flex",
4650
+ style: { align: "flex-start", gap: 10, padding: "7px 0" },
4651
+ children: [
4652
+ {
4653
+ type: "text",
4654
+ content: "",
4655
+ style: { width: 6, height: 6, radius: "50%", background: "#f53f3f", marginTop: 7 }
4656
+ },
4657
+ {
4658
+ type: "flex",
4659
+ style: { align: "baseline", gap: 4, wrap: true, flex: "1" },
4660
+ children: [
4661
+ {
4662
+ type: "text",
4663
+ content: "{{ item.b }}",
4664
+ style: {
4665
+ fontSize: 12.5,
4666
+ fontWeight: "700",
4667
+ lineHeight: 1.55,
4668
+ color: "#1f2533"
4669
+ }
4670
+ },
4671
+ {
4672
+ type: "text",
4673
+ content: "{{ item.tag }}",
4674
+ visibleWhen: "item.tag != ''",
4675
+ style: {
4676
+ background: "{{ item.sev == 'lose' ? '#ffd5cf' : 'rgba(255,255,255,0.78)' }}",
4677
+ color: "{{ item.sev == 'lose' ? '#cf1322' : '#8a7f78' }}",
4678
+ fontSize: 10,
4679
+ fontWeight: "800",
4680
+ radius: 4,
4681
+ padding: "1px 6px",
4682
+ whiteSpace: "nowrap"
4683
+ }
4684
+ },
4685
+ {
4686
+ type: "text",
4687
+ content: "\u2014 {{ item.t }}",
4688
+ style: { fontSize: 12.5, lineHeight: 1.55, color: "#4a4038" }
4689
+ }
4690
+ ]
4691
+ }
4692
+ ]
4693
+ };
4694
+ var tierCard3 = {
4695
+ type: "box",
4696
+ style: {
4697
+ flex: "1",
4698
+ height: 121,
4699
+ radius: 12,
4700
+ background: "{{ item.key == current.key ? '#fffaf0' : '#ffffff' }}",
4701
+ borderStyle: "solid",
4702
+ borderWidth: "{{ item.key == current.key ? '2px' : '1px' }}",
4703
+ borderColor: "{{ item.key == current.key ? '#f0a000' : '#e5e8ed' }}",
4704
+ cursor: "pointer"
4705
+ },
4706
+ action: {
4707
+ type: "sequence",
4708
+ actions: [
4709
+ { type: "setState", key: "period", value: "{{ index }}" },
4710
+ {
4711
+ type: "track",
4712
+ event: "popup_period_select",
4713
+ params: { period: "{{ item.key }}" }
4714
+ }
4715
+ ]
4716
+ },
4717
+ children: [
4718
+ {
4719
+ type: "text",
4720
+ rect: ["calc(50% - 19px)", -9, 38, 22],
4721
+ content: "\u63A8\u8350",
4722
+ visibleWhen: "item.hot",
4723
+ style: {
4724
+ background: ORANGE4,
4725
+ color: "#ffffff",
4726
+ fontSize: 11,
4727
+ fontWeight: "800",
4728
+ radius: 6,
4729
+ textAlign: "center",
4730
+ lineHeight: 22
4731
+ }
4732
+ },
4733
+ {
4734
+ type: "text",
4735
+ rect: [0, 12, "100%", 19],
4736
+ content: "{{ item.p }}",
4737
+ style: { fontSize: 13, color: "#8a909c", textAlign: "center" }
4738
+ },
4739
+ {
4740
+ type: "flex",
4741
+ rect: [0, 34, "100%", 26],
4742
+ style: { justify: "center", align: "baseline" },
4743
+ children: [
4744
+ {
4745
+ type: "text",
4746
+ content: "\xA5",
4747
+ style: { fontSize: 13, fontWeight: "800", color: "#1f2533" }
4748
+ },
4749
+ {
4750
+ type: "text",
4751
+ content: "{{ item.price }}",
4752
+ style: { fontSize: 21, fontWeight: "800", color: "#1f2533" }
4753
+ }
4754
+ ]
4755
+ },
4756
+ {
4757
+ type: "text",
4758
+ rect: [4, 63, "calc(100% - 8px)", 32],
4759
+ content: "{{ item.per }}",
4760
+ style: { fontSize: 11, color: "#8a909c", textAlign: "center", lineHeight: 1.35 }
4761
+ },
4762
+ {
4763
+ type: "text",
4764
+ rect: [0, 98, "100%", 15],
4765
+ content: "{{ item.flag }}",
4766
+ visibleWhen: "item.flag != ''",
4767
+ style: { fontSize: 11, color: "#8a909c", textAlign: "center" }
4768
+ }
4769
+ ]
4770
+ };
4771
+ var quotaLow = {
4772
+ version: 1,
4773
+ type: "popup",
4774
+ meta: { name: "\u642C\u5BB6\u6B21\u6570\u5C06\u5C3D \xB7 \u989D\u5EA6\u8FDB\u5EA6\u6761\uFF08\u590D\u523B\u8FD0\u8425 demo\uFF09" },
4775
+ stage: {
4776
+ width: 520,
4777
+ height: "auto",
4778
+ layout: "flow",
4779
+ mask: true,
4780
+ maskClosable: false,
4781
+ closeButton: { show: true, position: "top-right", offset: [14, 14] },
4782
+ style: { radius: 18 }
4783
+ },
4784
+ data: {
4785
+ // 实时统计走后端数据源。$source 填的是宿主注册过的数据源名(不是接口地址),
4786
+ // userStatistics 返回扁平对象,字段名就是后端的 snake_case
4787
+ stat: { $source: "userStatistics" },
4788
+ // 总额度:运营按当前套餐手填。为什么不走接口、以后怎么换,见文件头注释
4789
+ total: 30,
4790
+ lose: [
4791
+ { b: "\u6279\u91CF\u642C\u5BB6", tag: "\u5C06\u505C\u7528", sev: "lose", t: "\u989D\u5EA6\u5F52\u96F6\u540E\u65E0\u6CD5\u7EE7\u7EED\u4E0A\u8D27" },
4792
+ {
4793
+ b: "1688 \u4E00\u4EF6\u4EE3\u53D1",
4794
+ tag: "\u5C06\u505C\u7528",
4795
+ sev: "lose",
4796
+ t: "\u6E90\u5934\u8D27\u6E90\u65AD\u4F9B\uFF0C\u9009\u54C1\u3001\u94FA\u8D27\u3001\u4EE3\u53D1\u90FD\u8981\u624B\u52A8\u505A"
4797
+ },
4798
+ {
4799
+ b: "AI \u81EA\u52A8\u4F18\u5316",
4800
+ tag: "\u5C06\u6682\u505C",
4801
+ sev: "pause",
4802
+ t: "\u65B0\u5546\u54C1\u4E0D\u518D\u8865\u4E3B\u6807\u9898 / \u77ED\u6807\u9898 / \u767D\u5E95\u56FE"
4803
+ }
4804
+ ],
4805
+ // 价格档位从后端数据源取,后端返回几档就渲染几档,配置时不用知道数量
4806
+ tiers: { $source: "listRenewTiers", params: { scene: "quota_low" } }
4807
+ },
4808
+ state: { period: 1 },
4809
+ derived: { current: { list: "tiers", indexBy: "period" } },
4810
+ nodes: [
4811
+ // ===== 深色渐变头部:标签 + 2×2 成果格 =====
4812
+ {
4813
+ type: "flex",
4814
+ style: {
4815
+ direction: "column",
4816
+ background: "linear-gradient(135deg,#2b0f0f,#3a1414)",
4817
+ padding: "20px 22px 16px",
4818
+ gap: 13
4819
+ },
4820
+ children: [
4821
+ {
4822
+ type: "text",
4823
+ content: "\u26A1 \u642C\u5BB6\u6B21\u6570\u5373\u5C06\u7528\u5B8C",
4824
+ style: {
4825
+ // 不写 alignSelf 会被 flex 列拉满整行,标签必须按内容宽度
4826
+ alignSelf: "flex-start",
4827
+ background: "rgba(255,255,255,0.18)",
4828
+ color: "#ffffff",
4829
+ fontSize: 12,
4830
+ fontWeight: "700",
4831
+ radius: 6,
4832
+ padding: "5px 10px"
4833
+ }
4834
+ },
4835
+ {
4836
+ // 四格并列写死(扁平对象没法 bind 遍历),flex + wrap 排成 2×2。
4837
+ // 第一格的数字不是统计字段,而是「总额度 − 剩余次数」现算出来的
4838
+ type: "flex",
4839
+ style: { gap: 9, wrap: true },
4840
+ children: [
4841
+ achieveCell3("\u5DF2\u7528", USED, "\u6B21", "\u642C\u5BB6\u6B21\u6570"),
4842
+ achieveCell3("\u5DF2\u4E0A\u67B6", "{{ stat.move_success_count }}", "\u4E2A", "\u7D2F\u8BA1\u4E0A\u67B6\u5546\u54C1"),
4843
+ achieveCell3("\u65E5\u5747", "{{ stat.avg_daily_move_count }}", "\u4E2A", "\u5E73\u5747\u6BCF\u5929\u4E0A\u67B6"),
4844
+ achieveCell3(
4845
+ "\u5DF2\u8865\u9F50",
4846
+ "{{ stat.white_image_fill_count }}",
4847
+ "\u5F20",
4848
+ "\u767D\u5E95\u56FE \xB7 \u5408\u89C4\u53EF\u62A5\u6D3B\u52A8"
4849
+ )
4850
+ ]
4851
+ }
4852
+ ]
4853
+ },
4854
+ // ===== 白色 body =====
4855
+ {
4856
+ type: "flex",
4857
+ style: { direction: "column", background: "#ffffff", padding: "22px 26px 24px" },
4858
+ children: [
4859
+ // ===== 额度进度条:轨道 + 填充条 + 百分比表达式(本示例的重点)=====
4860
+ {
4861
+ type: "flex",
4862
+ style: {
4863
+ direction: "column",
4864
+ background: "#fff8f3",
4865
+ radius: 10,
4866
+ padding: "8px 13px 9px",
4867
+ gap: 4
4868
+ },
4869
+ children: [
4870
+ {
4871
+ // 标题行:左边「剩余 N 次」,右边「已用 X / 总额度 次」
4872
+ type: "flex",
4873
+ style: { align: "baseline", justify: "space-between" },
4874
+ children: [
4875
+ {
4876
+ type: "flex",
4877
+ style: { align: "baseline", gap: 3 },
4878
+ children: [
4879
+ {
4880
+ type: "text",
4881
+ content: "\u642C\u5BB6\u6B21\u6570\u5269\u4F59",
4882
+ style: { fontSize: 12, lineHeight: 1.35, color: "#3f4656" }
4883
+ },
4884
+ {
4885
+ type: "text",
4886
+ content: "{{ user.collectCount }} \u6B21",
4887
+ style: {
4888
+ fontSize: 15,
4889
+ fontWeight: "800",
4890
+ lineHeight: 1.25,
4891
+ color: "#cf1322"
4892
+ }
4893
+ }
4894
+ ]
4895
+ },
4896
+ {
4897
+ type: "text",
4898
+ content: `\u5DF2\u7528 ${USED} / {{ total }} \u6B21`,
4899
+ style: { fontSize: 10.5, lineHeight: 1.35, color: "#8a909c" }
4900
+ }
4901
+ ]
4902
+ },
4903
+ {
4904
+ // 轨道。用 flex 而不是 box —— box 的子节点走绝对定位、必须给 rect,
4905
+ // 填充条要的是「跟着父级流」;overflow: hidden 必须写,否则填充条的
4906
+ // 直角会戳出轨道的圆角外面
4907
+ type: "flex",
4908
+ style: {
4909
+ height: 5,
4910
+ radius: 4,
4911
+ background: "#ffe0cc",
4912
+ overflow: "hidden"
4913
+ },
4914
+ children: [
4915
+ {
4916
+ // 填充条。宽度是算出来的:已用 ÷ 总额度 × 100,节点 style 里的
4917
+ // 字符串同样走插值,所以百分比不需要后端多下发一个字段
4918
+ type: "box",
4919
+ style: {
4920
+ width: "{{ (total - user.collectCount) / total * 100 }}%",
4921
+ height: "100%",
4922
+ background: "linear-gradient(90deg,#f53f3f,#ff7a45)"
4923
+ }
4924
+ }
4925
+ ]
4926
+ }
4927
+ ]
4928
+ },
4929
+ {
4930
+ type: "text",
4931
+ content: "\u642C\u5BB6\u6B21\u6570\u7528\u5B8C\uFF0C\u4EA7\u54C1\u80FD\u529B\u5C06\u53D7\u9650\uFF1A",
4932
+ style: { fontSize: 15, fontWeight: "800", color: "#1f2533", marginTop: 17 }
4933
+ },
4934
+ {
4935
+ type: "repeat",
4936
+ bind: "lose",
4937
+ template: loseRow3,
4938
+ style: {
4939
+ direction: "column",
4940
+ marginTop: 12,
4941
+ background: "#ffe9e6",
4942
+ borderWidth: 1,
4943
+ borderStyle: "solid",
4944
+ borderColor: "#ffd0ca",
4945
+ radius: 12,
4946
+ padding: "7px 13px"
4947
+ }
4948
+ },
4949
+ {
4950
+ type: "flex",
4951
+ style: { align: "center", gap: 8, marginTop: 17, marginBottom: 9 },
4952
+ children: [
4953
+ {
4954
+ type: "text",
4955
+ content: "\u7EED\u6EE1\u989D\u5EA6 \xB7 \u9009\u62E9\u5468\u671F",
4956
+ style: { fontSize: 13.5, fontWeight: "700", color: "#747b89" }
4957
+ },
4958
+ {
4959
+ type: "text",
4960
+ content: "\u65B0\u4EBA\u9996\u8D2D\u4EF7",
4961
+ style: {
4962
+ alignSelf: "center",
4963
+ background: ORANGE4,
4964
+ color: "#ffffff",
4965
+ fontSize: 11,
4966
+ fontWeight: "800",
4967
+ radius: 5,
4968
+ padding: "2px 8px"
4969
+ }
4970
+ }
4971
+ ]
4972
+ },
4973
+ { type: "repeat", bind: "tiers", style: { gap: 8 }, template: tierCard3 },
4974
+ {
4975
+ type: "flex",
4976
+ style: {
4977
+ justify: "center",
4978
+ align: "center",
4979
+ gap: 5,
4980
+ height: 52,
4981
+ radius: 11,
4982
+ background: "linear-gradient(90deg,#f53f3f,#ff7a45)",
4983
+ marginTop: 15,
4984
+ cursor: "pointer"
4985
+ },
4986
+ action: {
4987
+ type: "sequence",
4988
+ actions: [
4989
+ {
4990
+ type: "track",
4991
+ event: "popup_renew_click",
4992
+ params: { period: "{{ current.key }}", stage: "quota_low" }
4993
+ },
4994
+ { type: "navigate", url: "{{ current.url }}" }
4995
+ ]
4996
+ },
4997
+ children: [
4998
+ {
4999
+ type: "text",
5000
+ content: "\u7EED\u6EE1\u989D\u5EA6 \xB7",
5001
+ style: { fontSize: 14, fontWeight: "800", color: "#ffffff" }
5002
+ },
5003
+ {
5004
+ type: "text",
5005
+ content: "{{ current.p }} \xA5{{ current.price }}",
5006
+ style: { fontSize: 16.5, fontWeight: "800", color: "#ffffff" }
5007
+ }
5008
+ ]
5009
+ },
5010
+ {
5011
+ type: "text",
5012
+ content: "\u5347\u7EA7\u6216\u67E5\u770B\u66F4\u591A\u4EA7\u54C1\u5957\u9910",
5013
+ style: {
5014
+ fontSize: 12.5,
5015
+ color: "#8a909c",
5016
+ textAlign: "center",
5017
+ marginTop: 11,
5018
+ cursor: "pointer"
5019
+ },
5020
+ action: { type: "track", event: "popup_more_plans" }
5021
+ }
5022
+ ]
5023
+ }
5024
+ ]
5025
+ };
5026
+ var quota_low_default = quotaLow;
5027
+
4565
5028
  // src/docs/examples/index.ts
4566
5029
  var HOTSPOT_BG = "rgba(255,68,51,0.16)";
4567
5030
  var imageHotspot = {
@@ -4813,6 +5276,11 @@ var examples = [
4813
5276
  label: "\u246B \u590D\u523B\u7EBF\u4E0A\u5F39\u7A97 \xB7 1 \u5206\u94B1\u534A\u5E74\u5361\uFF08\u52A8\u753B\u6700\u5BC6\u7684\u4E00\u4EFD\uFF09",
4814
5277
  value: "giftRedPacket",
4815
5278
  dsl: gift_red_packet_default
5279
+ },
5280
+ {
5281
+ label: "\u246C \u590D\u523B\u8FD0\u8425 demo \xB7 \u642C\u5BB6\u6B21\u6570\u5C06\u5C3D\uFF08\u989D\u5EA6\u8FDB\u5EA6\u6761\uFF09",
5282
+ value: "quotaLow",
5283
+ dsl: quota_low_default
4816
5284
  }
4817
5285
  ];
4818
5286
  var examples_default = examples;
package/dist/index.cjs CHANGED
@@ -2314,10 +2314,10 @@ function formatIssues(issues) {
2314
2314
  }
2315
2315
 
2316
2316
  // src/host-capabilities.ts
2317
- var HOST_SOURCE_NAMES = ["shopAchievements", "listRenewTiers"];
2317
+ var HOST_SOURCE_NAMES = ["userStatistics", "listRenewTiers"];
2318
2318
  var HOST_HANDLER_NAMES = [];
2319
2319
  var HOST_SOURCE_LABELS = {
2320
- shopAchievements: "\u5E97\u94FA\u6210\u679C\u7EDF\u8BA1\uFF08\u5DF2\u4E0A\u67B6/\u8FD0\u884C\u4E2D/\u767D\u5E95\u56FE\u7B49\u683C\u5B50\u6570\u7EC4\uFF09",
2320
+ userStatistics: "\u7528\u6237\u6570\u636E\u7EDF\u8BA1\uFF08\u7D2F\u8BA1\u642C\u5BB6\u6570 / \u6B21\u6570\u4F59\u989D / AI \u4F18\u5316\u6B21\u6570\u7B49\uFF0C\u6241\u5E73\u5BF9\u8C61\uFF0C\u5B57\u6BB5\u540D\u4E3A\u540E\u7AEF snake_case\uFF09",
2321
2321
  listRenewTiers: "\u7EED\u8D39\u4EF7\u683C\u6863\u4F4D\u5217\u8868\uFF08\u6708\u4ED8/\u5B63\u4ED8/\u534A\u5E74/\u5E74\u4ED8\uFF0C\u542B\u4E0B\u5355\u5730\u5740\uFF09"
2322
2322
  };
2323
2323
  var HOST_HANDLER_LABELS = {};
package/dist/index.d.cts CHANGED
@@ -166,7 +166,7 @@ declare function validateUserFields(dsl: unknown, allowed: string[]): FieldIssue
166
166
  *
167
167
  * 用 `as const` 是为了推导出 {@link HostSourceName} 联合类型,供前台约束注册表。
168
168
  */
169
- declare const HOST_SOURCE_NAMES: readonly ["shopAchievements", "listRenewTiers"];
169
+ declare const HOST_SOURCE_NAMES: readonly ["userStatistics", "listRenewTiers"];
170
170
  /** 数据源名的联合类型,前台注册表以它为键,漏注册一个就编译不过 */
171
171
  type HostSourceName = (typeof HOST_SOURCE_NAMES)[number];
172
172
  /**
package/dist/index.d.ts CHANGED
@@ -166,7 +166,7 @@ declare function validateUserFields(dsl: unknown, allowed: string[]): FieldIssue
166
166
  *
167
167
  * 用 `as const` 是为了推导出 {@link HostSourceName} 联合类型,供前台约束注册表。
168
168
  */
169
- declare const HOST_SOURCE_NAMES: readonly ["shopAchievements", "listRenewTiers"];
169
+ declare const HOST_SOURCE_NAMES: readonly ["userStatistics", "listRenewTiers"];
170
170
  /** 数据源名的联合类型,前台注册表以它为键,漏注册一个就编译不过 */
171
171
  type HostSourceName = (typeof HOST_SOURCE_NAMES)[number];
172
172
  /**