# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## 快速参考

**启动项目:**
- 后端: `mvn spring-boot:run` 或运行 `ry.bat`
- 前端: `cd ruoyi-ui && npm run dev`

**访问地址:**
- 前端: http://localhost:80
- 后端: http://localhost:8080
- Swagger: http://localhost:8080/swagger-ui/index.html
- Druid 监控: http://localhost:8080/druid/ (ruoyi/123456)

**测试账号:**
- 用户名: `admin`
- 密码: `admin123`

**获取 Token:**
```bash
POST http://localhost:8080/login/test?username=admin&password=admin123
```

---

## 项目概述

**纪检初核系统** - 基于 **若依管理系统 v3.9.1** 构建的企业级前后端分离管理系统，用于员工异常行为风险识别。

### 技术栈版本

| 后端技术                        | 版本     | 前端技术       | 版本      |
|-----------------------------|--------|------------|---------|
| Spring Boot                 | 3.5.8  | Vue.js     | 2.6.12  |
| Java                        | 21     | Element UI | 2.15.14 |
| MyBatis Spring Boot Starter | 3.0.5  | Vuex       | 3.6.0   |
| MySQL Connector             | 8.2.0  | Vue Router | 3.4.9   |
| SpringDoc OpenAPI           | 2.8.14 | Axios      | 0.28.1  |
| EasyExcel                   | 3.3.4  | ECharts    | 5.4.0   |
| Quartz                      | 2.5.2  | Sass       | 1.32.13 |

---

## 常用命令

### 后端 (Maven)

```bash
# 编译项目
mvn clean compile

# 运行应用 (开发环境)
mvn spring-boot:run

# 打包部署
mvn clean package

# Windows 启动
ry.bat

# Linux/Mac 启动
./ry.sh start
```

### 前端 (npm)

```bash
cd ruoyi-ui

# 安装依赖 (推荐使用国内镜像)
npm install --registry=https://registry.npmmirror.com

# 开发服务器 (端口 80)
npm run dev

# 生产构建
npm run build:prod

# 预览生产构建
npm run preview
```

### 数据库初始化

```bash
# 初始化若依框架基础表
mysql -u root -p < sql/ry_20250522.sql

# 初始化定时任务表
mysql -u root -p < sql/quartz.sql

# 导入业务表（根据需要执行）
mysql -u root -p ccdi < sql/dpc_employee.sql
mysql -u root -p ccdi < sql/dpc_intermediary_blacklist.sql
# ... 其他业务表脚本
```

**注意:**
- 业务表脚本文件名以 `ccdi_` 或 `dpc_` 开头
- 部分脚本包含菜单数据，需要按顺序执行
- 数据库需要先创建（数据库名: `ccdi`）

---

## 模块架构

```
ccdi/
├── ruoyi-admin/          # 主应用入口 (Spring Boot 启动类)
├── ruoyi-framework/      # 核心框架 (Security, Config, Filters)
├── ruoyi-system/         # 系统管理 (Users, Roles, Menus, Depts)
├── ruoyi-common/         # 通用工具 (annotations, utils, constants)
├── ruoyi-quartz/         # 定时任务
├── ruoyi-generator/      # 代码生成器
├── ccdi-info-collection/ # 【核心业务模块】信息采集
├── ccdi-project/         # 【核心业务模块】项目管理
├── ccdi-lsfx/            # 【核心业务模块】流水分析对接
├── lsfx-mock-server/     # 流水分析模拟服务器 (Python)
├── ruoyi-ui/             # 前端 Vue 应用
├── sql/                  # 数据库脚本
├── bin/                  # 启动脚本
└── doc/                  # 项目文档
```

### 模块依赖关系

```
ruoyi-admin (启动模块)
    ├── ruoyi-framework (核心安全配置)
    ├── ruoyi-system (系统核心业务)
    ├── ruoyi-common (共享工具)
    ├── ruoyi-quartz (定时任务)
    ├── ruoyi-generator (代码生成)
    ├── ccdi-info-collection (信息采集模块)
    │   └── 依赖 ruoyi-common
    ├── ccdi-project (项目管理模块)
    │   └── 依赖 ruoyi-common
    └── ccdi-lsfx (流水分析对接模块)
        └── 依赖 ruoyi-common
```

