M0-M11 狩夜人笔记初始实现:11里程碑+86测试
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { useState } from 'react';
|
||||
import { useStore } from '../../store';
|
||||
import { invoke } from '../../ipc-client';
|
||||
import { IPC } from '@hunter/shared';
|
||||
import type { TreeNode } from '@hunter/shared';
|
||||
|
||||
export function DocInfoPanel() {
|
||||
const { currentPath, title, meta, tree, toggleStar, addTag, removeTag, addLink, removeLink } = useStore();
|
||||
const [tagInput, setTagInput] = useState('');
|
||||
const [linkInput, setLinkInput] = useState('');
|
||||
|
||||
if (!currentPath) {
|
||||
return <div style={{ padding: 16, opacity: 0.5, fontSize: 13 }}>未打开文档</div>;
|
||||
}
|
||||
|
||||
// 库内 .md 文件供关联链接选择
|
||||
const docs = tree.filter(n => n.type === 'doc');
|
||||
const mtime = tree.find(n => n.path === currentPath)?.mtime;
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16, overflow: 'auto', fontSize: 13 }}>
|
||||
<div style={{ marginBottom: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<strong>{title}</strong>
|
||||
<button onClick={() => toggleStar()} title="星标" style={{ cursor: 'pointer', background: 'none', border: 'none', fontSize: 16, color: meta.star ? '#ffd54a' : '#888' }}>
|
||||
{meta.star ? '★' : '☆'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Section title="路径">
|
||||
<div style={{ opacity: 0.6, wordBreak: 'break-all' }}>{currentPath}</div>
|
||||
</Section>
|
||||
|
||||
<Section title="标签">
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginBottom: 6 }}>
|
||||
{(meta.tags ?? []).map(t => (
|
||||
<span key={t} style={{ background: '#2a2a3a', borderRadius: 4, padding: '2px 8px', display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
{t}<span style={{ cursor: 'pointer', opacity: 0.6 }} onClick={() => removeTag(t)}>×</span>
|
||||
</span>
|
||||
))}
|
||||
{(meta.tags ?? []).length === 0 && <span style={{ opacity: 0.4 }}>无标签</span>}
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 4 }}>
|
||||
<input value={tagInput} onChange={e => setTagInput(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && tagInput.trim()) { addTag(tagInput.trim()); setTagInput(''); } }} placeholder="添加标签" style={inp} />
|
||||
<button style={btn} onClick={() => { if (tagInput.trim()) { addTag(tagInput.trim()); setTagInput(''); } }}>+</button>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="关联文档">
|
||||
<div style={{ marginBottom: 6 }}>
|
||||
{(meta.links ?? []).map(l => (
|
||||
<div key={l} style={{ display: 'flex', justifyContent: 'space-between', padding: '2px 0' }}>
|
||||
<span style={{ opacity: 0.8 }}>{l}</span>
|
||||
<span style={{ cursor: 'pointer', opacity: 0.6 }} onClick={() => removeLink(l)}>×</span>
|
||||
</div>
|
||||
))}
|
||||
{(meta.links ?? []).length === 0 && <span style={{ opacity: 0.4 }}>无关联</span>}
|
||||
</div>
|
||||
<select value={linkInput} onChange={e => setLinkInput(e.target.value)} style={inp}>
|
||||
<option value="">选择库内文档…</option>
|
||||
{docs.filter(d => d.path !== currentPath && !(meta.links ?? []).includes(d.path + '')).map(d => (
|
||||
<option key={d.path} value={d.path}>{d.name}({d.path})</option>
|
||||
))}
|
||||
</select>
|
||||
<button style={{ ...btn, marginLeft: 4 }} onClick={() => { if (linkInput) { addLink(linkInput); setLinkInput(''); } }}>关联</button>
|
||||
</Section>
|
||||
|
||||
<Section title="修改时间">
|
||||
<div style={{ opacity: 0.6 }}>{mtime ? new Date(mtime).toLocaleString('zh-CN') : '—'}</div>
|
||||
<div style={{ opacity: 0.4, fontSize: 12, marginTop: 4 }}>创建时间:—(按设计不落盘)</div>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
||||
return (<div style={{ marginBottom: 16 }}><div style={{ opacity: 0.5, marginBottom: 6 }}>{title}</div>{children}</div>);
|
||||
}
|
||||
const inp: React.CSSProperties = { background: '#222', border: '1px solid #444', color: '#ddd', borderRadius: 4, padding: '3px 8px', fontSize: 13, flex: 1 };
|
||||
const btn: React.CSSProperties = { minWidth: 28, height: 26, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4 };
|
||||
Reference in New Issue
Block a user