Files
FSE-Ticket.sys/.trae/documents/新增对外车票查询与线上预定,并接入售票机凭证兑票.md
2026-06-21 10:00:13 +08:00

70 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 概览
- 新增两个对外页面:`/ticket-search`(车票查询/详情)与`/ticket-order`(线上预定)
- 后端增加“线上预定/凭证”API,售票机支持“NEW/ONLINE”两模式,线上凭证在当天有效
- 页面样式统一沿用现有控制台风格(`web/style.css`),Minecraft 端所有文案保持英文
## 后端改动(Node/Express
- 新增数据文件:`web/data/orders.json`(列表)、`web/data/order_index.json`(按码索引)
- 新增接口:
- `POST /api/public/orders`:创建线上预定,入参:`start``terminal``train_type``trips``ride_date`YYYY-MM-DD)。生成唯一5位字母数字凭证 `code`,返回 `{ ok:true, code, price }`。价格通过现有票价数据计算(普通/特急),并按当前促销折扣应用(与`/api/public/config`一致)。
- `GET /api/public/orders/:code`:查询凭证详情,返回 `{ code, start, terminal, train_type, trips, ride_date, price, created_ts, consumed:false }`
- `POST /api/public/orders/:code/consume`:兑票后标记消费(幂等),防重复使用;返回 `{ ok:true }`
- `GET /api/public/popular`:根据现有售票事件日志(`web/data/ticket_events.jsonl``type:'sale'`)统计近7天或全部的热门站点与热门路线,返回 `{ topStations: [{name, code, count}], topRoutes: [{from,to,count}] }`
- 路由与静态文件:
- 追加服务器路由以兼容直链:`GET /ticket-search/:id``GET /ticket-search` 均返回同一静态页面文件(`web/ticket-search.html`);页面端通过 `location.pathname` 识别 `:id` 并拉取数据。
- 同理为 `GET /ticket-order` 返回 `web/ticket-order.html`
- 复用/对齐:价格计算逻辑沿用控制台已有数据源与折扣(`server.js` 已持久化 `stations/lines/fares``promotion`)。
## 前端页面
- `web/ticket-search.html` + `web/ticket-search.js`
- 顶部搜索栏(支持模糊匹配,匹配票号、起点、终点、站点编号)。调用 `GET /api/public/tickets?q=...` 渲染列表,点击进入详情。
- 详情视图:支持直链 `ticket.fse-media.group/ticket-search/XXXX`,通过 `GET /api/public/tickets/:id` 展示“概览+事件时间线”。
- 辅助区块:热门站点与热门路线,调用 `GET /api/public/popular`,以卡片或列表展示。
- 样式统一使用 `web/style.css` 的卡片/列表/按钮体系。
- `web/ticket-order.html` + `web/ticket-order.js`
- 流程:选择起点/终点(下拉+模糊搜索)、车型(普通/特急)、乘次、乘车日期(日期选择器)。右侧实时显示价格(调用 `GET /api/public/fares/query` 并应用折扣)。
- 点击“生成凭证”后调用 `POST /api/public/orders`,展示返回的 5 位字母数字码及说明:“到游戏内售票机付款”。
- 提供“复制凭证码”、“查看我的凭证详情”按钮(跳到 `/ticket-search/:code`)。
## 售票机 Lua 改动
- 首页两按钮:`NEW`(线下购买)与 `ONLINE`(线上兑票)。位置/大小与现有 `Start` 等同(修改 `showHome`),其余流程保持英文。
- 新增页面:线上凭证输入与验证
- 屏幕键盘(AZ、09、Backspace、Clear、OK),输入 5 位码;UI使用既有 `addButton`/`waitButtons` 组件。
- 验证逻辑:
- `GET http://ticket.fse-media.group/api/public/orders/:code`(或由 `config.json``api_base` 指到生产域),若返回存在且 `ride_date == os.date('%Y-%m-%d')` 且未 `consumed`,则有效。
- 有效则将 `state.departure``state.terminal``state.trainType``state.trips``state.cost` 赋值并跳转到订单确认/支付页;支付逻辑与线下一致。
- 无效弹英文提示:`Invalid voucher`
- 兑票完成后调用 `POST /api/public/orders/:code/consume` 标记已使用。
- 变更点位置参考:
- 首页按钮处:在 `Lua/TicketMachine/startup.lua:805..822``showHome`,替换 `Start``NEW``ONLINE` 两个 `addButton`,分别进入现有线下流程与新逻辑。
- 新增函数如 `showOnlineVoucher()`:与 `showOrderAndAudio()` 类似结构,添加键盘与HTTP校验后复用订单页。
- HTTP 使用已存在封装:`fetchHTTP()``jsonDecode()``startup.lua:191..198`, `186..189`)。
## 域名与HTTP访问
- 站点部署到 `ticket.fse-media.group`,售票机需允许该域名的HTTP访问:
- Minecraft 1.13+:在 `serverconfig/computercraft-server.toml` 中移除或调整 `[[http.rules]] host = "$private" action = "deny"`(参见 Tweaked CC 文档)。
- 老版本或单机不同路径,参考提供的文档片段。
- 售票机 `config.json``API_ENDPOINT.txt` 指向生产 API 基础地址,`startup.lua``API_BASE` 也将改为生产地址。
## 文案与样式约定
- Web 前端:中文页面与控件;
- CC:T 端所有提示、按钮、错误信息统一英文(现有实现已如此,新增页面按该规范)。
- 整体风格沿用 `web/style.css` 控制台样式(深色/浅色模式兼容)。
## 交付物
- 新增/修改的文件:
- `web/ticket-search.html`, `web/ticket-search.js`
- `web/ticket-order.html`, `web/ticket-order.js`
- `web/server.js`(新增`orders`/`popular`接口与静态路由)
- `web/data/orders.json`, `web/data/order_index.json`
- `Lua/TicketMachine/startup.lua`(首页按钮与线上凭证流程)
## 验证
- 后端:本地启动后用 `GET /api/public/popular``POST /api/public/orders``GET /api/public/orders/:code` 联调;
- 前端:打开 `/ticket-order` 生成凭证 → 复制码直链查看 `/ticket-search/:code`
- 售票机:触发 `ONLINE` 流程,输入码验证跨天逻辑与支付流程,兑票后标记消费成功。
## 兼容/风险控制
- 所有新增逻辑均以新文件/新接口为主,避免破坏现有控制台;
- 前端/后端的模糊搜索初期采用子串匹配,后续可替换为更精细的打分;
- 若 HTTP 被禁,售票机将回退到线下流程,界面提示网络不可用。