**添加新业务模块:**
1. 在根目录 `pom.xml` 的 `<modules>` 中添加新模块
2. 在新模块的 `pom.xml` 中添加对 `ruoyi-common` 的依赖
3. 在 `ruoyi-admin/pom.xml` 中添加对新模块的依赖
4. 在新模块中按照分层规范创建 controller/service/mapper/domain 包

### ccdi-info-collection 业务模块 (核心)

自定义业务模块，包含以下核心功能：

| 功能       | Controller                            | 实体类                         |
|----------|---------------------------------------|-----------------------------|
| 员工基础信息   | CcdiBaseStaffController               | CcdiBaseStaff               |
| 中介黑名单    | CcdiIntermediaryController            | CcdiBizIntermediary         |
| 员工家庭关系   | CcdiStaffFmyRelationController        | CcdiStaffFmyRelation        |
| 员工企业关系   | CcdiStaffEnterpriseRelationController | CcdiStaffEnterpriseRelation |
| 信贷客户家庭关系 | CcdiCustFmyRelationController         | CcdiCustFmyRelation         |
| 信贷客户企业关系 | CcdiCustEnterpriseRelationController  | CcdiCustEnterpriseRelation  |
| 员工调动记录   | CcdiStaffTransferController           | CcdiStaffTransfer           |
| 员工招聘记录   | CcdiStaffRecruitmentController        | CcdiStaffRecruitment        |
| 采购交易     | CcdiPurchaseTransactionController     | CcdiPurchaseTransaction     |

**分层结构:**

- Controller: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/`
- Service: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/`
- Mapper: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/`
- Domain: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/`
  - dto/: 数据传输对象
  - vo/: 视图对象
  - excel/: Excel导入导出实体
- XML映射: `ccdi-info-collection/src/main/resources/mapper/info/collection/`

### ccdi-project 业务模块 (核心)

项目管理模块，用于管理纪检初核项目的全生命周期：

**核心功能:**
- 项目创建、更新、删除、查询
- 项目状态管理 (进行中、已完成、已归档)
- 项目统计（按状态统计数量）
- 模型参数配置管理

**主要 Controller:**
- CcdiProjectController: 项目管理
- CcdiModelParamController: 模型参数配置

**分层结构:**
- Controller: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/`
- Service: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/`
- Mapper: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/`
- Domain: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/`
- XML映射: `ccdi-project/src/main/resources/mapper/ccdi/project/`

### ccdi-lsfx 业务模块 (核心)

流水分析平台对接模块，用于与外部流水分析系统交互：

**核心功能:**
- 获取访问令牌 (Token)
- 上传流水文件并解析
- 拉取行内流水数据
- 查询解析状态和结果
- 获取银行流水明细

**主要组件:**
- LsfxAnalysisClient: 流水分析平台客户端
- LsfxTestController: 测试接口

**配置项 (application-dev.yml):**
```yaml
lsfx:
  api:
    base-url: http://localhost:8000  # 流水分析平台地址
    app-id: your-app-id
    app-secret: your-app-secret
    client-id: your-client-id
    endpoints:
      get-token: /api/auth/token
      upload-file: /api/files/upload
      fetch-inner-flow: /api/flow/inner
```

**分层结构:**
- Client: `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/client/`
- Controller: `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/controller/`
- Domain: `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/domain/`
  - request/: 请求对象
  - response/: 响应对象
- Config: `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/config/`

### lsfx-mock-server (开发测试工具)

Python 实现的流水分析平台模拟服务器，用于本地开发和测试：

**用途:**
- 模拟流水分析平台的 API 接口
- 提供测试数据和模拟响应
- 支持错误场景模拟

**启动方式:**
```bash
cd lsfx-mock-server
python app.py  # 默认监听 http://localhost:8000
```

---

## 后端开发规范

### 通用规范

