Files
rond-with-you/internal/web/templates/admin/index.html
T
tamakyi 7236c7a9d5 窄屏宽表不再横向滚动:改成一屏一行的「字段名 + 值」
移动端有 7 张表要横滑 300+px 才看得全,滑着还对不上表头(地点库 8 列、统计 3 张、专题详情、
首页天气、后台数据集表与数据说明、专题管理、报告页 2 张)。给这些表加 tb-stack:
窄屏隐藏 thead、每行一屏一块、每格「字段名 + 值」竖排,值多行时用悬挂缩进。

- 字段名取自 td 的 data-label(首格是这行主角,故意不带标签;操作格给「操作」)——
  这样改列顺序也不会串标签,比把名字写进 CSS 的 nth-child 稳。
- 表格结构、链接、表单、按钮一律没动(只是隐藏 thead + 改 display),桌面与平板仍是原表。
- 断点只用 @media (max-width:620px):试过容器查询(能顺手治掉「宽屏里 g2 窄卡片也要横滑」),
  但实测会把 /stats 三个卡片撑高 1300px,太臃肿,不划算。

实测:390/620 十张表需横滑全部为 0、每行每格都有标签;621/700/1440 的横滑量与改动前一致
(桌面零变化);128 个链接/按钮滚动到可见后逐个点测均可点中,无裁切;全站审计 390 站长/访客 +
320 + 1440 溢出全 0、0 JS 报错,小触控与小字数与改动前逐页一致(320 下露外元素 /places 277→2、
/stats 114→12、/admin 46→4,剩下的都是有意的横滑容器)。

新增回归 internal/web/tb_stack_test.go:渲染 7 个页面、逐行核对「每个非首格都有 data-label」
且「格子数 == 表头列数」(变异验证过:去掉一个标签立刻 FAIL)。
2026-09-18 22:24:12 +08:00

