新增: 工程依赖图数据层 + 依赖边渲染 + 小地图
- 后端 module_dependencies 表(V35 迁移)+ ModuleDependencyRepo CRUD - IPC:add/remove/list_module_dependencies - 前端 API 封装 + DependencyGraph 接入真实边数据 - 依赖类型颜色区分(library/api/mq/shared/custom) - 小地图插件(MiniMap)大图概览导航 - 点击节点跳转项目详情 - 任务列表后端真分页 count_by_query 方法
This commit is contained in:
@@ -23,30 +23,40 @@
|
||||
* 节点用 Vue 组件(ModuleNode.vue)渲染,通过 @antv/x6-vue-shape 注册。
|
||||
*/
|
||||
import { onMounted, onBeforeUnmount, ref, watch, markRaw } from 'vue'
|
||||
import { Graph, Selection, Snapline, History, Scroller } from '@antv/x6'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Graph, Selection, Snapline, History, Scroller, MiniMap } from '@antv/x6'
|
||||
import '@antv/x6-vue-shape'
|
||||
import { moduleApi, type ProjectModuleRecord } from '@/api/module'
|
||||
import { moduleApi, type ProjectModuleRecord, type ModuleDependencyRecord } from '@/api/module'
|
||||
import ModuleNode from './ModuleNode.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: string
|
||||
}>()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'select-module', moduleId: string): void
|
||||
}>()
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const modules = ref<ProjectModuleRecord[]>([])
|
||||
const dependencies = ref<ModuleDependencyRecord[]>([])
|
||||
const loading = ref(true)
|
||||
let graph: Graph | null = null
|
||||
|
||||
async function loadModules() {
|
||||
loading.value = true
|
||||
try {
|
||||
modules.value = await moduleApi.listProjectModules(props.projectId)
|
||||
const [mods, deps] = await Promise.all([
|
||||
moduleApi.listProjectModules(props.projectId),
|
||||
moduleApi.listModuleDependencies(props.projectId),
|
||||
])
|
||||
modules.value = mods
|
||||
dependencies.value = deps
|
||||
} catch {
|
||||
modules.value = []
|
||||
dependencies.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -81,8 +91,21 @@ function renderGraph() {
|
||||
}
|
||||
})
|
||||
|
||||
// 边暂为空(module_dependencies 表未建)
|
||||
graph.fromJSON({ nodes, edges: [] })
|
||||
// 边数据(module_dependencies 表)
|
||||
const edges = dependencies.value.map(d => ({
|
||||
source: d.from_module_id,
|
||||
target: d.to_module_id,
|
||||
labels: d.label ? [{ text: d.label }] : [{ text: d.dep_type }],
|
||||
attrs: {
|
||||
line: {
|
||||
stroke: depTypeColor(d.dep_type),
|
||||
strokeWidth: 1.5,
|
||||
targetMarker: { name: 'block', width: 8, height: 6 },
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
graph.fromJSON({ nodes, edges })
|
||||
graph.centerContent()
|
||||
}
|
||||
|
||||
@@ -101,9 +124,11 @@ function buildGraph() {
|
||||
graph.use(new Snapline({ enabled: true }))
|
||||
graph.use(new History({ enabled: true }))
|
||||
graph.use(new Scroller({ enabled: true, pannable: true }))
|
||||
graph.use(new MiniMap({ width: 200, height: 120, padding: 10 }))
|
||||
|
||||
graph.on('node:click', ({ node }) => {
|
||||
emit('select-module', String(node.id))
|
||||
router.push(`/projects/${props.projectId}`)
|
||||
})
|
||||
|
||||
renderGraph()
|
||||
@@ -121,6 +146,17 @@ function zoomOut() {
|
||||
graph?.zoom(-0.1)
|
||||
}
|
||||
|
||||
/** 依赖类型 → 边颜色 */
|
||||
function depTypeColor(depType: string): string {
|
||||
switch (depType) {
|
||||
case 'api': return '#5378e8'
|
||||
case 'mq': return '#e8a053'
|
||||
case 'shared': return '#53e8a0'
|
||||
case 'custom': return '#e853a0'
|
||||
default: return '#5c6b8a' // library
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadModules()
|
||||
buildGraph()
|
||||
|
||||
Reference in New Issue
Block a user