nav: 全量 world-catalog + status active/planned 分层

- world-catalog.js: 6洲48国127城市全量 NavNode catalog
  - 统一 schema(isEnabled → status: active|planned)
  - 64 个 NavNode 覆盖所有洲/国家/地区
- runtime-nav.js: 从 catalog 自动过滤 active 节点
  - MVP_OVERRIDES 机制跳过国家层直连城市
  - V1.1+ 删除覆写即恢复完整层级
- 删除 future-catalog.js,旧 shim 指向 world-catalog
- game-design 2.3 更新 schema + Framework Ready 说明

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
manpengan
2026-03-28 23:37:17 +08:00
parent 212b12ab6b
commit d7bea9aed5
8 changed files with 207 additions and 155 deletions

View File

@@ -160,17 +160,19 @@ MVP 只开放亚洲 6 城市,直入城市选择页,不启用完整多级导
| `childType` | string\|null | 子节点类型:`country` / `region` / `city` / null | | `childType` | string\|null | 子节点类型:`country` / `region` / `city` / null |
| `childIds` | string[] | 当前可消费的子节点 id仅已启用的 | | `childIds` | string[] | 当前可消费的子节点 id仅已启用的 |
| `pageSize` | number | 每页格子数,默认 9 | | `pageSize` | number | 每页格子数,默认 9 |
| `isEnabled` | boolean | 当前版本是否启用 | | `status` | string | `'active'`(当前可运行)/ `'planned'`(未来规划) |
| `isUnlockedByDefault` | boolean | 是否默认解锁 | | `isUnlockedByDefault` | boolean | 是否默认解锁 |
分页通过 `shared/pagination.js``paginate(childIds, pageSize)` 动态计算,不手写 page 常量。 分页通过 `shared/pagination.js``paginate(childIds, pageSize)` 动态计算,不手写 page 常量。
Framework Ready: 全量 6 洲 48 国 127 城市的 catalog 已搭好,扩城市只需加 CityManifest + 改 status 为 active。
**数据文件分层:** **数据文件分层:**
| 文件 | 用途 | 是否进入 runtime | | 文件 | 用途 | 是否进入 runtime |
|------|------|-----------------| |------|------|-----------------|
| `navigation/runtime-nav.js` | 当前版本可消费的导航节点 | ✅ 是 | | `navigation/runtime-nav.js` | 当前版本可消费的导航节点(从 world-catalog 自动过滤) | ✅ 是 |
| `navigation/future-catalog.js` | 未来版本城市/国家/地区规划 | ❌ 否 | | `navigation/world-catalog.js` | 全量世界导航规划(含 active + planned | ✅ 是runtime-nav 从中过滤 active 节点) |
| `navigation/nav-schema.js` | NavNode schema 定义 + 验证 | ✅ 是(类型定义) | | `navigation/nav-schema.js` | NavNode schema 定义 + 验证 | ✅ 是(类型定义) |
| `docs/city-roadmap.md` | 全量 127 城市路线图 | ❌ 否 | | `docs/city-roadmap.md` | 全量 127 城市路线图 | ❌ 否 |

View File

@@ -1,5 +1,6 @@
/** /**
* @deprecated 亚洲国家列表已移入 navigation/future-catalog.js * @deprecated 亚洲国家列表已移入 navigation/world-catalog.js
* MVP 阶段亚洲直接列出城市,不经过国家层。 * MVP 阶段亚洲直接列出城市,不经过国家层。
*/ */
export { asiaCountryPlan as asiaCountries } from '../navigation/future-catalog.js' import { getCatalogChildren } from '../navigation/world-catalog.js'
export const asiaCountries = getCatalogChildren('asia')

View File

@@ -1,6 +1,6 @@
/** /**
* @deprecated 国家城市列表已移入 navigation/future-catalog.js * @deprecated 国家城市列表已移入 navigation/world-catalog.js
*/ */
import { asiaCountryPlan } from '../navigation/future-catalog.js' import { getCatalogNode } from '../navigation/world-catalog.js'
export const japanCities = asiaCountryPlan.find(c => c.id === 'japan') export const japanCities = getCatalogNode('japan')
export default japanCities export default japanCities

