M0-M11 狩夜人笔记初始实现:11里程碑+86测试

This commit is contained in:
hunter-dev
2026-08-24 20:35:22 +08:00
commit 3ebd33536b
106 changed files with 10490 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
// 文件约定常量
export const MD_EXT = '.md';
export const ATTACHMENTS_DIR = '.attachments';
export const TMP_SUFFIX = '.dsh-tmp';
export const RECENT_VAULT_MAX = 5;
export const SEARCH_RESULT_MAX = 100;
export const DEFAULT_VAULT_NAME = 'notes';
+7
View File
@@ -0,0 +1,7 @@
// @hunter/shared — 主进程与渲染进程共享的类型与常量
export * from './types/ipc.js';
export * from './types/vault.js';
export * from './types/doc.js';
export * from './types/search.js';
export * from './types/graph.js';
export * from './constants.js';
+18
View File
@@ -0,0 +1,18 @@
// 文档元数据白名单(仅 4 个业务字段)
export interface DocMeta {
title?: string;
tags?: string[];
star?: boolean;
links?: string[];
}
export interface ReadDocResult {
meta: DocMeta;
body: string;
}
export interface WriteDocPayload {
path: string;
meta: DocMeta;
body: string;
}
+3
View File
@@ -0,0 +1,3 @@
export interface GraphNode { id: string; title: string; basePath: string; star: boolean; group: string; color: string; }
export interface GraphEdge { source: string; target: string; }
export interface GraphData { nodes: GraphNode[]; edges: GraphEdge[]; }
+69
View File
@@ -0,0 +1,69 @@
import type { TreeNode, VaultMeta } from './vault.js';
import type { SearchHit, TagStat } from './search.js';
import type { GraphData } from './graph.js';
import type { DocMeta, ReadDocResult, WriteDocPayload } from './doc.js';
// ===== IPC 通道命名 =====
export const IPC = {
vaultList: 'vault:list',
vaultSwitch: 'vault:switch',
vaultSetDefault: 'vault:set-default',
vaultPick: 'vault:pick',
treeList: 'tree:list',
treeRefresh: 'tree:refresh',
fileCreate: 'file:create',
fileRename: 'file:rename',
fileMove: 'file:move',
fileDelete: 'file:delete',
fileImport: 'file:import',
docRead: 'doc:read',
docWrite: 'doc:write',
docReveal: 'doc:reveal',
search: 'search',
tagStats: 'tag:stats',
graph: 'graph',
winMinimize: 'win:minimize',
winMaximize: 'win:maximize',
winClose: 'win:close',
copyMd: 'doc:copy-md',
printPdf: 'doc:print-pdf',
} as const;
export type IpcChannel = (typeof IPC)[keyof typeof IPC];
// ===== 请求/响应类型映射 =====
export interface IpcMap {
[IPC.vaultList]: { args: void; result: VaultMeta };
[IPC.vaultSwitch]: { args: { root: string }; result: VaultMeta };
[IPC.vaultSetDefault]: { args: { root: string }; result: void };
[IPC.vaultPick]: { args: void; result: VaultMeta | null };
[IPC.treeList]: { args: void; result: TreeNode[] };
[IPC.treeRefresh]: { args: void; result: TreeNode[] };
[IPC.fileCreate]: { args: { basePath: string; name: string; isFolder: boolean }; result: { path: string } };
[IPC.fileRename]: { args: { from: string; toName: string }; result: { path: string } };
[IPC.fileMove]: { args: { src: string; destDir: string }; result: { path: string } };
[IPC.fileDelete]: { args: { path: string; recursive: boolean }; result: void };
[IPC.fileImport]: { args: { sources: string[]; destDir: string }; result: { ok: string[]; failed: { path: string; reason: string }[] } };
[IPC.docRead]: { args: { path: string }; result: ReadDocResult };
[IPC.docWrite]: { args: WriteDocPayload; result: void };
[IPC.docReveal]: { args: { path: string }; result: void };
[IPC.search]: { args: { query: string }; result: SearchHit[] };
[IPC.tagStats]: { args: void; result: TagStat[] };
[IPC.graph]: { args: void; result: GraphData };
[IPC.winMinimize]: { args: void; result: void };
[IPC.winMaximize]: { args: void; result: void };
[IPC.winClose]: { args: void; result: void };
[IPC.copyMd]: { args: { path: string }; result: string };
[IPC.printPdf]: { args: void; result: void };
}
// 类型安全的 invoke 帮助器签名(preload 暴露 + 渲染层使用)
export type Invoke = <K extends keyof IpcMap>(
channel: K,
args: IpcMap[K]['args'],
) => Promise<IpcMap[K]['result']>;
// 渲染层通过 preload 拿到的受限 API
export interface BridgeApi {
invoke: Invoke;
send: <K extends keyof IpcMap>(channel: K, args: IpcMap[K]['args']) => void;
}
+2
View File
@@ -0,0 +1,2 @@
export interface SearchHit { path: string; title: string; snippet: string; }
export interface TagStat { tag: string; count: number; }
+19
View File
@@ -0,0 +1,19 @@
export interface VaultMeta {
currentRoot: string;
recents: string[];
defaultRoot: string;
}
export type TreeNodeType = 'folder' | 'doc';
export interface TreeNode {
/** 相对库根路径,作为稳定 id */
path: string;
type: TreeNodeType;
/** 显示名(doc 去除 .md) */
name: string;
parent: string;
/** doc 的所在目录相对路径;folder 为自身 */
basePath: string;
mtime: number;
}