170 lines
9.0 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="wrap">
<div class="page-head">
<div>
<h1>后台管理</h1>
<div class="sub">上传 rond 备份、切换展示的数据、调整站点设置</div>
</div>
<div class="row">
<a class="btn" href="/admin/edit">数据编辑</a>
<a class="btn" href="/admin/topics">专题管理</a>
<a class="btn" href="/admin/photos">照片导入</a>
<a class="btn" href="/admin/settings">站点设置</a>
<a class="btn" href="/admin/twofa">两步验证</a>
<a class="btn" href="/admin/notes">地点备注</a>
<a class="btn" href="/admin/password">账号设置</a>
<a class="btn" href="/" target="_blank">查看站点</a>
</div>
</div>
{{if .Flash}}<div class="alert ok">{{.Flash}}</div>{{end}}
{{if .Err}}<div class="alert err">{{.Err}}</div>{{end}}
{{if .DefaultPW}}<div class="alert err">⚠️ 您仍在使用初始口令 <span class="mono">rond-admin</span>,站点对公网开放时任何人都可以用这组口令登录后台。请尽快<a href="/admin/password">修改密码</a>,并在<a href="/admin/twofa">两步验证</a>中绑定动态口令。</div>{{end}}
<div class="card">
<h2>上传备份</h2>
<div class="card-sub">
在 rond App 中导出备份,得到 <span class="mono">.rondbackup</span> 文件后上传。
单次最大 {{size .MaxSize}}。
<b>上传是以备份为准重建数据</b>:站点里删掉的地点、改过的记录,只要下次传一份
<b>内容不同</b>的备份,就会被备份里的原样覆盖回来(重复传同一份文件不会,会提示「完全一致」)。
在站点上新加的地点属于当时那个数据集,传新备份后要看它们,可在下面的数据集列表里切回。
</div>
<form method="post" action="/admin/upload" enctype="multipart/form-data">
<label class="f" style="max-width:520px">
<span>选择文件</span>
<input type="file" name="backup" accept=".rondbackup,.zip" required
style="padding:8px;border:1px dashed var(--line);border-radius:8px;background:var(--bg-2)">
</label>
<button class="btn primary" type="submit">上传并导入</button>
</form>
</div>
<div class="card">
<h2>世界迷雾</h2>
<div class="card-sub">
导入 Fog of World 导出的 <span class="mono">.fwss</span> 快照,在足迹地图上叠加已探索区域。
迷雾网格为 WGS-84,站点会自动对高德等 GCJ-02 底图做纠偏。
迷雾是站点级数据,不属于任何数据集,删除数据集不影响迷雾。
{{if gt .FogBlocks 0}}
当前已入库 <span class="mono">{{num .FogBlocks}}</span> 块 / <span class="mono">{{num .FogCells}}</span> 格,
估算已探索 <span class="mono">{{printf "%.1f" .FogArea}}</span> km²{{if .FogUpdatedAt}},最近更新 {{dtt .FogUpdatedAt}}{{end}}。
{{else}}
<b>尚未导入迷雾</b>——把 Fog of World 的 <span class="mono">.fwss</span>(在 App 内导出,通常在 zip 里)上传即可点亮地图。
{{end}}
</div>
<form method="post" action="/admin/fog" enctype="multipart/form-data">
<label class="f" style="max-width:520px">
<span>选择快照</span>
<input type="file" name="fwss" accept=".fwss,.zip" required
style="padding:8px;border:1px dashed var(--line);border-radius:8px;background:var(--bg-2)">
</label>
<label class="f" style="max-width:520px">
<span>导入方式</span>
<select name="mode">
<option value="overlay" selected>叠加 — 保留现有迷雾,把新路线合并进来</option>
<option value="cover">覆盖 — 清空现有迷雾,整体替换</option>
</select>
</label>
<button class="btn primary" type="submit">导入迷雾</button>
</form>
{{if gt .FogBlocks 0}}
<div style="margin:10px 0 0;display:flex;gap:8px;flex-wrap:wrap">
<a class="btn" href="/admin/fog/export">导出当前迷雾(.fwss)</a>
<a class="btn" href="/admin/fog/mask">迷雾遮罩区{{if .FogMasks}}({{.FogMasks}}){{end}}</a>
<form method="post" action="/admin/fog/clear"
onsubmit="return confirm('将删除全部迷雾数据(数据库与地图图层同步清空),且不可恢复。确认清空?')">
<button class="btn danger" type="submit">清空迷雾</button>
</form>
</div>
{{end}}
</div>
<div class="card">
<h2>数据导出</h2>
<div class="card-sub">
把当前展示的数据集导出为通用格式,方便备份或迁移到其他平台。
坐标保持入库时的 GCJ-02,GeoJSON 里已注明坐标系。
</div>
<div class="row">
<a class="btn" href="/admin/export/places.geojson">导出地点(GeoJSON)</a>
<a class="btn" href="/admin/export/places.gpx">导出地点(GPX)</a>
</div>
<div class="card-sub" style="margin-top:14px">
也可导出为 rond 原始格式的 <span class="mono">.rondbackup</span>(含你在<a href="/admin/edit">数据编辑</a>里补录的记录),可直接导回 rond App。
坐标为 GCJ-02,原样写回、无需纠偏。
</div>
<a class="btn primary" href="/admin/export/rondbackup">导出 rondbackup(可回导 rond)</a>
</div>
<div class="card">
<div class="row" style="justify-content:space-between;align-items:center">
<h2 style="margin:0">已导入的数据集</h2>
<form method="post" action="/admin/places/backfill"
onsubmit="return confirm('对缺地址 / 没名字的地点逐个反查高德补全?(每次处理 100 个)')">
<button class="btn sm" type="submit">补全缺失地址</button>
</form>
</div>
<div class="card-sub">同一时刻只有一份数据处于「展示中」状态,主页与地图读取的就是它</div>
{{if .Datasets}}
<div class="tw">
<table class="tb tb-stack">
<thead>
<tr><th>文件</th><th>导入时间</th><th class="num">到访</th><th class="num">地点</th><th>数据跨度</th><th>状态</th><th></th></tr>
</thead>
<tbody>
{{range .Datasets}}
<tr>
<td><span class="mono">{{trunc .Name 34}}</span></td>
<td class="muted" data-label="导入时间">{{dt .UploadedAt}}</td>
<td class="num" data-label="到访">{{num .Visits}}</td>
<td class="num" data-label="地点">{{num .Places}}</td>
<td class="muted" data-label="数据跨度">{{if .First}}{{d .First}} ~ {{d .Last}}{{else}}—{{end}}</td>
<td data-label="状态">
{{if and $.Dataset (eq $.Dataset.ID .ID)}}
<span class="tag">展示中</span>
{{else}}
<span class="muted">未启用</span>
{{end}}
</td>
<td data-label="操作" style="white-space:nowrap">
{{if not (and $.Dataset (eq $.Dataset.ID .ID))}}
<form method="post" action="/admin/datasets/{{.ID}}/activate" style="display:inline">
<button class="btn sm" type="submit">启用</button>
</form>
{{end}}
<form method="post" action="/admin/datasets/{{.ID}}/delete" style="display:inline"
onsubmit="return confirm('删除后该数据集的所有记录都会从数据库移除,且不可恢复。确认删除?')">
<button class="btn sm danger" type="submit">删除</button>
</form>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
{{else}}
<div class="empty"><div class="big">📦</div>还没有导入任何数据集</div>
{{end}}
</div>
<div class="card">
<h2>数据说明</h2>
<div class="card-sub">从备份中读取并转换的字段</div>
<div class="tw">
<table class="tb tb-stack">
<thead><tr><th>来源表</th><th>内容</th><th>用途</th></tr></thead>
<tbody>
<tr><td class="mono">ZVISIT</td><td data-label="内容">到访记录(到达 / 离开时间、类型、地点、备注、标签)</td><td data-label="用途">时间线、统计、地图</td></tr>
<tr><td class="mono">ZLOCATION</td><td data-label="内容">地点(名称、经纬度、城市、省份、POI 分类)</td><td data-label="用途">地图打点、地点库</td></tr>
<tr><td class="mono">ZACTIVITY</td><td data-label="内容">自定义类型(颜色、图标、是否家 / 工作)</td><td data-label="用途">类型分布</td></tr>
<tr><td class="mono">ZMOVEMENT</td><td data-label="内容">位移段(交通方式、起止时间)</td><td data-label="用途">出行方式统计</td></tr>
<tr><td class="mono">ZTAG</td><td data-label="内容">自定义标签及分组</td><td data-label="用途">标签筛选</td></tr>
<tr><td class="mono">ZHOURLYWEATHER</td><td data-label="内容">逐小时天气(气温、天气现象、湿度)</td><td data-label="用途">天气足迹</td></tr>
</tbody>
</table>
</div>
</div>
</div>
{{end}}