本文面向参与 client/ 独立客户端开发的成员,目标是快速理解架构边界、目录职责和统一开发风格。
frontend/ 样式。cd client
npm install
npm run dev
npm run build
npm audit
client/ 是独立桌面客户端,不依赖旧 frontend/ 和 backend/ 源码。window.yibiao 调用 preload 暴露的安全桥接 API。localStorage 保存大文本或业务流程状态。client/
├── electron/ # Electron Main / Preload / IPC / Node 服务
│ ├── ipc/ # IPC 通道注册,只做参数转发
│ ├── services/ # 本地配置、AI、文件、导出服务
│ └── utils/ # Main 侧工具函数
├── src/
│ ├── app/ # 应用级路由、菜单、Provider
│ ├── components/ # 应用布局组件,例如 AppShell、Sidebar
│ ├── features/ # 业务功能模块
│ ├── shared/ # 跨功能共享能力
│ ├── main.tsx # Renderer 入口
│ └── styles.css # 全局样式
└── assets/ # 客户端图标和静态资源
src/app/menuConfig.ts:左侧菜单配置,新增一级功能优先改这里。src/app/AppRouter.tsx:根据 SectionId 渲染对应页面。src/app/providers/AppProviders.tsx:全局 Provider 入口,后续接状态管理或主题时从这里加。新增主菜单页面时,按以下顺序修改:
src/shared/types/navigation.ts 增加 SectionId。src/app/menuConfig.ts 增加菜单项。src/app/AppRouter.tsx 增加页面分支。FloatingToolbar。每个业务功能放在 src/features/<feature-name>/ 下:
features/<feature-name>/
├── pages/ # 页面级组件
├── components/ # 本功能专用组件
├── hooks/ # 本功能专用 Hook
├── services/ # 本功能流程编排
└── types.ts # 本功能专用类型
当前功能模块:
technical-plan:技术方案,流程统一为上传招标文件、招标文件解析、目录生成、正文生成、扩写改写。knowledge-base:知识库。duplicate-check:标书查重。rejection-check:废标项检查。settings:独立设置页,由侧栏底部入口进入,管理文本模型、生图模型、文件解析和关于信息。Feature 开发规则:
services/ 进入,再调用 shared/ai。shared/prompts/,不要散落在组件里。shared/types/,仅本功能使用的类型放本功能 types.ts。FloatingToolbar 控制,未满足前置条件时禁用“下一步”,不要在步骤页面主体里重复放同语义下一步按钮。FloatingToolbar,不要在各配置卡片底部重复放保存按钮。保存。src/shared/ 放跨功能复用能力:
shared/ai/aiClient.ts:Renderer 侧 AI 请求门面。shared/ai/stream.ts:流式文本收集工具。shared/prompts/:Prompt builder。shared/storage/:仅保留轻量 Renderer 缓存工具;业务工作区数据优先走 Electron Main 侧存储。shared/types/:跨功能共享类型。shared/ui/:跨功能通用 UI,例如 FloatingToolbar。shared/utils/:错误、JSON、ID 等通用工具。共享层规则:
interface,联合类型和泛型工具类型用 type。electron/ 只使用 CommonJS,保持与 Electron 当前入口一致。
electron/preload.cjs 暴露:
window.yibiao.config.load() // 返回 ClientConfig
window.yibiao.config.save(config) // 保存 ClientConfig
window.yibiao.config.listModels()
window.yibiao.ai.chat(request)
window.yibiao.ai.requestJson(request)
window.yibiao.ai.testImageModel(config)
window.yibiao.file.importDocument()
window.yibiao.workspace.loadTechnicalPlan()
window.yibiao.workspace.saveTechnicalPlan(state)
window.yibiao.workspace.clearTechnicalPlan()
window.yibiao.tasks.startBidAnalysis(payload)
window.yibiao.tasks.startOutlineGeneration(payload)
window.yibiao.tasks.startContentGeneration(payload)
window.yibiao.tasks.getActiveTasks()
window.yibiao.tasks.onTaskEvent(callback)
window.yibiao.export.exportWord(payload)
electron/ipc/*.cjs 只注册通道,不写业务逻辑。
命名规则:
config:*ai:*file:*workspace:*tasks:*export:*electron/services/*.cjs 承载 Main 侧业务:
configStore.cjs:配置读写,路径位于 Electron userData,包含文本模型、生图模型和文件解析配置。aiService.cjs:文本模型请求、生图模型测试、正文配图生图等 AI 能力封装。fileService.cjs:文档导入与解析,按配置选择本地或 MinerU 解析方式;新的文件上传/转换入口必须复用这里的 parseDocumentWithConfig()。workspaceStore.cjs:工作区业务数据缓存,例如技术方案流程状态和招标文件内容。taskService.cjs:后台长任务管理,负责招标文件解析、目录生成、正文生成等跨页面任务的状态推送和结果落盘。exportService.cjs:Word 导出,包含 Markdown 到 Word、图片插入、Mermaid 转图片和导出进度上报。updateService.cjs:打包应用启动后的 GitHub Release 更新检查、下载和重启安装提示。Main 层规则:
fs、path、ipcRenderer 原始对象。configStore 读取配置后选择。doc2markdown/convert.mjs 或自行拼接 MinerU 请求;统一在 Main 侧调用 electron/services/fileService.cjs 的 parseDocumentWithConfig(app, filePath, config, { assetScope })。parseDocumentWithConfig() 会统一处理本地解析、MinerU Agent、MinerU Accurate、MinerU 不支持格式自动切回本地解析、设置页“保留图片”和图片资产落盘。业务代码只负责选择文件、保存业务状态和传入稳定的 assetScope。assetScope 必须能对应到业务资源,例如技术方案使用 technical-plan,知识库文档使用 knowledge-${documentId}。后续新功能应使用 <feature>-<resourceId> 这类可定位前缀,便于删除时清理历史图片。userData/user_config.json,由 configStore.cjs 管理。userData/workspace/,由 workspaceStore.cjs 管理。userData/workspace/technical_plan.json,包含当前步骤、上传文件名、招标文件内容和后续流程中间结果。userData/workspace/generated-images/,正文中通过 yibiao-asset://generated-images/... 引用,不把图片 base64 长期写入 technical_plan.json。userData/workspace/imported-images/<assetScope>-<timestamp>-<random>/,正文中通过 yibiao-asset://imported-images/... 引用,不把图片 base64 长期写入业务 JSON。electron/utils/importedImages.cjs 的 deleteImportedImageBatches(app, assetScopePrefix) 清理对应历史图片目录,避免用户长期使用后磁盘被遗留图片占满。parseDocumentWithConfig() 会清理本次新建图片批次;业务删除、清空、重新导入或删除父级目录时仍必须按 assetScopePrefix 主动清理旧批次。userData/logs/ai/;每次 AI 请求对应一个 JSON 日志文件,包含完整请求参数、响应内容或错误信息。window.yibiao.workspace 读写工作区数据,不直接写文件,也不把招标文件 Markdown、正文草稿等大文本长期放进 localStorage。localStorage 只用于轻量 UI 偏好或临时状态,不作为业务数据的权威来源。window.yibiao.tasks.onTaskEvent()、展示 technical_plan.json 中的任务状态和结果。workspaceStore,确保切换页面后任务不中断,切回来能恢复当前日志、进度和结果。outlineData.outline[*].content 为展示和导出的权威来源,不要另建一套正文存储源。available 时执行;生图失败不应影响已生成正文落盘。mermaid 代码块保存;Renderer 负责前端本地渲染预览,Word 导出时由 Main 通过 mermaid.ink 转图片,并通过 window.yibiao.export.onWordExportProgress() 展示进度和失败提示。content,避免旧正文污染新目录和导出结果。导出 Word 和 继续扩写,不要再显示“下一步”。AI 调用分三层:
shared/prompts 生成 messages,再调 shared/ai/aiClient。aiClient 通过 window.yibiao.ai 调 Electron Main。Prompt 文件约定:
analysisPrompts.ts:招标文件分析。outlinePrompts.ts:目录生成、子目录生成、目录审核。contentPrompts.ts:章节正文生成。expandPrompts.ts:旧方案目录提取。duplicatePrompts.ts:标书查重。rejectionPrompts.ts:废标项检查。jsonRepairPrompts.ts:JSON 修复。当前除 jsonRepairPrompts.ts 外,多数 Prompt builder 是占位实现,后续迁移时参考旧 backend/app/utils/prompts/ 的职责,但不要直接依赖旧文件。
rehypeRaw,避免 HTML 被渲染成真实 DOM。#2174FD、#4098FC、#5B54D3、#f8fafd。FloatingToolbar 等模式,不要另起一套视觉语言。shared/ui,避免每个 feature 各写一套相似实现。command-bar + progress-card + workspace 结构;左侧列表/树、右侧阅读器的交互模式保持一致。FloatingToolbar 是覆盖层,必要内容应由内部滚动区域承载。shared/ui/,业务专用 UI 放 feature 内。components/。shared/ui/ToastProvider 提供的 Toast。alert,不在页面里自建长期占位提示条。通用组件位于 src/shared/ui/FloatingToolbar.tsx。
使用方式:
<FloatingToolbar groups={groups} />
FloatingToolbar,例如技术方案步骤工具条、设置页保存工具条、标书查重处理工具条。padding-bottom 或空白占位;被遮挡的长内容通过内部滚动查看。100vh 高度并隐藏全局溢出,禁止依赖 body 产生页面级滚动条。content-shell 只负责占满主内容区和承载悬浮层,不作为长内容滚动容器。height: 100%、min-height: 0,需要滚动时在页面内部容器上使用 overflow: auto。command-bar + workspace 的网格结构,workspace 占据剩余高度,左右面板分别内部滚动。electron-builder 打包,配置位于 client/package.json 的 build 字段。.github/workflows/release.yml,推送 v* tag 时触发,例如 v0.1.1;也支持手动执行 workflow 并输入已有 tag。git log 显式生成,避免 GitHub 原生自动说明只显示 Full Changelog。windows-latest 构建,产物包含 NSIS 安装包和 zip;macOS 在 macos-latest 构建,产物包含 dmg 和 zip。assets/icon.ico,必须允许 electron-builder 编辑 exe 资源;macOS 图标由 workflow 使用 assets/icon_256.png 临时生成 assets/icon.icns 后打包。v0.1.1 会临时执行 npm version 0.1.1 --no-git-tag-version --allow-same-version 后再打包。electron-builder --publish never 只负责构建,再通过 gh release upload 显式上传安装包、zip/dmg、blockmap 和 latest*.yml 更新元数据。electron-updater 负责,只在 app.isPackaged 的打包应用中启用;npm run dev 开发调试模式不会检查或下载更新。本地 Windows 打包验证可运行:
cd client
npm run dist:win
本地 macOS 打包需在 macOS 环境运行:
cd client
npm run dist:mac
发布新版本的基本流程:
git tag v0.1.1
git push origin v0.1.1
如果某个 tag 的 Release 已经创建但缺少产物,可以在 GitHub Actions 页面手动运行 Release Client,输入该 tag 重新生成说明并上传产物。
frontend/ 或 backend/ 的源码路径。parseDocumentWithConfig(),并在删除对应业务资源时复用 deleteImportedImageBatches() 清理导入图片资产。*Page.tsx,服务 *Service.ts 或 *Workflow.ts,Hook 以 use 开头。每次改动至少运行:
npm run build
涉及依赖变更时额外运行:
npm audit
涉及 Electron Main 或 preload 时,需要手动运行:
npm run dev
检查窗口是否正常打开、控制台是否有错误、window.yibiao 是否存在。