审计修复:前端(模板 / CSS / JS 与无障碍)
- 地图脚本:localStorage 读写走 lsGet/lsSet 兜底(隐私模式下裸访问会打断整段脚本); preview() 在 /api/map-config 还没回来时不丢点(previewQueue 在 if (live) 之前排队); 异步回包一律发序号作废,取消后回来的包不再画 - photo-exif.js:EXIF 时间全 0 不再变成 1899-11-30 写进到访时间;读 count 前先按版本卡宽度 - 数据编辑页:三个筛选表单都把其余条件用隐藏域原样带上,提交不再把别的列表的筛选清掉 - 补全页:sessionStorage 的读写一律包 try(脏数据/隐私模式都会抛) - 窄屏:删掉被后面同特异性规则盖掉的死内边距;宽表堆叠类名成对、判据扩到所有 tb 表 - 无障碍:图片删除按钮补 aria-label,访客画廊图片补 alt - report.html 补上漏掉的 </tr>,fog-mask 的宽表带 tb-stack 本批不碰数据库与导出路径:往返包 823/323/8/30/791/557/2246 全等、 坐标偏差 0.000000000、时间偏差 0s、迷雾 8701 块一致。
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestPageTemplatesParse 把每个页面模板都解析一遍。
|
||||
@@ -17,3 +20,48 @@ func TestPageTemplatesParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestLayoutFooterToleratesMissingLastVisit 钉住页脚在「数据集一条到访都没有」时也渲染得完。
|
||||
//
|
||||
// last_visit_at 可以为 NULL(refreshDatasetAgg 用 LEFT JOIN 求 max,零到访就写 NULL),
|
||||
// 而 d 的形参是 time.Time、实参是 *time.Time:非 nil 时模板会自动解一层指针,**nil 时报
|
||||
// "dereference of nil pointer" 并中断渲染**。render() 只把错误记进日志,客户端拿到的是
|
||||
// HTTP 200 加一个「页脚之后整段不存在」的页面——滚动恢复、地图脚本引入全丢,
|
||||
// 服务端一点动静都没有。所以这里断言「有收尾的 </html>」,而不只是断言没报错。
|
||||
func TestLayoutFooterToleratesMissingLastVisit(t *testing.T) {
|
||||
base, err := template.New("layout.html").Funcs(templateFuncs()).ParseFS(tmplFS, "templates/layout.html")
|
||||
if err != nil {
|
||||
t.Fatalf("解析 layout.html: %v", err)
|
||||
}
|
||||
tpl, err := base.Parse(`{{define "content"}}正文{{end}}`)
|
||||
if err != nil {
|
||||
t.Fatalf("补 content 块: %v", err)
|
||||
}
|
||||
last := time.Date(2026, 9, 21, 12, 0, 0, 0, time.Local)
|
||||
cases := []struct {
|
||||
name string
|
||||
ds *Dataset
|
||||
want string
|
||||
}{
|
||||
{"没有数据集", nil, ""},
|
||||
{"数据集里一条到访都没有", &Dataset{Name: "空数据集"}, ""},
|
||||
{"正常", &Dataset{Name: "有数据", Last: &last}, "数据截至 2026-09-21"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
var buf bytes.Buffer
|
||||
if err := tpl.ExecuteTemplate(&buf, "layout", Page{Nav: "home", Title: "测", Dataset: c.ds}); err != nil {
|
||||
t.Fatalf("%s: 渲染失败: %v", c.name, err)
|
||||
}
|
||||
got := buf.String()
|
||||
if !strings.Contains(got, "</html>") {
|
||||
t.Errorf("%s: 页面被截断(没有收尾的 </html>)", c.name)
|
||||
}
|
||||
if c.want == "" {
|
||||
if strings.Contains(got, "数据截至") {
|
||||
t.Errorf("%s: 没有可信的截止时间时不该渲染「数据截至」", c.name)
|
||||
}
|
||||
} else if !strings.Contains(got, c.want) {
|
||||
t.Errorf("%s: 页脚应含 %q", c.name, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user