export const SEARCH_TOPIC_GROUPS = { "空间": ["街区", "建筑", "公共空间", "住宅", "道路", "港口", "边界", "废墟", "城市规划", "城市漫游"], "生活": ["日常生活", "地方生活", "社区", "家庭", "消费", "饮食", "书店", "市井生活"], "流动": ["移民", "旅行", "殖民", "战争", "全球化", "跨境", "离散", "港口城市"], "治理": ["城市更新", "城市治理", "拆迁", "规划", "劳动", "权力", "公共治理"], "记忆": ["城市记忆", "地方史", "影像", "声音", "怀旧", "档案", "历史地图"], "出版": ["在地出版", "独立刊物", "地方杂志", "地图", "城市指南", "独立出版"], "经济": ["金融城市", "商业城市", "贸易城市", "资源城市", "非正规经济"], "产业": ["工业", "工业城市", "科技", "科技城市", "创意产业"], "形态": ["城市形态"], "区域": ["东亚城市", "东亚海域", "华人网络"], "地景": ["宗教建筑", "水系河流", "山体地形"], }; export const SEARCH_TOPIC_ALIASES = { "公共空间": ["公共生活", "公共场所", "广场", "公园", "城市空间"], "街区": ["街道", "胡同", "弄堂", "社区空间", "老街"], "建筑": ["建筑在场", "建筑空间", "住宅建筑"], "城市形态": ["空间形态", "都市形态", "城市肌理", "建成环境", "空间结构", "天际线", "交通网络", "街道设计"], "日常生活": ["日常", "生活纹理", "生活方式", "城市生活"], "城市记忆": ["记忆", "地方记忆", "城市史", "怀旧"], "在地出版": ["地方出版", "地方杂志", "独立刊物", "zine", "在地杂志"], "移民": ["迁徙", "外来者", "离散", "移居"], "殖民": ["殖民史", "帝国", "租界"], "战争": ["战后", "内战", "冲突", "创伤"], "城市治理": ["治理", "权力", "规训", "公共治理"], "城市更新": ["更新", "拆迁", "改造", "重建"], "劳动": ["工人", "人力车夫", "工作", "产业"], "港口": ["码头", "海港", "港口城市"], "声音": ["音乐", "城市声音", "声景"], "地图": ["历史地图", "地图集", "城市地图"], "金融城市": ["金融中心", "金融业", "金融资本", "地产金融", "公共财政", "资本市场", "全球资本市场"], "商业城市": ["商业和社会", "商业网络", "商业史", "商人", "市场", "商埠", "口岸", "公司政治"], "贸易城市": ["贸易", "贸易港", "贸易港口", "贸易共和国", "自由港", "十三行", "全球贸易", "海洋贸易", "大西洋贸易", "殖民贸易"], "资源城市": ["资源资本", "能源资本", "矿业资本", "石油", "石油国家", "油田", "黄金", "钻石", "白银", "矿业国家"], "非正规经济": ["非正规", "非正式经济", "非正规企业", "非正规住宅", "非正规贸易", "非正规交通", "摊贩经济", "棚户区", "产权制度"], "工业": ["钢铁", "钢铁城", "钢铁工业", "工业化", "去工业化", "产业转型", "锈带", "老工业", "老工业城市", "工厂", "制造业", "劳动史"], "工业城市": ["工业城市", "工业都市", "工业城", "产业城市", "制造业城市", "资源工业", "重工业", "汽车工业", "城市工业"], "科技": ["高科技", "技术产业", "科技产业", "技术公司", "科技公司", "工程师", "创业者", "创业公司", "硅谷", "创新圣地", "创新产业"], "科技城市": ["技术城市", "创新城市", "数字城市", "智慧城市", "产业创新", "创新经济", "技术社区"], "创意产业": ["创意设计", "文化创意", "创意经济", "设计产业", "游戏产业", "影视产业", "动画产业"], "东亚城市": ["东亚", "中日韩", "东北亚", "汉字文化圈", "中国城市", "日本城市", "韩国城市", "东亚现代城市"], "东亚海域": ["东亚海域", "南海", "南洋", "海港贸易", "跨海流动", "马尼拉体系", "广州贸易"], "华人网络": ["华人", "华侨华人", "海外华人", "全球华人", "唐人街", "华人移民", "华人社会", "华人政权", "跨太平洋"], "宗教建筑": ["教堂", "大教堂", "礼拜堂", "寺庙", "神庙", "清真寺", "宗教建筑", "宗教空间", "古寺", "圣城", "朝圣"], "水系河流": ["水系", "河流", "江河", "河道", "运河", "大运河", "水网", "湖泊", "西湖", "港湾", "海湾", "潟湖", "尼罗河", "长江", "黑龙江", "刚果河", "莱茵河", "贝加尔湖", "基伍湖", "安加拉河", "红海"], "山体地形": ["山体", "山地", "山脉", "山海", "小山", "丘陵", "地形", "地貌", "山城", "高海拔", "火山", "火山群", "山路", "高地", "绿洲", "喜马拉雅", "安第斯"], }; export const SEARCH_PINYIN_ALIASES = { "北京": ["beijing", "bj"], "上海": ["shanghai", "sh"], "东京": ["dongjing", "dj"], "新加坡": ["xinjiapo", "xjp", "sg"], "香港": ["xianggang", "xg"], "纽约": ["niuyue", "ny"], "檀香山": ["honolulu", "hnl", "火奴鲁鲁", "檀岛", "夏威夷", "夏威夷州", "hawaii"], "公共空间": ["gonggongkongjian", "ggkj"], "城市记忆": ["chengshijiyi", "csjy"], "日常生活": ["richangshenghuo", "rcsh"], "在地出版": ["zaidichuban", "zdcb"], "独立刊物": ["dulikanwu", "dlkw"], "地方杂志": ["difangzazhi", "dfzz"], "城市治理": ["chengshizhili", "cszl"], "城市更新": ["chengshigengxin", "csgx"], "街区": ["jiequ", "jq"], "建筑": ["jianzhu", "jz"], "移民": ["yimin", "ym"], "殖民": ["zhimin", "zm"], "港口": ["gangkou", "gk"], "书店": ["shudian", "sd"], "家庭": ["jiating", "jt"], "劳动": ["laodong", "ld"], "权力": ["quanli", "ql"], "地图": ["ditu", "dt"], "声音": ["shengyin", "sy"], "金融城市": ["jinrongchengshi", "jrcs"], "商业城市": ["shangyechengshi", "sycs"], "贸易城市": ["maoyichengshi", "mycs"], "资源城市": ["ziyuanchengshi", "zycs"], "非正规经济": ["feizhengguijingji", "fzg"], "工业": ["gongye", "gy", "industry", "industrial"], "工业城市": ["gongyechengshi", "gycs", "industrial city", "industry city", "rust belt"], "科技": ["keji", "kj", "technology", "tech"], "科技城市": ["kejichengshi", "kjcs", "technology city", "tech city"], "创意产业": ["chuangyichanye", "cycy", "creative industry"], "城市形态": ["chengshixingtai", "csxt"], "东亚城市": ["dongyachengshi", "dycs"], "东亚海域": ["dongyahaiyu", "dyhy"], "华人网络": ["huarenwangluo", "hrwl"], "宗教建筑": ["zongjiaojianzhu", "zjjz"], "水系河流": ["shuixiheliu", "sxhl"], "山体地形": ["shantidixing", "stdx"], }; function uniqueCleanTokens(values) { const seen = new Set(); const output = []; values.flat().forEach((value) => { const text = String(value || "").trim(); if (!text || seen.has(text)) return; seen.add(text); output.push(text); }); return output; } export function deriveSearchTopicsFromText(text) { const source = String(text || ""); const topics = []; Object.entries(SEARCH_TOPIC_ALIASES).forEach(([topic, aliases]) => { if (source.includes(topic)) topics.push(topic); aliases.forEach((alias) => { if (source.includes(alias)) topics.push(topic); }); }); Object.values(SEARCH_TOPIC_GROUPS).flat().forEach((topic) => { if (source.includes(topic)) topics.push(topic); }); return uniqueCleanTokens(topics); } export function deriveSearchTopicAliasMatchesFromText(text) { const source = String(text || ""); const aliases = []; Object.values(SEARCH_TOPIC_ALIASES).flat().forEach((alias) => { if (source.includes(alias)) aliases.push(alias); }); return uniqueCleanTokens(aliases); }