Files
cmautobuy/admin/templates/syb/list.html
T

268 lines
13 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 "syb/list"}}
{{template "header" .}}
<div class="toolbar">
<form class="inline sync-range-form" method="post" action="/syb/sync" data-syb-sync-form>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="order_no" value="{{.Keyword}}">
<input type="hidden" name="stage" value="{{.StageFilter}}">
<input type="hidden" name="page" value="{{.CurrentPage}}">
<label for="sync-date-from">开始日期</label>
<input id="sync-date-from" type="date" name="date_from"
value="{{.SyncDateFrom}}" max="{{.Today}}" required>
<label for="sync-date-to">结束日期</label>
<input id="sync-date-to" type="date" name="date_to"
value="{{.SyncDateTo}}" max="{{.Today}}" required>
<button type="submit" class="primary" data-syb-sync-submit
{{if .SyncRunning}}disabled aria-busy="true" title="同步正在进行,请耐心等待"{{end}}>
{{if .SyncRunning}}同步中…{{else}}同步{{end}}
</button>
</form>
<button type="button" data-modal-open="sync-history-modal">同步记录</button>
<button type="button" data-need-checked data-modal-open="purchase-modal" data-purchase-open>创建采购任务</button>
<form class="inline grow" method="get" action="/syb">
<label for="stage">处理阶段</label>
<select id="stage" name="stage">
{{range .StageOptions}}
<option value="{{.Value}}" {{if eq .Value $.StageFilter}}selected{{end}}>{{.Text}}</option>
{{end}}
</select>
<label for="q">订单号</label>
{{/* search-narrow 把搜索框收到 30%,让「搜索」按钮紧挨着它。
用类名而不是改 .toolbar input[type="text"]——那条被五个页面共用。 */}}
<input id="q" type="text" name="order_no" value="{{.Keyword}}"
class="search-narrow" placeholder="订单号">
<button type="submit">搜索</button>
</form>
<form class="inline" method="post" action="/syb/delete" data-confirm-delete>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="order_no" value="{{.Keyword}}">
<input type="hidden" name="stage" value="{{.StageFilter}}">
<input type="hidden" name="page" value="{{.CurrentPage}}">
<button type="submit" class="danger" data-need-checked>删除</button>
</form>
</div>
{{if .RangeError}}<p class="missing sync-range-message" role="alert">{{.RangeError}}</p>{{end}}
{{if .RangeWarning}}<p class="hint sync-range-message">{{.RangeWarning}}</p>{{end}}
<p class="hint sync-range-message">
按顺运宝货运单创建日期(UTC+8)同步,开始日和结束日都包含,每次最多 31 天。
</p>
<div class="modal-backdrop" id="sync-history-modal" {{if not .NeedSyncHistory}}hidden{{end}}>
<div class="modal modal-wide" role="dialog" aria-modal="true"
aria-labelledby="sync-history-modal-title">
<div class="modal-head">
<h2 id="sync-history-modal-title">同步记录</h2>
<button type="button" class="modal-x" data-modal-close aria-label="关闭">×</button>
</div>
<div data-syb-history-slot>
{{template "syb/history_partial" .}}
</div>
</div>
</div>
{{if .ConfigProblem}}
<p class="missing">
顺运宝配置有问题:{{.ConfigProblem}}
</p>
{{end}}
{{/* 未登录只给一行提示,**不弹窗**(工单 #48)。
打开页面纯粹是看数据,不该触发任何对外部系统的动作;
真正会登录的只有「同步」那一个按钮。
用 .hint 不用 .missing——这是状态说明不是错误,
红色留给「PDD 链接未填写」那种要立刻处理的。 */}}
{{if .LoginHint}}
<p class="hint">{{.LoginHint}}</p>
{{end}}
<div class="table-wrap">
<table>
<thead>
<tr>
<th class="col-check"><input type="checkbox" data-check-all></th>
<th>货运单 ID</th>
<th>订单号</th>
<th>商品标题</th>
<th>规格</th>
<th>蝦皮商品 ID</th>
<th>数量</th>
<th>价格</th>
<th>图片</th>
<th>处理阶段</th>
<th>下一步</th>
<th>更新时间</th>
</tr>
</thead>
<tbody>
{{range .Rows}}
<tr data-detail-id="{{.SybID}}" {{if .NeedsAttention}}class="row-warn"{{end}}>
<td class="col-check">
<input type="checkbox" value="{{.SybID}}" name="ids" {{if not .CanPurchase}}disabled{{end}}
aria-label="选择货运单明细 {{.SybID}}">
</td>
<td>{{.SybID}}</td>
<td>{{.OrderNo}}</td>
<td class="truncate" title="{{.Title}}">{{.Title}}</td>
<td class="truncate" title="{{.ProductSpec}}">{{.ProductSpec}}</td>
<td>{{.ShopeeGoodsID}}</td>
<td>{{.Quantity}}</td>
<td>{{.PriceText}}</td>
<td>
{{if .ImageURL}}<img src="{{.ImageURL}}" alt="" class="thumb">{{else}}—{{end}}
</td>
<td><span class="status-pill">{{.StageText}}</span><br><small>{{.StageHelp}}</small></td>
<td><button type="button" data-detail-open-id="{{.SybID}}">{{.ActionText}}</button></td>
<td>{{.UpdatedAt}}</td>
</tr>
{{else}}
<tr class="empty">
<td colspan="12">
{{if .IsFiltered}}
当前筛选条件下没有货运单明细。<br>
<small>换个订单号或清空搜索词再试。<a href="/syb">查看全部</a></small>
{{else}}
还没有货运单明细。<br>
<small>点上方「同步」从顺运宝拉取,第一次同步需要先登录(验证码需要手工输入)。</small>
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<div class="modal-backdrop" id="purchase-modal" hidden>
<div class="modal modal-wide" role="dialog" aria-modal="true" aria-labelledby="purchase-modal-title">
<div class="modal-head">
<h2 id="purchase-modal-title">确认创建采购任务</h2>
<button type="button" class="modal-x" data-modal-close aria-label="关闭">×</button>
</div>
<form method="post" action="/syb/create-task" data-purchase-form
data-confirm-submit="确认按下面的人民币价格上限创建采购任务?任务创建后将等待所选客户端领取。">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="order_no" value="{{.Keyword}}">
<input type="hidden" name="stage" value="{{.StageFilter}}">
<input type="hidden" name="page" value="{{.CurrentPage}}">
<div class="modal-body form-stack">
<div class="field">
<label for="purchase-client">执行客户端</label>
<select id="purchase-client" name="client_id" required autofocus>
<option value="">请选择当前账号可见的客户端</option>
{{range .AssignableClients}}<option value="{{.ClientID}}" data-purchase-mode="{{.PurchaseMode}}">{{.Name}}({{.ClientID}},{{.Status}},{{if eq .PurchaseMode "live"}}支持真实下单{{else}}仅演练{{end}})</option>{{end}}
</select>
{{if not .AssignableClients}}<small class="missing">当前账号没有可用客户端,请先让管理员完成客户端绑定。</small>{{end}}
</div>
<fieldset class="execution-mode-fieldset">
<legend>执行模式</legend>
<label class="choice-row">
<input type="radio" name="execution_mode" value="dry_run" checked data-execution-mode>
<span><strong>采购演练</strong><small>只验证采购流程,不在拼多多创建订单。</small></span>
</label>
<label class="choice-row">
<input type="radio" name="execution_mode" value="live" data-execution-mode>
<span><strong>真实下单(不支付)</strong><small>会在拼多多创建真实的未付款订单。</small></span>
</label>
</fieldset>
<div class="live-confirm-panel" data-live-confirm-panel hidden>
<strong>真实下单安全确认</strong>
<p>这会产生真实未付款订单。必须选择声明 live 能力的客户端;系统不会自动支付。</p>
<label class="choice-row">
<input type="checkbox" name="live_acknowledged" value="1" data-live-acknowledged>
<span>我确认本次操作会创建真实未付款订单</span>
</label>
<label for="live-confirmation">输入“创建未付款订单”继续</label>
<input id="live-confirmation" name="live_confirmation" type="text"
autocomplete="off" data-live-confirmation>
</div>
<p class="hint">价格上限单位是人民币元,默认取已映射 PDD 规格的采集价;不会使用顺运宝的台币售价。</p>
{{range .Rows}}
<div class="purchase-confirm-row" data-purchase-row="{{.SybID}}" hidden>
<input type="hidden" name="ids" value="{{.SybID}}" disabled>
<div><strong>{{.OrderNo}}</strong> · {{.Title}} · {{.ProductSpec}} × {{.Quantity}}</div>
<label>人民币价格上限(元)
<input type="number" name="max_price_yuan" min="0.01" step="0.01" value="{{.DefaultMaxPrice}}" required disabled>
</label>
</div>
{{end}}
<p class="missing" data-purchase-empty hidden>没有选择可采购的明细,请关闭后重新勾选。</p>
</div>
<div class="modal-foot">
<button type="button" data-modal-close>取消</button>
<button type="submit" class="primary" {{if not .AssignableClients}}disabled{{end}}>确认创建</button>
</div>
</form>
</div>
</div>
<p class="hint">
每行只显示当前最需要完成的下一步;双击行或点击“下一步”按钮可以打开处理详情。
</p>
<div class="modal-backdrop" id="detail-modal" data-detail-url="{{.DetailURL}}" hidden>
<div class="modal modal-wide" role="dialog" aria-modal="true" data-detail-slot>
<div class="modal-body">正在加载…</div>
</div>
</div>
{{/* ── 登录弹窗 ─────────────────────────────────
会话未登录/已过期时自动打开(不加 hidden);
`[必须]` 密码不在界面上显示、也不回显到 HTML,只显示只读账号。 */}}
<div class="modal-backdrop" id="login-modal" {{if not .NeedLogin}}hidden{{end}}>
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="login-modal-title">
<div class="modal-head">
<h2 id="login-modal-title">登录顺运宝</h2>
<button type="button" class="modal-x" data-modal-close aria-label="关闭">×</button>
</div>
<form method="post" action="/syb/login-and-sync">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="order_no" value="{{.Keyword}}">
<input type="hidden" name="stage" value="{{.StageFilter}}">
<input type="hidden" name="page" value="{{.CurrentPage}}">
{{/* 登录和 OCR 降级后必须把工具栏里已确认的日期范围原样带回来。 */}}
<input type="hidden" name="date_from" value="{{.SyncDateFrom}}">
<input type="hidden" name="date_to" value="{{.SyncDateTo}}">
<div class="modal-body">
{{/* `[必须]` 工单 #47:自动识别验证码失败/降级时要说明原因
(已尝试 N 次 / 服务不可用),操作员才知道是配置错了还是
服务挂了。ocr_url 留空时压根没尝试过自动识别,不显示这条。 */}}
{{if .NeedLoginReason}}
<p class="hint login-degrade-reason">{{.NeedLoginReason}}</p>
{{end}}
<div class="field">
<label for="login-username">账号</label>
<input id="login-username" type="text" value="{{.Username}}" readonly>
</div>
<div class="field">
<label for="login-captcha-img">验证码</label>
{{/* 图片地址带一个时间戳查询参数,确保每次打开弹窗/点"换一张"
都拿到新图,不被浏览器缓存吃掉旧的 */}}
<img id="login-captcha-img" src="/syb/captcha" alt="验证码"
class="captcha-img" data-captcha-refresh="/syb/captcha">
<button type="button" id="login-captcha-refresh">换一张</button>
</div>
<div class="field">
<label for="login-code">验证码文字</label>
<input id="login-code" type="text" name="code" required autocomplete="off"
maxlength="8" placeholder="图片里的 4 位字母数字">
</div>
<p class="hint">
账号密码取自 <code>admin/config.yaml</code>,界面上不显示密码。
</p>
</div>
<div class="modal-foot">
<button type="button" data-modal-close>取消</button>
<button type="submit" class="primary">登录并同步</button>
</div>
</form>
</div>
</div>
{{template "footer" .}}
{{end}}