feat: add HoloLake folder import and official assistant

This commit is contained in:
冰朔 2026-08-08 11:15:34 +08:00
commit a360982a9b
12 changed files with 507 additions and 76 deletions

View file

@ -18,6 +18,8 @@ export default function App() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [agentPanelOpen, setAgentPanelOpen] = useState(true);
const [importing, setImporting] = useState(false);
const [importMessage, setImportMessage] = useState<string | null>(null);
const refreshTree = useCallback(async () => {
try {
@ -85,6 +87,38 @@ export default function App() {
}
}, [currentPath, refreshTree]);
const importFolder = useCallback(async () => {
const bridge = (window as any).hololake?.knowledge;
if (!bridge?.importFolder) {
setError('本地文件夹导入只在 HoloLake 桌面 App 中提供');
return;
}
setImporting(true);
setError(null);
setImportMessage(null);
try {
const result = await bridge.importFolder();
if (result.cancelled) return;
if (!result.imported) {
setImportMessage(`没有找到可导入的文档;已跳过 ${result.skipped || 0} 个文件`);
return;
}
await refreshTree();
if (result.firstDocument) await openDoc(result.firstDocument);
const details = [
`已导入 ${result.imported} 篇文档`,
result.assets ? `${result.assets} 个图片资源` : '',
result.skipped ? `跳过 ${result.skipped} 个暂不支持的文件` : '',
result.failed?.length ? `${result.failed.length} 个文件失败` : '',
].filter(Boolean).join(' · ');
setImportMessage(details);
} catch (err: any) {
setError(`导入失败: ${err.message}`);
} finally {
setImporting(false);
}
}, [openDoc, refreshTree]);
useEffect(() => {
refreshTree();
}, [refreshTree]);
@ -101,7 +135,11 @@ export default function App() {
>
{sidebarOpen ? '◀' : '▶'}
</button>
<h1 className="kb-title"></h1>
<div className="kb-brand-mark" aria-hidden="true" />
<div>
<h1 className="kb-title">HoloLake</h1>
<div className="kb-subtitle"></div>
</div>
</div>
<div className="kb-header-center">
<SearchBar onSelect={openDoc} />
@ -131,7 +169,7 @@ export default function App() {
onClick={() => setAgentPanelOpen(!agentPanelOpen)}
title={agentPanelOpen ? '收起 Agent' : '展开 Agent'}
>
🌊 Agent
HoloLake
</button>
</div>
</header>
@ -141,11 +179,18 @@ export default function App() {
{/* 侧栏 */}
{sidebarOpen && (
<aside className="kb-sidebar">
<div className="kb-workspace-label"></div>
<div className="kb-sidebar-actions">
<button className="kb-btn-small" onClick={() => createDoc('')}>
+
<button className="kb-btn-import" onClick={importFolder} disabled={importing}>
<span className="kb-btn-import-icon"></span>
{importing ? '正在导入…' : '导入本地文件夹'}
</button>
<button className="kb-btn-new" onClick={() => createDoc('')}>
<span></span>
</button>
</div>
{importMessage && <div className="kb-import-message">{importMessage}</div>}
<div className="kb-tree-heading"></div>
<DocTree
nodes={tree}
currentPath={currentPath}
@ -166,9 +211,16 @@ export default function App() {
{loading && <div className="kb-loading">...</div>}
{!currentDoc && !loading && (
<div className="kb-empty">
<div className="kb-empty-icon">📖</div>
<p></p>
<p className="kb-empty-hint">+ </p>
<div className="kb-empty-card">
<div className="kb-empty-orbit"><span /></div>
<p className="kb-empty-eyebrow">HOLOLAKE KNOWLEDGE</p>
<h2></h2>
<p>HoloLake Git </p>
<button className="kb-empty-primary" onClick={importFolder} disabled={importing}>
{importing ? '正在导入…' : '选择本地文件夹'}
</button>
<div className="kb-empty-support"> MarkdownTXTCSVJSON YAML</div>
</div>
</div>
)}
{currentDoc && view === 'editor' && (