- **新模块命名**: 项目英文名首字母集合 + 主要功能 (如 `ruoyi-info-collection`)
- **代码分离**: 新功能代码与若依框架自带代码分离，Controller 放在新模块中
- **审计字段**: 实体类不继承 BaseEntity，单独添加审计字段，通过注释实现自动插入

### Java 代码风格

```java
// 使用 @Data 注解
@Data
public class CcdiBaseStaff {
  // 审计字段通过注释实现自动插入
  /** 创建者 */
  private String createBy;
  /** 创建时间 */
  private Date createTime;
  /** 更新者 */
  private String updateBy;
  /** 更新时间 */
  private Date updateTime;
}

  // 服务层使用 @Resource 注入
  @Resource
  private ICcdiBaseStaffService baseStaffService;
```

### 分层规范

- **Controller**: 所有接口添加 Swagger 注释，分页使用 MyBatis Plus Page
- **Service**: 简单 CRUD 用 MyBatis Plus 方法，复杂操作在 XML 写 SQL
- **DTO/VO**: 接口传参使用独立 DTO，返回使用独立 VO，不与 entity 混用
- **Mapper**: 简单操作继承 BaseMapper，复杂操作在 XML 中定义

### 禁止事项

- **禁止使用全限定类名**: 必须使用 `import` 语句导入类，不要在代码中使用 `java.util.List` 这样的全限定名
- **禁止使用 `extends ServiceImpl<>`**: Service 接口和实现类分离定义
- **禁止 Entity 混用**: DTO、VO、Excel 类必须独立，不与 Entity 混用
- **禁止缺少 `@Resource`**: Service 注入必须使用 `@Resource` 注解

### API 响应格式

```java
// 成功
AjaxResult.success("操作成功", data);

// 错误
AjaxResult.error("操作失败");

// 分页
Page<CcdiBaseStaff> page = new Page<>(pageNum, pageSize);
IPage<CcdiBaseStaff> result = baseStaffMapper.selectPage(page, queryWrapper);
return AjaxResult.success(result);
```

---

## 前端开发规范

### 目录结构

```
ruoyi-ui/src/
├── api/              # API 请求定义 (与后端 Controller 对应)
├── views/            # 页面组件 (按功能模块组织)
│   ├── ccdiBaseStaff/
│   ├── ccdiIntermediary/
│   └── ...
├── components/       # 可复用组件 (复杂组件需拆分)
├── router/           # 路由配置
└── store/            # Vuex 状态管理
```

### API 调用示例

```javascript
import request from '@/utils/request'

export function listStaff(query) {
  return request({
    url: '/ccdi/baseStaff/list',
    method: 'get',
    params: query
  })
}
```

### 菜单联动

添加页面和组件后，需要同步修改数据库中的菜单表 (`sys_menu`)。

---

## 特殊功能

### 异步导入

支持大数据量异步 Excel 导入，通过 taskId 查询导入状态：

```java
@PostMapping("/import")
public AjaxResult asyncImport(@RequestParam("file") MultipartFile file) {
    String taskId = asyncImportService.startImport(file);
    return AjaxResult.success("导入任务已启动", taskId);
}

@GetMapping("/import/status/{taskId}")
public AjaxResult getImportStatus(@PathVariable String taskId) {
    return AjaxResult.success(asyncImportService.getStatus(taskId));
}
```

**导入流程:**
1. 前端上传 Excel 文件
2. 后端异步处理，返回 taskId
3. 前端轮询 `/import/status/{taskId}` 获取导入进度
4. 导入完成后，可获取成功/失败数据统计

**导入结果处理:**
- 只返回导入失败的数据（含失败原因）
- 成功数据不返回，减少响应体积
- 支持批量插入，提高性能

### EasyExcel 字典下拉框

导入模板支持字典下拉框配置，提升数据录入准确性。使用 `DictDropdownWriteHandler` 实现。

### 权限控制

基于 Spring Security + JWT 的角色菜单权限系统：

- 权限格式: `system:user:edit`, `ccdi:staff:list`
- 数据权限: 支持全部、自定义、部门等范围

---

## 测试与验证

### 测试账号

