# 柚见三周年 · 幸运大转盘

> 活页公开模板 `sample-lucky-wheel` · 场景: 互动玩法 · 行业: 零售门店 / 餐饮茶饮
> 任何人、任何 Agent 都可以读、照着改，不需要账号。示例内容均为虚构。
> 真页面: https://space.24haowan.com/s/usZ7BRRRWkRb · 详情: https://space.24haowan.com/examples/sample-lucky-wheel

## 这是什么

幸运大转盘 · 门店店庆、会员日抽奖

## 什么时候用

门店店庆、会员日、开业、节日，想发一个在群里点开就能抽一次的转盘：奖品有限量、要显示还剩多少、抽中的券到店核销，选它。只收报名、按场次分名额选 sample-event-signup；请人来吃饭回个执选 sample-invitation；不需要抽奖、只想把商品和价格摆出来选 sample-product-catalog。

## 用户对助手说的原话

帮我给我们奶茶店的周年店庆做一个幸运大转盘，发成一个网页链接到会员群：首屏就是一只用 canvas 画的大转盘，8 格奖品，每格有一个现画的小插画和短字，外圈一圈会闪的灯泡，顶上一个指针，中间一个大的「开始」按钮；上面是店名、活动日期、一句大标题和一句店长的话，右上角一个静音键；点开始后转盘像真的一样减速停下，指针过格子边界时轻轻抖一下，停下时撒彩带、手机轻震、响一声合成的音效（点了才响），然后弹出一张奖券卡：奖品、插画、券码、有效期、在哪核销，下面填称呼点领取，存进一张数据表（name / prize / code）。转盘下面写今天还有几次机会、奖池还剩多少，一条「最近中奖」滚动条读这张表。往下是奖品与剩余：每样奖品的总数、剩余、此刻概率和一条剩余进度条，概率按剩余数算，写明规则；然后折叠的活动规则、门店地址带复制按钮。手机竖屏一屏看完首屏，电脑上居中一块手机比例的舞台；转盘不出来时也能看到奖品表、规则和一张登记表单。活动期间有变化就更新同一个链接。

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

## 照着做一份

1. 读入口文件 https://space.24haowan.com/examples/sample-lucky-wheel/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-lucky-wheel ，返回预览链接、7 天分享与认领链接（登录后保留、链接不变）。

## 页面结构

- 转一次
- 奖品与剩余
- 活动规则
- 门店地址

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

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

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

- canvas 现画的转盘、彩带粒子与 Web Audio 合成音（点按后才发声，可静音），一张值得截图的奖券卡
- 奖券卡里填称呼领取写回数据表（原生表单 POST ./_data/draws），页面读回扣减各奖品剩余、滚动显示最近中奖
- 同一链接活动期间持续更新（改奖池、补门店已抽数都在这一页）
- 微信卡片（share.title / share.desc）

## 发之前要备好

- 数据表 draws（列 name / prize / code，append_open=true）：奖券卡里的领取写进这里，页面读回扣减剩余、显示最近中奖；发布前先用 set_data 建好，活动结束把 append_open 关掉

## 模板说明（README）

模板市场第二波「富媒体 H5」样例（总览见 `core/space/examples/README.md`，品质标准见 `core/space/examples/QUALITY.md`）。虚构奶茶店「柚见」三周年店庆，店长发到会员群。示例数据均为虚构。

## 演示哪个特色

**一只在微信里点开就想转的大转盘，抽中的券写回数据表，页面读回剩余和最近中奖。**

