crawl(品牌抓取任务队列) - /admin/internal/crawl/tasks 领取 / :id/result 回报,spider 可常驻拉任务 - 后台品牌列表支持「加入抓取队列」,队列页可看状态与重试 - 租约超时的 running 自动回收为 queued,避免 worker 崩溃后任务卡死 media(媒体机直传) - ingest 载荷新增 main_key/detail_keys/main_size/detail_sizes: 有 key 就直接落库,跳过下载与上传;与 URL 形态可逐图混用 - 细节图按 Details/DetailKeys 两者较长者遍历(只给 key 时不再丢图) - 媒体机上传的 key 不进失败回滚清单(内容寻址、可能与他人共享) - /admin/internal/upload-url 签发 S4 PUT 预签名(spider 不持有 AK/SK) embeddings(向量回填) - GET /admin/internal/embeddings/pending 派发缺向量的图(含可直接下载的 url) - POST /admin/internal/embeddings 回写向量并重算近邻;失败项计入 image_embedding_failures,连续失败到上限后退出队列(坏图不占位) - 近邻重算改为异步串行:同步会让 100 张的批次 POST 超时(实测 >60s) - 新增 key 分支单测:混用 key/url、细节图只给 key、字节数、回滚清单、向量占位
79 lines
4.4 KiB
HTML
79 lines
4.4 KiB
HTML
{{define "title"}}品牌管理 · 管理后台{{end}}
|
|
{{define "barLabel"}}管理后台 · 品牌管理{{end}}
|
|
{{define "barRight"}}<a href="/admin/brands/new">+ 新建</a> · <a href="/admin/logout">退出</a>{{end}}
|
|
{{define "content"}}
|
|
{{template "bar" .}}
|
|
<div class="main">
|
|
<h1>品牌列表</h1>
|
|
<form class="toolbar" method="get" action="/admin/brands">
|
|
<input name="keyword" placeholder="搜索品牌名…" value="{{.Keyword}}">
|
|
{{if .All}}<input type="hidden" name="all" value="1">{{end}}
|
|
{{if .Sort}}<input type="hidden" name="sort" value="{{.Sort}}">{{end}}
|
|
<button type="submit">搜索</button>
|
|
{{if .Keyword}}<a href="/admin/brands{{if .All}}?all=1{{end}}">清除</a>{{end}}
|
|
<span class="spacer"></span>
|
|
{{if .All}}<a class="view" href="/admin/brands?keyword={{.Keyword}}">只看有图集的品牌</a>{{else}}<a class="view" href="/admin/brands?keyword={{.Keyword}}&all=1">显示全部品牌(含无图集)</a>{{end}}
|
|
</form>
|
|
|
|
<p class="muted">
|
|
默认只显示「已有图集」的品牌;品牌目录共 2 万余条,其余请用上面的搜索或开关查看。
|
|
排序:
|
|
{{if eq .Sort "updated"}}<strong>最近更新</strong>{{else}}<a href="/admin/brands?keyword={{.Keyword}}{{if .All}}&all=1{{end}}&sort=updated">最近更新</a>{{end}}
|
|
·
|
|
{{if eq .Sort "updated"}}<a href="/admin/brands?keyword={{.Keyword}}{{if .All}}&all=1{{end}}">按名字</a>{{else}}<strong>按名字</strong>{{end}}
|
|
</p>
|
|
|
|
{{if .Added}}<p class="muted">✅ 本次已加入抓取队列 <strong>{{.Added}}</strong> 个品牌(已在队列中的不会重复添加)。</p>{{end}}
|
|
|
|
<div class="idx">
|
|
<a href="/admin/brands?keyword={{.Keyword}}{{if .All}}&all=1{{end}}{{if .Sort}}&sort={{.Sort}}{{end}}" class="{{if eq .Letter ""}}on{{end}}">全部</a>
|
|
<a href="/admin/brands?letter=OTHER&keyword={{.Keyword}}{{if .All}}&all=1{{end}}{{if .Sort}}&sort={{.Sort}}{{end}}" class="{{if eq .Letter "OTHER"}}on{{end}}">中文</a>
|
|
{{range $l := .Letters}}<a href="/admin/brands?letter={{$l}}&keyword={{$.Keyword}}{{if $.All}}&all=1{{end}}{{if $.Sort}}&sort={{$.Sort}}{{end}}" class="{{if eq $l $.Letter}}on{{end}}">{{$l}}</a>{{end}}
|
|
</div>
|
|
|
|
{{/* 批量操作表单:勾选框用 form="bulk" 关联,避免与行内表单嵌套 */}}
|
|
<form id="bulk" method="post" action="/admin/crawl/bulk"></form>
|
|
<div class="ops" style="margin:10px 0">
|
|
<label class="muted">每品牌场次上限
|
|
<select name="maxShows" form="bulk">
|
|
<option value="1">1 场(最快探有无数据)</option>
|
|
<option value="3" selected>3 场(最近,推荐)</option>
|
|
<option value="0">全量(所有历史场次)</option>
|
|
</select>
|
|
</label>
|
|
<button type="submit" form="bulk" class="op">把勾选的品牌加入抓取队列</button>
|
|
<span class="muted">(勾选本页任意行,先点复选框列头可全选本页)</span>
|
|
</div>
|
|
|
|
<table>
|
|
<thead><tr>
|
|
<th><input type="checkbox" title="全选本页" onclick="document.querySelectorAll('input[name=uid]').forEach(function(c){c.checked=this.checked}.bind(this))"></th>
|
|
<th>编码 ID</th><th>英文名</th><th>中文名</th><th>图集</th><th>图片</th><th>抓取状态</th><th>上次抓取</th><th>操作</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
{{range .Items}}{{$cs := index $.CrawlStates .UID}}{{$st := index $.Stats .UID}}<tr>
|
|
<td><input type="checkbox" name="uid" value="{{.UID}}" form="bulk"></td>
|
|
<td><code>{{.UID}}</code></td>
|
|
<td>{{.NameEn}}</td>
|
|
<td>{{.NameCn}}</td>
|
|
<td>{{if $st}}{{$st.Runways}}{{else}}0{{end}}</td>
|
|
<td>{{if $st}}{{$st.Images}}{{else}}0{{end}}</td>
|
|
<td>{{if $cs}}<span class="badge {{$cs.Class}}">{{$cs.Label}}</span>{{else}}<span class="muted">—</span>{{end}}</td>
|
|
<td class="muted">{{if $cs}}{{$cs.LastAt}}{{else}}—{{end}}</td>
|
|
<td>
|
|
<a class="view" href="/admin/brands/{{.UID}}">编辑</a>
|
|
<form class="inline" method="post" action="/admin/crawl/brands/{{.UID}}" onsubmit="return confirm('把「{{.NameEn}}」加入抓取队列?默认只抓最近 3 场。')">
|
|
<input type="hidden" name="back" value="/admin/brands"><input type="hidden" name="maxShows" value="3">
|
|
<button type="submit" class="op">加入队列</button>
|
|
</form>
|
|
<form class="inline" method="post" action="/admin/brands/{{.UID}}/delete" onsubmit="return confirm('确认删除品牌「{{.NameEn}}」?该品牌下若还有图集会拒绝删除。')">
|
|
<button type="submit" class="op op-warn">删除</button>
|
|
</form>
|
|
</td>
|
|
</tr>{{end}}
|
|
</tbody>
|
|
</table>
|
|
{{template "pager" .Pager}}
|
|
</div>
|
|
{{end}}
|