Files
rond-with-you/internal/web/templates/home.html
T
tamakyi 5c7cf1a0e1 对访客公开的措辞按身份分支:访客不该看到「我的结论」
用户发现未登录也显示「推荐 & 踩雷(我的结论)」,访客没法解读「谁的我的」。
顺着把访客可见模板与 static/js 全过了一遍,同病共四处——都是**写模板时站在站长视角下笔、
而那一块又对访客公开**:

1. stats.html:标题 → {{if .IsAdmin}}我的结论{{else}}站长结论{{end}};
   副标题「只统计你自己…」→ 站长「你自己」/ 访客「站长」;两列「我推荐/我踩雷的地点」同理。
2. stats.html 访客块:「与我的结论互不影响:你标你的,访客投访客的」——对访客说不通,
   改成对两边都成立的「与上面的站长结论互不影响:各存各的表,谁也不会覆盖谁」。
3. home.html:「我的标签」→「足迹标签」(同级卡片全是中性的:足迹地图/城市足迹/天气足迹…)。
4. report.html:「这一年里,你第一次踏足的这些城市」→ 去掉人称(年报是站长的回顾)。

已经写对的照它学:place.html 的投票区早就是 {{if .IsAdmin}} 分支(站长「我的结论」、
访客「大家怎么说」),rond-map.js 的气泡同理;「含家/工作」chip 与一串「只有你自己能看到」
本来就在站长分支里。

门禁 TestVisitorPagesUseThirdPersonCopy:以**访客 ctx(无 user)**渲染 /、/stats、/report,
逐个禁用词断言,同时断言站长那份**仍旧说「我的」**(别把站长自己的视角也改掉);
前置需打开 marks_public(访客才看得到那一块),用完还原。

⚠️ 变异验证时踩了老坑:直接 `go test -run …` 因缺 ROND_TEST_CONF/ROND_SRC 会**静默 skip 并报 ok**
(0.17s 就 ok,一眼假绿)。改用 ./scripts/verify.sh 后变异被正确抓住
(visitor_copy_test.go:85 报「我的结论」),还原后转绿。

全量验收 PASS=339 FAIL=0 SKIP=0。
2026-10-01 02:15:49 +08:00

