窄屏宽表不再横向滚动:改成一屏一行的「字段名 + 值」
移动端有 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)。
This commit is contained in:
@@ -1007,3 +1007,40 @@ label.f > span.span-actions { display: flex; align-items: center; justify-conten
|
|||||||
.filters-card.collapsed > .panel-fold { margin: 0; border-radius: var(--radius); }
|
.filters-card.collapsed > .panel-fold { margin: 0; border-radius: var(--radius); }
|
||||||
.filters-card.collapsed > :not(.panel-fold) { display: none; }
|
.filters-card.collapsed > :not(.panel-fold) { display: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- 窄屏:要横滑的宽表改成一屏一行的「字段 + 值」 ----------
|
||||||
|
地点库(8 列)、统计、专题、后台这几张表在手机上要横滑 300+px 才看得全,滑着还对不上表头。
|
||||||
|
窄屏改成每行一块、每格「字段名 + 值」竖排:不用横滑,也不用记「第几列是什么」。
|
||||||
|
字段名取 td 的 data-label,每行的首格留空当小标题(如地点名),操作格给「操作」。
|
||||||
|
表格结构与脚本都没动(只是隐藏 thead),链接 / 表单 / 按钮照旧;断点跟其它移动端适配一致
|
||||||
|
(620px),桌面与平板仍是原来的表格,一行不差。
|
||||||
|
注:统计页那几张表在宽屏也被放在 g2 的窄卡片里(视口 1440 时卡片只有 494px),仍然要横滑
|
||||||
|
100+px —— 但那属于桌面版式,真要治得单说;这里先只管移动端(按容器宽度判断会让这些卡片
|
||||||
|
在宽屏也竖排,实测把 /stats 撑高 1300px,得不偿失)。 */
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
.tw > table.tb.tb-stack { min-width: 0; }
|
||||||
|
.tw > table.tb.tb-stack thead { display: none; }
|
||||||
|
.tw > table.tb.tb-stack,
|
||||||
|
.tw > table.tb.tb-stack > tbody,
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr,
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr > td { display: block; width: auto; }
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr {
|
||||||
|
padding: 9px 11px; border-bottom: 1px solid var(--line-soft);
|
||||||
|
}
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr:last-child { border-bottom: 0; }
|
||||||
|
/* 值用悬挂缩进:标签绝对定位在左边,值换行时对齐到值那一栏,而不是缩到标签下面 */
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr > td {
|
||||||
|
position: relative; padding: 2px 0 2px 5.6em; border-bottom: 0;
|
||||||
|
}
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr > td::before {
|
||||||
|
content: attr(data-label); position: absolute; left: 0; top: 2px;
|
||||||
|
width: 5em; color: var(--text-3); font-size: 12px;
|
||||||
|
}
|
||||||
|
/* 首格是这一行的主角(地点名 / 天气 / 方式…):不缩进、字号抬一档当小标题 */
|
||||||
|
.tw > table.tb.tb-stack > tbody > tr > td:not([data-label]) {
|
||||||
|
padding-left: 0; margin-bottom: 2px; font-size: 14px;
|
||||||
|
}
|
||||||
|
/* 数字列不必再右对齐(现在已经是「标签 + 值」两栏) */
|
||||||
|
.tw > table.tb.tb-stack td.num { text-align: left; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestStackedTablesHaveLabels 守住「窄屏宽表变一屏一行」这条改动的核心不变量:
|
||||||
|
// 每张打了 tb-stack 的表,窄屏会把表头藏起来、改成「字段名 + 值」竖排,字段名只能取自
|
||||||
|
// td 的 data-label。少写一个标签,那一格在手机上就是没有名字的裸值——而桌面端一切正常,
|
||||||
|
// 很难发现(这轮就漏过两次:一张表的中间几行、后台两张表的「状态 / 对访客 / 操作」)。
|
||||||
|
// 顺带钉住每行格子数 == 表头列数,否则说明模板结构歪了。
|
||||||
|
//
|
||||||
|
// ROND_TEST_CONF=conf/app-test.ini ROND_SRC=data/xxx.rondbackup go test ./internal/web -run StackedTables -v
|
||||||
|
func TestStackedTablesHaveLabels(t *testing.T) {
|
||||||
|
f := newMovementFixture(t)
|
||||||
|
|
||||||
|
var topicID int64
|
||||||
|
if err := f.pg.QueryRowContext(f.ctx, `SELECT id FROM topics WHERE dataset_id=$1 ORDER BY id LIMIT 1`,
|
||||||
|
f.dsID).Scan(&topicID); err != nil {
|
||||||
|
topicID = 0 // 这个数据集没有专题,就少查一页
|
||||||
|
}
|
||||||
|
|
||||||
|
type target struct {
|
||||||
|
path string
|
||||||
|
h http.HandlerFunc
|
||||||
|
admin bool
|
||||||
|
}
|
||||||
|
targets := []target{
|
||||||
|
{"/places", f.srv.placesPage, false},
|
||||||
|
{"/stats", f.srv.statsPage, false},
|
||||||
|
{"/", f.srv.home, false},
|
||||||
|
{"/report", f.srv.reportPage, false},
|
||||||
|
{"/admin", f.srv.adminHome, true},
|
||||||
|
{"/admin/topics", f.srv.topicsAdminPage, true},
|
||||||
|
}
|
||||||
|
if topicID > 0 {
|
||||||
|
targets = append(targets, target{"/topics/" + strconv.FormatInt(topicID, 10), f.srv.topicPage, false})
|
||||||
|
}
|
||||||
|
|
||||||
|
tableRe := regexp.MustCompile(`(?s)<table[^>]*class="[^"]*tb-stack[^"]*"[^>]*>.*?</table>`)
|
||||||
|
rowRe := regexp.MustCompile(`(?s)<tr[^>]*>(.*?)</tr>`)
|
||||||
|
tdRe := regexp.MustCompile(`(?s)<td([^>]*)>`)
|
||||||
|
thRe := regexp.MustCompile(`<th[\s>]`)
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
for _, tg := range targets {
|
||||||
|
ctx := context.Background()
|
||||||
|
if tg.admin {
|
||||||
|
ctx = f.ctx // 夹具的 ctx 里已经注入登录态
|
||||||
|
}
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
tg.h(w, httptest.NewRequest("GET", tg.path, nil).WithContext(ctx))
|
||||||
|
if w.Code != 200 {
|
||||||
|
t.Logf("%s 渲染 code=%d,跳过", tg.path, w.Code)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for ti, tb := range tableRe.FindAllString(w.Body.String(), -1) {
|
||||||
|
total++
|
||||||
|
head := ""
|
||||||
|
if i, j := strings.Index(tb, "<thead>"), strings.Index(tb, "</thead>"); i >= 0 && j > i {
|
||||||
|
head = tb[i:j]
|
||||||
|
}
|
||||||
|
cols := len(thRe.FindAllString(head, -1))
|
||||||
|
for ri, row := range rowRe.FindAllString(tb, -1) {
|
||||||
|
if !strings.Contains(row, "<td") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cells := tdRe.FindAllStringSubmatch(row, -1)
|
||||||
|
if cols > 0 && len(cells) != cols {
|
||||||
|
t.Errorf("%s 第 %d 张表第 %d 行有 %d 格,表头 %d 列", tg.path, ti+1, ri+1, len(cells), cols)
|
||||||
|
}
|
||||||
|
for ci, c := range cells {
|
||||||
|
if ci == 0 {
|
||||||
|
continue // 首格是这一行的主角,故意不带标签
|
||||||
|
}
|
||||||
|
if !strings.Contains(c[1], "data-label=") {
|
||||||
|
t.Errorf("%s 第 %d 张表第 %d 行第 %d 格没有 data-label(窄屏会变成没有名字的裸值)",
|
||||||
|
tg.path, ti+1, ri+1, ci+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if total == 0 {
|
||||||
|
t.Fatal("一页 tb-stack 表都没找到:模板里的类名是不是被改掉了")
|
||||||
|
}
|
||||||
|
t.Logf("检查了 %d 张 tb-stack 表", total)
|
||||||
|
}
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
<div class="card-sub">同一时刻只有一份数据处于「展示中」状态,主页与地图读取的就是它</div>
|
<div class="card-sub">同一时刻只有一份数据处于「展示中」状态,主页与地图读取的就是它</div>
|
||||||
{{if .Datasets}}
|
{{if .Datasets}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>文件</th><th>导入时间</th><th class="num">到访</th><th class="num">地点</th><th>数据跨度</th><th>状态</th><th></th></tr>
|
<tr><th>文件</th><th>导入时间</th><th class="num">到访</th><th class="num">地点</th><th>数据跨度</th><th>状态</th><th></th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -116,18 +116,18 @@
|
|||||||
{{range .Datasets}}
|
{{range .Datasets}}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="mono">{{trunc .Name 34}}</span></td>
|
<td><span class="mono">{{trunc .Name 34}}</span></td>
|
||||||
<td class="muted">{{dt .UploadedAt}}</td>
|
<td class="muted" data-label="导入时间">{{dt .UploadedAt}}</td>
|
||||||
<td class="num">{{num .Visits}}</td>
|
<td class="num" data-label="到访">{{num .Visits}}</td>
|
||||||
<td class="num">{{num .Places}}</td>
|
<td class="num" data-label="地点">{{num .Places}}</td>
|
||||||
<td class="muted">{{if .First}}{{d .First}} ~ {{d .Last}}{{else}}—{{end}}</td>
|
<td class="muted" data-label="数据跨度">{{if .First}}{{d .First}} ~ {{d .Last}}{{else}}—{{end}}</td>
|
||||||
<td>
|
<td data-label="状态">
|
||||||
{{if and $.Dataset (eq $.Dataset.ID .ID)}}
|
{{if and $.Dataset (eq $.Dataset.ID .ID)}}
|
||||||
<span class="tag">展示中</span>
|
<span class="tag">展示中</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="muted">未启用</span>
|
<span class="muted">未启用</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td style="white-space:nowrap">
|
<td data-label="操作" style="white-space:nowrap">
|
||||||
{{if not (and $.Dataset (eq $.Dataset.ID .ID))}}
|
{{if not (and $.Dataset (eq $.Dataset.ID .ID))}}
|
||||||
<form method="post" action="/admin/datasets/{{.ID}}/activate" style="display:inline">
|
<form method="post" action="/admin/datasets/{{.ID}}/activate" style="display:inline">
|
||||||
<button class="btn sm" type="submit">启用</button>
|
<button class="btn sm" type="submit">启用</button>
|
||||||
@@ -152,15 +152,15 @@
|
|||||||
<h2>数据说明</h2>
|
<h2>数据说明</h2>
|
||||||
<div class="card-sub">从备份中读取并转换的字段</div>
|
<div class="card-sub">从备份中读取并转换的字段</div>
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>来源表</th><th>内容</th><th>用途</th></tr></thead>
|
<thead><tr><th>来源表</th><th>内容</th><th>用途</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td class="mono">ZVISIT</td><td>到访记录(到达 / 离开时间、类型、地点、备注、标签)</td><td>时间线、统计、地图</td></tr>
|
<tr><td class="mono">ZVISIT</td><td data-label="内容">到访记录(到达 / 离开时间、类型、地点、备注、标签)</td><td data-label="用途">时间线、统计、地图</td></tr>
|
||||||
<tr><td class="mono">ZLOCATION</td><td>地点(名称、经纬度、城市、省份、POI 分类)</td><td>地图打点、地点库</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>自定义类型(颜色、图标、是否家 / 工作)</td><td>类型分布</td></tr>
|
<tr><td class="mono">ZACTIVITY</td><td data-label="内容">自定义类型(颜色、图标、是否家 / 工作)</td><td data-label="用途">类型分布</td></tr>
|
||||||
<tr><td class="mono">ZMOVEMENT</td><td>位移段(交通方式、起止时间)</td><td>出行方式统计</td></tr>
|
<tr><td class="mono">ZMOVEMENT</td><td data-label="内容">位移段(交通方式、起止时间)</td><td data-label="用途">出行方式统计</td></tr>
|
||||||
<tr><td class="mono">ZTAG</td><td>自定义标签及分组</td><td>标签筛选</td></tr>
|
<tr><td class="mono">ZTAG</td><td data-label="内容">自定义标签及分组</td><td data-label="用途">标签筛选</td></tr>
|
||||||
<tr><td class="mono">ZHOURLYWEATHER</td><td>逐小时天气(气温、天气现象、湿度)</td><td>天气足迹</td></tr>
|
<tr><td class="mono">ZHOURLYWEATHER</td><td data-label="内容">逐小时天气(气温、天气现象、湿度)</td><td data-label="用途">天气足迹</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -50,23 +50,23 @@
|
|||||||
<div class="card-sub">共 {{len .Topics}} 个;「对访客」一列是展示开关,关掉的专题只有你自己能预览</div>
|
<div class="card-sub">共 {{len .Topics}} 个;「对访客」一列是展示开关,关掉的专题只有你自己能预览</div>
|
||||||
{{if .Topics}}
|
{{if .Topics}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<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>
|
<thead><tr><th>标题</th><th>时间范围</th><th class="num">地点</th><th class="num">到访</th><th>区域</th><th>对访客</th><th></th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Topics}}
|
{{range .Topics}}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/topics/{{.ID}}" target="_blank">{{.Title}}</a>{{if .Subtitle}} <span class="muted">· {{.Subtitle}}</span>{{end}}</td>
|
<td><a href="/topics/{{.ID}}" target="_blank">{{.Title}}</a>{{if .Subtitle}} <span class="muted">· {{.Subtitle}}</span>{{end}}</td>
|
||||||
<td class="muted mono">{{.RangeLabel}}</td>
|
<td class="muted mono" data-label="时间范围">{{.RangeLabel}}</td>
|
||||||
<td class="num">{{num .PlaceCount}}</td>
|
<td class="num" data-label="地点">{{num .PlaceCount}}</td>
|
||||||
<td class="num">{{num .VisitCount}}</td>
|
<td class="num" data-label="到访">{{num .VisitCount}}</td>
|
||||||
<td class="muted">{{if .HasArea}}{{printf "%.1f" .RadiusKm}} km 内{{else}}不限{{end}}</td>
|
<td class="muted" data-label="区域">{{if .HasArea}}{{printf "%.1f" .RadiusKm}} km 内{{else}}不限{{end}}</td>
|
||||||
<td>
|
<td data-label="对访客">
|
||||||
<form method="post" action="/admin/topics/toggle" style="display:inline">
|
<form method="post" action="/admin/topics/toggle" style="display:inline">
|
||||||
<input type="hidden" name="id" value="{{.ID}}">
|
<input type="hidden" name="id" value="{{.ID}}">
|
||||||
<button class="btn sm {{if .Enabled}}primary{{end}}" type="submit">{{if .Enabled}}展示中{{else}}已隐藏{{end}}</button>
|
<button class="btn sm {{if .Enabled}}primary{{end}}" type="submit">{{if .Enabled}}展示中{{else}}已隐藏{{end}}</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
<td style="white-space:nowrap">
|
<td data-label="操作" style="white-space:nowrap">
|
||||||
<a class="btn sm" href="/admin/topics?edit={{.ID}}">编辑</a>
|
<a class="btn sm" href="/admin/topics?edit={{.ID}}">编辑</a>
|
||||||
<form method="post" action="/admin/topics/delete" style="display:inline"
|
<form method="post" action="/admin/topics/delete" style="display:inline"
|
||||||
onsubmit="return confirm('删除专题「{{.Title}}」?地点数据不受影响。')">
|
onsubmit="return confirm('删除专题「{{.Title}}」?地点数据不受影响。')">
|
||||||
|
|||||||
@@ -132,15 +132,15 @@
|
|||||||
<h2>天气足迹</h2>
|
<h2>天气足迹</h2>
|
||||||
<div class="card-sub">记录期间经历过的天气</div>
|
<div class="card-sub">记录期间经历过的天气</div>
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>天气</th><th class="num">记录小时数</th><th class="num">平均气温</th><th class="num">范围</th></tr></thead>
|
<thead><tr><th>天气</th><th class="num">记录小时数</th><th class="num">平均气温</th><th class="num">范围</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Weather}}
|
{{range .Weather}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{condition .Condition}}</td>
|
<td>{{condition .Condition}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="记录小时数">{{num .Count}}</td>
|
||||||
<td class="num">{{f1 .AvgTemp}} ℃</td>
|
<td class="num" data-label="平均气温">{{f1 .AvgTemp}} ℃</td>
|
||||||
<td class="num">{{f1 .MinTemp}} ~ {{f1 .MaxTemp}} ℃</td>
|
<td class="num" data-label="范围">{{f1 .MinTemp}} ~ {{f1 .MaxTemp}} ℃</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
{{if .Places}}
|
{{if .Places}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb places-table">
|
<table class="tb places-table tb-stack">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>地点</th><th>城市</th><th>主要类型</th><th>图片</th>
|
<th>地点</th><th>城市</th><th>主要类型</th><th>图片</th>
|
||||||
@@ -57,15 +57,15 @@
|
|||||||
{{if eq .Verdict 1}}<span class="tag vote-up">👍 推荐</span>{{else if eq .Verdict -1}}<span class="tag vote-down">👎 踩雷</span>{{end}}
|
{{if eq .Verdict 1}}<span class="tag vote-up">👍 推荐</span>{{else if eq .Verdict -1}}<span class="tag vote-down">👎 踩雷</span>{{end}}
|
||||||
{{if or .Up .Down}}<span class="muted" style="font-size:12px">👍{{.Up}} · 👎{{.Down}}</span>{{end}}
|
{{if or .Up .Down}}<span class="muted" style="font-size:12px">👍{{.Up}} · 👎{{.Down}}</span>{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td class="muted">{{if .City}}{{.City}}{{else}}—{{end}}</td>
|
<td class="muted" data-label="城市">{{if .City}}{{.City}}{{else}}—{{end}}</td>
|
||||||
<td>
|
<td data-label="主要类型">
|
||||||
{{if .TopActivity}}<span class="chip" style="padding:1px 8px"><span class="dot" style="background:{{colorof .TopColor}}"></span>{{.TopActivity}}</span>{{else}}<span class="muted">—</span>{{end}}
|
{{if .TopActivity}}<span class="chip" style="padding:1px 8px"><span class="dot" style="background:{{colorof .TopColor}}"></span>{{.TopActivity}}</span>{{else}}<span class="muted">—</span>{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td>{{if .HasImage}}<span title="有图片">📷</span>{{else}}<span class="muted" title="还没有上传图片">—</span>{{end}}</td>
|
<td data-label="图片">{{if .HasImage}}<span title="有图片">📷</span>{{else}}<span class="muted" title="还没有上传图片">—</span>{{end}}</td>
|
||||||
<td class="num">{{num .VisitCount}}</td>
|
<td class="num" data-label="到访">{{num .VisitCount}}</td>
|
||||||
<td class="num">{{dur .DwellMinutes}}</td>
|
<td class="num" data-label="累计停留">{{dur .DwellMinutes}}</td>
|
||||||
<td class="muted">{{if .FirstAt}}{{d .FirstAt}}{{else}}—{{end}}</td>
|
<td class="muted" data-label="首次">{{if .FirstAt}}{{d .FirstAt}}{{else}}—{{end}}</td>
|
||||||
<td class="muted">{{if .LastAt}}{{d .LastAt}}{{end}}</td>
|
<td class="muted" data-label="最近">{{if .LastAt}}{{d .LastAt}}{{end}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -64,11 +64,11 @@
|
|||||||
<div class="card-sub">这一年到过纬度最高与最低的地点</div>
|
<div class="card-sub">这一年到过纬度最高与最低的地点</div>
|
||||||
{{if .North}}
|
{{if .North}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>方位</th><th>地点</th><th class="num">纬度</th></tr></thead>
|
<thead><tr><th>方位</th><th>地点</th><th class="num">纬度</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>最北</td><td>{{.North.Name}}<span class="muted"> · {{.North.City}}</span></td><td class="num">{{f1 .North.Lat}}°N</td></tr>
|
<tr><td>最北</td><td data-label="地点">{{.North.Name}}<span class="muted"> · {{.North.City}}</span></td><td class="num" data-label="纬度">{{f1 .North.Lat}}°N</td></tr>
|
||||||
{{if .South}}<tr><td>最南</td><td>{{.South.Name}}<span class="muted"> · {{.South.City}}</span></td><td class="num">{{f1 .South.Lat}}°N</td>{{end}}
|
{{if .South}}<tr><td>最南</td><td data-label="地点">{{.South.Name}}<span class="muted"> · {{.South.City}}</span></td><td class="num" data-label="纬度">{{f1 .South.Lat}}°N</td>{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,14 +81,14 @@
|
|||||||
<h2>在路上</h2>
|
<h2>在路上</h2>
|
||||||
<div class="card-sub">这一年 {{num .Overview.Movements}} 段行程,共 {{km .Overview.DistanceKm}} km</div>
|
<div class="card-sub">这一年 {{num .Overview.Movements}} 段行程,共 {{km .Overview.DistanceKm}} km</div>
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>方式</th><th class="num">次数</th><th class="num">里程</th></tr></thead>
|
<thead><tr><th>方式</th><th class="num">次数</th><th class="num">里程</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Transports}}
|
{{range .Transports}}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="dot" style="display:inline-block;background:{{colorof .Color}}"></span> {{with icon .Icon}}{{.}} {{end}}{{.Name}}</td>
|
<td><span class="dot" style="display:inline-block;background:{{colorof .Color}}"></span> {{with icon .Icon}}{{.}} {{end}}{{.Name}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="次数">{{num .Count}}</td>
|
||||||
<td class="num">{{km .Distance}} km</td>
|
<td class="num" data-label="里程">{{km .Distance}} km</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -103,15 +103,15 @@
|
|||||||
<h2>省级行政区</h2>
|
<h2>省级行政区</h2>
|
||||||
<div class="card-sub">覆盖情况</div>
|
<div class="card-sub">覆盖情况</div>
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>省份</th><th class="num">城市</th><th class="num">地点</th><th class="num">到访</th></tr></thead>
|
<thead><tr><th>省份</th><th class="num">城市</th><th class="num">地点</th><th class="num">到访</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .ProvinceStats}}
|
{{range .ProvinceStats}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.Province}}</td>
|
<td>{{.Province}}</td>
|
||||||
<td class="num">{{num .Cities}}</td>
|
<td class="num" data-label="城市">{{num .Cities}}</td>
|
||||||
<td class="num">{{num .Places}}</td>
|
<td class="num" data-label="地点">{{num .Places}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="到访">{{num .Count}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -141,15 +141,15 @@
|
|||||||
<div class="card-sub">次数与估算里程</div>
|
<div class="card-sub">次数与估算里程</div>
|
||||||
{{if .Transports}}
|
{{if .Transports}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>方式</th><th class="num">次数</th><th class="num">里程</th><th class="num">在途时间</th></tr></thead>
|
<thead><tr><th>方式</th><th class="num">次数</th><th class="num">里程</th><th class="num">在途时间</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Transports}}
|
{{range .Transports}}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="dot" style="display:inline-block;background:{{colorof .Color}}"></span> {{with icon .Icon}}{{.}} {{end}}{{.Name}}</td>
|
<td><span class="dot" style="display:inline-block;background:{{colorof .Color}}"></span> {{with icon .Icon}}{{.}} {{end}}{{.Name}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="次数">{{num .Count}}</td>
|
||||||
<td class="num">{{km .Distance}} km</td>
|
<td class="num" data-label="里程">{{km .Distance}} km</td>
|
||||||
<td class="num">{{dur .DwellMin}}</td>
|
<td class="num" data-label="在途时间">{{dur .DwellMin}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -181,14 +181,14 @@
|
|||||||
<h2>天气与气温</h2>
|
<h2>天气与气温</h2>
|
||||||
<div class="card-sub">记录期间经历的小时级天气</div>
|
<div class="card-sub">记录期间经历的小时级天气</div>
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>天气</th><th class="num">小时数</th><th class="num">平均气温</th></tr></thead>
|
<thead><tr><th>天气</th><th class="num">小时数</th><th class="num">平均气温</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Weather}}
|
{{range .Weather}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{condition .Condition}}</td>
|
<td>{{condition .Condition}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="小时数">{{num .Count}}</td>
|
||||||
<td class="num">{{f1 .AvgTemp}} ℃</td>
|
<td class="num" data-label="平均气温">{{f1 .AvgTemp}} ℃</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -42,17 +42,17 @@
|
|||||||
<div class="card-sub">共 {{num .Topic.PlaceCount}} 个,按到访次数排序</div>
|
<div class="card-sub">共 {{num .Topic.PlaceCount}} 个,按到访次数排序</div>
|
||||||
{{if .Points}}
|
{{if .Points}}
|
||||||
<div class="tw">
|
<div class="tw">
|
||||||
<table class="tb">
|
<table class="tb tb-stack">
|
||||||
<thead><tr><th>地点</th><th>城市</th><th>类型</th><th class="num">到访</th><th class="num">停留</th><th>最近一次</th></tr></thead>
|
<thead><tr><th>地点</th><th>城市</th><th>类型</th><th class="num">到访</th><th class="num">停留</th><th>最近一次</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Points}}
|
{{range .Points}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{if .Name}}{{.Name}}{{else}}<span class="muted">(未命名)</span>{{end}}</td>
|
<td>{{if .Name}}{{.Name}}{{else}}<span class="muted">(未命名)</span>{{end}}</td>
|
||||||
<td class="muted">{{.City}}</td>
|
<td class="muted" data-label="城市">{{.City}}</td>
|
||||||
<td class="muted">{{if .Act}}<span class="dot" style="background:{{colorof .Color}}"></span>{{.Act}}{{end}}</td>
|
<td class="muted" data-label="类型">{{if .Act}}<span class="dot" style="background:{{colorof .Color}}"></span>{{.Act}}{{end}}</td>
|
||||||
<td class="num">{{num .Count}}</td>
|
<td class="num" data-label="到访">{{num .Count}}</td>
|
||||||
<td class="num muted">{{dur .Dwell}}</td>
|
<td class="num muted" data-label="停留">{{dur .Dwell}}</td>
|
||||||
<td class="muted mono">{{.LastAt}}</td>
|
<td class="muted mono" data-label="最近一次">{{.LastAt}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Reference in New Issue
Block a user