Phase 3: Memory & Growth - Multi-file fusion, Entity alignment with embedding, Document import, Knowledge base panel
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>InsightFlow - 知识工作台 (Phase 2)</title>
|
||||
<title>InsightFlow - 知识工作台 (Phase 3)</title>
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
@@ -46,10 +46,44 @@
|
||||
color: #888;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.main {
|
||||
display: flex;
|
||||
height: calc(100vh - 50px);
|
||||
}
|
||||
.sidebar {
|
||||
width: 60px;
|
||||
background: #111;
|
||||
border-right: 1px solid #222;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.sidebar-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #666;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.sidebar-btn:hover, .sidebar-btn.active {
|
||||
background: #1a1a1a;
|
||||
color: #00d4ff;
|
||||
}
|
||||
.content-area {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
.editor-panel {
|
||||
width: 50%;
|
||||
border-right: 1px solid #222;
|
||||
@@ -199,10 +233,29 @@
|
||||
border-radius: 16px;
|
||||
padding: 60px;
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
}
|
||||
.upload-box:hover {
|
||||
border-color: #00d4ff;
|
||||
}
|
||||
.upload-tabs {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
.upload-tab {
|
||||
padding: 8px 16px;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
color: #888;
|
||||
}
|
||||
.upload-tab.active {
|
||||
border-color: #00d4ff;
|
||||
color: #00d4ff;
|
||||
}
|
||||
.btn {
|
||||
background: linear-gradient(90deg, #00d4ff, #7b2cbf);
|
||||
color: white;
|
||||
@@ -373,6 +426,164 @@
|
||||
.node-label {
|
||||
pointer-events: none;
|
||||
}
|
||||
/* Phase 3: Knowledge Base Panel */
|
||||
.kb-panel {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
background: #0a0a0a;
|
||||
}
|
||||
.kb-panel.show {
|
||||
display: flex;
|
||||
}
|
||||
.kb-header {
|
||||
padding: 16px 20px;
|
||||
background: #141414;
|
||||
border-bottom: 1px solid #222;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.kb-stats {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
.kb-stat {
|
||||
text-align: center;
|
||||
}
|
||||
.kb-stat-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #00d4ff;
|
||||
}
|
||||
.kb-stat-label {
|
||||
font-size: 0.75rem;
|
||||
color: #666;
|
||||
}
|
||||
.kb-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
.kb-sidebar {
|
||||
width: 200px;
|
||||
background: #111;
|
||||
border-right: 1px solid #222;
|
||||
padding: 16px 0;
|
||||
}
|
||||
.kb-nav-item {
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
color: #888;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
.kb-nav-item:hover {
|
||||
background: #1a1a1a;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
.kb-nav-item.active {
|
||||
background: #1a1a1a;
|
||||
color: #00d4ff;
|
||||
border-left-color: #00d4ff;
|
||||
}
|
||||
.kb-main {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.kb-section {
|
||||
display: none;
|
||||
}
|
||||
.kb-section.active {
|
||||
display: block;
|
||||
}
|
||||
.kb-entity-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.kb-entity-card {
|
||||
background: #141414;
|
||||
border: 1px solid #222;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.kb-entity-card:hover {
|
||||
border-color: #00d4ff;
|
||||
}
|
||||
.kb-entity-name {
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.kb-entity-def {
|
||||
font-size: 0.85rem;
|
||||
color: #888;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.kb-entity-meta {
|
||||
font-size: 0.75rem;
|
||||
color: #666;
|
||||
}
|
||||
.kb-glossary-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: #141414;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.kb-transcript-item {
|
||||
padding: 12px 16px;
|
||||
background: #141414;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.file-type-icon {
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.type-audio { background: #7b2cbf; }
|
||||
.type-document { background: #00d4ff; color: #000; }
|
||||
/* Transcript selector */
|
||||
.transcript-selector {
|
||||
position: relative;
|
||||
}
|
||||
.transcript-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 8px;
|
||||
min-width: 200px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
}
|
||||
.transcript-dropdown.show {
|
||||
display: block;
|
||||
}
|
||||
.transcript-option {
|
||||
padding: 10px 16px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
.transcript-option:hover {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
.transcript-option.active {
|
||||
background: #00d4ff22;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -381,35 +592,113 @@
|
||||
<a href="/" class="back-link">← 返回项目列表</a>
|
||||
<span class="project-name" id="projectName">加载中...</span>
|
||||
</div>
|
||||
<button class="btn btn-small" onclick="showUpload()">+ 上传音频</button>
|
||||
<div class="header-actions">
|
||||
<button class="btn btn-small" onclick="showUpload()">+ 上传文件</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<div class="editor-panel">
|
||||
<div class="panel-header">
|
||||
<span>📄 转录文本</span>
|
||||
<div class="panel-actions">
|
||||
<button class="btn-icon" onclick="toggleEditMode()" id="editBtn">✏️ 编辑</button>
|
||||
<button class="btn-icon" onclick="saveTranscript()" id="saveBtn" style="display:none;">💾 保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="transcript-content" id="transcriptContent">
|
||||
<div class="empty-state">
|
||||
<p style="color:#666;">暂无转录内容</p>
|
||||
<button class="btn" onclick="showUpload()">上传音频</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<button class="sidebar-btn active" onclick="switchView('workbench')" title="工作台">📝</button>
|
||||
<button class="sidebar-btn" onclick="switchView('knowledge-base')" title="知识库">📚</button>
|
||||
</div>
|
||||
|
||||
<div class="graph-panel">
|
||||
<div class="panel-header">
|
||||
<span>🔗 知识图谱</span>
|
||||
<span style="font-size:0.8rem;color:#666;">右键节点编辑 | 拖拽建立关系</span>
|
||||
<!-- Content Area -->
|
||||
<div class="content-area">
|
||||
<!-- Workbench View -->
|
||||
<div id="workbenchView" class="workbench-view" style="display: flex; width: 100%;">
|
||||
<div class="editor-panel">
|
||||
<div class="panel-header">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span>📄 转录文本</span>
|
||||
<div class="transcript-selector">
|
||||
<button class="btn-icon" onclick="toggleTranscriptDropdown()">📁 选择文件</button>
|
||||
<div class="transcript-dropdown" id="transcriptDropdown"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-actions">
|
||||
<button class="btn-icon" onclick="toggleEditMode()" id="editBtn">✏️ 编辑</button>
|
||||
<button class="btn-icon" onclick="saveTranscript()" id="saveBtn" style="display:none;">💾 保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="transcript-content" id="transcriptContent">
|
||||
<div class="empty-state">
|
||||
<p style="color:#666;">暂无转录内容</p>
|
||||
<button class="btn" onclick="showUpload()">上传音频或文档</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="graph-panel">
|
||||
<div class="panel-header">
|
||||
<span>🔗 知识图谱</span>
|
||||
<span style="font-size:0.8rem;color:#666;">右键节点编辑 | 拖拽建立关系</span>
|
||||
</div>
|
||||
<svg id="graph-svg"></svg>
|
||||
<div class="entity-list" id="entityList">
|
||||
<h3 style="margin-bottom:12px;color:#888;font-size:0.9rem;">项目实体</h3>
|
||||
<p style="color:#666;font-size:0.85rem;">暂无实体数据</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svg id="graph-svg"></svg>
|
||||
<div class="entity-list" id="entityList">
|
||||
<h3 style="margin-bottom:12px;color:#888;font-size:0.9rem;">项目实体</h3>
|
||||
<p style="color:#666;font-size:0.85rem;">暂无实体数据</p>
|
||||
|
||||
<!-- Knowledge Base View -->
|
||||
<div id="knowledgeBaseView" class="kb-panel">
|
||||
<div class="kb-header">
|
||||
<h2>📚 项目知识库</h2>
|
||||
<div class="kb-stats">
|
||||
<div class="kb-stat">
|
||||
<div class="kb-stat-value" id="kbEntityCount">0</div>
|
||||
<div class="kb-stat-label">实体</div>
|
||||
</div>
|
||||
<div class="kb-stat">
|
||||
<div class="kb-stat-value" id="kbRelationCount">0</div>
|
||||
<div class="kb-stat-label">关系</div>
|
||||
</div>
|
||||
<div class="kb-stat">
|
||||
<div class="kb-stat-value" id="kbTranscriptCount">0</div>
|
||||
<div class="kb-stat-label">文件</div>
|
||||
</div>
|
||||
<div class="kb-stat">
|
||||
<div class="kb-stat-value" id="kbGlossaryCount">0</div>
|
||||
<div class="kb-stat-label">术语</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kb-content">
|
||||
<div class="kb-sidebar">
|
||||
<div class="kb-nav-item active" onclick="switchKBTab('entities')">🏷️ 实体</div>
|
||||
<div class="kb-nav-item" onclick="switchKBTab('relations')">🔗 关系</div>
|
||||
<div class="kb-nav-item" onclick="switchKBTab('glossary')">📖 术语表</div>
|
||||
<div class="kb-nav-item" onclick="switchKBTab('transcripts')">📁 文件</div>
|
||||
</div>
|
||||
<div class="kb-main">
|
||||
<!-- Entities Section -->
|
||||
<div class="kb-section active" id="kbEntitiesSection">
|
||||
<h3 style="margin-bottom:16px;">所有实体</h3>
|
||||
<div class="kb-entity-grid" id="kbEntityGrid"></div>
|
||||
</div>
|
||||
<!-- Relations Section -->
|
||||
<div class="kb-section" id="kbRelationsSection">
|
||||
<h3 style="margin-bottom:16px;">所有关系</h3>
|
||||
<div id="kbRelationsList"></div>
|
||||
</div>
|
||||
<!-- Glossary Section -->
|
||||
<div class="kb-section" id="kbGlossarySection">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;">
|
||||
<h3>术语表</h3>
|
||||
<button class="btn btn-small" onclick="showAddTermModal()">+ 添加术语</button>
|
||||
</div>
|
||||
<div id="kbGlossaryList"></div>
|
||||
</div>
|
||||
<!-- Transcripts Section -->
|
||||
<div class="kb-section" id="kbTranscriptsSection">
|
||||
<h3 style="margin-bottom:16px;">所有文件</h3>
|
||||
<div id="kbTranscriptsList"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -417,10 +706,15 @@
|
||||
<!-- Upload Modal -->
|
||||
<div class="upload-overlay" id="uploadOverlay">
|
||||
<div class="upload-box">
|
||||
<h2 style="margin-bottom:10px;">上传音频分析</h2>
|
||||
<p style="color:#666;">支持 MP3, WAV, M4A (最大 500MB)</p>
|
||||
<h2 style="margin-bottom:10px;">上传文件</h2>
|
||||
<div class="upload-tabs">
|
||||
<div class="upload-tab active" onclick="switchUploadTab('audio')">🎵 音频</div>
|
||||
<div class="upload-tab" onclick="switchUploadTab('document')">📄 文档</div>
|
||||
</div>
|
||||
<p style="color:#666;" id="uploadHint">支持 MP3, WAV, M4A (最大 500MB)</p>
|
||||
<input type="file" id="fileInput" accept="audio/*" hidden>
|
||||
<button class="btn" onclick="document.getElementById('fileInput').click()">选择文件</button>
|
||||
<input type="file" id="docInput" accept=".pdf,.docx,.doc,.txt,.md" hidden>
|
||||
<button class="btn" onclick="triggerFileSelect()">选择文件</button>
|
||||
<br><br>
|
||||
<button class="btn btn-secondary" onclick="hideUpload()">取消</button>
|
||||
</div>
|
||||
@@ -514,6 +808,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Glossary Term Modal -->
|
||||
<div class="modal-overlay" id="glossaryModal">
|
||||
<div class="modal">
|
||||
<h3 class="modal-header">添加术语</h3>
|
||||
<div class="form-group">
|
||||
<label>术语</label>
|
||||
<input type="text" id="glossaryTerm" placeholder="术语名称">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>发音提示 (可选)</label>
|
||||
<input type="text" id="glossaryPronunciation" placeholder="如: K8s 发音为 Kubernetes">
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn btn-secondary" onclick="hideGlossaryModal()">取消</button>
|
||||
<button class="btn" onclick="saveGlossaryTerm()">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Context Menu -->
|
||||
<div class="context-menu" id="contextMenu">
|
||||
<div class="context-menu-item" onclick="editEntity()">✏️ 编辑实体</div>
|
||||
|
||||
Reference in New Issue
Block a user