diff --git a/apps/desktop/src/renderer/features/appearance/AppearancePanel.tsx b/apps/desktop/src/renderer/features/appearance/AppearancePanel.tsx index 62c567f..5294c7b 100644 --- a/apps/desktop/src/renderer/features/appearance/AppearancePanel.tsx +++ b/apps/desktop/src/renderer/features/appearance/AppearancePanel.tsx @@ -12,19 +12,19 @@ export function AppearancePanel({ onClose }: { onClose: () => void }) { const colors: [keyof typeof draft, string][] = [['accent','强调色'],['glow','辉光色'],['accentText','强调色文字'],['textPrimary','主要文字'],['textSecondary','辅助文字'],['textTertiary','弱化文字'],['controlBorder','控件边框'],['bgPrimary','工作区背景'],['bgSecondary','浮层背景']]; return (
{ if (e.target === e.currentTarget) { revert(); onClose(); } }} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1500 }}> -
+
外观定制
- +
{isDirty() ? '更改尚未保存' : '所有设置已保存'}
主题
{THEMES.map((t: ThemeDef) => ( -
selectTheme(t.id)} style={{ cursor: 'pointer', padding: 8, borderRadius: 6, border: themeId === t.id ? '2px solid #4a9eff' : '1px solid #3a3a4a', background: t.params.bgPrimary, color: t.params.textPrimary, fontSize: 11, minHeight: 48, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}> +
selectTheme(t.id)} style={{ cursor: 'pointer', padding: 8, borderRadius: 6, border: themeId === t.id ? '2px solid var(--accent)' : '1px solid var(--control-border)', background: t.params.bgPrimary, color: t.params.textPrimary, fontSize: 11, minHeight: 48, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
{t.name}
{t.desc}
))} @@ -43,13 +43,13 @@ export function AppearancePanel({ onClose }: { onClose: () => void }) {
{ const f = e.target.files?.[0]; if (f) compressImage(f).then(d => setBgImage(d)); e.target.value = ''; }} /> - {bgImage && <>bg} - {!bgImage && 未设置} + {bgImage && <>bg} + {!bgImage && 未设置}
鼠标特效
{EFFECTS.map(([t, label]) => ( - + ))}
@@ -73,4 +73,4 @@ function normalizeColor(c: string): string { if (c === 'transparent' || c.startsWith('rgba')) return '#1a1a2a'; return c; } -const btn: React.CSSProperties = { padding: '6px 14px', border: '1px solid #3a3a4a', background: 'transparent', color: '#aaa', borderRadius: 4, cursor: 'pointer', fontSize: 13 }; +const btn: React.CSSProperties = { padding: '6px 14px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-secondary)', borderRadius: 4, cursor: 'pointer', fontSize: 13 }; \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/dialog/InputDialog.tsx b/apps/desktop/src/renderer/features/dialog/InputDialog.tsx index 6cc25a1..180b5fa 100644 --- a/apps/desktop/src/renderer/features/dialog/InputDialog.tsx +++ b/apps/desktop/src/renderer/features/dialog/InputDialog.tsx @@ -16,21 +16,21 @@ export function InputDialog() { return (
{ if (e.target === e.currentTarget) close(null); }} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000 }}> -
-
{title}
+
+
{title}
{mode === 'confirm' ? (
{message}
) : ( setValue(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') submit(); if (e.key === 'Escape') close(null); }} - placeholder={placeholder} style={{ width: '100%', background: '#15151f', border: '1px solid #3a3a4a', color: '#ddd', borderRadius: 4, padding: '8px 12px', fontSize: 14, outline: 'none' }} /> + placeholder={placeholder} style={{ width: '100%', background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '8px 12px', fontSize: 14, outline: 'none' }} /> )}
- +
); } -const btn: React.CSSProperties = { padding: '6px 16px', border: '1px solid #3a3a4a', background: 'transparent', color: '#aaa', borderRadius: 4, cursor: 'pointer', fontSize: 13 }; +const btn: React.CSSProperties = { padding: '6px 16px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-secondary)', borderRadius: 4, cursor: 'pointer', fontSize: 13 }; \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx b/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx index 77203a1..9b2c100 100644 --- a/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx +++ b/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx @@ -1,6 +1,6 @@ import { useNotify } from './notify-store'; export function NotifyLayer() { const { items, remove } = useNotify(); return
{items.map(n => ( -
remove(n.id)} style={{ padding: '10px 16px', borderRadius: 6, fontSize: 13, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.3)', background: n.type === 'success' ? '#2a4a3a' : n.type === 'error' ? '#4a2a2a' : '#2a2a3a', color: n.type === 'success' ? '#9fc' : n.type === 'error' ? '#f88' : '#9cf' }}>{n.msg}
+
remove(n.id)} style={{ padding: '10px 16px', borderRadius: 6, fontSize: 13, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.3)', background: n.type === 'success' ? '#2a4a3a' : n.type === 'error' ? '#4a2a2a' : 'var(--control-border)', color: n.type === 'success' ? '#9fc' : n.type === 'error' ? '#f88' : 'var(--accent-text)' }}>{n.msg}
))}
; -} +} \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx b/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx index e361217..f6c9263 100644 --- a/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx +++ b/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx @@ -21,7 +21,7 @@ export function DocInfoPanel() {
{title} -
@@ -33,7 +33,7 @@ export function DocInfoPanel() {
{(meta.tags ?? []).map(t => ( - + {t} removeTag(t)}>× ))} @@ -75,5 +75,5 @@ export function DocInfoPanel() { function Section({ title, children }: { title: string; children: React.ReactNode }) { return (
{title}
{children}
); } -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 }; +const inp: React.CSSProperties = { background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', fontSize: 13, flex: 1 }; +const btn: React.CSSProperties = { minWidth: 28, height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4 }; \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx b/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx index 08e65f5..f6b56b8 100644 --- a/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx +++ b/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx @@ -29,12 +29,12 @@ export function CodeBlockView({ node, updateAttributes, selected }: NodeViewProp const language = (node.attrs.language as string) || ''; const codeClass = language ? `language-${language} hljs` : 'hljs'; return ( - -
+ +
@@ -44,4 +44,4 @@ export function CodeBlockView({ node, updateAttributes, selected }: NodeViewProp ); -} +} \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/Editor.tsx b/apps/desktop/src/renderer/features/editor/Editor.tsx index 0e822d3..42c35d7 100644 --- a/apps/desktop/src/renderer/features/editor/Editor.tsx +++ b/apps/desktop/src/renderer/features/editor/Editor.tsx @@ -20,7 +20,7 @@ export function Editor() { } return (
-
+
{title} {currentPath}
{saveLabel(saveState)} diff --git a/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx b/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx index 51d8306..ac08a88 100644 --- a/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx +++ b/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx @@ -5,7 +5,7 @@ import { useDialog } from '../dialog/dialog-store'; import { invoke } from '../../ipc-client'; import { IPC } from '@hunter/shared'; -const btn: React.CSSProperties = { minWidth: 30, height: 28, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 13 }; +const btn: React.CSSProperties = { minWidth: 30, height: 28, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 13 }; function T({ onClick, title, children, disabled }: { onClick: () => void; title: string; children: React.ReactNode; disabled?: boolean }) { return ; @@ -35,29 +35,29 @@ export function EditorToolbar() { editor.chain().focus().setImage({ src: url }).run(); }; return ( -
+
e.chain().focus().undo().run())} disabled={d}>↶ e.chain().focus().redo().run())} disabled={d}>↷ - + e.chain().focus().toggleBold().run())} disabled={d}>B e.chain().focus().toggleItalic().run())} disabled={d}>I e.chain().focus().toggleStrike().run())} disabled={d}>S e.chain().focus().toggleCode().run())} disabled={d}>code e.chain().focus().unsetAllMarks().run())} disabled={d}>T× e.chain().focus().toggleBlockquote().run())} disabled={d}>❝ - + e.chain().focus().toggleHeading({ level: 1 }).run())} disabled={d}>H1 e.chain().focus().toggleHeading({ level: 2 }).run())} disabled={d}>H2 e.chain().focus().toggleHeading({ level: 3 }).run())} disabled={d}>H3 - + e.chain().focus().toggleBulletList().run())} disabled={d}>• e.chain().focus().toggleOrderedList().run())} disabled={d}>1. e.chain().focus().toggleCodeBlock().run())} disabled={d}>{''} e.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run())} disabled={d}>▦ - + { void link(); }} disabled={d}>链接 { void pickImage(); }} disabled={d}>图片 { void imageUrl(); }} disabled={d}>网图
); -} +} \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/FindReplace.tsx b/apps/desktop/src/renderer/features/editor/FindReplace.tsx index 7317966..1108245 100644 --- a/apps/desktop/src/renderer/features/editor/FindReplace.tsx +++ b/apps/desktop/src/renderer/features/editor/FindReplace.tsx @@ -80,7 +80,7 @@ export function FindReplace() { }; return ( -
+
setFind(e.target.value)} placeholder="查找" onKeyDown={e => e.key === 'Enter' && doFind()} style={inp} /> setReplace(e.target.value)} placeholder="替换" style={inp} /> @@ -95,6 +95,6 @@ export function FindReplace() {
); } -const inp: React.CSSProperties = { background: '#222', border: '1px solid #444', color: '#ddd', borderRadius: 4, padding: '3px 8px', width: 110, fontSize: 13 }; -const btn: React.CSSProperties = { minWidth: 30, height: 26, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 12 }; -const lab: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 3, fontSize: 12, color: '#aaa', cursor: 'pointer' }; +const inp: React.CSSProperties = { background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', width: 110, fontSize: 13 }; +const btn: React.CSSProperties = { minWidth: 30, height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 12 }; +const lab: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 3, fontSize: 12, color: 'var(--text-secondary)', cursor: 'pointer' }; \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx b/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx index 4ec265c..fef287a 100644 --- a/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx +++ b/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx @@ -17,12 +17,12 @@ export function LinkBubbleMenu({ editor }: { editor: Editor }) { const remove = () => editor.chain().focus().extendMarkRange('link').unsetLink().run(); return ( editor.isActive('link')} className="link-bubble" - style={{ display: 'flex', gap: 4, alignItems: 'center', background: '#1e1e2a', border: '1px solid #3a3a4a', borderRadius: 6, padding: 4, boxShadow: '0 4px 16px rgba(0,0,0,0.4)' }}> + style={{ display: 'flex', gap: 4, alignItems: 'center', background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', borderRadius: 6, padding: 4, boxShadow: '0 4px 16px rgba(0,0,0,0.4)' }}> setHref(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); apply(); } }} - placeholder="链接地址" style={{ width: 180, background: '#15151f', border: '1px solid #3a3a4a', color: '#ddd', borderRadius: 4, padding: '3px 8px', fontSize: 13, outline: 'none' }} /> + placeholder="链接地址" style={{ width: 180, background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', fontSize: 13, outline: 'none' }} /> ); } -const btn: React.CSSProperties = { padding: '3px 10px', border: '1px solid #3a3a4a', background: 'transparent', color: '#ccc', borderRadius: 4, cursor: 'pointer', fontSize: 12 }; +const btn: React.CSSProperties = { padding: '3px 10px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', borderRadius: 4, cursor: 'pointer', fontSize: 12 }; \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/MathBlock.tsx b/apps/desktop/src/renderer/features/editor/MathBlock.tsx index e9fa531..e21aa3a 100644 --- a/apps/desktop/src/renderer/features/editor/MathBlock.tsx +++ b/apps/desktop/src/renderer/features/editor/MathBlock.tsx @@ -19,9 +19,9 @@ const MathBlockView = (props: NodeViewProps) => { const tex = props.node.textContent; const html = renderLatex(tex, true); return ( - +
- + ); }; @@ -82,4 +82,4 @@ export const InlineMath = Node.create({ insertInlineMath: (tex: string) => ({ chain }: { chain: () => any }) => chain().insertContent({ type: 'inlineMath', attrs: { tex } }).run(), } as any; }, -}); +}); \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/MoreActions.tsx b/apps/desktop/src/renderer/features/editor/MoreActions.tsx index 631c296..b93cd4c 100644 --- a/apps/desktop/src/renderer/features/editor/MoreActions.tsx +++ b/apps/desktop/src/renderer/features/editor/MoreActions.tsx @@ -15,7 +15,7 @@ export function MoreActions() {
{open && ( -
+
复制 Markdown 打印 / 另存为 PDF 在文件管理器中显示 @@ -26,7 +26,7 @@ export function MoreActions() { ); } function Item({ children, onClick }: { children: React.ReactNode; onClick: () => void }) { - return
(e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
; + return
(e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
; } -const btn: React.CSSProperties = { height: 26, border: '1px solid #3a3a4a', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 14, padding: '0 8px' }; -function notify(msg: string) { const el = document.createElement('div'); el.textContent = msg; el.style.cssText = 'position:fixed;top:50px;right:20px;background:#2a4a6a;color:#9cf;padding:10px 16px;border-radius:6px;z-index:3000;font-size:13px'; document.body.appendChild(el); setTimeout(() => el.remove(), 2500); } +const btn: React.CSSProperties = { height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 14, padding: '0 8px' }; +function notify(msg: string) { const el = document.createElement('div'); el.textContent = msg; el.style.cssText = 'position:fixed;top:50px;right:20px;background:var(--accent);color:var(--accent-text);padding:10px 16px;border-radius:6px;z-index:3000;font-size:13px'; document.body.appendChild(el); setTimeout(() => el.remove(), 2500); } \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/editor/SlashMenu.tsx b/apps/desktop/src/renderer/features/editor/SlashMenu.tsx index cc43324..e4e8280 100644 --- a/apps/desktop/src/renderer/features/editor/SlashMenu.tsx +++ b/apps/desktop/src/renderer/features/editor/SlashMenu.tsx @@ -50,9 +50,9 @@ export function SlashMenu() { setOpen(false); }; return ( -
+
{items.length === 0 &&
无匹配
} - {items.map(it =>
pick(it)} style={{ padding: '6px 10px', cursor: 'pointer', borderRadius: 4, fontSize: 13 }} onMouseEnter={e => (e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{it.label}
)} + {items.map(it =>
pick(it)} style={{ padding: '6px 10px', cursor: 'pointer', borderRadius: 4, fontSize: 13 }} onMouseEnter={e => (e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{it.label}
)}
); -} +} \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/file-tree/FileTree.tsx b/apps/desktop/src/renderer/features/file-tree/FileTree.tsx index 4e806ab..5d69deb 100644 --- a/apps/desktop/src/renderer/features/file-tree/FileTree.tsx +++ b/apps/desktop/src/renderer/features/file-tree/FileTree.tsx @@ -73,7 +73,7 @@ export function FileTree() { {isRenaming ? ( setRenameVal(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { setRenaming(null); invoke(IPC.fileRename, { from: n.path, toName: renameVal }).then(r => { useTabs.getState().renamePath(n.path, r.path); syncCurrentPath(n.path, r.path); loadTree(); }); } if (e.key === 'Escape') setRenaming(null); }} - onBlur={() => setRenaming(null)} style={{ flex: 1, background: '#15151f', border: '1px solid #4a6a8a', color: '#ddd', borderRadius: 3, padding: '1px 4px', fontSize: 13 }} /> + onBlur={() => setRenaming(null)} style={{ flex: 1, background: 'var(--bg-secondary)', border: '1px solid #4a6a8a', color: 'var(--text-primary)', borderRadius: 3, padding: '1px 4px', fontSize: 13 }} /> ) : ( {n.name} )} @@ -98,7 +98,7 @@ export function FileTree() { {roots.map(n => renderNode(n, 0))} {tree.length === 0 && !treeLoading &&
空库,点击上方「+ 新建文档」开始
} {menu && menuNode && ( -
e.stopPropagation()}> +
e.stopPropagation()}> {menuNode.type === 'doc' && { openDoc(menuNode.path); setMenu(null); }}>打开} {menuNode.type === 'folder' && <> { doCreate(menuNode.path, false); setMenu(null); }}>新建文档 @@ -111,8 +111,8 @@ export function FileTree() { ); } -const miniBtn: React.CSSProperties = { border: 'none', background: 'transparent', color: '#888', cursor: 'pointer', padding: '0 3px', fontSize: 12 }; +const miniBtn: React.CSSProperties = { border: 'none', background: 'transparent', color: 'var(--text-tertiary)', cursor: 'pointer', padding: '0 3px', fontSize: 12 }; function MenuItem({ children, onClick, danger }: { children: React.ReactNode; onClick: () => void; danger?: boolean }) { - return
(e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
; + return
(e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
; } \ No newline at end of file diff --git a/apps/desktop/src/renderer/features/graph/GraphView.tsx b/apps/desktop/src/renderer/features/graph/GraphView.tsx index 19ad424..5189cc9 100644 --- a/apps/desktop/src/renderer/features/graph/GraphView.tsx +++ b/apps/desktop/src/renderer/features/graph/GraphView.tsx @@ -46,7 +46,7 @@ const MARKMAP_OPTIONS = { const t = node.payload?.type as NodeType | undefined; if (t === 'doc') return '#9aa0aa'; if (t === 'folder') return '#5db0ff'; - return '#4a9eff'; + return 'var(--accent)'; }, }; @@ -92,15 +92,15 @@ function MindmapTree() { }, [tree]); return ( -
+