@lark-apaas/coding-steering 0.1.24-alpha.20260729134517 → 0.1.24-beta.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 +19 -21
- package/package.json +1 -1
- package/steering/design-html/skills/animated-video/SKILL.md +1 -1
- package/steering/design-html/skills/charts/SKILL.md +48 -7
- package/steering/design-html/skills/{data-report → data-viz}/SKILL.md +65 -9
- package/steering/design-html/skills/interactive-prototype/SKILL.md +19 -2
- package/steering/design-html/skills/slide-deck/SKILL.md +145 -0
- package/steering/design-html/skills/visual-exposure/SKILL.md +23 -1
- package/steering/nestjs-react-fullstack/skills_common/trigger-guide/SKILL.md +180 -0
- package/steering/nestjs-react-fullstack/{skills/trigger-guide/SKILL.md → skills_common/trigger-guide/references/trigger-lifecycle.md} +11 -162
- package/steering/design-html/skills/make-a-deck/SKILL.md +0 -209
package/README.md
CHANGED
|
@@ -2,23 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Stack-specific steering content for [miaoda coding](https://code.byted.org/apaas/miaoda-coding) templates.
|
|
4
4
|
|
|
5
|
-
Consumed by [miaoda-cli](https://code.byted.org/apaas/miaoda-cli)
|
|
5
|
+
Consumed by [miaoda-cli](https://code.byted.org/apaas/miaoda-cli) during `miaoda skills sync` (including `app init`). It is **not a runtime dependency** — no entry in the user project's `package.json`.
|
|
6
6
|
|
|
7
7
|
## Layout
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
steering/
|
|
11
|
-
├── _common/
|
|
12
|
-
│ └── skills/ # cross-stack shared skills
|
|
13
11
|
├── <stack>/
|
|
14
|
-
│ ├── tech.md #
|
|
15
|
-
│ ├──
|
|
16
|
-
│
|
|
17
|
-
│
|
|
12
|
+
│ ├── tech.md # optional, stack overview
|
|
13
|
+
│ ├── skills_common/<id>/SKILL.md # both local and sandbox; copied first
|
|
14
|
+
│ ├── skills/<id>/SKILL.md # sandbox-only; copied after common
|
|
15
|
+
│ └── skills_local/<id>/SKILL.md # local-only; copied after common
|
|
18
16
|
└── ...
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
Top-level directory names
|
|
19
|
+
Top-level directory names are stack IDs — discovery is by directory convention, with no central manifest.
|
|
22
20
|
|
|
23
21
|
## Supported stacks
|
|
24
22
|
|
|
@@ -31,7 +29,7 @@ vice versa). Current state:
|
|
|
31
29
|
| `vite-react` | React + Vite SPA | ✅ | `plugin-guide`, `react-three-fiber` | [`coding-template-vite-react`](../../templates/vite-react) |
|
|
32
30
|
| `html` | 妙搭 html,带 devserver | ✅ | `rich-interactive-design` | [`coding-template-html`](../../templates/html) |
|
|
33
31
|
| `nestjs-react-fullstack` | NestJS + React 全栈 | — | `authn`/`authz`/`feishu`/`plugin`/`devops`/`trigger`/`user-*` … + `skills_local/` (`code-fix`, `coding-guide`) | [`coding-template-nestjs-react-fullstack`](../../templates/nestjs-react-fullstack) |
|
|
34
|
-
| `design-html` | **无构建**纯静态 HTML
|
|
32
|
+
| `design-html` | **无构建**纯静态 HTML 托管(源码即产物) | — | _(占位,待补)_ | [`coding-template-design-html`](../../templates/design-html) |
|
|
35
33
|
| `design-stack` | **带构建**的 design / 创意栈(有工具链,区别于 buildless 的 `design-html`) | — | _(占位,待补)_ | _(暂无)_ |
|
|
36
34
|
|
|
37
35
|
`design-html` 与 `design-stack` 是两个**有意分开**的 design 栈:前者无构建、纯静态托管;
|
|
@@ -41,20 +39,20 @@ vice versa). Current state:
|
|
|
41
39
|
|
|
42
40
|
## Sync mapping (executed by miaoda-cli)
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|---|---|
|
|
46
|
-
| `steering/<stack>/tech.md` | `.agent/steering/tech.md` |
|
|
47
|
-
| `steering/<stack>/skills/<id>/**` | `.agent/steering/skills/<id>/**` |
|
|
48
|
-
| `steering/<stack>/skills_local/<id>/**` | `.agent/steering/skills/<id>/**` (local-dev sync only) |
|
|
49
|
-
| `steering/_common/skills/<id>/**` | `.agent/steering/skills/<id>/**` |
|
|
42
|
+
`MIAODA_DEP_CACHE_DIR` selects the source mode; `--local` selects only the output layout. Do not use a sandbox environment plus `--local` as evidence for either supported flow.
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
| Source in this package | Local output (`MIAODA_DEP_CACHE_DIR` empty + `--local`) | Sandbox output (`MIAODA_DEP_CACHE_DIR` non-empty, no `--local`) |
|
|
45
|
+
| ---------------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------- |
|
|
46
|
+
| `steering/<stack>/skills_common/<id>/**` | `.agents/skills/<id>/**` | `.agent/skills/steering/<stack>/skills/<id>/**` |
|
|
47
|
+
| `steering/<stack>/skills_local/<id>/**` | Same local path, copied after common. | Not copied. |
|
|
48
|
+
| `steering/<stack>/skills/<id>/**` | Not copied. | Same sandbox path, copied after common. |
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
For a duplicated skill ID, the copy order is:
|
|
51
|
+
|
|
52
|
+
- Local: `skills_common → skills_local`; the local variant wins.
|
|
53
|
+
- Sandbox: `skills_common → skills`; the sandbox variant wins.
|
|
54
|
+
|
|
55
|
+
Put a guide in `skills_common/<id>/SKILL.md` when it must reach both supported modes. Keep a same-name `skills/` or `skills_local/` copy only when a deliberate mode-specific override is required.
|
|
58
56
|
|
|
59
57
|
## Writing rules
|
|
60
58
|
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
# Animated video
|
|
11
11
|
|
|
12
|
-
Create an animated video or motion design piece rendered as an HTML page. Build a timeline-based animation with smooth transitions. Design frame-by-frame sequences with playback controls (play/pause, scrubber). Focus on visual storytelling
|
|
12
|
+
Create an animated video or motion design piece rendered as an HTML page. Build a timeline-based animation with smooth transitions. Design frame-by-frame sequences with playback controls (play/pause, scrubber). Focus on visual storytelling. Export-ready at a fixed aspect ratio (16:9 or 9:16). If you need to know the position of an element (eg to move a cursor or character between elements) use refs to grab the position.
|
|
13
13
|
|
|
14
14
|
START by calling `copy_starter_component` with `kind: "animations.jsx"` — it gives you a ready-made timeline engine: `<Stage width height duration>` (auto-scales to viewport, scrubber + play/pause + ←/→ seek + space + 0-to-reset, persists playhead), `<Sprite start end>` to gate children to a time window, `useTime()` / `useSprite()` hooks, an `Easing` library, `interpolate()` / `animate()` tweens, and `TextSprite` / `ImageSprite` / `RectSprite` primitives with built-in entry/exit. Read the file after copying and build YOUR scenes by composing Sprites inside a Stage; only fall back to Popmotion (https://sf3-scmcdn-cn.feishucdn.com/obj/feishu-static/miaoda/coding-unpkg-sdk/popmotion@11.0.5/dist/popmotion.min.js) if the starter genuinely can't do what you need.
|
|
15
15
|
|
|
@@ -48,7 +48,7 @@ metadata:
|
|
|
48
48
|
|
|
49
49
|
5. **编写 ECharts 代码。** 挂载模式和 API 约束见下方技术参考。
|
|
50
50
|
|
|
51
|
-
6. **自检。**
|
|
51
|
+
6. **自检。** 按文末清单验证渲染结果。然后回到视觉编码步骤:渲染出来的图表是否真的表达了你想表达的信息?颜色编码与仪表盘其他部分是否一致?
|
|
52
52
|
|
|
53
53
|
## 图表类型映射
|
|
54
54
|
|
|
@@ -77,6 +77,44 @@ metadata:
|
|
|
77
77
|
- **表达覆盖**:把用户需求拆成需要被回答的信息关系;每个被承诺的关系都要有对应的图表、表格、矩阵或文字证据承载。不要用少量通用指标和默认图表替代所有分析任务。
|
|
78
78
|
- **小容器防崩**:小尺寸图表优先用 bar / line / number strip。饼图、雷达图、词云和外部标签很容易挤压重叠;空间不足时换图表类型,而不是缩小到不可读。
|
|
79
79
|
|
|
80
|
+
## 窄屏适配
|
|
81
|
+
|
|
82
|
+
图表出现在报表或看板中时,移动端(≤768px)的容器宽度可能压到 300px 以下。盲目把桌面端图表原样塞进窄容器,会导致 axis label 堆叠、legend 遮盖绘图区、饼图标签溢出。以下是在窄屏容器中保证可读性的规则:
|
|
83
|
+
|
|
84
|
+
### 布局容器
|
|
85
|
+
|
|
86
|
+
报表中承载图表的网格必须在窄屏时折叠为单列。写多列网格时,用 `auto-fit` + `minmax()` 让浏览器自动折叠,或配合 `@media` 断点显式切换:
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
/* 自动折叠:每列最小 320px,不够就换行 */
|
|
90
|
+
.chart-grid {
|
|
91
|
+
display: grid;
|
|
92
|
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
93
|
+
gap: 16px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* 或显式断点 */
|
|
97
|
+
@media (max-width: 768px) {
|
|
98
|
+
.chart-grid { grid-template-columns: 1fr; }
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
不要写死 `grid-template-columns: 1.2fr 2fr` 而不提供窄屏回退——390px 视口下,1.2fr 只有 146px,放不下任何图表。
|
|
103
|
+
|
|
104
|
+
### ECharts option 适配
|
|
105
|
+
|
|
106
|
+
在窄容器(宽度 <400px)中调整 ECharts option:
|
|
107
|
+
|
|
108
|
+
- **legend**:改为 `orient: 'horizontal'` + `type: 'scroll'`,放在图表底部(`bottom: 0`),不要放在侧面挤占绘图区。
|
|
109
|
+
- **grid**:增大 `left` / `right` 留白到 `'12%'` 以上,防止 axis label 被裁切。
|
|
110
|
+
- **x 轴 label**:长文本加 `axisLabel: { rotate: 30, interval: 0 }` 或截断 formatter;分类超过 8 个时用 `interval: 'auto'` 让 ECharts 自动跳标签。
|
|
111
|
+
- **tooltip**:窄屏下 tooltip 容易超出视口,设 `confine: true`。
|
|
112
|
+
- **图表类型降级**:桌面端的并排双图在移动端改为上下堆叠;桌面端的 Pie 在容器宽度 <250px 时考虑改为横向 Bar。
|
|
113
|
+
|
|
114
|
+
### 容器尺寸监听
|
|
115
|
+
|
|
116
|
+
用 `ResizeObserver` 而非 `window.resize` 监听图表容器(见下方「技术参考 · 挂载」的封装代码)。当网格从双列折叠为单列时,window 尺寸不变但容器变宽,`resize` 事件不触发,图表不会重绘。
|
|
117
|
+
|
|
80
118
|
## 技术参考
|
|
81
119
|
|
|
82
120
|
### 加载 ECharts
|
|
@@ -94,23 +132,24 @@ metadata:
|
|
|
94
132
|
<script>
|
|
95
133
|
const chart = echarts.init(document.getElementById('chart'));
|
|
96
134
|
chart.setOption({ /* ... */ });
|
|
97
|
-
|
|
135
|
+
new ResizeObserver(() => chart.resize()).observe(document.getElementById('chart'));
|
|
98
136
|
</script>
|
|
99
137
|
```
|
|
100
138
|
|
|
101
139
|
### 挂载——React 封装
|
|
102
140
|
|
|
103
|
-
定义一次,复用。**不要**添加 echarts-for-react
|
|
141
|
+
定义一次,复用。**不要**添加 echarts-for-react。用 `ResizeObserver` 而非 `window.resize` 监听容器尺寸变化(见「窄屏适配」说明)。
|
|
104
142
|
|
|
105
143
|
```jsx
|
|
106
144
|
function EChart({ option, style }) {
|
|
107
145
|
const ref = React.useRef(null);
|
|
108
146
|
React.useEffect(() => {
|
|
109
|
-
const
|
|
147
|
+
const el = ref.current;
|
|
148
|
+
const chart = echarts.init(el);
|
|
110
149
|
chart.setOption(option);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
return () => {
|
|
150
|
+
const ro = new ResizeObserver(() => chart.resize());
|
|
151
|
+
ro.observe(el);
|
|
152
|
+
return () => { ro.disconnect(); chart.dispose(); };
|
|
114
153
|
}, [option]);
|
|
115
154
|
return <div ref={ref} style={{ width: '100%', minHeight: 300, ...style }} />;
|
|
116
155
|
}
|
|
@@ -152,6 +191,8 @@ Object.assign(window, { EChart });
|
|
|
152
191
|
| 17 | 双 Y 轴零点未对齐 | 匹配 `\|min\| / max` 比例 |
|
|
153
192
|
| 18 | 图表 series 或容器使用阴影/发光效果 | 移除 `shadowBlur`、`shadowColor`、容器 `box-shadow`,改用线宽、透明度、注释或面积大小表达层级 |
|
|
154
193
|
| 19 | 图表或标签挤压、重叠、被容器裁切 | 增大容器、减少标签、改用 tooltip / inside label,或换成更稳的图表类型 |
|
|
194
|
+
| 20 | 图表容器的父级网格在窄屏(≤768px)下没有折叠为单列 | 用 `auto-fit + minmax(320px, 1fr)` 或 `@media` 断点,保证每个图表容器至少 320px 宽 |
|
|
195
|
+
| 21 | 使用 `window.addEventListener('resize', ...)` 监听图表尺寸 | 改用 `ResizeObserver`——网格列折叠时 window 尺寸不变但容器变宽,`resize` 事件不触发 |
|
|
155
196
|
|
|
156
197
|
### 不建议
|
|
157
198
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: data-
|
|
3
|
-
description: "
|
|
2
|
+
name: data-viz
|
|
3
|
+
description: "数据可视化设计。从数据分析到版面规划、信息层级组织,适用于用户有数据文件或明确指标,需要产出结构化报表、看板或可视化页面的场景。图表绘制部分由 charts skill 承担。触发词:数据可视化, 数据报表, 数据看板, 数据分析报表, BI, 经营报表, 指标看板, 周报, 月报, 数据大盘, KPI, 报表设计, data visualization, data report, dashboard report, analytics report"
|
|
4
4
|
metadata:
|
|
5
5
|
display-names:
|
|
6
|
-
zh-CN:
|
|
7
|
-
en-US: Data
|
|
6
|
+
zh-CN: 数据可视化
|
|
7
|
+
en-US: Data Visualization
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# 数据可视化
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
你是数据可视化设计者。你的工作是把原始数据变成一份读者能直接用来做判断的可视化页面——不只是画几张图,而是回答"这份数据在说什么、读者应该关注什么"。
|
|
13
13
|
|
|
14
14
|
报表的价值不在图表数量,而在信息层级:读者能在 5 秒内抓到主要结论,30 秒内理解支撑证据,需要时能下钻到明细。
|
|
15
15
|
|
|
@@ -19,7 +19,9 @@ metadata:
|
|
|
19
19
|
|
|
20
20
|
布局必须比普通上下堆叠更丰富。先根据数据任务选择版式骨架,再写代码:监控型、复盘型、诊断型、对比型、明细型、汇报型可以有完全不同的扫描路径。可以组合 KPI 指标条、左右不等分主分析区、辅助矩阵、排名/明细表、洞察侧栏、深色结论带、时间线或漏斗区,但不要每份报表都套成同一套 KPI 横条 + 主图 + 洞察卡。不要把每个章节都做成同宽标题加一张满宽卡片;核心模块占更大面积,支撑模块用不同宽度、密度和位置服务它。
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
报表不是产品原型。内容型或分析型交付服务阅读和决策,不默认生成多页面后台导航、可下拉应用名、无意义返回按钮或设置菜单。标题、范围、口径、结论、图表、洞察和明细都是可用的信息部件,不是每份报表都必须同时出现的固定章节。
|
|
23
|
+
|
|
24
|
+
看板中的筛选器、标签页切换(如"今日/近7天/近30天"、"库存量/库存金额"、"30天/90天")、下拉选择等控件如果出现在页面上,必须用 JavaScript 实现真实的切换逻辑——点击后切换数据视图、过滤图表或改变显示内容。不实现功能的控件不得使用 `<button>`、`cursor:pointer` 或 active/hover 样式暗示可点击;纯标注用 `<span>` 或静态文字呈现。
|
|
23
25
|
|
|
24
26
|
不要让页面全是文字,也不要把所有章节都做成同一种"结论 + 指标 + 图表 + 洞察"结构。长材料先判断每段内容在当前报表里的作用:它是在给背景、定义口径、证明结论、展示变化、比较对象、解释异常、列明细,还是提出行动。每段只选择最适合的表达方式,可以是短结论、关键数字、对比、时间顺序、表格、矩阵、引用、图表、注释或截图。重要内容不能被塞进附录或角落;如果一个章节是汇报目标的核心,就给它相称的版面面积和区别于其他章节的版式处理。
|
|
25
27
|
|
|
@@ -50,6 +52,13 @@ metadata:
|
|
|
50
52
|
|
|
51
53
|
产出:维度-指标清单,以及一句话叙事重点。
|
|
52
54
|
|
|
55
|
+
**数据忠实度约束。** 在此步完成后,明确标注哪些指标可以直接从源数据计算、哪些缺少必要数据(如历史期、目标值、预算基线)。后续步骤中:
|
|
56
|
+
|
|
57
|
+
- 可直接计算的指标:使用真实值。
|
|
58
|
+
- 源数据不含的派生指标(同比/环比变化率、完成率、差额等需要两期或多源数据而只有单期的):不编造数值,用"—"占位或省略该指标。
|
|
59
|
+
- 超出数据时间范围的外推值:不补齐,图表只覆盖数据实际跨度。
|
|
60
|
+
- 确需补充示例数据时:必须在页面上用视觉标记(虚线边框、"示例数据"标签、灰色斜体)明确区分。
|
|
61
|
+
|
|
53
62
|
### 3. 报表规划
|
|
54
63
|
|
|
55
64
|
在写代码之前,先确定报表由哪些组件构成:
|
|
@@ -59,7 +68,7 @@ metadata:
|
|
|
59
68
|
- **候选部件**:标题 / 范围 / 口径、摘要、KPI、主图表、辅助图表、文字洞察、明细表、时间线、矩阵、截图或注释都只是候选。需要哪个用哪个,不要为了"完整"把它们凑齐。
|
|
60
69
|
- **核心承载**:只给真正承载核心问题的模块更大面积。核心可能是一张趋势图、一张排名表、一段异常解释、一个流程漏斗,也可能是一组明细,不固定。
|
|
61
70
|
- **版式差异**:为不同信息角色安排不同形态,例如紧凑指标条、宽图、窄侧栏、表格区、注释带、对比矩阵或分段背景。避免每个章节都重复同一张满宽白卡。
|
|
62
|
-
- **布局骨架**:明确每个模块的相对面积和扫描路径,例如 `1.2fr 2fr`、`1fr 1.6fr`、`repeat(4,1fr)`、`auto 1fr`
|
|
71
|
+
- **布局骨架**:明确每个模块的相对面积和扫描路径,例如 `1.2fr 2fr`、`1fr 1.6fr`、`repeat(4,1fr)`、`auto 1fr` 等混合栅格。多列网格必须提供窄屏回退(`auto-fit + minmax()` 或 `@media` 断点),不要写死 fr 比例而不处理移动端——详见下方「移动端适配」。
|
|
63
72
|
|
|
64
73
|
组件取舍由读者任务、数据复杂度和材料内容决定。
|
|
65
74
|
|
|
@@ -84,12 +93,53 @@ metadata:
|
|
|
84
93
|
- 表格用于精确查数和比较对象,不要把长表伪装成密集柱状图。
|
|
85
94
|
- KPI 用于概览,不要把每个字段都做成指标卡。
|
|
86
95
|
- 没有真实依据时不编造结论;可写"待补充口径"或使用中性描述。
|
|
96
|
+
- 页面中每个数值必须可溯源:源数据直读、或从源数据可验证计算得出。缺少计算所需数据时(如同比需要上期数据但只有本期),用"—"占位或省略,不编造。
|
|
97
|
+
- 所有视觉上暗示可交互的控件(标签页、筛选器、按钮、下拉、日期切换)必须绑定真实 JS 逻辑。不实现切换功能就不画成可点击样式。
|
|
87
98
|
|
|
88
99
|
产出:完整报表页面。
|
|
89
100
|
|
|
101
|
+
### 5.5 移动端适配
|
|
102
|
+
|
|
103
|
+
报表在桌面端的复杂网格不会自动适配移动端。写完桌面布局后,必须为 ≤768px 视口补充响应式处理:
|
|
104
|
+
|
|
105
|
+
**页面基础**:HTML 必须包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`,否则移动浏览器用 980px 默认视口渲染再缩小,所有字都变成蚊子大小。
|
|
106
|
+
|
|
107
|
+
**模块折叠策略**:
|
|
108
|
+
|
|
109
|
+
- **KPI 指标条**:桌面端横排 4 个时,移动端折叠为 2×2 网格。用 `repeat(auto-fit, minmax(160px, 1fr))` 自动处理,或 `@media (max-width: 768px)` 显式切到两列。
|
|
110
|
+
- **主分析区(左右不等分)**:`1.2fr 2fr` 或 `auto 1fr` 这类侧栏 + 主区布局,移动端必须折叠为单列——侧栏内容移到主区上方或下方。
|
|
111
|
+
- **并列图表**:两图并排在移动端改为上下堆叠,每个图表独占一行。图表容器的窄屏处理由 charts skill 的「窄屏适配」规则覆盖。
|
|
112
|
+
- **明细表格**:宽表在窄屏下加 `overflow-x: auto` 让表格可横向滚动,不要压缩列宽到不可读。
|
|
113
|
+
- **洞察侧栏 / 注释带**:移动端折叠到对应图表下方,不要浮动遮盖内容。
|
|
114
|
+
|
|
115
|
+
**断点写法**(二选一):
|
|
116
|
+
|
|
117
|
+
```css
|
|
118
|
+
/* 方式 A:auto-fit 自动折叠 */
|
|
119
|
+
.report-grid {
|
|
120
|
+
display: grid;
|
|
121
|
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
122
|
+
gap: 16px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* 方式 B:显式断点 */
|
|
126
|
+
.report-layout {
|
|
127
|
+
display: grid;
|
|
128
|
+
grid-template-columns: 1.2fr 2fr;
|
|
129
|
+
gap: 24px;
|
|
130
|
+
}
|
|
131
|
+
@media (max-width: 768px) {
|
|
132
|
+
.report-layout {
|
|
133
|
+
grid-template-columns: 1fr;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**字号底线**:移动端正文不低于 14px,KPI 数字不低于 20px,图表标题不低于 13px。
|
|
139
|
+
|
|
90
140
|
### 6. 自检
|
|
91
141
|
|
|
92
|
-
|
|
142
|
+
检查渲染结果,验证以下几点:
|
|
93
143
|
|
|
94
144
|
- 报表是否回答了步骤 1 确定的核心问题。
|
|
95
145
|
- 信息层级是否清晰(读者能在 5 秒内抓到主要结论)。
|
|
@@ -101,5 +151,11 @@ metadata:
|
|
|
101
151
|
- 文字洞察是否与图表数据互相支撑。
|
|
102
152
|
- 图表部分是否通过了 charts skill 的自检清单。
|
|
103
153
|
- 口径和单位是否全报表一致。
|
|
154
|
+
- 页面中展示的每个数值是否可溯源到用户提供的数据;同比/环比/完成率等派生指标是否有对应的基准数据支撑,没有的是否已用"—"占位而非编造。
|
|
155
|
+
- 所有视觉上可点击的控件(标签页、筛选器、按钮、下拉)是否都绑定了真实 JS 逻辑,点击后确实切换数据或视图;没有功能的元素是否已改为静态文字样式。
|
|
156
|
+
- HTML 是否包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`。
|
|
157
|
+
- 多列网格是否提供了窄屏回退(`auto-fit + minmax()` 或 `@media` 断点),在 390px 视口下是否折叠为单列且无横向滚动。
|
|
158
|
+
- 宽表格是否有 `overflow-x: auto` 容器包裹。
|
|
159
|
+
- 移动端字号是否达到底线(正文 ≥14px、KPI 数字 ≥20px、图表标题 ≥13px)。
|
|
104
160
|
|
|
105
161
|
产出:确认或修正。
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: interactive-prototype
|
|
3
|
-
description:
|
|
3
|
+
description: 创建具备真实交互的可运行应用原型。触发词:interactive prototype, 交互原型, 可交互原型, 动态原型, 原型演示, 交互演示, working app
|
|
4
4
|
metadata:
|
|
5
5
|
display-names:
|
|
6
6
|
zh-CN: 交互原型
|
|
7
7
|
en-US: Interactive Prototype
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
# 交互原型
|
|
11
|
+
|
|
12
|
+
创建一个完全可交互的原型,具备真实的状态管理和页面切换。用 React 的 useState/useEffect 实现动态行为。包含悬停状态、点击交互、表单验证、动画过渡和多步导航流程。用起来要像真正能运行的应用,而不是静态效果图。
|
|
13
|
+
|
|
14
|
+
## 响应式适配
|
|
15
|
+
|
|
16
|
+
先判断 brief 的目标场景,走不同策略:
|
|
17
|
+
|
|
18
|
+
**面向终端用户的产品**(官网、营销页、C 端应用、展示型页面)——必须适配移动端。用 `@media (max-width: 768px)` 做断点,375px 宽度下无水平滚动、无内容不可读、无元素互相遮挡:
|
|
19
|
+
|
|
20
|
+
- **侧边栏**:窄屏默认收起,汉堡按钮切换;展开时 `position: fixed` + 半透明遮罩覆盖内容,不挤压主区域。
|
|
21
|
+
- **顶部导航**:导航项超出视口宽度时折叠为汉堡菜单,不允许换行堆叠或水平溢出。
|
|
22
|
+
- **网格与卡片**:用 CSS Grid `auto-fit` / `minmax()` 或 Flexbox `flex-wrap`,窄屏自动堆叠为单列;卡片内数字和文字不因容器变窄而截断。
|
|
23
|
+
- **固定定位元素**:浮动按钮、悬浮面板等 `position: fixed/absolute` 元素用 `right: 16px` 等安全边距约束在视口内,不允许超出屏幕边缘。
|
|
24
|
+
|
|
25
|
+
**面向桌面的场景**(管理后台、内部工具、数据密集型仪表盘)——不需要重排为移动端布局,但必须设 `min-width`(通常 1024px–1200px),窄于此宽度时整体水平滚动,而不是让布局被挤压变形。
|
|
26
|
+
|
|
27
|
+
brief 未指明时默认按终端用户产品处理。
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slide-deck
|
|
3
|
+
description: 当用户要求制作演示文稿 / PPT / PPTX / pitch deck / slides / keynote / 路演材料时使用——即供演讲者现场演示、固定画幅 16:9 的自包含 HTML deck。
|
|
4
|
+
metadata:
|
|
5
|
+
display-names:
|
|
6
|
+
zh-CN: 幻灯片制作
|
|
7
|
+
en-US: Slide Deck
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Slide deck
|
|
11
|
+
|
|
12
|
+
把演示 deck 做成一个自包含的 HTML 单页。
|
|
13
|
+
|
|
14
|
+
进入这个角色:你是一名演示设计师(presentation designer)。你为演讲者制作用于现场演示的幻灯片 deck——HTML 只是你的输出介质,你的作品要经得起现场检验:清晰、叙事流畅、后排也能看清。你不是在做网站。
|
|
15
|
+
|
|
16
|
+
**先判断场合,再定设计语气。** 判定场合后,代入该场合最专业的制作者身份——为这类场合做过上百场 deck 的人会怎么取舍——用它校准每一页的语气与密度。场合决定三件事:信息密度(听众扫读还是研读)、标题语法(论点式还是主题式)、节奏权重(哪类版式原型承担叙事高点)。动手前在 scratchpad 用一两句写明场合、代入的身份与这三项决策,全 deck 一致执行;工艺规则(构图、字号、平行性)不随场合变。
|
|
17
|
+
|
|
18
|
+
每张幻灯片既是版式设计的练习,也是文案写作的练习。动手前先写大纲;好的大纲本身就是一次讲故事和叙事结构的练习。
|
|
19
|
+
|
|
20
|
+
## 动手前先问
|
|
21
|
+
|
|
22
|
+
- 如果用户没有说明想要的视觉风格,也没有提供 design system,就用提问工具(ask_user_question)**主动询问**。绝不要直接给出一个通用设计!
|
|
23
|
+
|
|
24
|
+
## 构建准备与技术契约
|
|
25
|
+
|
|
26
|
+
### deck-stage 组件
|
|
27
|
+
|
|
28
|
+
以 1920×1080(16:9)为基准构建。**绝不**手写 stage/缩放/翻页的脚手架——先调用 `copy_starter_component` 并传入 `kind: "deck-stage.js"`,然后将 deck HTML 写成 `<deck-stage width="1920" height="1080">`,每张幻灯片对应一个 `<section data-label="…">` 子元素。该组件负责:
|
|
29
|
+
|
|
30
|
+
- letterbox 缩放
|
|
31
|
+
- 键盘 + 触控翻页
|
|
32
|
+
- speaker-notes 的 postMessage 协议
|
|
33
|
+
- `data-screen-label` / `data-miaoda-validate` 标记
|
|
34
|
+
- print-to-PDF(每张幻灯片一页)
|
|
35
|
+
|
|
36
|
+
用 `<script src="deck-stage.js"></script>` 加载它——它是 vanilla JS,不是 JSX。(为了之后导出 PPTX:向 gen_pptx 传入 `resetTransformSelector: "deck-stage"`——该组件支持 `noscale` 属性来禁用 shadow-DOM 缩放,使截图拿到原始尺寸的几何信息。)
|
|
37
|
+
|
|
38
|
+
deck-stage 组件会对每个 slotted 子元素做绝对定位——**绝不**在幻灯片 `<section>` 元素上自行设置 position/inset/width/height。
|
|
39
|
+
|
|
40
|
+
### 把幻灯片内容写成静态 HTML,而不是 React
|
|
41
|
+
|
|
42
|
+
幻灯片内容应写成静态 HTML,而非 React 或脚本生成的 DOM。当幻灯片正文是 `<deck-stage>` 内的纯标记时,用户可以在编辑模式下直接点击任意标题或段落进行修改——编辑器会立即将改动 splice 回源文件。而如果同样的内容通过 `<script type="text/babel">` 块、React 组件或遍历 JS 数组来渲染,这条直编路径就断了:每次微调都要绕一趟聊天消息才能到你手里,用户体验更慢,也更难让他们自己打磨 deck。因此,凡是静态页面能表达的——文本、布局、背景、图片——都直接在 HTML 里写字面元素并用 CSS 设置样式。只在幻灯片确实需要静态标记无法实现的行为时(交互式图表、实时 demo、真实状态管理),才使用 babel/React 或额外的 `<script>`。同样的渲染结果,静态 HTML 版本**始终优先于**动态版本,因为静态版本可被直接编辑。Tweaks 面板(`tweaks-panel.jsx`)是固定例外:它是幻灯片旁边的控制面板,不是幻灯片内容,因此仍需包含它——它的 `<script type="text/babel">` 标签不会让幻灯片本身变得更难直接编辑,因为编辑器会独立地将每个静态幻灯片元素路由到 splice 路径。
|
|
43
|
+
|
|
44
|
+
### 两个细节保持静态幻灯片可直接编辑
|
|
45
|
+
|
|
46
|
+
两个细节确保静态幻灯片可被直接编辑:每段文字都放在自己的叶子元素中(把 "Revenue" 放在 `<h2>` 内单独的 `<span>` 里,而不是写成 `<h2>Revenue <span class="sub">Q3</span></h2>` 这样文本和子元素混在同一父节点的形式),重复结构要逐一写出而非生成——三条 `<li>` 直接写在标记里,而不是从数组渲染一个 `<li>` 三次。重复正是重点所在;它让用户能编辑第二条而不影响第一条。
|
|
47
|
+
|
|
48
|
+
## 幻灯片设计与构图
|
|
49
|
+
|
|
50
|
+
先定方向:动手前先调用 `frontend-design` skill 立视觉方向框架,再结合主题、受众、场景提炼视觉关键词,用它们决定配色、字体、图片类型和页面节奏;frontend-design 的通用设计规则与本 skill 的 deck / 构图规则冲突时,以本 skill 为准。保持清晰的层级与一致的视觉系统。
|
|
51
|
+
|
|
52
|
+
### 构图原则
|
|
53
|
+
|
|
54
|
+
- **留白 ≠ 空洞。** 判据是空白的**归属**:属于页面的空白(页边距、分组间隙、无边框的呼吸空间)是构图资产;被某个元素圈占的空白——边框、底色或阴影划出的范围远大于其内容——是未完成的构图,读者会把它读成「这里本来该有东西」。元素的边界应由内容撑出来,而不是由要填的空间决定;画布填不满时,把空间留在元素**之间**,或按「视觉平衡」的出路增密。
|
|
55
|
+
|
|
56
|
+
- **视觉锚点。** 每页要能回答:视线第一眼落在哪里,为什么是那里。锚点可以是一个大数字、一张图表、一句大字陈述,也可以是并列结构中被刻意加重的一项。所有元素等面积、等字号、等色彩权重的页面,是把第一落点交给了随机——那不是中性,是没做构图决策。
|
|
57
|
+
|
|
58
|
+
- **视觉平衡。** 视觉重量要在整幅画布上分布均衡,不要全压在画幅一角。**内容只占上半画布、下半大面积空置的页面直接违规。** 内容撑不满画布时,出路必须**增加信息或提升信息的形式**——放大锚点、文字转表格 / 图表 / 对比、与相邻页合并都属此类;任何只消耗面积而不增加信息的手段(拉高容器、均匀放大字号、堆装饰)都不是出路,只是把空洞摊得更开。
|
|
59
|
+
|
|
60
|
+
- **平行性。** 平行性很重要:章节标题页外观必须一致;页码、眉标等结构件在所有页面位置样式一致;以此类推。
|
|
61
|
+
|
|
62
|
+
- **版式节奏。** 与平行性互为对偶:平行性守住不变的东西,节奏经营变化的东西。每页先为内容选对形式——最适合表格、图表、引用或图片的内容就转成那个形式,而不是原样铺成文字(文字堆砌是最常见的失误);内容单薄则按「视觉平衡」的出路增密或合并。逐页的形式选择连起来就是 deck 的节奏:节奏跟随叙事结构——章节转折、重点页、过渡页各有形态——而不是机械交替;节奏也需要对比才成立——满版图、大数字、图表、引用、不同背景色、纯文字,原型库要够开阔,页页同一骨架无节奏可言,那不叫一致,叫单调。用版式和可视化把画布用满不是「填充性内容」;凭空编造数据和板块才是。
|
|
63
|
+
|
|
64
|
+
### 素材与工艺
|
|
65
|
+
|
|
66
|
+
- **字号与单位。** 使用大号字体(标题至少 48px)。当用户指定具体字号时,默认他们说的是**磅(points)**(PowerPoint/Keynote 的单位)而非像素——用 `px = pt × 1.333` 换算。所以"把标题设成 36pt" → 在 CSS 里设成约 48px。
|
|
67
|
+
|
|
68
|
+
- **中文字体。** 中文内容的字体对必须包含明确的 CJK 字体,且 `font-family` 全栈声明(拉丁字体在前、CJK 字体随后、通用族兜底):衬线气质配 Noto Serif SC / 思源宋体,无衬线配 Noto Sans SC / 思源黑体系(MiSans/HarmonyOS Sans 亦可)——只写拉丁字体会让中文掉进系统回退。中文不用 italic(CJK 无真斜体,伪斜发虚);强调用字重、颜色或引言竖线。标题拉开字重跨度(如正文 400、大标题 800-900)。
|
|
69
|
+
|
|
70
|
+
- **素材来源。** 除非用户要求,绝不使用 emoji。使用 design system / 品牌中的图标、用户提供的图片,或图片生成工具产出的图片。
|
|
71
|
+
|
|
72
|
+
- **图片呈现。** 务必先查看图片,再决定最佳展示方式。
|
|
73
|
+
- 满版图片可用 aspect-fill;
|
|
74
|
+
- 截图必须 aspect-fit,且极少在其上叠加内容;
|
|
75
|
+
- 透明或 aspect-fit 的图片应置于对比色背景之上。
|
|
76
|
+
|
|
77
|
+
在图片上叠加文字时,参照品牌惯常做法:根据你在其他地方看到的样式,酌情使用卡片、保护渐变或模糊效果。
|
|
78
|
+
|
|
79
|
+
- **不 iframe 外站。** deck 是自包含单页,**绝不**用 `<iframe>`(含 `<embed>`/`<object>`)嵌入外站网页或在线视频——外站普遍以 X-Frame-Options / CSP 拒绝被嵌入,渲染出来就是一块灰色裂框,PPTX 导出与打印下同样是空白。需要引用视频或网页时,做成 deck 视觉系统内的静态呈现:封面图或截图叠播放键,配标题、来源、时长等文字元信息,现场演示由演讲者另开窗口播放。
|
|
80
|
+
|
|
81
|
+
- **图表与数据可视化。** 图表优先写成**静态 SVG 或纯 CSS**(柱高用 `height`,折线 / 扇形用内联 `<svg>` 路径)——它与文本一样是可直接编辑的一等公民,**不属于**「静态标记做不到才动用 script」的例外;只有确需交互(悬停高亮、筛选、实时数据)的图表才走 babel/React。数字之间只要存在能被眼睛读出的关系(趋势、占比、对比、分布),就转成图表,而不是原样铺成文字。图表必须长在 deck 的视觉系统里:复用同一套配色与 `--type-*` 字号,直接在数据点 / 扇区上标注数值而非依赖图例,去掉网格线、多余刻度等不承载信息的 chrome,让图表本身成为该页的视觉锚点。
|
|
82
|
+
|
|
83
|
+
- **时间线布局。** 时间线的点与连接线必须共享同一个定位上下文,连接线必须穿过每个节点圆点的圆心。判据:把任意一个节点的内容区高度改成两倍,点和线仍然对齐——如果会错位,说明两者的垂直基准不统一。把点和线放在独立的绝对定位层里分别偏移是最常见的错位根因,不要这样做。
|
|
84
|
+
|
|
85
|
+
- **动效。** 动效服务于叙事——引导视线、分层揭示信息、平滑衔接页面——而不是炫技或填空。默认克制,始终以不干扰阅读为底线。deck 动效的形态是**翻到该页时播放一次的入场 / 分步揭示**,不做环境循环——无限循环的装饰动画会持续争夺注意力。实现用 CSS 动画(幻灯片保持可直编的静态 HTML),两条契约(细节见 deck-stage.js 头部 Authoring guidance):
|
|
86
|
+
- 动画门控在 `[data-deck-active]` 与 `prefers-reduced-motion: no-preference` 上——组件在激活页维护该属性,翻页即触发;需要 JS 编排时监听组件的 `slidechange` 事件。
|
|
87
|
+
- 基础样式写**可见的最终态**,隐藏态只进 `@keyframes` 的 `from`——缩略图栏、reduced-motion 等场景只渲染静态基础态、从不播动画,把 `opacity: 0` 写在基础规则上,会导致这些场景全成空白。
|
|
88
|
+
|
|
89
|
+
- **层次靠版式,不靠特效。** 页内层级由字号、字重、色块、边框、分隔线和留白建立;内容卡片和区块默认平面化——不加 box-shadow、发光、玻璃拟态(backdrop-filter + 半透明底),渐变默认只用于图上文字的保护渐变(见「图片呈现」)和数据可视化的连续色带。深色底 + 紫蓝渐变 + 发光卡片的「科技感」组合是模型默认值而非设计选择(frontend-design 校准清单第 4 种长相),除非品牌 / brief 明确要求,不要用它。
|
|
90
|
+
|
|
91
|
+
- **结构件。** 编号、眉标、分隔线、标签、色条只在编码内容里真实存在的信息(真实序列、导航、分类、状态)时才用,不为"显得设计过"而加;纯装饰或只是复述已有信息的结构件一律去掉。
|
|
92
|
+
|
|
93
|
+
- **彩色边条。** 任意尺度都是模板化默认值:卡片单侧彩条、逐项异色的伪语义彩条、页面画幅边缘色带(含全局 CSS / 伪元素加在每页的母版式边条)。判据一条:删掉后读者不损失任何信息的即装饰,一律去掉,平行性不为装饰续命。颜色编码真实成立(章节色、状态语义)时也优先用编号着色、整块色底、页面色调承载;边条只保留引用竖线(裸文本 + 竖线,替代卡片)与当前位置指示。
|
|
94
|
+
|
|
95
|
+
## 幻灯片写作指南
|
|
96
|
+
|
|
97
|
+
### 仅凭标题就应能讲清整个故事
|
|
98
|
+
|
|
99
|
+
通常来说,仅靠幻灯片标题就应能让人了解 deck 的整体故事和内容(类似书籍的目录)。
|
|
100
|
+
|
|
101
|
+
幻灯片标题一般有以下几种结构类型:
|
|
102
|
+
|
|
103
|
+
- 简短的教科书式标题(如 市场调研、用户增长概览、团队架构;英文标题习惯全部大写)
|
|
104
|
+
- 行动式标题,更接近短句(如"亚洲是我们最大的市场……"、"……但东欧的增长潜力最高")
|
|
105
|
+
|
|
106
|
+
选定合适的标题结构后,始终保持一致。
|
|
107
|
+
|
|
108
|
+
### 避免暴露 AI 生成痕迹的 "AI 味"
|
|
109
|
+
|
|
110
|
+
避免以下常见的 "AI 味"——它们会暴露这个 deck 是 AI 生成的:
|
|
111
|
+
|
|
112
|
+
- "宣判式"的标题和要点总结,过度戏剧化/简化,无缘由地制造张力(经典的"不是 X,而是 Y"),使用强祈使句,过度重新包装概念,或刻意悬念、故作洞察。
|
|
113
|
+
- 类似"奇迹时刻"这样的标题
|
|
114
|
+
- 总之,AI 倾向于把标题写成演讲者的金句,而非引导听众进入该页内容的**标题**——必须避免!
|
|
115
|
+
|
|
116
|
+
## 规划步骤
|
|
117
|
+
|
|
118
|
+
在常规规划之外,务必完成以下步骤:
|
|
119
|
+
|
|
120
|
+
1. 如果不清楚受众、期望的品牌风格,先提问。
|
|
121
|
+
2. 写出完整的标题序列。选择**一种**语法风格(例如短主题名词短语或简短陈述句),确保适合内容,并用该风格写出每一个标题。回头通读一遍,判断一个人**仅凭标题**能否跟上整个演示的脉络。标题应像书的章节——用直白的语言告诉读者接下来是什么。审阅这些标题并按需修订。将它们写入 scratchpad.md 文件。
|
|
122
|
+
3. 在 scratchpad.md 里为每张幻灯片标注**版式原型**(满版图 / 大数字 / 图表 / 表格 / 引用 / 多栏卡片 / 时间线 / 纯文字……)与**视觉锚点**(这页视线的第一落点)。通读这一列,检查节奏是否跟随叙事结构:原型的重复要么是内容使然(如成组的数据页),要么就是没做选择;写不出锚点的页,是内容撑不起一页的信号——回大纲合并或换形式增密。
|
|
123
|
+
4. 在写任何幻灯片**之前**,先在 `<head>` 的一个 `<style>` 块中将字号、行高和间距定义为 CSS custom properties——这会锁定适合投影的尺寸,防止不自觉退回网页密度。画幅恒为 1920×1080(deck-stage 的基准,输出尺寸由组件 letterbox 缩放解决),合理的起始体系为:`:root { --type-display: 120px; --type-title: 64px; --type-subtitle: 44px; --type-body: 34px; --type-small: 28px; --leading-title: 1.15; --leading-body: 1.4; --measure-body: 40em; --pad-top: 100px; --pad-bottom: 80px; --pad-x: 100px; --gap-title: 52px; --gap-item: 28px; }`。所有地方都引用这些变量——每个 font-size 都用 `--type-*`,每个 line-height 都用 `--leading-*`,每个 padding/gap 都用 `--pad-*` 或 `--gap-*`,通过 inline style 或 class 规则中的 `var(…)` 引用。取档跟着版式原型走:大数字 / 引用页的主角上 `--type-display`,表格单元格用 `--type-small`;连续文本块限宽 `max-width: var(--measure-body)`——行长超限会让达标的字号读起来又小又密,多出来的画幅宽度用双栏、图文并排消化,而不是让一行文字全宽跑。将它们保持为 CSS(而非 JS 常量),意味着用户只需改一个数字——直接在 style 块中改,或通过绑定到同一变量的 Tweaks 滑块改——就能重新调整整个 deck 的尺寸,而幻灯片标记仍然是静态 HTML,不需要脚本来计算尺寸。显式的 `--pad-bottom` 为每张幻灯片底部预留呼吸空间;那个留白是结构性的,不是空的。网页默认值(body 14-16px、padding 48-72px)对幻灯片太小;如果数值让你觉得不够大方,那就是还不够。任何文字不得小于 24px——这是下限不是目标。
|
|
124
|
+
5. **把这套 token 当成每页的内容预算**:在上述数值下,一页正文区大约容纳 14 行正文、或 6 个两行 bullet——在 scratchpad 排内容时就按预算裁剪,而不是写完再看塞不塞得下。装不下的处置顺序是**拆页 > 删内容 > 换更省空间的版式**;缩小字号是最后手段,且绝不越过 24px 下限——靠缩字塞进去的页,只是把溢出换成了后排看不清。反过来,内容远少于预算的页按「视觉平衡」的出路增密或合并,而不是放大字号去撑面积。
|
|
125
|
+
6. 构建幻灯片,牢记每张幻灯片既是设计练习也是文案练习。在版式、文字内容和语调方面给予每张幻灯片应有的关注。遵循上述原则,确保每张幻灯片能独立成立;一个只看这一页的人,应当无需其他上下文就能理解其高层含义。
|
|
126
|
+
|
|
127
|
+
## 验证要点
|
|
128
|
+
|
|
129
|
+
审阅时,用幻灯片构图规则——而非网页布局直觉——来检查版面。底部留白是不是缺陷,用「留白 ≠ 空洞」的归属判据:内容自身完整、下方是无边框的整块呼吸空间,这是正确的幻灯片构图——不要出于网页直觉把 `flex-start` 改成 `center`;空白被元素边界圈占的,是被动空洞,按「视觉平衡」的出路修。
|
|
130
|
+
|
|
131
|
+
逐页核对以下各项:
|
|
132
|
+
|
|
133
|
+
- 字号匹配你的 `--type-*` 体系(而非网页密度),没有为塞内容缩到 24px 以下
|
|
134
|
+
- 连续文本块行长不超过 `--measure-body`,没有一行文字横穿整个画幅
|
|
135
|
+
- 幻灯片边距匹配你的 `--pad-*` 值(而非网页紧凑间距)
|
|
136
|
+
- 封面有统治画面的主视觉,标题位置有构图意图,不是「小图标 + 居中标题 + 居中副标题」三件套
|
|
137
|
+
- 结构件(页码、眉标)全 deck 位置样式一致;章节页彼此外观一致
|
|
138
|
+
- 没有任何尺度的装饰性彩色边条(判据见「彩色边条」);没有 takeaway box
|
|
139
|
+
- 内容区平面化:没有装饰性渐变背景、发光、玻璃拟态;渐变只出现在图上文字保护或数据色带上
|
|
140
|
+
- 没有内容被画幅边缘裁切、显示不全
|
|
141
|
+
- 没有元素相互压叠、遮挡到读不清
|
|
142
|
+
- 没有被动空洞:边框 / 底色圈出的范围与其内容相称
|
|
143
|
+
- 页面视觉重量在画布上分布均衡,没有大片区域读成「缺了东西」
|
|
144
|
+
- 每页能指出视觉锚点;版式原型的重复经得起「内容使然还是没做选择」的追问
|
|
145
|
+
- 带动效的元素在缩略图栏和打印视图下完整可见(基础样式即最终态,隐藏态只在 keyframes 的 `from` 里)
|
|
@@ -45,6 +45,23 @@ metadata:
|
|
|
45
45
|
|
|
46
46
|
不要为了“丰富”而乱放装饰。变化应该来自内容关系和阅读任务,而不是从组件清单里凑满页面。
|
|
47
47
|
|
|
48
|
+
## 移动端适配
|
|
49
|
+
|
|
50
|
+
可视化报告的产物(长页报告、专题页、信息图)经常在手机上被打开和转发。桌面端的多列版式、满版图文和精细间距到了 390px 宽度上会挤碎。写完桌面布局后,必须为窄屏补充响应式处理:
|
|
51
|
+
|
|
52
|
+
**页面基础**:HTML 必须包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`。
|
|
53
|
+
|
|
54
|
+
**版式折叠**:
|
|
55
|
+
|
|
56
|
+
- **多列章节**(并排图文、对比矩阵、左右证据栏):移动端折叠为单列堆叠。用 `auto-fit + minmax(320px, 1fr)` 自动折叠,或 `@media (max-width: 768px)` 显式切换。
|
|
57
|
+
- **满版主视觉 / 封面**:桌面端的固定高度大图在移动端改为 `aspect-ratio` 或 `min-height` + `max-height` 约束,避免图片撑满整屏看不到内容。
|
|
58
|
+
- **数字/指标区**:横排的 KPI 或关键数字在移动端折叠为 2 列或纵向排列,每个数字块至少 160px 宽。
|
|
59
|
+
- **图表**:图表容器的窄屏处理由 charts skill 的「窄屏适配」规则覆盖。
|
|
60
|
+
- **宽表格 / 时间线 / 矩阵**:加 `overflow-x: auto` 容器让内容可横向滚动,不要压缩到不可读。
|
|
61
|
+
- **大字标题**:桌面端 48px+ 的展示字体在移动端用 `clamp()` 或 `@media` 缩到合理范围(如 `clamp(24px, 6vw, 48px)`),避免单词撑出视口。
|
|
62
|
+
|
|
63
|
+
**字号底线**:移动端正文不低于 14px,标注 / 图注不低于 12px。
|
|
64
|
+
|
|
48
65
|
## 视觉原则
|
|
49
66
|
|
|
50
67
|
- 优先清楚,其次好看。读者应该先理解结构,再感受到风格。
|
|
@@ -54,6 +71,7 @@ metadata:
|
|
|
54
71
|
- 风格跟随内容、受众和品牌:可以正式、温和、技术、编辑化、品牌化或实验感,但不要从某个样例场景继承固定颜色、固定目录或固定组件。
|
|
55
72
|
- 每份报告应有一个可解释的签名元素。签名元素要从用户主题、材料质感和阅读任务中生成,而不是复用固定手法;它可以是任何能组织内容、建立记忆点并保持一致性的视觉规则。
|
|
56
73
|
- 真实素材优先:用户给的截图、logo、图片、图标、数据片段要优先使用。没有素材时,用清楚的占位结构和可替换文案。
|
|
74
|
+
- 数据忠实度:页面中展示的每个数值必须可溯源到用户提供的数据或可验证的计算过程。源数据不含的派生指标(同比/环比、完成率等缺少基准数据的)不编造——用"—"占位或省略。确需补充示例数据时,必须用视觉标记(虚线边框、"示例数据"标签、灰色斜体)明确区分。
|
|
57
75
|
- 允许少量动效,但只用于进入、强调或引导阅读,不做干扰理解的持续动画。
|
|
58
76
|
- 可以包含数字、图表和表格,但它们服务于报告叙事;不要为了“可视化”而把所有内容都做成图。
|
|
59
77
|
- 深色区域可以用于封面、结论、行动区或整篇报告的主视觉;只要它服务主题气质和阅读体验,而不是作为无依据的装饰。
|
|
@@ -77,4 +95,8 @@ metadata:
|
|
|
77
95
|
- 文字密度可读,没有小字堆叠。
|
|
78
96
|
- 图标、线条、颜色和卡片样式属于同一套视觉语言。
|
|
79
97
|
- 明暗选择能解释为什么适合这个主题;无论浅色还是暗色,都保证长文、图表和表格可读。
|
|
80
|
-
- 事实性内容没有编造;不确定内容用中性描述或占位说明。
|
|
98
|
+
- 事实性内容没有编造;不确定内容用中性描述或占位说明。
|
|
99
|
+
- 页面中每个数值可溯源到用户提供的数据;缺少基准数据的派生指标(同比/环比/完成率等)没有编造数值,而是用"—"占位或省略。
|
|
100
|
+
- HTML 包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`。
|
|
101
|
+
- 多列版式在 390px 视口下折叠为单列且无横向滚动;宽表格 / 矩阵有 `overflow-x: auto` 包裹。
|
|
102
|
+
- 移动端字号达到底线(正文 ≥14px、图注 ≥12px),大标题没有撑出视口。
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trigger-guide
|
|
3
|
+
description: 自动化任务触发器代码开发指南,支持 cron 定时触发器、record_change 数据变更触发器和 webhook 触发器,包含 @Automation/@BindTrigger 装饰器用法、handler 入参解析和 Crontab 表达式规范。Use when 需要:(1) 为已创建的自动化任务/定时任务编写业务 handler,(2) 编写 automation 代码绑定触发器,或其他自动化任务相关开发
|
|
4
|
+
steering: true
|
|
5
|
+
steering-topic: trigger_guide
|
|
6
|
+
match-template-name: nestjs-react-fullstack
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 自动化任务配置与代码编写指引
|
|
10
|
+
|
|
11
|
+
### 自动化任务配置
|
|
12
|
+
|
|
13
|
+
1. 新建自动化任务触发器时无需 enable(激活),将任务创建好然后开发完代码即可。触发器随后交由用户主动操作、要求开始。
|
|
14
|
+
|
|
15
|
+
### 目录结构
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
server
|
|
19
|
+
└── modules
|
|
20
|
+
└── xxx
|
|
21
|
+
├── xxx.automation.ts
|
|
22
|
+
├── xxx.module.ts // 必须在 module 中注册自动化任务类,并且在 app.module.ts 中引用并注册该 module,否则代码将不会生效。
|
|
23
|
+
└── 其他文件(如有的话)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
文件命名规则:{模块名}.automation.ts
|
|
27
|
+
|
|
28
|
+
注意:
|
|
29
|
+
|
|
30
|
+
1. 每个模块只应该有一个存放自动化任务逻辑的文件,业务逻辑需要聚合到该文件中。
|
|
31
|
+
2. 如果该模块只有对应的自动化任务,无需编写 Controller
|
|
32
|
+
|
|
33
|
+
### 触发器类型
|
|
34
|
+
|
|
35
|
+
触发器类型(`triggerType`)有三种:
|
|
36
|
+
|
|
37
|
+
- `record_change`:记录变更触发器,**有入参**
|
|
38
|
+
- `cron`:定时触发器,**无入参**
|
|
39
|
+
- `webhook`:Webhook 触发器,**有入参**
|
|
40
|
+
|
|
41
|
+
各触发器 handler 的入参类型定义(`TaskHandlerArgs`、`DataChangeEventInput`、`WebhookEvent`)见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
42
|
+
|
|
43
|
+
### 指定值限制
|
|
44
|
+
|
|
45
|
+
1. Webhook 触发器不可以设置指定值,并且告知用户。
|
|
46
|
+
|
|
47
|
+
### 代码绑定
|
|
48
|
+
|
|
49
|
+
你需要根据触发器创建后确定的自动化任务名字(应用内唯一),编写并绑定到对应的方法上:`@BindTrigger('<任务名字>')` 中的名字必须与创建触发器时确定的名字逐字相同,不能用 trigger ID 或方法名代替。`@Automation()` 标记的类需注册为对应 `<module>.module.ts` 的 provider,且该 module 必须被 `server/app.module.ts` 直接或传递 import,否则装饰器不会生效。完整代码示例见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
50
|
+
|
|
51
|
+
### 任务代码实现约束
|
|
52
|
+
|
|
53
|
+
1. 执行自动化任务时无法获取用户信息。依赖用户信息的场景,实现路径如下:
|
|
54
|
+
- 需要查询数据库中的特定数据,给用户发消息:数据库中需要存储用户 id,使用从数据库中查询到的用户 id 进行后续操作
|
|
55
|
+
- 需要调用飞书能力给用户发消息:飞书能力不应该接受用户信息作为参数,而是应该在飞书能力配置里要求用户自己预先指定
|
|
56
|
+
|
|
57
|
+
2. 入参解析规范(仅 record_change 和 webhook 触发器):
|
|
58
|
+
- 有入参的触发器方法签名为 `async methodName(event: TaskHandlerArgs)`,`cron` 触发器无入参
|
|
59
|
+
- `content.input` 是 JSON 字符串,先用 `typeof input === 'string'` 检查类型,再用 `JSON.parse()` 解析,需添加 try-catch 错误处理
|
|
60
|
+
- `record_change`:根据操作类型获取数据:INSERT/UPDATE 使用 `after` 字段,DELETE 使用 `before` 字段
|
|
61
|
+
- `webhook`:从 `method`、`path`、`query`、`headers`、`body` 中按需取用;`body` 本身也是 JSON 字符串,需要时再次 `JSON.parse()` 解析;`query` 和 `headers` 的值均为 `string[]`
|
|
62
|
+
|
|
63
|
+
### 技术实现路径参考
|
|
64
|
+
|
|
65
|
+
以下常见需求的推荐实现路径,帮助你在平台能力限制下找到合理的技术方案;完整代码见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
66
|
+
|
|
67
|
+
- **场景一:管理页面控制定时任务启停** —— 平台侧不支持通过 API 动态启停触发器;定时触发器始终保持开启,在任务执行时查询数据库中的开关状态决定是否执行。
|
|
68
|
+
- **场景二:定时任务通知特定用户** —— 任务执行时无法获取用户上下文;在数据库预存目标用户 ID,执行时查询再调用飞书插件发送。
|
|
69
|
+
- **场景三:记录变更触发器防抖/去重** —— 利用数据库记录最近一次处理时间戳,对比 event 时间戳进行去重。
|
|
70
|
+
- **场景四:自定义定时任务触发时间** —— cron 创建后不可动态改;平台设固定高频定时器(如每 30 分钟),执行时读数据库配置判断是否命中。
|
|
71
|
+
|
|
72
|
+
## Crontab 表达式规范
|
|
73
|
+
|
|
74
|
+
### 基本结构
|
|
75
|
+
|
|
76
|
+
Crontab 表达式由 5 个字段组成:`<minute> <hour> <day> <month> <week>`
|
|
77
|
+
|
|
78
|
+
### 字段说明
|
|
79
|
+
|
|
80
|
+
1. **minute(分钟)**:0-59 的整数
|
|
81
|
+
2. **hour(小时)**:0-23 的整数
|
|
82
|
+
3. **day(日期)**:1-31 的整数,或大写字母 `L` 表示月份的最后一天
|
|
83
|
+
4. **month(月份)**:1-12 的整数
|
|
84
|
+
5. **week(星期)**:0-6 的整数,其中 0 表示星期天
|
|
85
|
+
|
|
86
|
+
### 特殊字符
|
|
87
|
+
|
|
88
|
+
- **星号 `*`**:表示所有可能的值(每)
|
|
89
|
+
- 例:`* * * * *` 表示每分钟
|
|
90
|
+
- **逗号 `,`**:表示列表范围
|
|
91
|
+
- 例:`1,2,3 * * * *` 表示每小时的第 1、2、3 分钟
|
|
92
|
+
- **中杠 `-`**:表示数值范围
|
|
93
|
+
- 例:`1-10 * * * *` 表示每小时的第 1 到 10 分钟
|
|
94
|
+
- **正斜线 `/`**:表示间隔频率
|
|
95
|
+
- 例:`0 10-18/2 * * *` 表示每天 10 点到 18 点,每隔 2 小时执行
|
|
96
|
+
|
|
97
|
+
## 输出要求
|
|
98
|
+
|
|
99
|
+
1. 必须以 JSON 格式输出
|
|
100
|
+
2. JSON 包含两个字段:
|
|
101
|
+
- `expression`:Crontab 表达式字符串
|
|
102
|
+
- `explanation`:中文说明,简要描述执行时间
|
|
103
|
+
3. 如果用户描述不清晰,请询问具体细节
|
|
104
|
+
|
|
105
|
+
## 示例
|
|
106
|
+
|
|
107
|
+
**用户输入**:每天早上 8 点执行
|
|
108
|
+
|
|
109
|
+
**输出**:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"expression": "0 8 * * *",
|
|
114
|
+
"explanation": "每天早上 8:00 执行"
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**用户输入**:每周一到周五的上午 9 点和下午 6 点执行
|
|
119
|
+
|
|
120
|
+
**输出**:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"expression": "0 9,18 * * 1-5",
|
|
125
|
+
"explanation": "每周一至周五的 9:00 和 18:00 执行"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**用户输入**:每隔 30 分钟执行一次
|
|
130
|
+
|
|
131
|
+
**输出**:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"expression": "*/30 * * * *",
|
|
136
|
+
"explanation": "每隔 30 分钟执行一次"
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**用户输入**:每月最后一天的晚上 11 点执行
|
|
141
|
+
|
|
142
|
+
**输出**:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"expression": "0 23 L * *",
|
|
147
|
+
"explanation": "每月最后一天的 23:00 执行"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**用户输入**:每个工作日的每小时第 15 和 45 分钟执行
|
|
152
|
+
|
|
153
|
+
**输出**:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"expression": "15,45 * * * 1-5",
|
|
158
|
+
"explanation": "每周一至周五,每小时的第 15 和 45 分钟执行"
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**用户输入**:每天上午 10 点到下午 6 点,每隔 2 小时执行
|
|
163
|
+
|
|
164
|
+
**输出**:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"expression": "0 10-18/2 * * *",
|
|
169
|
+
"explanation": "每天 10:00、12:00、14:00、16:00、18:00 执行"
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 注意事项
|
|
174
|
+
|
|
175
|
+
- 星期字段:0 和 7 都可以表示星期天(但本规范使用 0)
|
|
176
|
+
- 时间采用 24 小时制
|
|
177
|
+
- 月份和星期都从较小的数字开始计数
|
|
178
|
+
- 确保生成的表达式符合实际日历逻辑
|
|
179
|
+
- 由于技术限制,最小间隔为 30 分钟,如用户要求有误请直接拒绝用户并给出原因
|
|
180
|
+
- 输出必须是有效的 JSON 格式
|
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
name: trigger-guide
|
|
3
|
-
description: 自动化任务触发器配置与代码开发指南,支持 cron 定时触发器、record_change 数据变更触发器和 webhook 触发器,包含 @Automation/@BindTrigger 装饰器用法和 Crontab 表达式规范。Use when 需要:(1) 创建或配置自动化任务/定时任务,(2) 编写 automation 代码绑定触发器,或其他自动化任务相关开发
|
|
4
|
-
steering: true
|
|
5
|
-
steering-topic: trigger_guide
|
|
6
|
-
match-template-name: nestjs-react-fullstack
|
|
7
|
-
---
|
|
1
|
+
# 触发器入参类型与代码示例
|
|
8
2
|
|
|
9
|
-
|
|
3
|
+
本 reference 承载 nestjs-react-fullstack 触发器 handler 的入参类型定义、完整代码示例与常见实现场景。先读主 [trigger-guide](../SKILL.md) 了解目录结构、绑定约束与配置要求。
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
1. 新建自动化任务触发器时无需 enable(激活),将任务创建好然后开发完代码即可。触发器随后交由用户主动操作、要求开始。
|
|
14
|
-
|
|
15
|
-
### 目录结构
|
|
16
|
-
|
|
17
|
-
```text
|
|
18
|
-
server
|
|
19
|
-
└── modules
|
|
20
|
-
└── xxx
|
|
21
|
-
├── xxx.automation.ts
|
|
22
|
-
├── xxx.module.ts // 必须在 module 中注册自动化任务类,并且在 app.module.ts 中引用并注册该 module,否则代码将不会生效。
|
|
23
|
-
└── 其他文件(如有的话)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
文件命名规则:{模块名}.automation.ts
|
|
27
|
-
|
|
28
|
-
注意:
|
|
29
|
-
|
|
30
|
-
1. 每个模块只应该有一个存放自动化任务逻辑的文件,业务逻辑需要聚合到该文件中。
|
|
31
|
-
2. 如果该模块只有对应的自动化任务,无需编写 Controller
|
|
32
|
-
|
|
33
|
-
### 触发器类型与入参
|
|
5
|
+
## 触发器类型与入参
|
|
34
6
|
|
|
35
7
|
触发器类型(`triggerType`)有三种:
|
|
36
8
|
|
|
@@ -85,12 +57,11 @@ interface WebhookEvent {
|
|
|
85
57
|
}
|
|
86
58
|
```
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
1. Webhook 触发器不可以设置指定值,并且告知用户。
|
|
60
|
+
`DataChangeEventInput.type` 只定义 `INSERT`、`UPDATE`、`DELETE`,不包含 `UPSERT`。
|
|
90
61
|
|
|
91
|
-
|
|
62
|
+
## 代码示例
|
|
92
63
|
|
|
93
|
-
|
|
64
|
+
根据触发器创建后确定的任务名字(应用内唯一),编写并绑定到对应的方法上。使用模板已有的 `@lark-apaas/fullstack-nestjs-core` 聚合入口导入 `Automation` / `BindTrigger`,不要求项目再感知底层 trigger 包。具体代码示例如下:
|
|
94
65
|
|
|
95
66
|
```typescript
|
|
96
67
|
// 文件名:demo.automation.ts
|
|
@@ -184,23 +155,11 @@ export class DemoAutomationTasksService {
|
|
|
184
155
|
}
|
|
185
156
|
```
|
|
186
157
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
1. 执行自动化任务时无法获取用户信息。依赖用户信息的场景,实现路径如下:
|
|
190
|
-
- 需要查询数据库中的特定数据,给用户发消息:数据库中需要存储用户 id,使用从数据库中查询到的用户 id 进行后续操作
|
|
191
|
-
- 需要调用飞书能力给用户发消息:飞书能力不应该接受用户信息作为参数,而是应该在飞书能力配置里要求用户自己预先指定
|
|
192
|
-
|
|
193
|
-
2. 入参解析规范(仅 record_change 和 webhook 触发器):
|
|
194
|
-
- 有入参的触发器方法签名为 `async methodName(event: TaskHandlerArgs)`,`cron` 触发器无入参
|
|
195
|
-
- `content.input` 是 JSON 字符串,先用 `typeof input === 'string'` 检查类型,再用 `JSON.parse()` 解析,需添加 try-catch 错误处理
|
|
196
|
-
- `record_change`:根据操作类型获取数据:INSERT/UPDATE 使用 `after` 字段,DELETE 使用 `before` 字段
|
|
197
|
-
- `webhook`:从 `method`、`path`、`query`、`headers`、`body` 中按需取用;`body` 本身也是 JSON 字符串,需要时再次 `JSON.parse()` 解析;`query` 和 `headers` 的值均为 `string[]`
|
|
198
|
-
|
|
199
|
-
### 技术实现路径参考
|
|
158
|
+
## 技术实现路径参考
|
|
200
159
|
|
|
201
160
|
以下是一些常见需求的推荐实现路径,帮助你在平台能力限制下找到合理的技术方案。
|
|
202
161
|
|
|
203
|
-
|
|
162
|
+
### 场景一:用户需要管理页面控制定时任务的启停
|
|
204
163
|
|
|
205
164
|
平台侧不支持通过 API 动态启停触发器。推荐方案:**平台定时触发器始终保持开启,在任务执行时查询数据库中的开关状态,决定是否真正执行业务逻辑。**
|
|
206
165
|
|
|
@@ -233,7 +192,7 @@ export class ReportAutomationService {
|
|
|
233
192
|
}
|
|
234
193
|
```
|
|
235
194
|
|
|
236
|
-
|
|
195
|
+
### 场景二:定时任务需要将结果通知给特定用户
|
|
237
196
|
|
|
238
197
|
自动化任务执行时无法获取当前用户上下文。推荐方案:**在数据库中预存需要通知的用户 ID,任务执行时从数据库查询目标用户,再调用飞书插件发送通知。**
|
|
239
198
|
|
|
@@ -267,7 +226,7 @@ export class NotifyAutomationService {
|
|
|
267
226
|
}
|
|
268
227
|
```
|
|
269
228
|
|
|
270
|
-
|
|
229
|
+
### 场景三:记录变更触发器需要做防抖/去重
|
|
271
230
|
|
|
272
231
|
高频数据变更场景下,同一条记录可能短时间内触发多次。推荐方案:**利用数据库记录最近一次处理时间戳,对比 event 时间戳进行去重。**
|
|
273
232
|
|
|
@@ -294,7 +253,7 @@ async handleOrderChange(event: TaskHandlerArgs) {
|
|
|
294
253
|
}
|
|
295
254
|
```
|
|
296
255
|
|
|
297
|
-
|
|
256
|
+
### 场景四:用户需要自定义定时任务的触发时间
|
|
298
257
|
|
|
299
258
|
平台侧的 cron 表达式在触发器创建后无法由用户动态修改。推荐方案:**平台设置一个固定的高频定时器(如每 30 分钟执行一次),在任务执行时从数据库读取用户配置的触发时间,判断当前是否命中再决定是否执行。**
|
|
300
259
|
|
|
@@ -340,113 +299,3 @@ export class ScheduleAutomationService {
|
|
|
340
299
|
```
|
|
341
300
|
|
|
342
301
|
> 注意:由于平台最小调度间隔为 30 分钟,用户可配置的时间精度也应限制为 30 分钟的整数倍(如 `09:00`、`09:30`),前端做好校验提示。
|
|
343
|
-
|
|
344
|
-
## Crontab 表达式规范
|
|
345
|
-
|
|
346
|
-
### 基本结构
|
|
347
|
-
|
|
348
|
-
Crontab 表达式由 5 个字段组成:`<minute> <hour> <day> <month> <week>`
|
|
349
|
-
|
|
350
|
-
### 字段说明
|
|
351
|
-
|
|
352
|
-
1. **minute(分钟)**:0-59 的整数
|
|
353
|
-
2. **hour(小时)**:0-23 的整数
|
|
354
|
-
3. **day(日期)**:1-31 的整数,或大写字母 `L` 表示月份的最后一天
|
|
355
|
-
4. **month(月份)**:1-12 的整数
|
|
356
|
-
5. **week(星期)**:0-6 的整数,其中 0 表示星期天
|
|
357
|
-
|
|
358
|
-
### 特殊字符
|
|
359
|
-
|
|
360
|
-
- **星号 `*`**:表示所有可能的值(每)
|
|
361
|
-
- 例:`* * * * *` 表示每分钟
|
|
362
|
-
- **逗号 `,`**:表示列表范围
|
|
363
|
-
- 例:`1,2,3 * * * *` 表示每小时的第 1、2、3 分钟
|
|
364
|
-
- **中杠 `-`**:表示数值范围
|
|
365
|
-
- 例:`1-10 * * * *` 表示每小时的第 1 到 10 分钟
|
|
366
|
-
- **正斜线 `/`**:表示间隔频率
|
|
367
|
-
- 例:`0 10-18/2 * * *` 表示每天 10 点到 18 点,每隔 2 小时执行
|
|
368
|
-
|
|
369
|
-
## 输出要求
|
|
370
|
-
|
|
371
|
-
1. 必须以 JSON 格式输出
|
|
372
|
-
2. JSON 包含两个字段:
|
|
373
|
-
- `expression`:Crontab 表达式字符串
|
|
374
|
-
- `explanation`:中文说明,简要描述执行时间
|
|
375
|
-
3. 如果用户描述不清晰,请询问具体细节
|
|
376
|
-
|
|
377
|
-
## 示例
|
|
378
|
-
|
|
379
|
-
**用户输入**:每天早上 8 点执行
|
|
380
|
-
|
|
381
|
-
**输出**:
|
|
382
|
-
|
|
383
|
-
```json
|
|
384
|
-
{
|
|
385
|
-
"expression": "0 8 * * *",
|
|
386
|
-
"explanation": "每天早上 8:00 执行"
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**用户输入**:每周一到周五的上午 9 点和下午 6 点执行
|
|
391
|
-
|
|
392
|
-
**输出**:
|
|
393
|
-
|
|
394
|
-
```json
|
|
395
|
-
{
|
|
396
|
-
"expression": "0 9,18 * * 1-5",
|
|
397
|
-
"explanation": "每周一至周五的 9:00 和 18:00 执行"
|
|
398
|
-
}
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
**用户输入**:每隔 30 分钟执行一次
|
|
402
|
-
|
|
403
|
-
**输出**:
|
|
404
|
-
|
|
405
|
-
```json
|
|
406
|
-
{
|
|
407
|
-
"expression": "*/30 * * * *",
|
|
408
|
-
"explanation": "每隔 30 分钟执行一次"
|
|
409
|
-
}
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
**用户输入**:每月最后一天的晚上 11 点执行
|
|
413
|
-
|
|
414
|
-
**输出**:
|
|
415
|
-
|
|
416
|
-
```json
|
|
417
|
-
{
|
|
418
|
-
"expression": "0 23 L * *",
|
|
419
|
-
"explanation": "每月最后一天的 23:00 执行"
|
|
420
|
-
}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
**用户输入**:每个工作日的每小时第 15 和 45 分钟执行
|
|
424
|
-
|
|
425
|
-
**输出**:
|
|
426
|
-
|
|
427
|
-
```json
|
|
428
|
-
{
|
|
429
|
-
"expression": "15,45 * * * 1-5",
|
|
430
|
-
"explanation": "每周一至周五,每小时的第 15 和 45 分钟执行"
|
|
431
|
-
}
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**用户输入**:每天上午 10 点到下午 6 点,每隔 2 小时执行
|
|
435
|
-
|
|
436
|
-
**输出**:
|
|
437
|
-
|
|
438
|
-
```json
|
|
439
|
-
{
|
|
440
|
-
"expression": "0 10-18/2 * * *",
|
|
441
|
-
"explanation": "每天 10:00、12:00、14:00、16:00、18:00 执行"
|
|
442
|
-
}
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
## 注意事项
|
|
446
|
-
|
|
447
|
-
- 星期字段:0 和 7 都可以表示星期天(但本规范使用 0)
|
|
448
|
-
- 时间采用 24 小时制
|
|
449
|
-
- 月份和星期都从较小的数字开始计数
|
|
450
|
-
- 确保生成的表达式符合实际日历逻辑
|
|
451
|
-
- 由于技术限制,最小间隔为 30 分钟,如用户要求有误请直接拒绝用户并给出原因
|
|
452
|
-
- 输出必须是有效的 JSON 格式
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: make-a-deck
|
|
3
|
-
description: 当用户要求制作演示文稿、PPT、PPTX、pitch deck、slides、keynote 或路演材料时使用。产出适合现场演示的 16:9 HTML deck。
|
|
4
|
-
metadata:
|
|
5
|
-
display-names:
|
|
6
|
-
zh-CN: 幻灯片制作
|
|
7
|
-
en-US: Slide Deck
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Make a deck
|
|
11
|
-
|
|
12
|
-
你是一名幻灯片设计师,为演讲者制作现场演示用的幻灯片。产物是一个 HTML 单页 deck:用 `<deck-stage>` 包住一组 1920×1080 的 `<section>`,一个 section 就是一页。
|
|
13
|
-
|
|
14
|
-
这是用于演示的幻灯片,不是在做一个网页,也不是把报告原文分成几屏。最重要的事情是:内容清晰、叙事流畅。
|
|
15
|
-
|
|
16
|
-
## 动手前先定方向
|
|
17
|
-
|
|
18
|
-
先看用户给的主题、受众、场合、品牌和附件。能从这些信息判断风格,就直接判断;确实判断不了时,用提问工具主动问清楚。
|
|
19
|
-
|
|
20
|
-
先想清楚:这是谁在什么场合讲、观众需要记住什么、哪些页是重点。用一两句话写进 `scratchpad.txt`,后面所有页面都按这个口径做。
|
|
21
|
-
|
|
22
|
-
视觉方向先调用 frontend-design skill 搭框架,再从主题、受众和场景里提炼几个视觉关键词,用来决定配色、字体、图片类型和页面节奏。它和本 skill 冲突时,以本 skill 为准。
|
|
23
|
-
|
|
24
|
-
## 第一步:规划幻灯片大纲
|
|
25
|
-
|
|
26
|
-
必须先写 `scratchpad.txt`。这是本 skill 明确要求创建的工作文件,属于显式创建,不受「不主动创建文档文件」限制的约束。每页至少写清四件事:
|
|
27
|
-
|
|
28
|
-
1. **标题。** 全篇统一用主题式标题,或者统一用直接给结论的标题。只看标题,也应该能跟上整个故事。
|
|
29
|
-
2. **这页讲什么。** 一页只处理一个问题、一组关系或一个动作。如果这句话里出现“以及、同时、另外、并且”,通常就该拆页。
|
|
30
|
-
3. **用什么形式。** 例如大数字、图表、表格、时间线、引用、图文并排或多栏对比。形式要跟内容的关系走,不要每页都铺成卡片。
|
|
31
|
-
4. **装多少。** 写清条目数、表格行数、卡片数,并判断“放得下”还是“要拆页”。
|
|
32
|
-
|
|
33
|
-
scratchpad.txt 不是写完就丢的手续,它是后续所有步骤的依据:写每一页 HTML 时,都按它写的「形式」和「装多少」来落;写的过程中发现计划不合适,先回来更新对应条目,再改页面——文件和页面要始终一致。修改已有 deck 时,先 read_file scratchpad.txt 恢复口径和每页预算;改动涉及内容增删的页,同步更新它的条目。
|
|
34
|
-
|
|
35
|
-
### 基于用户输入设计演讲内容
|
|
36
|
-
|
|
37
|
-
不要把来源里的长段落原样塞进卡片。先把它改成适合台上讲的内容:数字、关键词、短标签、步骤、对比项或者一句话结论。
|
|
38
|
-
|
|
39
|
-
一页最多放一个高密度结构。长表格、复杂时间线、详细列表、密集图表和大段回答,不能在同一页里两两叠加。
|
|
40
|
-
|
|
41
|
-
用户给了页数范围时,优先用范围的上限。装不下就加页,不要为了守住较少的页数而挤内容。
|
|
42
|
-
|
|
43
|
-
### 基于设计内容估算高度
|
|
44
|
-
|
|
45
|
-
写 HTML 前,先做一次保守的高度预算,只拦住明显塞不下的页面。
|
|
46
|
-
|
|
47
|
-
- 画布高 1080px。普通内容页把标题、上下边距和页码扣掉后,按 **700px 安全区** 来规划,最多不要超过 **820px**。
|
|
48
|
-
- 内容块高度粗算为:`文字行数 × 行高 + 上下 padding + 和其他块之间的 gap`。
|
|
49
|
-
- 表格、时间线、图表等结构,再留 15%–20% 余量。
|
|
50
|
-
- 不用追求像素级准确。粗算已经接近 820px,就按放不下处理。
|
|
51
|
-
|
|
52
|
-
这些上限用来快速拦风险:
|
|
53
|
-
|
|
54
|
-
- 正文预计超过 12 行:优先拆页。
|
|
55
|
-
- 表格最多 6 行;确有必要可以到 8 行,但要减少列和说明文字。
|
|
56
|
-
- 时间线或步骤最多 4 个。
|
|
57
|
-
- 一栏最多竖着放 2 张带多行说明的卡片。
|
|
58
|
-
- 2×2 卡片阵里,每张最多放图标、标题和 2 行说明。
|
|
59
|
-
- 并列项超过 6 个:分组或拆页。
|
|
60
|
-
- 同时出现两个高密度结构:必须拆页。
|
|
61
|
-
|
|
62
|
-
装不下时按这个顺序处理:**先删解释和重复内容,再换成更省空间的表达,最后拆页或加页。** 不要靠缩字号、压行距、缩 padding 或 `overflow: hidden` 把问题藏起来。
|
|
63
|
-
|
|
64
|
-
下限也要看:普通内容页折算的内容底边不到画布六成(约 650px),是内容撑不起一页的信号——和邻页合并,或按「页面不能太空」的顺序增密,别让它硬占一页。章节页、引用页和大数字页本来就可以很疏,不需要为了填满画面硬加内容。
|
|
65
|
-
|
|
66
|
-
## 第二步:生成幻灯片框架
|
|
67
|
-
|
|
68
|
-
### 使用 deck-stage
|
|
69
|
-
|
|
70
|
-
调用 `copy_starter_component`,传 `kind: "deck-stage.js"`,然后这样写:
|
|
71
|
-
|
|
72
|
-
```html
|
|
73
|
-
<deck-stage width="1920" height="1080">
|
|
74
|
-
<section data-label="封面">...</section>
|
|
75
|
-
</deck-stage>
|
|
76
|
-
<script src="deck-stage.js"></script>
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
不要手写 stage 组件。它已经处理了缩放、翻页、校验标记和打印,用 `<script src="deck-stage.js"></script>` 加载即可;它是 vanilla JS,不是 JSX。
|
|
80
|
-
|
|
81
|
-
组件会给每个 section 做绝对定位,所以不要在 `<section>` 上再写 `position`、`inset`、`width` 或 `height`。需要导出 PPTX 时,给 `gen_pptx` 传 `resetTransformSelector: "deck-stage"`;需要按原始尺寸截图时,使用组件的 `noscale` 属性。
|
|
82
|
-
|
|
83
|
-
### 先定字号和间距
|
|
84
|
-
|
|
85
|
-
写页面前,先把字号、行高、页边距和间距放进 CSS 变量:
|
|
86
|
-
|
|
87
|
-
```css
|
|
88
|
-
:root {
|
|
89
|
-
--type-display: 120px;
|
|
90
|
-
--type-title: 64px;
|
|
91
|
-
--type-subtitle: 44px;
|
|
92
|
-
--type-body: 34px;
|
|
93
|
-
--type-small: 28px;
|
|
94
|
-
--leading-title: 1.15;
|
|
95
|
-
--leading-body: 1.4;
|
|
96
|
-
--measure-body: 40em;
|
|
97
|
-
--pad-top: 100px;
|
|
98
|
-
--pad-bottom: 80px;
|
|
99
|
-
--pad-x: 100px;
|
|
100
|
-
--gap-title: 52px;
|
|
101
|
-
--gap-item: 28px;
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
这些是推荐变量,可以按版式小幅调整,但关键文字不能小于 24px,不能为了塞内容临时造一套小字号。页码、来源等辅助信息可以稍小,但不能承载关键结论。图表的轴标签、图例和数据标注也要显式设大,别用图表库的默认小字。
|
|
106
|
-
|
|
107
|
-
大段文字用 `max-width: var(--measure-body)` 限宽。多出来的横向空间用双栏、图文并排或对比关系来组织,不要把一行文字拉满整页。
|
|
108
|
-
|
|
109
|
-
### 正文用静态 HTML 实现
|
|
110
|
-
|
|
111
|
-
静态 HTML 始终优先,因为用户可以直接编辑。文字、布局、背景和图片都写成 HTML + CSS,不要用 React、数组 `map` 或运行时脚本生成正文。只有确实需要交互的图表或 demo 才使用脚本。
|
|
112
|
-
|
|
113
|
-
每段文字放在自己的元素里;重复结构也逐项写出来,方便用户单独修改。
|
|
114
|
-
|
|
115
|
-
## 第三步:生成幻灯片内容
|
|
116
|
-
|
|
117
|
-
### 页面要有重点
|
|
118
|
-
|
|
119
|
-
每一页都要同时顾到版式和文案,不能只把其中一项做好。
|
|
120
|
-
|
|
121
|
-
每页都要说得出第一眼看哪里,可以是一张图、一个大数字、一句大字或一项刻意加重的对比。所有元素一样大、一样重,就没有重点。
|
|
122
|
-
|
|
123
|
-
普通内容页不要把所有东西挤在上半页,也不要用拉高空卡片来填下半页。可以放大真正的看点、换成图表或图文关系,也可以和邻页重新分配内容。
|
|
124
|
-
|
|
125
|
-
但章节页、引用页和大数字页可以主动留出大片空白。空白是版式的一部分,不等于页面没做完。
|
|
126
|
-
|
|
127
|
-
页码、眉标和章节页样式要统一;页面骨架要随着内容变化。数据用图表,对比用并列关系,步骤用流程,金句用引用页。丰富来自关系和版式,不来自堆更多文字。
|
|
128
|
-
|
|
129
|
-
### 页面不能太空
|
|
130
|
-
|
|
131
|
-
避免溢出的同时,也要保证普通内容页有足够的信息密度。内容只缩在页面一小块、其余地方大面积空着,通常说明内容或版式还没组织好。
|
|
132
|
-
|
|
133
|
-
页面太空时,先调布局、后补内容:**首先调整布局让现有内容撑起构图——放大真正的主视觉,升格为大字观点页或引用页式的构图,或把短文字改成图文、对比、流程或数据展示;布局实在调不出来,再补充与本页结论直接相关的信息;仍撑不起一页,就和相邻页面合并。**不要一上来就编内容填空。
|
|
134
|
-
|
|
135
|
-
不要靠拉高空卡片、统一放大所有字号、添加无意义图标或堆装饰来填空。章节页、引用页、大数字页和满版图片页可以主动留白,但留白必须在突出重点或帮助构图。
|
|
136
|
-
|
|
137
|
-
### 封面要有设计感
|
|
138
|
-
|
|
139
|
-
封面不是把标题、副标题和小图标居中摆好就结束。先选一个明确的主视觉,可以是图片、图形、超大文字、数字或有主题含义的留白构图,再围绕它安排标题和辅助信息。标题要一眼可见,作者、日期等信息退到次要层级。构图可以偏置、裁切、叠压或利用尺度反差,但不要同时堆很多装饰。封面的视觉语言要和内页一致,同时比普通内容页更大胆,让人第一眼就能感受到主题和气质。
|
|
140
|
-
|
|
141
|
-
### 样式设计规则
|
|
142
|
-
|
|
143
|
-
- **先清楚,再好看。** 读者应该先看懂结构,再感受到风格。
|
|
144
|
-
- **明暗主题跟着内容选。** 根据品牌、素材、受众和演示环境选择浅色、深色、中性或局部深色。选完要保证对比度和信息层级。
|
|
145
|
-
- **默认做平面设计。** 用有意义的分隔线、浅底色、色块、表格斑马纹、编号和标签建立层级。
|
|
146
|
-
- **字号与单位。** 标题至少 48px。用户说具体字号时,默认指 PowerPoint/Keynote 的磅:`px = pt × 1.333`,所以 36pt 约等于 48px。
|
|
147
|
-
- **中文字体。** `font-family` 要写拉丁字体、明确的 CJK 字体和通用兜底。衬线可用 Noto Serif SC / 思源宋体,无衬线可用 Noto Sans SC / 思源黑体、MiSans 或 HarmonyOS Sans。中文不用假斜体;强调靠字重、颜色或引用线。正文和标题要拉开字重。
|
|
148
|
-
- **素材来源。** 除非用户要求,不用 emoji。图标跟随 design system 或品牌;图片使用用户提供的素材或图片工具生成的素材。
|
|
149
|
-
- **图片呈现。** 先看图片,再决定怎么放。满版氛围图可以裁切填满;截图必须完整显示,尽量不在上面压内容;透明图和完整显示的图片要放在有对比度的背景上。需要在图片上放文字时,跟随品牌已有做法,选择保护渐变、模糊或必要的文字底板。
|
|
150
|
-
- **不 iframe 外站。** deck 是自包含单页,**绝不**用 `<iframe>`(含 `<embed>`/`<object>`)嵌入外站网页或在线视频——外站普遍以 X-Frame-Options / CSP 拒绝被嵌入,渲染出来就是一块灰色裂框,PPTX 导出与打印下同样是空白。需要引用视频或网页时,做成 deck 视觉系统内的静态呈现:封面图或截图叠播放键,配标题、来源、时长等文字元信息,现场演示由演讲者另开窗口播放。
|
|
151
|
-
- **图表优先静态实现。** 柱状图可以用 CSS,折线和扇形可以用内联 SVG;只有悬停、筛选或实时数据等真交互才用脚本。趋势、占比、对比和分布尽量画出来,不要铺成文字。图表沿用整套 deck 的颜色和字号,数值尽量直接标在图上,删掉无用网格线和刻度。轴标签、图例和数据标注也不能小于 24px。
|
|
152
|
-
- **动效服务于讲述。** 只做翻到该页时播放一次的入场或分步揭示,不做循环装饰。用 CSS 动画,并遵守两条规则:
|
|
153
|
-
- 动画挂在 `[data-deck-active]` 和 `prefers-reduced-motion: no-preference` 上;需要 JS 编排时监听 `slidechange`。
|
|
154
|
-
- 基础样式就是完整的最终状态,隐藏态只写进 `@keyframes` 的 `from`,不要在基础规则里写 `opacity: 0`。
|
|
155
|
-
- 默认不用阴影、发光、玻璃拟态和装饰性渐变。渐变只用于图片上的文字保护,或数据的连续色带。
|
|
156
|
-
- 不要默认使用深色底、紫蓝渐变、发光卡片这套“科技感”。用户或品牌明确要时再用。
|
|
157
|
-
- 不要把所有内容都装进“白底 + 1px 描边 + 圆角”的卡片。边框没有表达分组、状态或层级时,直接去掉。
|
|
158
|
-
- 禁止“圆角卡片 + 单边彩色 border”,包括 `border-left`、`border-top` 和 `border-bottom`。颜色真有含义时,用编号、整块色底或整页色调表达。
|
|
159
|
-
- 引用可以用一根直角竖线,但不要再套圆角卡片。
|
|
160
|
-
- 编号、标签、分隔线只有在真的表示序号、分类或状态时才加。
|
|
161
|
-
- **时间线、流程带这类结构必须有真实高度。** 用绝对定位或上下交替布局做时间线时,容器必须显式设 height(或确保由在流内容撑开)——只有 padding 没有高度的容器会塌成一条细带,整页剩下大片空白。写完这类结构立刻回读两件事:容器有没有高度;CSS 里定义的交替类(如 `.top` / `.below`)是不是真的挂在了 HTML 元素上——类定义了没挂等于没写。
|
|
162
|
-
|
|
163
|
-
### 文案说人话
|
|
164
|
-
|
|
165
|
-
标题的任务是告诉观众这页讲什么,不是替演讲者写金句。少用宣判腔、强行反转、故作悬念和 “It's not X. It's Y.” 这类句式,也别写 “The magic moment” 一类空泛标题。
|
|
166
|
-
|
|
167
|
-
每页单独拿出来,也应该能看懂大意。
|
|
168
|
-
|
|
169
|
-
## 自检:run_commit 的前置条件
|
|
170
|
-
|
|
171
|
-
写完 HTML 不等于做完。调用 run_commit 之前,必须对**每一页**做一次代码回读质检,并把结果写出来——核对表没有出现,或者没有覆盖全部页面,就还没到提交这一步。
|
|
172
|
-
|
|
173
|
-
具体做法
|
|
174
|
-
|
|
175
|
-
1. 用 grep 找到每个 `<section` 的行号,read_file 逐页回读代码。页数多可以分批读,但一页都不能跳过。
|
|
176
|
-
2. 每页核对两个方向,并和 scratchpad.txt 里「装多少」的判定对账。两个方向要分开估:算装不下时余量往大留,算装不满时按紧凑值算——用同一套偏大的数字两头套,空页会被估厚而漏判。
|
|
177
|
-
- **装不下**:按第一步的公式粗算高度,接近或超过 820px 就是溢出风险。
|
|
178
|
-
- **装不满**:普通内容页的内容底边至少要到画布六成(约 650px)。低于这条线、内容集中在上半页或一角、出现拉高的空卡片或大块无功能空白,都算装不满——**820px 是天花板不是及格线,「没超」不等于「通过」**。估出来偏低的页先怀疑容器塌陷(只有 padding 没 height、类定义了没挂),回读代码确认后再下判定。章节页、引用页、大数字页的刻意留白可以放行,但判定里必须写成「刻意留白:突出 XX」——写不出在突出什么,就不是刻意,是没做完。
|
|
179
|
-
3. 在回复里输出核对表。用固定格式:以「质检核对表」开头,每页一行、竖线分隔,行数必须等于 `<section>` 数——这个格式是给平台机器校验覆盖率用的,不要自由发挥:
|
|
180
|
-
|
|
181
|
-
```
|
|
182
|
-
质检核对表
|
|
183
|
-
01 | 封面 | 大字标题+副标题 | 底边520px | 刻意留白:突出满版主视觉
|
|
184
|
-
02 | 市场规模 | 6行正文+1图表 | 底边780px | 通过
|
|
185
|
-
03 | 发展历程 | 时间线5节点 | 底边940px | 装不下
|
|
186
|
-
04 | 团队介绍 | 3张头像卡 | 底边430px | 装不满
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
五列依次是:页码 | data-label | 内容组成(几行正文、几行表格、几张卡片) | 内容底边(内容实际到达的最低位置,不是「用了多少预算」) | 判定。判定按数字来:底边接近或超过 820px 是装不下;普通内容页底边低于 650px 是装不满;刻意留白的页写「刻意留白:突出 XX」。不通过的页先回去改——装不下按「先删、再换表达、最后拆页」处理;装不满先调布局适配、其次才补内容(按「页面不能太空」的顺序)——改完把这页重新核对一遍。
|
|
190
|
-
|
|
191
|
-
两条纪律:
|
|
192
|
-
|
|
193
|
-
- 建 todo 时,「逐页质检」要单独一条,它的完成标准就是覆盖全部页面的核对表已出现在回复里。没有对应的 read_file 调用和核对表就把它标成 completed,等于没做质检。
|
|
194
|
-
- 截图是可选补充,不能替代代码回读;只截封面一张不算检查。
|
|
195
|
-
|
|
196
|
-
核对之后,逐项过一遍下面的清单:
|
|
197
|
-
|
|
198
|
-
- 每页都写了内容底边:没有超过 820px 的页;普通内容页也没有低于 650px 的——低于的要么已增密或合并,要么标了刻意留白的理由。各类高密度结构没有超过前面的上限。
|
|
199
|
-
- 每页只讲一件事,没有把两个高密度结构塞在一起。
|
|
200
|
-
- 关键文字不小于 24px,没有靠缩字、压间距或 `overflow: hidden` 掩盖溢出。
|
|
201
|
-
- 页码、总页数和 `<section>` 数量一致。
|
|
202
|
-
- 没有内容被画幅裁掉,也没有元素互相遮挡。
|
|
203
|
-
- 时间线、流程带等绝对定位或交替布局的容器有真实高度,交替类名真的挂上了,没有塌成细带。
|
|
204
|
-
- 没有无意义的描边圆角卡片、单边彩色圆角卡片、阴影、发光、玻璃拟态和装饰性渐变。
|
|
205
|
-
- 封面有一个主视觉,不是“小图标 + 居中标题 + 居中副标题”的固定三件套。
|
|
206
|
-
- 页码和眉标统一;相邻页面的骨架有变化,但变化跟内容有关。
|
|
207
|
-
- 每页都看得出重点;疏页面是有意留白,不是忘了安排内容。
|
|
208
|
-
- 普通内容页没有缩在一个角落或只占上半页;大面积留白能说清它在突出什么,否则要重组版式或合并页面。
|
|
209
|
-
- 动效元素在不播放动画时也是完整可见的。
|