Files
subtrack/internal/web/templates/pages/portal.html
T
chun_qiu ddc7988f34
build / build-and-test (push) Successful in 3m18s
fix(v1.11.3): 客户自助查询 /customer 全量修复
- 路由:从 screen_public 拆出 portal_public(默认 true),关掉大屏不再连带 404;
  设置页显示客户自助状态;/customer 与 /screen 各自独立。
- 查询:尾号只接受 4–8 位数字,服务端精确匹配,去掉 LIKE 模糊回退;按 IP
  40 次/分钟限流;页面 noindex。
- 语义:修正「今日待完成」把已完成数当待完成数的问题;0/0 改为「今日无排单」;
  无订阅走空态;删掉进度条和重复的今日文案,只留一个状态。
- 订阅:复用管理端 SubView / calSub;通行证 1/1、深渊 x/y 周期;过期、暂停、
  按次用尽、跳过都有独立口径;「最近到期」只取未来日期。
- 日历:与主日历一致,只在本月格显示任务;通行证/深渊整段色块(深渊按周期
  减淡),日常任务用空心/实心点;每格带读屏描述;today 加「今天」文字标记。
- 错误:只渲染一次并放回内容容器,字段加 aria-invalid;删掉顶部重复横幅。
- 多客户:显示掩码姓名 + 卡内补姓名表单;姓名回填;翻月用 url.Values 编码;
  1 位尾号不触发查询;只有空态/补姓名时 autofocus。
- UI:品牌头、可折叠「查询其他尾号」、订阅全宽列表、状态统一用现有 chip、
  月份按钮 44px、去掉卡中卡 / opacity / 满屏 0/1。
- 版本 1.11.3;README 增加 4.4 与 portal_public 配置说明。

验证:gofmt / go vet / go test 全绿;portal_public=true 时 /customer 200、
false 时 404;screen_public=false + portal_public=true 时 /customer 200、
/screen 302;尾号 2 与 % 被拒;2222 多客户掩码;9900 日常点、3321 通行证
1/1、6677 深渊 1/4 + 已到期订阅;明暗 1440 与 390 截图无对比度/溢出问题。
2026-10-20 03:39:41 +08:00

