类别显示名可自己维护,顺手把两套对不上的中文名合成一套

你要改的那个「海滩」原来根本不在数据里——它是 Go 里硬编码的 map,所以改不动。
更糟的是这样的 map 有**两张**,而且对不上:

  MKPOICategoryFoodMarket   菜市场(编辑页)  /  食品市场(补全页、GPX)
  MKPOICategoryCafe         咖啡馆              /  咖啡厅
  MKPOICategoryFitnessCenter 健身房             /  健身中心
  外加 ATM / Atm 大小写各写一份、一条永远匹配不上的 MKPOICategoryMarina2

现在合成一张内置表(42 条,冲突处取编辑页那套),并在它上面加了一层站点覆盖:

- 新表 category_labels(value, label),站点级、不挂 dataset——值本身才是稳定键
- 端点 POST /admin/edit/category/label;传空 label = 删掉覆盖行、恢复内置默认名
- 类别台账那行改成两个带标签的输入框:
      导出值 [MKPOICategoryBeach]   ← 会跟着导出写回手机
      显示名 [               ]      ← 只影响站内显示,placeholder 写着默认值
  是 MKPOICategory 枚举但内置表里没有的,会提示「填一个中文名」,这就是你要的补全入口

**显示名绝不写进 places.poi_category**——中文跟着写进去就把导出数据污染了,
专门加了 TestCategoryLabelNeverTouchesValue 钉这条。显示名会贯穿到所有中文名的地方:
编辑页/照片页/补全页的下拉、补全页「在用」标签、访客地点页、GPX 的 desc。