- **用户名**: `admin`
- **密码**: `admin123`

### 登录获取 Token

```bash
# 登录接口
POST /login/test?username=admin&password=admin123
```

### API 文档

- **Swagger UI**: `/swagger-ui/index.html`
- **API Docs**: `/v3/api-docs`

### 测试规范

- 不在命令行启动后端进行测试
- 生成可执行的测试脚本进行验证
- 测试完成后保存接口输出并生成测试用例报告

### 开发调试技巧

**使用 Swagger 测试接口:**
1. 访问 `/swagger-ui/index.html`
2. 点击接口展开详情
3. 点击 "Try it out" 进行测试
4. 填写参数后点击 "Execute" 执行

**查看 SQL 执行日志:**
- 在 `application.yml` 中设置日志级别: `com.ruoyi: debug`
- 使用 Druid 监控台查看慢 SQL

**前端代理配置:**
前端开发服务器通过代理转发请求到后端：
- 前端地址: `http://localhost:80`
- 后端地址: `http://localhost:8080`
- 代理配置文件: `ruoyi-ui/vue.config.js`

---

## 配置说明

| 配置项     | 值                 |
|---------|-------------------|
| 后端端口    | 8080              |
| 前端开发端口  | 80                |
| 默认管理员   | admin/admin123    |
| JWT 有效期 | 30 分钟             |
| 文件上传限制  | 单文件 10MB, 总计 20MB |

### 配置文件位置

| 配置       | 路径                                                   |
|----------|------------------------------------------------------|
| 主配置      | `ruoyi-admin/src/main/resources/application.yml`     |
| 开发环境     | `ruoyi-admin/src/main/resources/application-dev.yml` |
| 数据库连接    | `application-dev.yml`                                |
| Redis 配置 | `application-dev.yml`                                |

### 数据源配置

项目使用 Druid 连接池，支持主从分离（默认关闭从库）：

- **数据库连接**: `jdbc:mysql://host:3306/ccdi`
- **初始连接数**: 5
- **最小连接数**: 10
- **最大连接数**: 20
- **慢 SQL 记录**: 超过 1000ms 的 SQL 会被记录

### Redis 配置

- **默认端口**: 6379
- **数据库索引**: 0
- **连接超时**: 10s

### 流水分析平台配置

项目集成了外部流水分析平台，配置项位于 `application-dev.yml`:

```yaml
lsfx:
  api:
    base-url: http://localhost:8000      # 流水分析平台基础地址
    app-id: ccdi-app                     # 应用ID
    app-secret: ccdi-secret-2024         # 应用密钥
    client-id: ccdi-client               # 客户端ID
    endpoints:
      get-token: /api/auth/token         # 获取令牌接口
      upload-file: /api/files/upload     # 文件上传接口
      fetch-inner-flow: /api/flow/inner  # 拉取行内流水接口
```

**开发环境使用 Mock 服务器:**
- 本地开发时，将 `base-url` 设置为 `http://localhost:8000`
- 启动 `lsfx-mock-server` 提供模拟接口
- 生产环境替换为真实的流水分析平台地址

### MCP 配置

项目使用 MCP (Model Context Protocol) 连接数据库，配置文件: `.mcp.json`

```json
{
  "mcpServers": {
    "mysql": {
      "command": "npx",
      "args": ["-y", "@fhuang/mcp-mysql-server"],
      "env": {
        "MYSQL_HOST": "116.62.17.81",
        "MYSQL_PORT": "3306",
        "MYSQL_USER": "root",
        "MYSQL_PASSWORD": "Kfcx@1234",
        "MYSQL_DATABASE": "ccdi"
      }
    }
  }
}
```

**使用场景:**
- 通过 MCP 工具直接查询和操作数据库
- 在开发过程中快速验证数据
- 生成测试数据和调试 SQL

### Druid 监控台

访问地址: `http://localhost:8080/druid/`
- 用户名: `ruoyi`
- 密码: `123456`

用于监控 SQL 执行情况、连接池状态等。

---

## 重要文件路径

