feat(relation): 显示名可点 → 跳目标模块并过滤到该 _id(单行)
- VueAdmin: 记录 moduleKey→IRouteInfo(moduleRoutes),加 routeForModule(判已注册+非子模块)
- FieldRelation.display: 目标可达时名字渲成链接,点击 router.push 到目标模块
+ ?filter={_id},落成过滤到单条的列表(框架无详情页,单项查看即此形态)
- 子模块目标/无权限目标不可点(routeForModule 返回 undefined)
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "shrimp-admin",
|
"name": "shrimp-admin",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现",
|
"description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -123,11 +123,19 @@ export class VueAdmin extends ShrimpClient {
|
|||||||
userName = ''
|
userName = ''
|
||||||
config: ShrimpAdminConfig
|
config: ShrimpAdminConfig
|
||||||
langList: { lang: string; name: string }[]
|
langList: { lang: string; name: string }[]
|
||||||
|
/** 已注册成功的模块路由(moduleKey → IRouteInfo),供 relation 跳转/单项查看解析路由 */
|
||||||
|
moduleRoutes = new Map<string, IRouteInfo>()
|
||||||
|
|
||||||
getFieldComponent(_moduleKey: string, type: string, _fieldKey?: string): Component {
|
getFieldComponent(_moduleKey: string, type: string, _fieldKey?: string): Component {
|
||||||
return fieldRegistry.get(type) || fieldRegistry.get('string')!
|
return fieldRegistry.get(type) || fieldRegistry.get('string')!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 目标模块能否作为「单项查看」跳转目标:已按权限注册路由 且 非子模块。返回其路由信息或 undefined(不可跳) */
|
||||||
|
routeForModule(moduleKey: string): IRouteInfo | undefined {
|
||||||
|
if (this.moduleInfo.find(m => m.moduleKey === moduleKey)?.parent) return undefined
|
||||||
|
return this.moduleRoutes.get(moduleKey)
|
||||||
|
}
|
||||||
|
|
||||||
state = reactive({ isMobile: false })
|
state = reactive({ isMobile: false })
|
||||||
|
|
||||||
private _token: string | null = null
|
private _token: string | null = null
|
||||||
@@ -256,6 +264,7 @@ export class VueAdmin extends ShrimpClient {
|
|||||||
props: { moduleKey: info.moduleKey, events: info.events },
|
props: { moduleKey: info.moduleKey, events: info.events },
|
||||||
meta: { title: info.label }
|
meta: { title: info.label }
|
||||||
})
|
})
|
||||||
|
this.moduleRoutes.set(info.moduleKey, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
initRouter() {
|
initRouter() {
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-if="mode === 'display'">
|
<template v-if="mode === 'display'">
|
||||||
<template v-if="field.multiple">{{ displayNames.join('、') || '-' }}</template>
|
<template v-if="field.multiple">
|
||||||
<template v-else>{{ displayName || '-' }}</template>
|
<span v-if="!displayItems.length">-</span>
|
||||||
|
<template v-for="(it, i) in displayItems" :key="i"><a v-if="jumpable" class="rel-link" @click.stop="goto(it.id)">{{ it.name }}</a><span v-else>{{ it.name }}</span><span v-if="i < displayItems.length - 1">、</span></template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a v-if="jumpable && modelValue != null" class="rel-link" @click.stop="goto(modelValue)">{{ displayName }}</a>
|
||||||
|
<span v-else>{{ displayName || '-' }}</span>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<el-select
|
<el-select
|
||||||
v-else-if="mode === 'filter'"
|
v-else-if="mode === 'filter'"
|
||||||
@@ -44,12 +50,22 @@ const displayName = computed(() => {
|
|||||||
if (id == null) return ''
|
if (id == null) return ''
|
||||||
return dict.value[String(id)] ?? String(id)
|
return dict.value[String(id)] ?? String(id)
|
||||||
})
|
})
|
||||||
const displayNames = computed(() =>
|
const displayItems = computed(() =>
|
||||||
(Array.isArray(props.modelValue) ? props.modelValue : [])
|
(Array.isArray(props.modelValue) ? props.modelValue : [])
|
||||||
.map((id: any) => dict.value[String(id)] ?? String(id))
|
.filter((id: any) => id != null)
|
||||||
.filter(Boolean)
|
.map((id: any) => ({ id, name: dict.value[String(id)] ?? String(id) }))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 单项查看跳转:目标模块可达(已注册路由)且非子模块时,名字可点 → 跳目标模块并过滤到该 _id(单行)
|
||||||
|
const jumpable = computed(() =>
|
||||||
|
props.mode === 'display' && !!props.field.relation && !!vueAdmin.routeForModule(props.field.relation.moduleKey)
|
||||||
|
)
|
||||||
|
function goto(id: any) {
|
||||||
|
const r = props.field.relation && vueAdmin.routeForModule(props.field.relation.moduleKey)
|
||||||
|
if (!r || id == null) return
|
||||||
|
vueAdmin.router.push({ name: r.name, query: { filter: JSON.stringify({ _id: String(id) }) } })
|
||||||
|
}
|
||||||
|
|
||||||
/** 统一转为字符串值,解决 ObjectId 与 el-select 的匹配问题 */
|
/** 统一转为字符串值,解决 ObjectId 与 el-select 的匹配问题 */
|
||||||
const stringValue = computed(() => {
|
const stringValue = computed(() => {
|
||||||
// filter 模式强制 multiple,始终返回数组
|
// filter 模式强制 multiple,始终返回数组
|
||||||
@@ -105,3 +121,13 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.rel-link {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.rel-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user