地点库 / 时间线 / 统计:窄屏筛选卡默认收成一条(与地图页筛选面板同形)
手机上这三页共用的筛选卡一上来就占掉大半屏(时间预设 + 已选条件 + 类型 chips + 六个输入框,
实测 945px),内容反而看不见。按地图页那套 .panel-fold 收成一条:
- 折叠条显示「筛选 + 当前时间范围〔+ N 个条件〕」,展开/收起箭头都能点;
- 状态记在 localStorage('rond-filters-fold'),翻页/换页不会又自己弹开;
- 收起只是 CSS 隐藏,表单控件照旧随提交带上(act/hw/sort 那几个 hidden 也在);
- 整组显示规则都在窄屏媒体查询里 ⇒ 桌面端 .collapsed 不生效、折叠条也 display:none,零影响;
- 折叠脚本紧跟表单(放 body 末尾会先按展开画一帧再收起,手机上就是闪一下整张大卡)。
实测:390 三页站长/访客都默认收起、条高 44、内容隐藏、滚动时粘在导航下方(top=50);
筛选卡 945px → 46px;1440 无变化;320/350 摘要不溢出;全站审计 320/390/1440 溢出全 0、
0 JS 报错、小触控只减不增(A/B 31/181/82 vs 35/185/86);关键词回车提交未受影响
(折叠条是 type="button",默认按钮仍是「查询」)。
新增回归 internal/web/filters_fold_test.go(三页的挂载点 + 筛选控件仍在,做了变异验证)。
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFiltersFoldHook 盯住「地点库 / 时间线 / 统计三页共用筛选卡在窄屏默认收起」的挂载点。
|
||||
//
|
||||
// 折叠是纯前端的事:CSS 认 `.filters-card.collapsed`,脚本认 `#filters-fold`,两边都靠
|
||||
// 模板里的类名/ID 挂钩子。谁哪天把表单的 class 换了、或者把这个按钮删了,页面照样能渲染、
|
||||
// 桌面端也看不出问题 —— 只有手机会退化成「永远展开」,所以在这里钉住。
|
||||
//
|
||||
// ROND_TEST_CONF=conf/app-test.ini ROND_SRC=data/xxx.rondbackup go test ./internal/web -run FiltersFold -v
|
||||
func TestFiltersFoldHook(t *testing.T) {
|
||||
f := newMovementFixture(t)
|
||||
for _, path := range []string{"/places", "/timeline", "/stats"} {
|
||||
var h http.HandlerFunc
|
||||
switch path {
|
||||
case "/places":
|
||||
h = f.srv.placesPage
|
||||
case "/timeline":
|
||||
h = f.srv.timelinePage
|
||||
case "/stats":
|
||||
h = f.srv.statsPage
|
||||
}
|
||||
// 访客身份:这三页公开,折叠对访客同样生效
|
||||
w := httptest.NewRecorder()
|
||||
h(w, httptest.NewRequest("GET", path, nil).WithContext(context.Background()))
|
||||
body := w.Body.String()
|
||||
if w.Code != 200 {
|
||||
t.Fatalf("%s 渲染失败: code=%d", path, w.Code)
|
||||
}
|
||||
for _, want := range []string{
|
||||
`class="card filters-card"`, // CSS 的挂载点
|
||||
`id="filters-fold"`, // 折叠条
|
||||
`id="filters-fold-caret"`, // 箭头(脚本要改它的字)
|
||||
`id="filters-form"`, // 脚本靠它找表单;收起时表单控件仍在里面
|
||||
`rond-filters-fold`, // 记收起状态的本地键:翻了页不该又弹开
|
||||
`name="q"`, // 收起只是 CSS 隐藏,筛选控件得照旧提交得出去
|
||||
} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Fatalf("%s 里找不到 %q:窄屏筛选折叠的挂载点断了", path, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -993,4 +993,17 @@ label.f > span.span-actions { display: flex; align-items: center; justify-conten
|
||||
/* 导航左上角那个 logo 是回首页的入口,原来只有 25×29:给它撑到 44 高,
|
||||
横向也补到 44(.brand .t 在窄屏被隐藏,加内边距就够了)。 */
|
||||
.brand { min-width: 44px; min-height: 44px; justify-content: center; }
|
||||
|
||||
/* ---------- 地点库 / 时间线 / 统计三页共用的筛选卡:窄屏默认收成一条 ----------
|
||||
与地图页那块 .panel-fold 同形——手机上它一上来就占掉大半屏(预设 + 已选 + 类型 + 六个
|
||||
输入框),内容反而看不见。展开时折叠条用负外边距贴到卡片上沿(圆角照着卡片补,
|
||||
卡片没有 overflow:hidden,否则折叠条就粘不住了);收起时卡片内边距归零、只留那一条。
|
||||
top 取 --nav-h:导航是 sticky 的,写 0 会被压在它下面。
|
||||
这些规则整条在媒体查询里 ⇒ 桌面端 .collapsed 不生效,等于没影响。 */
|
||||
.filters-card > .panel-fold {
|
||||
margin: -18px -18px 14px; border-radius: var(--radius) var(--radius) 0 0; top: var(--nav-h);
|
||||
}
|
||||
.filters-card.collapsed { padding: 0; }
|
||||
.filters-card.collapsed > .panel-fold { margin: 0; border-radius: var(--radius); }
|
||||
.filters-card.collapsed > :not(.panel-fold) { display: none; }
|
||||
}
|
||||
|
||||
@@ -25,7 +25,15 @@
|
||||
{{end}}
|
||||
|
||||
{{define "filters"}}
|
||||
<form class="card" method="get" action="{{.FilterBase}}" id="filters-form">
|
||||
<form class="card filters-card" method="get" action="{{.FilterBase}}" id="filters-form">
|
||||
{{/* 窄屏折叠开关,与地图页筛选面板同一套(.panel-fold):桌面端它 display:none、表单照旧常开;
|
||||
手机上默认收成这一条,只留「筛选 + 当前范围 + 箭头」。收起只是 CSS 隐藏,
|
||||
表单里的控件都还在,筛选条件照旧随提交带上(act/hw/sort 那几个 hidden 也在)。 */}}
|
||||
<button class="panel-fold" id="filters-fold" type="button" aria-controls="filters-form" aria-expanded="true">
|
||||
<span>筛选</span>
|
||||
<span class="pf-n">{{.RangeLabel}}{{if .ActiveChips}} · {{len .ActiveChips}} 个条件{{end}}</span>
|
||||
<span class="pf-c" id="filters-fold-caret" aria-hidden="true">▾</span>
|
||||
</button>
|
||||
<div class="chips" style="margin-bottom:12px">
|
||||
{{range .Presets}}<a class="chip {{if .Active}}on{{end}}" href="{{$.RangeLink .From .To}}">{{.Label}}</a>{{end}}
|
||||
<span class="chip" style="background:transparent;color:var(--text-3)">{{.RangeLabel}}</span>
|
||||
@@ -104,6 +112,37 @@
|
||||
{{if .ShowHomeWork}}<input type="hidden" name="hw" value="1">{{end}}
|
||||
{{if .Sort}}<input type="hidden" name="sort" value="{{.Sort}}">{{end}}
|
||||
</form>
|
||||
{{/* 窄屏折叠:脚本必须紧跟这个表单 —— 放到 body 末尾时,手机上会先按「全部展开」画一帧
|
||||
再收起,看着就是闪一下整张大卡(地图页那块面板也是贴在面板后面)。收起态记在本地,
|
||||
翻页/换页之后不该又自己弹开。 */}}
|
||||
<script>
|
||||
(function () {
|
||||
var form = document.getElementById('filters-form');
|
||||
var btn = document.getElementById('filters-fold');
|
||||
if (!form || !btn) return;
|
||||
var caret = document.getElementById('filters-fold-caret');
|
||||
var KEY = 'rond-filters-fold';
|
||||
var desk = window.matchMedia('(min-width: 621px)');
|
||||
var saved = null;
|
||||
try { saved = localStorage.getItem(KEY); } catch (e) { /* 隐私模式禁用了,忽略 */ }
|
||||
|
||||
function apply(collapsed) {
|
||||
form.classList.toggle('collapsed', collapsed);
|
||||
btn.setAttribute('aria-expanded', String(!collapsed));
|
||||
btn.title = collapsed ? '展开筛选' : '收起筛选';
|
||||
if (caret) caret.textContent = collapsed ? '▸' : '▾';
|
||||
}
|
||||
// 没记过状态时窄屏默认收起。桌面端这条 class 不生效(显示规则整条在窄屏媒体查询里),
|
||||
// 所以同一个浏览器在手机上收起过、回桌面照样看得见筛选。
|
||||
apply(saved === null ? !desk.matches : saved === '1');
|
||||
|
||||
btn.addEventListener('click', function () {
|
||||
var collapsed = !form.classList.contains('collapsed');
|
||||
apply(collapsed);
|
||||
try { localStorage.setItem(KEY, collapsed ? '1' : '0'); } catch (e) { /* 同上 */ }
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "emptystate"}}
|
||||
|
||||
Reference in New Issue
Block a user