183 lines
7.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"}}
{{if not .HasData}}
<div class="wrap">{{template "emptystate" .}}</div>
{{else}}
<div class="wrap">
<div class="page-head">
<div>
<h1>{{.Settings.OwnerAvatar}} {{.Settings.OwnerName}}</h1>
<div class="sub">{{if .Settings.SiteSubtitle}}{{.Settings.SiteSubtitle}} · {{end}}{{.RangeLabel}}</div>
</div>
<div class="row">
<a class="btn" href="/map">全屏地图</a>
<a class="btn" href="/stats">数据统计</a>
</div>
</div>
{{if .Settings.Has "overview"}}
<div class="kpis" style="margin-bottom:16px">
<div class="kpi"><div class="v">{{num .Overview.Places}}<small>个</small></div><div class="k">去过的地点</div></div>
<div class="kpi"><div class="v">{{num .Overview.Cities}}<small>座</small></div><div class="k">到过的城市</div></div>
<div class="kpi"><div class="v">{{num .Overview.Provinces}}<small>个</small></div><div class="k">覆盖省份</div></div>
<div class="kpi"><div class="v">{{num .Overview.Days}}<small>天</small></div><div class="k">有记录的日子</div></div>
<div class="kpi"><div class="v">{{num .Overview.Visits}}<small>次</small></div><div class="k">累计到访</div></div>
<div class="kpi"><div class="v">{{dur .Overview.DwellMin}}</div><div class="k">累计停留</div></div>
<div class="kpi"><div class="v">{{km .Overview.DistanceKm}}<small>km</small></div><div class="k">出行里程</div></div>
<div class="kpi"><div class="v">{{if .Overview.FirstAt}}{{since .Overview.FirstAt}}{{else}}—{{end}}</div><div class="k">开始记录于</div></div>
</div>
{{end}}
{{if and (.Settings.Has "map") .Points}}
<div class="card">
<h2>足迹地图</h2>
<div class="card-sub">共 {{num (len .Points)}} 个地点{{if .Settings.HideHome}} · 已隐藏「家」{{end}}{{if .Settings.HideWork}} · 已隐藏「工作」{{end}}</div>
<div id="home-map" class="map-preview"></div>
<div style="margin-top:10px;font-size:12.5px" class="muted">滚轮被禁用,点击地图进入全屏模式查看细节与筛选。</div>
</div>
{{end}}
<div class="grid g2">
{{if and (.Settings.Has "types") .ActivityStats}}
<div class="card">
<h2>去过的类型</h2>
<div class="card-sub">按到访次数排序</div>
<div class="bars">
{{range .ActivityStats}}
<div class="bar-row">
<div class="nm" title="{{.Name}}">{{with icon .Icon}}{{.}} {{end}}{{.Name}}</div>
<div class="bar-track"><div class="bar-fill" style="width:{{pct .Count $.MaxActivity}}%;background:{{colorof .Color}}"></div></div>
<div class="vv">{{num .Count}} 次</div>
</div>
{{end}}
</div>
</div>
{{end}}
{{if and (.Settings.Has "cities") .CityStats}}
<div class="card">
<h2>城市足迹</h2>
<div class="card-sub">按到访次数排序</div>
<div class="bars">
{{range .CityStats}}
<div class="bar-row">
<div class="nm"><a href="{{$.CityLink .City}}">{{.City}}</a></div>
<div class="bar-track"><div class="bar-fill" style="width:{{pct .Count $.MaxCity}}%"></div></div>
<div class="vv">{{num .Count}} 次</div>
</div>
{{end}}
</div>
<div style="margin-top:12px" class="muted">共覆盖 {{num .Overview.Cities}} 座城市、{{num .Overview.Provinces}} 个省级行政区。</div>
</div>
{{end}}
</div>
{{if .Monthly}}
<div class="card">
<h2>月度活跃度</h2>
<div class="card-sub">每月到访次数</div>
<div class="cols">
{{range .Monthly}}<div class="col" style="height:{{.Pct}}%" title="{{.Key}}:{{.Count}} 次"></div>{{end}}
</div>
<div class="cols-x">{{range .Monthly}}<span>{{.Label}}</span>{{end}}</div>
</div>
{{end}}
{{if and (.Settings.Has "heatmap") .Calendar}}
<div class="card">
<h2>活跃日历</h2>
<div class="card-sub">每一列是一周,颜色越深记录越多</div>
<div class="heat">
{{range .Calendar}}<div class="wk">{{range .Days}}<div class="d {{if gt .Level 0}}l{{.Level}}{{end}}" title="{{.Title}}"></div>{{end}}</div>{{end}}
</div>
<div class="heat-legend">少 <span class="d"></span><span class="d l1"></span><span class="d l2"></span><span class="d l3"></span><span class="d l4"></span> 多</div>
</div>
{{end}}
<div class="grid g2">
{{if and (.Settings.Has "transport") .Transports}}
<div class="card">
<h2>出行方式</h2>
<div class="card-sub">按次数排序,里程为两点间直线距离估算</div>
<div class="bars">
{{range .Transports}}
<div class="bar-row">
<div class="nm">{{with icon .Icon}}{{.}} {{end}}{{.Name}}</div>
<div class="bar-track"><div class="bar-fill" style="width:{{pct .Count $.MaxTransport}}%;background:{{colorof .Color}}"></div></div>
<div class="vv">{{num .Count}} 次</div>
</div>
{{end}}
</div>
</div>
{{end}}
{{if and (.Settings.Has "tags") .Tags}}
<div class="card">
<h2>足迹标签</h2>
<div class="card-sub">记录时打上的自定义标签</div>
<div class="chips">
{{range .Tags}}
<a class="chip" href="{{$.TagLink .ID}}" title="{{num .Count}} 次">
<span class="dot" style="background:{{colorof .Color}}"></span>{{.Name}}
<span class="muted">{{num .Count}}</span>
</a>
{{end}}
</div>
</div>
{{end}}
</div>
{{if and (.Settings.Has "weather") .Weather}}
<div class="card">
<h2>天气足迹</h2>
<div class="card-sub">记录期间经历过的天气</div>
<div class="tw">
<table class="tb tb-stack">
<thead><tr><th>天气</th><th class="num">记录小时数</th><th class="num">平均气温</th><th class="num">范围</th></tr></thead>
<tbody>
{{range .Weather}}
<tr>
<td>{{condition .Condition}}</td>
<td class="num" data-label="记录小时数">{{num .Count}}</td>
<td class="num" data-label="平均气温">{{f1 .AvgTemp}} ℃</td>
<td class="num" data-label="范围">{{f1 .MinTemp}} ~ {{f1 .MaxTemp}} ℃</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
{{end}}
{{if and (.Settings.Has "timeline") .Recent}}
<div class="card">
<h2>最近足迹</h2>
<div class="card-sub">最新 {{num (len .Recent)}} 条到访记录</div>
<div class="list">
{{range .Recent}}
<div class="item">
<div class="ic" style="background:{{colorof .Color}}22">{{iconor .Icon "📍"}}</div>
<div>
<div class="t">{{if .PlaceID}}<a href="{{$.PlaceLink .PlaceID}}">{{.PlaceName}}</a>{{else}}未命名地点{{end}}</div>
<div class="m">{{day .Arrival}} · {{hm .Arrival}}{{if .City}} · {{.City}}{{end}}{{if .ActivityName}} · {{.ActivityName}}{{end}}{{if .Tags}} · {{range $i, $t := .Tags}}{{if $i}}、{{end}}<span class="tag">{{$t}}</span>{{end}}{{end}}</div>
</div>
<div class="r">{{dur .DurationMin}}<br><span class="muted">{{since .Arrival}}</span></div>
</div>
{{end}}
</div>
<div style="margin-top:12px"><a class="btn sm" href="/timeline">查看完整时间线 →</a></div>
</div>
{{end}}
</div>
{{if and (.Settings.Has "map") .Points}}
<script>
window.addEventListener('load', function () {
window.rondMap.preview({ id: 'home-map', points: {{json .Points}}, clickToFull: true });
});
</script>
{{end}}
{{end}}
{{end}}