diff --git a/apps/jingrow/frontend/src/core/registry/controlOverride.ts b/apps/jingrow/frontend/src/core/registry/controlOverride.ts index 69235ef..4936443 100644 --- a/apps/jingrow/frontend/src/core/registry/controlOverride.ts +++ b/apps/jingrow/frontend/src/core/registry/controlOverride.ts @@ -21,12 +21,7 @@ type Entry = { const allEntries: Entry[] = [] function appsOrder(): string[] { - const order = Array.isArray(__APPS_ORDER__) && __APPS_ORDER__.length > 0 ? __APPS_ORDER__ : ['jingrow'] - try { - // 日志:构建注入的应用优先级 - console.debug('[control-override] __APPS_ORDER__ =', order) - } catch (_e) {} - return order + return Array.isArray(__APPS_ORDER__) && __APPS_ORDER__.length > 0 ? __APPS_ORDER__ : ['jingrow'] } function rankByAppsOrder(appName: string): number { @@ -87,48 +82,45 @@ function pushEntries(map: Record) { pushEntries(globAllApps) pushEntries(globLocal) -/** - * 解析并返回指定 pagetype 和 fieldtype 的控件覆盖组件(按 apps.txt 优先级,靠后优先) - */ -export async function resolveControlOverride(entity: string, fieldtype: string): Promise { - if (!entity || !fieldtype) return null +// 预构建索引:(entity, fieldtype) -> 已排序候选列表 +const indexedByKey: Record = {} - const entityKey = String(entity).toLowerCase().replace(/-/g, '_') - const fieldtypeKey = String(fieldtype).replace(/\s+/g, '') +for (const e of allEntries) { + const key = `${e.entity}:${e.fieldtype}` + if (!indexedByKey[key]) indexedByKey[key] = [] + indexedByKey[key].push(e) +} - let candidates = allEntries.filter(e => e.entity === entityKey && e.fieldtype === fieldtypeKey) - console.debug('[control-override] resolve', { entityKey, fieldtypeKey, found: candidates.length }) - // 若未找到实体定制控件,尝试全局控件:约定 entity = _global - if (candidates.length === 0) { - console.debug('[control-override] fallback to _global for fieldtype', fieldtypeKey) - candidates = allEntries.filter(e => e.entity === '_global' && e.fieldtype === fieldtypeKey) - } - if (candidates.length === 0) return null - - candidates.sort((a, b) => { +// 预排序所有索引 +for (const key of Object.keys(indexedByKey)) { + indexedByKey[key].sort((a, b) => { const ra = rankByAppsOrder(a.appName) const rb = rankByAppsOrder(b.appName) - if (ra !== rb) return rb - ra // 靠后优先 - // 当 app 解析结果相同(可能都被识别为 jingrow)时,优先选择来自 apps 目录的候选 - const aIsExternal = a.fullPath.includes('/apps/') || a.fullPath.includes('@apps/') || (a.fullPath.includes('/@fs/') && a.fullPath.includes('/apps/')) - const bIsExternal = b.fullPath.includes('/apps/') || b.fullPath.includes('@apps/') || (b.fullPath.includes('/@fs/') && b.fullPath.includes('/apps/')) + if (ra !== rb) return rb - ra + const aIsExternal = a.fullPath.includes('/apps/') || a.fullPath.includes('@apps/') + const bIsExternal = b.fullPath.includes('/apps/') || b.fullPath.includes('@apps/') if (aIsExternal !== bIsExternal) return aIsExternal ? -1 : 1 if (a.fullPath.length !== b.fullPath.length) return a.fullPath.length - b.fullPath.length return a.fullPath.localeCompare(b.fullPath) }) +} - const pick = candidates[0] - console.debug('[control-override] pick', { - app: pick.appName, - path: pick.fullPath, - candidates: candidates.map(c => ({ app: c.appName, path: c.fullPath })) - }) - try { console.log('[control-override] candidates-json', JSON.stringify(candidates.map(c => ({ app: c.appName, path: c.fullPath })))) } catch (_e) {} +/** + * 解析控件覆盖:优先级 其他app > jingrow/pagetype > 核心通用 + */ +export async function resolveControlOverride(entity: string, fieldtype: string): Promise { + if (!entity || !fieldtype) return null + const k = `${entity.toLowerCase().replace(/-/g, '_')}:${String(fieldtype).replace(/\s+/g, '')}` + let bucket = indexedByKey[k] + // 全局控件兜底 + if (!bucket || bucket.length === 0) { + bucket = indexedByKey[`_global:${String(fieldtype).replace(/\s+/g, '')}`] + } + if (!bucket || bucket.length === 0) return null try { - const mod = await pick.loader() + const mod = await bucket[0].loader() return mod?.default ?? mod } catch { - console.warn('[control-override] failed to load', pick.fullPath) return null } }