1493 lines
122 KiB
Markdown
1493 lines
122 KiB
Markdown
|
|
# IC储蓄卡功能开发
|
|||
|
|
|
|||
|
|
> **Workspace:** d:\TaoYuan2023_HSTG\HSTG\Lua\TicketMachine
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
现在我们新增了一个IC储蓄卡的功能。MOD那边的API是这样的:
|
|||
|
|
IC 卡系统 Lua API
|
|||
|
|
|
|||
|
|
售票机 ticket_vending_machine 新增
|
|||
|
|
方法 | 返回
|
|||
|
|
issueTicket(...) | true, ticketId
|
|||
|
|
issueICCard() | true, cardId
|
|||
|
|
`local ok, cardId = vm.issueICCard()`
|
|||
|
|
|
|||
|
|
充值机 ic_refill_machine
|
|||
|
|
方法 | 参数 | 返回 | 说明
|
|||
|
|
getCardInfo() | 无 | table |卡号/持有者/余额
|
|||
|
|
refill(amount) | 金额 | true, 新余额 | 充值
|
|||
|
|
deduct(amount) | 金额 | true, 新余额 | 扣费
|
|||
|
|
|
|||
|
|
操作流程:手持卡右键方块 → 插入 → CC 操作 → ejectCard() 取出
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
所以要加:
|
|||
|
|
1. `d:\TaoYuan2023_HSTG\HSTG\Lua\TicketMachine\ticketmachine.lua` 添加一个“办卡”的页面。点击按钮后开始办卡。首先输入卡的使用者。输入框下面有26键键盘以及符号键盘。确定之后选择首次充值余额。可以自定义,也可以选择预设:5、10、15、20。然后选择之后就像“购票支付” `d:\TaoYuan2023_HSTG\HSTG\Lua\TicketMachine\ticketmachine.lua#L902-902` 那样付钱充值.完成之后就出卡。把使用者名、余额传入出票机。同时也要向网页端记录该卡。
|
|||
|
|
|
|||
|
|
2. 检票模块:
|
|||
|
|
卡右键检票机,向卡中传入进站的车站编号。出站时通过识别卡中的进站站台编号和当前出站站台编号,计算路费。计算后扣费后向卡中传入新的余额。
|
|||
|
|
|
|||
|
|
其它“已经进站”/“还未进站”等提示照旧
|
|||
|
|
|
|||
|
|
3.网页控制台端。加上新的记录卡信息的/api 地址。然后后台也能看到卡的所有信息(类似车票)。同时也要在公开的页面显示,加入查询的索引。
|
|||
|
|
|
|||
|
|
4. 线上购卡
|
|||
|
|
和线上购票类似,通过线上购卡,然后获得凭证,在computercraft中通过凭证兑卡。
|
|||
|
|
|
|||
|
|
请注意,所有网页的css请按照当前的css风格(模仿JR官网 `https://www.jreast.co.jp/` )
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先梳理现有代码结构,重点看 `ticketmachine.lua` 的购票支付流程、检票模块的进出站逻辑,以及网页端现有的票据 API 和展示页,确认新加 IC 储蓄卡最合适的接入点。
|
|||
|
|
|
|||
|
|
我已做了完整检索,覆盖了售票机主程序、线上预定页、凭证详情页,以及闸机核验侧代码;下面按“页面结构、输入交互、支付、出票、接入点”汇总。
|
|||
|
|
|
|||
|
|
**主流程**
|
|||
|
|
- 主状态机在 [mainPageLoop](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1429-L1444),页面顺序是 `home -> departure -> terminal -> type -> trips -> order -> done`,线上兑票走 `home -> online -> order -> done`
|
|||
|
|
- 首页模式选择在 [showHome](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L693-L732),只有两个入口:`NEW` 新购票、`ONLINE` 凭证兑票
|
|||
|
|
- 站点/线路选择页共用 [renderLinesSelection](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L735-L796),数据来自 `CFG.lines / CFG.stations`
|
|||
|
|
- 订单确认与支付页在 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1023-L1154),出票完成页在 [showDone](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1190-L1336)
|
|||
|
|
- 线上凭证输入页在 [showOnlineVoucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1338-L1424)
|
|||
|
|
|
|||
|
|
**页面结构**
|
|||
|
|
- `home`:模式选择页,按钮为 `NEW / ONLINE`,进入不同购票链路,见 [showHome](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L693-L732)
|
|||
|
|
- `departure`:选择出发站,见 [showDeparture](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L798-L816)
|
|||
|
|
- `terminal`:选择到达站,禁止同站,见 [showTerminal](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L818-L848)
|
|||
|
|
- `type`:选择 `Local / Express`,见 [showType](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L850-L877)
|
|||
|
|
- `trips`:选择乘次数量,`+/-` 调整,见 [showTrips](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L879-L900)
|
|||
|
|
- `order`:显示区间、车型、次数、金额、支付进度条、确认按钮,见 [drawOrder](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L962-L1021) 与 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1023-L1154)
|
|||
|
|
- `done`:真正执行出票/上传后展示票据信息,见 [showDone](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1190-L1336)
|
|||
|
|
- `online`:5 位凭证码输入页,见 [showOnlineVoucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1338-L1424)
|
|||
|
|
|
|||
|
|
**输入交互**
|
|||
|
|
- 统一按钮机制在 [addButton / waitButtons](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L582-L600),支持 `mouse_click` 和 `monitor_touch`
|
|||
|
|
- 全局取消弹窗在 [renderConfirmCancel](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L662-L674),各页通过 `addCancelButton` 接入
|
|||
|
|
- 站点选择通过触摸按钮完成,支持滚动翻页,见 [renderLinesSelection](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L735-L796)
|
|||
|
|
- 线上凭证支持两种输入:屏幕软键盘、实体键盘 `char/backspace/enter`,见 [showOnlineVoucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1374-L1420)
|
|||
|
|
- 金额不是文本输入,而是监听右侧红石输入脉冲累加,见 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1114-L1129)
|
|||
|
|
|
|||
|
|
**支付流程**
|
|||
|
|
- 票价计算核心在 [computeCost](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L902-L960),基于 `CFG.fares` 构造普通/特急邻接图后跑最短路
|
|||
|
|
- 订单页会先重算价格,避免旧数据残留,见 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1023-L1037)
|
|||
|
|
- 支付状态 UI 在 [drawOrder](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L998-L1020),显示 `Paid / Remaining` 与进度条
|
|||
|
|
- 实际“收款”逻辑很简单:每次 `redstone.getInput('right')` 从 `false -> true`,`state.paid += 1`,见 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1114-L1129)
|
|||
|
|
- 付满后自动确认;若金额为 0 也会自动确认,见 [confirmAction](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1050-L1082) 与 [auto-confirm](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1108-L1112)
|
|||
|
|
- 当前代码没有接现金/扫码/银行卡 API;支付接入本质上就是把外设回调换成更新 `state.paid`,或重写确认条件
|
|||
|
|
|
|||
|
|
**出票流程**
|
|||
|
|
- 本地新购票:支付满足后 `confirmed=true`,跳到 `done`,见 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1050-L1082)
|
|||
|
|
- 线上凭证兑票:确认时先 POST `/public/orders/{code}/consume`,成功后才进入 `done`,见 [consume voucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1060-L1074)
|
|||
|
|
- 真正出票发生在 [showDone](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1236-L1249):优先调用外设 `ticket_vending_machine.issueTicket(...)`
|
|||
|
|
- 若外设调用失败,则退化为本地生成票号 [generateTicketId](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1162-L1169)
|
|||
|
|
- 出票后会组装 `ticketDataMod` 并上报 `/tickets/sale`,见 [showDone](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1264-L1308) 与 [uploadTicketRecord](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L223-L246)
|
|||
|
|
- 上传失败会写入 `logs/pending_ticket_upload.jsonl`,后台任务自动补传,见 [enqueueTicketUpload](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L248-L259) 和 [backgroundTicketUploadTask](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L339-L354)
|
|||
|
|
|
|||
|
|
**线上预定关联文件**
|
|||
|
|
- 预定页面结构: [ticket-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.html#L120-L244)
|
|||
|
|
- 预定页逻辑: [ticket-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.js#L1-L22) 与 [createOrder](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.js#L406-L451)
|
|||
|
|
- 凭证详情页结构: [token.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.html#L104-L128)
|
|||
|
|
- 凭证详情页逻辑: [token.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.js#L37-L57)
|
|||
|
|
- Web 端创建凭证接口:`POST /api/public/orders`,见 [ticket-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.js#L418-L420)
|
|||
|
|
- 机台兑票查询接口:`GET /public/orders/{code}`,见 [showOnlineVoucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1348-L1370)
|
|||
|
|
|
|||
|
|
**建议接入点**
|
|||
|
|
- 支付外设接入:优先改 [showOrderAndAudio](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1114-L1129),把 `redstone right` 替换为投币器/纸币器/扫码回调,再统一累加到 `state.paid`
|
|||
|
|
- 支付校验扩展:改 [confirmAction](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1050-L1082),可在确认前增加第三方支付结果查询、超时撤单、退款判断
|
|||
|
|
- 出票设备接入:改 [showDone](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1236-L1249),当前已预留 `ticket_vending_machine.issueTicket(...)`,这是最直接硬件接入点
|
|||
|
|
- 售票上报接入:改 [uploadTicketRecord](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L223-L246),适合补充订单号、支付渠道、设备编号、流水号
|
|||
|
|
- 线上订单联动:改 [showOnlineVoucher.submitCode](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1348-L1370) 与 [consume voucher](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1060-L1074),适合加预锁定、核销前校验、重复兑票保护
|
|||
|
|
- 闸机验票联动:下游在 [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua),用于票据进出站核验,适合作为出票后全链路闭环入口
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- `ticketmachine.lua` 已具备完整页面状态机、触摸/键盘交互、基础支付累加、出票外设调用、售票上传与离线补传
|
|||
|
|
- 当前最薄弱的部分是“支付”,本质仍是右侧红石脉冲计数,不是真正支付网关
|
|||
|
|
- 最推荐的三个接入点是:`showOrderAndAudio` 的支付监听、`confirmAction` 的核销确认、`showDone` 的 `issueTicket` 外设调用
|
|||
|
|
|
|||
|
|
如果你需要,我下一步可以继续把这些流程整理成一张“页面/状态/事件/接口”的接入表。
|
|||
|
|
|
|||
|
|
已做一轮完整检索,覆盖 `gate.lua`、售票机 Lua、安装脚本,以及与闸机校验直接对应的服务端路由;结论是:当前 Lua 侧已经有比较清晰的“票卡介质适配层”,可直接扩展为 IC 卡接入。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- 最核心接入点在 [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L479-L670):闸机不直接操作软盘文件,而是依赖 `ticket_inspection_machine` 外设的事件和方法,这里最适合替换/扩展为 IC 卡读写器。
|
|||
|
|
- 售票/发卡接入点在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1236-L1308):售票机通过 `ticket_vending_machine.issueTicket(...)` 下发票据,可平移为“写 IC 卡初始化数据/发新卡”。
|
|||
|
|
- 进出站状态维护分两层:Lua 侧只做事件接收、服务器请求、回写介质;真正的状态判定和扣次在服务端 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L553-L698)。
|
|||
|
|
- 如果要支持 IC 卡,优先保留现有 HTTP 校验协议不变,只替换 Lua 外设层,改造成本最低。
|
|||
|
|
|
|||
|
|
**进出站状态**
|
|||
|
|
- 闸机模式来自 [loadConfig](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L44-L55),支持单向 `mode=entry/exit`,也支持双向 `side_modes`,见 [gate.lua:L422-L471](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L422-L471)。
|
|||
|
|
- 扫描事件入口是 [ticket_scanned](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L672-L682),参数解析在 [parseTicketScannedArgsPacked](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L530-L545)。
|
|||
|
|
- 进/出站动作选择在 [handleScan](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L554-L618):优先按闸机侧别决定,双向且无侧别时会根据票内 `entered/exited` 推断当前是进站还是出站。
|
|||
|
|
- 票状态字段明确使用 `entered`、`exited`、`trips_total`、`trips_remaining`,见 [gate.lua:L559-L600](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L559-L600) 和 [ticketmachine.lua:L1265-L1279](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1265-L1279)。
|
|||
|
|
|
|||
|
|
**票据读写**
|
|||
|
|
- 读票不是 Lua 自己读文件,而是等待外设抛出 `ticket_scanned` 事件,并从事件里拿 `scan` 表,见 [gate.lua:L530-L545](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L530-L545)。
|
|||
|
|
- 票号读取统一走 [getTicketId](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L319-L340),兼容 `ticketId/ticket_id/id` 多种字段。
|
|||
|
|
- 起终点读取统一走 [getStartStation](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L353-L387),兼容多种字段名,也支持从站名反推站码。
|
|||
|
|
- 验票通过后,Lua 侧对介质回写在 [gate.lua:L632-L659](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L632-L659):`updateTicket("entered"/"exited"/"rides", ...)`,以及必要时 `destroyTicket()`。
|
|||
|
|
- 售票写票在 [ticketmachine.lua:L1236-L1249](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1236-L1249):调用 `ticket_vending_machine.issueTicket(...)`,这是发新票/初始化卡片的现成接入点。
|
|||
|
|
|
|||
|
|
**扣费与校验**
|
|||
|
|
- `gate.lua` 自己不做本地票价计算,也不直接扣费;它只向 `/api/tickets/check` 提交 `ticket_id + action + station_codes + trips_*`,见 [postCheck](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L250-L258) 与 [doCheck](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L591-L602)。
|
|||
|
|
- 服务端才是权威校验点:进站校验起点站、是否已进站;出站校验终点站、是否已进站/已出站,并在出站时 `trips_remaining - 1`,见 [api.js:L650-L697](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L650-L697)。
|
|||
|
|
- 服务端返回 `resp.trips_remaining` 与 `resp.destroy_ticket`,Lua 再把剩余次数写回票介质,见 [gate.lua:L632-L659](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L632-L659)。
|
|||
|
|
- 售票后会把票据记录上传到后端,见 [enqueueTicketUpload](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L223-L259) 与 [ticketmachine.lua:L1308-L1310](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1308-L1310)。
|
|||
|
|
|
|||
|
|
**可扩展为 IC 卡的接入点**
|
|||
|
|
- `ticket_inspection_machine` 外设接口是第一接入点,见 [gate.lua:L479-L493](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L479-L493);只要 IC 卡读卡器实现:
|
|||
|
|
- 抛出 `ticket_scanned` 事件,并提供一个 `scan` 表,至少含 `ticket_id/id`,最好再带 `entered/exited/trips_remaining/start_station/terminal_station`。
|
|||
|
|
- 提供 `updateTicket(key, value)`,用于进出站后回写卡内状态。
|
|||
|
|
- 提供 `destroyTicket()`,用于单次票或次数耗尽后的废票/锁卡处理。
|
|||
|
|
- `ticket_vending_machine.issueTicket(...)` 是第二接入点,见 [ticketmachine.lua:L1236-L1249](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1236-L1249);可替换成 IC 发卡器,把新票初始数据写入空卡。
|
|||
|
|
- 安装配置层已支持闸机模式和站点下发,见 [installer.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/installer.lua#L90-L107) 与 [installer_bi.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/installer_bi.lua#L108-L140);无需改协议,只需新增 IC 设备部署说明。
|
|||
|
|
|
|||
|
|
**建议方案**
|
|||
|
|
- 最小改造:保留 [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua) 与后端 `/tickets/check` 协议不变,实现一个兼容 `ticket_inspection_machine` 的 IC 卡外设。
|
|||
|
|
- 如果 IC 卡要做脱机校验,可把 [handleScan](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L554-L670) 中 `doCheck()` 前后拆成“本地预校验 + 在线确认 + 回写卡片”三段。
|
|||
|
|
- 如果要支持储值卡而不是次数票,新增点应放在服务端 `/tickets/check` 与售票记录模型,不建议把扣费逻辑直接塞进 Lua。
|
|||
|
|
- 当前代码最像“票卡介质抽象层”的其实不是文件读写,而是这两个外设接口:`ticket_inspection_machine` 和 `ticket_vending_machine`。
|
|||
|
|
|
|||
|
|
如果你要,我下一步可以直接给你整理一份“IC 卡外设最小接口协议”,按这个项目现有 Lua 调用方式列出函数签名和事件格式。
|
|||
|
|
|
|||
|
|
我已做过一轮较完整的代码检查,覆盖了管理控制台、公开查询/预定页、后端路由、MySQL 持久化,以及售票机侧的线上兑票流程;结论如下。
|
|||
|
|
|
|||
|
|
**现状总览**
|
|||
|
|
- 网页控制台入口是 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L1-L49),已包含“车票记录”“凭证管理”等视图。
|
|||
|
|
- 控制台前端逻辑在 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js#L12-L27);其数据拉取集中在 [index.js:L546-L560](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js#L546-L560),已直接读取 `/api/tickets`、`/api/orders`。
|
|||
|
|
- 公开查询页是 [ticket-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-search.html#L1-L93) + [ticket-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-search.js#L8-L20),调用 `/api/public/tickets` 与 `/api/public/tickets/:id`。
|
|||
|
|
- 线上预定/凭证页是 [ticket-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.js#L9-L21) 和 [token.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.js#L37-L57),调用 `/api/public/orders`、`/api/public/orders/:code`。
|
|||
|
|
- 路由挂载统一在 [server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L29-L33);公开页面 URL 在 [server/index.js:L66-L87](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L66-L87)。
|
|||
|
|
- 数据存储不是 README 里旧的 `web/data/*.json`,而是 MySQL;核心实现是 [data.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L13-L22) 和建表逻辑 [data.js:L47-L60](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L47-L60)。
|
|||
|
|
|
|||
|
|
**当前已存在的票据/兑票结构**
|
|||
|
|
- 票据主索引:`ticket_index`,缓存字段见 [data.js:L35-L39](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L35-L39) 与 [data.js:L335-L375](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L335-L375)。
|
|||
|
|
- 票据事件流:`ticket_events`,写入/读取见 [data.js:L312-L333](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L312-L333)。
|
|||
|
|
- 线上预定凭证:`orders` + `order_index`,创建/查询/消费在 [public.js:L109-L143](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L109-L143)、[public.js:L146-L176](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L146-L176)、[public.js:L178-L215](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L178-L215)。
|
|||
|
|
- 售票机已支持“ONLINE”凭证兑票:入口在 [ticketmachine.lua:L693-L731](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L693-L731),凭证输入与校验在 [ticketmachine.lua:L1338-L1424](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1338-L1424),支付确认后调用消费接口在 [ticketmachine.lua:L1057-L1074](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1057-L1074)。
|
|||
|
|
- 售票后会把票据上传到 `/api/tickets/sale`,离线失败写本地队列 `logs/pending_ticket_upload.jsonl`,见 [ticketmachine.lua:L192-L259](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L192-L259)。
|
|||
|
|
|
|||
|
|
**IC 卡现状**
|
|||
|
|
- 项目里没有独立的 “IC 卡记录 / IC 卡索引 / IC 卡事件” 后端结构。
|
|||
|
|
- 现有模型只有“纸票/电子票 ticket”与“线上凭证 order”;也就是线上兑票已经有,但“兑卡”还没有独立数据层。
|
|||
|
|
|
|||
|
|
**新增 IC 卡记录与线上兑卡,最少需要的文件**
|
|||
|
|
- 后端存储扩展:修改 [data.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js)
|
|||
|
|
- 管理端 API:修改 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)
|
|||
|
|
- 公开端 API:修改 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)
|
|||
|
|
- 控制台页面:修改 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html) 与 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js)
|
|||
|
|
- 若要给用户公开查卡/看兑卡凭证:复用或新增 [token.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.html)、[token.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.js)
|
|||
|
|
- 若售票机直接兑卡:修改 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua)
|
|||
|
|
|
|||
|
|
**建议新增的数据结构**
|
|||
|
|
- `ic_cards`
|
|||
|
|
- `card_id`
|
|||
|
|
- `physical_uid`
|
|||
|
|
- `status` (`active`/`lost`/`disabled`)
|
|||
|
|
- `balance`
|
|||
|
|
- `deposit`
|
|||
|
|
- `holder`
|
|||
|
|
- `bind_order_code`
|
|||
|
|
- `created_ts`
|
|||
|
|
- `updated_ts`
|
|||
|
|
- `ic_card_events`
|
|||
|
|
- `card_id`
|
|||
|
|
- `type` (`issue`/`topup`/`redeem`/`entry`/`exit`/`refund`/`disable`)
|
|||
|
|
- `station_code`
|
|||
|
|
- `device`
|
|||
|
|
- `amount`
|
|||
|
|
- `ticket_id`
|
|||
|
|
- `order_code`
|
|||
|
|
- `ts`
|
|||
|
|
- `ic_order_index` 或复用 `orders`
|
|||
|
|
- 若复用现有 `orders`,建议加字段:
|
|||
|
|
- `fulfill_type: 'ticket' | 'ic_card'`
|
|||
|
|
- `target_card_id`
|
|||
|
|
- `redeem_status`
|
|||
|
|
- `redeemed_ts`
|
|||
|
|
|
|||
|
|
**建议新增的 API 结构**
|
|||
|
|
- 管理端
|
|||
|
|
- `GET /api/ic-cards`
|
|||
|
|
- `GET /api/ic-cards/:id`
|
|||
|
|
- `POST /api/ic-cards`
|
|||
|
|
- `PUT /api/ic-cards/:id`
|
|||
|
|
- `GET /api/ic-cards/:id/events`
|
|||
|
|
- 公开端
|
|||
|
|
- `POST /api/public/ic-orders` 创建线上兑卡订单
|
|||
|
|
- `GET /api/public/ic-orders/:code` 查询兑卡凭证
|
|||
|
|
- `POST /api/public/ic-orders/:code/redeem` 售票机/制卡机兑卡
|
|||
|
|
- 设备端
|
|||
|
|
- 若沿用现有订单体系,也可直接在 `orders` 上扩展 `redeem_target='ic_card'`
|
|||
|
|
|
|||
|
|
**落地建议**
|
|||
|
|
- 最稳妥的做法是:不要硬改现有 `ticket_index`;新增 `ic_cards`、`ic_card_events` 两套表。
|
|||
|
|
- 线上兑卡优先复用现有 `orders/order_index` 流程,只给订单加 `fulfill_type='ic_card'` 和兑卡结果字段。
|
|||
|
|
- 控制台可在现有 “凭证管理” 基础上增加 “IC卡记录” 视图,避免再开一套后台框架。
|
|||
|
|
- 售票机侧已具备线上凭证输入/消费骨架,新增“兑卡”只需要在 [ticketmachine.lua:L1338-L1424](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1338-L1424) 的成功分支里把目标从“出票”改为“写卡/绑卡”。
|
|||
|
|
|
|||
|
|
如果你要,我下一步可以直接按这个检查结果,继续给你整理一份“IC 卡功能改造清单(逐文件到字段级)”。
|
|||
|
|
|
|||
|
|
现有结构已经比较清楚了:Lua 侧有成熟的页面状态机、支付与出票上传链路,后端也有票据与线上凭证模型。接下来我会直接读关键文件,把 IC 卡需要复用和新增的字段、页面、API 精确到函数级,再开始落代码。
|
|||
|
|
|
|||
|
|
我改成分段读取,避免一次性拉太多文件导致 IDE 超时。先把将要修改的函数和路由精确定位出来,再逐段展开读取。
|
|||
|
|
|
|||
|
|
我已经锁定了关键函数和路由位置,现在开始逐段读取并准备改动方案。先从 `ticketmachine.lua` 的页面流和 `data.js` 的存储接口入手,因为这两处会决定前后端字段是否能对齐。
|
|||
|
|
|
|||
|
|
读取工具对这些大文件持续超时,我改用终端按行读取,并顺手检查工作区当前改动,避免误覆盖你已有的内容。
|
|||
|
|
|
|||
|
|
这里有一个关键不确定点:你给的 MOD API 里只明确了 `issueICCard()` 和充值机 `getCardInfo/refill/deduct`,但没有看到“在办卡时写入持有者名/初始余额”以及“检票机读写进站站号”的具体 Lua 接口。
|
|||
|
|
我先继续把现有代码读细,确认哪些地方可以先做;如果最终缺少 MOD 侧读写接口,我会单独把那一处列出来请你补一下函数名。
|
|||
|
|
|
|||
|
|
我继续往前做,不过会把缺失的 MOD 接口影响控制在最小范围内:先把服务端、网页端和售票机办卡流程落好,Lua 检票端则按“卡数据同步到服务端、设备侧尽量兼容现有事件格式”的思路实现。等你补到精确接口名时,只需要替换设备读写那一层。
|
|||
|
|
|
|||
|
|
先梳理 `TicketMachine` 现有 Lua 工程结构,定位办卡、支付、兑卡、闸机扣费和外设事件相关代码,再基于现有流程做兼容式扩展。
|
|||
|
|
|
|||
|
|
先查看 `TicketMachine` 项目的结构和现有网页/后端实现方式,确认应该在什么技术栈和目录下扩展 IC 卡相关功能。
|
|||
|
|
|
|||
|
|
已经定位到 `server` 和 `web` 目录,下一步会读现有数据层、路由和票务页面,沿用当前项目的接口风格与样式结构扩展 IC 卡功能。
|
|||
|
|
|
|||
|
|
已定位到核心文件主要集中在 `ticketmachine.lua` 和 `gate.lua`,接下来读取主流程并搜索现有卡务、支付、同步、外设事件入口。
|
|||
|
|
|
|||
|
|
主流程里目前已有纸票购票和线上券核销基础,但还没有会员卡/IC 卡独立状态与首充支付流程。我在继续查找是否已有服务端卡同步字段或外设读卡事件约定,避免破坏现有事件模型。
|
|||
|
|
|
|||
|
|
现有项目已经有票务、订单和公共查询的雏形,我在继续确认后台单页应用的导航与渲染方式,再把 IC 卡页面无缝接进去。
|
|||
|
|
|
|||
|
|
我在改动前先补齐后台入口与现有订票页的上下文;刚才直接读大文件超时了,改用检索关键片段定位页面和渲染函数。
|
|||
|
|
|
|||
|
|
还需要对齐服务端已有接口字段,尤其是 `/tickets/check` 和线上订单相关返回结构,这样 Lua 侧新增卡务字段才能尽量复用当前同步模型。
|
|||
|
|
|
|||
|
|
我已经确认后台是 Vue 单页,接下来直接抓取 `index.js` 里视图状态和票据模块的关键代码片段,避免盲改导航和渲染逻辑。
|
|||
|
|
|
|||
|
|
我已经确认仓库里还有 Node 服务端代码,接下来直接读服务端入口,核对 Lua 侧要提交的字段名和可复用接口。
|
|||
|
|
|
|||
|
|
当前结构已经够用,我准备开始落地实现:先补数据层和 API,再把后台列表详情与公开查询/购卡页接上现有导航和样式。
|
|||
|
|
|
|||
|
|
先获取后台模板和脚本的精确片段,随后会直接修改导航、数据源与新页面文件。
|
|||
|
|
|
|||
|
|
服务端文件较大,我改用按路由片段抓取,重点看售票上传、检票、订单查询/核销几段实现。
|
|||
|
|
|
|||
|
|
准备按两条线改:
|
|||
|
|
1. `ticketmachine.lua` 增加卡务状态、办卡入口、姓名软键盘、首充金额与支付确认、线上兑卡查询与确认,并把写卡/建卡动作做成“优先调用已存在外设能力,缺失时保留同步与日志”的兼容实现。
|
|||
|
|
2. `gate.lua` 保持 `ticket_scanned` 事件不变,新增 IC 卡识别与服务端同步扣费分支,优先走卡专用同步接口,失败时不影响原纸票检票逻辑,同时把返回的余额/进站站点等字段尽量写回现有 `updateTicket`。开始改 `ticketmachine.lua`,先补通用请求与卡务辅助函数,再接页面流转和确认逻辑。
|
|||
|
|
|
|||
|
|
我在按最小侵入方案设计 IC 卡数据模型:一张卡对应基础信息、状态、余额和事件流;线上购卡会生成订单号并同步落卡,后台直接基于这套记录做列表和详情。
|
|||
|
|
|
|||
|
|
辅助函数已补进主文件,现在先回读最新片段,再接首页入口、卡务页面和确认提交流程,避免和刚才的改动冲突。
|
|||
|
|
|
|||
|
|
首页和卡务子页面已经接上,下一步改确认页与完成页,让票务和卡务共用支付界面,但按不同产品分支处理。
|
|||
|
|
|
|||
|
|
先改服务端数据层,增加 IC 卡主表与事件流,后面的管理和公开页面都会直接复用这套接口。
|
|||
|
|
|
|||
|
|
现在补管理 API:提供 IC 卡列表、详情、建卡、编辑和充值,前端后台页面就能直接接这几个接口。
|
|||
|
|
|
|||
|
|
再补公开 API:支持线上购卡下单、按卡号或订单号查询,以及给购卡页读取卡种配置。
|
|||
|
|
|
|||
|
|
后端数据和公开接口已经补上,接着把新页面路由挂到 Express,保证 IC 卡查询和购卡页可以直接访问。
|
|||
|
|
|
|||
|
|
售票机主线基本串起来了,开始处理 `gate.lua`:保持现有 `ticket_scanned` 事件入口不变,只在识别到 IC 卡字段时切到卡务同步分支。
|
|||
|
|
|
|||
|
|
我改成最小侵入的后台接入方式:在现有控制台侧边栏增加一个独立的 IC 卡管理页入口,这样不用重写原有 Vue 控制台也能保持一致风格。
|
|||
|
|
|
|||
|
|
接下来新增三个页面文件:后台 IC 卡管理页、公开查询页和线上购卡页;页面结构会直接复用现在的深色后台和 JR 风格公开页。
|
|||
|
|
|
|||
|
|
代码已经落到两个 Lua 主文件里,我先跑编辑器诊断看有没有明显语法或引用问题,再决定是否需要补一轮修正。
|
|||
|
|
|
|||
|
|
诊断没报语法问题,但我在回读 `gate.lua` 时发现一个运行时风险:`getCardId()` 提前引用了后面才声明的 `firstNonEmpty()`,这类 Lua 闭包在本文件写法下可能取到全局空值。我先修这个,再做一次最终检查。
|
|||
|
|
|
|||
|
|
语法检查已经过了,环境里没有可直接调用的 `lua/luajit` 解释器,所以验证会以编辑器诊断和静态流程核对为主。我再取一份变更摘要和关键片段行号,方便你对照 review。
|
|||
|
|
|
|||
|
|
再做一处稳健性修正:`writeICCard()` 目前把“调用成功但返回 `false`”也当成写卡成功,我把这个分支收紧,避免外设明确失败时误报完成。
|
|||
|
|
|
|||
|
|
页面文件已经生成,最后补一组很薄的样式扩展,让 IC 卡表单、卡种卡片和后台详情区能贴合现有视觉体系。
|
|||
|
|
|
|||
|
|
我顺手把首页入口补上,让新增的 IC 卡查询和线上购卡页能从门户页直接进入,不会变成隐藏功能。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L915-L1160):首页新增 `CARD` 入口,加入办卡子菜单、姓名输入软键盘、首充金额选择、线上兑卡页。
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1390-L1669):确认页兼容票务/卡务双模式,首充走现有右侧红石支付,线上兑卡支持免现场支付确认。
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1705-L1764):新增卡片完成页与 `logs/last_card_issue.json` 快照记录,保留原纸票完成页。
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L345-L388):补充卡片写卡辅助、卡务同步请求封装、外设方法兼容探测。
|
|||
|
|
- [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L345-L386):新增 IC 卡识别字段解析,兼容 `card_id`、余额、媒体类型等扫描数据。
|
|||
|
|
- [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L626-L717):新增 IC 卡进出站同步扣费分支,按服务端返回写回 `entered/exited/balance/entry_station/exit_station/last_fare`。
|
|||
|
|
- [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L822-L836):主循环继续只监听 `ticket_scanned`,检测到卡数据时切到卡务分支,纸票分支保持原逻辑。
|
|||
|
|
|
|||
|
|
**实现说明**
|
|||
|
|
- 办卡流程:`Home -> CARD -> OPEN CARD -> 姓名输入 -> 首充金额 -> 支付确认 -> 写卡完成`。
|
|||
|
|
- 姓名输入:使用屏幕软键盘与 `char/key` 事件,支持字母、数字、空格,限制 12 字符。
|
|||
|
|
- 首充支付:复用原 `order` 页面与右侧红石投币/支付事件,尽量不改既有外设触发方式。
|
|||
|
|
- 线上兑卡:`CARD -> ONLINE REDEEM` 输入 5 位码,读取 `/public/orders/:code`,识别为卡订单后直接进入确认页。
|
|||
|
|
- 写卡兼容:优先尝试 `issueCard / issueICCard / writeCard / writeICCard / issueTicketData / writeTicketData`,成功后记录快照;明确返回 `false` 时判定写卡失败。
|
|||
|
|
- 闸机扣费:继续走服务端判定模型,只是把纸票 `/tickets/check` 扩到卡片 `/cards/check`,并保留双向闸机的自动进出站推断逻辑。
|
|||
|
|
|
|||
|
|
**假设**
|
|||
|
|
- 服务端提供 `POST /api/cards/open` 用于办卡/线上兑卡建卡,返回可包含 `card_id / balance / deposit / topup`。
|
|||
|
|
- 服务端提供 `POST /api/cards/check`,返回结构尽量仿照现有 `/api/tickets/check`,至少包含 `result`,可选 `reason / balance / fare / entry_station / exit_station`。
|
|||
|
|
- IC 卡介质仍通过现有 `ticket_scanned` 事件上报,只是扫描表里会带 `card_id`、`balance`、`media` 等字段。
|
|||
|
|
- 售票机外设若没有上述写卡方法,则本次实现会停在“写卡失败”而不会伪装成功;同时保留 `logs/last_card_issue.json` 便于后续对接外设。
|
|||
|
|
- 姓名输入按当前 CC:Tweaked 屏幕与键盘能力处理为 ASCII 软键盘,不做中文输入法。
|
|||
|
|
|
|||
|
|
**验证结果**
|
|||
|
|
- 诊断检查:`ticketmachine.lua`、`gate.lua` 的 VS Code 诊断均为 `0` 错误。
|
|||
|
|
- 运行环境检查:当前环境未发现 `lua` 或 `luajit` 可执行文件,无法做本地解释执行验证。
|
|||
|
|
- 静态流程核对:已逐段检查办卡首页流转、姓名输入、首充确认、线上兑卡确认、卡完成页,以及闸机 `ticket_scanned -> isICCardScan() -> handleICCardScan()` 分支闭环。
|
|||
|
|
- 仓库状态:当前目录不是 Git 仓库,无法直接给出 `git diff`/提交号;如果你需要,我可以下一步按这两份文件再整理一版人工 diff 摘要。
|
|||
|
|
|
|||
|
|
**建议下一步**
|
|||
|
|
- 先在服务端补齐或确认 `/api/cards/open`、`/api/cards/check` 的字段名。
|
|||
|
|
- 在真实外设上确认 `ticket_vending_machine` 的写卡方法名;如果你给我外设 API,我可以把兼容探测改成精确调用。
|
|||
|
|
- 如果你希望,我可以继续补一版服务端 `cards` 路由,和网页后台里的卡订单管理。
|
|||
|
|
|
|||
|
|
`home.html` 修改时工具超时了,我改用精确替换的方式更新首页卡片文案和入口,避免影响现有结构。
|
|||
|
|
|
|||
|
|
功能已经接上,下面开始做静态检查和实际启动验证,优先排语法错误和明显的页面脚本问题。
|
|||
|
|
|
|||
|
|
语法检查已通过。现在启动一次本地服务并打几个新接口,确认路由和页面文件都能被服务器正常挂载。
|
|||
|
|
|
|||
|
|
服务正在拉起,我改用更小输出重试状态检查,确认端口和启动日志即可。
|
|||
|
|
|
|||
|
|
新页面请求返回了 `404`,我在看服务端运行日志和实际加载的 `server/index.js`,确认是不是需要重启或有路由没生效。
|
|||
|
|
|
|||
|
|
端口 `23333` 已被现有进程占用,所以我改在 `23334` 启动修改后的版本做独立验证,这样能确认新增路由确实来自本次代码。
|
|||
|
|
|
|||
|
|
新页面路由已经在 `23334` 验证为 `200`。我再补一次接口验证,确认健康检查和新增 IC 卡公开配置接口也可响应。
|
|||
|
|
|
|||
|
|
再做一组端到端验证:调用线上购卡接口生成一张测试卡,再用公开查询接口回查,确认关键流程闭环可用。
|
|||
|
|
|
|||
|
|
我补一个容错修正:让 IC 卡事件流同时写入内存缓存。这样即使本地没起 MySQL,测试环境下也能正常看到详情时间线,不影响正式有库部署。
|
|||
|
|
|
|||
|
|
事件缓存修正已完成,我会重启 `23334` 的验证实例,再确认查询接口能带出事件记录。
|
|||
|
|
|
|||
|
|
**已完成**
|
|||
|
|
- 已在项目中补齐 IC 卡数据存储、管理 API、公开 API、后台列表详情页、公开查询页、线上购卡页,并复用现有深色后台与 JR 风格公开页样式。
|
|||
|
|
- 后端新增 `ic_cards` / `ic_card_events` 数据结构,同时做了内存缓存兜底,便于本地无 MySQL 时继续联调。
|
|||
|
|
- 后台入口已加到现有控制台侧栏,首页也补了 IC 卡相关服务入口。
|
|||
|
|
|
|||
|
|
**修改文件**
|
|||
|
|
- 后端:
|
|||
|
|
- [data.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js)
|
|||
|
|
- [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)
|
|||
|
|
- [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)
|
|||
|
|
- [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js)
|
|||
|
|
- 后台页面:
|
|||
|
|
- [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html)
|
|||
|
|
- [ic-card-admin.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.html)
|
|||
|
|
- [ic-card-admin.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.js)
|
|||
|
|
- 公开页面:
|
|||
|
|
- [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html)
|
|||
|
|
- [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)
|
|||
|
|
- [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)
|
|||
|
|
- [ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html)
|
|||
|
|
- [ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js)
|
|||
|
|
- 样式:
|
|||
|
|
- [style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css)
|
|||
|
|
|
|||
|
|
**新增能力**
|
|||
|
|
- 管理 API:
|
|||
|
|
- `GET /api/ic-cards`
|
|||
|
|
- `GET /api/ic-cards/:id`
|
|||
|
|
- `POST /api/ic-cards`
|
|||
|
|
- `PUT /api/ic-cards/:id`
|
|||
|
|
- `POST /api/ic-cards/:id/topup`
|
|||
|
|
- 公开 API:
|
|||
|
|
- `GET /api/public/ic-cards/config`
|
|||
|
|
- `GET /api/public/ic-cards/query?q=...`
|
|||
|
|
- `GET /api/public/ic-cards/orders/:code`
|
|||
|
|
- `POST /api/public/ic-cards/orders`
|
|||
|
|
- 页面路由:
|
|||
|
|
- `/admin/ic-card`
|
|||
|
|
- `/ic-card/order`
|
|||
|
|
- `/ic-card/search`
|
|||
|
|
|
|||
|
|
**验证结果**
|
|||
|
|
- 语法检查通过:
|
|||
|
|
- `node --check server/index.js`
|
|||
|
|
- `node --check server/routes/api.js`
|
|||
|
|
- `node --check server/routes/public.js`
|
|||
|
|
- `node --check server/services/data.js`
|
|||
|
|
- `node --check web/ic-card-admin.js`
|
|||
|
|
- `node --check web/ic-card-order.js`
|
|||
|
|
- `node --check web/ic-card-search.js`
|
|||
|
|
- 编辑后诊断结果:
|
|||
|
|
- `GetDiagnostics` 返回空,无新增诊断错误。
|
|||
|
|
- 本地服务验证:
|
|||
|
|
- 因现有 `23333` 端口已被占用,验证实例使用 `PORT=23334`
|
|||
|
|
- `GET http://127.0.0.1:23334/ic-card/order` 返回 `200`
|
|||
|
|
- `GET http://127.0.0.1:23334/ic-card/search` 返回 `200`
|
|||
|
|
- `GET http://127.0.0.1:23334/admin/ic-card` 返回 `200`
|
|||
|
|
- `GET http://127.0.0.1:23334/api/public/health` 返回正常
|
|||
|
|
- `GET http://127.0.0.1:23334/api/public/ic-cards/config` 返回卡种配置
|
|||
|
|
- `GET http://127.0.0.1:23334/api/ic-cards` 返回空列表后可正常写入
|
|||
|
|
- `POST /api/public/ic-cards/orders` 已成功生成测试订单与卡号
|
|||
|
|
- `GET /api/public/ic-cards/query?q=卡号/订单号` 已成功回查,并能返回事件流
|
|||
|
|
- `POST /api/ic-cards` 与 `GET /api/ic-cards/:id` 已成功验证后台建卡与详情读取
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 本机 `127.0.0.1:3306` 当前未启动 MySQL,启动日志里有 `ECONNREFUSED`;因此本次运行验证主要依赖新增的内存缓存兜底。
|
|||
|
|
- 正式环境只要 MySQL 可用,代码已会自动建表并写入 `ic_cards`、`ic_card_events`。
|
|||
|
|
|
|||
|
|
两块改动都已经落下来了。我先在主会话里做一次交叉核对,确认新增的 IC 路由、页面入口和 Lua 页面状态都在项目里,并补跑一次诊断,避免子任务改完后还有漏项。
|
|||
|
|
|
|||
|
|
我做交叉核对时发现一个需要马上确认的点:Lua 侧现在已经调用了 `/api/cards/open` 和 `/api/cards/check`,但我还要再检查服务端是否真的暴露了这两个设备接口,避免页面改完但机台联不起来。
|
|||
|
|
|
|||
|
|
我确认到一个真实问题了:目前后端有 `ic-cards` 的管理和公开页面接口,但还没有机台/闸机直接调用的 `/api/cards/open`、`/api/cards/check` 设备接口。
|
|||
|
|
这会导致网页能用、Lua 机台却打不到后端。我现在补这一层,让售票机办卡和闸机扣费真正闭环。
|
|||
|
|
|
|||
|
|
我要补两个设备端关键点:一是线上兑卡查询改成优先走新的 IC 卡公开接口,避免机台还去查旧票据凭证;二是后端补出 `/api/cards/open` 和 `/api/cards/check`,把办卡、进站、出站扣费都接上。
|
|||
|
|
|
|||
|
|
先查看 `api.js` 和 `ticketmachine.lua` 的现状,确认现有卡务接口、扣费流程,以及线上兑卡当前调用链,再进行最小范围修改和验证。
|
|||
|
|
|
|||
|
|
已定位到服务端路由和 Lua 客户端文件,接下来读取相关实现,确认 `/public/ic-cards/orders/:code` 现有返回结构以及当前线上兑卡分支如何落到本地逻辑。
|
|||
|
|
|
|||
|
|
文件直读超时了,我先用内容检索切出关键片段,定位新增接口应插入的位置,以及 Lua 里当前兑卡查询顺序。
|
|||
|
|
|
|||
|
|
已经锁定到关键行号,但编辑前还需要把这些行附近的代码完整取出来。我改用终端分段读取,避免 IDE 读大文件超时。
|
|||
|
|
|
|||
|
|
关键片段已经拿到一部分。现在继续补齐 `tickets/check`、`cards/open` 调用方和 `ticketmachine.lua` 的兑卡分支,这样就能准确对齐请求/响应字段。
|
|||
|
|
|
|||
|
|
现在已经能看到服务器和终端两端的关键入口。下一步会对齐 `gate.lua` 期望的 `/api/cards/check` 响应格式,然后在 `api.js` 里补足对应卡片状态流转。
|
|||
|
|
|
|||
|
|
准备开始改文件前,我先确认工作区是否已有未提交改动,避免覆盖你现有编辑;然后会按最小补丁方式更新 `api.js` 和 `ticketmachine.lua`。
|
|||
|
|
|
|||
|
|
准备写入 `api.js`:会新增卡片下发与检票两个接口,并复用现有 `DataService`/`LogicService`,保证返回结构能直接被 `ticketmachine.lua` 和 `gate.lua` 消费。
|
|||
|
|
|
|||
|
|
接着修改 `ticketmachine.lua` 的兑卡查询顺序,只动线上兑卡入口,先查卡单接口,再回退旧票券接口,避免影响普通车票兑换流程。
|
|||
|
|
|
|||
|
|
代码已写入。现在回读关键片段确认没有插错位置,再做语法/诊断检查与最小验证。
|
|||
|
|
|
|||
|
|
语法诊断已经通过。为了补一层验证,我再做一次 JS 语法检查,并确认路由已按现有 `server/index.js` 的 `/api` 挂载方式生效。
|
|||
|
|
|
|||
|
|
关键改动和验证都完成了,我再补一遍精确位置,方便你直接点开对应代码。
|
|||
|
|
|
|||
|
|
**修改结果**
|
|||
|
|
- 在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L724-L1026) 新增了 `POST /cards/open` 与 `POST /cards/check` 两个接口,实际挂载路径是 `/api/cards/open` 与 `/api/cards/check`,挂载位置见 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L29-L33)。
|
|||
|
|
- 在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L77-L129) 补了卡单号、金额、车站解析等辅助方法,供新卡务接口复用。
|
|||
|
|
- 在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1091-L1112) 调整了线上兑卡逻辑,先查 `/public/ic-cards/orders/:code`,失败后再回退 `/public/orders/:code`,并对非 `pending_pickup` 的卡单直接提示 `Already Used!`。
|
|||
|
|
|
|||
|
|
**接口行为**
|
|||
|
|
- `POST /api/cards/open`
|
|||
|
|
- 支持本地办卡:生成或激活 `card_id`,落库为 `active`,记录开卡事件。
|
|||
|
|
- 支持线上兑卡:按 `voucher_code/order_code` 查找 `pending_pickup` 卡单,兑卡成功后改为 `active`,写入兑卡站点、设备、余额等信息。
|
|||
|
|
- 已兑过的线上卡单会返回 `409`,Lua 端会显示 `Already Used!`。
|
|||
|
|
- `POST /api/cards/check`
|
|||
|
|
- 支持 IC 卡进站:记录 `entry_station`、进站时间与当前卡状态。
|
|||
|
|
- 支持 IC 卡出站:按 `entry_station -> 当前站` 调用现有票价逻辑扣费,返回 `fare`、`balance/remaining_balance`、`entry_station`、`exit_station`。
|
|||
|
|
- 对 `not_found`、`already_entered`、`not_entered`、`already_exited`、`insufficient_balance`、`fare_not_found` 等情况返回 `result: 'deny'`,与 `gate.lua` 当前处理方式兼容。
|
|||
|
|
|
|||
|
|
**验证情况**
|
|||
|
|
- `api.js` 通过 `node --check` 语法检查。
|
|||
|
|
- `GetDiagnostics` 检查 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js) 与 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua) 均无诊断错误。
|
|||
|
|
- 已确认新接口会被现有 `/api` 路由挂载,不需要额外改 `server/index.js`。
|
|||
|
|
|
|||
|
|
**补充说明**
|
|||
|
|
- 这次验证是静态语法与编辑器诊断级别,未做带真实卡数据/站点票价数据的联机跑单。
|
|||
|
|
- 如果你要,我下一步可以继续帮你补一组最小联调用例,直接给出 `curl` 或 `PowerShell Invoke-RestMethod` 的办卡、兑卡、进站、出站验证脚本。
|
|||
|
|
|
|||
|
|
**已完成**
|
|||
|
|
- 已把 IC 储蓄卡主流程接进项目:售票机办卡、首次充值支付、检票机进出站扣费、网页后台记录、公开查询、线上购卡与机台兑卡。
|
|||
|
|
- 售票机首页新增 `CARD` 入口,支持“办卡”和“线上兑卡”,办卡流程含持有人输入、首充金额选择、支付确认、出卡完成页,主改动在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L930-L970)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L977-L1079)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1474-L1669)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1705-L1733)。
|
|||
|
|
- 线上兑卡已改为优先查询新的 IC 卡订单接口,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1091-L1112)。
|
|||
|
|
- 检票机已增加 IC 卡分支,支持根据进站站号和当前站号计算路费并扣减余额,再把结果写回卡数据,主改动在 [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L554-L670) 和 [gate.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/gate.lua#L672-L682)。
|
|||
|
|
- 后端已补齐 IC 卡存储和设备接口,包括 `/api/cards/open`、`/api/cards/check`、后台 `/api/ic-cards*`、公开 `/api/public/ic-cards*`,主改动在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L524-L668)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L724-L1026)、[public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L191-L425)、[data.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L50-L96)、[data.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/services/data.js#L267-L347)。
|
|||
|
|
- 网页端已新增后台卡管理页、公开购卡页、公开查卡页,并接入现有站点风格与路由,主改动在 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html)、[home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html)、[ic-card-admin.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.html)、[ic-card-admin.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.js)、[ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html)、[ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js)、[style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css)。
|
|||
|
|
- 服务端页面路由也已补上,见 [server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L68-L83)。
|
|||
|
|
|
|||
|
|
**关键说明**
|
|||
|
|
- 机台写卡这一层做了兼容探测,会按顺序尝试 `issueCard`、`issueICCard`、`writeCard`、`writeICCard`、`issueTicketData`、`writeTicketData`,实现位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L345-L388)。
|
|||
|
|
- 这是为了兼容你目前给出的 MOD 信息不完整的情况;也就是说,服务端与网页闭环已经补齐,但如果 MOD 最终实际写卡函数名不同,还需要把这层适配精确收口一次。
|
|||
|
|
- 进出站状态提示仍沿用现有逻辑,`already_entered`、`not_entered`、`already_exited` 这类提示链路没有拆掉,只是新增了卡的余额与扣费分支。
|
|||
|
|
- 卡数据会同步写入服务端,并记录事件流,后台与公开查询都能查到。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- 我做了主会话交叉核对,确认新入口和新路由已经落在代码里,关键命中包括 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1096-L1096)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L724-L724)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L860-L860)。
|
|||
|
|
- 全局 `GetDiagnostics` 返回空,没有看到新增诊断错误。
|
|||
|
|
- 之前子任务里也完成了 Node 语法检查和页面/API 基本联通检查。
|
|||
|
|
|
|||
|
|
**残余风险**
|
|||
|
|
- 最大风险仍然是 MOD 侧真实的“写卡/回写卡字段”函数签名未最终确认;现在代码已按兼容方式实现,但如果你那边的真实接口名、参数顺序、返回字段不同,需要再做一次精准对接。
|
|||
|
|
- 目前售票机姓名输入是 ASCII 软键盘,不支持中文输入法;如果你要中文持有人名,需要 MOD 或 CC 侧另给输入方案。
|
|||
|
|
- 如果你愿意,下一步我可以直接继续做两件事中的任意一件:
|
|||
|
|
- 给你一份“MOD 侧最终应提供的精确接口清单”,你发给做 MOD 的人即可。
|
|||
|
|
- 给你一组联调脚本,按“办卡 -> 兑卡 -> 进站 -> 出站”完整跑通。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
现在有好多内容都出现了乱码!请修复
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先定位哪些文件出现了编码乱码,重点检查刚改过的网页、Lua 和后端文件里的中文文本,再逐个修复成统一编码内容。
|
|||
|
|
|
|||
|
|
我先排除了 `node_modules` 里的无关命中。现在重点看项目自身文件,尤其是网页页头有没有缺少 UTF-8 声明,以及哪些中文文本已经被写坏。
|
|||
|
|
|
|||
|
|
已经确认至少 `web/home.html` 的中文文本本身被写坏了,不是浏览器编码声明问题;`web/index.html` 只有一处注释/注释尾部残缺。
|
|||
|
|
我继续扫描公开页面和脚本里是否还有类似 `鍙`、`绗`、`鏈` 这类乱码串,然后统一修复。
|
|||
|
|
|
|||
|
|
我已经定位到主要乱码源就在 `web/home.html`,内容像是被错误编码后又保存了一次。我直接把这页的中文文案全部重写为正常 UTF-8,同时顺手修掉几个被截断的标签文本。
|
|||
|
|
|
|||
|
|
`home.html` 的主体乱码已经换回正常中文了。我再做一轮扫描,把剩余的残留乱码和注释损坏一并清掉,然后检查有没有因此引入语法问题。
|
|||
|
|
|
|||
|
|
现在只剩 `web/index.html` 里一处注释残留乱码,虽然不影响显示,但我把它也修掉,保持文件干净。
|
|||
|
|
|
|||
|
|
**已修复**
|
|||
|
|
- 主要乱码来源确认是 [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html),这不是浏览器编码声明缺失,而是文件内容本身已经被错误编码后保存了。
|
|||
|
|
- 我已经把这页的中文文案全部恢复为正常 UTF-8,包括标题、导航、首页说明、服务卡片、提醒文案、票价图/线路图提示和页脚备案号。
|
|||
|
|
- 同时清理了 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html) 里残留的一处乱码注释。
|
|||
|
|
|
|||
|
|
**修改文件**
|
|||
|
|
- [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html)
|
|||
|
|
- [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html)
|
|||
|
|
|
|||
|
|
**检查结果**
|
|||
|
|
- 再次扫描 `web` 目录后,项目自身网页文件里已没有同类乱码残留。
|
|||
|
|
- [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html) 的诊断结果为空。
|
|||
|
|
- [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html) 的诊断结果也为空。
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 这次确认到的乱码集中在首页 [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html),其他我本轮扫描到的网页、Lua、JS 文件没有发现同类坏字串。
|
|||
|
|
- 如果你现在浏览器里还有页面显示乱码,通常是浏览器缓存或服务器还在提供旧文件;建议先强刷一次页面。
|
|||
|
|
|
|||
|
|
**建议**
|
|||
|
|
- 先重点刷新首页、线上购卡页、IC 卡查询页确认显示是否正常。
|
|||
|
|
- 如果你还看到别的页面有乱码,直接把页面路径发我,我可以继续逐页清。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
还是有乱码字符 `div`
|
|||
|
|
线上购卡的css失效了 `https://ticket.fse-media.group/ic-card/order`
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先做两件事并行确认:一是继续扫描 `home.html` 是否还有漏掉的乱码文本,二是检查 `ic-card/order` 页面为什么样式没生效,重点看 HTML 引用、CSS 文件、以及线上实际页面加载情况。
|
|||
|
|
|
|||
|
|
我已经看到一个很像根因的问题:`ic-card/order` 页面里 CSS 用的是相对路径 `style.css?v=6`,在 `/ic-card/order` 这个地址下会被浏览器解析成 `/ic-card/style.css?v=6`,这很可能直接 404。
|
|||
|
|
我再用浏览器和线上请求确认一下,然后一并修复相对路径和剩余乱码。
|
|||
|
|
|
|||
|
|
问题确认了两点:
|
|||
|
|
1. `线上购卡` 样式失效的根因就是 CSS 路径写成了相对路径,线上实际请求了 `https://ticket.fse-media.group/ic-card/style.css`,而这个地址返回 `Cannot GET`。
|
|||
|
|
2. `home.html` 里还残留了一处乱码文本 `绾胯矾璧勬簮`。
|
|||
|
|
|
|||
|
|
我现在直接修这两个点。
|
|||
|
|
|
|||
|
|
我又确认到一个更完整的原因:`线上购卡` 不只是 CSS,相对路径的 `logo.png`、`ic-card-order.js`、`public-status.js` 也都会在 `/ic-card/order` 下解析错。
|
|||
|
|
所以这次我会把公开页面里所有静态资源统一改成站点根路径,避免同类问题反复出现。
|
|||
|
|
|
|||
|
|
我已经把公开页面的静态资源路径统一改成绝对路径了,这样 `/ic-card/order`、`/ic-card/search` 这类带子路径的页面就不会再把 CSS 和脚本请求到错误地址。
|
|||
|
|
接下来我做一轮快速验证,确认没有残留相对路径和新语法问题。
|
|||
|
|
|
|||
|
|
**已修**
|
|||
|
|
- 修掉了 `home.html` 里残留的乱码文案,`绾胯矾璧勬簮` 已恢复为“线路资源”,位置在 [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html)。
|
|||
|
|
- 修掉了 `线上购卡` 样式失效的根因:`/ic-card/order` 页面原来用的是相对路径 `style.css?v=6`,浏览器实际请求成了 `https://ticket.fse-media.group/ic-card/style.css`,线上返回了 `Cannot GET /ic-card/style.css`。
|
|||
|
|
- 现在已把公开页面静态资源统一改成根路径,避免带子路径的页面再次把资源请求错位置。
|
|||
|
|
|
|||
|
|
**已改文件**
|
|||
|
|
- [home.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/home.html)
|
|||
|
|
- [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)
|
|||
|
|
- [ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html)
|
|||
|
|
- [ticket-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-order.html)
|
|||
|
|
- [ticket-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-search.html)
|
|||
|
|
- [token.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/token.html)
|
|||
|
|
|
|||
|
|
**修复内容**
|
|||
|
|
- 把 `href="style.css?...` 改为 `href="/style.css?...`
|
|||
|
|
- 把 `src="logo.png"` 改为 `src="/logo.png"`
|
|||
|
|
- 把 `public-status.js`、`ic-card-order.js`、`ic-card-search.js`、`ticket-order.js`、`ticket-search.js`、`token.js` 改为根路径引用
|
|||
|
|
- 这样 `/ic-card/order` 和 `/ic-card/search` 不会再去请求 `/ic-card/style.css`、`/ic-card/ic-card-order.js` 这类错误地址
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- 我直接验证了线上请求:
|
|||
|
|
- `https://ticket.fse-media.group/ic-card/style.css?v=6` 当前确实返回 `Cannot GET /ic-card/style.css`
|
|||
|
|
- `https://ticket.fse-media.group/style.css?v=6` 可以正常返回 CSS
|
|||
|
|
- 修改后的几个 HTML 文件诊断都为空,没有新增语法错误
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 你现在浏览器里还能看到那个乱码 `div`,大概率是页面还没重新加载到最新文件,或者线上站点还没重新部署/重载静态文件。
|
|||
|
|
- 代码层面这两个问题都已经修好了;如果线上 URL 还是旧表现,需要让当前服务重新读到这些改动。
|
|||
|
|
|
|||
|
|
**下一步**
|
|||
|
|
- 先强制刷新 `home` 和 `https://ticket.fse-media.group/ic-card/order`
|
|||
|
|
- 如果这是你本机运行的 Node 服务,重启一下站点进程
|
|||
|
|
- 如果你愿意,我可以继续把其他仍使用相对静态资源路径的页面也一并扫完,例如 `blog.html`、`ticket-route.html`、`login.html`,一次性消掉同类隐患
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
购卡界面去掉卡类型,改成首次充值:5、10、15、20、自定义,去掉备注,去掉联系电话,然后持卡人名改成只能英文+符号,去掉押金
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先改线上购卡这一套:页面表单、前端校验和后端下单字段一起收口,确保“卡类型/备注/联系电话/押金”都真正去掉,不只是前端隐藏。
|
|||
|
|
|
|||
|
|
我已经确认线上购卡页和公开下单接口目前都还带着“卡类型、押金、备注、联系电话”这套旧逻辑。现在把它们一起改成“首次充值”模式,并把姓名限制改成英文+符号校验。
|
|||
|
|
|
|||
|
|
我会顺手把公开查询页里和这次规则冲突的“卡种、押金、备注”展示也收一下,避免用户购卡后在查询页又看到旧概念。
|
|||
|
|
|
|||
|
|
我把界面结构改成“首次充值按钮 + 自定义金额”,并同步把前后端字段削到只剩 `holder_name` 和 `initial_balance`,这样规则不会前端后端不一致。
|
|||
|
|
|
|||
|
|
我已经把公开购卡页和后端下单接口都改成“首次充值”模型了。现在做一轮语法和残留字段检查,确认前端没有还在引用被删掉的 `phone`、`note`、`card_type`。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- 线上购卡页去掉了“卡类型”“备注”“联系电话”,改成“首次充值”模式,支持 `5 / 10 / 15 / 20 / 自定义`,改动在 [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html) 和 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)。
|
|||
|
|
- 持卡人姓名现在限制为“英文 + 常用符号”,不允许中文和数字;前端和后端都做了校验,后端规则在 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)。
|
|||
|
|
- 押金已从线上购卡逻辑中移除,购卡金额现在等于首次充值金额;公开下单接口也不再使用 `phone`、`note`、`card_type` 作为必需/核心字段,见 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L191-L196) 和 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L357-L425)。
|
|||
|
|
- 公开查询页同步去掉了“押金”和“备注”展示,改为显示“首次充值”,见 [ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js#L47-L65)。
|
|||
|
|
|
|||
|
|
**现在的购卡规则**
|
|||
|
|
- 卡片固定按 `IC 储值卡` 处理,不再让用户选卡种。
|
|||
|
|
- 首次充值可直接点 `5 / 10 / 15 / 20`,也可切到“自定义”手输金额。
|
|||
|
|
- 持卡人姓名必须匹配英文和常用符号格式,例如 `Alex Smith`、`A.Brown`、`Chris-O'Neil`。
|
|||
|
|
- 押金固定为 `0`,实付金额就是首次充值金额。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js)、[public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js) 的诊断均为空。
|
|||
|
|
- `node --check` 校验 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js) 通过。
|
|||
|
|
|
|||
|
|
**提醒**
|
|||
|
|
- 线上站点要看到新表单,需要重载当前服务或重新部署静态文件。
|
|||
|
|
- 如果你还想把后台 `IC 卡管理` 里的“卡种 / 联系电话 / 押金 / 备注”也一起删掉,我可以下一步继续统一那一页。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
继续统一
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我继续把后台 `IC 卡管理` 一并统一到新规则,重点清掉“卡种、联系电话、押金、备注”相关表单和展示,保留持卡人姓名、状态、余额这几个真正还在使用的字段。
|
|||
|
|
|
|||
|
|
我把后台这边也按同一套规则收口:建卡只保留“持卡人姓名 + 初始余额”,详情只保留“姓名 + 状态 + 余额”,其余旧字段全部从界面上撤掉。必要的话,我也会顺手把后台接口默认值改成和公开购卡一致。
|
|||
|
|
|
|||
|
|
后台页面和后台 API 已经按新规则收口了。现在做最后一轮残留字段扫描和语法检查,确认没有再引用旧的 `联系电话 / 卡种 / 押金 / 备注` 输入。
|
|||
|
|
|
|||
|
|
**已统一**
|
|||
|
|
- 后台 `IC 卡管理` 现在也按同一规则收口了,不再出现“卡种、联系电话、押金、备注”这套旧字段。
|
|||
|
|
- 快速建卡只保留 `持卡人姓名(仅英文与符号)` 和 `初始余额`,改动在 [ic-card-admin.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.html)。
|
|||
|
|
- 后台详情页只保留 `持卡人 / 卡片类型(固定显示 IC 储值卡)/ 状态 / 余额`,并把摘要区补成“首次充值 + 购卡金额”,改动在 [ic-card-admin.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.js)。
|
|||
|
|
- 后台列表里的卡片副标题也统一成 `持卡人 · IC 储值卡`,不再根据旧 `card_type` 显示月票卡/纪念卡。
|
|||
|
|
|
|||
|
|
**接口同步**
|
|||
|
|
- 后台 API 现在也统一默认按 `IC 储值卡` 处理,建卡和更新都不再接受前端传入的 `phone / note / deposit / card_type` 作为主逻辑字段,改动在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)。
|
|||
|
|
- 后台建卡和编辑同样加入了“持卡人姓名仅支持英文与常用符号”的校验,和公开购卡页保持一致。
|
|||
|
|
- 后台卡片列表搜索也去掉了对 `phone`、`note` 的依赖。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ic-card-admin.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.html)、[ic-card-admin.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.js)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js) 诊断均为空。
|
|||
|
|
- `node --check` 校验 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js) 已通过。
|
|||
|
|
- 我也额外扫过后台页面代码,已没有 `createPhone`、`createType`、`detailPhone`、`detailType`、`detailDeposit`、`detailNote` 这类旧字段残留。
|
|||
|
|
|
|||
|
|
**当前统一结果**
|
|||
|
|
- 公开购卡页:只填持卡人姓名,选择首次充值金额。
|
|||
|
|
- 公开查询页:不再展示押金、备注。
|
|||
|
|
- 后台管理页:不再编辑卡种、联系电话、押金、备注。
|
|||
|
|
- 后台和公开端:都使用同一套英文姓名校验规则。
|
|||
|
|
|
|||
|
|
**如果继续**
|
|||
|
|
- 现在还可以再统一一层:把设备端 `/api/cards/open` 里残留的 `phone / note / deposit / card_type` 兼容字段也进一步收窄成纯“姓名 + 余额”模型。
|
|||
|
|
- 如果你要,我下一步就继续清这一层。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
没有显示出充值配置 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
|
|||
|
|
at ic-card-order.js:167:22
|
|||
|
|
at ic-card-order.js:182:3
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先对照 `ic-card-order.html` 和 `ic-card-order.js` 定位是哪一个元素 ID 没对上,再补一层空值保护,避免单个 DOM 缺失就直接把整页脚本打挂。
|
|||
|
|
|
|||
|
|
我确认这更像是“线上实际 HTML 还是旧版、JS 已经是新版”造成的前后不匹配:旧页面没有 `#customInitialBalance`,新版脚本一绑定事件就炸了。
|
|||
|
|
我现在把 `ic-card-order.js` 做成向后兼容,能同时兼容新旧 DOM,避免线上缓存/灰度状态下直接白屏。
|
|||
|
|
|
|||
|
|
我已经把线上购卡脚本改成兼容新旧页面结构了:即使线上还在缓存旧 HTML,也不会因为找不到新 ID 直接抛错。再做一轮诊断确认没有手滑引入新问题。
|
|||
|
|
|
|||
|
|
**已修**
|
|||
|
|
- 这个报错的根因是线上页面很可能还是旧版 HTML,而浏览器拿到了新版 `ic-card-order.js`。
|
|||
|
|
- 新版脚本会找 `#customInitialBalance` 和 `#rechargeOptionList`,但旧版页面只有 `#initialBalance` 和 `#planList`,所以在绑定 `addEventListener` 时直接对 `null` 调用了方法。
|
|||
|
|
|
|||
|
|
**这次改动**
|
|||
|
|
- 我把 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js) 改成了兼容新旧 DOM:
|
|||
|
|
- `#rechargeOptionList` 不存在时,自动回退到旧的 `#planList`
|
|||
|
|
- `#customInitialBalance` 不存在时,自动回退到旧的 `#initialBalance`
|
|||
|
|
- 如果关键节点仍然缺失,会先 `console.error` 并安全退出,不再整页脚本崩掉
|
|||
|
|
- 旧页面里残留的 `联系电话`、`备注` 输入框会被脚本自动禁用并隐藏,避免旧 HTML 和新逻辑混在一起
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js) 诊断为空,没有新增错误。
|
|||
|
|
|
|||
|
|
**你现在应该看到的效果**
|
|||
|
|
- 即使线上还是旧 HTML,页面也不该再报 `Cannot read properties of null (reading 'addEventListener')`
|
|||
|
|
- 充值配置应该能正常渲染出来
|
|||
|
|
- 旧的“联系电话/备注”如果还在缓存页面里,也会被隐藏掉
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 这属于典型的“HTML 和 JS 部署版本不一致”问题。
|
|||
|
|
- 代码侧我已经做了兼容,但如果你想完全干净,还是建议把线上静态页面一起更新并清缓存。
|
|||
|
|
|
|||
|
|
**建议**
|
|||
|
|
- 强刷 `https://ticket.fse-media.group/ic-card/order`
|
|||
|
|
- 如果服务端有静态缓存/CDN,也一起清掉
|
|||
|
|
- 如果刷新后还有问题,我可以继续帮你直接排线上实际返回的 HTML 和 JS 是否版本不一致
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
现在似乎cc端没有正确传给售票方块出卡参数,导致没有正常出卡。
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先对照售票机 Lua 里“购票正常出票”的调用方式,检查办卡分支到底传了哪些参数给 `ticket_vending_machine`,再和你给的 MOD API `issueICCard()` 对比,找出哪里少传或传错了。
|
|||
|
|
|
|||
|
|
我基本锁定根因了:当前 CC 端 `writeICCard()` 是按“带参数写卡”去试 `issueICCard` 的,但你最早给的 MOD API 里 `issueICCard()` 是**无参**。
|
|||
|
|
这就很可能导致外设方法被调用时参数不匹配,最终根本没成功出卡。我先把这一层改成优先按真实无参 API 调用,再兼容旧的猜测式写法。
|
|||
|
|
|
|||
|
|
我发现这块不只是“参数不对”,还有更深一层的问题:如果 MOD 的 `issueICCard()` 真的是**无参并返回真实卡号**,那现在 CC 端是“先向服务端开卡,再尝试往方块写卡”,顺序也反了。
|
|||
|
|
正确闭环应该更像“先让售票方块实际出卡拿到真实 `cardId`,再把这个 `cardId` 连同姓名/余额同步到服务端”。我先确认 `firstString()` 这类工具函数怎么取返回值,再按这个思路改。
|
|||
|
|
|
|||
|
|
我按“真实无参 `issueICCard()` 优先”的方式改:先让方块出卡拿到物理 `cardId`,再把这个 `cardId` 发给服务端建卡/兑卡。旧的“带参数写卡”逻辑保留作兼容后备。
|
|||
|
|
|
|||
|
|
我已经把办卡/兑卡的出卡顺序改成“优先真实无参 `issueICCard()` 出物理卡,再把返回的 `cardId` 同步给服务端”。同时保留了旧的参数写卡逻辑作为后备,避免兼容老实现时直接失效。
|
|||
|
|
|
|||
|
|
**已修方向**
|
|||
|
|
- 我已经把 CC 端出卡流程改成更符合你给的 MOD API:
|
|||
|
|
- 先调用售票方块的无参 `issueICCard()` 尝试**实际出卡**
|
|||
|
|
- 拿到它返回的真实 `cardId`
|
|||
|
|
- 再把这个 `cardId + 持卡人 + 余额` 发给服务端 `/cards/open`
|
|||
|
|
- 只有当无参出卡接口不存在或失败时,才回退到之前那套“服务端先建卡,再尝试参数写卡”的兼容逻辑
|
|||
|
|
|
|||
|
|
**为什么之前会出问题**
|
|||
|
|
- 你给的 API 是 `local ok, cardId = vm.issueICCard()`
|
|||
|
|
- 但原来的 `ticketmachine.lua` 把 `issueICCard` 当成“可带参数写卡”的方法来试,这很容易导致外设调用参数不匹配,最终不出卡
|
|||
|
|
- 更严重的是,原来顺序是“先服务端生成卡号,再让方块出卡”,如果方块自己返回了一个真实 `cardId`,那物理卡号和服务端卡号还会错位
|
|||
|
|
|
|||
|
|
**这次改动**
|
|||
|
|
- 新增了物理出卡 helper,在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L372-L382)
|
|||
|
|
- 调整了办卡确认分支,优先走“先出卡再同步”,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1523-L1592)
|
|||
|
|
- 旧的 `writeICCard()` 仍保留为 fallback,并补了一些兼容字段和无参尝试,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L387-L413)
|
|||
|
|
|
|||
|
|
**现在行为**
|
|||
|
|
- 如果 `ticket_vending_machine.issueICCard()` 正常返回 `true, cardId`
|
|||
|
|
- 会直接用这个 `cardId` 去服务端开卡/兑卡
|
|||
|
|
- 这样服务端和实体卡号一致
|
|||
|
|
- 如果物理卡已经出了,但服务端同步失败
|
|||
|
|
- 页面会显示 `Issued, sync failed: ...`
|
|||
|
|
- 不会误报“办卡成功”
|
|||
|
|
- 如果方块出了卡但没返回 `cardId`
|
|||
|
|
- 页面会显示 `Card issued without ID`
|
|||
|
|
- 方便你继续判断 MOD 侧返回值是否异常
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua) 诊断为空,没有新增语法问题。
|
|||
|
|
|
|||
|
|
**建议你现在测试**
|
|||
|
|
- 在 CC 端实际点一次办卡
|
|||
|
|
- 看售票机屏幕提示是否从之前的写卡失败,变成正常 `Card ready`
|
|||
|
|
- 如果还不行,优先看两件事:
|
|||
|
|
- `issueICCard()` 是否真的返回了 `true, cardId`
|
|||
|
|
- 物理卡出了以后,服务端 `/cards/open` 是否返回成功
|
|||
|
|
|
|||
|
|
**如果继续排**
|
|||
|
|
- 我下一步可以直接给你加一版更明确的现场调试输出:
|
|||
|
|
- 在 CC 屏幕或 `logs/last_card_issue.json` 里把 `issueICCard()` 的返回值、方法名、最终提交给 `/cards/open` 的 `cardId` 都打印出来
|
|||
|
|
这样就能马上判断是“方块没出卡”,还是“出了卡但没回传卡号”,还是“服务端同步失败”。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
还是方块没出卡,你先确定这里的代码没有问题
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我按代码审查方式只看这条链路:`ticketmachine.lua` 里办卡确认 → 调用售票方块 → 同步 `/cards/open`。先把相关代码和服务端接口完整读一遍,再给你结论,优先找“必然导致不出卡/错卡”的问题。
|
|||
|
|
|
|||
|
|
我还要核对一件关键事:正常出票 `issueTicket(...)` 是怎么调用的,以及 `ticketVendingMachine` 这个外设对象到底是怎么拿到的。这样才能判断现在 `issueICCard()` 的调用方式是不是和现有外设包装层一致。
|
|||
|
|
|
|||
|
|
我已经抓到至少一个会直接影响“没出卡却被当成成功分支处理”的硬问题,现在做第二遍交叉验证,避免把猜测当结论给你。
|
|||
|
|
|
|||
|
|
先定位 `ticketmachine.lua` 和 `server/routes/api.js` 中办卡、兑卡与 `/cards/open` 的实现,再沿着调用链核对 `card_id` 的来源、落库逻辑,以及同步失败后的重试/去重控制。
|
|||
|
|
|
|||
|
|
先查看 `ticketmachine.lua` 里这两个函数及其调用链,核实返回值约定和失败回退路径,再给出逐条审查结论。
|
|||
|
|
|
|||
|
|
已经定位到关键判断:两处都用 `r1 ~= false` 作为成功条件,我继续查卡片开户流程里失败后的补偿/回退逻辑,确认是否会出现“没出卡但流程已成功/已扣款”的后果。
|
|||
|
|
|
|||
|
|
回退链路也查过了:当前卡开户分支只有 `submitCardOpen` 正向调用,没有对应撤销/退款/作废分支;接下来我按“是否会把 `nil` 当成功、是否会导致不出卡不回退”分别给出结论和等级。
|
|||
|
|
|
|||
|
|
我已经看到终端机分成两条路径:一条先出空白卡再调 `/cards/open`,另一条先调接口再写卡。接下来补看服务端 `upsert` 与订单索引逻辑,确认线上兑卡是否真的保留设备上报的 `card_id`,以及“同步失败后重试”会不会再放一张新卡。
|
|||
|
|
|
|||
|
|
我在补读辅助函数时遇到一次读取超时,改成更小范围继续取证。重点会放在 `normalizeIcCardId`、`findIcCardByOrderCode`、`upsertIcCard`,这些能直接决定是否覆盖 `card_id` 和是否允许重复兑卡。
|
|||
|
|
|
|||
|
|
补充看了一下服务端路由,`/cards/open` 存在,但暂时没看到与这条开卡调用成对的回滚接口;我再取一小段路由确认一下,避免把“前端无回退”误说成“系统绝对无回退”。
|
|||
|
|
|
|||
|
|
**发现**
|
|||
|
|
- `严重`:`writeICCard` 的成功判断会把 `nil` 误判为成功;一旦外设方法“正常返回但首返回值是 nil”,代码仍会走成功分支,直接把订单标记为 `confirmed = true` 并显示 `Card ready`,即使实际没有写卡/出卡。[ticketmachine.lua:L362-L364](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L362-L364) [ticketmachine.lua:L1611-L1617](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1611-L1617)
|
|||
|
|
- `结论`:这里的 `nil` 返回会被误判为成功,且会导致“可能没出卡却不回退”。更严重的是,`submitCardOpen(payload)` 在写卡前已把服务端卡状态创建/激活,当前 `ticketmachine.lua` 中没有对应撤销/退款/回退逻辑。[ticketmachine.lua:L1594-L1617](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1594-L1617) [api.js:L729-L818](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L729-L818)
|
|||
|
|
- `高`:`issueBlankICCard` 的成功判断同样会把 `nil` 误判为成功;但它的后果和 `writeICCard` 不完全一样。这里不会直接把 UI 标成成功,而是进入 `elseif okIssueBlank` 分支,报 `Card issued without ID`,同时跳过后续 `submitCardOpen + writeICCard` 的后备路径。[ticketmachine.lua:L378-L380](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L378-L380) [ticketmachine.lua:L1568-L1592](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1568-L1592)
|
|||
|
|
- `结论`:`issueBlankICCard` 的 `nil` 返回也会被误判为成功;如果这个 `nil` 实际表示“未出空白卡/未拿到有效结果”,当前流程不会回退付款,也不会进入后备写卡路径,结果是订单停在失败态但没有补偿逻辑,属于“支付后可能不出卡且不回退”。[ticketmachine.lua:L1568-L1594](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1568-L1594)
|
|||
|
|
|
|||
|
|
**流程图**
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
A[确认开卡] --> B[issueBlankICCard]
|
|||
|
|
B -->|pcall成功 且 r1=nil| C[被判定为 okIssueBlank=true]
|
|||
|
|
C --> D{blankCardId 是否为空}
|
|||
|
|
D -->|为空| E[显示 Card issued without ID]
|
|||
|
|
E --> F[不走 submitCardOpen/writeICCard]
|
|||
|
|
F --> G[无回退/退款逻辑]
|
|||
|
|
|
|||
|
|
B -->|返回 false| H[submitCardOpen]
|
|||
|
|
H --> I[writeICCard]
|
|||
|
|
I -->|pcall成功 且 r1=nil| J[被判定为 okWrite=true]
|
|||
|
|
J --> K[confirmed=true + Card ready]
|
|||
|
|
K --> L[即使未实际写卡/出卡也结束交易]
|
|||
|
|
|
|||
|
|
style C fill:#fff3e0,color:#e65100
|
|||
|
|
style E fill:#fff3e0,color:#e65100
|
|||
|
|
style J fill:#ffcdd2,color:#b71c1c
|
|||
|
|
style K fill:#ffcdd2,color:#b71c1c
|
|||
|
|
style G fill:#ffcdd2,color:#b71c1c
|
|||
|
|
style L fill:#ffcdd2,color:#b71c1c
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**审查表**
|
|||
|
|
| No. | Issue Title | Suggestion | Code Link |
|
|||
|
|
|-----|-------------|------------|-----------|
|
|||
|
|
| 1 | `严重` `writeICCard` 经由 `callPeripheralMethods` 将 `nil` 当成功,可能未写卡却显示成功 | 成功条件改为“显式成功值”或“显式拿到有效卡标识/写卡结果”,不要用 `r1 ~= false`;同时在 `submitCardOpen` 成功但写卡失败时增加补偿逻辑 | [ticketmachine.lua:L362-L364](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L362-L364), [ticketmachine.lua:L1611-L1617](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1611-L1617) |
|
|||
|
|
| 2 | `高` `issueBlankICCard` 将 `nil` 当成功,导致跳过后备路径并卡死已支付交易 | `issueBlankICCard` 仅在返回明确成功信号时才置 `okIssueBlank=true`;若无卡号,应继续尝试后备路径或进入补偿/退款流程,而不是停在“issued without ID” | [ticketmachine.lua:L378-L380](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L378-L380), [ticketmachine.lua:L1568-L1592](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1568-L1592) |
|
|||
|
|
|
|||
|
|
**补充说明**
|
|||
|
|
- `nil` 会被误判为成功,这一点是代码语义上可以直接确认的,因为 Lua 中 `nil ~= false` 为真。
|
|||
|
|
- 两处问题的区别在于:`issueBlankICCard` 的误判更像“内部成功态误判,阻断后续分支”;`writeICCard` 的误判则是“最终用户可见成功误判”,风险更高。
|
|||
|
|
- 就当前代码范围看,确实存在“可能不出卡却不回退”的结果;其中 `writeICCard` 路径是最明确、最严重的一条。
|
|||
|
|
|
|||
|
|
如果你要,我可以下一步直接把这两处成功判断改成“只接受显式成功返回”,并补一个最小化的失败补偿方案。
|
|||
|
|
|
|||
|
|
关键证据已经比较清楚了:线上卡订单在下单时就预生成了 `card_id`,而终端兑卡时又会先从设备拿真实空白卡号再上报。如果 `/cards/open` 不接纳这个真实卡号,就会出现“数据库里是预生成号,实体卡上是设备号”的错位;我再补一眼 `/cards/check` 的查卡逻辑,确认这个错位会不会直接导致刷卡失败。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
A[线上下单生成待领卡订单] --> B[public.js 预生成 card_id]
|
|||
|
|
B --> C[终端兑卡先从设备拿空白卡真实 card_id]
|
|||
|
|
C --> D[/cards/open 兑卡分支]
|
|||
|
|
D --> E[沿用订单原 card_id]
|
|||
|
|
E --> F[返回旧 card_id 给终端]
|
|||
|
|
F --> G[数据库 card_id 与实体卡真实 card_id 错位]
|
|||
|
|
|
|||
|
|
H[终端确认办卡/兑卡] --> I[先 issueBlankICCard 出卡]
|
|||
|
|
I --> J[再调用 /cards/open 同步]
|
|||
|
|
J --> K{同步失败?}
|
|||
|
|
K -->|是| L[仅提示 Issued, sync failed]
|
|||
|
|
L --> M[processing=false 且 confirmed=false]
|
|||
|
|
M --> N[CONFIRM 再次可点]
|
|||
|
|
N --> I
|
|||
|
|
|
|||
|
|
style B fill:#bbdefb,color:#0d47a1
|
|||
|
|
style E fill:#fff3e0,color:#e65100
|
|||
|
|
style G fill:#ffcdd2,color:#b71c1c
|
|||
|
|
style I fill:#f3e5f5,color:#7b1fa2
|
|||
|
|
style L fill:#fff3e0,color:#e65100
|
|||
|
|
style N fill:#ffcdd2,color:#b71c1c
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- `1. 严重` 线上兑卡会忽略设备返回的 `card_id`。
|
|||
|
|
结论:`会`。在线订单在创建时就预生成了一个 `card_id`,[public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L366-L382);终端兑卡时先从设备拿到真实空白卡号并放进 `payload.card_id`,[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1568-L1574)。但 `/cards/open` 的兑卡分支只用 `findIcCardByOrderCode()` 找到原订单后直接 `upsert {...current, ...}`,没有把 `body.card_id` 写回卡记录,因此仍保留订单原来的 `card_id`,[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L743-L800)。随后终端又优先采用服务端返回的 `respData.card_id` 覆盖本地显示值,[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1571-L1578)。而后续验卡是按上报的 `card_id` 直接查索引,[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L865-L878),所以一旦设备真实卡号与订单预生成号不一致,就会形成“实体卡号和后台卡号错位”。
|
|||
|
|
|
|||
|
|
- `2. 严重` 同步失败后允许重复出卡。
|
|||
|
|
结论:`允许`。无论办新卡还是兑卡,终端在确认时都会先执行 `issueBlankICCard()` 出卡,再调用 `/cards/open` 同步,[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1554-L1590)。如果同步失败,代码只是提示 `Issued, sync failed`,没有落本地待补偿队列,也没有把本次出卡锁死;随后 `processing` 被清回 `false`,`confirmed` 仍是 `false`,`CONFIRM` 按钮重新可点,[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1654-L1680)。同时当前工程的离线补偿队列只覆盖车票上传,不覆盖卡开卡/兑卡,[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L246-L313) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L480-L487)。这意味着操作员重试时会再次先出一张新卡;若第一次其实已被服务端受理但响应丢失,第二次重试在兑卡场景会先出第二张卡再收到 `409 already redeemed`,在普通开卡场景还可能直接生成第二张有效卡。
|
|||
|
|
|
|||
|
|
**补充**
|
|||
|
|
- 未看到能够推翻上述两点的保护逻辑。
|
|||
|
|
- 这两个问题都不是纯日志/展示问题,都会影响线上实体卡与后台状态的一致性。
|
|||
|
|
- 如需,我可以下一步直接给出修复方案,或按“先修 `card_id` 错位 / 先修重复出卡”分别落代码。
|
|||
|
|
|
|||
|
|
我已经确认:这段代码目前**还不能说没问题**,而且有两处是会直接影响实体卡流程的硬问题。
|
|||
|
|
我先把问题按严重级别列清楚,再由你选是一起修还是先修最影响出卡的那一处。
|
|||
|
|
|
|||
|
|
你这边已经选了“全部修复”,我就直接动手。
|
|||
|
|
这次我会同时修 3 件事:`nil` 误判成功、线上兑卡忽略真实 `card_id`、同步失败后重复点确认会再次出卡。
|
|||
|
|
|
|||
|
|
我要顺手确认一下 `DataService.upsertIcCard()` 在“在线兑卡时替换 `card_id`”这个场景下是否会清理旧索引;如果不会,我会一起补上,避免后台里残留旧卡号脏数据。
|
|||
|
|
|
|||
|
|
我现在开始改 Lua 主流程,重点是让“重试只重试同步、不再重复出卡”,并把外设成功判断收严成“必须显式成功”。
|
|||
|
|
|
|||
|
|
Lua 侧第一轮已改完。接着补服务端 `/cards/open` 的兑卡分支,把设备真实 `card_id` 接住并替换旧预生成卡号,避免实体卡和后台错位。
|
|||
|
|
|
|||
|
|
我补一处刚才顺手写错的服务端语法:把误写成 Lua 的 `~=` 改回 JS 比较,并顺便把旧卡号变量提出来,避免重复归一化。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- 这段代码原来**不是没问题**,我确认到了 3 个会影响实体卡流程的硬问题,并且已经全部修掉。
|
|||
|
|
- 现在这条链路从静态代码上看已经顺了:外设成功判断更严格、线上兑卡会接住真实 `card_id`、同步失败后不会再次重复出卡。
|
|||
|
|
- 语法和诊断已通过:`ticketmachine.lua` 与 `api.js` 都无诊断错误,`node --check` 也通过。
|
|||
|
|
|
|||
|
|
**本次修复**
|
|||
|
|
- `nil` 误判成功已修:外设调用现在只接受“显式成功返回”,不再把 `nil` 当成功,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L356-L383)。
|
|||
|
|
- 同步失败重复出卡已修:如果空白卡已经出过但服务端同步失败,后续重试会复用同一张已出的卡号,只重试同步,不会再调用方块重新出卡,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1574-L1633)。
|
|||
|
|
- 线上兑卡卡号错位已修:`/cards/open` 的兑卡分支现在会采用设备返回的真实 `card_id`,并清理旧的预生成卡号记录,位置在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L755-L805)。
|
|||
|
|
|
|||
|
|
**流程图**
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
A[CC 确认办卡/兑卡] --> B{已有待同步空白卡号?}
|
|||
|
|
B -->|否| C[调用 issueICCard 出实体卡]
|
|||
|
|
B -->|是| D[复用上次 blank card_id]
|
|||
|
|
C --> E{返回显式成功且有 card_id}
|
|||
|
|
E -->|是| F[/cards/open 同步服务端]
|
|||
|
|
E -->|否| G[停在失败态,不误判成功]
|
|||
|
|
D --> F
|
|||
|
|
F -->|成功| H[Card ready]
|
|||
|
|
F -->|失败| I[保留 pendingBlankCardId,仅重试同步]
|
|||
|
|
style C fill:#bbdefb,color:#0d47a1
|
|||
|
|
style F fill:#c8e6c9,color:#1a5e20
|
|||
|
|
style G fill:#ffcdd2,color:#b71c1c
|
|||
|
|
style I fill:#fff3e0,color:#e65100
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**我确认过的关键点**
|
|||
|
|
- 成功判断:`r1 ~= false` 已改成“`r1` 不能是 `nil/false`”,避免外设没回值时被当成成功。
|
|||
|
|
- 重试逻辑:同步失败后会记住 `pendingBlankCardId`,下一次 `CONFIRM` 不会再出第二张卡。
|
|||
|
|
- 在线兑卡:服务端不再死守下单时预生成的卡号,而是跟随设备真实卡号。
|
|||
|
|
|
|||
|
|
**现在如果还不出卡,优先怀疑代码外因素**
|
|||
|
|
- `ticket_vending_machine` 外设没有被 `peripheral.find('ticket_vending_machine')` 找到。
|
|||
|
|
- MOD 实际方法名/返回值和你给的文档不一致,比如 `issueICCard()` 并不返回 `true, cardId`。
|
|||
|
|
- 售票方块出卡前还有额外前置条件,例如库存、朝向、内部槽位、红石状态或实体卡物品未就绪。
|
|||
|
|
|
|||
|
|
**下一步最有效**
|
|||
|
|
- 我建议直接再加一轮运行时日志,把这 4 个值打印出来:
|
|||
|
|
- `ticketVendingMachine` 是否存在
|
|||
|
|
- `issueICCard` 是否存在
|
|||
|
|
- `pcall(issueICCard)` 的原始返回值
|
|||
|
|
- 最终提交到 `/cards/open` 的 `card_id`
|
|||
|
|
- 这样就能马上把问题切成“代码流程问题”还是“MOD/外设行为问题”。
|
|||
|
|
|
|||
|
|
**状态**
|
|||
|
|
- 这轮代码我已经改完。
|
|||
|
|
- 如果你愿意,我下一步直接给你把 CC 端调试日志也补上,专门抓“为什么方块没出卡”。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
IC卡网页控制台端可以正常收到信息,也能看到卡号、持卡人。但是订单号那里显示“---”。而且页面上还是有联系方式,请删除。然后加一个“删除卡”的按钮。然后把这个IC卡管理的页合并到/admin页
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先检查后台页面结构和 IC 卡管理页现状,重点看 3 件事:订单号为什么显示 `---`、联系方式残留在哪里、以及现在 `/admin` 和独立 IC 卡页是怎么分开的。
|
|||
|
|
|
|||
|
|
我已经确认独立的 IC 卡页就是现在那套后台界面。接下来我会把它并到现有主控制台页,同时补上删除接口和删除按钮,再顺手查订单号为什么总是空。
|
|||
|
|
|
|||
|
|
我在看主控制台的 Vue 结构,判断是直接并一块原生区域,还是把现有 IC 卡逻辑迁进 Vue。优先会选改动更小但不别扭的方案。
|
|||
|
|
|
|||
|
|
我准备直接把 IC 卡管理迁进主控制台的 Vue 页,不走 iframe。这样 `/admin` 里能原生切标签、共享现有刷新逻辑,也方便加“删除卡”按钮和统一样式。
|
|||
|
|
|
|||
|
|
我开始改主控制台模板,把独立的 IC 卡区块直接并进去,同时会让旧地址 `/admin/ic-card` 自动落到这个新视图,不再维持两套后台入口。
|
|||
|
|
|
|||
|
|
主控制台里的 IC 卡视图已经嵌进去了。现在我先重新读一遍刚改过的 `index.js`,再补最后几处导出和路由改动,避免在同一文件上踩掉刚才的上下文。
|
|||
|
|
|
|||
|
|
我再补两层后端收口:去掉 IC 卡记录里的联系方式字段,并加删除卡接口。顺手把旧 `/admin/ic-card` 入口指向新的 `/admin` 视图。
|
|||
|
|
|
|||
|
|
我已经把主界面、后台接口和旧入口路由都串起来了。现在做最后一轮检查,确认 `index.html/index.js/api.js/server/index.js` 没有新报错,也确认后台页里不再残留“联系方式”。
|
|||
|
|
|
|||
|
|
最后我再抓一下关键改动的定位行,方便你直接点开看:主控制台入口、IC 卡视图、删除接口和旧路由跳转。
|
|||
|
|
|
|||
|
|
**已调整**
|
|||
|
|
- IC 卡管理已并入主控制台 `/admin`,侧边栏不再跳独立页,而是在主控制台内切换到 `IC 卡管理` 视图,改动在 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L43-L45) 和 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L455-L590)。
|
|||
|
|
- 订单号显示已改成优先读取 `order_code / voucher_code / code`,如果本来就是现场办卡没有线上订单,则显示“现场办卡”,不再一律是 `---`,逻辑在 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js#L355-L365)。
|
|||
|
|
- 后台页中的“联系方式”已去掉;我也确认新的 `/admin` 页面代码里已经没有 `联系方式 / 联系电话 / phone` 残留。
|
|||
|
|
- 卡片详情区新增了“删除卡”按钮,前端逻辑在 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L528-L531) 和 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js#L712-L721)。
|
|||
|
|
|
|||
|
|
**接口变更**
|
|||
|
|
- 新增后台删除接口 `DELETE /api/ic-cards/:id`,会删除卡记录并记一条删除事件,位置在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L703-L721)。
|
|||
|
|
- `cards/open` 这条卡开卡接口里不再继续写 `phone`,位置在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L751-L849)。
|
|||
|
|
|
|||
|
|
**路由合并**
|
|||
|
|
- 旧入口 `/admin/ic-card` 现在会跳转到 `/admin?view=iccards`,位置在 [server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L71-L72)。
|
|||
|
|
- 旧兼容入口 `/ic-card-admin` 也同样跳转到新的主控制台视图,位置在 [server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L78-L81)。
|
|||
|
|
- 主控制台脚本会自动识别 `view=iccards` 并直接打开 IC 卡管理页,位置在 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js#L14-L20)。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html)、[index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)、[server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js) 诊断均为空。
|
|||
|
|
- `node --check` 已通过 [index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.js) 和 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)。
|
|||
|
|
- 我额外扫过合并后的后台页面代码,没再找到 `联系方式 / 联系电话 / phone`。
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 独立文件 `ic-card-admin.html/js` 还保留在仓库里,但运行时入口已经并回 `/admin` 了,用户访问旧地址会自动跳到新视图。
|
|||
|
|
- 如果你愿意,我下一步可以继续把这两个旧文件也彻底清理掉,避免以后误维护两套页面。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
在出卡的时候持卡人name是否正确传给mod
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我直接核对办卡这条调用链里“持卡人姓名”从页面状态到 `ticket_vending_machine` 外设调用的传递路径,重点确认有没有真正作为参数传到 MOD。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- 按你现在给的 MOD API 来看,**持卡人 `name` 在主流程里没有直接传给 MOD 出卡方法**。
|
|||
|
|
- 当前代码的“优先路径”是先调无参 `issueICCard()` 出空白卡,这一步**不带姓名参数**,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L372-L385) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1578-L1587)。
|
|||
|
|
- `holder_name` 目前是先组进本地 `payload`,然后发给你的网站后端 `/cards/open`,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1561-L1573) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1584-L1588)。
|
|||
|
|
|
|||
|
|
**现在的实际行为**
|
|||
|
|
- 姓名来源:`state.holderName` 会写进 `payload.holder_name`,见 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1561-L1563)。
|
|||
|
|
- 主出卡调用:`issueBlankICCard()` 只做 `pcall(fn)`,没有任何参数,见 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L375-L383)。
|
|||
|
|
- 服务端同步:姓名会跟着 `payload` 提交给 `/cards/open`,所以网页控制台能看到持卡人姓名,这和你观察到的一致。
|
|||
|
|
|
|||
|
|
**只有哪种情况会传给 MOD**
|
|||
|
|
- 只有走到后备路径 `writeICCard(finalCard)` 时,代码才会尝试把姓名传给外设。
|
|||
|
|
- 这里会把 `holder_name` 填进 `payload.owner`、`payload.card_holder`,并尝试多种参数形式调用外设,见 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L391-L412)。
|
|||
|
|
- 例如它会尝试:
|
|||
|
|
```lua
|
|||
|
|
{ payload }
|
|||
|
|
{ tostring(payload.holder_name or ''), tonumber(payload.initial_balance) or 0 }
|
|||
|
|
{ tostring(payload.card_id or ''), tostring(payload.holder_name or ''), ... }
|
|||
|
|
```
|
|||
|
|
- 但这只是**兼容性后备**,不是当前你这套 `issueICCard()` API 的主流程。
|
|||
|
|
|
|||
|
|
**所以答案是**
|
|||
|
|
- 如果 MOD 真实接口就是你发的:
|
|||
|
|
```lua
|
|||
|
|
local ok, cardId = vm.issueICCard()
|
|||
|
|
```
|
|||
|
|
- 那么答案是:**没有,姓名没有在“出卡给 MOD”这一步传进去。**
|
|||
|
|
- 目前姓名只进了后端记录,没有确定写进实体 IC 卡的数据区。
|
|||
|
|
|
|||
|
|
**建议**
|
|||
|
|
- 如果你希望“出卡时就把持卡人名写进卡里”,MOD 侧还需要提供明确的写卡接口,比如:
|
|||
|
|
- `issueICCard(holderName, balance)`
|
|||
|
|
- 或 `issueICCard()` 后再 `writeCardData(cardId, data)`
|
|||
|
|
- 如果你要,我下一步可以直接把 CC 端改成“只支持你最终确认的 MOD 写卡接口”,把这层彻底收口,不再靠兼容猜测。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
调用是:
|
|||
|
|
vm.issueICCard("<name>")
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我按你刚确认的真实调用签名把 CC 端收口到 `vm.issueICCard("<name>")`,这样主出卡路径会把持卡人姓名直接传给 MOD,不再走无参猜测。
|
|||
|
|
|
|||
|
|
我已经把主流程改成按姓名参数出卡了,同时把后备写卡路径也补上了“单参数姓名”这一种调用形式,避免 `issueICCard(name)` 被别的参数组合打偏。现在做一轮语法检查。
|
|||
|
|
|
|||
|
|
**已改**
|
|||
|
|
- 现在主出卡调用已经按你给的真实签名改成:`vm.issueICCard("<name>")`。
|
|||
|
|
- 也就是说,持卡人姓名现在会在“出卡给 MOD”这一步直接传入,不再是之前的无参调用。
|
|||
|
|
|
|||
|
|
**具体改动**
|
|||
|
|
- `issueBlankICCard()` 改成接收 `holderName`,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L376-L388)。
|
|||
|
|
- 主办卡确认分支现在会把 `payload.holder_name` 传给它,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1584-L1585)。
|
|||
|
|
- 后备写卡路径也补上了单参数调用形式 `{ holder_name }`,这样如果走到兼容分支,也会优先尝试 `issueICCard(name)`,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L404-L413)。
|
|||
|
|
|
|||
|
|
**现在的实际行为**
|
|||
|
|
- 办卡页输入的姓名先进入 `payload.holder_name`
|
|||
|
|
- 然后主流程调用:
|
|||
|
|
```lua
|
|||
|
|
ticketVendingMachine.issueICCard(payload.holder_name)
|
|||
|
|
```
|
|||
|
|
- 如果这种调用失败,代码才会退回到旧的兼容尝试
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua) 诊断为空,没有新增错误。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- 现在可以明确说:**持卡人 name 已经会正确传给 MOD 出卡方法**。
|
|||
|
|
- 如果接下来还是“不出卡”或“卡里名字不对”,问题就更可能在 MOD 侧实现,而不是这里没把参数传过去。
|
|||
|
|
|
|||
|
|
**如果你要继续排**
|
|||
|
|
- 我下一步可以再把这次调用的运行时参数直接写到 `logs/last_card_issue.json` 或屏幕调试输出里,确认现场实际传出去的名字字符串到底是什么。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
办卡充值时不要计算手续费、押金等内容。就直接是充值多少付多少钱。
|
|||
|
|
|
|||
|
|
然后网页查询那里支持查询凭证码
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先收口两处逻辑:CC 办卡支付金额只按首充金额计算,以及网页查询把“凭证码”也作为 IC 卡查询入口。随后会把前后端一起对齐。
|
|||
|
|
|
|||
|
|
我看到查询页目前只认 `card_id / order_code`,还没把线上购卡返回的“凭证码/兑换码”纳入匹配。我再把购卡下单返回字段和服务端存储字段核对一下,一并修成可按凭证码查。
|
|||
|
|
|
|||
|
|
我已经定位到 CC 端办卡金额仍然沿用了旧的 `deposit + topup` 计算。我现在把这套金额模型直接改成“首充即实付”,并同步把公开查询文案和后端匹配都加上“凭证码”。
|
|||
|
|
|
|||
|
|
金额逻辑和查询入口都已经改完。我现在做检查,确认 Lua 和网页脚本没有新报错,同时抓一下关键位置方便你直接点开看。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- 办卡充值现在不再计算手续费、押金等附加项,实付金额就是首充金额,改动在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L775-L790)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L810-L824)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L843-L883)。
|
|||
|
|
- CC 办卡确认页也去掉了押金显示,只保留 `Top-up / Balance / Order`,并且 `Order` 现在等于首充金额,见 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1457-L1468) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1523-L1531)。
|
|||
|
|
- 网页 IC 卡查询现在支持按 `卡号 / 订单号 / 凭证码` 查询,后端匹配已补上,见 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L298-L325)。
|
|||
|
|
- 查询页文案、输入提示和结果展示也已同步加入“凭证码”,见 [ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html#L46-L70) 和 [ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js#L47-L64)。
|
|||
|
|
|
|||
|
|
**现在的行为**
|
|||
|
|
- 现场办卡:付 `5` 就充 `5`,付 `10` 就充 `10`,不再额外加押金。
|
|||
|
|
- 线上购卡查询:如果你拿到的是 IC 卡订单生成的凭证码,也可以直接在查询页输入。
|
|||
|
|
- 查询结果里会显示“凭证码”字段;当前若没有单独存 `voucher_code`,会回退显示已有的 `order_code`。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua)、[public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)、[ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html)、[ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js) 诊断均为空。
|
|||
|
|
- `node --check` 已通过 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)。
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 你现在如果在线上页面还看不到新查询提示,通常是静态文件缓存;强刷 `IC 卡查询` 页即可。
|
|||
|
|
- 如果你还想更彻底一点,我下一步可以把后台 `/admin` 里的 IC 卡搜索框也一起扩成支持“凭证码”检索。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
把后台 /admin 里的 IC 卡搜索框也一起扩成支持“凭证码”检索。
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先把 `/admin` 的 IC 卡搜索链路看一遍,确认是前端占位文案要改,还是后台 `/api/ic-cards?q=` 本身还没把“凭证码”纳入检索。
|
|||
|
|
|
|||
|
|
后台接口这边确实还没把 `voucher_code/code` 纳入过滤;前端占位文案也还是旧的。我直接一起补上。
|
|||
|
|
|
|||
|
|
我再做一轮检查,确认 `/api/ic-cards?q=` 和 `/admin` 的 IC 卡页都没有新问题。
|
|||
|
|
|
|||
|
|
**已支持**
|
|||
|
|
- `/admin` 里的 IC 卡搜索框现在也支持按“凭证码”检索。
|
|||
|
|
- 后台接口 `/api/ic-cards?q=` 已把 `voucher_code` 和 `code` 纳入搜索字段,改动在 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L589-L598)。
|
|||
|
|
- 前端输入框提示文案也同步改成“搜索卡号 / 订单号 / 凭证码 / 姓名”,位置在 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L520-L522)。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js) 和 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html) 诊断均为空。
|
|||
|
|
- `node --check` 已通过 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js)。
|
|||
|
|
|
|||
|
|
**说明**
|
|||
|
|
- 现在后台 IC 卡列表可按 `card_id / order_code / voucher_code / code / holder_name / source` 命中。
|
|||
|
|
- 如果线上数据里“凭证码”实际仍是写在 `order_code`,这次改动也兼容,不会影响原有搜索。
|
|||
|
|
|
|||
|
|
**建议**
|
|||
|
|
- 强刷一下 `/admin?view=iccards` 后测试一张线上购卡记录的凭证码。
|
|||
|
|
- 如果你愿意,我还可以继续把后台 IC 卡列表里那行“订单 xxx”文案也改成“订单/凭证 xxx”,避免展示上看起来像只能搜订单号。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
售票机办卡的时候也要传入余额参数:
|
|||
|
|
issueICCard(ownerName, initialBalance) — 第二参数可选,默认 0。
|
|||
|
|
vm.issueICCard("张三", 50) -- 开卡,余额 50
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我把售票机办卡主调用再收口一次,改成按你最新确认的签名传 `name + initialBalance`,并同步检查后备分支的参数顺序。
|
|||
|
|
|
|||
|
|
我顺手扫到办卡金额选择页里还有一处旧公式残留,仍在用 `押金 + 充值`。这次会一起修掉,避免界面金额和实际出卡参数不一致。
|
|||
|
|
|
|||
|
|
我开始改 `ticketmachine.lua`:主出卡改成 `issueICCard(name, initialBalance)`,并把办卡金额页里残留的押金公式和提示一起清干净。
|
|||
|
|
|
|||
|
|
主调用已经改完了。我现在做一轮诊断,确认 Lua 没有语法问题,并把关键位置抓出来给你确认。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- 售票机办卡主调用现在会把“持卡人姓名 + 初始余额”一起传给 MOD:
|
|||
|
|
- `vm.issueICCard(ownerName, initialBalance)`
|
|||
|
|
- 对应改动在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L376-L394) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1562-L1593)。
|
|||
|
|
|
|||
|
|
**现在的实际调用**
|
|||
|
|
- 主流程会调用:
|
|||
|
|
```lua
|
|||
|
|
issueBlankICCard(payload.holder_name, payload.balance)
|
|||
|
|
```
|
|||
|
|
- 而 `issueBlankICCard()` 内部优先尝试:
|
|||
|
|
```lua
|
|||
|
|
ticketVendingMachine.issueICCard(holderName, initialBalance)
|
|||
|
|
```
|
|||
|
|
- 位置分别在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L384-L389) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1582-L1585)。
|
|||
|
|
|
|||
|
|
**兼容处理**
|
|||
|
|
- 如果 `issueICCard(name, balance)` 失败,代码还会回退尝试:
|
|||
|
|
- `issueICCard(name)`
|
|||
|
|
- `issueICCard()`
|
|||
|
|
- 这样既满足你现在确认的真实签名,也不会把旧兼容路径直接砍掉。
|
|||
|
|
|
|||
|
|
**顺手修正**
|
|||
|
|
- 办卡充值页里残留的旧公式也一起修了,不再出现 `押金 + 充值` 的计算。
|
|||
|
|
- 现在 `Need Pay` 直接等于首充金额,位置在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1077-L1090)。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua) 诊断为空,没有新增错误。
|
|||
|
|
|
|||
|
|
**结论**
|
|||
|
|
- 现在 CC 端已经会按你给的最新接口,把姓名和余额一起传给 MOD 出卡。
|
|||
|
|
- 如果接下来实体卡余额仍不对,就更像是 MOD 侧没有正确使用第二参数,而不是 CC 端没传。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
线上购卡这里没有正确出五位凭证码,出了一个ICO-xxxx,请修改。
|
|||
|
|
然后一些订单信息的字颜色要醒目一些。
|
|||
|
|
|
|||
|
|
我希望卡片信息也有一个单独的界面,类似电子客票。
|
|||
|
|
在ticket.fse-media.group/ic/<卡号>
|
|||
|
|
|
|||
|
|
cc的屏幕键盘要加上符号的按钮
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先核对 4 条链路:线上购卡凭证码生成规则、购卡结果页样式、独立卡片详情页路由,以及 CC 办卡软键盘的按键布局。
|
|||
|
|
|
|||
|
|
我看到一个关键不一致:CC 线上兑卡当前就只接受 5 位码,但网页购卡后端还在生成 `ICO-xxxxxx`。我会把后端和结果页一起改成统一的 5 位凭证码,并顺手把乱码 HTML 一并清掉。
|
|||
|
|
|
|||
|
|
我再看一下现有的 5 位凭证码生成器和“电子客票”样式,尽量复用现成的设计语言,不新造一套。
|
|||
|
|
|
|||
|
|
我已经确认这次有三类改动要一起做:凭证码统一为 5 位、独立 IC 卡详情页、CC 符号键盘;同时会把购卡结果卡片的关键信息做成更醒目的高对比展示。
|
|||
|
|
|
|||
|
|
我准备开始改后端与页面文件了:先统一生成 5 位凭证码,再补独立卡片详情页和更醒目的结果展示,最后处理 CC 键盘。
|
|||
|
|
|
|||
|
|
我先把后端码制改掉:线上购卡返回的主标识改成 5 位凭证码,并把卡数据里也显式保留 `voucher_code/code` 字段,方便展示和查询。
|
|||
|
|
|
|||
|
|
我已经开始做页面层改造了。接下来把新卡片详情页路由接上,并新建 `/ic/<卡号>` 页面文件。
|
|||
|
|
|
|||
|
|
CC 这边我会把姓名输入键盘做成 `ABC / SYM` 切换,不只补符号按钮,也顺手把输入约束收口到“英文 + 常用符号 + 空格”。
|
|||
|
|
|
|||
|
|
我在补最后的细节检查前,先把新详情页脚本做一层转义处理,避免事件详情里有特殊字符时把 DOM 撑坏。
|
|||
|
|
|
|||
|
|
我开始做最后一轮检查:后端码制、两个网页脚本、新增详情页和 CC Lua 一起过一遍,避免这波改动互相打架。
|
|||
|
|
|
|||
|
|
诊断已经空了。我再做一层语法校验,并抓关键定位行,方便你直接跳到 5 位凭证码、独立卡片页和符号键盘这几处确认。
|
|||
|
|
|
|||
|
|
我再抓一下几处精确行号:5 位凭证码、独立卡片页入口、购卡结果链接,以及 CC `ABC/SYM` 键盘按钮,方便你直接点进去看。
|
|||
|
|
|
|||
|
|
新页面的行号我再单独补一下,上一轮通配路径没命中。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- 线上购卡凭证码已改成统一 `5` 位,不再生成 `ICO-xxxx`;生成逻辑在 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L60-L67),新建卡记录时也会同时写入 `voucher_code/code` 字段,位置在 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L370-L376)。
|
|||
|
|
- 购卡结果区已改成更醒目的高对比展示,重点强化了 `凭证码 / 卡号 / 首次充值 / 状态` 的颜色和层级,主逻辑在 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js#L154-L219),样式在 [style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css)。
|
|||
|
|
- `ic-card-order.html` 这页我也顺手清掉了残留乱码,并把文案统一成“凭证码”口径,文件在 [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)。
|
|||
|
|
|
|||
|
|
**新页面**
|
|||
|
|
- 已新增独立 IC 卡详情页入口 `ticket.fse-media.group/ic/<卡号>`,服务端路由在 [server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js#L68-L72)。
|
|||
|
|
- 新页面模板在 [ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html#L45-L109),走的是类似电子客票的双栏卡片样式。
|
|||
|
|
- 页面数据通过公开查询接口加载,脚本在 [ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js#L82-L123)。
|
|||
|
|
- 线上购卡成功后,结果卡片里已新增“卡片详情”按钮,会直接跳到 `/ic/<卡号>`,位置在 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js#L160-L194)。
|
|||
|
|
|
|||
|
|
**CC 键盘**
|
|||
|
|
- 办卡姓名输入已新增 `ABC / SYM` 切换按钮,支持常用符号键盘。
|
|||
|
|
- 现在姓名输入会走“英文 + 常用符号 + 空格”的收口逻辑,相关代码在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1016-L1102)。
|
|||
|
|
- `SYM` 按钮和字符追加逻辑分别在 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1070-L1076) 和 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1038-L1043)。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)、[server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js)、[ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html)、[ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js)、[style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua) 诊断都为空。
|
|||
|
|
- `node --check` 已通过 [public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js)、[server/index.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/index.js)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js)。
|
|||
|
|
|
|||
|
|
**注意**
|
|||
|
|
- 这次改的是“新生成的线上购卡凭证码”规则;历史上已经生成出来的 `ICO-xxxx` 老记录不会自动改写,但现有查询仍兼容旧值。
|
|||
|
|
- 线上要看到新页面和 5 位凭证码,需要重新部署或重载当前服务,并强刷 `ic-card/order`。
|
|||
|
|
- 如果你要,我下一步可以继续把 `IC 卡查询页` 也加一个“查看电子卡片页”按钮,直接从查询结果跳到 `/ic/<卡号>`。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
线上购卡那里 自定义充值的框放到那个按钮下面,就是把按钮的高度换成现在的一半,然后把输入框放到下面。
|
|||
|
|
有个问题:首次充值的卡(未使用),但是卡详情里面显示余额10,首次充值30. 我们直接改成只显示余额就可以了不显示首次充值
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先改线上购卡页的自定义充值布局,再把 IC 卡详情页里“首次充值”字段去掉,只保留余额,避免和实际卡内余额混淆。
|
|||
|
|
|
|||
|
|
我把自定义金额输入框从“持卡人信息”区挪到充值选项区下面,并且会把“自定义”按钮做得更紧凑一些。然后把详情页里的“首次充值”整块删掉。
|
|||
|
|
|
|||
|
|
我已经把布局和详情字段都改完了。现在做一轮检查,确认购卡页和详情页没有新增错误。
|
|||
|
|
|
|||
|
|
我再抓一下关键位置的行号:自定义充值框的新位置、按钮高度样式,以及详情页去掉“首次充值”后的字段区。
|
|||
|
|
|
|||
|
|
**已调整**
|
|||
|
|
- 线上购卡页的“自定义充值”输入框已经移到充值按钮区下面,位置在 [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html#L66-L78)。
|
|||
|
|
- “自定义”按钮高度已改成更紧凑的一版,并在选中时显示下面的输入框,逻辑在 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js#L65-L99)。
|
|||
|
|
- 对应样式在 [style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css#L3463-L3476)。
|
|||
|
|
|
|||
|
|
**卡详情页**
|
|||
|
|
- `/ic/<卡号>` 详情页里已经去掉“首次充值”字段,只保留 `当前余额 / 凭证码 / 开卡时间`,模板在 [ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html#L76-L81)。
|
|||
|
|
- 详情页脚本也同步去掉了对“首次充值”的赋值,现在只写余额、凭证码和开卡时间,见 [ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js#L96-L103)。
|
|||
|
|
|
|||
|
|
**现在效果**
|
|||
|
|
- 充值区:先点 `自定义`,下面才会出现金额输入框。
|
|||
|
|
- 输入区:持卡人姓名表单不再混着自定义金额输入框。
|
|||
|
|
- 卡详情页:不会再出现“余额 10、首次充值 30”这种并排冲突展示,只显示当前余额。
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html)、[ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js)、[style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css) 诊断都为空。
|
|||
|
|
|
|||
|
|
**提示**
|
|||
|
|
- 线上页面如果暂时还是旧布局,强刷 `ic-card/order` 和 `/ic/<卡号>` 即可。
|
|||
|
|
- 如果你愿意,我还可以顺手把 `IC 卡查询页` 里的“首次充值”字段也一起去掉,整站统一成只显示余额。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
没有看到“自定义充值”输入框
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先核对购卡页当前 DOM 和切换逻辑,确认是“按钮没切到显示状态”,还是输入框实际被隐藏在别处。
|
|||
|
|
|
|||
|
|
我确认到问题点了:现在这版是“只有点了自定义才显示输入框”,在缓存或旧静态文件混用时很容易看不到。
|
|||
|
|
我准备改成更稳妥的方案:输入框固定显示在按钮区下面,点“自定义”时启用并聚焦,选预设金额时禁用但仍可见。
|
|||
|
|
|
|||
|
|
我已经把输入框改成固定显示了,现在只是在“自定义”时高亮并可输入。再做一轮检查确认没有新错误。
|
|||
|
|
|
|||
|
|
**已修**
|
|||
|
|
- 我把“自定义充值”输入框改成了**固定显示在按钮区下面**,不再依赖“点了才出现”的隐藏逻辑。
|
|||
|
|
- 现在的行为是:
|
|||
|
|
- 选 `5 / 10 / 15 / 20` 时:输入框可见,但禁用
|
|||
|
|
- 选 `自定义` 时:输入框可见、启用,并自动聚焦
|
|||
|
|
|
|||
|
|
**改动位置**
|
|||
|
|
- 输入框固定放在充值按钮区下方:[ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html#L66-L71)
|
|||
|
|
- 切换逻辑改成“高亮/启用”,不再做隐藏:[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)
|
|||
|
|
- 样式补成固定可见的盒子:[style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css)
|
|||
|
|
|
|||
|
|
**验证**
|
|||
|
|
- [ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js)、[style.css](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/style.css) 诊断均为空。
|
|||
|
|
|
|||
|
|
**你现在应该看到**
|
|||
|
|
- “自定义”按钮下方始终有一个输入框
|
|||
|
|
- 点击“自定义”后,这个输入框会变为可输入状态
|
|||
|
|
|
|||
|
|
**提醒**
|
|||
|
|
- 如果线上还没看到,先强刷 `ic-card/order`,因为这次改的是静态页面和前端脚本。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
卡ID要统一啊,现在各个界面显示的都不一样,有00020,有64AE5246
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先把 IC 卡 `card_id` 的生成和展示链路梳理一下,重点找出哪里在用“预生成卡号”,哪里在用“MOD 实际返回卡号”,再统一成一套口径。
|
|||
|
|
|
|||
|
|
我已经定位到根因了:
|
|||
|
|
现在系统里同时存在两种 ID 口径。
|
|||
|
|
|
|||
|
|
- 线上购卡下单时,后端先预生成一个占位卡号,比如 `IC-000020`
|
|||
|
|
- 真正出卡时,MOD 又返回实体卡号,比如 `64AE5246`
|
|||
|
|
|
|||
|
|
所以有些页面拿的是“预生成号”,有些页面拿的是“实体卡号”,就分裂了。
|
|||
|
|
我再确认一下检票和查卡接口现在是按哪一个字段找卡,避免直接改显示把进出站链路弄断。
|
|||
|
|
|
|||
|
|
我已经确认到一个关键点:后台和公开页面很多地方都直接渲染 `card.card_id`,而这个字段在“线上待领卡”和“实体卡已出卡”两个阶段含义不一样。
|
|||
|
|
我再读一下 `/api/cards/check`,确认它是不是强依赖当前这条主键,避免我统一显示后把检票查卡弄断。
|
|||
|
|
|
|||
|
|
我准备把“卡 ID”的显示口径收成一条规则:
|
|||
|
|
只有 MOD/实体卡真正拿到的那个 ID 才当作对外卡号;线上待领卡阶段不再把 `IC-000020` 这种内部占位号当成“卡 ID”展示。
|
|||
|
|
|
|||
|
|
具体会做两层:
|
|||
|
|
- 后端统一给卡对象补一个 `display_card_id`
|
|||
|
|
- 前端各页面都改成显示这个字段,不再直接拿 `card_id` 上屏
|
|||
|
|
|
|||
|
|
这样至少页面上不会再一会儿 `00020`、一会儿 `64AE5246`。
|
|||
|
|
|
|||
|
|
我开始改后端响应和前端展示,把“显示用卡号”抽成一个统一字段,不碰底层实际查卡主键,这样不会影响检票和数据同步。
|
|||
|
|
|
|||
|
|
后端已经补好了统一展示字段。现在把前端几个页面都改成只显示 `display_card_id`,不再直接把内部 `card_id` 上屏。
|
|||
|
|
|
|||
|
|
我顺手把旧的独立 IC 管理页也一并改一下,避免你本地如果还开着旧文件时继续看到两套卡号。
|
|||
|
|
|
|||
|
|
我已经把主后台、公开查询、详情页、购卡结果页和旧后台页的显示都收成统一字段了。现在做一轮检查,确保没有新增报错。
|
|||
|
|
|
|||
|
|
我再把关键定位行抓一下,方便你直接点进去核对“显示用卡号”的规则和几个页面的替换点。
|
|||
|
|
|
|||
|
|
先继续收口“卡 ID 统一显示”这件事,我会先把代码里所有仍然直接显示 `card_id` 的地方找出来,再核对后端返回的展示字段是否已经统一。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
IC卡详情页东西不要那么多,就和电子客票上显示的内容差不多就好了。
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我继续把卡号显示统一收口,同时会顺手把 IC 卡详情页精简成接近电子客票的展示,不再堆太多字段。
|
|||
|
|
|
|||
|
|
现在看到后端已经在返回 `display_card_id`,但详情页和结果页还保留了不少“真实卡号”直出逻辑;我先把这些展示入口统一掉,再把详情页内容裁成电子客票那种简洁版。
|
|||
|
|
|
|||
|
|
我准备直接改两个点:一是把 `ic-card-detail` 页面收成单卡片、少字段的电子客票样式;二是把待领卡状态下的跳转和复制逻辑改成优先用凭证码,避免看到占位卡号。
|
|||
|
|
|
|||
|
|
我已经把详情页主体裁掉了“最近记录”等重内容,接下来再扫一遍剩余直接露出原始 `card_id` 的前端代码,避免还有漏网的显示入口。
|
|||
|
|
|
|||
|
|
细节页和线上购卡页已经没有新的报错,我再把旧的 `ic-card-admin` 残留提示也顺手统一一下,避免弹窗里还冒出原始占位号。
|
|||
|
|
|
|||
|
|
**已调整**
|
|||
|
|
- 已把详情页精简成接近电子客票的单卡片样式,只保留 `卡号 / 持卡人 / 余额 / 凭证码 / 开卡时间 / 状态提示 / 操作按钮`,去掉了“最近记录”等过重内容,见 [ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html#L45-L96)
|
|||
|
|
- 已把详情页逻辑改成统一优先显示 `display_card_id`,并根据状态自动切换提示文案;待领卡时按钮会优先按“凭证码”处理,避免又露出占位卡号,见 [ic-card-detail.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.js#L41-L110)
|
|||
|
|
- 已把线上购卡结果页的“查询此卡 / 卡片详情”跳转改成待领卡时优先使用凭证码,避免后续实体卡出卡后链接还绑着旧占位号,见 [ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js#L159-L177)
|
|||
|
|
- 旧后台页里的创建成功提示和充值弹窗也改成走统一展示口径,不再直接弹原始 `card_id`,见 [ic-card-admin.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.js#L240-L288)
|
|||
|
|
|
|||
|
|
**当前效果**
|
|||
|
|
- 详情页现在会更像电子客票,不再堆很多字段。
|
|||
|
|
- 待领卡状态下,页面展示继续是统一口径,不会一会儿是 `IC-000020` 一会儿又是别的显示。
|
|||
|
|
- 已启用实体卡时,仍然显示并复制真实卡号,检票主键逻辑没有动。
|
|||
|
|
|
|||
|
|
**检查**
|
|||
|
|
- 已检查 `ic-card-detail.html`、`ic-card-detail.js`、`ic-card-order.js`、`ic-card-admin.js` 的诊断,当前无新增报错。
|
|||
|
|
|
|||
|
|
**建议**
|
|||
|
|
- 如果你要再进一步统一,我下一步可以把公开查询页 `ic-card-search` 也继续裁成和电子客票同一套信息密度,这样所有对外页面观感会更一致。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**User**
|
|||
|
|
|
|||
|
|
去掉购卡的“订单号”吧。
|
|||
|
|
然后在兑换卡的时候没有支付就直接出卡了。
|
|||
|
|
卡号改成后面几位随机的。
|
|||
|
|
控制台无法进入“IC卡管理”页
|
|||
|
|
`section` 这一块直接拉宽到和上面 `section` 对齐
|
|||
|
|
|
|||
|
|
**Assistant**
|
|||
|
|
|
|||
|
|
我先分五块排查:购卡页文案、兑卡支付校验、卡号生成规则、后台 `/admin` 视图切换、以及详情页宽度布局,然后一起改掉。
|
|||
|
|
|
|||
|
|
我已经定位到后台入口和详情页布局点了,接着看卡号生成和 CC 兑卡支付流程,重点查是不是线上兑卡分支直接跳过了付费确认。
|
|||
|
|
|
|||
|
|
问题点找到了:`ticketmachine.lua` 的线上兑卡分支把 `state.cost = 0` 且 `payment_mode = 'online'`,所以确认页会自动放行并直接出卡,这里我会改回“到机支付后才能兑卡”。
|
|||
|
|
|
|||
|
|
后台进不去的根因也找到了:顶部导航还写着旧地址 `/ic-card-admin.html`,而现在真正可用的是 `/admin?view=iccards`。我会一并改掉。
|
|||
|
|
|
|||
|
|
我会顺手把服务端也加一道“兑卡必须已支付”的校验,不只修前端/CC 流程,这样就算有人直接调接口也不能白拿卡。
|
|||
|
|
|
|||
|
|
我顺手把公开页文案里的“订单号”一起淡出,保留“凭证码”作为统一说法;后台内部检索能力不动。
|
|||
|
|
|
|||
|
|
改动已经落下去了,我先做一轮诊断检查,重点看 `api/public` 路由、后台页和购卡详情页有没有因为这些改动引入新错误。
|
|||
|
|
|
|||
|
|
**已修改**
|
|||
|
|
- 去掉公开购卡/查询页里对“订单号”的展示和文案,统一对外强调“凭证码”,见 [ic-card-search.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.js#L47-L66)、[ic-card-search.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-search.html#L46-L70)、[ic-card-order.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.html#L97-L104)、[ic-card-order.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-order.js#L177-L202)
|
|||
|
|
- 修了“兑卡不付钱直接出卡”问题:CC 端线上兑卡现在会按订单金额收款,且上送真实已付金额;服务端也新增了未付款拒绝兑卡的校验,见 [ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1182-L1193)、[ticketmachine.lua](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/ticketmachine.lua#L1590-L1603)、[api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L790-L799)
|
|||
|
|
- 把系统生成的 IC 卡号从顺序号改成 `IC-` 后 6 位随机数,避免再是 `IC-000020` 这种递增格式,见 [api.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/api.js#L33-L40)、[public.js](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/server/routes/public.js#L50-L57)
|
|||
|
|
- 修了后台“IC 卡管理”入口:顶部导航原来还指向旧地址 `/ic-card-admin.html`,现在统一跳到 `/admin?view=iccards`,见 [index.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/index.html#L42-L46)、[ic-card-admin.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-admin.html)、[ticket-route.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ticket-route.html)
|
|||
|
|
- 把 IC 卡详情页那块 `section` 拉宽,和上面的介绍区保持同一列宽,不再单独缩成 760,见 [ic-card-detail.html](file:///d:/TaoYuan2023_HSTG/HSTG/Lua/TicketMachine/web/ic-card-detail.html#L64-L96)
|
|||
|
|
|
|||
|
|
**检查**
|
|||
|
|
- 已检查 `server/routes/api.js`、`server/routes/public.js`、`web/index.html`、`web/ic-card-order.js`、`web/ic-card-search.js`、`web/ic-card-search.html`、`web/ic-card-detail.html`、`web/ticket-route.html`,当前无新增诊断错误。
|
|||
|
|
- 这次没有在实际 ComputerCraft 机器上跑兑卡流程,所以设备侧建议你再现场点一次“线上兑卡”确认红石付费后才会出卡。
|
|||
|
|
|
|||
|
|
**建议验证**
|
|||
|
|
- 线上购卡新建一单,确认生成的占位卡号已变成随机 6 位。
|
|||
|
|
- 在 CC 上输入凭证码后,不投币时应不能确认出卡。
|
|||
|
|
- 后台顶部导航点击 `IC 卡管理`,应直接进入 `/admin?view=iccards`。
|
|||
|
|
- `/ic/<id>` 详情页中卡片主区域宽度应与上方介绍区对齐。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|