@yaoxiu/marketing-dsl 2.7.0 → 2.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/README.md +25 -1
- package/dist/{chunk-DT3ZINDI.js → chunk-B6BKOMWL.js} +107 -3
- package/dist/docs/index.cjs +228 -5
- package/dist/docs/index.d.cts +3 -2
- package/dist/docs/index.d.ts +3 -2
- package/dist/docs/index.js +224 -6
- package/dist/index.cjs +128 -2
- package/dist/index.d.cts +41 -4
- package/dist/index.d.ts +41 -4
- package/dist/index.js +20 -2
- package/dist/report/index.cjs +1 -1
- package/dist/report/index.d.cts +5 -3
- package/dist/report/index.d.ts +5 -3
- package/dist/report/index.js +1 -1
- package/dist/{types-8FNxDXp0.d.cts → types-BapBTTio.d.cts} +32 -4
- package/dist/{types-8FNxDXp0.d.ts → types-BapBTTio.d.ts} +32 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,7 +111,7 @@ const unsubscribe = runtime.subscribe(() => {
|
|
|
111
111
|
// 还会把用户已经切到的 tab 打回默认值。
|
|
112
112
|
runtime.update({ user: { shopName: '麦爆了旗舰店' } });
|
|
113
113
|
|
|
114
|
-
//
|
|
114
|
+
// 卸载时必须调,否则倒计时 / 自动轮播的定时器不会停
|
|
115
115
|
runtime.destroy();
|
|
116
116
|
unsubscribe();
|
|
117
117
|
```
|
|
@@ -143,6 +143,8 @@ unsubscribe();
|
|
|
143
143
|
countdownPrecision: 's',
|
|
144
144
|
css: '', // 要注入的 CSS 文本(keyframes + hover 规则),没有动画时是空串
|
|
145
145
|
rootClassName: 'dsl-renderer dsl-r3', // 根容器类名,后半截是这份物料的作用域前缀
|
|
146
|
+
onRootEnter: fn, // 可选:只有配了 pauseOnHover 的自动轮播才有,见下
|
|
147
|
+
onRootLeave: fn,
|
|
146
148
|
}
|
|
147
149
|
```
|
|
148
150
|
|
|
@@ -167,6 +169,28 @@ unsubscribe();
|
|
|
167
169
|
|
|
168
170
|
父子都可点是常见排版——公告条整条点开弹窗、行末 × 关闭公告条——不阻止的话点 × 会连带触发外层,关掉的瞬间又弹出来。没有 `onClick` 的节点不要绑任何事件,让它正常冒泡到有 `onClick` 的祖先。
|
|
169
171
|
|
|
172
|
+
### 自动轮播(`derived.xxx.autoplay`)
|
|
173
|
+
|
|
174
|
+
```jsonc
|
|
175
|
+
"state": { "slide": 0 },
|
|
176
|
+
"derived": { "cur": { "list": "slides", "indexBy": "slide",
|
|
177
|
+
"autoplay": { "interval": 4000, "pauseOnHover": true } } }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
配了就开启、始终循环(没有 `enabled` / `loop`):每 `interval` 毫秒把 `state[indexBy]` 推到
|
|
181
|
+
`(当前 + 1) % 列表长度`。定时逻辑在 `src/autoplay.ts`,`runtime.ts` 只接线。
|
|
182
|
+
|
|
183
|
+
- **与点击同一条路径**:到点调的就是运行时的 `setState`,`state-change` 照常派发,文案 / 图片 /
|
|
184
|
+
tabs 指示器 / 链接 / 运营配的 `transition` 与手动点击效果完全一致,不引入额外切换动画
|
|
185
|
+
- 任何 `setState` 改了同一个 key(用户点 tab)都会**重新计时**
|
|
186
|
+
- 列表长度 ≤1、数据源未就绪或失败时不播;数据源回来后开始;`editMode` 下照样播
|
|
187
|
+
- `destroy()` 清掉全部轮播定时器,之后不会再 `setState`
|
|
188
|
+
- `pauseOnHover` 需要壳配合:渲染树此时带 `onRootEnter` / `onRootLeave`,
|
|
189
|
+
壳在根容器上绑 `mouseenter` / `mouseleave` 原样调用即可(**有才绑、不拦冒泡、不加判断**)
|
|
190
|
+
|
|
191
|
+
校验:`autoplay` 须是对象;`interval` 须是 ≥300 的数字(单位毫秒,否则 error);
|
|
192
|
+
`pauseOnHover` 须是布尔;其余字段只告警(运行时忽略)。字段表导出为 `AUTOPLAY_FIELDS`。
|
|
193
|
+
|
|
170
194
|
## 运行时事件(`emit`)
|
|
171
195
|
|
|
172
196
|
| 事件 | 何时抛 | 宿主拿它干嘛 |
|
|
@@ -399,6 +399,109 @@ function createTicker(options) {
|
|
|
399
399
|
return { sync, stop };
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
// src/autoplay.ts
|
|
403
|
+
var DERIVED_FIELDS = ["list", "indexBy", "autoplay"];
|
|
404
|
+
var AUTOPLAY_FIELDS = ["interval", "pauseOnHover"];
|
|
405
|
+
var AUTOPLAY_MIN_INTERVAL = 300;
|
|
406
|
+
function collectEntries(derived) {
|
|
407
|
+
const entries = [];
|
|
408
|
+
Object.keys(derived || {}).forEach((name) => {
|
|
409
|
+
const config = (derived || {})[name];
|
|
410
|
+
const autoplay = config && config.autoplay;
|
|
411
|
+
if (!autoplay || typeof autoplay !== "object") return;
|
|
412
|
+
const interval = Number(autoplay.interval);
|
|
413
|
+
if (!isFinite(interval) || interval < AUTOPLAY_MIN_INTERVAL) return;
|
|
414
|
+
entries.push({
|
|
415
|
+
list: config.list,
|
|
416
|
+
indexBy: config.indexBy,
|
|
417
|
+
interval,
|
|
418
|
+
pauseOnHover: autoplay.pauseOnHover === true,
|
|
419
|
+
timer: null
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
return entries;
|
|
423
|
+
}
|
|
424
|
+
function createAutoplay(options) {
|
|
425
|
+
const entries = collectEntries(options.derived);
|
|
426
|
+
let started = false;
|
|
427
|
+
let hovering = false;
|
|
428
|
+
let stopped = false;
|
|
429
|
+
function clear(entry) {
|
|
430
|
+
if (entry.timer) {
|
|
431
|
+
clearTimeout(entry.timer);
|
|
432
|
+
entry.timer = null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function advance(entry) {
|
|
436
|
+
entry.timer = null;
|
|
437
|
+
const length = options.getLength(entry.list);
|
|
438
|
+
if (length <= 1) return;
|
|
439
|
+
const index = options.getIndex(entry.indexBy);
|
|
440
|
+
options.setState(entry.indexBy, (index + 1) % length);
|
|
441
|
+
}
|
|
442
|
+
function schedule(entry) {
|
|
443
|
+
clear(entry);
|
|
444
|
+
if (stopped || !started) return;
|
|
445
|
+
if (hovering && entry.pauseOnHover) return;
|
|
446
|
+
if (options.getLength(entry.list) <= 1) return;
|
|
447
|
+
entry.timer = setTimeout(() => advance(entry), entry.interval);
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
pausable: entries.some((entry) => entry.pauseOnHover),
|
|
451
|
+
start() {
|
|
452
|
+
started = true;
|
|
453
|
+
entries.forEach(schedule);
|
|
454
|
+
},
|
|
455
|
+
reset(key) {
|
|
456
|
+
entries.forEach((entry) => {
|
|
457
|
+
if (entry.indexBy === key) schedule(entry);
|
|
458
|
+
});
|
|
459
|
+
},
|
|
460
|
+
pause() {
|
|
461
|
+
hovering = true;
|
|
462
|
+
entries.forEach((entry) => {
|
|
463
|
+
if (entry.pauseOnHover) clear(entry);
|
|
464
|
+
});
|
|
465
|
+
},
|
|
466
|
+
resume() {
|
|
467
|
+
hovering = false;
|
|
468
|
+
entries.forEach((entry) => {
|
|
469
|
+
if (entry.pauseOnHover) schedule(entry);
|
|
470
|
+
});
|
|
471
|
+
},
|
|
472
|
+
stop() {
|
|
473
|
+
stopped = true;
|
|
474
|
+
entries.forEach(clear);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function validateAutoplay(autoplay, path, add, warn) {
|
|
479
|
+
if (autoplay === void 0) return;
|
|
480
|
+
if (!autoplay || typeof autoplay !== "object" || Array.isArray(autoplay)) {
|
|
481
|
+
add(path, 'autoplay \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u5F62\u5982 { "interval": 4000, "pauseOnHover": true }');
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const config = autoplay;
|
|
485
|
+
const interval = config.interval;
|
|
486
|
+
if (typeof interval !== "number" || !isFinite(interval) || interval < AUTOPLAY_MIN_INTERVAL) {
|
|
487
|
+
add(
|
|
488
|
+
`${path}.interval`,
|
|
489
|
+
`interval \u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL} \u7684\u6570\u5B57\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF08\u5982 4000 \u8868\u793A 4 \u79D2\uFF09\uFF0C\u5F53\u524D\u4E3A ${JSON.stringify(interval)}`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
if (config.pauseOnHover !== void 0 && typeof config.pauseOnHover !== "boolean") {
|
|
493
|
+
add(`${path}.pauseOnHover`, "pauseOnHover \u5FC5\u987B\u662F true \u6216 false");
|
|
494
|
+
}
|
|
495
|
+
Object.keys(config).forEach((key) => {
|
|
496
|
+
if (AUTOPLAY_FIELDS.indexOf(key) === -1) {
|
|
497
|
+
warn(
|
|
498
|
+
`${path}.${key}`,
|
|
499
|
+
`autoplay \u4E0D\u8BA4\u8BC6 "${key}"\uFF0C\u4F1A\u88AB\u5FFD\u7565\u3002\u53EF\u7528\uFF1A${AUTOPLAY_FIELDS.join(" / ")}\uFF08\u914D\u4E86 autoplay \u5C31\u5F00\u542F\u4E14\u59CB\u7EC8\u5FAA\u73AF\uFF0C\u4E0D\u9700\u8981 enabled / loop\uFF09`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
402
505
|
// src/views.ts
|
|
403
506
|
var SINGLE_VIEW_NAME = "main";
|
|
404
507
|
function normalizeViews(dsl) {
|
|
@@ -962,7 +1065,7 @@ function validate(dsl, options) {
|
|
|
962
1065
|
}
|
|
963
1066
|
const dataKeys = validateData(doc.data, add);
|
|
964
1067
|
const stateKeys = validateState(doc.state, add);
|
|
965
|
-
validateDerived(doc.derived, dataKeys, stateKeys, add);
|
|
1068
|
+
validateDerived(doc.derived, dataKeys, stateKeys, add, warn);
|
|
966
1069
|
const keyframeNames = validateKeyframes(doc.keyframes, add, warn);
|
|
967
1070
|
const isMulti = doc.views !== void 0;
|
|
968
1071
|
if (isMulti) validateMultiView(doc, add);
|
|
@@ -1211,7 +1314,7 @@ function validateState(state, add) {
|
|
|
1211
1314
|
}
|
|
1212
1315
|
return Object.keys(state);
|
|
1213
1316
|
}
|
|
1214
|
-
function validateDerived(derived, dataKeys, stateKeys, add) {
|
|
1317
|
+
function validateDerived(derived, dataKeys, stateKeys, add, warn) {
|
|
1215
1318
|
if (derived === void 0) return;
|
|
1216
1319
|
if (typeof derived !== "object" || derived === null || Array.isArray(derived)) {
|
|
1217
1320
|
add("derived", "derived \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
@@ -1229,6 +1332,7 @@ function validateDerived(derived, dataKeys, stateKeys, add) {
|
|
|
1229
1332
|
} else if (stateKeys.indexOf(item.indexBy) === -1) {
|
|
1230
1333
|
add(`derived.${key}.indexBy`, `state \u4E2D\u4E0D\u5B58\u5728 "${item.indexBy}"`);
|
|
1231
1334
|
}
|
|
1335
|
+
validateAutoplay(item.autoplay, `derived.${key}.autoplay`, add, warn);
|
|
1232
1336
|
});
|
|
1233
1337
|
}
|
|
1234
1338
|
function validateNodeStyle(style, path, ctx) {
|
|
@@ -1443,4 +1547,4 @@ function formatIssues(issues) {
|
|
|
1443
1547
|
return issues.map((item) => item.path ? `${item.path}: ${item.message}` : item.message).join("\n");
|
|
1444
1548
|
}
|
|
1445
1549
|
|
|
1446
|
-
export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, DEFAULT_USER_FIELDS, DSL_VERSION, NODE_TYPES, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, check, computeParts, createCssBuilder, createTicker, declarations, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isValidEasing, isValidEndTime, nextScopeUid, normalizeViews, parseEndTime, resolveNodeStyle, sanitizeCssValue, toCssStyle, toLength, validate, validateUserFields };
|
|
1550
|
+
export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, AUTOPLAY_FIELDS, AUTOPLAY_MIN_INTERVAL, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, DEFAULT_USER_FIELDS, DERIVED_FIELDS, DSL_VERSION, NODE_TYPES, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, check, computeParts, createAutoplay, createCssBuilder, createTicker, declarations, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isValidEasing, isValidEndTime, nextScopeUid, normalizeViews, parseEndTime, resolveNodeStyle, sanitizeCssValue, toCssStyle, toLength, validate, validateAutoplay, validateUserFields };
|
package/dist/docs/index.cjs
CHANGED
|
@@ -129,6 +129,11 @@ var ALLOWED_EASINGS = [
|
|
|
129
129
|
"step-end"
|
|
130
130
|
];
|
|
131
131
|
|
|
132
|
+
// src/autoplay.ts
|
|
133
|
+
var DERIVED_FIELDS = ["list", "indexBy", "autoplay"];
|
|
134
|
+
var AUTOPLAY_FIELDS = ["interval", "pauseOnHover"];
|
|
135
|
+
var AUTOPLAY_MIN_INTERVAL = 300;
|
|
136
|
+
|
|
132
137
|
// src/validate.ts
|
|
133
138
|
var DSL_VERSION = 1;
|
|
134
139
|
var NODE_TYPES = [
|
|
@@ -477,9 +482,14 @@ countdown_end // \u5012\u8BA1\u65F6\u5F52\u96F6`
|
|
|
477
482
|
"`close` \u7684 `extra.name`\uFF08`reason` \u4ECD\u662F\u5173\u95ED\u539F\u56E0\uFF09"
|
|
478
483
|
],
|
|
479
484
|
[
|
|
480
|
-
"\u5173\u95ED\u6309\u94AE\u7684 `action` \u91CC\uFF08\u548C `close` \u5199\u5728\u540C\u4E00\u4E2A `sequence`\uFF09",
|
|
485
|
+
"\u5173\u95ED\u6309\u94AE\u7684 `action` \u91CC\uFF08\u548C `close` \u5199\u5728\u540C\u4E00\u4E2A `sequence`\uFF0C\u4E14**\u4E0D\u8DF3\u8F6C**\uFF09",
|
|
481
486
|
"**\u4E0D\u7B97\u70B9\u51FB**\uFF0C\u5E76\u8FDB\u90A3\u6761\u5173\u95ED",
|
|
482
487
|
"`close` \u7684 `extra.name`"
|
|
488
|
+
],
|
|
489
|
+
[
|
|
490
|
+
"\u4E3B\u6309\u94AE\u7684 `action` \u91CC\uFF08`sequence` \u91CC\u65E2\u6709 `close` / `closeAll`\uFF0C\u53C8\u6709 `navigate`\uFF09",
|
|
491
|
+
"**\u7B97\u4E00\u6761 `click`**\uFF08\u8DF3\u8D70\u4E86\u5C31\u662F\u8F6C\u5316\uFF09",
|
|
492
|
+
"`extra.name`\uFF1B\u8DF3\u8F6C\u5730\u5740\u5E76\u8FDB `extra.url`"
|
|
483
493
|
]
|
|
484
494
|
]
|
|
485
495
|
},
|
|
@@ -491,7 +501,12 @@ countdown_end // \u5012\u8BA1\u65F6\u5F52\u96F6`
|
|
|
491
501
|
{
|
|
492
502
|
t: "note",
|
|
493
503
|
tone: "warn",
|
|
494
|
-
text: '**\u5173\u95ED\u52A8\u4F5C\u4E0D\u4EA7\u751F\u70B9\u51FB\u3002**\
|
|
504
|
+
text: '**\u7EAF\u5173\u95ED\u52A8\u4F5C\u4E0D\u4EA7\u751F\u70B9\u51FB\u3002**\u8FD9\u4E00\u4E0B\u6267\u884C\u4E86 `close` / `closeAll`\u3001\u53C8\u6CA1\u6709\u8DF3\u8F6C\uFF0C\u5B83\u7684\u672C\u8D28\u5C31\u662F\u300C\u5173\u6389\u5B83\u300D\u800C\u4E0D\u662F\u300C\u70B9\u4E86\u5B83\u300D\u2014\u2014\u540E\u7AEF\u7B97\u70B9\u51FB\u7387\u65F6\u5206\u6BCD\u662F\u66DD\u5149\u3001\u5206\u5B50\u662F\u70B9\u51FB\uFF0C\u628A\u5173\u95ED\u7B97\u8FDB\u70B9\u51FB\u4F1A\u8BA9\u70B9\u51FB\u7387\u865A\u9AD8\u3002\u4F60\u914D\u5728\u5173\u95ED\u6309\u94AE\u4E0A\u7684\u57CB\u70B9\u540D\u4E0D\u4F1A\u4E22\uFF0C\u5B83\u8FDB\u4E86 `close` \u7684 `extra`\u3002\u60F3\u533A\u5206\u300C\u4ECE\u54EA\u4E2A\u5165\u53E3\u5173\u7684\u300D\uFF0C\u66F4\u63A8\u8350\u7528 `close` \u52A8\u4F5C\u7684 `reason`\uFF08\u5982 `reason: "user-dismiss"`\uFF09\u3002'
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
t: "note",
|
|
508
|
+
tone: "info",
|
|
509
|
+
text: "**\u4F46\u300C\u70B9\u4E86\u5C31\u8DF3\u8D70\u300D\u7684\u6309\u94AE\u5373\u4F7F\u5E26\u5173\u95ED\u4E5F\u7B97\u4E00\u6B21\u70B9\u51FB\u3002**\u4E3B CTA \u5E38\u5199\u6210 `sequence: [track, closeAll, navigate]`\uFF08\u8DF3\u8D70\u524D\u987A\u624B\u628A\u5F39\u7A97\u6536\u6389\uFF09\uFF0C\u540C\u4E00\u6B21\u624B\u52BF\u91CC\u53EA\u8981\u6709 `navigate`\uFF0C\u5C31\u7167\u5E38\u4E0A\u62A5\u4E00\u6761 `click`\u2014\u2014\u7528\u6237\u771F\u7684\u8DF3\u8FC7\u53BB\u4E86\uFF0C\u8FD9\u662F\u8F6C\u5316\u884C\u4E3A\uFF0C\u5173\u95ED\u53EA\u662F\u5B83\u7684\u526F\u4F5C\u7528\u3002\u8FD9\u6761 `click` \u7684 `extra` \u91CC\u65E2\u6709\u4F60\u914D\u7684\u57CB\u70B9\u540D\uFF0C\u4E5F\u6709\u8DF3\u8F6C\u5730\u5740\uFF1B\u8FD9\u4E00\u4E0B\u4E0D\u4F1A\u518D\u628A\u57CB\u70B9\u540D\u5E76\u8FDB `close`\uFF0C\u540C\u4E00\u4E2A\u540D\u5B57\u4E0D\u4F1A\u88AB\u62A5\u4E24\u904D\u3002"
|
|
495
510
|
},
|
|
496
511
|
{
|
|
497
512
|
t: "note",
|
|
@@ -852,6 +867,18 @@ var userFieldRows = DEFAULT_USER_FIELDS.map((field) => [
|
|
|
852
867
|
`\`user.${field}\``,
|
|
853
868
|
USER_FIELD_LABELS[field] || ""
|
|
854
869
|
]);
|
|
870
|
+
var derivedRows = [
|
|
871
|
+
["list", "`data` \u91CC\u7684\u6570\u7EC4\u5B57\u6BB5\u540D"],
|
|
872
|
+
["indexBy", "`state` \u91CC\u7684\u4E0B\u6807\u5B57\u6BB5\u540D"],
|
|
873
|
+
["autoplay", "\u53EF\u9009\u3002\u81EA\u52A8\u8F6E\u64AD\uFF0C\u89C1\u4E0B"]
|
|
874
|
+
];
|
|
875
|
+
var autoplayRows = [
|
|
876
|
+
[
|
|
877
|
+
"interval",
|
|
878
|
+
`\u5FC5\u586B\u3002\u5207\u6362\u95F4\u9694\uFF0C**\u5355\u4F4D\u6BEB\u79D2**\uFF0C\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL}\uFF08\u5982 \`4000\` = 4 \u79D2\uFF09`
|
|
879
|
+
],
|
|
880
|
+
["pauseOnHover", "\u53EF\u9009\uFF0C\u9ED8\u8BA4 `false`\u3002\u9F20\u6807\u60AC\u505C\u5728\u6574\u4E2A\u7269\u6599\u4E0A\u65F6\u6682\u505C\uFF0C\u79FB\u5F00\u540E\u91CD\u65B0\u8BA1\u65F6"]
|
|
881
|
+
];
|
|
855
882
|
var sections4 = [
|
|
856
883
|
{
|
|
857
884
|
id: "data",
|
|
@@ -921,9 +948,42 @@ var sections4 = [
|
|
|
921
948
|
{
|
|
922
949
|
t: "table",
|
|
923
950
|
head: ["\u5B57\u6BB5", "\u8BF4\u660E"],
|
|
924
|
-
rows:
|
|
925
|
-
|
|
926
|
-
|
|
951
|
+
rows: derivedRows.concat(
|
|
952
|
+
reconcileRows({ rows: derivedRows, actual: DERIVED_FIELDS, label: "\u65B0\u589E\u5B57\u6BB5" })
|
|
953
|
+
)
|
|
954
|
+
},
|
|
955
|
+
{ t: "h3", text: "derived.autoplay\uFF1A\u81EA\u52A8\u8F6E\u64AD" },
|
|
956
|
+
{
|
|
957
|
+
t: "p",
|
|
958
|
+
text: "\u516C\u544A\u6761\u8F6E\u64AD\u6587\u6848\u3001\u8F6E\u64AD\u56FE\u8FD9\u7C7B\u300C\u9694\u51E0\u79D2\u81EA\u52A8\u6362\u4E0B\u4E00\u6761\u300D\u7684\u9700\u6C42\uFF0C\u5728 derived \u4E0A\u52A0 `autoplay` \u5373\u53EF\u3002\u914D\u4E86\u5C31\u5F00\u542F\u3001\u59CB\u7EC8\u5FAA\u73AF\uFF1A\u6BCF\u9694 `interval` \u6BEB\u79D2\u628A `state[indexBy]` \u52A0 1\uFF0C\u5230\u672B\u5C3E\u56DE\u5230 0\u3002\u5B83\u6539\u72B6\u6001\u8D70\u7684\u5C31\u662F\u70B9 tab \u90A3\u4E00\u6761\u8DEF\uFF0C\u6240\u4EE5\u6587\u6848\u3001\u56FE\u7247\u3001tabs \u5706\u70B9\u6307\u793A\u5668\u3001\u8DF3\u8F6C\u94FE\u63A5\u4F1A\u4E00\u8D77\u5207\uFF0C\u6548\u679C\u548C\u7528\u6237\u624B\u52A8\u70B9\u5B8C\u5168\u4E00\u6837\u2014\u2014\u4E0D\u4F1A\u51ED\u7A7A\u591A\u51FA\u5207\u6362\u52A8\u753B\uFF0C\u60F3\u8981\u8FC7\u6E21\u6548\u679C\u81EA\u5DF1\u5728 `style` \u91CC\u914D `transition`\u3002"
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
t: "code",
|
|
962
|
+
code: `"data": { "slides": [ { "text": "\u2026", "url": "\u2026" }, { \u2026 }, { \u2026 } ] },
|
|
963
|
+
"state": { "slide": 0 },
|
|
964
|
+
"derived": { "cur": { "list": "slides", "indexBy": "slide",
|
|
965
|
+
"autoplay": { "interval": 4000, "pauseOnHover": true } } }
|
|
966
|
+
|
|
967
|
+
// \u6587\u6848 {{ cur.text }}\u3001\u94FE\u63A5 {{ cur.url }} \u81EA\u52A8\u8DDF\u7740\u5F53\u524D\u9879\u8D70\uFF1B
|
|
968
|
+
// \u5706\u70B9\u6307\u793A\u5668\u5C31\u662F\u4E00\u4E2A tabs\uFF1A{ "type": "tabs", "bind": "slides", "stateKey": "slide" }`
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
t: "table",
|
|
972
|
+
head: ["\u5B57\u6BB5", "\u8BF4\u660E"],
|
|
973
|
+
rows: autoplayRows.concat(
|
|
974
|
+
reconcileRows({
|
|
975
|
+
rows: autoplayRows,
|
|
976
|
+
actual: AUTOPLAY_FIELDS,
|
|
977
|
+
label: "\u65B0\u589E\u5B57\u6BB5"
|
|
978
|
+
})
|
|
979
|
+
)
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
t: "list",
|
|
983
|
+
items: [
|
|
984
|
+
"\u7528\u6237\u70B9\u4E86 tab\uFF08\u6216\u4EFB\u4F55 `setState` \u6539\u4E86\u540C\u4E00\u4E2A key\uFF09\u4F1A**\u91CD\u65B0\u8BA1\u65F6**\uFF0C\u4E0D\u4F1A\u521A\u70B9\u5B8C\u5C31\u88AB\u5207\u8D70",
|
|
985
|
+
"\u5217\u8868\u53EA\u6709 0~1 \u6761\u3001\u6216\u6570\u636E\u6E90\u8FD8\u6CA1\u56DE\u6765\u65F6\u4E0D\u64AD\uFF1B\u6570\u636E\u56DE\u6765\u540E\u81EA\u52A8\u5F00\u59CB",
|
|
986
|
+
"\u6CA1\u6709 `enabled` / `loop` \u5F00\u5173\uFF1A\u4E0D\u60F3\u8F6E\u64AD\u5C31\u522B\u5199 `autoplay`\uFF0C\u5199\u4E86\u5C31\u4E00\u76F4\u5FAA\u73AF"
|
|
927
987
|
]
|
|
928
988
|
}
|
|
929
989
|
]
|
|
@@ -1851,6 +1911,15 @@ var sections_default = sections10;
|
|
|
1851
1911
|
|
|
1852
1912
|
// src/docs/meta.ts
|
|
1853
1913
|
var changelog = [
|
|
1914
|
+
{
|
|
1915
|
+
date: "2026-09-22",
|
|
1916
|
+
items: [
|
|
1917
|
+
'\u65B0\u589E derived.autoplay \u81EA\u52A8\u8F6E\u64AD\uFF08\u7B2C 8 \u8282\uFF09\uFF1A`{ "interval": 4000, "pauseOnHover": true }` \u6302\u5728 derived \u4E0A\u5373\u53EF\u8BA9\u516C\u544A\u6761\u6587\u6848 / \u8F6E\u64AD\u56FE\u6BCF\u9694\u51E0\u79D2\u81EA\u52A8\u6362\u4E0B\u4E00\u6761\u3001\u5230\u672B\u5C3E\u56DE\u5230\u7B2C\u4E00\u6761\u3002\u5207\u6362\u8D70\u7684\u662F\u548C\u70B9 tab \u540C\u4E00\u6761\u8DEF\uFF0C\u6587\u6848\u3001\u56FE\u7247\u3001\u5706\u70B9\u6307\u793A\u5668\u3001\u8DF3\u8F6C\u94FE\u63A5\u4E00\u8D77\u5207\uFF1B\u7528\u6237\u624B\u52A8\u70B9\u8FC7\u4F1A\u91CD\u65B0\u8BA1\u65F6\uFF0C\u5217\u8868\u4E0D\u8DB3 2 \u6761\u6216\u6570\u636E\u6CA1\u56DE\u6765\u65F6\u4E0D\u64AD',
|
|
1918
|
+
"autoplay \u4FDD\u5B58\u65F6\u4F1A\u6821\u9A8C\uFF1Ainterval \u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E 300 \u7684\u6BEB\u79D2\u6570\uFF08\u5199\u6210 4 \u8868\u793A 4 \u6BEB\u79D2\uFF0C\u4F1A\u88AB\u62E6\u4E0B\uFF09\uFF0CpauseOnHover \u5FC5\u987B\u662F\u5E03\u5C14\uFF1B\u6CA1\u6709 enabled / loop \u5B57\u6BB5\uFF0C\u5199\u4E86\u53EA\u544A\u8B66\u5E76\u88AB\u5FFD\u7565",
|
|
1919
|
+
"\u65B0\u589E\u793A\u4F8B \u246D \u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF1A3 \u6761\u6587\u6848 + tabs \u5706\u70B9\u6307\u793A\u5668 + \u8DF3\u8F6C\u94FE\u63A5\u8DDF\u968F\u5F53\u524D\u9879\uFF0C\u8981\u505A\u8F6E\u64AD\u6284\u8FD9\u4EFD",
|
|
1920
|
+
"\u6846\u67B6\u58F3\u65B0\u589E\u4E00\u6761\u4E49\u52A1\uFF1A\u6E32\u67D3\u6811\u5E26 onRootEnter / onRootLeave \u65F6\u5728\u6839\u5BB9\u5668\u4E0A\u7ED1 mouseenter / mouseleave\uFF08Vue 2 \u58F3\u5DF2\u8DDF\u4E0A\uFF09"
|
|
1921
|
+
]
|
|
1922
|
+
},
|
|
1854
1923
|
{
|
|
1855
1924
|
date: "2026-09-01",
|
|
1856
1925
|
items: [
|
|
@@ -5326,6 +5395,142 @@ var quotaLow = {
|
|
|
5326
5395
|
};
|
|
5327
5396
|
var quota_low_default = quotaLow;
|
|
5328
5397
|
|
|
5398
|
+
// src/docs/examples/notice-carousel.ts
|
|
5399
|
+
var slides = [
|
|
5400
|
+
{
|
|
5401
|
+
key: "move",
|
|
5402
|
+
text: "\u{1F389} \u4ECA\u65E5\u5DF2\u6709 12,806 \u5BB6\u5E97\u94FA\u7528\u9EA6\u7206\u4E86\u5B8C\u6210\u5546\u54C1\u642C\u5BB6",
|
|
5403
|
+
url: "https://maibaole.example.com/move",
|
|
5404
|
+
// tabs 的标签字段,圆点不显示文字,留空串
|
|
5405
|
+
dot: ""
|
|
5406
|
+
},
|
|
5407
|
+
{
|
|
5408
|
+
key: "ai",
|
|
5409
|
+
text: "\u{1F525} AI \u667A\u80FD\u4F18\u5316\u672C\u5468\u7D2F\u8BA1\u6539\u5199\u6807\u9898 38 \u4E07\u6761\uFF0C\u70B9\u51FB\u7387\u5E73\u5747\u63D0\u5347 17%",
|
|
5410
|
+
url: "https://maibaole.example.com/ai-optimize",
|
|
5411
|
+
dot: ""
|
|
5412
|
+
},
|
|
5413
|
+
{
|
|
5414
|
+
key: "renew",
|
|
5415
|
+
text: "\u{1F4B0} \u4E13\u4E1A\u7248\u9650\u65F6 8 \u6298\uFF0C\u7EED\u8D39\u7ACB\u7701 180 \u5143",
|
|
5416
|
+
url: "https://maibaole.example.com/renew",
|
|
5417
|
+
dot: ""
|
|
5418
|
+
}
|
|
5419
|
+
];
|
|
5420
|
+
var noticeCarousel = {
|
|
5421
|
+
version: 1,
|
|
5422
|
+
type: "notice",
|
|
5423
|
+
meta: { name: "\u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF08\u81EA\u52A8\u8F6E\u64AD\uFF09" },
|
|
5424
|
+
data: { slides },
|
|
5425
|
+
state: { slide: 0 },
|
|
5426
|
+
derived: {
|
|
5427
|
+
cur: {
|
|
5428
|
+
list: "slides",
|
|
5429
|
+
indexBy: "slide",
|
|
5430
|
+
// 4 秒一条,悬停暂停;单位是毫秒
|
|
5431
|
+
autoplay: { interval: 4e3, pauseOnHover: true }
|
|
5432
|
+
}
|
|
5433
|
+
},
|
|
5434
|
+
stage: {
|
|
5435
|
+
width: "100%",
|
|
5436
|
+
height: "auto",
|
|
5437
|
+
layout: "flow",
|
|
5438
|
+
// 通栏类型不写 maxWidth,宽度交给宿主坑位
|
|
5439
|
+
style: { radius: 6, background: "#fff8e6" },
|
|
5440
|
+
onShow: { type: "track", event: "notice_show", params: { notice: "carousel" } },
|
|
5441
|
+
onClose: {
|
|
5442
|
+
type: "track",
|
|
5443
|
+
event: "notice_dismiss",
|
|
5444
|
+
params: { notice: "carousel", reason: "{{ closeReason }}" }
|
|
5445
|
+
}
|
|
5446
|
+
},
|
|
5447
|
+
nodes: [
|
|
5448
|
+
{
|
|
5449
|
+
type: "flex",
|
|
5450
|
+
style: { align: "center", gap: 10, padding: "10px 14px" },
|
|
5451
|
+
children: [
|
|
5452
|
+
{
|
|
5453
|
+
// 文案跟着当前项走;定高单行,换条时公告条高度不跳
|
|
5454
|
+
type: "text",
|
|
5455
|
+
content: "{{ cur.text }}",
|
|
5456
|
+
style: {
|
|
5457
|
+
flex: "1",
|
|
5458
|
+
fontSize: 14,
|
|
5459
|
+
color: "#8a6212",
|
|
5460
|
+
lineHeight: 22,
|
|
5461
|
+
height: 22,
|
|
5462
|
+
overflow: "hidden",
|
|
5463
|
+
whiteSpace: "nowrap"
|
|
5464
|
+
}
|
|
5465
|
+
},
|
|
5466
|
+
{
|
|
5467
|
+
// 圆点指示器:当前项拉长成胶囊,宽度变化用 transition 过渡
|
|
5468
|
+
type: "tabs",
|
|
5469
|
+
bind: "slides",
|
|
5470
|
+
stateKey: "slide",
|
|
5471
|
+
labelField: "dot",
|
|
5472
|
+
style: { direction: "row", align: "center", gap: 6 },
|
|
5473
|
+
itemStyle: {
|
|
5474
|
+
width: 6,
|
|
5475
|
+
height: 6,
|
|
5476
|
+
radius: 3,
|
|
5477
|
+
background: "rgba(176,138,62,0.35)",
|
|
5478
|
+
cursor: "pointer",
|
|
5479
|
+
transition: "width 0.3s ease"
|
|
5480
|
+
},
|
|
5481
|
+
activeItemStyle: { width: 16, background: "#f5a623" },
|
|
5482
|
+
action: {
|
|
5483
|
+
type: "track",
|
|
5484
|
+
event: "notice_dot_click",
|
|
5485
|
+
params: { notice: "carousel" }
|
|
5486
|
+
}
|
|
5487
|
+
},
|
|
5488
|
+
{
|
|
5489
|
+
// 链接跟着当前项走:看到哪条、点的就是哪条
|
|
5490
|
+
type: "button",
|
|
5491
|
+
text: "\u53BB\u770B\u770B",
|
|
5492
|
+
style: {
|
|
5493
|
+
width: 64,
|
|
5494
|
+
height: 26,
|
|
5495
|
+
radius: 13,
|
|
5496
|
+
background: "#f5a623",
|
|
5497
|
+
color: "#fff",
|
|
5498
|
+
fontSize: 12,
|
|
5499
|
+
cursor: "pointer"
|
|
5500
|
+
},
|
|
5501
|
+
action: {
|
|
5502
|
+
type: "sequence",
|
|
5503
|
+
actions: [
|
|
5504
|
+
{
|
|
5505
|
+
type: "track",
|
|
5506
|
+
event: "notice_click",
|
|
5507
|
+
params: { notice: "carousel", slide: "{{ cur.key }}" }
|
|
5508
|
+
},
|
|
5509
|
+
{ type: "navigate", url: "{{ cur.url }}", target: "_blank" }
|
|
5510
|
+
]
|
|
5511
|
+
}
|
|
5512
|
+
},
|
|
5513
|
+
{
|
|
5514
|
+
type: "text",
|
|
5515
|
+
content: "\u2715",
|
|
5516
|
+
style: {
|
|
5517
|
+
alignSelf: "center",
|
|
5518
|
+
width: 22,
|
|
5519
|
+
height: 22,
|
|
5520
|
+
textAlign: "center",
|
|
5521
|
+
lineHeight: 22,
|
|
5522
|
+
color: "#b08a3e",
|
|
5523
|
+
fontSize: 13,
|
|
5524
|
+
cursor: "pointer"
|
|
5525
|
+
},
|
|
5526
|
+
action: { type: "close", reason: "user-close" }
|
|
5527
|
+
}
|
|
5528
|
+
]
|
|
5529
|
+
}
|
|
5530
|
+
]
|
|
5531
|
+
};
|
|
5532
|
+
var notice_carousel_default = noticeCarousel;
|
|
5533
|
+
|
|
5329
5534
|
// src/docs/examples/index.ts
|
|
5330
5535
|
var HOTSPOT_BG = "rgba(255,68,51,0.16)";
|
|
5331
5536
|
var imageHotspot = {
|
|
@@ -5591,6 +5796,11 @@ var examples = [
|
|
|
5591
5796
|
label: "\u246C \u590D\u523B\u8FD0\u8425 demo \xB7 \u642C\u5BB6\u6B21\u6570\u5C06\u5C3D\uFF08\u989D\u5EA6\u8FDB\u5EA6\u6761\uFF09",
|
|
5592
5797
|
value: "quotaLow",
|
|
5593
5798
|
dsl: quota_low_default
|
|
5799
|
+
},
|
|
5800
|
+
{
|
|
5801
|
+
label: "\u246D \u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF08\u81EA\u52A8\u8F6E\u64AD + \u5706\u70B9\u6307\u793A\u5668\uFF09",
|
|
5802
|
+
value: "noticeCarousel",
|
|
5803
|
+
dsl: notice_carousel_default
|
|
5594
5804
|
}
|
|
5595
5805
|
];
|
|
5596
5806
|
var examples_default = examples;
|
|
@@ -5769,6 +5979,7 @@ function checklistSection() {
|
|
|
5769
5979
|
- [ ] \u6240\u6709 \`style\` \u7684\u5C5E\u6027\u540D\u90FD\u5728\u767D\u540D\u5355\u91CC
|
|
5770
5980
|
- [ ] \u6CA1\u6709\u4EFB\u4F55 JS \u4EE3\u7801\u3001\`javascript:\` \u94FE\u63A5\u3001\u51FD\u6570\u8C03\u7528
|
|
5771
5981
|
- [ ] \`derived.list\` \u6307\u5411\u7684\u5B57\u6BB5\u5728 \`data\` \u91CC\u771F\u5B9E\u5B58\u5728\uFF0C\`derived.indexBy\` \u5728 \`state\` \u91CC\u5B58\u5728
|
|
5982
|
+
- [ ] \u7528\u4E86 \`derived.autoplay\` \u7684\u8BDD\uFF1A\`interval\` \u662F \u2265${AUTOPLAY_MIN_INTERVAL} \u7684\u6BEB\u79D2\u6570\u5B57\uFF08\u4E0D\u662F\u79D2\uFF09\uFF0C\u6CA1\u6709\u5199 \`enabled\` / \`loop\` \u8FD9\u7C7B\u4E0D\u5B58\u5728\u7684\u5B57\u6BB5
|
|
5772
5983
|
- [ ] \u7528\u4E86 \`views\` \u7684\u8BDD\uFF1A\`entry\` \u5B58\u5728\u4E8E \`views\`\uFF0C\u9876\u5C42\u6CA1\u6709\u6B8B\u7559 \`stage\`/\`nodes\`\uFF0C\u6240\u6709 \`open\` \u7684 \`view\` \u90FD\u80FD\u5BF9\u4E0A
|
|
5773
5984
|
- [ ] \`repeat.bind\` \u6307\u5411\u7684\u662F\u6570\u7EC4
|
|
5774
5985
|
- [ ] \u6BCF\u4E2A\u53EF\u70B9\u51FB\u5143\u7D20\u90FD\u6709 \`action\`\uFF0C\u4E14\u5E26 \`track\` \u57CB\u70B9
|
|
@@ -6018,6 +6229,18 @@ function dataSection() {
|
|
|
6018
6229
|
\u4E4B\u540E\u4EFB\u610F\u8282\u70B9\u91CC\u7528 \`{{ current.price }}\` \`{{ current.url }}\`\uFF0C
|
|
6019
6230
|
\u5207\u6362\u65F6\u4EF7\u683C\u3001\u94FE\u63A5\u3001\u57CB\u70B9\u53C2\u6570\u5168\u90E8\u81EA\u52A8\u8054\u52A8\uFF0C\u7248\u5F0F\u53EA\u9700\u8981\u6392\u4E00\u904D\u3002
|
|
6020
6231
|
|
|
6232
|
+
**\u81EA\u52A8\u8F6E\u64AD**\uFF08\u516C\u544A\u6761\u8F6E\u64AD\u6587\u6848 / \u6218\u62A5\u6EDA\u52A8\u3001\u8F6E\u64AD\u56FE\uFF09\u7528 \`derived.xxx.autoplay\`\uFF0C\u4E0D\u8981\u81EA\u5DF1\u62FC\u5B9A\u65F6\u903B\u8F91\uFF1A
|
|
6233
|
+
|
|
6234
|
+
\`\`\`jsonc
|
|
6235
|
+
"state": { "slide": 0 },
|
|
6236
|
+
"derived": { "cur": { "list": "slides", "indexBy": "slide",
|
|
6237
|
+
"autoplay": { "interval": 4000, "pauseOnHover": true } } }
|
|
6238
|
+
\`\`\`
|
|
6239
|
+
|
|
6240
|
+
- \`interval\` \u5FC5\u586B\uFF0C**\u5355\u4F4D\u6BEB\u79D2**\uFF0C\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL}\uFF1B\`pauseOnHover\` \u53EF\u9009\u5E03\u5C14\uFF08\u60AC\u505C\u6682\u505C\uFF09
|
|
6241
|
+
- \u53EA\u6709\u8FD9\u4E24\u4E2A\u5B57\u6BB5\uFF0C**\u6CA1\u6709** \`enabled\` / \`loop\`\uFF1A\u914D\u4E86\u5C31\u5F00\u542F\u3001\u59CB\u7EC8\u5FAA\u73AF
|
|
6242
|
+
- \u5207\u6362\u6548\u679C\u4E0E\u70B9 tab \u5B8C\u5168\u4E00\u6837\uFF0C\u6587\u6848 / \u56FE\u7247 / \u94FE\u63A5\u90FD\u4ECE \`{{ cur.xxx }}\` \u53D6\uFF1B\u8981\u5706\u70B9\u6307\u793A\u5668\u5C31\u653E\u4E00\u4E2A \`tabs\`\uFF08\`bind\` \u540C\u4E00\u4E2A\u5217\u8868\u3001\`stateKey\` \u540C\u4E00\u4E2A state\uFF09
|
|
6243
|
+
|
|
6021
6244
|
\u6570\u636E\u8981\u4ECE\u540E\u7AEF\u53D6\u65F6\u5199 \`"tiers": { "$source": "\u6570\u636E\u6E90\u540D", "params": {} }\`\uFF0C
|
|
6022
6245
|
\u6570\u636E\u6E90\u540D\u5FC5\u987B\u662F\u540E\u7AEF\u5DF2\u6CE8\u518C\u7684\uFF0C**\u4E0D\u80FD\u5199\u63A5\u53E3\u5730\u5740**\u3002\u7528\u6237\u6CA1\u8BF4\u5C31\u7528\u5199\u6B7B\u7684\u6570\u636E\u3002
|
|
6023
6246
|
|
package/dist/docs/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as Dsl } from '../types-
|
|
1
|
+
import { D as Dsl } from '../types-BapBTTio.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 开发文档的数据结构。
|
|
@@ -97,7 +97,8 @@ declare const meta: DocMeta;
|
|
|
97
97
|
* ①② 是最小骨架,③④ 是运营 demo 真实弹窗的完整复刻,⑤⑥ 是多视图,⑦ 是换肤换布局,
|
|
98
98
|
* ⑧ 是通栏 banner(宽度由页面决定、只能声明比例),⑨⑩ 是商品编辑抽屉里两个**固定尺寸**坑位,
|
|
99
99
|
* ⑪⑫ 是搬家成功页两个线上弹窗的一比一复刻(动画、hover、相对时长倒计时的完整用法),
|
|
100
|
-
* ⑬
|
|
100
|
+
* ⑬ 是额度进度条(用表达式算填充宽度,要画任何比例条都抄这份),
|
|
101
|
+
* ⑭ 是公告条自动轮播(derived.autoplay + tabs 圆点指示器)。
|
|
101
102
|
* 后端数据源($source)用法见 ③。
|
|
102
103
|
*/
|
|
103
104
|
|
package/dist/docs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as Dsl } from '../types-
|
|
1
|
+
import { D as Dsl } from '../types-BapBTTio.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 开发文档的数据结构。
|
|
@@ -97,7 +97,8 @@ declare const meta: DocMeta;
|
|
|
97
97
|
* ①② 是最小骨架,③④ 是运营 demo 真实弹窗的完整复刻,⑤⑥ 是多视图,⑦ 是换肤换布局,
|
|
98
98
|
* ⑧ 是通栏 banner(宽度由页面决定、只能声明比例),⑨⑩ 是商品编辑抽屉里两个**固定尺寸**坑位,
|
|
99
99
|
* ⑪⑫ 是搬家成功页两个线上弹窗的一比一复刻(动画、hover、相对时长倒计时的完整用法),
|
|
100
|
-
* ⑬
|
|
100
|
+
* ⑬ 是额度进度条(用表达式算填充宽度,要画任何比例条都抄这份),
|
|
101
|
+
* ⑭ 是公告条自动轮播(derived.autoplay + tabs 圆点指示器)。
|
|
101
102
|
* 后端数据源($source)用法见 ③。
|
|
102
103
|
*/
|
|
103
104
|
|