优化字段控件模板覆盖优先级排序

This commit is contained in:
jingrow 2025-10-28 19:02:09 +08:00
parent c83c10d7ea
commit 6ce935f34a

View File

@ -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<string, any>) {
pushEntries(globAllApps)
pushEntries(globLocal)
/**
* pagetype fieldtype apps.txt
*/
export async function resolveControlOverride(entity: string, fieldtype: string): Promise<any | null> {
if (!entity || !fieldtype) return null
// 预构建索引:(entity, fieldtype) -> 已排序候选列表
const indexedByKey: Record<string, Entry[]> = {}
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<any | null> {
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
}
}