126 lines
6.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "content"}}
<div class="portal-wrap">
<header class="portal-head">
<a class="portal-brand" href="/customer"><span class="brand-mark" aria-hidden="true">代</span><span>代打台</span></a>
<h1>排单查询</h1>
<p class="muted">输入手机尾号查看自己的排单与完成情况。</p>
</header>
{{if .InlineError}}<div class="notice notice-danger portal-error" id="portal-error" role="alert">{{.InlineError}}</div>{{end}}
<details class="portal-search" {{if or (not .Query) .InlineError}}open{{end}}>
<summary class="portal-search-head">{{if .InlineError}}修改查询{{else if .Query}}查询其他尾号{{else}}输入手机尾号查询{{end}}</summary>
<form class="portal-form" method="get" action="/customer">
<div class="portal-form-body">
<div class="row g-2 align-items-end">
<div class="col-12 col-sm-4">
<label class="form-label" for="tail">手机尾号(4–8 位)</label>
<input class="form-control" id="tail" name="tail" value="{{.Query}}" inputmode="numeric" pattern="[0-9]{4,8}" minlength="4" maxlength="8" placeholder="例如 2300" required{{if not .Query}} autofocus{{end}}{{if eq .InvalidField "tail"}} aria-invalid="true" aria-describedby="portal-error"{{end}}>
</div>
<div class="col-12 col-sm-4">
<label class="form-label" for="name">客户姓名(可选)</label>
<input class="form-control" id="name" name="name" value="{{.Name}}" maxlength="32" placeholder="尾号重复时填写"{{if eq .InvalidField "name"}} aria-invalid="true" aria-describedby="portal-error"{{end}}>
</div>
<div class="col-12 col-sm-4">
<button class="btn btn-primary w-100" type="submit">查询</button>
</div>
</div>
<p class="muted small mb-0 mt-2">只显示排单与完成情况,不含备注与价格。</p>
</div>
</form>
</details>
{{with .D}}
{{if .Masked}}
<section class="portal-result">
<div class="card mt-3"><div class="card-body">
<h2 class="h5">找到 {{.Count}} 位客户</h2>
<p class="muted mb-2">尾号 {{.Tail}} 对应多位客户,请补一个姓名后查询。</p>
{{if .Masked}}<p class="portal-ask-names">可能是:{{range $i, $n := .Masked}}{{if $i}}、{{end}}{{$n}}{{end}}</p>{{end}}
<form class="portal-ask-form" method="get" action="/customer">
<input type="hidden" name="tail" value="{{.Tail}}">
<label class="visually-hidden" for="ask-name">姓名</label>
<input class="form-control" id="ask-name" name="name" maxlength="32" placeholder="输入姓名(可只填一部分)" required autofocus>
<button class="btn btn-primary" type="submit">查询</button>
</form>
</div></div>
</section>
{{else}}
<section class="portal-result">
{{if .Subs}}
<div class="card mt-3"><div class="card-body">
<div class="portal-client">
<div class="portal-client-main">
<h2 class="portal-client-name">{{.Tail}} · {{.Name}}</h2>
<div class="portal-client-meta">
{{if .Game}}<span class="tagchip">{{.Game}}</span>{{end}}
{{if .Expiring}}<span class="tagchip">最近到期 {{.Expiring}}</span>{{end}}
</div>
</div>
<div class="portal-client-status">
{{if eq .TodayState "done"}}<span class="chip chip-active">今日已清完</span>
{{else if eq .TodayState "pending"}}<span class="chip chip-plain">今日待完成 {{.TodayPending}} / {{.TodayTotal}}</span>
{{else}}<span class="chip chip-plain">今日无排单</span>{{end}}
</div>
</div>
</div></div>
<div class="card mt-3"><div class="card-body">
<div class="portal-section-head"><h2>订阅</h2><span class="portal-section-count">{{.SubCount}}</span></div>
<div class="portal-sub-list">
{{range .Subs}}
<article class="portal-sub">
<div class="portal-sub-main">
<strong>{{.PackageName}}</strong>
<span class="tagchip">{{.UnitLabel}}</span>
{{if .TodayLabel}}<span class="chip chip-{{.TodayClass}}">{{.TodayLabel}}</span>{{else}}{{template "state-chip" .}}{{end}}
</div>
<div class="portal-sub-meta">
<span>{{.RemainText}}</span>
<span class="muted">{{.PeriodText}}</span>
</div>
</article>
{{end}}
</div>
</div></div>
<div class="card mt-3"><div class="card-body">
<div class="portal-section-head">
<h2>当月排单</h2>
<div class="pcal-nav">
<a class="btn btn-soft pcal-nav-btn" href="{{.Prev}}" aria-label="上个月">‹</a>
<b>{{.MonthTitle}}</b>
<a class="btn btn-soft pcal-nav-btn" href="{{.Next}}" aria-label="下个月">›</a>
</div>
</div>
<div class="pcal" role="grid" aria-label="{{.MonthTitle}}排单">
<div class="pcal-dow" role="row">
<span role="columnheader">一</span><span role="columnheader">二</span><span role="columnheader">三</span><span role="columnheader">四</span><span role="columnheader">五</span><span role="columnheader">六</span><span role="columnheader">日</span>
</div>
{{range .Weeks}}
<div class="pcal-row" role="row">
{{range .}}
<div class="pcal-cell{{if not .InMonth}} out{{end}}{{if .Today}} today{{end}}{{if .BlockColor}} has-block{{end}}" role="gridcell" aria-label="{{.Label}}"{{if .BlockColor}} style="--block:{{.BlockColor}};--block-pct:{{.BlockPercent}}%"{{end}}>
<b>{{.Day}}</b>
{{if .Today}}<i class="pcal-today">今天</i>{{end}}
{{if .BlockText}}<span class="pcal-block" title="{{.BlockTitle}}">{{.BlockText}}</span>{{end}}
{{if .Total}}{{if eq .Total 1}}<span class="pcal-dot{{if .Done}} done{{end}}" title="{{.Done}}/{{.Total}} 单"></span>{{else}}<span class="pcal-count">{{.Done}}/{{.Total}}</span>{{end}}{{end}}
</div>
{{end}}
</div>
{{end}}
</div>
</div></div>
{{else}}
<div class="card mt-3"><div class="card-body">
<h2 class="h4 mb-1">{{.Tail}} · {{.Name}}</h2>
<div class="portal-client-meta">{{if .Game}}<span class="tagchip">{{.Game}}</span>{{end}}</div>
<p class="muted mb-0 mt-3">还没有进行中的订阅。如需开通,请联系你的代打。</p>
</div></div>
{{end}}
</section>
{{end}}
{{end}}
</div>
{{end}}