# 可比公司选择

<cite>
**本文引用的文件**
- `src/app/comparable-company-selection/comparable-company-selection.component.ts`
- `src/app/comparable-company-selection/managers/search.manager.ts`
- `src/app/comparable-company-selection/managers/tree.manager.ts`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts`
- `src/app/comparable-company-selection/handlers/event.handlers.ts`
- `src/app/comparable-company-selection/constants/component.constants.ts`
- `src/app/comparable-company-selection/types/component.types.ts`
- `src/app/comparable-company-selection/utils/component.utils.ts`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts`
- `src/app/services/comparable-company-selection.service.ts`
- `src/app/comparable-company-selection/persistence-timing.spec.ts`
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本技术文档围绕 GSDJGXApp 的“可比公司选择”算法模块，系统阐述以下内容：
- 贪婪搜索策略：搜索空间定义、评估函数设计、局部最优解生成
- 全局最优搜索算法：搜索树构建、剪枝策略、全局最优路径查找
- 两种算法的适用场景与性能对比（时间复杂度、内存优化）
- 可比公司筛选标准：行业匹配、规模相似性、财务特征对比
- 算法参数配置指南、调优建议与实际应用案例
- 算法可视化与调试工具使用方法

本模块采用“树形分类 + 动态筛选 + 搜索”的组合模式，结合前端状态机与后端持久化服务，形成完整的可比公司筛选流程。

## 项目结构
可比公司选择模块位于 src/app/comparable-company-selection 目录下，主要由组件、管理器、处理器、工具与常量构成，并通过服务层与后端进行数据持久化。

```mermaid
graph TB
subgraph "UI层"
C["ComparableCompanySelectionComponent<br/>主组件"]
TV["TreeView 组件"]
GV["Grid 组件"]
end
subgraph "管理器层"
TM["TreeManager<br/>树节点管理"]
GM["GridDataManager<br/>网格数据管理"]
SM["SearchManager<br/>搜索管理"]
end
subgraph "处理器层"
EH["EventHandlers<br/>事件处理"]
end
subgraph "工具与常量"
CU["ComponentUtils<br/>通用工具"]
FC["FIELD_NAME_MAPPING_SERVICE<br/>字段映射"]
CT["component.constants.ts<br/>常量"]
TT["component.types.ts<br/>类型定义"]
end
subgraph "服务层"
CS["ComparableCompanySelectionService<br/>持久化服务"]
end
C --> TM
C --> GM
C --> SM
C --> EH
C --> CU
C --> FC
C --> CT
C --> TT
C --> CS
EH --> TM
EH --> GM
SM --> CU
GM --> CU
TM --> CU
```

图表来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L92-L446`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L8-L681`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L8-L373`
- `src/app/comparable-company-selection/managers/search.manager.ts#L9-L248`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L11-L800`
- `src/app/comparable-company-selection/constants/component.constants.ts#L1-L64`
- `src/app/comparable-company-selection/types/component.types.ts#L1-L104`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L65-L214`
- `src/app/services/comparable-company-selection.service.ts#L102-L522`

章节来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L92-L446`
- `src/app/comparable-company-selection/constants/component.constants.ts#L1-L64`

## 核心组件
- 主组件：负责生命周期、状态管理、UI 初始化与持久化触发时机控制
- TreeManager：封装 TreeView 组件的节点添加、展开、选中状态同步等操作
- GridDataManager：负责网格数据源构建、筛选应用、UI 选择状态同步
- SearchManager：负责搜索输入防抖、搜索历史、结果转换与状态更新
- EventHandlers：处理树节点勾选/展开、列表项选择、网格行样式与筛选变更
- ComponentUtils：提供股票代码标准化、状态查询、树内搜索等工具方法
- FieldNameMappingService：动态财务字段的中文显示与格式化
- ComparableCompanySelectionService：与后端交互，实现自动保存、解析序列化、指标均值计算