- **记忆点**是首屏那只 `<canvas>` 转盘：8 格奖品，每格的插画（奶茶杯、小料碗、帆布袋、券……）都是脚本现画的，不用一张图。待机时极慢地转、外圈灯泡交替闪；点「开始」后按四次方缓出减速（约 5.6 秒），指针每过一条扇区边界被拨一下、弹簧回正，并配一声很轻的「嗒」。
- 停下时：彩带粒子（全屏 canvas）+ `navigator.vibrate` 轻震（不支持就跳过）+ Web Audio 合成的四音上行（**只在点按后**发声，右上角静音键，记在本机），然后弹出奖券卡：奖品、插画、券码（`YJ3-月日-四位`）、有效期、核销地点 —— 一张值得截图的结果画面。
- 发出去之后：奖券卡里填称呼点「领取」= 原生表单 `POST ./_data/draws`（列 `name / prize / code`），脚本在时页内提交。页面读 `./_data/draws.json`：群里已领的从各奖品剩余里扣掉、最新几条进「最近中奖」滚动条（名字只露第一个字）。
- **概率与剩余自洽**：格子一样大，抽中某样的概率 = 它的剩余 ÷ 全部剩余，页面上「奖品与剩余」里的百分比就是此刻的抽签权重，抽完的那样自动不再转到。剩余 = 总数 − 门店现场已抽（写在页面里）− 群里已领（读表）。
- 每人每天 1 次只用 `localStorage` 做提示（转过后按钮变「我的券」），读不到就当没转过，不影响显示；真正的限次在到店核券时按会员手机号。
- `prefers-reduced-motion`：转盘不待机旋转、灯泡不闪、滚动条不翻，「开始」后 0.7 秒直接停在结果，不放彩带。
- 脚本不跑时：首屏换成静态页头，奖品表与规则照常显示，页末出现「到店抽中后登记」表单（同一张表 `draws`）。

## 改哪里变成我的

| 位置 | 改什么 |
|---|---|
| 首屏 `.shop` / `h1` / `.boss` | 店名、活动名与日期、一句店长的话 |
| 脚本 `SECTORS` | 转盘上从 12 点顺时针的 8 格：`k`（奖品键，和奖品表 `data-k`、表单 `<option>` 三处一致）、格子上的短字、底色、插画（`ICONS` 里现成 8 种，可换） |
| 奖品表 `.prizes li` | `data-total` 总数、`data-store` 门店现场已抽；名称、一句说明；`剩 N / 总数 · 百分比` 与条形宽度是不跑脚本时显示的值（脚本会按表重算），一起改 |
| `.sumline` / `.pool` | 奖池总数、已抽、还剩（同上，静态值要和奖品表加起来对得上） |
| 活动规则 `ol.rules` | 时间、次数、概率口径、领取与用券规则、有效期 |
| 门店地址 `.store` | 店名、地址、怎么到、营业时间、电话 |
| 奖券卡 `.t-meta` | 有效期、核销地点；券码前缀在脚本 `code()` 里 |
| 页脚 | 平台标志与名称（与 `core/space/src/theme.ts` 的 `MARK_SVG` / `PUBLIC_NAME` 逐字一致，测试咬着）+ 一句适用场景；发自己的活动时整段删掉 |
| `manifest.json` | `title` / `share.title` / `share.desc`（微信卡片上的字） |

## 数据表

领取写进数据表 `draws`（一次一行，`append_open=true`）。发之前先建表：

```
set_data  proposal_id: <id>  table: "draws"  columns: ["name","prize","code"]  rows: []  append_open: true  revision: 0
```

店员核券时用 `list_data_rows table=draws` 读回、按券码对；活动结束把 `append_open` 关掉。本地 `space-cli serve` 会把提交写进包里的 `_data/draws.json`，试完记得改回 `[]`。

## 怎么发出去

```bash
export SPACE_TOKEN=sk-space-…            # MCP create_cli_token
node core/space/cli/space-cli.mjs push core/space/examples/sample-lucky-wheel \
  --proposal <proposal_id> --manifest core/space/examples/sample-lucky-wheel/manifest.json --hold
```

没有终端时也可以 MCP `publish_file`（`filename: "index.html"`、`content` 为全文、`manifest` 为 manifest.json 去掉 entry、`hold: true`），再按上面建表。
给谁看：默认仅自己可见；发到会员群前用 `set_visibility` 改成 `public`（或 `passcode` 只给会员）。

## 素材

- 没有位图：店标、转盘、插画、指针、彩带全部是内联 SVG 或 canvas 现画；店名、地址、电话、人名均为虚构。
- `thumb.webp` / `phone.webp`：画廊缩略图与手机首屏图，由 `examples/verify-shots.mjs --write-thumb --write-phone` 从成品截出，不进发布包。
