Files
subtrack/internal/web/templates/pages/settings.html
T
chun_qiu 8b9c347649
build / build-and-test (push) Successful in 3m38s
feat(v1.10.0): 重建 Bootstrap 主题层,修复迁移遗留的明暗/缓存/布局问题
背景:v1.9.0 把界面迁到 Bootstrap 5 时保留了旧自研 CSS,v1.9.2 又叠加了一层
「墨绿渐变」覆盖层,形成三套令牌(--paper/--ink、prefers-color-scheme、
data-bs-theme)并存。系统偏好与 Cookie 不一致时,页面会出现半亮半暗、表单
标签/抽屉标题/订阅页签不可见、输入框变黑块等问题。

本次改动:
- 样式加载顺序改为 bootstrap → app.css;删除旧纸墨令牌与 v1.9.2 覆盖层,
  app.css 重写为单一主题层(:root/[data-bs-theme=light] 与 [data-bs-theme=dark]
  两套语义令牌)。组件只读 --app-*,解决 --ink-2 同时被当作「次级文字色」和
  「卡片底色」的语义冲突。
- 主题只认 <html data-bs-theme>:服务端按 Cookie 直出;没有 Cookie 时由 <head>
  内联脚本在首屏按系统偏好补齐,修好「跟随系统」并避免闪白。大屏同理。
- 修复 Bootstrap 覆盖自研设计的问题:正文 14px + 中文字体栈、22/16/14px 标题、
  按钮/输入框/焦点环/卡片回到设计值;普通按钮新增 .btn-soft,不再变透明文字。
- 布局修复:客户/套餐表单的 .grid-2 不再塞 3 个字段;包详情页把筛选独立成
  GET 表单(在搜索框回车不再误触批量开通);客户详情操作区与 meta 重排;
  抽屉时钟改为固定 46px 并用它对齐抽屉头的 sticky 偏移;追加面板在抽屉里
  两列月历、不再 1100px 竖排;手机端日历数字不再换行溢出,移动端表格隐藏
  低优先级列,不再被裁切。
- 大屏:KPI/面板去掉 Bootstrap utility,统一由 screen.css 控制;TOP/今日待打
  改为固定列宽 + grid-column 对齐;浅色主题的链接、热力、图例对比度补齐;
  热力格不再整体降透明度;当日浮层可滚动并支持点击/键盘打开。
- 配色与可读性:普通文本对比度全部达标(截图 lint 由 65 处降到 0);日历
  外月日期改为浅底深字,不再整格 opacity;archived 行改为中性底色而非降透明。
- 缓存:新增内嵌静态资源内容指纹 AssetVersion(12 位 sha256),所有 /static
  链接带 ?v=;带指纹的响应 public, max-age=31536000, immutable,不带指纹的
  回源 no-cache;HTML 继续 no-store。改样式重新编译即自动破缓存,不再依赖
  手改版本号(仍保留 v1.10.0 作为产品版本)。
- 认证页重做:登录/初始化页改用 .auth 卡片(品牌、主题切换、绿色焦点环),
  去掉 min-height:100vh 叠加 main padding 造成的 40px 纵向滚动。
- JS:修 toISOString 计算自然日差一天的时区 bug;主题切换读 data-bs-theme
  并同步 aria-pressed;全选支持半选;大屏切主题同时更新 data-bs-theme;
  提示条改为固定定位、淡出不再顶动页面。
- README 更新主题与缓存说明;版本号 1.9.5 → 1.10.0。

验证:gofmt / go vet / go test 全绿;1440、1100、390 三档,明暗两套,工作台/
客户/套餐/订阅/设置/日志/大屏/登录全部截图走查,无横向溢出与控制台错误。
2026-10-20 01:46:11 +08:00

113 lines
6.1 KiB
HTML

