|
|
@@ -0,0 +1,79 @@
|
|
|
+const SCORE = {
|
|
|
+ SUFFIX_BASE: 1000,
|
|
|
+ WATER_PATH: 500,
|
|
|
+ ROOT_TYPE: 400,
|
|
|
+ SHARED_ALARM_PATH: 200,
|
|
|
+ TITLE: 100
|
|
|
+}
|
|
|
+
|
|
|
+const WATER_ALARM_ENTRY_ALIASES = {
|
|
|
+ '/monitorAlarm/index': {
|
|
|
+ title: '报警管理',
|
|
|
+ suffixes: ['/monitorAlarm/index', '/alarm/common/list', '/alarm/list', '/alarm/alarmList', '/alarm/index']
|
|
|
+ },
|
|
|
+ '/monitorAlarm/audit': {
|
|
|
+ title: '报警审核',
|
|
|
+ suffixes: ['/monitorAlarm/audit', '/alarm/common/audit', '/alarm/audit', '/alarm/alarmAudit']
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function normalizePath(value) {
|
|
|
+ const path = String(value || '').trim()
|
|
|
+ if (!path) return ''
|
|
|
+ const normalized = path.startsWith('/') ? path : `/${path}`
|
|
|
+ return normalized.replace(/\/+/gu, '/').replace(/\/$/u, '') || '/'
|
|
|
+}
|
|
|
+
|
|
|
+function parseQuery(value) {
|
|
|
+ if (!value) return {}
|
|
|
+ if (typeof value === 'object') return value
|
|
|
+ try { return JSON.parse(value) || {} } catch { return {} }
|
|
|
+}
|
|
|
+
|
|
|
+function routeRootTypeId(route) {
|
|
|
+ const query = parseQuery(route?.query || route?.meta?.query)
|
|
|
+ return query.rootTypeId == null ? null : Number(query.rootTypeId)
|
|
|
+}
|
|
|
+
|
|
|
+function routeScore(route, candidates, title) {
|
|
|
+ const path = normalizePath(route?.path)
|
|
|
+ if (!path) return Number.NEGATIVE_INFINITY
|
|
|
+ const rootTypeId = routeRootTypeId(route)
|
|
|
+ if (rootTypeId != null && rootTypeId !== 1) return Number.NEGATIVE_INFINITY
|
|
|
+ if (title && !path.includes('/subSystem/waterSupply/') && !path.startsWith('/subSystem/alarm/')) {
|
|
|
+ return Number.NEGATIVE_INFINITY
|
|
|
+ }
|
|
|
+
|
|
|
+ const suffixIndex = candidates.findIndex(candidate => path.endsWith(normalizePath(candidate)))
|
|
|
+ const titleMatch = route?.meta?.title === title
|
|
|
+ if (suffixIndex < 0 && !titleMatch) return Number.NEGATIVE_INFINITY
|
|
|
+ let score = suffixIndex < 0 ? 0 : SCORE.SUFFIX_BASE - suffixIndex
|
|
|
+ if (titleMatch) score += SCORE.TITLE
|
|
|
+ if (path.includes('/subSystem/waterSupply/')) score += SCORE.WATER_PATH
|
|
|
+ if (rootTypeId === 1) score += SCORE.ROOT_TYPE
|
|
|
+ if (path.startsWith('/subSystem/alarm/')) score += SCORE.SHARED_ALARM_PATH
|
|
|
+ return score
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Resolve a semantic water-home entry against the routes currently registered by
|
|
|
+ * the permission store. Shared alarm menus and dedicated water menus both occur
|
|
|
+ * in deployed environments, so this boundary must not assume a database path.
|
|
|
+ */
|
|
|
+export function resolveWaterHomeRoute(routes, target) {
|
|
|
+ const list = Array.isArray(routes) ? routes : []
|
|
|
+ const canonicalPath = typeof target === 'string' ? target : target?.path
|
|
|
+ const definition = WATER_ALARM_ENTRY_ALIASES[canonicalPath]
|
|
|
+ const candidates = definition?.suffixes || [canonicalPath]
|
|
|
+ const title = definition?.title
|
|
|
+ let best = null
|
|
|
+ let bestScore = Number.NEGATIVE_INFINITY
|
|
|
+ for (const route of list) {
|
|
|
+ const score = routeScore(route, candidates, title)
|
|
|
+ if (score > bestScore) {
|
|
|
+ best = route
|
|
|
+ bestScore = score
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return bestScore === Number.NEGATIVE_INFINITY ? null : best
|
|
|
+}
|