章节来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L259-L446`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L8-L681`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L8-L373`
- `src/app/comparable-company-selection/managers/search.manager.ts#L9-L248`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L11-L800`
- `src/app/comparable-company-selection/utils/component.utils.ts#L6-L438`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L65-L214`
- `src/app/services/comparable-company-selection.service.ts#L102-L522`

## 架构总览
整体采用“组件 + 管理器 + 处理器 + 工具 + 服务”的分层架构：
- 组件层：协调各管理器与处理器，维护组件状态与 UI 生命周期
- 管理器层：封装第三方 UI 组件（TreeView/Grid）与业务状态的桥接
- 处理器层：承接用户事件，驱动状态变更与异步数据加载
- 工具层：提供通用算法与数据校验能力
- 服务层：对接后端持久化与计算接口

```mermaid
sequenceDiagram
participant U as "用户"
participant C as "主组件"
participant EH as "事件处理器"
participant TM as "TreeManager"
participant GM as "GridDataManager"
participant SM as "SearchManager"
participant CS as "持久化服务"
U->>C : 选择筛选条件/勾选节点/输入搜索
C->>EH : 分发事件
EH->>TM : 展开/添加节点/同步选中
EH->>GM : 更新网格数据/应用筛选
EH->>SM : 搜索输入/结果转换
C->>CS : 自动保存满足条件后
CS-->>C : 保存完成/刷新视图
```

图表来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L723-L765`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L65-L97`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L38-L84`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L28-L104`
- `src/app/comparable-company-selection/managers/search.manager.ts#L75-L154`
- `src/app/services/comparable-company-selection.service.ts#L432-L456`

## 详细组件分析

### 贪婪搜索策略
- 搜索空间定义
  - 树形分类空间：基于行业/概念板块的树节点，节点展开时按需加载子节点
  - 搜索结果空间：基于关键词的实时搜索，支持防抖与历史记录
- 评估函数设计
  - 优先级：已选公司去重、分类来源禁用、动态字段映射
  - 状态评估：通过工具函数计算“是否已选/是否来自分类/是否可移除”
- 局部最优解生成
  - 勾选分类节点时，一次性拉取该分类下全部股票，避免多次请求
  - 搜索结果中，优先标记已选状态，保证 UI 与数据一致

```mermaid
flowchart TD
Start(["开始"]) --> Input["输入搜索词"]
Input --> Debounce["防抖等待"]
Debounce --> Query["调用API获取搜索结果"]
Query --> Convert["转换为ListView格式<br/>标注已选/禁用状态"]
Convert --> Update["更新搜索结果状态"]
Update --> End(["结束"])
```

图表来源
- `src/app/comparable-company-selection/managers/search.manager.ts#L75-L154`
- `src/app/comparable-company-selection/utils/component.utils.ts#L257-L298`

章节来源
- `src/app/comparable-company-selection/managers/search.manager.ts#L75-L154`
- `src/app/comparable-company-selection/utils/component.utils.ts#L257-L298`

### 全局最优搜索算法（树形搜索与筛选）
- 搜索树构建
  - TreeManager 负责节点安全添加、展开、同步选中状态
  - 事件处理器在节点展开时按需加载子节点，避免一次性加载全量数据
- 剪枝策略
  - 已选公司去重：通过标准化股票代码进行精确匹配
  - 分类来源控制：来自分类的项目禁止在搜索结果中直接移除
  - 筛选条件即时生效：勾选即剔除，取消勾选即保留
- 全局最优路径查找
  - 通过“分类勾选 + 动态筛选 + 搜索”的组合，逐步缩小候选空间
  - GridDataManager 应用筛选规则，实时更新网格状态与视觉反馈

```mermaid
sequenceDiagram
participant U as "用户"
participant EH as "事件处理器"
participant TM as "TreeManager"
participant API as "ThsApiService"
participant GM as "GridDataManager"
U->>EH : 勾选分类节点
EH->>API : 获取该分类下股票列表
API-->>EH : 返回股票数据
EH->>TM : 添加节点/同步选中
EH->>GM : 更新网格数据并应用筛选
GM-->>U : 刷新网格显示
```

