fix(birth-sky): print the city for stored 「中国 · 省 · 市」 labels (BUG-1082)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
cfed06822f
commit
3d0f1cf6eb
@@ -14562,3 +14562,18 @@
|
||||
- 防复发:守卫测试锁住「本人出生资料至少有一个编辑入口,且走共享的 `saveSelfProfile`」;取代某个入口的改动必须在任务书里写明新入口。
|
||||
- 相关记录:BUG-1030/1039(星盘档案)、BUG-018(账户出生资料声明与状态同写)。
|
||||
- 修复版本:分支 `codex/self-edit-avatar-menu-20260928`,未部署。
|
||||
|
||||
## BUG-1082 | 天空封面底部的出生城市对中国出生地一律印不出来
|
||||
|
||||
- 状态:resolved(代码与回归测试;真机待部署后按 `docs/testing/birth-sky-cover-checklist.md` 城市条目复核)
|
||||
- 首次发现 / 最近更新:2026-09-29 / 2026-09-29
|
||||
- 影响面:星盘页「那一刻的天空」图片、报告封面、首次建盘过场底部的 caption(`TASK-birth-sky-polish-20260928` P2,staging `adbb2054` 起)。
|
||||
- 用户现象:中国出生地只印「日期 时刻」,没有「· 城市」。
|
||||
- 触发条件:出生地来自中国地点库(存储标签形如 `中国 · 省 · 市 · 区`)。
|
||||
- 根因:`lib/birth-sky/caption.ts` `birthSkyCity` 从第一段开始按「省 / 直辖市」识别,而存储标签由 `geoapify-location-service.ts` 生成、第一段固定是「中国」,于是每次都判为「取不到可靠城市」。测试夹具手写成不带「中国」的 `省 · 市 · 区`,与真实存储格式不一致,所以单测与样张都显示了城市。执行方在下一单(`TASK-self-edit-avatar-menu-20260928`)读 `people-archive-view.ts` 时发现;Claude 验收 polish 时也只看了夹具样张,未对照真实标签格式。
|
||||
- 修复:识别前先去掉开头的「中国」段,其余规则不变。
|
||||
- 验证:`frontend/tests/birth-sky-caption.test.ts` 新增「stored China labels lead with 「中国 · 」」一条(省市区、省市、直辖市、只到省、只有「中国」、完整 caption);`birth-sky-caption` / `birth-sky-route` / `birth-sky-draw` 22 pass。
|
||||
- 防复发:解析地点标签的测试夹具必须取自 `geoapify-location-service.ts` 的真实生成格式(AGENTS §7.4 golden 原则);新增的地名解析先对照 `people-archive-view.ts` `peopleCityLabel` 已有做法。
|
||||
- 相关记录:BUG-1080
|
||||
- 复发自:无
|
||||
- 修复版本:`codex/self-edit-avatar-menu-20260928` 第 4 个提交
|
||||
|
||||
@@ -26,6 +26,7 @@ const HAN = /[㐀-鿿]/;
|
||||
/**
|
||||
* City from a stored birth place label. Rules, most specific first:
|
||||
*
|
||||
* 0. A leading 「中国」 segment (how stored labels start) is dropped first.
|
||||
* 1. Municipalities and SARs (`北京市 · 朝阳区`, `香港特别行政区`) → `北京`, `香港`.
|
||||
* 2. Chinese labels `省 · 市 · 区` → the second segment when it ends in 「市」,
|
||||
* without the 「市」 (`河北省 · 邯郸市 · 峰峰矿区` → `邯郸`). Prefectures that are
|
||||
@@ -36,7 +37,9 @@ const HAN = /[㐀-鿿]/;
|
||||
*/
|
||||
export function birthSkyCity(label: string | null | undefined): string | null {
|
||||
if (typeof label !== "string") return null;
|
||||
const segments = label.split(SEPARATOR).map((segment) => segment.trim()).filter(Boolean);
|
||||
const all = label.split(SEPARATOR).map((segment) => segment.trim()).filter(Boolean);
|
||||
// Stored China labels lead with 「中国 · 」 (geoapify-location-service); the rules below start at the province (BUG-1082).
|
||||
const segments = all[0] === "中国" ? all.slice(1) : all;
|
||||
if (segments.length === 0) return null;
|
||||
const [first, second, third] = segments;
|
||||
if (CITY_PROVINCES[first]) return CITY_PROVINCES[first];
|
||||
|
||||
@@ -12,6 +12,17 @@ test("China 省 · 市 · 区 labels give the prefecture city without 「市」"
|
||||
assert.equal(birthSkyCity("广西壮族自治区 · 桂林市 · 秀峰区"), "桂林");
|
||||
});
|
||||
|
||||
// BUG-1082: stored labels are built as 「中国 · 省 · 市 · 区」 (geoapify-location-service.ts);
|
||||
// the fixtures above lacked the prefix, so real Chinese birthplaces printed no city.
|
||||
test("stored China labels lead with 「中国 · 」 and still give the city", () => {
|
||||
assert.equal(birthSkyCity("中国 · 河北省 · 邯郸市 · 峰峰矿区"), "邯郸");
|
||||
assert.equal(birthSkyCity("中国 · 浙江省 · 杭州市"), "杭州");
|
||||
assert.equal(birthSkyCity("中国 · 北京市 · 北京市 · 朝阳区"), "北京");
|
||||
assert.equal(birthSkyCity("中国 · 浙江省"), null);
|
||||
assert.equal(birthSkyCity("中国"), null);
|
||||
assert.equal(birthSkyCaption({ date: "1994-05-18", time: "07:40", placeLabel: "中国 · 浙江省 · 杭州市 · 西湖区" }), "1994年5月18日 07:40 · 杭州");
|
||||
});
|
||||
|
||||
test("municipalities and SARs use their own name", () => {
|
||||
assert.equal(birthSkyCity("北京市 · 朝阳区"), "北京");
|
||||
assert.equal(birthSkyCity("上海市"), "上海");
|
||||
|
||||
Reference in New Issue
Block a user