89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
import { cities, type City } from "@/app/data/cities";
|
||
|
||
const CITY_SLUG_BY_NAME: Record<string, string> = {
|
||
大理: "dali",
|
||
成都: "chengdu",
|
||
深圳: "shenzhen",
|
||
上海: "shanghai",
|
||
杭州: "hangzhou",
|
||
厦门: "xiamen",
|
||
北京: "beijing",
|
||
广州: "guangzhou",
|
||
重庆: "chongqing",
|
||
昆明: "kunming",
|
||
三亚: "sanya",
|
||
丽江: "lijiang",
|
||
西安: "xian",
|
||
南京: "nanjing",
|
||
长沙: "changsha",
|
||
青岛: "qingdao",
|
||
苏州: "suzhou",
|
||
珠海: "zhuhai",
|
||
天津: "tianjin",
|
||
石家庄: "shijiazhuang",
|
||
太原: "taiyuan",
|
||
呼和浩特: "hohhot",
|
||
大连: "dalian",
|
||
沈阳: "shenyang",
|
||
长春: "changchun",
|
||
哈尔滨: "harbin",
|
||
无锡: "wuxi",
|
||
宁波: "ningbo",
|
||
合肥: "hefei",
|
||
福州: "fuzhou",
|
||
南昌: "nanchang",
|
||
济南: "jinan",
|
||
郑州: "zhengzhou",
|
||
武汉: "wuhan",
|
||
桂林: "guilin",
|
||
南宁: "nanning",
|
||
海口: "haikou",
|
||
贵阳: "guiyang",
|
||
拉萨: "lhasa",
|
||
兰州: "lanzhou",
|
||
西宁: "xining",
|
||
银川: "yinchuan",
|
||
乌鲁木齐: "urumqi",
|
||
香港: "hong-kong",
|
||
澳门: "macau",
|
||
台北: "taipei",
|
||
};
|
||
|
||
function normalizeSlug(value: string): string {
|
||
return value
|
||
.trim()
|
||
.toLowerCase()
|
||
.replace(/['’]/g, "")
|
||
.replace(/[^a-z0-9]+/g, "-")
|
||
.replace(/^-+|-+$/g, "");
|
||
}
|
||
|
||
export function citySlug(city: Pick<City, "slug" | "name" | "nameEn" | "id">): string {
|
||
if (city.slug) return normalizeSlug(city.slug);
|
||
if (CITY_SLUG_BY_NAME[city.name]) return CITY_SLUG_BY_NAME[city.name];
|
||
if (city.nameEn) return normalizeSlug(city.nameEn);
|
||
return `city-${city.id}`;
|
||
}
|
||
|
||
export function cityVolunteerHref(city: Pick<City, "slug" | "name" | "nameEn" | "id">): string {
|
||
return `/city/${encodeURIComponent(citySlug(city))}/volunteer`;
|
||
}
|
||
|
||
export function findCityBySlug(slug: string): City | undefined {
|
||
const decoded = decodeURIComponent(slug).trim();
|
||
const normalized = normalizeSlug(decoded);
|
||
return cities.find((city) => {
|
||
const candidates = [
|
||
city.slug,
|
||
citySlug(city),
|
||
city.name,
|
||
city.nameEn,
|
||
CITY_SLUG_BY_NAME[city.name],
|
||
].filter(Boolean);
|
||
return candidates.some((candidate) => {
|
||
const text = String(candidate);
|
||
return text === decoded || normalizeSlug(text) === normalized;
|
||
});
|
||
});
|
||
}
|