图表来源
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L102-L168`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L38-L84`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L28-L104`

章节来源
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L102-L168`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L38-L84`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L109-L230`

### 筛选标准与评估
- 行业匹配
  - 通过树形分类选择行业板块，自动加载该板块下全部股票
  - 支持多层级分类路径，便于精细化筛选
- 规模相似性
  - 市值阈值（如小于 50 亿元）可作为剔除条件
- 财务特征对比
  - 动态财务字段映射（PE、PB、PS、ROE、ROA、EV/EBITDA 等）
  - 字段格式化与中文显示，支持 Excel 风格筛选

章节来源
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L109-L230`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L13-L60`
- `src/app/comparable-company-selection/constants/component.constants.ts#L14-L27`

### 算法参数配置与调优
- 搜索防抖时间：300ms（平衡响应速度与请求频率）
- 自动保存延迟：1000ms（避免频繁保存）
- 筛选默认选项：ST公司剔除、非A股剔除
- 树节点等待超时：2000ms（确保 DOM 就绪）

章节来源
- `src/app/comparable-company-selection/constants/component.constants.ts#L10-L12`
- `src/app/comparable-company-selection/constants/component.constants.ts#L59-L61`
- `src/app/comparable-company-selection/constants/component.constants.ts#L23-L27`

### 实际应用案例
- 场景一：按申万一级行业筛选可比公司
  - 步骤：展开行业树 -> 勾选目标行业 -> 应用默认筛选 -> 导出结果
- 场景二：跨行业寻找相似规模公司
  - 步骤：使用搜索框定位目标公司 -> 手动勾选 -> 调整市值阈值筛选
- 场景三：动态财务指标对比
  - 步骤：启用动态字段 -> 查看 PE/PB/PS 等指标 -> 使用筛选器排序

章节来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L259-L446`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L84-L98`

### 可视化与调试工具
- 持久化触发时序测试：验证筛选与网格更新在保存前完成
- 日志与状态打印：组件状态、树节点展开状态、网格刷新状态
- UI 视觉反馈：未选中行的弱化显示、禁用复选框、展开/加载状态指示

章节来源
- `src/app/comparable-company-selection/persistence-timing.spec.ts#L19-L344`
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L107-L142`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L457-L480`

## 依赖关系分析

```mermaid
classDiagram
class ComparableCompanySelectionComponent {
+ngOnInit()
+onFilterChange()
+updateGridDataAndFilters()
+triggerAutoSave()
}
class EventHandlers {
+onTreeNodeChecked()
+onTreeNodeExpanding()
+onListItemSelect()
}
class TreeManager {
+safeAddNodes()
+expandNodes()
+getCheckedNodes()
}
class GridDataManager {
+updateGridData()
+applyFilters()
+refreshGrid()
}
class SearchManager {
+onSearchInput()
+performSearch()
+updateSearchResultsSelection()
}
class ComparableCompanySelectionService {
+autoSave()
+createOrUpdateComparableCompanySelection()
+calculateFinancialMetricsAverages()
}
class ComponentUtils {
+normalizeStockCode()
+getItemDetailedStatus()
+searchInTreeData()
}
class FieldNameMappingService {
+addApiFieldMappings()
+getDisplayName()
+getFormat()
}
ComparableCompanySelectionComponent --> EventHandlers : "使用"
ComparableCompanySelectionComponent --> TreeManager : "使用"
ComparableCompanySelectionComponent --> GridDataManager : "使用"
ComparableCompanySelectionComponent --> SearchManager : "使用"
ComparableCompanySelectionComponent --> ComparableCompanySelectionService : "持久化"
EventHandlers --> TreeManager : "依赖"
EventHandlers --> GridDataManager : "依赖"
GridDataManager --> ComponentUtils : "使用"
SearchManager --> ComponentUtils : "使用"
ComparableCompanySelectionComponent --> ComponentUtils : "使用"
ComparableCompanySelectionComponent --> FieldNameMappingService : "使用"
```

