refactor(ui): 优化知识图谱界面布局和交互
调整图谱布局参数提升渲染效果 重构顶部操作栏布局,改进搜索框样式和交互 移除冗余的说明按钮
This commit is contained in:
parent
2e9fd9cbe0
commit
7df10afba7
@ -68,14 +68,13 @@ const MAX_RETRIES = 5
|
||||
const defaultLayout = {
|
||||
type: 'd3-force',
|
||||
preventOverlap: true,
|
||||
// 性能友好参数(参考 GraphView.vue)
|
||||
alphaDecay: 0.1,
|
||||
alphaMin: 0.01,
|
||||
velocityDecay: 0.7,
|
||||
iterations: 100,
|
||||
velocityDecay: 0.6,
|
||||
iterations: 150,
|
||||
force: {
|
||||
center: { x: 0.5, y: 0.5, strength: 0.1 },
|
||||
charge: { strength: -400, distanceMax: 400 },
|
||||
charge: { strength: -400, distanceMax: 600 },
|
||||
link: { distance: 100, strength: 0.8 },
|
||||
},
|
||||
collide: { radius: 40, strength: 0.8, iterations: 3 },
|
||||
@ -217,9 +216,6 @@ function initGraph() {
|
||||
const { target } = evt
|
||||
// 获取节点ID
|
||||
const nodeId = target.id
|
||||
// 从 graph data 中找到对应的节点数据
|
||||
// 注意:G6 v5 的事件对象结构可能有所不同,这里假设 target.id 是节点ID
|
||||
// 也可以通过 graphInstance.getNodeData(nodeId) 获取
|
||||
const nodeData = graphInstance.getNodeData(nodeId)
|
||||
emit('node-click', nodeData)
|
||||
})
|
||||
@ -271,7 +267,7 @@ function setGraphData() {
|
||||
emit('data-rendered')
|
||||
console.log('图谱渲染完成,布局已稳定')
|
||||
}, 1500)
|
||||
}, 10) // 等待 1ms 确保布局完成
|
||||
}, 10) // 等待 10ms 确保布局完成
|
||||
}
|
||||
|
||||
// 关键词高亮功能
|
||||
|
||||
@ -18,26 +18,34 @@
|
||||
>
|
||||
<template #top>
|
||||
<div class="compact-actions">
|
||||
<a-input-search
|
||||
v-model:value="searchInput"
|
||||
placeholder="搜索实体"
|
||||
style="width: 200px"
|
||||
@search="onSearch"
|
||||
allow-clear
|
||||
/>
|
||||
<a-button
|
||||
type="text"
|
||||
:icon="h(ReloadOutlined)"
|
||||
:loading="graph.fetching"
|
||||
@click="loadGraph"
|
||||
title="刷新"
|
||||
/>
|
||||
<a-button
|
||||
type="text"
|
||||
:icon="h(SettingOutlined)"
|
||||
@click="showSettings = true"
|
||||
title="设置"
|
||||
/>
|
||||
<div class="actions-left">
|
||||
<a-input
|
||||
v-model:value="searchInput"
|
||||
placeholder="搜索实体"
|
||||
style="width: 240px"
|
||||
@keydown.enter="onSearch"
|
||||
allow-clear
|
||||
>
|
||||
<template #suffix>
|
||||
<component :is="graph.fetching ? LoadingOutlined : SearchOutlined" @click="onSearch" />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-button
|
||||
class="action-btn"
|
||||
:icon="h(ReloadOutlined)"
|
||||
:loading="graph.fetching"
|
||||
@click="loadGraph"
|
||||
title="刷新"
|
||||
/>
|
||||
</div>
|
||||
<div class="actions-right">
|
||||
<a-button
|
||||
class="action-btn"
|
||||
:icon="h(SettingOutlined)"
|
||||
@click="showSettings = true"
|
||||
title="设置"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</GraphCanvas>
|
||||
@ -94,7 +102,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick, onUnmounted, reactive, h } from 'vue';
|
||||
import { useDatabaseStore } from '@/stores/database';
|
||||
import { ReloadOutlined, SettingOutlined } from '@ant-design/icons-vue';
|
||||
import { ReloadOutlined, SettingOutlined, SearchOutlined, LoadingOutlined } from '@ant-design/icons-vue';
|
||||
import GraphCanvas from '@/components/GraphCanvas.vue';
|
||||
import GraphDetailPanel from '@/components/GraphDetailPanel.vue';
|
||||
import { getKbTypeLabel } from '@/utils/kb_utils';
|
||||
@ -241,14 +249,59 @@ onUnmounted(() => {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: var(--color-trans-light);
|
||||
backdrop-filter: blur(4px);
|
||||
padding: 6px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0px 4px var(--shadow-3);
|
||||
pointer-events: none; /* Let clicks pass through empty areas */
|
||||
|
||||
.actions-left, .actions-right {
|
||||
pointer-events: auto; /* Re-enable clicks for buttons/inputs */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: var(--color-trans-light);
|
||||
backdrop-filter: blur(4px);
|
||||
padding: 2px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0px 4px var(--shadow-3);
|
||||
}
|
||||
|
||||
:deep(.ant-input-affix-wrapper) {
|
||||
padding: 4px 11px;
|
||||
border-radius: 6px;
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
|
||||
&:hover, &:focus, &-focused {
|
||||
background: #fff;
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--gray-600);
|
||||
border-radius: 6px;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.graph-disabled {
|
||||
|
||||
@ -86,9 +86,6 @@
|
||||
<a-button type="default" @click="exportGraphData" :icon="h(ExportOutlined)">
|
||||
导出数据
|
||||
</a-button>
|
||||
<a-button type="default" @click="state.showInfoModal = true" :icon="h(InfoCircleOutlined)">
|
||||
说明
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user