View File

@@ -1,50 +0,0 @@
/**
* Future Catalog — 未来版本导航规划
*
* 这些节点不进入当前 runtime 消费链路。
* 当新版本上线新城市时,将对应节点移入 runtime-nav.js 并设 isEnabled: true。
* 引用的 cityId 可能尚不存在对应 CityManifest。
*/
// V1.1: 中国一线城市扩展
export const v11_china_cities = ['shanghai', 'guangzhou', 'chengdu', 'shenzhen', 'hangzhou', 'chongqing']
// V1.2: 中国二线 A
export const v12_china_cities = ['wuhan', 'xian', 'changsha', 'nanjing', 'harbin', 'xiamen']
// V1.3: 欧洲热门
export const v13_europe_cities = ['paris', 'london', 'rome', 'barcelona', 'prague', 'amsterdam']
// 中国地区划分V1.1+ 启用国家→地区→城市导航时使用)
export const chinaRegionPlan = [
{ id: 'north_china', name: '华北', cityIds: ['beijing', 'tianjin', 'shijiazhuang', 'taiyuan', 'hohhot'] },
{ id: 'northeast', name: '东北', cityIds: ['shenyang', 'changchun', 'harbin', 'dalian'] },
{ id: 'east_china', name: '华东', cityIds: ['shanghai', 'nanjing', 'hangzhou', 'hefei', 'fuzhou', 'nanchang', 'jinan', 'suzhou', 'xiamen', 'qingdao', 'ningbo'] },
{ id: 'central_china', name: '华中', cityIds: ['zhengzhou', 'wuhan', 'changsha'] },
{ id: 'south_china', name: '华南', cityIds: ['guangzhou', 'shenzhen', 'nanning', 'haikou', 'sanya'] },
{ id: 'southwest', name: '西南', cityIds: ['chengdu', 'chongqing', 'guiyang', 'kunming', 'lhasa'] },
{ id: 'northwest', name: '西北', cityIds: ['xian', 'lanzhou', 'xining', 'yinchuan', 'urumqi'] },
{ id: 'hk_macao_tw', name: '港澳台', cityIds: ['hongkong', 'macao', 'taipei'] },
]
// 全部亚洲国家V1.1+ 启用)
export const asiaCountryPlan = [
{ id: 'china', name: '中国', hasRegions: true, totalCities: 41 },
{ id: 'japan', name: '日本', cityIds: ['tokyo', 'osaka', 'kyoto', 'sapporo'] },
{ id: 'korea', name: '韩国', cityIds: ['seoul', 'busan', 'jeju'] },
{ id: 'thailand', name: '泰国', cityIds: ['bangkok', 'chiangmai', 'phuket'] },
{ id: 'singapore_country', name: '新加坡', cityIds: ['singapore'] },
{ id: 'vietnam', name: '越南', cityIds: ['hanoi', 'hochiminh'] },
{ id: 'malaysia', name: '马来西亚', cityIds: ['kualalumpur', 'malacca'] },
{ id: 'indonesia', name: '印度尼西亚', cityIds: ['jakarta', 'bali'] },
{ id: 'philippines', name: '菲律宾', cityIds: ['manila'] },
{ id: 'india', name: '印度', cityIds: ['delhi', 'mumbai'] },
{ id: 'uae', name: '阿联酋', cityIds: ['dubai'] },
{ id: 'turkey', name: '土耳其', cityIds: ['istanbul'] },
{ id: 'israel', name: '以色列', cityIds: ['jerusalem'] },
{ id: 'nepal', name: '尼泊尔', cityIds: ['kathmandu'] },
{ id: 'cambodia', name: '柬埔寨', cityIds: ['siemreap'] },
{ id: 'sri_lanka', name: '斯里兰卡', cityIds: ['colombo'] },
{ id: 'myanmar', name: '缅甸', cityIds: ['yangon'] },
{ id: 'mongolia', name: '蒙古', cityIds: ['ulaanbaatar'] },
]

