feat(v1.11.5-L): lite 精简版——移除大屏/客户自查/多用户/小键盘,套餐仅保留按日

需求与确认(用户逐项确认):
- 老数据「按次 / 通行证 / 深渊」统一迁移成按日,代码里彻底删除三种模式
- 打手归属一并移除(只剩一个人,颜色与指派没有区分意义)
- 盲水印做成完全不可见:只存在于 DOM / 源码,肉眼与截图都看不到
- 拼写采用更正后的 Powered by Baka春秋
- 版本号与品牌全站统一带 -L
- screen_public / portal_public 保留解析但不起作用,保证旧 ini 能直接启动
- README 同步更新

品牌与版本(全站统一):
- const version = "1.11.5-L":<title>、启动横幅、日志前缀 [代打台-L]、
  设置页版本号、页脚版本号全部带 -L
- 左上角导航品牌 代打台 → 代打台-L(登录页、初始化页同步)
- 页脚新增可见署名 Powered by Baka春秋

盲水印:
- _layout.html 在 <body> 起始处注入 .wm-blind 容器(含注释与 data-wm 双标记),
  覆盖包括登录/初始化在内的所有页面
- app.css 用零尺寸 + 透明 + opacity:0 + clip-path:inset(50%) 四重隐藏,
  同时留同名注释;不占位、不上色、不进无障碍树、不影响打印

功能移除:
- 大屏:删除 handlers_screen.go、pages/screen.html、_screen_layout.html、
  static/screen.css、static/screen.js、store.Stats/ScreenStats;
  导航「大屏 ↗」、页脚「大屏」、设置页「大屏刷新/大屏」行、启动横幅大屏行一并删除
- 客户自查:删除 handlers_portal.go、pages/portal.html 与 .portal-*/.pcal-* 样式,
  设置页「客户自助」行删除
- 多管理员:删除 handleUserCreate/Toggle/Color/UserEditPage/UserEditSave、
  pages/user_form.html、store 侧 ActiveUsers/SetUserColor/SetUserActive/
  UpdateUserByAdmin/NormalizeColor/AssigneePalette;设置页「管理员」整块移除,
  只保留首次启动创建的那一个账户与「修改我的密码」
- 打手归属:删除 customers.assignee_id 相关读写与 UI(客户详情指派下拉、
  客户表单「归属打手」、日历格左侧打手色竖条、任务卡打手标签、套餐详情客户列)
- 登录页与初始化页的说明文案同步改为单账户口径(「只有一个管理员账户」
  「创建后不能再添加其他管理员」),字数与 main 对齐,卡片不换行、高度不变
- 触摸小键盘:删除 3×4 键盘、⌨/触控开关、localStorage 记忆、.keypad* 样式
- 套餐计费方式:只保留按日。删除按次/通行证/深渊的 Package 与 Subscription 字段、
  domain 里的 UnitCount/StateUsedUp/CycleIndex、package_form 计费方式单选与
  通行证/深渊/有效期字段、日历整段色块(has-block/cell-block/season-band)、
  追加次数分支、SeasonComplete/AddCount、CountActiveSubs 的次数条件

数据库迁移(幂等,Migrate 内自动执行):
- normalizeLegacyData:套餐一律 unit='day' 并清 season/abyss/cycle_days/
  default_validity_days/season_*;订阅清 season/abyss/cycle_days/season_done
- 通行证、深渊当年就是 unit='day' 且起止日完整,仅清标记,服务区间原样保留
- 按次按「1 次 = 1 天」折算:结束日 = 开始日 + 总次数 − 1;仍缺结束日退回开始日
- 只动数据,不删表不删列:老库的 season/abyss/cycle_days/total_count/used_count
  保留但不再使用,升级可逆、不会因为 DDL 失败卡住
- 新库 schema 干净:不再创建上述列,users.color / customers.assignee_id 也不创建
- 老库 ensureColumn 保留 calendar_separate / tag / archived 三项(真增量列)

