项目架构与开发约束
更新:2026-08-01
1. 当前边界
客户端只维护一条主链路:
蛋卷数据 → 证据归一化 → SQLite 快照 → 规则/AI 研究
→ 关注/每日信号 → 用户确认的定投计划
定投计划已经接在研究链路之后,没有另建第二套数据采集和研究体系。打开定投页只读 SQLite,不隐式访问蛋卷或 DeepSeek。
2. 代码分层
Main
src/main/data-sources/danjuan/client.ts:HTTP 与响应校验。src/main/data-sources/danjuan/selection.ts:宽基、行业、主题、全球、策略的数据适配与三阶段执行壳。src/main/data-sources/danjuan/radar.ts:估值雷达数据适配与三阶段执行壳;原始证据、逐项 AI 摘要和最终汇总互不隐式触发。src/main/data-sources/danjuan/run-control.ts:批次控制。src/main/storage/research-db.ts:研究快照。src/main/storage/dca-repository.ts:SQLite v6 四级关注度、计划和每日信号;旧关注/排除表仅用于幂等迁移。src/main/dca/dca-service.ts:本地研究转候选、倍率、预算与历史信号。src/main/storage/file-cache.ts:接口缓存。src/main/ai/deepseek.ts:AI 配置、提示和结果解析。src/main/index.ts:窗口与 IPC 组合根。
Shared
src/shared/types.ts:Main、Preload、Renderer 的公共契约。src/shared/index-scoring.ts:指数/基金规则分。src/shared/ai-action-schema.ts:AI 行动协议。src/shared/default-fund-selection.ts:从候选审计结果选择默认研究基金。src/shared/fund-candidate-comparison.ts:合并完整/精选基金池并生成全候选浅层工具分、缺失证据和入选/落选理由;资产规模只使用可解析的scale金额,tot_share作为份额字段保留说明但不参与金额阈值评分。src/shared/research-run-state.ts:两个执行壳实际调用的纯函数领域内核,统一范围、状态分类、续跑、失效与汇总门禁。src/shared/dca-plan.ts:0–6 倍、有效分位、证据上限与计划领域模型。
Renderer
IndexSelectionView.vue:五大类共用研究入口与阶段调度。DanjuanIndexValuationView.vue:估值雷达入口,与分类页使用同一阶段协议。components/index-research/ResearchWorkflowSteps.vue:六个入口共用的三阶段流程与暂停入口。components/index-research/*:共享表格、详情和图表。DcaPlanView.vue、components/dca/*:定投候选、计划、证据链和历史信号。SettingsView.vue:本地配置状态。
3. 已移除的架构分支
- 东方财富数据源与行业/股票估值页面。
- 本地基金筛选和蛋卷在线基金筛选。
- Mock 行业、基金列表和七步详情页。
- 旧低估指数基金研究聚合页。
- 乌龟量化:未发现独立实现。
这些分支不得因旧文档或旧路由再次进入当前主流程。需要恢复时从 Git 创建独立设计任务。
4. 复杂度判断
当前主要复杂度不在页面,而在三个地方:
- 长批次可恢复性:几十个指数涉及多接口和 AI;必须先完成可审查的原始数据检查点,再按人工筛选范围逐项 AI,最后独立汇总,三个阶段都不能互相隐式补跑。
- 证据口径:缺失、0、不可适用、历史不足不能混为一类。
- 状态一致性:同一指数跨大类、估值雷达、关注和定投计划必须使用同一主键和同一最新快照。
不应增加的复杂度:
- 为每个页面复制一套 API 和评分代码。
- 在 Vue 组件里直接请求数据或拼业务规则。
- 同时维护文件缓存、SQLite 和组件状态三套互相矛盾的真相。
- 为未来可能用到的交易、持仓、账户功能提前建完整系统。
5. 架构规则
单一标识
- 指数主键使用规范化
indexCode/symbol。 - 基金主键使用
fundCode。 - 同一指数跨分类只保存一份当日证据,分类关系单独记录。
数据分层
RawEvidence 原始接口证据
NormalizedFacts 归一化事实
RuleResult 确定性评分/倍率
AiAssessment AI 解释与上限
UserPlan 用户确认的计划
ExecutionRecord 用户手工登记的执行
后一层可以引用前一层,不能改写前一层。
缓存与数据库
- HTTP 文件缓存解决重复请求与 304。
- SQLite 是研究状态和 UI 恢复的唯一持久化真相。
- 六个指数入口的原始证据、逐项 AI 摘要与最终汇总是三个独立检查点;刷新证据必须把旧 AI 标记为待更新,后续阶段不得隐式补拉前序数据。
- 原始数据覆盖选定目录内全部一至三级指数,不受名称、状态、结论、动作或分页过滤影响;AI 使用显式筛选范围,汇总必须精确匹配成功摘要范围。
- UI 本地状态只保存筛选、分页、展开和选中项。
- 新表通过幂等迁移增加,不删除旧研究表或用户数据。
IPC
- Preload 只暴露业务动作,例如“读取计划”“刷新指数”“保存关注”。
- Renderer 不接触文件路径、数据库句柄、密钥或任意网络请求。
- IPC 返回结构化错误和状态,不把异常吞成空数组。
6. 页面设计原则
- Element Plus 为唯一组件体系。
- 表格优先表达可比较信息;详情用标签页,不平铺所有模块。
- 状态必须同时使用文字和颜色,不能只靠颜色。
- 表头提示说明定义、作用、适用范围和分界,不只展开缩写。
- 图表必须有横纵坐标、十字准星、日期/数值提示和可见的数据窗口。
- 返回页面时恢复分页、筛选、选中项、折叠和滚动位置。
7. 测试门槛
每轮实现至少运行:
npm run typecheck
npm test
npm run build
重点测试:
- API 响应归一化和缺失字段。
- 批次暂停、续跑、同日恢复和失败项重试。
- 评分及倍率边界。
- SQLite 迁移与 CRUD。
- AI 失败时的确定性降级。
真实接口冒烟测试必须低频执行,不作为每次单元测试的依赖。
8. 文档治理
PLAN.md只做入口。plan/只保留当前计划。docs/文档索引.md区分活跃文档和退役档案。- 旧实现与旧计划依赖 Git 追溯,不在仓库工作区重复保留。