View File

@@ -15,15 +15,16 @@
* @property {'country'|'region'|'city'|null} childType - 子节点类型 * @property {'country'|'region'|'city'|null} childType - 子节点类型
* @property {string[]} childIds - 当前可消费的子节点 id仅已启用的 * @property {string[]} childIds - 当前可消费的子节点 id仅已启用的
* @property {number} pageSize - 每页格子数,默认 9 * @property {number} pageSize - 每页格子数,默认 9
* @property {boolean} isEnabled - 当前版本是否启用 * @property {'active'|'planned'} status - 'active'(当前可运行)/ 'planned'(未来规划)
* @property {boolean} isUnlockedByDefault - 是否默认解锁 * @property {boolean} isUnlockedByDefault - 是否默认解锁
*/ */
// schema 验证函数 // schema 验证函数
export function validateNavNode(node) { export function validateNavNode(node) {
const required = ['type', 'id', 'name', 'nameEn', 'sortOrder', 'themeColor', 'childType', 'childIds', 'pageSize', 'isEnabled', 'isUnlockedByDefault'] const required = ['type', 'id', 'name', 'nameEn', 'sortOrder', 'themeColor', 'childType', 'childIds', 'pageSize', 'status', 'isUnlockedByDefault']
const validTypes = ['continent', 'country', 'region', 'city-group'] const validTypes = ['continent', 'country', 'region', 'city-group']
const validChildTypes = ['country', 'region', 'city', null] const validChildTypes = ['country', 'region', 'city', null]
const validStatuses = ['active', 'planned']
const errors = [] const errors = []
for (const key of required) { for (const key of required) {
@@ -33,5 +34,6 @@ export function validateNavNode(node) {
if (!validChildTypes.includes(node.childType)) errors.push(`invalid childType: ${node.childType}`) if (!validChildTypes.includes(node.childType)) errors.push(`invalid childType: ${node.childType}`)
if (!Array.isArray(node.childIds)) errors.push('childIds must be array') if (!Array.isArray(node.childIds)) errors.push('childIds must be array')
if (node.parentId !== null && typeof node.parentId !== 'string') errors.push('parentId must be string or null') if (node.parentId !== null && typeof node.parentId !== 'string') errors.push('parentId must be string or null')
if (!validStatuses.includes(node.status)) errors.push(`invalid status: ${node.status}, must be 'active' or 'planned'`)
return errors return errors
} }

View File

@@ -1,110 +1,42 @@
/** /**
* Runtime Navigation — MVP * Runtime Navigation — 从 world-catalog 自动生成
* *
* 只包含当前版本已启用、childIds 均指向已存在实体的节点。 * 只包含 status === 'active' 的节点。
* MVP 导航直入亚洲城市页6 城市平铺。 * MVP 阶段手动覆写亚洲的 childType 为 'city'(跳过国家层),
* V1.1+ 启用完整洲→国家→地区→城市多级导航时,在此文件追加节点 * V1.1+ 切换为 catalog 默认的 'country'
*/ */
export const runtimeNavNodes = [ import { worldCatalog } from './world-catalog.js'
// ── MVP: 只有 1 个洲,直接列出 6 城市 ──
{ // MVP 覆写:亚洲直接指向城市,不经过国家层
type: 'continent', const MVP_OVERRIDES = {
id: 'asia', asia: {
parentId: null, childType: 'city',
name: '亚洲',
nameEn: 'Asia',
sortOrder: 1,
themeColor: '#FF6B6B',
childType: 'city', // MVP: 直接指向城市,跳过国家层
childIds: ['beijing', 'tokyo', 'bangkok', 'seoul', 'singapore', 'istanbul'], childIds: ['beijing', 'tokyo', 'bangkok', 'seoul', 'singapore', 'istanbul'],
pageSize: 9,
isEnabled: true,
isUnlockedByDefault: true,
}, },
}
// ── 未启用的洲占位UI 显示锁定态) ── function buildRuntimeNav() {
{ const activeNodes = worldCatalog.filter(n => n.status === 'active')
type: 'continent', return activeNodes.map(node => {
id: 'europe', const override = MVP_OVERRIDES[node.id]
parentId: null, if (override) {
name: '欧洲', return { ...node, ...override }
nameEn: 'Europe', }
sortOrder: 2, return { ...node }
themeColor: '#6B8CFF', })
childType: 'country', }
childIds: [], // 无可消费子节点
pageSize: 9, export const runtimeNavNodes = buildRuntimeNav()
isEnabled: false,
isUnlockedByDefault: false,
},
{
type: 'continent',
id: 'north_america',
parentId: null,
name: '北美洲',
nameEn: 'North America',
sortOrder: 3,
themeColor: '#FFB347',
childType: 'country',
childIds: [],
pageSize: 9,
isEnabled: false,
isUnlockedByDefault: false,
},
{
type: 'continent',
id: 'south_america',
parentId: null,
name: '南美洲',
nameEn: 'South America',
sortOrder: 4,
themeColor: '#4ECDC4',
childType: 'country',
childIds: [],
pageSize: 9,
isEnabled: false,
isUnlockedByDefault: false,
},
{
type: 'continent',
id: 'africa',
parentId: null,
name: '非洲',
nameEn: 'Africa',
sortOrder: 5,
themeColor: '#F7DC6F',
childType: 'country',
childIds: [],
pageSize: 9,
isEnabled: false,
isUnlockedByDefault: false,
},
{
type: 'continent',
id: 'oceania',
parentId: null,
name: '大洋洲',
nameEn: 'Oceania',
sortOrder: 6,
themeColor: '#82E0AA',
childType: 'country',
childIds: [],
pageSize: 9,
isEnabled: false,
isUnlockedByDefault: false,
},
]
// ── 便捷查询 ──
export function getNavNode(id) { export function getNavNode(id) {
return runtimeNavNodes.find(n => n.id === id) || null return runtimeNavNodes.find(n => n.id === id) || null
} }
export function getEnabledRoots() { export function getEnabledRoots() {
return runtimeNavNodes.filter(n => n.parentId === null && n.isEnabled) return runtimeNavNodes.filter(n => n.parentId === null)
} }
export function getChildren(parentId) { export function getChildren(parentId) {
return runtimeNavNodes.filter(n => n.parentId === parentId && n.isEnabled) return runtimeNavNodes.filter(n => n.parentId === parentId)
} }

View File

@@ -0,0 +1,164 @@
/**
* World Catalog — 全量世界导航规划
*
* 所有节点使用统一 NavNode schema。
* status: 'active' = 当前版本可运行(有对应真实内容)
* status: 'planned' = 未来版本规划(无对应内容,不进入 runtime
*
* 扩展新城市时:
* 1. 创建城市 CityManifest 文件
* 2. 将对应节点 status 改为 'active'
* 3. runtime-nav.js 会自动过滤出 active 节点
*/
export const worldCatalog = [
// ═══════════════════════════════════════
// 洲级
// ═══════════════════════════════════════
{
type: 'continent', id: 'asia', parentId: null,
name: '亚洲', nameEn: 'Asia', sortOrder: 1, themeColor: '#FF6B6B',
childType: 'country',
childIds: ['china', 'japan', 'korea', 'thailand', 'singapore_country', 'vietnam', 'malaysia', 'indonesia', 'philippines', 'india', 'uae', 'turkey', 'israel', 'nepal', 'cambodia', 'sri_lanka', 'myanmar', 'mongolia'],
pageSize: 9, status: 'active', isUnlockedByDefault: true,
},
{
type: 'continent', id: 'europe', parentId: null,
name: '欧洲', nameEn: 'Europe', sortOrder: 2, themeColor: '#6B8CFF',
childType: 'country',
childIds: ['france', 'uk', 'italy', 'spain', 'germany', 'netherlands', 'switzerland', 'austria', 'czech', 'greece', 'russia', 'portugal', 'norway', 'sweden', 'denmark', 'finland', 'iceland', 'hungary'],
pageSize: 9, status: 'planned', isUnlockedByDefault: false,
},
{
type: 'continent', id: 'north_america', parentId: null,
name: '北美洲', nameEn: 'North America', sortOrder: 3, themeColor: '#FFB347',
childType: 'country',
childIds: ['usa', 'canada', 'mexico'],
pageSize: 9, status: 'planned', isUnlockedByDefault: false,
},
{
type: 'continent', id: 'south_america', parentId: null,
name: '南美洲', nameEn: 'South America', sortOrder: 4, themeColor: '#4ECDC4',
childType: 'country',
childIds: ['brazil', 'argentina', 'peru', 'chile', 'colombia'],
pageSize: 9, status: 'planned', isUnlockedByDefault: false,
},
{
type: 'continent', id: 'africa', parentId: null,
name: '非洲', nameEn: 'Africa', sortOrder: 5, themeColor: '#F7DC6F',
childType: 'country',
childIds: ['egypt', 'south_africa', 'morocco', 'kenya'],
pageSize: 9, status: 'planned', isUnlockedByDefault: false,
},
{
type: 'continent', id: 'oceania', parentId: null,
name: '大洋洲', nameEn: 'Oceania', sortOrder: 6, themeColor: '#82E0AA',
childType: 'country',
childIds: ['australia', 'new_zealand'],
pageSize: 9, status: 'planned', isUnlockedByDefault: false,
},
// ═══════════════════════════════════════
// 亚洲国家18 国)
// ═══════════════════════════════════════
// MVP active: 中国/日本/韩国/泰国/新加坡/土耳其各有 1 个 active 城市
{ type: 'country', id: 'china', parentId: 'asia', name: '中国', nameEn: 'China', sortOrder: 1, themeColor: '#CC2936', childType: 'region', childIds: ['north_china', 'northeast', 'east_china', 'central_china', 'south_china', 'southwest', 'northwest', 'hk_macao_tw'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'japan', parentId: 'asia', name: '日本', nameEn: 'Japan', sortOrder: 2, themeColor: '#E84057', childType: 'city', childIds: ['tokyo', 'osaka', 'kyoto', 'sapporo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'korea', parentId: 'asia', name: '韩国', nameEn: 'South Korea', sortOrder: 3, themeColor: '#4A90D9', childType: 'city', childIds: ['seoul', 'busan', 'jeju'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'thailand', parentId: 'asia', name: '泰国', nameEn: 'Thailand', sortOrder: 4, themeColor: '#FFB347', childType: 'city', childIds: ['bangkok', 'chiangmai', 'phuket'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'singapore_country', parentId: 'asia', name: '新加坡', nameEn: 'Singapore', sortOrder: 5, themeColor: '#00A896', childType: 'city', childIds: ['singapore'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'vietnam', parentId: 'asia', name: '越南', nameEn: 'Vietnam', sortOrder: 6, themeColor: '#E74C3C', childType: 'city', childIds: ['hanoi', 'hochiminh'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'malaysia', parentId: 'asia', name: '马来西亚', nameEn: 'Malaysia', sortOrder: 7, themeColor: '#3498DB', childType: 'city', childIds: ['kualalumpur', 'malacca'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'indonesia', parentId: 'asia', name: '印度尼西亚', nameEn: 'Indonesia', sortOrder: 8, themeColor: '#E67E22', childType: 'city', childIds: ['jakarta', 'bali'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'philippines', parentId: 'asia', name: '菲律宾', nameEn: 'Philippines', sortOrder: 9, themeColor: '#2ECC71', childType: 'city', childIds: ['manila'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'india', parentId: 'asia', name: '印度', nameEn: 'India', sortOrder: 10, themeColor: '#FF9933', childType: 'city', childIds: ['delhi', 'mumbai'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'uae', parentId: 'asia', name: '阿联酋', nameEn: 'UAE', sortOrder: 11, themeColor: '#C0A062', childType: 'city', childIds: ['dubai'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'turkey', parentId: 'asia', name: '土耳其', nameEn: 'Turkey', sortOrder: 12, themeColor: '#1A5276', childType: 'city', childIds: ['istanbul'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'israel', parentId: 'asia', name: '以色列', nameEn: 'Israel', sortOrder: 13, themeColor: '#5DADE2', childType: 'city', childIds: ['jerusalem'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'nepal', parentId: 'asia', name: '尼泊尔', nameEn: 'Nepal', sortOrder: 14, themeColor: '#DC143C', childType: 'city', childIds: ['kathmandu'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'cambodia', parentId: 'asia', name: '柬埔寨', nameEn: 'Cambodia', sortOrder: 15, themeColor: '#1E8449', childType: 'city', childIds: ['siemreap'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'sri_lanka', parentId: 'asia', name: '斯里兰卡', nameEn: 'Sri Lanka', sortOrder: 16, themeColor: '#8E44AD', childType: 'city', childIds: ['colombo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'myanmar', parentId: 'asia', name: '缅甸', nameEn: 'Myanmar', sortOrder: 17, themeColor: '#F4D03F', childType: 'city', childIds: ['yangon'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'mongolia', parentId: 'asia', name: '蒙古', nameEn: 'Mongolia', sortOrder: 18, themeColor: '#2980B9', childType: 'city', childIds: ['ulaanbaatar'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 中国地区8 区)
// ═══════════════════════════════════════
{ type: 'region', id: 'north_china', parentId: 'china', name: '华北', nameEn: 'North China', sortOrder: 1, themeColor: '#CC2936', childType: 'city', childIds: ['beijing', 'tianjin', 'shijiazhuang', 'taiyuan', 'hohhot'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'northeast', parentId: 'china', name: '东北', nameEn: 'Northeast', sortOrder: 2, themeColor: '#5DADE2', childType: 'city', childIds: ['shenyang', 'changchun', 'harbin', 'dalian'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'east_china', parentId: 'china', name: '华东', nameEn: 'East China', sortOrder: 3, themeColor: '#2ECC71', childType: 'city', childIds: ['shanghai', 'nanjing', 'hangzhou', 'hefei', 'fuzhou', 'nanchang', 'jinan', 'suzhou', 'xiamen', 'qingdao', 'ningbo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'central_china', parentId: 'china', name: '华中', nameEn: 'Central China', sortOrder: 4, themeColor: '#E67E22', childType: 'city', childIds: ['zhengzhou', 'wuhan', 'changsha'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'south_china', parentId: 'china', name: '华南', nameEn: 'South China', sortOrder: 5, themeColor: '#FF6B6B', childType: 'city', childIds: ['guangzhou', 'shenzhen', 'nanning', 'haikou', 'sanya'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'southwest', parentId: 'china', name: '西南', nameEn: 'Southwest', sortOrder: 6, themeColor: '#9B59B6', childType: 'city', childIds: ['chengdu', 'chongqing', 'guiyang', 'kunming', 'lhasa'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'northwest', parentId: 'china', name: '西北', nameEn: 'Northwest', sortOrder: 7, themeColor: '#F4D03F', childType: 'city', childIds: ['xian', 'lanzhou', 'xining', 'yinchuan', 'urumqi'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'region', id: 'hk_macao_tw', parentId: 'china', name: '港澳台', nameEn: 'HK, Macao & Taiwan', sortOrder: 8, themeColor: '#E74C3C', childType: 'city', childIds: ['hongkong', 'macao', 'taipei'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 欧洲国家18 国)
// ═══════════════════════════════════════
{ type: 'country', id: 'france', parentId: 'europe', name: '法国', nameEn: 'France', sortOrder: 1, themeColor: '#3B5998', childType: 'city', childIds: ['paris', 'nice'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'uk', parentId: 'europe', name: '英国', nameEn: 'United Kingdom', sortOrder: 2, themeColor: '#C0392B', childType: 'city', childIds: ['london', 'edinburgh'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'italy', parentId: 'europe', name: '意大利', nameEn: 'Italy', sortOrder: 3, themeColor: '#27AE60', childType: 'city', childIds: ['rome', 'milan', 'venice', 'florence'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'spain', parentId: 'europe', name: '西班牙', nameEn: 'Spain', sortOrder: 4, themeColor: '#E74C3C', childType: 'city', childIds: ['madrid', 'barcelona'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'germany', parentId: 'europe', name: '德国', nameEn: 'Germany', sortOrder: 5, themeColor: '#2C3E50', childType: 'city', childIds: ['berlin', 'munich'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'netherlands', parentId: 'europe', name: '荷兰', nameEn: 'Netherlands', sortOrder: 6, themeColor: '#FF6600', childType: 'city', childIds: ['amsterdam'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'switzerland', parentId: 'europe', name: '瑞士', nameEn: 'Switzerland', sortOrder: 7, themeColor: '#E74C3C', childType: 'city', childIds: ['zurich'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'austria', parentId: 'europe', name: '奥地利', nameEn: 'Austria', sortOrder: 8, themeColor: '#C0392B', childType: 'city', childIds: ['vienna'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'czech', parentId: 'europe', name: '捷克', nameEn: 'Czech Republic', sortOrder: 9, themeColor: '#2980B9', childType: 'city', childIds: ['prague'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'greece', parentId: 'europe', name: '希腊', nameEn: 'Greece', sortOrder: 10, themeColor: '#0D5EAF', childType: 'city', childIds: ['athens'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'russia', parentId: 'europe', name: '俄罗斯', nameEn: 'Russia', sortOrder: 11, themeColor: '#C0392B', childType: 'city', childIds: ['moscow', 'stpetersburg'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'portugal', parentId: 'europe', name: '葡萄牙', nameEn: 'Portugal', sortOrder: 12, themeColor: '#27AE60', childType: 'city', childIds: ['lisbon'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'norway', parentId: 'europe', name: '挪威', nameEn: 'Norway', sortOrder: 13, themeColor: '#2980B9', childType: 'city', childIds: ['oslo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'sweden', parentId: 'europe', name: '瑞典', nameEn: 'Sweden', sortOrder: 14, themeColor: '#F1C40F', childType: 'city', childIds: ['stockholm'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'denmark', parentId: 'europe', name: '丹麦', nameEn: 'Denmark', sortOrder: 15, themeColor: '#C0392B', childType: 'city', childIds: ['copenhagen'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'finland', parentId: 'europe', name: '芬兰', nameEn: 'Finland', sortOrder: 16, themeColor: '#2980B9', childType: 'city', childIds: ['helsinki'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'iceland', parentId: 'europe', name: '冰岛', nameEn: 'Iceland', sortOrder: 17, themeColor: '#2C3E50', childType: 'city', childIds: ['reykjavik'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'hungary', parentId: 'europe', name: '匈牙利', nameEn: 'Hungary', sortOrder: 18, themeColor: '#27AE60', childType: 'city', childIds: ['budapest'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 北美国家3 国)
// ═══════════════════════════════════════
{ type: 'country', id: 'usa', parentId: 'north_america', name: '美国', nameEn: 'United States', sortOrder: 1, themeColor: '#3B5998', childType: 'city', childIds: ['newyork', 'losangeles', 'sanfrancisco', 'lasvegas', 'washington', 'chicago', 'miami'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'canada', parentId: 'north_america', name: '加拿大', nameEn: 'Canada', sortOrder: 2, themeColor: '#E74C3C', childType: 'city', childIds: ['vancouver', 'toronto', 'montreal'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'mexico', parentId: 'north_america', name: '墨西哥', nameEn: 'Mexico', sortOrder: 3, themeColor: '#27AE60', childType: 'city', childIds: ['mexicocity', 'cancun'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 南美国家5 国)
// ═══════════════════════════════════════
{ type: 'country', id: 'brazil', parentId: 'south_america', name: '巴西', nameEn: 'Brazil', sortOrder: 1, themeColor: '#F1C40F', childType: 'city', childIds: ['rio', 'saopaulo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'argentina', parentId: 'south_america', name: '阿根廷', nameEn: 'Argentina', sortOrder: 2, themeColor: '#5DADE2', childType: 'city', childIds: ['buenosaires'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'peru', parentId: 'south_america', name: '秘鲁', nameEn: 'Peru', sortOrder: 3, themeColor: '#E74C3C', childType: 'city', childIds: ['lima', 'cusco'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'chile', parentId: 'south_america', name: '智利', nameEn: 'Chile', sortOrder: 4, themeColor: '#2980B9', childType: 'city', childIds: ['santiago'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'colombia', parentId: 'south_america', name: '哥伦比亚', nameEn: 'Colombia', sortOrder: 5, themeColor: '#F39C12', childType: 'city', childIds: ['bogota'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 非洲国家4 国)
// ═══════════════════════════════════════
{ type: 'country', id: 'egypt', parentId: 'africa', name: '埃及', nameEn: 'Egypt', sortOrder: 1, themeColor: '#F39C12', childType: 'city', childIds: ['cairo'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'south_africa', parentId: 'africa', name: '南非', nameEn: 'South Africa', sortOrder: 2, themeColor: '#27AE60', childType: 'city', childIds: ['capetown'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'morocco', parentId: 'africa', name: '摩洛哥', nameEn: 'Morocco', sortOrder: 3, themeColor: '#E74C3C', childType: 'city', childIds: ['marrakech'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'kenya', parentId: 'africa', name: '肯尼亚', nameEn: 'Kenya', sortOrder: 4, themeColor: '#2C3E50', childType: 'city', childIds: ['nairobi', 'mombasa'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
// ═══════════════════════════════════════
// 大洋洲国家2 国)
// ═══════════════════════════════════════
{ type: 'country', id: 'australia', parentId: 'oceania', name: '澳大利亚', nameEn: 'Australia', sortOrder: 1, themeColor: '#F39C12', childType: 'city', childIds: ['sydney', 'melbourne'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
{ type: 'country', id: 'new_zealand', parentId: 'oceania', name: '新西兰', nameEn: 'New Zealand', sortOrder: 2, themeColor: '#2C3E50', childType: 'city', childIds: ['auckland', 'queenstown'], pageSize: 9, status: 'planned', isUnlockedByDefault: false },
]
// ── 查询工具 ──
export function getCatalogNode(id) {
return worldCatalog.find(n => n.id === id) || null
}
export function getCatalogChildren(parentId) {
return worldCatalog.filter(n => n.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder)
}
export function getActiveNodes() {
return worldCatalog.filter(n => n.status === 'active')
}
export function getPlannedNodes() {
return worldCatalog.filter(n => n.status === 'planned')
}

View File

@@ -1,5 +1,6 @@
/** /**
* @deprecated 中国地区数据已移入 navigation/future-catalog.js * @deprecated 中国地区数据已移入 navigation/world-catalog.js
* 仅在 V1.1+ 启用国家→地区导航后使用。 * 仅在 V1.1+ 启用国家→地区导航后使用。
*/ */
export { chinaRegionPlan as chinaRegions } from '../navigation/future-catalog.js' import { getCatalogChildren } from '../navigation/world-catalog.js'
export const chinaRegions = getCatalogChildren('china')