兼容:
- config 仍解析 screen_public / portal_public(结构体字段注明已废弃),
  默认 ini 模板里改为「已废弃,写了不报错、不生效」

测试:
- go vet ./... 通过;go test ./... 全部通过
  (新增 TestNormalizeLegacyTypeData 验证三模式折算成按日;
   TestSingleUserAccount / TestSessionLifecycle 覆盖单用户与会话;
   删除按次、深渊、打手颜色、多用户等已不存在的能力的用例)
- 新增 scripts/smoke-lite.ps1:起隔离实例,19 个页面级请求全部 200,
  已移除的 /screen、/customer、/api/screen/day 均 404,
  水印/品牌/v1.11.5-L/无残留词 12 项断言通过,
  真实数据下日历出现待打任务、「剩 30 天」、今天到期徽标 4 项断言通过,
  本次 0 失败

README:改为 lite 版说明,删除大屏/客户自查/通行证/深渊/按次/小键盘/多用户章节,
新增「盲水印」与「与 main 分支的差异」两节(含老数据折算规则与列保留说明)。
This commit is contained in:
2026-10-21 03:33:27 +08:00
parent 0392f44cf1
commit cde1c84c9a
45 changed files with 786 additions and 4391 deletions
+88 -92
View File
@@ -1,8 +1,12 @@
# 代打台 · 代打管理平台
# 代打台-L · 代打管理平台(lite 版)
一个给代打工作室用的单文件管理程序:**套餐 → 订阅 → 追加时长 → 日历打卡 → 大屏**。
一个给代打工作室用的单文件管理程序:**套餐 → 订阅 → 追加时长 → 日历打卡**。
整个程序就是一个 `daili.exe` + 一个 `daili.ini`,数据存在同目录的 `daili.db` 里,局域网内手机、电视都能打开。界面支持亮色 / 暗色切换,默认跟随系统。
> **这是 lite 分支**:只保留「按日(包时)」一种套餐,去掉了大屏、客户自助查询、多管理员、触摸小键盘。
> 版本号统一带 `-L` 后缀(当前 `1.11.5-L`),界面品牌为「代打台-L」,页脚署名 `Powered by Baka春秋`。
> 与 `main` 分支的差异见文末「[10. 与 main 分支的差异](#10-与-main-分支的差异)」。
---
## 1. 快速开始
@@ -12,20 +16,18 @@
- 首次运行会自动生成配置文件 `daili.ini`;
- 弹出一个黑色窗口,打印访问地址(默认 **17777** 端口);
- 默认会自动打开浏览器;
3. 浏览器打开 `http://127.0.0.1:17777` → 第一次会让你**创建管理员账号**;
3. 浏览器打开 `http://127.0.0.1:17777` → 第一次会让你**创建管理员账号**(这是唯一的账号,之后不能再添加);
4. 之后按「套餐 → 客户 → 订阅」的顺序录入即可。
```
┌───────────────────────────────────────────────┐
│ 代 打 台 · 代打管理平台 │
│ 代 打 台 - L · 代打管理平台 │
└───────────────────────────────────────────────┘
版本 1.11.5 配置文件 daili.ini
版本 1.11.5-L 配置文件 daili.ini
数据库 D:\代打台\daili.db
访问地址:
本机 http://127.0.0.1:17777
局域网 http://192.168.1.23:17777
大屏 http://127.0.0.1:17777/screen(免登录)
注意:大屏免登录且监听所有网卡,同局域网内任何人都能打开 /screen
按 Ctrl+C 停止服务
```
@@ -48,18 +50,19 @@
| `backup_keep` | `14` | 备份保留份数(1–365),超出自动清理 |
| `timezone` | 空 | 留空跟随系统;可固定 `Asia/Shanghai`。**影响所有“自然日”计算** |
| `open_browser` | `true` | 启动后自动打开浏览器 |
| `screen_public` | `true` | 大屏 `/screen` 免登录(投屏用);改 `false` 则需登录 |
| `portal_public` | `true` | 客户自助查询 `/customer` 免登录;改 `false` 则关闭该页(不影响大屏) |
| `log_enabled` | `true` | 运行日志写文件(控制台始终输出) |
| `log_dir` | `logs` | 日志目录,按天切分 `daili-YYYY-MM-DD.log` |
> `screen_public`(大屏)与 `portal_public`(客户自助)在 lite 版**已废弃**:仍然接受解析,但不起任何作用。
> 保留它们只是为了让你从 `main` 升级时,旧 `daili.ini` 能直接启动,不会被「未知配置项」拦住。
**行为约定**
- 文件不存在 → 自动生成默认配置,照常启动;
- 文件写错 → **报错退出并指出行号**,原文件不会被修改。例如:
```
[代打台] 配置文件有问题,已停止启动:
[代打台-L] 配置文件有问题,已停止启动:
第 3 行: listen_port 必须在 1-65535 之间,当前是 99999
修好后重新启动即可(原文件未被修改)
@@ -81,31 +84,31 @@
示例:`daili.exe -addr 127.0.0.1:19000 -no-open`
> 业务参数(到期预警天数、大屏刷新秒数)不在配置文件里,仍在网页「设置」中修改。
> 业务参数(到期预警天数)不在配置文件里,仍在网页「设置」中修改。
---
## 3. 第一次使用(5 分钟走完)
1. **建套餐**:`套餐 → 新增套餐`
- 「包月日常」按日 30 天,色签绿;
- 「深渊十次」按次 10 次,色签紫。
- 「包月日常」默认 30 天,色签绿;
- 只有「按日」一种计费方式:有开始日与结束日,每天一条待打任务。
> 以后要加套餐 D/E/F,直接再加一行就行,**不会影响任何已有客户数据**。
2. **建客户**:`客户 → 新建客户`,填手机尾号 + 客户名(这两项组合唯一)。
3. **开通订阅**:进客户详情 → 选套餐、开始日、天数(按次则填次数)→ 开通订阅。
3. **开通订阅**:进客户详情 → 选套餐、开始日、天数 → 开通订阅。
4. **日常使用**:打开「日历」,今天那格里就是这个客户今天要打的单,点「完成」打卡。
5. **续费**:客户转账后,点订阅上的「追加时长」→ 在日历上点新的终止日期 → 确认。
面板会实时显示「计算起点 / 原结束日 / 新结束日 / 本次追加几天 / 追加后剩余几天」,并在客户页留下追加记录。
> 想先看效果再录自己的数据?程序启动后运行 `powershell -ExecutionPolicy Bypass -File scripts\seed.ps1`,会写入 8 个演示客户和 4 个套餐(默认账号 `admin` / `daili123`)。
> 想先看效果再录自己的数据?程序启动后运行 `powershell -ExecutionPolicy Bypass -File scripts\seed.ps1`,会写入演示客户与套餐(默认账号 `admin` / `daili123`)。
---
## 4. 业务规则(和 PRD 一致)
**剩余时长**
- 按日:`剩余天数 = 结束日 − 今天 + 1`,结束日当天仍算服务日;
- 按次:`剩余次数 = 总次数 − 已用次数`;按次套餐的「有效期」可留空,留空就一直有效直到次数用完。
- `剩余天数 = 结束日 − 今天 + 1`,结束日当天仍算服务日;
- 没有次数、没有周期:一个订阅就是从开始日到结束日的一段连续服务期。
**追加时长(核心)**
- 打开追加面板,**在月历上点选新的终止日期**,系统自动反算;
@@ -115,15 +118,14 @@
**暂停 / 恢复**
- 暂停期间冻结剩余时长,日历上不出现待打任务;
- 恢复时按日套餐的结束日**自动顺延**暂停的自然日天数,时间轴上是灰色斜纹段。
- 恢复时结束日**自动顺延**暂停的自然日天数,时间轴上是灰色斜纹段。
**打卡**
- 按日套餐:每天一条「完成 / 跳过」,只做记录不扣天数(天数按自然日流逝);
- 按次套餐:打卡「完成」自动扣 1 次,撤销打卡返还 1 次;次数为 0 时不允许再打;
- 按次套餐如果没设有效期,它不会出现在日历里 —— 直接在客户详情点订阅卡片上的「今日打卡」扣次。
- 每天一条「完成 / 跳过」,只做记录不扣天数(天数按自然日流逝);
- 撤销打卡会删掉这条记录,不影响结束日。
**预警**
- 剩余 ≤3 天橙色、今天到期红色、已过期灰色;顶栏常驻「今日到期 / 3 天内」两个数字。
- 剩余 ≤3 天橙色、今天到期红色、已过期灰色;顶栏常驻「今日到期 / 3 天内 / 7 天内」三个数字。
**查询**
- 顶栏搜索框输入手机尾号即可定位客户(也支持姓名、游戏名、联系方式),按 `/` 快速聚焦。
@@ -135,51 +137,24 @@
- **按尾号快速完成**:日历右侧「当日待完成」顶部输入手机尾号 → 回车。
- 只匹配到 1 项:直接完成并提示;
- 同一尾号有多个客户,或一个客户今天有多个服务:弹出勾选面板,默认全选,可多选后一次完成。
- **加急**:每条任务右侧点「加急」,会加红色 `加急` 标签并排到最前;日历格子出现红点,大屏「今日待打」同步置顶。再点一次取消。
- **按套餐分日历**:套餐编辑页勾选「在日历中独立显示」后,工作台与大屏顶部会出现套餐标签(全部 / 每日任务 / …),可以只看某类委托的排单。
- **触摸小键盘**:日历右侧输入框下面有 3 列 4 行数字键盘,底行是 ⌫ / 0 / ✓,点 ✓ 直接提交;按键为自定义样式,不是浏览器原生按钮,触摸目标 52px 高;
- **日历格子**:不再显示排单缩略信息,只保留左侧打手色竖条 + 大字「待完成 / 总数」(如 1/2 = 还剩 1 单,共 2 单);
- **按钮收纳**:任务行只露出「完成」,跳过 / 加急 / 追加收进「⋯」菜单,点空白处自动收起;
- **停用客户**:客户详情页可「停用」(默认从列表、日历、大屏隐藏,订阅保留)或「彻底删除」(连订阅/打卡/追加记录一起删,需二次确认);列表右上角可切换到「显示已停用」再恢复;
- **7 天内到期**:顶栏新增徽标,固定统计未来 7 天内到期的订阅;
- **抽屉时钟**:右侧当日面板顶部有时钟,30px 大写、水平垂直居中,24 小时制精确到秒,下面一行是当天日期;
- **触控 / PC 模式**:尾号输入框右侧有「⌨ / 触控」开关。切到触控时展开 3×4 小键盘、输入框变只读并关闭系统输入法(`inputmode=none`),点键直接写值;切回 PC 收起键盘。选择记在浏览器里。
- **格子计数**:工作台和大屏的日历格都显示「已完成 / 总数」,例如 2/5 = 5 单里做完 2 单。
- **已完成折叠**:当日清单里已完成/已跳过的单子自动折叠成一行(尾号 + 姓名 + 套餐 + 状态),点这一行展开看剩余、打手,以及撤销/加急/追加;未完成的行不受影响;
- **打手颜色**:`设置 → 管理员` 里给每个管理员选一个颜色。客户详情或编辑页可以把客户指派给某个打手,之后这个客户的所有单子都用该颜色标识:
- 日历格左侧竖条 = 当天涉及的所有打手颜色(几种人几条,等分显示);
- 「当日待完成」每条前面有打手色条 + 名字,未指派的显示灰色「未指派」;
- 大屏的今日待打、悬停浮层、热力格竖条同样带颜色。
- **加急**:每条任务右侧点「加急」,会加红色 `加急` 标签并排到最前;日历格子出现红点。再点一次取消。
- **按套餐分日历**:套餐编辑页勾选「在日历中独立显示」后,工作台顶部会出现套餐标签(全部 / 每日任务 / …),可以只看某类委托的排单。
- **日历格子**:只保留大字「已完成 / 总数」(如 1/2 = 2 单里做完 1 单)。
- **按钮收纳**:任务行只露出「完成」,跳过 / 加急 / 追加收进「⋯」菜单,点空白处自动收起。
- **停用客户**:客户详情页可「停用」(默认从列表与日历隐藏,订阅保留)或「彻底删除」(连订阅/打卡/追加记录一起删,需二次确认);列表右上角可切换到「显示已停用」再恢复;
- **7 天内到期**:顶栏徽标,固定统计未来 7 天内到期的订阅;
- **抽屉时钟**:右侧当日面板顶部有时钟,24 小时制精确到秒,下面一行是当天日期;
- **已完成折叠**:当日清单里已完成/已跳过的单子自动折叠成一行(尾号 + 姓名 + 套餐 + 状态),点这一行展开看剩余,以及撤销/加急/追加;未完成的行不受影响;
- **主题**:顶栏右上角 ☾ / ☀ 切换亮 / 暗,偏好记在浏览器里;没选过时由页面在首屏按系统偏好自动决定。整套界面只认 `<html data-bs-theme>` 一个开关,不会出现「半亮半暗」。
- **升级不缓存旧界面**:CSS/JS 链接带**内容指纹**(`app.css?v=<12 位哈希>`)。资源可以长缓存(一年、immutable),但样式或脚本一改、重新编译,URL 就会变,浏览器自动取新文件,不用手动清缓存;HTML 仍然 `no-store`。
---
## 4.4 客户自助查询 /customer
- **独立开关**:`/customer` 由 `portal_public` 控制(默认 `true`),和大屏 `screen_public` 互不影响;关掉大屏不会连带关掉客户页。
- **查法**:只接受 4–8 位数字手机尾号,精确匹配;同一尾号有多位客户时要求补姓名,并用「张* / Z***」这样的掩码提示,不直接列全名;每个 IP 每分钟最多 40 次查询。
- **展示**:今日待完成数量、订阅列表(通行证 / 深渊 / 按次 / 按日,含已到期、暂停、已用尽状态)、当月排单。月历里日常任务用空心/实心点表示未完成/已完成,通行证和深渊用连续色块并显示 `1/1` 或 `1/4 周期`;前后月只做日期占位。页面不含备注与价格。
- **隐私**:页面 `noindex`,HTML `no-store`;只显示排单与完成情况。若不需要客户自助,把 `portal_public` 改成 `false`。
---
## 4.3 通行证、深渊与按次有效期
- **通行证**(原「包赛季」):套餐上直接填通行证开始日/结束日。客户开通后,该套餐的独立日历会把整段有效期连续着色(用套餐色签的淡化色),每一格显示同一个「已完成 / 总单数」(0/1 或 1/1)。有效期内任意一天点「完成通行证」即整段完成,完成后色块保留并显示 1/1。
- **深渊**:套餐填「周期天数 N」与「周期数 X」。开通时从开始日连续排出 X 个 N 天周期;独立日历按周期连续着色,颜色从约 34% 依次减淡到约 4%。每一格显示**该周期自己**的完成情况:`1/1` 或 `0/1`,不再重复全局的 `x/X`;工作台、大屏、客户自助页同一口径。周期内任意一天完成即算该周期完成(同周期重复完成不会重复计数),撤销该天打卡会退回该周期。
- **通行证过期不可选**:今天已过通行证结束日的套餐,在客户开通下拉里会置灰并标「通行证已结束」,服务端也会拒绝开通。
- **按次默认有效期**:按次套餐可设「默认有效期(天)」,开单时自动算出到期日(开始日 + 天数 − 1),仍可手动改。
- **删除订阅**:已结束的订阅卡片上,在「重新启用」旁新增「删除」,二次确认后彻底删除该订阅及其打卡/追加记录。
---
## 4.2 套餐标签与批量开通
- **套餐标签**:套餐编辑页可以填一个标签(如「包月」)。日历/大屏顶部页签会**按标签合并**:同标签的套餐合成一个页签;勾了「在日历中独立显示」的套餐**额外**再开一个自己的页签。
- **批量开通**:`套餐 → 详情/批量`,勾选客户(表头有全选,已订阅该套餐的客户置灰),填开始日期与天数/次数后一次开通;重复的会自动跳过并提示。
- **客户月历**:客户详情页新增「当月排单」,显示该客户当月每天几单、完成几单,可翻月,点某天直接跳到日历那天。
- **按次到期**:按次订阅的「到期日」仍是选填;填了到期后状态显示「已到期」、不再进日历待排。
- **套餐标签**:套餐编辑页可以填一个标签(如「包月」)。日历顶部页签会**按标签合并**:同标签的套餐合成一个页签;勾了「在日历中独立显示」的套餐**额外**再开一个自己的页签。
- **批量开通**:`套餐 → 详情/批量`,勾选客户(表头有全选,已订阅该套餐的客户置灰),填开始日期与天数后一次开通;重复的会自动跳过并提示。
- **客户月历**:客户详情页「当月排单」,显示该客户当月每天几单、完成几单,可翻月,点某天直接跳到日历那天。
---
@@ -194,8 +169,9 @@
### 迁移与重置(只说一次,很重要)
- **迁移**:关闭程序 → 把 `daili.db` 复制到新电脑的新目录 → 放入 `daili.exe` 双击即可,账号、套餐、客户、订阅、追加记录、打卡、日志全部原样保留。
- **重置**:关闭程序 → 删除 `daili.db` → 重新打开,会回到「创建第一个管理员」的全新状态。
- 通行证是 `packages.season/season_start/season_end` 与 `subscriptions.season/season_done`;深渊是 `packages.abyss/cycle_days` 与 `subscriptions.abyss/cycle_days`(`total_count` 存周期数);套餐标签是 `packages.tag`;客户停用是 `customers.archived`(0/1);打手颜色存在 `users.color`,客户归属打手是 `customers.assignee_id`;加急标记存在 `daili.db` 的 `task_flags` 表;套餐的「独立日历」是 `packages.calendar_separate` 列,老版本数据库打开时会**自动加列**,不用手工迁移;
- **重置**:关闭程序 → 删除 `daili.db` → 重新打开,会回到「创建管理员」的全新状态。
- 套餐标签是 `packages.tag`;客户停用是 `customers.archived`(0/1);加急标记存在 `task_flags` 表;套餐的「独立日历」是 `packages.calendar_separate` 列,老版本数据库打开时会**自动加列**,不用手工迁移。
- **从 main 升级**:lite 版启动时会自动把老库里的「按次 / 通行证 / 深渊」统一折算成按日(详见文末差异说明),老库直接打开即可,无需手工改数据。
- `daili.ini`(监听/备份/日志配置)与 `backup/`、`logs/` 都是**独立于数据**的,迁移时可以不拷,程序会按默认值重新生成。
- 手动备份:`设置 → 立即备份`(同样遵守保留份数),备份文件本身也是可直接打开的单文件库;
@@ -203,22 +179,7 @@
---
## 6. 大屏
- 地址:`http://<本机IP>:17777/screen`
- 默认 `screen_public = true`:**免登录**,电视/副屏直接打开即可(仅建议局域网使用);
- 改成 `screen_public = false` 后大屏回到登录保护;
- 「记分板」风格,亮 / 暗主题同样可切(右上角 ☾ / ☀):
- 顶部 KPI:客户 / 活跃订阅 / 今日到期 / 7 天内到期;
- 中部:**热力月历 + 即将到期 TOP10**。热力默认统计「每日待完成单量」,点右上角按钮可切回「到期热力」;鼠标悬停任意格子会浮出当日待办明细(含加急标记);
- 底部:**今日到期**(左)+ **今日待打**(右,加急置顶带红 tag);
- 最下方细条:最近追加流水;
- 套餐勾选「在日历中独立显示」后,大屏顶部会出现套餐标签,可切换只看某类委托;
- 默认 30 秒自动刷新(设置页可改),按 `F` 全屏。
---
## 7. 从源码构建
## 6. 从源码构建
环境:Windows + Go 1.25(本项目在 `go1.25.6` 上验证)。
@@ -243,6 +204,12 @@ $env:GOFLAGS='-mod=mod'; $env:GOPROXY='off'; $env:GOCACHE="$PWD\.gocache"
go test ./...
```
页面级冒烟(起一个隔离实例,把所有页面渲染一遍,并校验水印/品牌/已移除入口):
```powershell
powershell -ExecutionPolicy Bypass -File scripts\smoke-lite.ps1
```
目录结构:
```
@@ -254,10 +221,10 @@ internal/logx 控制台 + 按天切分的运行日志
internal/pw 口令散列(PBKDF2-SHA256,标准库实现)
internal/web 路由、会话、模板渲染、处理器
internal/web/templates 页面与布局(embed 进二进制)
internal/web/static app.css / screen.css / app.js / screen.js
scripts/acceptance.ps1 冒烟清单执行器(119 条断言)
scripts/config-test.ps1 配置文件专项测试(14 条断言)
scripts/smoke.ps1 端到端冒烟(早期版本,保留)
internal/web/static app.css / app.js
scripts/smoke-lite.ps1 lite 版页面级冒烟(渲染 + 水印 + 已移除入口 404)
scripts/acceptance.ps1 冒烟清单执行器(main 分支遗留,部分条目已不适用)
scripts/config-test.ps1 配置文件专项测试
scripts/seed.ps1 写入演示数据
scripts/dbtool.py 测试预处理(暂停回溯、批量造数、完整性检查)
.gitea/workflows/build.yml Gitea Actions:vet → test → 交叉编译 → 上传产物
@@ -283,7 +250,7 @@ daili.ini 首次运行自动生成
---
## 8. 常见问题
## 7. 常见问题
**Windows 提示「已保护你的电脑」**
点「更多信息 → 仍要运行」。这是 Windows 对未签名 exe 的默认拦截。
@@ -301,26 +268,55 @@ daili.ini 首次运行自动生成
4. 用启动时打印的那个 `192.168.x.x` 地址,不要用 `127.0.0.1`。
**忘记密码**
让另一位管理员在 `设置 → 管理员` 里新增一个账户即可;如果只剩一个管理员且忘了密码,只能删掉 `daili.db` 重来。
lite 版只有一个管理员,没有「新增管理员」可以绕过,只能二选一:删掉 `daili.db` 从零开始,或用任意 SQLite 工具把 `users` 表的 `password_hash` 清空后重新初始化。请务必记牢密码。
**数据会不会因为程序崩溃丢?**
单文件 SQLite + 每次操作即时落盘,正常使用不会丢;每天的自动备份是双保险。仍然建议定期把 `backup/` 拷到别的盘。
**能放到公网吗?**
不建议。程序按「局域网内可信环境」设计:会话 Cookie 有 HttpOnly / SameSite 保护,但没有 HTTPS、没有登录失败锁定,且大屏和客户自助页默认免登录。要放公网请套一层反向代理 + HTTPS + 访问控制,并把 `screen_public`、`portal_public` 改成 `false`。
不建议。程序按「局域网内可信环境」设计:会话 Cookie 有 HttpOnly / SameSite 保护,但没有 HTTPS、没有登录失败锁定。要放公网请套一层反向代理 + HTTPS + 访问控制。
---
## 9. 安全说明
- **初始管理员**(第一个创建的账号,`id=1`)在 `设置 → 管理员` 每行可以点「编辑」,修改其他管理员的用户名、昵称,或重置密码;
- 重置密码会立刻清除对方的登录会话,他需要用新密码重新登录;昵称/用户名的修改不影响会话;
- 自己那一行不显示编辑(改自己的密码用「修改我的密码」),避免误操作把自己锁在门外;
- 其余管理员权限相同,但只能改自己的密码。
## 8. 安全说明
- lite 版**只有一个管理员**,就是首次启动时创建的那个账户(`users.id = 1`),不提供新增、停用或编辑他人账户的入口;
- 改自己的密码用 `设置 → 修改我的密码`;
- 口令使用 PBKDF2-HMAC-SHA256(12 万次迭代 + 随机盐)存储,不可逆;
- 所有写操作记录操作人、时间、IP 与摘要,可在「操作日志」里查询;
- 服务端模板全部走 `html/template` 自动转义;
- 所有 POST 校验 `Origin`,会话 Cookie 使用 `SameSite=Lax` + `HttpOnly`;
- 配置文件里的数据库/备份/日志路径请自行确保目录权限,程序不会覆盖已有文件(备份重名会跳过)。
---
## 9. 盲水印
界面里带一处不可见的版权水印 `Powered by Baka春秋`:写在 `_layout.html` 里由 `.wm-blind` 样式隐藏(零尺寸、透明、`clip-path` 裁掉、不进入无障碍树),同时在 `app.css` 里留了同名注释。它不占位、不上色、不影响布局与打印,只用于源码/DOM 层面溯源,**请勿删除**。
页脚另有一行可见署名 `Powered by Baka春秋`。
---
## 10. 与 main 分支的差异
| 项目 | main | lite(本分支) |
| --- | --- | --- |
| 版本号 | `1.11.5` | `1.11.5-L`(`<title>`、启动横幅、日志前缀、页脚全站统一带 `-L`) |
| 品牌 | 代打台 | 代打台-L |
| 大屏 `/screen` | 有,`screen_public` 控制免登录 | **已移除**,路由返回 404 |
| 客户自助 `/customer` | 有,`portal_public` 控制免登录 | **已移除**,路由返回 404 |
| 套餐计费方式 | 按日 / 按次 / 通行证 / 深渊 | **只有按日** |
| 管理员 | 可新增多个,为主管可编辑他人 | **只有首次启动创建的那一个** |
| 打手归属 | 客户可指派打手,彩色竖条标识 | **已移除**(只剩一个人,颜色无意义) |
| 触摸小键盘 | 3×4 小键盘 + 触控/PC 切换 | **已移除** |
| 署名 | 无 | 页脚 + 盲水印 `Powered by Baka春秋` |
**老数据怎么折算成按日**(启动时自动完成,可重复执行):
- **通行证**:当年就是 `unit='day'` 且起止日期完整,清掉 `season` 标记即可,服务区间原样保留;
- **深渊**:同样已是 `unit='day'`,结束日 = 开始日 + 周期天数 × 周期数 − 1,清掉 `abyss/cycle_days` 标记,区间原样保留;
- **按次**:按「1 次 = 1 天」折算。有总次数但没结束日的,结束日 = 开始日 + 总次数 − 1 天;仍缺结束日的退回开始日;
- 折算只动数据,不删表、不删列:老库里的 `season / abyss / cycle_days / total_count / used_count` 等列会保留但不再使用,避免升级过程不可逆。
`screen_public` 与 `portal_public` 两个配置项在 lite 版仍然被解析(不报错),但不再有任何作用。