图表来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L259-L446`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L11-L800`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L8-L681`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L8-L373`
- `src/app/comparable-company-selection/managers/search.manager.ts#L9-L248`
- `src/app/services/comparable-company-selection.service.ts#L102-L522`
- `src/app/comparable-company-selection/utils/component.utils.ts#L6-L438`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L65-L214`

章节来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L259-L446`
- `src/app/comparable-company-selection/handlers/event.handlers.ts#L11-L800`
- `src/app/comparable-company-selection/managers/tree.manager.ts#L8-L681`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L8-L373`
- `src/app/comparable-company-selection/managers/search.manager.ts#L9-L248`
- `src/app/services/comparable-company-selection.service.ts#L102-L522`
- `src/app/comparable-company-selection/utils/component.utils.ts#L6-L438`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L65-L214`

## 性能考量
- 前端性能优化
  - TreeView 虚拟滚动、禁用悬停与交替行以降低大数据集渲染开销
  - 搜索防抖（300ms）、自动保存延迟（1000ms）减少请求与持久化压力
  - 网格刷新前的安全检查，避免未就绪状态下的异常
- 算法复杂度
  - 搜索：O(n) 遍历树/列表，配合防抖与增量更新
  - 筛选：O(m) 应用筛选规则，m 为网格行数
  - 去重与匹配：基于标准化股票代码的 O(1) 查找（Set/Map）
- 内存优化
  - 动态字段映射与列生成，避免冗余字段存储
  - 按需加载树节点，避免一次性加载全量数据

章节来源
- `src/app/comparable-company-selection/comparable-company-selection.component.ts#L96-L105`
- `src/app/comparable-company-selection/constants/component.constants.ts#L59-L61`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L212-L230`

## 故障排查指南
- 树节点展开失败
  - 检查 TreeManager 的等待就绪与父节点 DOM 状态
  - 确认节点已存在且 hasChildren 状态正确
- 网格刷新异常
  - 确保 headerModule 就绪后再调用 refresh
  - 检查网格选择状态同步逻辑
- 搜索结果状态不同步
  - 确认已调用 updateSearchResultsSelection 并触发状态更新
  - 检查已选清单标准化与去重逻辑
- 自动保存未触发或触发过早
  - 通过时序测试验证 applyFilters/updateGridData 完成后再触发保存
  - 检查 hasUnsavedChanges 标志与延迟定时器

章节来源
- `src/app/comparable-company-selection/managers/tree.manager.ts#L21-L29`
- `src/app/comparable-company-selection/managers/grid-data.manager.ts#L297-L327`
- `src/app/comparable-company-selection/managers/search.manager.ts#L173-L205`
- `src/app/comparable-company-selection/persistence-timing.spec.ts#L111-L166`

## 结论
本模块通过“树形分类 + 动态筛选 + 搜索”的组合策略，实现了高效、可控的可比公司筛选流程。前端采用管理器与处理器解耦 UI 与业务逻辑，配合工具函数与服务层实现数据一致性与持久化。在性能方面，通过防抖、延迟保存与虚拟滚动等手段，兼顾了用户体验与系统资源消耗。后续可在以下方向进一步优化：
- 引入更精细的相似度评估函数（财务指标权重、行业聚类）
- 增强搜索评分与排序策略
- 扩展筛选规则与可视化面板

## 附录
- 关键类型与常量
  - 类型定义：SelectedItem、GridItem、SearchResult、ComponentState、PersistenceState
  - 常量：筛选选项、默认筛选、自动保存延迟、搜索防抖时间、树等待超时
- 字段映射
  - 财务指标中文显示与格式化规则，支持 API 动态字段扩展

章节来源
- `src/app/comparable-company-selection/types/component.types.ts#L28-L104`
- `src/app/comparable-company-selection/constants/component.constants.ts#L14-L61`
- `src/app/comparable-company-selection/services/field-name-mapping.service.ts#L13-L60`