feat: restore Wolai workspace navigation and assets
This commit is contained in:
@@ -705,7 +705,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="mnote-weknora-kb-page-title">' +
|
||||
'<span class="mnote-weknora-kb-page-eyebrow">LightRAG</span>' +
|
||||
'<strong>知识库</strong>' +
|
||||
'<span>由 MNote source registry 与 LightRAG 索引驱动</span>' +
|
||||
'<span>资料、索引状态和检索</span>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-weknora-kb-page-actions">' +
|
||||
'<button type="button" data-knowledge-rag-action="refresh" title="刷新"><span class="material-symbols-outlined" data-icon="refresh" aria-hidden="true"></span></button>' +
|
||||
@@ -714,44 +714,54 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-weknora-kb-page-status" data-testid="mnote-knowledge-rag-status"></div>' +
|
||||
'<div class="mnote-weknora-kb-page-body">' +
|
||||
'<aside class="mnote-weknora-kb-list-pane" data-testid="mnote-weknora-kb-list-pane">' +
|
||||
'<div class="mnote-weknora-kb-page-body" data-kb-list-hidden="true">' +
|
||||
'<aside class="mnote-weknora-kb-list-pane" data-testid="mnote-weknora-kb-list-pane" hidden>' +
|
||||
'<div class="mnote-weknora-kb-list-head">' +
|
||||
'<div><strong>资料库</strong><span data-testid="mnote-weknora-kb-list-count">0</span></div>' +
|
||||
'<button type="button" data-knowledge-rag-action="focus-create-kb" title="LightRAG 当前使用单资料库" hidden><span class="material-symbols-outlined" data-icon="create_new_folder" aria-hidden="true"></span></button>' +
|
||||
'<button type="button" data-knowledge-rag-action="toggle-create-kb" title="新建资料库"><span class="material-symbols-outlined" data-icon="create_new_folder" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-weknora-kb-card-wrap" data-testid="mnote-weknora-kb-card-list"></div>' +
|
||||
'<section class="mnote-weknora-kb-create-card" data-testid="mnote-weknora-kb-controls" hidden>' +
|
||||
'<div class="mnote-weknora-kb-create-title"><span class="material-symbols-outlined" data-icon="folder_add" aria-hidden="true"></span><strong>新建逻辑资料库</strong></div>' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-testid="mnote-weknora-create-kb-name" data-knowledge-rag-create-kb-name="true" placeholder="知识库名称" spellcheck="false" />' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-testid="mnote-weknora-create-kb-description" data-knowledge-rag-create-kb-description="true" placeholder="描述,可留空" spellcheck="false" />' +
|
||||
'<button type="button" class="wolai-page-settings-index-add" data-knowledge-rag-action="create-kb">创建知识库</button>' +
|
||||
'<span class="mnote-knowledge-rag-input-status" data-testid="mnote-weknora-create-kb-status" data-knowledge-rag-create-kb-status hidden></span>' +
|
||||
'</section>' +
|
||||
'</aside>' +
|
||||
'<section class="mnote-weknora-kb-detail-pane" data-testid="mnote-weknora-kb-detail-pane">' +
|
||||
'<div class="mnote-weknora-kb-detail-hero" data-testid="mnote-weknora-kb-detail-hero">' +
|
||||
'<div>' +
|
||||
'<nav class="mnote-weknora-kb-breadcrumb" data-testid="mnote-weknora-kb-breadcrumb" aria-label="知识库面包屑"><span>知识库</span><span>/</span><strong data-testid="mnote-weknora-kb-breadcrumb-current">LightRAG 资料库</strong></nav>' +
|
||||
'<span class="mnote-weknora-kb-type-pill"><span class="material-symbols-outlined" data-icon="folder" aria-hidden="true"></span>Source Registry</span>' +
|
||||
'<span class="mnote-weknora-kb-type-pill"><span class="material-symbols-outlined" data-icon="folder" aria-hidden="true"></span>资料来源</span>' +
|
||||
'<h2 data-testid="mnote-weknora-kb-detail-title">LightRAG 资料库</h2>' +
|
||||
'<p data-testid="mnote-weknora-kb-detail-description">MNote 管理本地来源、引用定位和权限边界,LightRAG 负责索引与召回。</p>' +
|
||||
'</div>' +
|
||||
'<select class="mnote-kb-params-select" data-testid="mnote-weknora-kb-select" data-knowledge-rag-kb-select="true"><option value="">加载中...</option></select>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-meta" data-testid="mnote-knowledge-rag-meta"></div>' +
|
||||
'<div class="mnote-knowledge-rag-detail-tabs" role="tablist" aria-label="LightRAG 知识库详情">' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab is-active" role="tab" aria-selected="true" data-kb-rag-tab="sources" data-testid="mnote-weknora-tab-documents">来源</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab" role="tab" aria-selected="false" data-kb-rag-tab="wiki" data-testid="mnote-weknora-tab-wiki">Wiki</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab" role="tab" aria-selected="false" data-kb-rag-tab="graph" data-testid="mnote-weknora-tab-graph">Graph</button>' +
|
||||
'<section class="mnote-knowledge-rag-kb-manager" data-testid="mnote-knowledge-rag-kb-manager">' +
|
||||
'<div class="mnote-knowledge-rag-kb-manager-row">' +
|
||||
'<label class="mnote-knowledge-rag-kb-select-field"><span>当前资料库</span><select class="mnote-kb-params-select" data-testid="mnote-weknora-kb-select" data-knowledge-rag-kb-select="true"><option value="">加载中...</option></select></label>' +
|
||||
'<button type="button" data-knowledge-rag-action="toggle-create-kb"><span class="material-symbols-outlined" data-icon="folder_add" aria-hidden="true"></span>新建</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="delete-kb" data-knowledge-rag-delete-selected-kb="true"><span class="material-symbols-outlined" data-icon="delete" aria-hidden="true"></span>删除</button>' +
|
||||
'</div>' +
|
||||
'<section class="mnote-weknora-kb-create-card" data-testid="mnote-weknora-kb-controls" hidden>' +
|
||||
'<div class="mnote-weknora-kb-create-title"><span class="material-symbols-outlined" data-icon="folder_add" aria-hidden="true"></span><strong>新建资料库</strong></div>' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-testid="mnote-weknora-create-kb-name" data-knowledge-rag-create-kb-name="true" placeholder="知识库名称" spellcheck="false" />' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-testid="mnote-weknora-create-kb-description" data-knowledge-rag-create-kb-description="true" placeholder="描述,可留空" spellcheck="false" />' +
|
||||
'<button type="button" class="wolai-page-settings-index-add" data-knowledge-rag-action="create-kb">创建知识库</button>' +
|
||||
'<span class="mnote-knowledge-rag-input-status" data-testid="mnote-weknora-create-kb-status" data-knowledge-rag-create-kb-status hidden></span>' +
|
||||
'</section>' +
|
||||
'<div class="mnote-knowledge-rag-kb-manager-note" data-testid="mnote-knowledge-rag-kb-manager-note"></div>' +
|
||||
'</section>' +
|
||||
'<details class="mnote-knowledge-rag-diagnostics" data-testid="mnote-knowledge-rag-diagnostics">' +
|
||||
'<summary>诊断信息</summary>' +
|
||||
'<div class="mnote-knowledge-rag-meta" data-testid="mnote-knowledge-rag-meta"></div>' +
|
||||
'</details>' +
|
||||
'<div class="mnote-knowledge-rag-detail-tabs" role="tablist" aria-label="当前资料库内容">' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab is-active" role="tab" aria-selected="true" data-kb-rag-tab="sources" data-testid="mnote-weknora-tab-documents">资料</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab" role="tab" aria-selected="false" data-kb-rag-tab="wiki" data-testid="mnote-weknora-tab-wiki" hidden>Wiki</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab" role="tab" aria-selected="false" data-kb-rag-tab="graph" data-testid="mnote-weknora-tab-graph" hidden>Graph</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab" role="tab" aria-selected="false" data-kb-rag-tab="search">检索</button>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-detail-panel" data-kb-rag-panel="sources">' +
|
||||
'<div class="mnote-weknora-doc-layout" data-testid="mnote-weknora-document-management">' +
|
||||
'<aside class="mnote-weknora-doc-sidebar" data-testid="mnote-weknora-doc-source-sidebar">' +
|
||||
'<aside class="mnote-weknora-doc-sidebar" data-testid="mnote-weknora-doc-source-sidebar" hidden>' +
|
||||
'<div class="mnote-weknora-doc-sidebar-head"><strong>来源</strong><span>MNote registry</span></div>' +
|
||||
'<div class="mnote-weknora-doc-source-tags" data-testid="mnote-weknora-doc-source-tags">' +
|
||||
'<button type="button" data-knowledge-rag-action="filter-sources" data-knowledge-rag-filter="all" data-active="true"><span class="material-symbols-outlined" data-icon="folder" aria-hidden="true"></span>全部来源</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="filter-sources" data-knowledge-rag-filter="all" data-active="true"><span class="material-symbols-outlined" data-icon="folder" aria-hidden="true"></span>全部资料</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="filter-sources" data-knowledge-rag-filter="indexed"><span class="material-symbols-outlined" data-icon="check_circle" aria-hidden="true"></span>已索引</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="filter-sources" data-knowledge-rag-filter="indexing"><span class="material-symbols-outlined" data-icon="sync" aria-hidden="true"></span>处理中</button>' +
|
||||
'</div>' +
|
||||
@@ -760,21 +770,23 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'</aside>' +
|
||||
'<section class="mnote-weknora-doc-main">' +
|
||||
'<div class="mnote-weknora-doc-toolbar">' +
|
||||
'<div class="mnote-weknora-doc-search"><span class="material-symbols-outlined" data-icon="search" aria-hidden="true"></span><input type="text" data-testid="mnote-weknora-doc-filter-input" data-knowledge-rag-doc-filter-input="true" placeholder="搜索或筛选当前知识库文档" spellcheck="false" /></div>' +
|
||||
'<div class="mnote-weknora-doc-search"><span class="material-symbols-outlined" data-icon="search" aria-hidden="true"></span><input type="text" data-testid="mnote-weknora-doc-filter-input" data-knowledge-rag-doc-filter-input="true" placeholder="搜索或筛选当前资料库内容" spellcheck="false" /></div>' +
|
||||
'<div class="mnote-weknora-view-switch" role="group" aria-label="文档视图切换" data-testid="mnote-weknora-view-switch">' +
|
||||
'<button type="button" class="is-active" data-knowledge-rag-view="list" aria-pressed="true" title="列表视图"><span class="material-symbols-outlined" data-icon="view_list" aria-hidden="true"></span></button>' +
|
||||
'<button type="button" data-knowledge-rag-view="grid" aria-pressed="false" title="网格视图"><span class="material-symbols-outlined" data-icon="grid_view" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<button type="button" data-knowledge-rag-action="use-filetree-selection"><span class="material-symbols-outlined" data-icon="account_tree" aria-hidden="true"></span>添加文件夹</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="add-source"><span class="material-symbols-outlined" data-icon="upload_file" aria-hidden="true"></span>添加文档</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="use-filetree-selection"><span class="material-symbols-outlined" data-icon="account_tree" aria-hidden="true"></span>从文件树添加</button>' +
|
||||
'<button type="button" class="mnote-knowledge-rag-primary-action" data-knowledge-rag-action="add-source"><span class="material-symbols-outlined" data-icon="upload_file" aria-hidden="true"></span>添加资料</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="ingest-active"><span class="material-symbols-outlined" data-icon="note_add" aria-hidden="true"></span>加入当前页</button>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-source-inputs" data-testid="mnote-knowledge-rag-source-inputs">' +
|
||||
knowledgeRagSourceInputRow('') +
|
||||
'</div>' +
|
||||
'<div class="mnote-weknora-doc-actions">' +
|
||||
'<button type="button" data-knowledge-rag-action="ingest">索引到 LightRAG</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="prune">清除失效记录</button>' +
|
||||
'<div class="mnote-knowledge-rag-source-composer" data-knowledge-rag-source-composer="true" hidden>' +
|
||||
'<div class="mnote-knowledge-rag-source-inputs" data-testid="mnote-knowledge-rag-source-inputs">' +
|
||||
knowledgeRagSourceInputRow('') +
|
||||
'</div>' +
|
||||
'<div class="mnote-weknora-doc-actions">' +
|
||||
'<button type="button" class="mnote-knowledge-rag-primary-action" data-knowledge-rag-action="ingest">开始索引</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="prune">清除失效记录</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-source-filters" data-testid="mnote-knowledge-rag-source-filters"></div>' +
|
||||
'<div class="mnote-weknora-doc-table" data-testid="mnote-knowledge-rag-sources" data-weknora-document-list-view="true"></div>' +
|
||||
@@ -795,11 +807,11 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-detail-panel" data-kb-rag-panel="search" hidden>' +
|
||||
'<div class="mnote-kb-search-form">' +
|
||||
'<input type="text" class="mnote-kb-search-input" data-kb-rag-search-input="true" placeholder="输入检索关键词...">' +
|
||||
'<button type="button" class="wolai-page-settings-index-add" data-kb-rag-action="search">搜索</button>' +
|
||||
'<div class="mnote-kb-search-box"><span class="material-symbols-outlined" data-icon="search" aria-hidden="true"></span><input type="text" class="mnote-kb-search-input" data-kb-rag-search-input="true" placeholder="在当前资料库中检索关键词" spellcheck="false"></div>' +
|
||||
'<button type="button" class="wolai-page-settings-index-add" data-kb-rag-action="search"><span class="material-symbols-outlined" data-icon="search" aria-hidden="true"></span>检索</button>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-kb-search-results" data-kb-rag-search-results="true">' +
|
||||
'<span class="mnote-extensions-loading">输入关键词后用 LightRAG hybrid 检索</span>' +
|
||||
'<div class="mnote-kb-search-empty">输入关键词后检索当前资料库</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-detail-panel" data-kb-rag-panel="params" hidden>' +
|
||||
@@ -819,7 +831,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'</div>' +
|
||||
'<div class="mnote-kb-params-row">' +
|
||||
'<label class="mnote-kb-params-label">排序说明</label>' +
|
||||
'<span class="mnote-kb-params-help">结果按 provider 排序分返回;兼容阈值字段保留在请求层,不作为默认主控。</span>' +
|
||||
'<span class="mnote-kb-params-help">结果按相关度排序;高级阈值保留在请求层。</span>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="wolai-page-settings-index-add" data-kb-rag-action="save-params">保存参数</button>' +
|
||||
'</div>' +
|
||||
@@ -1194,6 +1206,12 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function setKnowledgeRagSourceComposerVisible(visible) {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var composer = popover.querySelector('[data-knowledge-rag-source-composer]');
|
||||
if (composer instanceof HTMLElement) composer.hidden = !visible;
|
||||
}
|
||||
|
||||
function knowledgeRagSourceInputValues() {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
return Array.from(popover.querySelectorAll('[data-knowledge-rag-source-input]')).map(function(input) {
|
||||
@@ -1342,6 +1360,25 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
return knowledgeRagStatusValue(status);
|
||||
}
|
||||
|
||||
function knowledgeRagUserStatusLabel(status) {
|
||||
var text = String(status || '').trim().toLowerCase();
|
||||
if (!text) return '';
|
||||
if (text === 'provider_missing') return '索引记录缺失';
|
||||
if (text === 'failed' || text.includes('fail')) return '索引失败';
|
||||
if (text === 'delete_submitted') return '正在移除索引';
|
||||
if (text === 'delete_completed') return '已移除索引';
|
||||
if (text === 'provider_mapped' || text === 'completed' || text === 'processed' || text === 'indexed') return '已索引';
|
||||
if (['pending', 'submitted', 'scanning', 'parsing', 'parse', 'parsed', 'analyzing', 'analyze', 'processing', 'process'].includes(text)) return '处理中';
|
||||
return text.replace(/_/g, ' ');
|
||||
}
|
||||
|
||||
function knowledgeRagUserDescription(description) {
|
||||
var text = String(description || '').trim();
|
||||
if (!text) return '';
|
||||
if (/source registry|provider|sidecar|chunk|kb id|knowledge base id/i.test(text)) return '';
|
||||
return text;
|
||||
}
|
||||
|
||||
function knowledgeRagProviderKnowledgeBaseIds(status) {
|
||||
var config = status && status.providerConfig && typeof status.providerConfig === 'object' ? status.providerConfig : {};
|
||||
var weknora = config.weknora && typeof config.weknora === 'object' ? config.weknora : {};
|
||||
@@ -1415,11 +1452,12 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
status: 'configured'
|
||||
});
|
||||
});
|
||||
if (!output.length && ['lightrag', 'lightrag_legacy'].includes(knowledgeRagProviderName(status || {}))) {
|
||||
output.push({
|
||||
if (!seen['lightrag-default'] && ['lightrag', 'lightrag_legacy'].includes(knowledgeRagProviderName(status || {}))) {
|
||||
seen['lightrag-default'] = true;
|
||||
output.unshift({
|
||||
providerKbId: 'lightrag-default',
|
||||
name: '默认资料库',
|
||||
description: 'LightRAG 单工作区索引,由 MNote source registry 划分范围',
|
||||
description: '包含当前工作区的全部已索引资料',
|
||||
sourceCount: ((status && status.registry && Array.isArray(status.registry.entries)) ? status.registry.entries.length : 0),
|
||||
chunkCount: 0,
|
||||
updatedAt: '',
|
||||
@@ -1440,6 +1478,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
|
||||
function setKnowledgeRagSelectedProviderKnowledgeBaseId(providerKnowledgeBaseId) {
|
||||
pageUiState.knowledgeRagSelectedProviderKnowledgeBaseId = String(providerKnowledgeBaseId || '').trim();
|
||||
pageUiState.knowledgeRagSourceFilter = 'all';
|
||||
renderKnowledgeRagSettings();
|
||||
}
|
||||
|
||||
@@ -1491,22 +1530,47 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
};
|
||||
}
|
||||
|
||||
function knowledgeRagBaseStatusLabel(status) {
|
||||
var text = String(status || 'active').trim().toLowerCase();
|
||||
if (!text || text === 'active' || text === 'configured') return '可用';
|
||||
if (text === 'processing' || text === 'indexing') return '处理中';
|
||||
if (text === 'test' || text === 'preview' || text === 'local') return '测试';
|
||||
if (text === 'failed' || text === 'error') return '异常';
|
||||
return String(status || '可用').replace(/_/g, ' ');
|
||||
}
|
||||
|
||||
function knowledgeRagOptimisticBases() {
|
||||
return Array.isArray(pageUiState.knowledgeRagOptimisticBases) ? pageUiState.knowledgeRagOptimisticBases : [];
|
||||
}
|
||||
|
||||
function knowledgeRagBaseIsOptimistic(providerKnowledgeBaseId) {
|
||||
var selected = String(providerKnowledgeBaseId || '').trim();
|
||||
return Boolean(selected && knowledgeRagOptimisticBases().some(function(base) {
|
||||
return knowledgeRagBaseProviderKbId(base) === selected;
|
||||
}));
|
||||
}
|
||||
|
||||
function renderKnowledgeRagKnowledgeBaseCards(popover, status, entries, providerDocs) {
|
||||
var listNode = popover.querySelector('[data-testid="mnote-weknora-kb-card-list"]');
|
||||
var countNode = popover.querySelector('[data-testid="mnote-weknora-kb-list-count"]');
|
||||
var listPane = popover.querySelector('[data-testid="mnote-weknora-kb-list-pane"]');
|
||||
var pageBody = popover.querySelector('.mnote-weknora-kb-page-body');
|
||||
if (!(listNode instanceof HTMLElement)) return;
|
||||
var bases = knowledgeRagKnowledgeBases(status || {});
|
||||
var selected = selectedKnowledgeRagProviderKnowledgeBaseId(status || {});
|
||||
var providerName = knowledgeRagProviderName(status || {});
|
||||
if (countNode instanceof HTMLElement) countNode.textContent = String(bases.length);
|
||||
if (listPane instanceof HTMLElement) listPane.hidden = bases.length <= 1;
|
||||
if (pageBody instanceof HTMLElement) pageBody.setAttribute('data-kb-list-hidden', bases.length <= 1 ? 'true' : 'false');
|
||||
if (!bases.length) {
|
||||
listNode.innerHTML = '<div class="wolai-page-settings-index-empty">还没有知识库来源</div>';
|
||||
listNode.innerHTML = '<div class="wolai-page-settings-index-empty">还没有资料库</div>';
|
||||
return;
|
||||
}
|
||||
listNode.innerHTML = bases.map(function(base) {
|
||||
var stats = knowledgeRagBaseStats(base, entries, providerDocs);
|
||||
var isActive = base.providerKbId === selected;
|
||||
var baseStatus = String(base.status || 'active');
|
||||
var baseStatusLabel = knowledgeRagBaseStatusLabel(baseStatus);
|
||||
return '' +
|
||||
'<button type="button" class="mnote-weknora-kb-card' + (isActive ? ' is-active' : '') + '" data-knowledge-rag-action="select-kb" data-knowledge-rag-kb-id="' + escapeHtml(base.providerKbId) + '" data-knowledge-rag-kb-provider="' + escapeHtml(providerName) + '" data-knowledge-rag-processing-count="' + escapeHtml(String(stats.processingCount)) + '">' +
|
||||
'<span class="mnote-weknora-kb-card-star"><span class="material-symbols-outlined" data-icon="folder" aria-hidden="true"></span></span>' +
|
||||
@@ -1519,12 +1583,13 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
(stats.processingCount ? '<i class="is-processing"><span class="material-symbols-outlined" data-icon="sync" aria-hidden="true"></span>' + escapeHtml(String(stats.processingCount)) + '</i>' : '') +
|
||||
'</span>' +
|
||||
'</span>' +
|
||||
'<span class="mnote-weknora-kb-card-status" data-status="' + escapeHtml(baseStatus) + '">' + escapeHtml(baseStatus) + '</span>' +
|
||||
'<span class="mnote-weknora-kb-card-status" data-status="' + escapeHtml(baseStatus) + '">' + escapeHtml(baseStatusLabel) + '</span>' +
|
||||
'</button>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderKnowledgeRagKnowledgeBaseHero(popover, status, entries, providerDocs) {
|
||||
var heroNode = popover.querySelector('[data-testid="mnote-weknora-kb-detail-hero"]');
|
||||
var titleNode = popover.querySelector('[data-testid="mnote-weknora-kb-detail-title"]');
|
||||
var descNode = popover.querySelector('[data-testid="mnote-weknora-kb-detail-description"]');
|
||||
var breadcrumbNode = popover.querySelector('[data-testid="mnote-weknora-kb-breadcrumb-current"]');
|
||||
@@ -1532,6 +1597,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var bases = knowledgeRagKnowledgeBases(status || {});
|
||||
var selected = selectedKnowledgeRagProviderKnowledgeBaseId(status || {});
|
||||
var base = bases.find(function(item) { return item.providerKbId === selected; }) || bases[0] || null;
|
||||
if (heroNode instanceof HTMLElement) heroNode.hidden = true;
|
||||
if (!base) {
|
||||
titleNode.textContent = '未配置知识库';
|
||||
descNode.textContent = '加入资料来源后,可在这里管理 MNote 授权的本地文件和引用。';
|
||||
@@ -1541,27 +1607,66 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var stats = knowledgeRagBaseStats(base, entries, providerDocs);
|
||||
titleNode.textContent = base.name;
|
||||
if (breadcrumbNode instanceof HTMLElement) breadcrumbNode.textContent = base.name;
|
||||
descNode.textContent = (base.description || '暂无描述') + ' · 文档 ' + stats.sourceCount + ' · chunk ' + stats.chunkCount + ' · processing ' + stats.processingCount;
|
||||
var userDescription = knowledgeRagUserDescription(base.description);
|
||||
descNode.textContent = stats.sourceCount + ' 个资料 · ' + stats.processingCount + ' 个处理中 · ' + stats.chunkCount + ' 个片段'
|
||||
+ (userDescription ? ' · ' + userDescription : '');
|
||||
}
|
||||
|
||||
function renderKnowledgeRagKnowledgeBaseControls(popover, status) {
|
||||
var select = popover.querySelector('[data-knowledge-rag-kb-select]');
|
||||
if (!(select instanceof HTMLSelectElement)) return;
|
||||
function renderKnowledgeRagKnowledgeBaseControls(popover, status, entries, providerDocs) {
|
||||
var selects = Array.from(popover.querySelectorAll('[data-knowledge-rag-kb-select]'))
|
||||
.filter(function(select) { return select instanceof HTMLSelectElement; });
|
||||
var deleteButton = popover.querySelector('[data-knowledge-rag-delete-selected-kb]');
|
||||
var noteNode = popover.querySelector('[data-testid="mnote-knowledge-rag-kb-manager-note"]');
|
||||
var bases = knowledgeRagKnowledgeBases(status || {});
|
||||
var selected = selectedKnowledgeRagProviderKnowledgeBaseId(status || {});
|
||||
if (!bases.length) {
|
||||
select.innerHTML = '<option value="">未配置 KB</option>';
|
||||
select.value = '';
|
||||
select.disabled = true;
|
||||
selects.forEach(function(select) {
|
||||
select.innerHTML = '<option value="">未配置资料库</option>';
|
||||
select.value = '';
|
||||
select.disabled = true;
|
||||
select.hidden = false;
|
||||
});
|
||||
if (deleteButton instanceof HTMLButtonElement) {
|
||||
deleteButton.disabled = true;
|
||||
deleteButton.title = '没有可删除的资料库';
|
||||
}
|
||||
if (noteNode instanceof HTMLElement) noteNode.textContent = '新建资料库后,可在这里切换当前工作区的资料范围。';
|
||||
return;
|
||||
}
|
||||
select.disabled = false;
|
||||
select.innerHTML = bases.map(function(base) {
|
||||
var label = base.name + ' · ' + base.sourceCount + ' sources · ' + base.providerKbId;
|
||||
var activeBase = bases.find(function(base) { return base.providerKbId === selected; }) || bases[0];
|
||||
var selectedValue = activeBase.providerKbId;
|
||||
var activeStats = knowledgeRagBaseStats(activeBase, entries || [], providerDocs || []);
|
||||
var optionsHtml = bases.map(function(base) {
|
||||
var stats = knowledgeRagBaseStats(base, entries || [], providerDocs || []);
|
||||
var label = base.name + ' · ' + stats.sourceCount + ' 个资料';
|
||||
return '<option value="' + escapeHtml(base.providerKbId) + '">' + escapeHtml(label) + '</option>';
|
||||
}).join('');
|
||||
select.value = selected || bases[0].providerKbId;
|
||||
pageUiState.knowledgeRagSelectedProviderKnowledgeBaseId = select.value;
|
||||
selects.forEach(function(select) {
|
||||
select.disabled = false;
|
||||
select.hidden = false;
|
||||
select.innerHTML = optionsHtml;
|
||||
select.value = selectedValue;
|
||||
});
|
||||
pageUiState.knowledgeRagSelectedProviderKnowledgeBaseId = selectedValue;
|
||||
if (deleteButton instanceof HTMLButtonElement) {
|
||||
var canDelete = selectedValue !== 'lightrag-default' && activeStats.sourceCount === 0 && activeStats.processingCount === 0;
|
||||
deleteButton.disabled = !canDelete;
|
||||
deleteButton.setAttribute('data-knowledge-rag-kb-id', selectedValue);
|
||||
deleteButton.title = canDelete ? '删除当前空资料库' : (selectedValue === 'lightrag-default' ? '默认资料库不能删除' : '请先移除资料后再删除资料库');
|
||||
}
|
||||
if (noteNode instanceof HTMLElement) {
|
||||
var providerName = knowledgeRagProviderName(status || {});
|
||||
var activeName = activeBase.name || '当前资料库';
|
||||
if (selectedValue === 'lightrag-default') {
|
||||
noteNode.textContent = '默认资料库显示当前工作区全部已索引资料;新建资料库可管理独立资料范围。';
|
||||
} else if (activeStats.sourceCount === 0 && activeStats.processingCount === 0) {
|
||||
noteNode.textContent = activeName + ':空资料库,可添加资料或直接删除。';
|
||||
} else if (providerName === 'weknora') {
|
||||
noteNode.textContent = bases.length > 1 ? '已连接多个资料库,可用下拉框切换当前范围。' : '当前只有一个资料库,可新建后切换。';
|
||||
} else {
|
||||
noteNode.textContent = bases.length > 1 ? '当前可切换资料库;删除前需要先移除其中资料。' : '当前使用默认资料库,也可以新建一个资料库管理独立范围。';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function knowledgeRagKbSummaryHtml(status, entries, providerDocs) {
|
||||
@@ -1581,8 +1686,8 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="mnote-weknora-kb-summary-card" data-testid="mnote-weknora-kb-summary" data-knowledge-rag-kb-id="' + escapeHtml(kbIds[0] || '') + '" data-knowledge-rag-kb-ids="' + escapeHtml(kbIds.join(',')) + '" data-knowledge-rag-kb-provider="' + escapeHtml(knowledgeRagProviderName(status || {})) + '" data-knowledge-rag-kb-status="configured">' +
|
||||
'<div><span>知识库</span><strong>' + escapeHtml(activeCount ? String(activeCount) + ' 个' : '未配置') + '</strong></div>' +
|
||||
'<div><span>文档</span><strong>' + escapeHtml(String((entries || []).length)) + '</strong></div>' +
|
||||
'<div><span>Provider docs</span><strong>' + escapeHtml(String((providerDocs || []).length)) + '</strong></div>' +
|
||||
'<div><span>Processing</span><strong data-knowledge-rag-processing-count="' + escapeHtml(String(processingCount)) + '">' + escapeHtml(String(processingCount)) + '</strong></div>' +
|
||||
'<div><span>索引文档</span><strong>' + escapeHtml(String((providerDocs || []).length)) + '</strong></div>' +
|
||||
'<div><span>处理中</span><strong data-knowledge-rag-processing-count="' + escapeHtml(String(processingCount)) + '">' + escapeHtml(String(processingCount)) + '</strong></div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
@@ -1797,8 +1902,8 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
startKnowledgeRagPipelineWatcher(reason);
|
||||
}
|
||||
|
||||
function knowledgeRagUnmappedProviderRows(status, entries) {
|
||||
var docs = knowledgeRagProviderDocuments(status);
|
||||
function knowledgeRagUnmappedProviderRows(status, entries, providerDocs) {
|
||||
var docs = Array.isArray(providerDocs) ? providerDocs : knowledgeRagProviderDocuments(status);
|
||||
if (!docs.length) return [];
|
||||
var mappedDocIds = new Set();
|
||||
var mappedFilePaths = new Set();
|
||||
@@ -1846,14 +1951,14 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
}, { all: 0, attention: 0, indexing: 0, failed: 0, indexed: 0, removed: 0, unmapped: 0 });
|
||||
var current = knowledgeRagCurrentFilter();
|
||||
var options = [
|
||||
['all', '全部'],
|
||||
['attention', '需处理'],
|
||||
['indexing', '索引中'],
|
||||
['indexing', '处理中'],
|
||||
['failed', '失败/过期'],
|
||||
['indexed', '已索引'],
|
||||
['removed', '已移除'],
|
||||
['unmapped', 'Provider 未映射'],
|
||||
['all', '全部']
|
||||
['indexed', '已索引']
|
||||
];
|
||||
if (counts.removed) options.push(['removed', '已移除']);
|
||||
if (counts.unmapped) options.push(['unmapped', '未关联资料']);
|
||||
filtersNode.innerHTML = options.map(function(item) {
|
||||
var key = item[0];
|
||||
var label = item[1];
|
||||
@@ -1868,32 +1973,33 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderKnowledgeRagSources(popover, entries, status) {
|
||||
function renderKnowledgeRagSources(popover, entries, status, providerDocs, activeBase) {
|
||||
var sourcesNode = popover.querySelector('[data-testid="mnote-knowledge-rag-sources"]');
|
||||
if (!(sourcesNode instanceof HTMLElement)) return;
|
||||
var scopedProviderDocs = Array.isArray(providerDocs) ? providerDocs : knowledgeRagProviderDocuments(status || {});
|
||||
var registryRows = (Array.isArray(entries) ? entries : []).map(function(entry) {
|
||||
return { kind: 'registry', category: knowledgeRagRegistryEntryCategory(entry), entry: entry };
|
||||
});
|
||||
var rows = registryRows.concat(knowledgeRagUnmappedProviderRows(status || {}, entries));
|
||||
var rows = registryRows.concat(knowledgeRagUnmappedProviderRows(status || {}, entries, scopedProviderDocs));
|
||||
renderKnowledgeRagSourceFilters(popover, rows);
|
||||
var filter = knowledgeRagCurrentFilter();
|
||||
var items = rows.filter(function(row) {
|
||||
return knowledgeRagVisibleForFilter(row, filter);
|
||||
});
|
||||
if (!rows.length) {
|
||||
sourcesNode.innerHTML = '<div class="wolai-page-settings-index-empty">还没有登记到知识库 provider 的资料来源</div>';
|
||||
var emptyName = activeBase && activeBase.name ? activeBase.name : '当前资料库';
|
||||
sourcesNode.innerHTML = '<div class="wolai-page-settings-index-empty">' + escapeHtml(emptyName) + ' 还没有资料</div>';
|
||||
return;
|
||||
}
|
||||
if (!items.length) {
|
||||
sourcesNode.innerHTML = '<div class="wolai-page-settings-index-empty">当前分类没有资料来源</div>';
|
||||
sourcesNode.innerHTML = '<div class="wolai-page-settings-index-empty">当前分类没有资料</div>';
|
||||
return;
|
||||
}
|
||||
var pipelineProgress = knowledgeRagPipelineProgress(status || {});
|
||||
var providerName = knowledgeRagProviderName(status || {});
|
||||
var providerDocs = knowledgeRagProviderDocuments(status || {});
|
||||
var providerDocsById = new Map();
|
||||
var providerDocsByPath = new Map();
|
||||
providerDocs.forEach(function(doc) {
|
||||
scopedProviderDocs.forEach(function(doc) {
|
||||
var docId = knowledgeRagProviderDocId(doc);
|
||||
var filePath = String(doc && doc.filePath || '').trim();
|
||||
if (docId) providerDocsById.set(docId, doc);
|
||||
@@ -1907,28 +2013,28 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var providerId = knowledgeRagProviderDocId(doc);
|
||||
var providerPath = String(doc.filePath || '');
|
||||
var docStatus = knowledgeRagProviderStatusText(doc.status || doc.statusGroup || doc.processingStatus || doc.processing_status);
|
||||
var docStatusLabel = knowledgeRagUserStatusLabel(docStatus) || '已记录';
|
||||
var failedDoc = row.category === 'unmapped_failed';
|
||||
var providerProgress = pipelineProgress && pipelineProgress.docId && pipelineProgress.docId === providerId ? pipelineProgress : null;
|
||||
var knowledgeId = knowledgeRagProviderKnowledgeId(doc);
|
||||
var providerTitle = providerPath || providerId || 'Provider 文档';
|
||||
var providerTitle = providerPath || providerId || '索引文档';
|
||||
var chunkCount = knowledgeRagProviderChunkCount(doc);
|
||||
var providerMeta = 'provider=' + providerName + ' · 未映射到 MNote source registry · ' + docStatus
|
||||
+ (providerId ? ' · provider id ' + providerId : '')
|
||||
+ (chunkCount ? ' · chunk ' + chunkCount : '')
|
||||
+ (providerPath ? '' : ' · 定位降级');
|
||||
var providerMeta = '未关联本地资料 · ' + docStatusLabel
|
||||
+ (chunkCount ? ' · ' + chunkCount + ' 个片段' : '')
|
||||
+ (providerPath ? '' : ' · 无法直接定位原文件');
|
||||
if (!providerProgress && !failedDoc && knowledgeRagDocumentIsInFlight(doc)) {
|
||||
providerProgress = knowledgeRagIndeterminateProgress(status || {}, doc, docStatus);
|
||||
}
|
||||
return '' +
|
||||
'<div class="mnote-knowledge-rag-source-row" data-knowledge-rag-source-row="true" data-knowledge-rag-source-kind="provider" data-knowledge-rag-provider="' + escapeHtml(providerName) + '" data-knowledge-rag-provider-id="' + escapeHtml(providerId) + '" data-knowledge-rag-knowledge-id="' + escapeHtml(knowledgeId) + '" data-knowledge-rag-chunk-count="' + escapeHtml(String(chunkCount || 0)) + '" data-knowledge-rag-processing-status="' + escapeHtml(docStatus) + '" data-knowledge-rag-open-reference-mode="provider-reference-fallback" data-knowledge-rag-source-path="' + escapeHtml(providerPath || providerId) + '">' +
|
||||
'<span class="wolai-page-settings-index-status-dot" data-index-status="' + (failedDoc ? 'fault' : 'indexed') + '" title="' + escapeHtml(docStatus || 'Provider 文档') + '"></span>' +
|
||||
'<span class="wolai-page-settings-index-status-dot" data-index-status="' + (failedDoc ? 'fault' : 'indexed') + '" title="' + escapeHtml(docStatusLabel || '索引文档') + '"></span>' +
|
||||
'<div class="mnote-knowledge-rag-source-main">' +
|
||||
'<strong title="' + escapeHtml(providerTitle) + '">' + escapeHtml(providerTitle) + '</strong>' +
|
||||
'<span>' + escapeHtml(providerMeta) + '</span>' +
|
||||
'<span class="mnote-weknora-source-aux"><i>' + escapeHtml(knowledgeId || 'provider-only') + '</i><i>' + escapeHtml(providerPath ? '引用可回跳' : '仅 provider 定位') + '</i></span>' +
|
||||
'<span class="mnote-weknora-source-aux"><i>' + escapeHtml(knowledgeId || '索引记录') + '</i><i>' + escapeHtml(providerPath ? '引用可回跳' : '无法直接定位') + '</i></span>' +
|
||||
knowledgeRagSourceProgressHtml(providerProgress) +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-source-actions"><button type="button" disabled>只读</button></div>' +
|
||||
'<div class="mnote-knowledge-rag-source-actions"></div>' +
|
||||
'</div>';
|
||||
}
|
||||
var entry = row.entry || {};
|
||||
@@ -1944,11 +2050,12 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var indexed = entry && (entry.indexedAtMs || providerStatus === 'provider_mapped' || providerStatus === 'completed' || providerStatus === 'processed') && docId && !deleted && !stale && !failed && !deleting && !deletedDone;
|
||||
var kind = deletedDone ? '' : (deleting ? 'indexing' : (failed || stale || deleted ? 'fault' : (indexed ? 'indexed' : 'indexing')));
|
||||
var title = String(entry && entry.sourceRootRelativePath || entry && entry.lightRagFilePath || '');
|
||||
var statusLabel = deletedDone ? 'Provider 已移除'
|
||||
var rawProviderStatusLabel = knowledgeRagUserStatusLabel(providerStatus);
|
||||
var statusLabel = deletedDone ? '已移除索引'
|
||||
: deleting ? '删除已提交'
|
||||
: deleted ? '已删除'
|
||||
: stale ? '已过期'
|
||||
: providerMissing ? 'Provider 索引缺失'
|
||||
: providerMissing ? '索引记录缺失'
|
||||
: failed ? '索引失败'
|
||||
: indexed ? '已索引'
|
||||
: (docId || providerStatus ? '正在索引' : '待提交');
|
||||
@@ -1958,12 +2065,10 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var kbId = knowledgeRagEntryProviderKnowledgeBaseId(entry);
|
||||
var metaParts = [
|
||||
statusLabel,
|
||||
'provider=' + providerName,
|
||||
'MNote source registry',
|
||||
kbId ? 'kb ' + kbId : '',
|
||||
providerIds.length ? 'provider ids ' + providerIds.join(', ') : '',
|
||||
chunkCount ? 'chunk ' + chunkCount : '',
|
||||
providerStatus ? 'processing ' + providerStatus : ''
|
||||
chunkCount ? chunkCount + ' 个片段' : '',
|
||||
rawProviderStatusLabel && !indexed && rawProviderStatusLabel !== statusLabel ? rawProviderStatusLabel : '',
|
||||
kbId ? '已绑定资料库' : '',
|
||||
providerIds.length ? providerIds.length + ' 个索引记录' : ''
|
||||
].filter(Boolean);
|
||||
var meta = metaParts.join(' · ');
|
||||
var sourcePath = String(entry && entry.sourceRootRelativePath || '');
|
||||
@@ -1977,15 +2082,15 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="mnote-knowledge-rag-source-row" data-knowledge-rag-source-row="true" data-knowledge-rag-provider="' + escapeHtml(providerName) + '" data-knowledge-rag-provider-ids="' + escapeHtml(providerIds.join(',')) + '" data-knowledge-rag-kb-id="' + escapeHtml(kbId) + '" data-knowledge-rag-knowledge-id="' + escapeHtml(knowledgeId) + '" data-knowledge-rag-chunk-count="' + escapeHtml(String(chunkCount || 0)) + '" data-knowledge-rag-processing-status="' + escapeHtml(providerStatus || statusLabel) + '" data-knowledge-rag-open-reference-mode="source-registry-reference" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '">' +
|
||||
'<span class="wolai-page-settings-index-status-dot" data-index-status="' + kind + '" title="' + escapeHtml(statusLabel) + '"></span>' +
|
||||
'<div class="mnote-knowledge-rag-source-main">' +
|
||||
'<strong title="' + escapeHtml(title) + '">' + escapeHtml(title || '未命名来源') + '</strong>' +
|
||||
'<strong title="' + escapeHtml(title) + '">' + escapeHtml(title || '未命名资料') + '</strong>' +
|
||||
'<span>' + escapeHtml(meta) + '</span>' +
|
||||
'<span class="mnote-weknora-source-aux"><i>' + escapeHtml(kbId || '未绑定 KB') + '</i><i>' + escapeHtml(knowledgeId || '待生成 citation') + '</i></span>' +
|
||||
knowledgeRagSourceProgressHtml(entryProgress) +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-source-actions">' +
|
||||
'<button type="button" data-knowledge-rag-action="open-source-reference" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (sourcePath ? '' : ' disabled') + '>打开引用</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="reindex-source" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (canReindex ? '' : ' disabled') + '>重索引</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="delete-source" data-knowledge-rag-delete-local-file-policy="preserve-local-file" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (canDelete ? '' : ' disabled') + ' title="删除 provider index 与 registry 映射,不删除本地文件">删除索引</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="open-source-reference" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (sourcePath ? '' : ' disabled') + '>打开</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="reindex-source" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (canReindex ? '' : ' disabled') + '>重试</button>' +
|
||||
'<button type="button" data-knowledge-rag-action="delete-source" data-knowledge-rag-delete-local-file-policy="preserve-local-file" data-knowledge-rag-source-path="' + escapeHtml(sourcePath) + '"' + (canDelete ? '' : ' disabled') + ' title="只移除索引记录,不删除本地文件">移除索引</button>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
@@ -2002,7 +2107,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
statusNode.textContent = '知识库仅在本地工作区可用';
|
||||
if (metaNode instanceof HTMLElement) metaNode.innerHTML = '';
|
||||
renderKnowledgeRagSourceFilters(popover, []);
|
||||
renderKnowledgeRagSources(popover, [], {});
|
||||
renderKnowledgeRagSources(popover, [], {}, [], null);
|
||||
if (dashboardButton instanceof HTMLButtonElement) dashboardButton.disabled = true;
|
||||
return;
|
||||
}
|
||||
@@ -2012,7 +2117,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
statusNode.textContent = '正在读取知识库 provider 状态...';
|
||||
if (metaNode instanceof HTMLElement) metaNode.innerHTML = '';
|
||||
renderKnowledgeRagSourceFilters(popover, []);
|
||||
renderKnowledgeRagSources(popover, [], {});
|
||||
renderKnowledgeRagSources(popover, [], {}, [], null);
|
||||
if (dashboardButton instanceof HTMLButtonElement) dashboardButton.disabled = true;
|
||||
return;
|
||||
}
|
||||
@@ -2020,7 +2125,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
statusNode.textContent = '知识库 provider 状态读取失败:' + summary.error;
|
||||
if (metaNode instanceof HTMLElement) metaNode.innerHTML = '';
|
||||
renderKnowledgeRagSourceFilters(popover, []);
|
||||
renderKnowledgeRagSources(popover, [], {});
|
||||
renderKnowledgeRagSources(popover, [], {}, [], null);
|
||||
if (dashboardButton instanceof HTMLButtonElement) dashboardButton.disabled = true;
|
||||
return;
|
||||
}
|
||||
@@ -2046,12 +2151,21 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
button.classList.toggle('is-active', active);
|
||||
button.setAttribute('aria-pressed', active ? 'true' : 'false');
|
||||
});
|
||||
renderKnowledgeRagKnowledgeBaseControls(popover, status);
|
||||
renderKnowledgeRagKnowledgeBaseControls(popover, status, entries, providerDocs);
|
||||
renderKnowledgeRagKnowledgeBaseCards(popover, status, entries, providerDocs);
|
||||
renderKnowledgeRagKnowledgeBaseHero(popover, status, entries, providerDocs);
|
||||
var processingCount = knowledgeRagInFlightCount(entries, providerDocs);
|
||||
var bases = knowledgeRagKnowledgeBases(status || {});
|
||||
var selectedBaseId = selectedKnowledgeRagProviderKnowledgeBaseId(status || {});
|
||||
var activeBase = bases.find(function(base) { return base.providerKbId === selectedBaseId; }) || bases[0] || null;
|
||||
var activeStats = activeBase ? knowledgeRagBaseStats(activeBase, entries, providerDocs) : null;
|
||||
var activeEntries = activeBase ? knowledgeRagEntriesForKb(entries, activeBase.providerKbId) : entries;
|
||||
var activeProviderDocs = activeBase ? knowledgeRagProviderDocsForKb(providerDocs, activeBase.providerKbId) : providerDocs;
|
||||
statusNode.textContent = healthy
|
||||
? providerLabel + ' 就绪,MNote 登记 ' + entries.length + ' 个来源,provider 文档 ' + providerDocs.length + ' 个'
|
||||
: providerLabel + ' 未就绪';
|
||||
? (activeBase
|
||||
? activeBase.name + ' · 服务可用 · ' + activeStats.sourceCount + ' 个资料' + (activeStats.processingCount ? ' · ' + activeStats.processingCount + ' 个处理中' : '')
|
||||
: '知识库服务可用 · ' + entries.length + ' 个资料' + (processingCount ? ' · ' + processingCount + ' 个处理中' : ''))
|
||||
: '知识库服务不可用,页面仍可编辑';
|
||||
if (metaNode instanceof HTMLElement) {
|
||||
var dashboardUrl = publicKnowledgeRagDashboardUrl(status);
|
||||
var inputDir = String((status.legacyFallback && status.legacyFallback.inputDir) || status.inputDir || '');
|
||||
@@ -2072,15 +2186,15 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
: 'unknown';
|
||||
metaNode.innerHTML = '' +
|
||||
knowledgeRagKbSummaryHtml(status, entries, providerDocs) +
|
||||
'<div><span>Provider</span><code>' + escapeHtml(providerLabel) + '</code></div>' +
|
||||
'<div><span>Boundary</span><code>MNote source registry / LightRAG sidecar locator</code></div>' +
|
||||
'<div><span>Dashboard</span><code>' + escapeHtml(dashboardUrl || '未配置') + '</code></div>' +
|
||||
'<div><span>Model</span><code>' + escapeHtml(llmModel || '未上报') + (vlmModel ? ' / VLM ' + escapeHtml(vlmModel) : '') + '</code></div>' +
|
||||
'<div><span>服务</span><code>' + escapeHtml(providerLabel) + '</code></div>' +
|
||||
'<div><span>边界</span><code>MNote source registry / LightRAG sidecar locator</code></div>' +
|
||||
'<div><span>控制台</span><code>' + escapeHtml(dashboardUrl || '未配置') + '</code></div>' +
|
||||
'<div><span>模型</span><code>' + escapeHtml(llmModel || '未上报') + (vlmModel ? ' / VLM ' + escapeHtml(vlmModel) : '') + '</code></div>' +
|
||||
'<div><span>Rerank</span><code>' + escapeHtml(rerankLabel + (rerankBinding ? ' · ' + rerankBinding : '') + (rerankModel ? ' · ' + rerankModel : '')) + '</code></div>' +
|
||||
'<div><span>Input</span><code>' + escapeHtml(inputDir || '未配置') + '</code></div>' +
|
||||
'<div><span>Storage</span><code>' + escapeHtml(workingDir || '未上报') + '</code></div>';
|
||||
'<div><span>输入目录</span><code>' + escapeHtml(inputDir || '未配置') + '</code></div>' +
|
||||
'<div><span>存储目录</span><code>' + escapeHtml(workingDir || '未上报') + '</code></div>';
|
||||
}
|
||||
renderKnowledgeRagSources(popover, entries, status);
|
||||
renderKnowledgeRagSources(popover, activeEntries, status, activeProviderDocs, activeBase);
|
||||
if (dashboardButton instanceof HTMLButtonElement) dashboardButton.disabled = !publicKnowledgeRagDashboardUrl(status);
|
||||
}
|
||||
|
||||
@@ -2165,8 +2279,11 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
function addKnowledgeRagSourceInput() {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var node = popover.querySelector('[data-testid="mnote-knowledge-rag-source-inputs"]');
|
||||
var composer = popover.querySelector('[data-knowledge-rag-source-composer]');
|
||||
if (!(node instanceof HTMLElement)) return;
|
||||
node.insertAdjacentHTML('beforeend', knowledgeRagSourceInputRow(''));
|
||||
var shouldAppend = !(composer instanceof HTMLElement && composer.hidden);
|
||||
setKnowledgeRagSourceComposerVisible(true);
|
||||
if (shouldAppend) node.insertAdjacentHTML('beforeend', knowledgeRagSourceInputRow(''));
|
||||
var inputs = Array.from(node.querySelectorAll('[data-knowledge-rag-source-input]'));
|
||||
var last = inputs[inputs.length - 1];
|
||||
if (last instanceof HTMLInputElement) last.focus();
|
||||
@@ -2202,6 +2319,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var node = popover.querySelector('[data-testid="mnote-knowledge-rag-source-inputs"]');
|
||||
if (!(node instanceof HTMLElement)) return;
|
||||
setKnowledgeRagSourceComposerVisible(true);
|
||||
var existing = knowledgeRagSourceInputValues();
|
||||
var next = existing.concat(selectedPaths).filter(function(value, index, list) {
|
||||
return list.indexOf(value) === index;
|
||||
@@ -2249,6 +2367,78 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
if (node instanceof HTMLElement) node.innerHTML = knowledgeRagSourceInputRow('');
|
||||
}
|
||||
|
||||
function setKnowledgeRagCreateCardVisible(visible) {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var card = popover.querySelector('[data-testid="mnote-weknora-kb-controls"]');
|
||||
var statusNode = popover.querySelector('[data-knowledge-rag-create-kb-status]');
|
||||
if (card instanceof HTMLElement) card.hidden = !visible;
|
||||
if (statusNode instanceof HTMLElement && visible) statusNode.hidden = true;
|
||||
if (visible) {
|
||||
var input = popover.querySelector('[data-knowledge-rag-create-kb-name]');
|
||||
if (input instanceof HTMLInputElement) input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleKnowledgeRagCreateCard() {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var card = popover.querySelector('[data-testid="mnote-weknora-kb-controls"]');
|
||||
setKnowledgeRagCreateCardVisible(!(card instanceof HTMLElement) || card.hidden);
|
||||
}
|
||||
|
||||
function setKnowledgeRagCreateStatus(text, status) {
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
var statusNode = popover.querySelector('[data-knowledge-rag-create-kb-status]');
|
||||
if (statusNode instanceof HTMLElement) {
|
||||
statusNode.textContent = String(text || '');
|
||||
statusNode.setAttribute('data-status', status || 'done');
|
||||
statusNode.hidden = !text;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteKnowledgeRagKnowledgeBase() {
|
||||
var status = currentKnowledgeRagSummary().status || {};
|
||||
var bases = knowledgeRagKnowledgeBases(status);
|
||||
var selected = selectedKnowledgeRagProviderKnowledgeBaseId(status);
|
||||
if (!selected || selected === 'lightrag-default') {
|
||||
setKnowledgeRagCreateStatus('默认资料库不能删除', 'failed');
|
||||
return;
|
||||
}
|
||||
var activeBase = bases.find(function(base) { return base.providerKbId === selected; }) || null;
|
||||
var registry = status.registry && typeof status.registry === 'object' ? status.registry : {};
|
||||
var entries = Array.isArray(registry.entries) ? registry.entries : [];
|
||||
var activeStats = activeBase ? knowledgeRagBaseStats(activeBase, entries, knowledgeRagProviderDocuments(status)) : null;
|
||||
if (activeStats && (activeStats.sourceCount > 0 || activeStats.processingCount > 0)) {
|
||||
setKnowledgeRagCreateStatus('请先移除资料后再删除资料库', 'failed');
|
||||
return;
|
||||
}
|
||||
setKnowledgeRagCreateStatus('删除中', 'running');
|
||||
try {
|
||||
var response = await fetch('/api/knowledge-rag/knowledge-bases', {
|
||||
method: 'DELETE',
|
||||
headers: { 'content-type': 'application/json', accept: 'application/json' },
|
||||
body: JSON.stringify({
|
||||
workspaceId: resolveWorkspaceId(document.body),
|
||||
rootUri: currentRootUri(),
|
||||
providerKnowledgeBaseId: selected
|
||||
})
|
||||
});
|
||||
var payload = await response.json().catch(function(){ return null; });
|
||||
if (!response.ok || !payload || payload.ok !== true) {
|
||||
throw new Error(payload && payload.message ? payload.message : 'knowledge_rag_delete_kb_' + response.status);
|
||||
}
|
||||
pageUiState.knowledgeRagOptimisticBases = knowledgeRagOptimisticBases().filter(function(base) {
|
||||
return knowledgeRagBaseProviderKbId(base) !== selected;
|
||||
});
|
||||
pageUiState.knowledgeRagSelectedProviderKnowledgeBaseId = 'lightrag-default';
|
||||
setKnowledgeRagCreateStatus('已删除资料库', 'done');
|
||||
await loadKnowledgeRagStatus(true, { reason: 'delete-kb', notifyUpdated: true });
|
||||
renderKnowledgeRagSettings();
|
||||
notifyKnowledgeRagSourceUpdated({ action: 'delete-kb', result: payload, providerKnowledgeBaseId: selected });
|
||||
} catch (error) {
|
||||
setKnowledgeRagCreateStatus(error instanceof Error ? error.message : String(error), 'failed');
|
||||
}
|
||||
}
|
||||
|
||||
async function createKnowledgeRagKnowledgeBase() {
|
||||
if (!knowledgeRagIsAvailable()) return;
|
||||
var popover = ensureKnowledgeRagSettingsPopover();
|
||||
@@ -2259,7 +2449,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
var description = descriptionInput instanceof HTMLInputElement ? descriptionInput.value.trim() : '';
|
||||
if (!name) {
|
||||
if (statusNode instanceof HTMLElement) {
|
||||
statusNode.textContent = '请填写 KB 名称';
|
||||
statusNode.textContent = '请填写资料库名称';
|
||||
statusNode.setAttribute('data-status', 'failed');
|
||||
statusNode.hidden = false;
|
||||
}
|
||||
@@ -2308,6 +2498,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
statusNode.setAttribute('data-status', 'done');
|
||||
statusNode.hidden = false;
|
||||
}
|
||||
setKnowledgeRagCreateCardVisible(false);
|
||||
await loadKnowledgeRagStatus(true, { reason: 'create-kb', notifyUpdated: true });
|
||||
if (providerKnowledgeBaseId) {
|
||||
pageUiState.knowledgeRagSelectedProviderKnowledgeBaseId = providerKnowledgeBaseId;
|
||||
@@ -2385,6 +2576,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
setKnowledgeRagInputStatuses(done, 'done');
|
||||
await loadKnowledgeRagStatus(true);
|
||||
resetKnowledgeRagSourceInputs();
|
||||
setKnowledgeRagSourceComposerVisible(false);
|
||||
notifyKnowledgeRagSourceUpdated({ action: 'ingest', sources: sources, result: payload });
|
||||
scheduleKnowledgeRagStatusBridge('ingest');
|
||||
} catch (error) {
|
||||
@@ -2590,10 +2782,10 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
if (!input || !resultsEl) return;
|
||||
var query = (input.value || '').trim();
|
||||
if (!query) {
|
||||
resultsEl.innerHTML = '<span class="mnote-extensions-error">请输入检索关键词</span>';
|
||||
resultsEl.innerHTML = '<div class="mnote-kb-search-empty">请输入检索关键词</div>';
|
||||
return;
|
||||
}
|
||||
resultsEl.innerHTML = '<span class="mnote-extensions-loading">检索中...</span>';
|
||||
resultsEl.innerHTML = '<div class="mnote-kb-search-empty">检索中...</div>';
|
||||
try {
|
||||
var params = new URLSearchParams();
|
||||
params.set('query', query);
|
||||
@@ -2623,7 +2815,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
? data.results
|
||||
: (Array.isArray(data.references) ? data.references : (Array.isArray(data) ? data : []));
|
||||
if (!results.length) {
|
||||
resultsEl.innerHTML = '<div class="mnote-extensions-item"><span>未找到匹配结果</span></div>';
|
||||
resultsEl.innerHTML = '<div class="mnote-kb-search-empty">未找到匹配结果</div>';
|
||||
return;
|
||||
}
|
||||
var html = '';
|
||||
@@ -2640,7 +2832,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
html += '<div class="mnote-kb-search-result-item" data-kb-rag-search-result="true" data-knowledge-rag-provider="' + escapeHtml(knowledgeRagProviderName(currentKnowledgeRagSummary().status || {})) + '" data-knowledge-rag-kb-id="' + escapeHtml(providerKnowledgeBaseId) + '" data-knowledge-rag-knowledge-id="' + escapeHtml(providerKnowledgeId) + '" data-knowledge-rag-chunk-id="' + escapeHtml(providerChunkId) + '" data-knowledge-rag-source-path="' + escapeHtml(String(source)) + '">' +
|
||||
'<div class="mnote-kb-search-result-header">' +
|
||||
'<span class="mnote-kb-search-result-index">#' + (i + 1) + '</span>' +
|
||||
'<span class="mnote-kb-search-result-score" data-kb-rag-score-label="provider-ranking-score" data-kb-rag-score-is-similarity-percent="false">provider 排序分: ' + score + '</span>' +
|
||||
'<span class="mnote-kb-search-result-score" data-kb-rag-score-label="relevance" data-kb-rag-score-is-similarity-percent="false">相关度 ' + score + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-kb-search-result-source">' + escapeHtml(String(source)) + '</div>' +
|
||||
'<div class="mnote-kb-search-result-preview">' + escapeHtml(preview) + (content.length > 200 ? '...' : '') + '</div>' +
|
||||
@@ -2650,7 +2842,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
});
|
||||
resultsEl.innerHTML = html;
|
||||
} catch (err) {
|
||||
resultsEl.innerHTML = '<div class="mnote-extensions-item"><span class="mnote-extensions-error">检索失败: ' + escapeHtml(String(err.message || err)) + '</span></div>';
|
||||
resultsEl.innerHTML = '<div class="mnote-kb-search-empty is-error">检索失败:' + escapeHtml(String(err.message || err)) + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3312,6 +3504,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
loadKnowledgeRagStatus,
|
||||
openKnowledgeRagDashboard,
|
||||
createKnowledgeRagKnowledgeBase,
|
||||
deleteKnowledgeRagKnowledgeBase,
|
||||
loadKnowledgeRagSearchParamsToForm,
|
||||
performKnowledgeRagSearch,
|
||||
saveKnowledgeRagSearchParams,
|
||||
@@ -3323,6 +3516,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
setKnowledgeRagSelectedProviderKnowledgeBaseId,
|
||||
setKnowledgeRagSourceFilter,
|
||||
useKnowledgeRagFileTreeSelection,
|
||||
toggleKnowledgeRagCreateCard,
|
||||
togglePageSettingsPopover,
|
||||
updatePageSettingsTriggerState,
|
||||
writeGlobalShowHeadingNumbers,
|
||||
|
||||
Reference in New Issue
Block a user