# 青螺山秋季徒步 · 10 月 24 日报名

> 活页公开模板 `sample-event-signup` · 场景: 报名 · 投票 · 接龙 · 行业: 旅游出行 / 个人家庭
> 任何人、任何 Agent 都可以读、照着改，不需要账号。示例内容均为虚构。
> 真页面: https://space.24haowan.com/s/nBo2gKHle_qG · 详情: https://space.24haowan.com/examples/sample-event-signup

## 这是什么

活动报名页 · 发到群里收报名

## 什么时候用

要让读者填东西回来：活动报名、分线路 / 分场次的名额、课程或聚会登记。名额改了只改表，链接不变。只是发通知、不收报名选 sample-weekend-trip。

## 用户对助手说的原话

帮我做一个周末徒步活动的报名页，发成一个网页链接：页头是俱乐部名、活动编号和活动要素（日期、集合点、领队、报名截止）；接着把三条线路画成一张海拔剖面图（三条线不同颜色，标出各自最高点），下面逐条写距离、爬升、用时、适合谁和剩余名额；然后按时间排当天安排、写清下撤和雨天顺延规则，再列带什么和费用；最后是报名表单：选线路、填称呼和备注，一个报名按钮，报名存到一张数据表里，名额按报名人数实时减少，已报名的称呼列在下面。手机上剖面图换一套坐标，线路选项改竖排。

如果你还没有活页连接器（MCP），先读 https://space.24haowan.com/for-agents.md ，照里面的说明接入，或不登录直接发布。

## 照着做一份

1. 读入口文件 https://space.24haowan.com/examples/sample-event-signup/source/index.html（它引用的其他文件见下方列表）。
2. 保留结构、版式和交互，把内容**全部**换成用户自己的；模板里的公司、人名、数字都是虚构的，一样都别留。
3. 交付一个自包含的单文件 HTML：样式写在页面里，不引外部字体 / 脚本 / CDN；手机 375 宽和电脑 1440 宽都要好看，模板有暗色就保留暗色。
4. 要发成微信里能打开、改了链接不变的网页：接入活页（https://space.24haowan.com/for-agents.md）后发布；没有账号也可以让用户在 https://space.24haowan.com/quick 上传这个文件。
5. 没有活页工具、但能发 HTTPS 请求：把做好的 HTML 以 Content-Type: text/html POST 到 https://space.24haowan.com/api/quick?client=template-sample-event-signup ，返回预览链接、7 天分享与认领链接（登录后保留、链接不变）。

## 页面结构

- 三条线路
- 当天安排
- 带什么 · 费用
- 报名

## 文件（公开，纯文本）

- https://space.24haowan.com/examples/sample-event-signup/source/index.html（入口）

## 发成活页之后还能做的

- 页内报名回写数据表（原生表单 POST ./_data/signups）
- 名额放在数据表里，改名额不重发页面
- 同一链接更新不变

## 发之前要备好

- 数据表 sessions（列 session / title / time / place / seats，append_open=false）：三条线路与名额，改名额只改这张表
- 数据表 signups（列 session / name / note，append_open=true）：报名表单写进这里；截止报名时把 append_open 关掉。新工作区种入时两张表自动建好

## 模板说明（README）

「示例 · 五种用法」文件夹的第 4 份（总览见 `core/space/examples/README.md`）。按 `core/space/examples/QUALITY.md` 重做（EPIC #9032 C5，#9038）。示例内容均为虚构（俱乐部、山、线路、人名都是编的）。

## 演示哪个特色

**报名写回数据表，名额放在另一张表里：改名额只改表，页面不重发，链接不变。**

- 文末是一张原生表单 `<form action="./_data/signups" method="post">`：不跑脚本也能报名（服务端 303 回到本页并带 `?space_submitted=signups`）；
  脚本在时改成 `fetch` POST 一行 JSON，就地显示「报上了」。
- 页面用 `fetch('./_data/sessions.json')` / `fetch('./_data/signups.json')` 读两张表，按 `session` 计数算「剩几位」，满了的线路在表单里禁选；
  已报名的称呼列在表单下面（`signups` 的 GET 结果 = 底表 + 过审的读者写回）。
