From bf23fc62d748d596ab9ec70e184e77a9ca4d1db9 Mon Sep 17 00:00:00 2001 From: tamakyi Date: Sat, 19 Sep 2026 23:46:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E9=A1=B5=EF=BC=9A=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8=E6=94=B9=E6=88=90=E5=92=8C=E7=B1=BB=E5=88=AB=E5=90=8C?= =?UTF-8?q?=E6=AC=BE=E4=B8=8B=E6=8B=89=EF=BC=8C=E4=B8=A4=E5=88=97=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 活动原本是 input+datalist、类别是 select,同在一行列里长得不一样,看着别扭。 现在两者共用同一套写法:下拉 + 末尾「其它(自己写)…」+ 选中后露出的文本框 (后端 act_==__custom__ 时读 act___custom,与类别同一套约定)。 CSS 类也合成一个 fill-sel,脚本只需遍历一次。 顺带:删掉不再需要的 datalist;采纳建议、草稿存取都改走 select.fill-sel。 草稿恢复时对下拉派发 change,所以「其它」的文本框也能跟着恢复显示。 --- internal/web/fillup.go | 10 +++++-- internal/web/fillup_test.go | 35 ++++++++++++++++++++++++ internal/web/templates/admin/fillup.html | 32 ++++++++++------------ 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/internal/web/fillup.go b/internal/web/fillup.go index 4bfa36a..3e41aa2 100644 --- a/internal/web/fillup.go +++ b/internal/web/fillup.go @@ -315,8 +315,14 @@ func (s *Server) adminFillupApply(w http.ResponseWriter, r *http.Request) { } for _, pid := range ids { - // 框里填的是**活动名**:对得上就用现有的,对不上就新建一个 - if name := strings.TrimSpace(r.PostFormValue("act_" + strconv.FormatInt(pid, 10))); name != "" { + // 框里填的是**活动名**:对得上就用现有的,对不上就新建一个。 + // 下拉选了「其它(自己写)」时,真正要读的是旁边那个文本框——与类别同一套写法。 + actKey := "act_" + strconv.FormatInt(pid, 10) + actName := strings.TrimSpace(r.PostFormValue(actKey)) + if actName == "__custom__" { + actName = strings.TrimSpace(r.PostFormValue(actKey + "__custom")) + } + if name := actName; name != "" { actID, ok := actByName[name] if !ok { pk, err := s.nextSrcPK(ctx, ex, ds.ID, activitySeq) diff --git a/internal/web/fillup_test.go b/internal/web/fillup_test.go index a4a4932..d728505 100644 --- a/internal/web/fillup_test.go +++ b/internal/web/fillup_test.go @@ -266,3 +266,38 @@ func TestFillupCustomCategoryEmptyIsSkipped(t *testing.T) { t.Fatalf("没填内容时不该写库,实际 %q", got) } } + +// 活动下拉选「其它(自己写)」时,读的是旁边文本框里的名字——与类别同一套写法。 +func TestFillupCustomActivity(t *testing.T) { + f := newMovementFixture(t) + placeID, _ := fillupPlace(t, f) + key := "act_" + strconv.FormatInt(placeID, 10) + + applyFillup(t, f, url.Values{key: {"__custom__"}, key + "__custom": {"爬山"}}) + + var got string + if err := f.pg.QueryRowContext(f.ctx, `SELECT a.name FROM visits v JOIN activities a ON a.id=v.activity_id + WHERE v.dataset_id=$1 AND v.place_id=$2 LIMIT 1`, f.dsID, placeID).Scan(&got); err != nil { + t.Fatalf("读活动失败: %v", err) + } + if got != "爬山" { + t.Fatalf("应写入手工填的活动名,实际 %q", got) + } + t.Cleanup(func() { + f.pg.ExecContext(f.ctx, `DELETE FROM activities WHERE dataset_id=$1 AND name=$2`, f.dsID, "爬山") + }) +} + +// 选了「其它」却没写名字:什么都不做,别建一个空名活动。 +func TestFillupCustomActivityEmptyIsSkipped(t *testing.T) { + f := newMovementFixture(t) + placeID, _ := fillupPlace(t, f) + key := "act_" + strconv.FormatInt(placeID, 10) + before := f.scalar(t, `SELECT count(*) FROM activities WHERE dataset_id=$1`, f.dsID) + + applyFillup(t, f, url.Values{key: {"__custom__"}, key + "__custom": {" "}}) + + if n := f.scalar(t, `SELECT count(*) FROM activities WHERE dataset_id=$1`, f.dsID); n != before { + t.Fatalf("没填名字不该建类型,活动数 %d → %d", before, n) + } +} diff --git a/internal/web/templates/admin/fillup.html b/internal/web/templates/admin/fillup.html index 3d93760..e0ee1a3 100644 --- a/internal/web/templates/admin/fillup.html +++ b/internal/web/templates/admin/fillup.html @@ -52,14 +52,21 @@ {{$row.Missing}} {{if $row.NoAct}} - + {{$ahint := $row.ActHint}} + + {{else}}—{{end}} {{if $row.NoCat}} {{$hint := $row.CatHint}} - {{if $hint}}{{end}} {{range $.Categories}}{{if ne .Value $hint}}{{end}}{{end}} @@ -103,16 +110,12 @@ {{end}} - - {{range .Activities}}{{end}} - -