| 用途            | 路径                                                                             |
|---------------|--------------------------------------------------------------------------------|
| 应用入口          | `ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java`                    |
| 安全配置          | `ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java` |
| 信息采集 Controller | `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/` |
| 信息采集 Mapper XML | `ccdi-info-collection/src/main/resources/mapper/info/collection/`          |
| 项目管理 Controller | `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/` |
| 项目管理 Mapper XML | `ccdi-project/src/main/resources/mapper/ccdi/project/` |
| 流水分析 Client | `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/client/LsfxAnalysisClient.java` |
| Vue 路由        | `ruoyi-ui/src/router/index.js`                                                 |
| Vuex Store    | `ruoyi-ui/src/store/`                                                          |
| 前端 API        | `ruoyi-ui/src/api/`                                                            |

---

## 数据库规范

- **新建表名**: 需要加上项目英文名首字母集合前缀 `ccdi_` (如 `ccdi_base_staff`)

---

## 文档管理

- **文档语言**: 使用简体中文编写 .md 文档
- **文档目录**: 所有生成的文档放在 `doc/` 目录下，按类型分类
- **需求分析**: 在 `doc/` 目录下新建文件夹，以需求内容命名

### doc 目录结构

```
doc/
├── api-docs/          # API 文档
├── database/          # 数据库相关
├── design/            # 设计文档
├── implementation/    # 实施文档
├── requirements/      # 需求文档
└── test-scripts/      # 测试脚本
```

---

## OpenSpec 工作流

项目使用 OpenSpec 进行规范驱动开发，参考 `openspec/AGENTS.md`。

### 何时创建 Proposal

**需要创建:**

- 新功能或能力
- 破坏性变更 (API, 数据库结构)
- 架构变更
- 改变行为的性能优化

**无需创建:**

- Bug 修复 (恢复预期行为)
- 拼写错误、格式、注释
- 非破坏性依赖更新
- 配置变更

---

## 沟通规范

- 永远使用简体中文进行思考和对话

---

## 常见问题排查

### 数据库连接失败

**检查项:**
1. 确认 MySQL 服务已启动
2. 检查 `application-dev.yml` 中的数据库连接配置
3. 确认数据库用户名和密码正确
4. 检查数据库是否已创建（数据库名: `ccdi`）

### Redis 连接失败

**检查项:**
1. 确认 Redis 服务已启动
2. 检查 `application-dev.yml` 中的 Redis 配置
3. 如果 Redis 不需要密码，将 `password` 配置注释掉

### 前端无法访问后端接口

**检查项:**
1. 确认后端已启动（端口 8080）
2. 检查前端代理配置（`ruoyi-ui/vue.config.js`）
3. 确认后端接口路径正确（查看 Controller 的 `@RequestMapping`）

### 导入功能无响应

**检查项:**
1. 检查文件大小是否超过限制（默认 10MB）
2. 查看后端日志是否有异常
3. 确认 Excel 模板格式正确
4. 检查必填字段是否为空

### 流水分析平台连接失败

**检查项:**
1. 确认 `lsfx-mock-server` 已启动（开发环境）
2. 检查 `application-dev.yml` 中的 `lsfx.api.base-url` 配置
3. 验证 app-id、app-secret、client-id 是否正确
4. 检查网络连接和防火墙设置
5. 查看后端日志中的 HTTP 请求错误信息

---

## MyBatis Plus 分页使用

```java
// Controller 层
@GetMapping("/list")
public TableDataInfo list(QueryDTO queryDTO) {
    PageDomain pageDomain = TableSupport.buildPageRequest();
    Page<VO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
    Page<VO> result = service.selectPage(page, queryDTO);
    return getDataTable(result.getRecords(), result.getTotal());
}

// Service 层
Page<VO> selectPage(Page<VO> page, QueryDTO queryDTO);

// Mapper 层 (使用 XML)
<select id="selectPage" resultType="VO">
    SELECT * FROM table_name
    <where>
        <if test="queryDTO.name != null">
            AND name LIKE CONCAT('%', #{queryDTO.name}, '%')
        </if>
    </where>
</select>
```