- 领队（作者或工作区同事）自己在页面上报的名，读回的那一行多带 `_author: true`，名单里在称呼后显示「作者」；读者交上来的 `_author` 平台一律丢弃，起同一个称呼也冒充不了。
- 组织者读报名：MCP `list_data_rows table=signups`。改名额、加线路：`get_data` 拿修订号 → `set_data` 整表替换 `sessions`。
- 记忆点是三条线路叠在一起的海拔剖面图（内联 SVG，电脑 / 手机各一套坐标，进入视野时画出来）。

## 两张表（挂在页面上，包里 `_data/` 是同名回落）

| 表 | 列 | 读者写回 `append_open` | 页面怎么用 |
|---|---|---|---|
| `sessions` | `session`, `title`, `time`, `place`, `seats` | **关** | `seats − 该线路报名数` = 剩余名额，≤ 0 显示「已满」并禁选 |
| `signups` | `session`, `name`, `note` | **开** | 报名写回；按 `session` 计数；名单列出 `name` |

`session` 是线路的机器名（`short` / `mid` / `long`），两张表靠它对上，也是页面里 `data-session` 与单选框的 `value`。
新工作区种入时由 `core/space/src/publish/samples.ts` 的 `SAMPLE_DATA_TABLES` 建好；自己发的时候先建表：

```
set_data proposal_id=<id> table="sessions" revision=0 append_open=false rows=[
  {"session":"short","title":"溪谷环线 · 6 km","time":"08:30 集合","place":"青螺站 B 口","seats":12},
  {"session":"mid","title":"山脊线 · 11 km","time":"07:30 集合","place":"青螺站 B 口","seats":10},
  {"session":"long","title":"南北穿越 · 18 km","time":"06:30 集合","place":"青螺站 B 口","seats":8}
]
set_data proposal_id=<id> table="signups" revision=0 rows=[] columns=["session","name","note"] append_open=true
```

截止报名 = 只翻开关：`set_data table="signups" revision=<当前> append_open=false`（页面会印「报名已经截止了」）。
本地 `space-cli serve` 会把提交写进包里的 `_data/signups.json`，试完记得改回 `[]`。

## 改哪里变成我的

| 位置 | 改什么 |
|---|---|
| 页头 `.org` / `h1` / `.sub` / `.facts` | 组织名、活动编号、活动名、一句话、日期 / 集合 / 领队 / 截止 |
| 海拔剖面 `svg.elev`（`.wide` / `.narrow` 两段） | 按你们的线路重画；不是徒步就整块换成与活动相关的一张图（场地图、日程条），或删掉 |
| `.routes` 三条 | 每条 `<li data-session="…">`：名称、距离、用时、适合谁；名额数字只是没数据时的回落，真值在 `sessions` 表 |
| 「当天安排」「带什么 · 费用」 | 整段换掉；两处的备注（`.aside`）写你们真实的约束 |
| 报名表单 | 单选的 `value` 与 `sessions.session` 一致；多收一格就给 `signups` 加一列、表单加一个同名输入框 |
| 页脚 | 平台标志与名称（与 `core/space/src/theme.ts` 的 `MARK_SVG` / `PUBLIC_NAME` 逐字一致，测试咬着）+ 一句适用场景；发自己的活动时整段删掉 |
| `manifest.json` | `title` / `share.*`；节增减时 `sections` 与页里的 `id` / `data-track-section` 三处同改 |

纪律：开了写回的表只放能公开的列 —— 过审的读者行会出现在 `GET ./_data/signups.json` 里，任何能看这页的人都读得到。
手机号不要收进 `signups`（页面上写了「不收手机号」）。写回每行只记设备、时间与版本，不是实名。

## 怎么发出去

```bash
# 1. 建页面（MCP create_proposal）→ proposal_id；2. 建两张表（上面的 set_data）
# 3. 推整个目录（带 _data/ 回落）：
node core/space/cli/space-cli.mjs push core/space/examples/sample-event-signup \
  --proposal <proposal_id> --manifest core/space/examples/sample-event-signup/manifest.json --hold
# 4. 预览：线路显示「剩 N 位」；5. publish_version；6. 群里发用口令（set_visibility passcode），公开要本人明确同意
# 7. 验收：真机报一条 → list_data_rows 能读回、页面剩余名额 −1；关掉 append_open 再报 → 页面印「报名已经截止了」
```

验收截图：`node --import tsx examples/verify-shots.mjs sample-event-signup --write-thumb`（QUALITY.md §7）。
