diff --git a/Agents.md b/Agents.md new file mode 100644 index 0000000..b98aac2 --- /dev/null +++ b/Agents.md @@ -0,0 +1,715 @@ +# 资金服务平台 (FundPlatform) - 开发规范 + +> **文档版本**: v1.0 +> **创建日期**: 2026-02-20 +> **适用范围**: 本项目所有开发人员 + +--- + +## 一、项目概述 + +资金服务平台是一套完整的公司项目资金管理解决方案,采用微服务架构,实现应收账款和项目支出的全流程跟踪与管理。 + +### 1.1 技术栈 + +| 层级 | 技术选型 | +|------|----------| +| **应用框架** | Spring Boot 3.2 + Spring Cloud Alibaba | +| **服务注册** | Nacos 3.x | +| **数据库** | MySQL 8.0 | +| **缓存** | Redis 7.x | +| **ORM框架** | MyBatis-Plus 3.5 | +| **API网关** | Spring Cloud Gateway | +| **前端框架** | Vue 3 + TypeScript + Element Plus | +| **移动端** | Vue 3 + Vite 5 + Vant 4 | + +### 1.2 模块划分 + +| 模块 | 端口 | 说明 | +|------|------|------| +| fund-gateway | 8000 | API网关 | +| fund-sys | 8100 | 系统管理服务 | +| fund-cust | 8110 | 客户管理服务 | +| fund-proj | 8120 | 项目管理服务 | +| fund-req | 8130 | 需求工单服务 | +| fund-exp | 8140 | 支出管理服务 | +| fund-receipt | 8150 | 收款管理服务 | +| fund-file | 8600 | 文件服务 | +| fund-report | 8700 | 报表服务 | +| fund-admin | 3000 | 管理后台前端 | +| fund-mobile | - | 移动端H5 | + +--- + +## 二、项目结构规范 + +### 2.1 后端模块结构 + +``` +fund-xxx/ +├── src/main/java/com/fundplatform/xxx/ +│ ├── XxxApplication.java # 启动类 +│ ├── config/ # 配置类 +│ ├── controller/ # 控制器层 +│ ├── service/ # 服务层 +│ │ └── impl/ # 服务实现 +│ ├── mapper/ # MyBatis Mapper +│ ├── entity/ # 实体类 +│ ├── dto/ # 数据传输对象 +│ ├── vo/ # 视图对象 +│ └── enums/ # 枚举类 +├── src/main/resources/ +│ ├── application.yml # 主配置 +│ ├── application-docker.yml # Docker配置 +│ └── logback-spring.xml # 日志配置 +└── pom.xml +``` + +### 2.2 公共模块 (fund-common) + +``` +fund-common/ +├── src/main/java/com/fundplatform/common/ +│ ├── auth/ # 认证相关 +│ ├── cache/ # 缓存服务 +│ ├── config/ # 通用配置 +│ ├── context/ # 上下文管理 +│ ├── core/ # 核心类(Result, PageResult等) +│ ├── exception/ # 异常处理 +│ ├── feign/ # Feign拦截器 +│ ├── loadbalancer/ # 负载均衡 +│ ├── mybatis/ # MyBatis配置 +│ ├── nacos/ # Nacos配置 +│ └── web/ # Web拦截器 +``` + +### 2.3 启动类配置 + +所有业务服务必须配置 `scanBasePackages`: + +```java +@SpringBootApplication(scanBasePackages = {"com.fundplatform.xxx", "com.fundplatform.common"}) +@EnableDiscoveryClient +public class XxxApplication { + public static void main(String[] args) { + SpringApplication.run(XxxApplication.class, args); + } +} +``` + +**注意**: Gateway 作为 WebFlux 应用,**不扫描** `fund-common` 的任何包,避免 Servlet 依赖冲突。 + +--- + +## 三、命名规范 + +### 3.1 包命名 + +- 全部小写 +- 格式:`com.fundplatform.{模块名}.{层级}` + +``` +com.fundplatform.cust.controller +com.fundplatform.cust.service +com.fundplatform.cust.service.impl +com.fundplatform.cust.mapper +com.fundplatform.cust.entity +com.fundplatform.cust.dto +com.fundplatform.cust.vo +``` + +### 3.2 类命名 + +| 类型 | 命名规则 | 示例 | +|------|----------|------| +| 实体类 | 名词,PascalCase | `Customer`, `Project` | +| Controller | 名词 + Controller | `CustomerController` | +| Service接口 | 名词 + Service | `CustomerService` | +| Service实现 | 名词 + ServiceImpl | `CustomerServiceImpl` | +| Mapper | 名词 + Mapper | `CustomerMapper` | +| DTO | 动作 + 名词 + DTO | `CustomerCreateDTO`, `CustomerUpdateDTO` | +| VO | 名词 + VO | `CustomerVO`, `ProjectVO` | +| 配置类 | 功能 + Config | `RedisConfig`, `MybatisConfig` | + +### 3.3 方法命名 + +| 操作 | Service方法 | Controller方法 | +|------|-------------|----------------| +| 创建 | `createXxx()` | `createXxx()` | +| 更新 | `updateXxx()` | `updateXxx()` | +| 删除 | `deleteXxx()` | `deleteXxx()` | +| 查询单个 | `getXxxById()` | `getXxx()` | +| 分页查询 | `pageXxxs()` | `pageXxxs()` | +| 列表查询 | `listXxxs()` | `listXxxs()` | + +### 3.4 数据库命名 + +- 表名:小写,下划线分隔,如 `customer`, `project_member` +- 字段名:小写,下划线分隔,如 `customer_name`, `created_time` +- 索引名:`idx_表名_字段名`,如 `idx_customer_status` +- 主键:`表名_id`,如 `customer_id` + +--- + +## 四、数据库设计规范 + +### 4.1 必备字段 + +所有业务表必须包含以下审计字段: + +```sql +created_by BIGINT NOT NULL COMMENT '创建人ID', +created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', +updated_by BIGINT NOT NULL COMMENT '更新人ID', +updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', +deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0-未删除,1-已删除)' +``` + +### 4.2 多租户字段 + +支持多租户的表必须包含: + +```sql +tenant_id BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID' +``` + +### 4.3 主键策略 + +- 使用雪花算法(Snowflake)生成分布式ID +- MyBatis-Plus配置:`@TableId(type = IdType.ASSIGN_ID)` + +### 4.4 逻辑删除 + +- 统一使用 `deleted` 字段 +- 0 = 未删除,1 = 已删除 +- MyBatis-Plus配置:`@TableLogic` + +--- + +## 五、API设计规范 + +### 5.1 URL规范 + +``` +# 基础格式 +/{模块}/api/v1/{资源}/{动作} + +# 示例 +POST /sys/api/v1/auth/login # 登录 +GET /cust/api/v1/customer/{id} # 查询客户 +POST /cust/api/v1/customer # 创建客户 +PUT /cust/api/v1/customer/{id} # 更新客户 +DELETE /cust/api/v1/customer/{id} # 删除客户 +GET /cust/api/v1/customer/page # 分页查询 +``` + +### 5.2 HTTP方法 + +| 方法 | 用途 | 示例 | +|------|------|------| +| GET | 查询 | 查询客户列表、详情 | +| POST | 创建 | 新增客户 | +| PUT | 更新 | 修改客户信息 | +| DELETE | 删除 | 删除客户 | + +### 5.3 响应格式 + +统一使用 `Result` 包装: + +```json +{ + "code": 200, + "message": "success", + "data": { ... }, + "success": true +} +``` + +错误响应: + +```json +{ + "code": 400, + "message": "参数错误:客户名称不能为空", + "data": null, + "success": false +} +``` + +### 5.4 分页格式 + +```json +{ + "code": 200, + "message": "success", + "data": { + "pageNum": 1, + "pageSize": 10, + "total": 100, + "list": [ ... ] + }, + "success": true +} +``` + +### 5.5 状态码规范 + +| 状态码 | 说明 | +|--------|------| +| 200 | 成功 | +| 400 | 参数错误 | +| 401 | 未授权/Token无效 | +| 403 | 权限不足 | +| 404 | 资源不存在 | +| 500 | 服务器内部错误 | + +--- + +## 六、多租户规范 + +### 6.1 租户ID传递 + +1. **前端请求**:Header 传递 `X-Tenant-Id` +2. **Gateway**:`TenantGatewayFilter` 提取并透传 +3. **后端服务**:`TenantContextHolder` 存储到 ThreadLocal +4. **MyBatis拦截器**:自动注入 `tenant_id` 条件 + +### 6.2 租户隔离 + +```java +// 自动注入 tenant_id +@TableField(fill = FieldFill.INSERT) +private Long tenantId; + +// MyBatis-Plus 元数据填充 +public class TenantMetaObjectHandler implements MetaObjectHandler { + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "tenantId", Long.class, + TenantContextHolder.getTenantId()); + } +} +``` + +### 6.3 租户上下文 + +```java +// 获取当前租户ID +Long tenantId = TenantContextHolder.getTenantId(); + +// 设置租户ID(通常由拦截器自动设置) +TenantContextHolder.setTenantId(tenantId); + +// 清除上下文(请求结束时) +TenantContextHolder.clear(); +``` + +--- + +## 七、链路追踪规范 + +### 7.1 TraceId 和 SpanId + +- **TraceId**:全链路唯一标识,32位UUID +- **SpanId**:服务节点标识,16位UUID + +### 7.2 日志格式 + +``` +%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}][%X{spanId:-}] %-5level %logger{50} - %msg%n +``` + +日志示例: +``` +2026-02-20 18:10:25.240 [http-nio-8100-exec-1] [a1b2c3d4e5f6...][1234567890abcdef] INFO c.f.c.controller.CustomerController - 查询客户列表 +``` + +### 7.3 HTTP Header 透传 + +| Header | 说明 | +|--------|------| +| `X-Trace-Id` | 全链路追踪ID | +| `X-Span-Id` | 当前服务SpanID | +| `X-Source-Service` | 来源服务名 | +| `X-Request-Time` | 请求发起时间戳 | +| `X-Tenant-Id` | 租户ID | +| `X-User-Id` | 用户ID | +| `X-Username` | 用户名 | + +### 7.4 响应头返回 + +API响应必须返回追踪信息: + +``` +X-Trace-Id: a1b2c3d4e5f67890a1b2c3d4e5f67890 +X-Span-Id: 1234567890abcdef +``` + +--- + +## 八、Token认证规范 + +### 8.1 Token机制 + +采用 **UUID + Redis** 方案(非JWT): + +```java +// 生成Token +String token = tokenService.generateToken(userId, username, tenantId); + +// Token存储到Redis +Key: auth:token:{token} +Value: TokenInfo(userId, username, tenantId, expireTime) +TTL: 24小时 +``` + +### 8.2 请求认证 + +``` +Authorization: Bearer {token} +``` + +### 8.3 白名单路径 + +以下路径无需Token验证: + +``` +/sys/api/v1/auth/login +/sys/api/v1/sys/health +``` + +--- + +## 九、日志规范 + +### 9.1 日志级别 + +| 级别 | 使用场景 | +|------|----------| +| ERROR | 异常、错误、需要立即处理的问题 | +| WARN | 警告、潜在问题 | +| INFO | 关键业务流程、重要操作 | +| DEBUG | 调试信息、详细流程 | + +### 9.2 日志文件 + +``` +logs/ +├── fund-xxx.log # 主日志 +├── fund-xxx/ +│ ├── info.log # INFO级别日志 +│ ├── error.log # ERROR级别日志 +│ └── aop.log # API请求日志 +``` + +### 9.3 API请求日志 + +通过AOP记录所有API请求: + +```java +@Around("execution(* com.fundplatform..controller..*(..))") +public Object logApiRequest(ProceedingJoinPoint joinPoint) { + // 记录:请求方法、参数、响应时间、结果状态 +} +``` + +--- + +## 十、异常处理规范 + +### 10.1 统一异常处理 + +```java +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(BusinessException.class) + public Result handleBusinessException(BusinessException e) { + return Result.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(Exception.class) + public Result handleException(Exception e) { + log.error("系统异常", e); + return Result.error(500, "系统异常,请稍后重试"); + } +} +``` + +### 10.2 业务异常 + +```java +public class BusinessException extends RuntimeException { + private final int code; + + public BusinessException(String message) { + super(message); + this.code = 400; + } + + public BusinessException(int code, String message) { + super(message); + this.code = code; + } +} +``` + +### 10.3 异常使用 + +```java +// 参数校验 +if (customerName == null || customerName.isEmpty()) { + throw new BusinessException("客户名称不能为空"); +} + +// 业务校验 +Customer customer = customerMapper.selectById(id); +if (customer == null) { + throw new BusinessException(404, "客户不存在"); +} +``` + +--- + +## 十一、Git提交规范 + +### 11.1 分支命名 + +``` +master # 主分支 +develop # 开发分支 +feature/xxx # 功能分支 +bugfix/xxx # Bug修复分支 +hotfix/xxx # 紧急修复分支 +``` + +### 11.2 提交信息格式 + +``` +: + + +``` + +**type 类型**: + +| 类型 | 说明 | +|------|------| +| feat | 新功能 | +| fix | Bug修复 | +| docs | 文档更新 | +| style | 代码格式调整 | +| refactor | 重构 | +| test | 测试相关 | +| chore | 构建/工具相关 | + +**示例**: + +``` +feat: 新增客户管理分页查询接口 + +- 支持按客户名称模糊查询 +- 支持按状态筛选 +- 分页参数校验 +``` + +``` +fix: 修复Gateway路由配置错误 + +fund-cust 路由路径配置错误,修正为 /cust/** +``` + +--- + +## 十二、代码规范 + +### 12.1 Controller层 + +```java +@RestController +@RequestMapping("/api/v1/customer") +@RequiredArgsConstructor +public class CustomerController { + + private final CustomerService customerService; + + @PostMapping + public Result createCustomer(@Valid @RequestBody CustomerCreateDTO dto) { + Long id = customerService.createCustomer(dto); + return Result.success(id); + } + + @GetMapping("/page") + public Result> pageCustomers( + @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize, + @RequestParam(required = false) String keyword) { + Page page = customerService.pageCustomers(pageNum, pageSize, keyword); + return Result.success(PageResult.of(page)); + } +} +``` + +### 12.2 Service层 + +```java +@Service +@RequiredArgsConstructor +public class CustomerServiceImpl implements CustomerService { + + private final CustomerMapper customerMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createCustomer(CustomerCreateDTO dto) { + // 1. 参数校验 + // 2. 业务逻辑 + // 3. 数据持久化 + // 4. 返回结果 + } +} +``` + +### 12.3 DTO/VO规范 + +```java +@Data +public class CustomerCreateDTO { + + @NotBlank(message = "客户名称不能为空") + @Size(max = 200, message = "客户名称最长200字符") + private String customerName; + + @NotBlank(message = "联系人不能为空") + private String contact; + + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + private String phone; +} +``` + +--- + +## 十三、配置规范 + +### 13.1 Redis配置 + +所有服务统一使用 **database 0**: + +```yaml +spring: + data: + redis: + host: localhost + port: 6379 + password: zjf@123456 + database: 0 +``` + +### 13.2 Nacos配置 + +```yaml +spring: + cloud: + nacos: + discovery: + server-addr: localhost:8848 + namespace: fund-platform + group: DEFAULT_GROUP + username: nacos + password: nacos +``` + +### 13.3 日志配置 + +```xml + + + + + ./logs/${APP_NAME}/info.log + + ./logs/${APP_NAME}/info-%d{yyyy-MM-dd}.%i.log + 100MB + 30 + + +``` + +--- + +## 十四、常见问题处理 + +### 14.1 Bean名称冲突 + +多模块配置类避免冲突: + +```java +// 错误:多个模块都有 RedisConfig +@Configuration +public class RedisConfig { } + +// 正确:添加模块前缀 +@Configuration +public class GatewayRedisConfig { } // Gateway专用 +``` + +### 14.2 WebFlux与Servlet冲突 + +Gateway作为WebFlux应用,不能使用Servlet API: + +```java +// 错误:Gateway中使用Servlet API +public class TokenAuthFilter implements Filter { + public void doFilter(ServletRequest request, ServletResponse response) { } +} + +// 正确:Gateway使用WebFlux +public class TokenAuthFilter implements GlobalFilter { + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { } +} +``` + +### 14.3 Nacos服务发现失败 + +确保pom.xml包含依赖: + +```xml + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + +``` + +--- + +## 十五、附录 + +### 15.1 环境变量 + +| 变量名 | 说明 | 默认值 | +|--------|------|--------| +| `TENANT_ID` | 租户ID | - | +| `MYSQL_HOST` | MySQL地址 | localhost | +| `MYSQL_PORT` | MySQL端口 | 3306 | +| `REDIS_HOST` | Redis地址 | localhost | +| `NACOS_ADDR` | Nacos地址 | localhost:8848 | + +### 15.2 访问地址 + +| 服务 | 地址 | +|------|------| +| 管理后台 | http://localhost:3000 | +| API网关 | http://localhost:8000 | +| Nacos控制台 | http://localhost:8048/nacos | + +### 15.3 默认账号 + +| 系统 | 用户名 | 密码 | +|------|--------|------| +| Nacos | nacos | nacos | +| 管理后台 | admin | 123456 | + +--- + +**文档结束**