连带删掉两个绑在旧表上的模板函数 catName / poiname:模板里算不出显示名(要读站点覆盖),
改成在 Go 侧算好塞进数据(FillupRow.CatLabel、PlaceData.CategoryLabel)。
This commit is contained in:
tamakyi
2026-09-20 10:54:51 +08:00
parent cbb45b6d6b
commit 82e63412c0
12 changed files with 287 additions and 83 deletions
+14 -10
View File
@@ -60,6 +60,7 @@ type FillupRow struct {
ActHint string // 建议的活动名(空 = 没建议)
ActID int64 // 建议命中现有活动时的 id;0 表示得新建
CatHint string // 建议的类别
CatLabel string // 上面那个类别建议的显示名(站点自定义的优先)
Source string // 建议从哪来
AmapType string // 高德给出的类型原文,供人工判断(可能没映射出建议)
AmapPoi string // 高德找到的最近 POI 名字
@@ -112,7 +113,7 @@ type activityOption struct {
// - 缺类别 = poi_category 为空。
//
// 零到访的地点只要缺类别也会进来——它们没有到访可挂活动,补类别仍然有意义。
func (s *Server) fillupRows(ctx context.Context, datasetID int64) ([]FillupRow, error) {
func (s *Server) fillupRows(ctx context.Context, datasetID int64, custom map[string]string) ([]FillupRow, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT p.id, p.src_pk, COALESCE(p.name,''), COALESCE(p.city,''),
COALESCE(p.lat,0), COALESCE(p.lon,0), COALESCE(p.poi_category,''),
@@ -169,6 +170,7 @@ func (s *Server) fillupRows(ctx context.Context, datasetID int64) ([]FillupRow,
}
if out[i].NoCat && h.Cat != "" {
out[i].CatHint = h.Cat
out[i].CatLabel = categoryLabel(h.Cat, custom)
}
out[i].AmapType, out[i].AmapPoi = h.Type, h.Poi
}
@@ -196,7 +198,8 @@ func (s *Server) adminFillupPage(w http.ResponseWriter, r *http.Request) {
return
}
p.SetFlashFromQuery(r)
rows, err := s.fillupRows(ctx, ds.ID)
catNames := s.categoryLabels(ctx)
rows, err := s.fillupRows(ctx, ds.ID, catNames)
if err != nil {
s.serverError(w, r, err)
return
@@ -206,7 +209,7 @@ func (s *Server) adminFillupPage(w http.ResponseWriter, r *http.Request) {
s.serverError(w, r, err)
return
}
usedCats, err := s.usedCategories(ctx, ds.ID)
usedCats, err := s.usedCategories(ctx, ds.ID, catNames)
if err != nil {
s.serverError(w, r, err)
return
@@ -228,7 +231,7 @@ func (s *Server) adminFillupPage(w http.ResponseWriter, r *http.Request) {
rows = rows[from:to]
s.render(w, "admin/fillup", FillupData{
Page: p, Rows: rows, Activities: acts, Categories: fillupCategories(usedCats),
Page: p, Rows: rows, Activities: acts, Categories: fillupCategories(usedCats, catNames),
Total: total, WithHint: hinted, PageNo: pageNo, PageCount: pageCount,
})
}
@@ -263,7 +266,7 @@ type fillupCategory struct {
// usedCategories 列出这个数据集里真在用的类别(按地点数从多到少),排在静态表前面。
// 候选得先跟已有数据对得上——否则用户会在这一页挑一个名字相近的静态枚举,
// 跟库里已有的值并存成两种,同一个意思分两处统计。
func (s *Server) usedCategories(ctx context.Context, datasetID int64) ([]fillupCategory, error) {
func (s *Server) usedCategories(ctx context.Context, datasetID int64, custom map[string]string) ([]fillupCategory, error) {
rows, err := s.db.QueryContext(ctx, `SELECT poi_category, count(*) FROM places
WHERE dataset_id=$1 AND COALESCE(poi_category,'')<>'' GROUP BY 1 ORDER BY 2 DESC, 1`, datasetID)
if err != nil {
@@ -278,14 +281,14 @@ func (s *Server) usedCategories(ctx context.Context, datasetID int64) ([]fillupC
return nil, err
}
// 值可能是 MKPOICategory 枚举,也可能是真机自己写的中文——poiCategoryLabel 两种都认
out = append(out, fillupCategory{v, fmt.Sprintf("%s(在用 %d)", poiCategoryLabel(v), n)})
out = append(out, fillupCategory{v, fmt.Sprintf("%s(在用 %d)", categoryLabel(v, custom), n)})
}
return out, rows.Err()
}
// fillupCategories 是类别下拉的选项:数据集里真在用的排最前面,再跟真机用过的 12 种、
// 其余常见 MapKit 类别。同一个值只出现一次——在用的那份信息更准,就顶掉静态表里的说明。
func fillupCategories(inUse []fillupCategory) []fillupCategory {
func fillupCategories(inUse []fillupCategory, custom map[string]string) []fillupCategory {
known := []string{
"MKPOICategoryRestaurant", "MKPOICategoryStore", "MKPOICategoryPublicTransport",
"MKPOICategoryHotel", "MKPOICategoryLandmark", "MKPOICategoryFoodMarket",
@@ -313,10 +316,10 @@ func fillupCategories(inUse []fillupCategory) []fillupCategory {
push(c)
}
for _, c := range known {
push(fillupCategory{c, poiName(c) + "(真机用过)"})
push(fillupCategory{c, categoryLabel(c, custom) + "(真机用过)"})
}
for _, c := range extra {
push(fillupCategory{c, poiName(c)})
push(fillupCategory{c, categoryLabel(c, custom)})
}
return out
}
@@ -489,7 +492,8 @@ func (s *Server) adminFillupAmap(w http.ResponseWriter, r *http.Request) {
s.fillupFlash(w, r, "err", "conf/app.ini 里没配 geocode_key,用不了高德")
return
}
rows, err := s.fillupRows(ctx, ds.ID)
catNames := s.categoryLabels(ctx)
rows, err := s.fillupRows(ctx, ds.ID, catNames)
if err != nil {
s.serverError(w, r, err)
return