{{define "content"}}
<div class="page narrow">
<header class="page-head">
<div>
<h1>设置</h1>
<p>预警天数、备份、账户与数据导出</p>
</div>
</header>
<section class="section card">
<h2>基础设置</h2>
<form method="post" action="/settings" class="form">
<div class="grid-2">
<label class="field"><span>到期预警(天)</span>
<input type="number" name="warn_days" min="0" max="60" value="{{.D.WarnDays}}">
</label>
<label class="field"><span>大屏自动刷新(秒)</span>
<input type="number" name="screen_refresh" min="5" max="600" value="{{.D.ScreenRefresh}}">
</label>
</div>
<p class="muted small">监听地址、端口、数据库、备份、日志、时区等部署参数在 <code>daili.ini</code> 里配置,改完重启生效。</p>
<div class="actions"><button class="btn btn-primary" type="submit">保存设置</button></div>
</form>
</section>
<section class="section card">
<h2>管理员</h2>
<p class="muted small">所有账户权限相同,任何操作都会记在日志里。每个管理员的颜色用于日历左侧竖条和待办标识。</p>
<p class="muted small">{{if eq .User.ID 1}}你是初始管理员,可以点「编辑」修改其他管理员的用户名、昵称和密码。{{else}}只有初始管理员(首个账号)可以修改其他管理员的资料。{{end}}</p>
<div class="table-wrap">
<table class="table tight table-users">
<thead><tr><th scope="col">用户名</th><th scope="col">显示名称</th><th scope="col">打手颜色</th><th scope="col">状态</th><th scope="col">创建时间</th><th scope="col">最近登录</th><th scope="col"><span class="visually-hidden">操作</span></th></tr></thead>
<tbody>
{{$me := .User}}
{{range .D.Users}}
<tr>
<td class="mono">{{.Username}}</td>
<td>{{.DisplayName}}</td>
<td>
<form method="post" action="/settings/users/{{.ID}}/color" class="color-form">
<input type="color" name="color" value="{{if .Color}}{{.Color}}{{else}}#8A8F98{{end}}" title="打手颜色" aria-label="打手颜色">
<button class="btn btn-soft btn-sm" type="submit">保存</button>
</form>
</td>
<td>{{if .IsActive}}<span class="chip chip-active">启用</span>{{else}}<span class="chip chip-closed">停用</span>{{end}}</td>
<td class="mono small">{{.CreatedAt}}</td>
<td class="mono small">{{if .LastLoginAt}}{{.LastLoginAt}}{{else}}—{{end}}</td>
<td class="actions-cell">
{{if eq .ID $me.ID}}
<span class="muted small">当前账户</span>
{{else}}
{{if eq $me.ID 1}}
<a class="btn btn-soft btn-sm" href="/settings/users/{{.ID}}/edit">编辑</a>
{{end}}
<form method="post" action="/settings/users/{{.ID}}/toggle">
<button class="btn btn-ghost btn-sm">{{if .IsActive}}停用{{else}}启用{{end}}</button>
</form>
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<form method="post" action="/settings/users" class="inline-form">
<label class="inline-field">用户名 <input type="text" name="username" required minlength="3" maxlength="32" autocomplete="off"></label>
<label class="inline-field">显示名称 <input type="text" name="display_name" maxlength="32"></label>
<label class="inline-field">初始密码 <input type="password" name="password" required minlength="6" autocomplete="new-password"></label>
<button class="btn btn-primary" type="submit">新增管理员</button>
</form>
</section>
<section class="section card">
<h2>修改我的密码</h2>
<form method="post" action="/settings/password" class="form">
<div class="grid-3">
<label class="field"><span>原密码</span><input type="password" name="old_password" required autocomplete="current-password"></label>
<label class="field"><span>新密码(≥6 位)</span><input type="password" name="password" required minlength="6" autocomplete="new-password"></label>
<label class="field"><span>再输一次</span><input type="password" name="password2" required minlength="6" autocomplete="new-password"></label>
</div>
<div class="actions"><button class="btn btn-primary" type="submit">更新密码</button></div>
</form>
</section>
<section class="section card">
<h2>数据</h2>
<dl class="kv">
<div><dt>配置文件</dt><dd class="mono small">{{.D.ConfigPath}} <span class="muted">(修改后重启生效)</span></dd></div>
<div><dt>数据库</dt><dd class="mono small">{{.D.DBPath}}</dd></div>
<div><dt>备份</dt><dd class="mono small">{{.D.BackupDir}} · 保留 {{.D.BackupKeep}} 份 · {{if .D.BackupEnabled}}自动备份已开启{{else}}自动备份已关闭{{end}}</dd></div>
<div><dt>大屏</dt><dd class="mono small">/screen {{if .D.ScreenPublic}}免登录{{else}}需登录{{end}}</dd></div>
<div><dt>局域网地址</dt><dd class="mono small">http://{{if .D.Addrs}}{{index .D.Addrs 0}}{{else}}127.0.0.1{{end}}:{{.D.Port}}/screen</dd></div>
<div><dt>已运行</dt><dd class="mono">{{.D.Uptime}}</dd></div>
<div><dt>数据量</dt><dd>{{.D.CustomerCount}} 位客户 · {{.D.PackageCount}} 个套餐 · {{.D.LogCount}} 条日志</dd></div>
</dl>
<div class="actions wrap">
<form method="post" action="/settings/backup"><button class="btn btn-soft" type="submit">立即备份</button></form>
<a class="btn btn-soft" href="/export/customers.csv">导出客户 CSV</a>
<a class="btn btn-soft" href="/export/subscriptions.csv">导出订阅 CSV</a>
<a class="btn btn-soft" href="/export/logs.csv">导出日志 CSV</a>
</div>
{{if .D.Backups}}
<details class="backups">
<summary>最近备份({{len .D.Backups}} 份)</summary>
<ul class="mono small">
{{range .D.Backups}}<li>{{.}}</li>{{end}}
</ul>
</details>
{{end}}
</section>
</div>
{{end}}