diff --git a/.gitignore b/.gitignore index a65ef9dd..33a4bc7e 100644 --- a/.gitignore +++ b/.gitignore @@ -93,4 +93,3 @@ target/ .DS_Store devops-monitor-id_rsa.key -/claude/ diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 97f78763..00000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# red-circle-service - -#### Description -服务后台 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/claude/ai-context/ARCHITECTURE.md b/claude/ai-context/ARCHITECTURE.md new file mode 100644 index 00000000..bc766a54 --- /dev/null +++ b/claude/ai-context/ARCHITECTURE.md @@ -0,0 +1,93 @@ +# 架构说明 + +## 一、子服务内部分层(DDD + CQRS) + +每个子服务(如 rc-service-other)都遵循以下固定分层: + +``` +{service}-adapter # 适配层:Controller,对外 REST API +{service}-application # 应用层:ServiceImpl、CmdExe、QryExe、Manager、Scheduler +{service}-client # 客户端接口层:Service 接口、Cmd、CO、枚举 +{service}-domain # 领域层:Entity、领域服务接口(纯业务,无框架依赖) +{service}-infrastructure # 基础设施层:DAO、DatabaseService、Gateway、缓存、MQ +{service}-inner-endpoint # 内部服务端点:供其他微服务 Feign 调用的实现 +{service}-start # 启动模块:Spring Boot 入口、application.yml +``` + +--- + +## 二、层次调用链 + +``` +HTTP 请求 + ↓ +Controller(adapter) + ↓ +ServiceImpl(application) + ↓ +CmdExe / QryExe(application) + ↓ 简单场景 ↓ 复杂场景 +DatabaseService Gateway(封装锁+缓存+多数据源) + ↓ ↓ + DAO DAO / Redis / MongoDB +``` + +**强制规则**: +- Controller 只调用 Service +- Service 只调用 CmdExe/QryExe +- CmdExe 可直接调用 DatabaseService(简单)或 Gateway(复杂) +- 禁止跨层调用 + +--- + +## 三、跨服务调用(Feign) + +``` +调用方服务 + └── 注入 Feign 客户端(来自 rc-inner-api/{service}-inner/{service}-inner-api) + +rc-inner-api/ +└── {service}-inner/ + ├── {service}-inner-api/ # Feign 接口定义(endpoint 包) + ├── {service}-inner-model/ # 传输数据模型(model 包) + └── (实现在 {service}-inner-endpoint 子服务中) +``` + +--- + +## 四、文件路径速查(以 other 服务为例) + +| 文件类型 | 路径 | +|---------|------| +| Controller | `other-adapter/src/.../adapter/app/{模块}/` | +| Service 接口 | `other-client/src/.../app/service/{模块}/` | +| Cmd / QryCmd | `other-client/src/.../app/dto/cmd/{模块}/` | +| CO(返回对象) | `other-client/src/.../app/dto/clientobject/{模块}/` | +| CmdExe | `other-application/src/.../app/command/{模块}/` | +| QryExe | `other-application/src/.../app/command/{模块}/query/` | +| ServiceImpl | `other-application/src/.../app/service/{模块}/` | +| Manager | `other-application/src/.../app/manager/{模块}/` | +| Gateway 接口+实现 | `other-infrastructure/src/.../infra/gateway/{模块}/` | +| DAO | `other-infrastructure/src/.../infra/database/rds/dao/` | +| Entity | `other-infrastructure/src/.../infra/database/rds/entity/` | +| DatabaseService | `other-infrastructure/src/.../infra/database/rds/service/` | +| MongoDB | `other-infrastructure/src/.../infra/database/mongo/` | +| Cache | `other-infrastructure/src/.../infra/database/cache/` | +| Inner API 接口 | `rc-inner-api/other-inner/other-inner-api/endpoint/{模块}/` | +| Inner Model | `rc-inner-api/other-inner/other-inner-model/model/{模块}/` | +| Inner 实现 | `other-inner-endpoint/src/.../app/inner/service/{模块}/` | + +--- + +## 五、常见功能模块目录名 +`user` / `room` / `activity` / `game` / `family` / `gift` / `task` / `material` / `ranking` / `vip` + +--- + +## 六、Gateway 使用原则 + +**需要 Gateway 的场景**:分布式锁、缓存+DB 双写、多数据源聚合、复杂事务协调 + +**不需要 Gateway 的场景**:简单 CRUD、单表查询、无缓存的简单操作 + +**原则:简单直接,复杂封装,不过度设计** diff --git a/claude/ai-context/CODING_STYLE.md b/claude/ai-context/CODING_STYLE.md new file mode 100644 index 00000000..d5258873 --- /dev/null +++ b/claude/ai-context/CODING_STYLE.md @@ -0,0 +1,244 @@ +# 编码风格规范 + +## 一、命名规范 + +| 类型 | 命名规则 | 示例 | +|------|---------|------| +| Controller | `{功能}RestController` | `LotteryActivityRestController` | +| Service 接口 | `{功能}Service` | `LotteryActivityRestService` | +| Service 实现 | `{功能}ServiceImpl` | `LotteryActivityRestServiceImpl` | +| 写操作执行器 | `{功能}CmdExe` 或 `{功能}Exe` | `LotteryDrawExe` | +| 查询执行器 | `{功能}QryExe` | `LotteryRecordQryExe` | +| 写命令 | `{功能}Cmd` | `LotteryDrawCmd` | +| 查询命令 | `{功能}QryCmd` | `LotteryRecordQryCmd` | +| 返回对象 | `{功能}CO` | `LotteryDrawResultCO` | +| DAO | `{实体名}DAO` | `LotteryTicketDAO` | +| Entity | `{实体名}` | `LotteryTicket` | +| 数据库服务 | `{功能}DatabaseService` | `LotteryActivityDatabaseService` | +| Gateway | `{功能}Gateway` + `{功能}GatewayImpl` | `LotteryActivityGateway` | + +--- + +## 二、Controller 规范 + +```java +/** + * 功能说明. + * + * @author xxx + * @eo.api-type http + * @eo.groupName 模块名.子模块名 + * @eo.path /模块/资源 + */ +@RestController +@RequestMapping(value = "/user/user-profile", produces = MediaType.APPLICATION_JSON_VALUE) +@RequiredArgsConstructor +public class UserProfileRestController extends BaseController { + + private final UserProfileService userProfileService; + + /** + * 接口说明. + * + * @eo.name 接口名称 + * @eo.url /具体路径(GET 无路径时留空) + * @eo.method get/post/put/delete + * @eo.request-type formdata(GET)/ json(POST/PUT) + */ + @GetMapping + public UserProfileDTO getProfile(UserProfileQryCmd cmd) { + return userProfileService.getUserProfile(cmd); + } + + @PostMapping("/draw") + public LotteryDrawResultCO draw(@RequestBody @Validated LotteryDrawCmd cmd) { + return lotteryService.draw(cmd); + } +} +``` + +**关键点**: +- 继承 `BaseController` +- `@RequiredArgsConstructor`(构造器注入) +- API 文档用 `@eo.` 注解,不用 Swagger +- GET 请求参数直接用 Cmd 对象接收(无 `@RequestBody`) +- POST/PUT 用 `@RequestBody @Validated` + +--- + +## 三、Cmd / CO 规范 + +```java +// 写命令 - 继承 AppExtCommand(包含 reqUserId 等公共字段) +@Data +public class LotteryDrawCmd extends AppExtCommand { + @NotNull + private Long activityId; + + @Min(1) @Max(10) + private Integer drawCount; +} + +// 查询命令 - 分页继承 PageQueryCmd +@Data +public class LotteryRecordQryCmd extends PageQueryCmd { + private Long activityId; +} + +// 返回对象 +@Data +public class LotteryDrawResultCO { + private Long prizeId; + private String prizeName; +} +``` + +**规则**: +- 校验注解用 `jakarta.validation.constraints.*`(不用 javax) +- Cmd 需要用户身份时继承 `AppExtCommand`,通过 `cmd.getReqUserId()` 获取当前用户 + +--- + +## 四、Service / CmdExe 规范 + +```java +// ServiceImpl - 门面,调用 CmdExe +@Service +@RequiredArgsConstructor +@Slf4j +public class LotteryActivityRestServiceImpl implements LotteryActivityRestService { + private final LotteryDrawExe lotteryDrawExe; + private final LotteryRecordQryExe recordQryExe; + + @Override + public LotteryDrawResultCO draw(LotteryDrawCmd cmd) { + return lotteryDrawExe.execute(cmd); + } +} + +// CmdExe - 核心业务逻辑 +@Component +@RequiredArgsConstructor +@Slf4j +public class LotteryDrawExe { + private final LotteryActivityDatabaseService lotteryDbService; + + @Transactional + public LotteryDrawResultCO execute(LotteryDrawCmd cmd) { + // 1. 参数校验 + // 2. 业务逻辑 + // 3. 记录日志 + log.info("用户抽奖: userId={}, activityId={}", cmd.getReqUserId(), cmd.getActivityId()); + // 4. 返回结果 + } +} +``` + +--- + +## 五、Infrastructure 规范 + +```java +// DAO - 继承 BaseDAO +public interface LotteryTicketDAO extends BaseDAO {} + +// DatabaseService - 简单场景直接用 +@Service +@RequiredArgsConstructor +public class LotteryActivityDatabaseService { + private final LotteryTicketDAO ticketDAO; + + public void consumeTicket(Long userId, Long activityId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(Objects.nonNull(userId), LotteryTicket::getUserId, userId) + .eq(Objects.nonNull(activityId), LotteryTicket::getActivityId, activityId); + // ... + } +} + +// Gateway - 复杂场景:锁 + 缓存 + 多数据源 +@Component +@RequiredArgsConstructor +public class LotteryActivityGatewayImpl implements LotteryActivityGateway { + private final LotteryTicketDAO ticketDAO; + private final RedisTemplate redisTemplate; + + @Override + public void consumeTicketWithLock(Long userId, Long activityId) { + String lockKey = "lottery:lock:" + userId; + // 分布式锁 + DB 操作 + 缓存更新 + } +} +``` + +--- + +## 六、通用代码规范 + +### 条件判断 +```java +// ✅ +if (StringUtils.isNotBlank(name)) { ... } +if (Objects.nonNull(userId)) { ... } + +// ❌ +if (name != null && !name.isEmpty()) { ... } +if (userId != null) { ... } +``` + +### 金额 +```java +// ✅ +BigDecimal amount = new BigDecimal("100.00"); +BigDecimal total = a.add(b); + +// ❌ 禁止 +double amount = 100.00; +``` + +### 返回分页 +```java +return PageResult.of(records, total, cmd.getPageNum(), cmd.getPageSize()); +``` + +### 异常 +```java +// ✅ +throw new BusinessException("抽奖券不足"); + +// ❌ +throw new RuntimeException("抽奖券不足"); +``` + +### Redis Key 规范 +``` +缓存: {module}:{entity}:{id} user:info:10001 +排行榜: ranking:{type}:{period}:{date} ranking:send_gift:day:20240101 +分布式锁: {module}:lock:{bizId} coin:lock:10001 +``` + +--- + +## 七、新功能开发顺序(黄金路径) + +1. 定义 Cmd / CO(other-client) +2. 定义 Service 接口(other-client) +3. 实现 CmdExe(other-application) +4. 实现 ServiceImpl(other-application) +5. 创建 Controller(other-adapter) +6. 按需创建 DatabaseService 或 Gateway(other-infrastructure) +7. 如需跨服务调用,添加 Inner API + +--- + +## 八、质量检查清单 + +- [ ] 命名清晰,无 a/b/temp 类命名 +- [ ] 参数校验(`@Validated`、`@NotNull`) +- [ ] 写操作有 `@Transactional` +- [ ] 金额操作有幂等性保障(bizNo) +- [ ] 并发场景有分布式锁 +- [ ] 关键操作有 `log.info` / `log.error` +- [ ] 业务异常用 `BusinessException` +- [ ] 无魔法值(常量或枚举) +- [ ] 分页查询用 `PageResult` diff --git a/claude/ai-context/CONTEXT.md b/claude/ai-context/CONTEXT.md new file mode 100644 index 00000000..52adae57 --- /dev/null +++ b/claude/ai-context/CONTEXT.md @@ -0,0 +1,52 @@ +# likei-services 项目上下文 + +## 项目概述 +社交娱乐平台,核心服务为 `rc-service`(多子服务),约 1000 DAU,运行于 AWS EKS。 +前端通过 REST API 调用;微服务之间通过 Feign(Inner API)调用。 + +--- + +## 技术栈 +| 类型 | 技术 | +|------|------| +| 框架 | Spring Boot,DDD + CQRS | +| ORM | MyBatis-Plus,`BaseDAO` | +| 数据库 | MySQL、MongoDB、Redis | +| 消息队列 | RocketMQ(部分模块用 RabbitMQ) | +| 服务间调用 | Spring Cloud Feign | +| 配置/注册 | Nacos | +| 基础设施 | AWS EKS(Kubernetes) | +| 校验 | `jakarta.validation.constraints.*`(非 javax) | +| 文档 | `@eo.` 注解系列(非 Swagger) | + +--- + +## 子服务清单 +| 子服务 | 说明 | +|--------|------| +| rc-service-other | 综合业务:用户、房间、家族、礼物、活动、任务等 | +| rc-service-live | 直播相关 | +| rc-service-wallet | 钱包、金币、支付 | +| rc-service-order | 订单 | +| rc-service-console | 管理后台接口 | +| rc-service-external | 对外开放接口 | +| rc-auth | 认证授权 | +| rc-gateway | Spring Cloud Gateway 网关 | +| rc-scheduling | 定时任务 | +| rc-service-game | 游戏子服务(百顺、灵仙等) | + +--- + +## 核心编码规范(速查) +- 条件判断:`StringUtils.isNotBlank()` / `Objects.nonNull()` +- 查询构造:`LambdaQueryWrapper`,禁止字符串字段名 +- 金额:`BigDecimal`,禁止 `float` / `double` +- 时间:`LocalDateTime` / `LocalDate` +- 返回值:统一 `Result` 或 `PageResult` +- 异常:`throw new BusinessException("...")` +- 注入:`@RequiredArgsConstructor`(构造器注入),禁止 `@Autowired` 字段注入 +- 日志:`@Slf4j`,关键操作必须 log +- 事务:写操作必须 `@Transactional` + +> 详细规范见 CODING_STYLE.md +> 架构分层与调用链见 ARCHITECTURE.md diff --git a/claude/api/_TEMPLATE.md b/claude/api/_TEMPLATE.md new file mode 100644 index 00000000..b0636553 --- /dev/null +++ b/claude/api/_TEMPLATE.md @@ -0,0 +1,92 @@ +# API 接口文档模板 + +> 复制此文件,命名为 {module}-api.md,记录该模块对外暴露的 REST 接口。 + +--- + +## 模块信息 +- **模块名**:{模块中文名} / {module} +- **Controller**:`{功能}RestController` +- **@eo.groupName**:`{一级模块}.{二级模块}` +- **@eo.path(base)**:`/{模块}/{资源}` +- **文件路径**:`other-adapter/src/.../adapter/app/{模块}/{功能}RestController.java` + +--- + +## 接口列表 + +### 1. {接口名称} + +```java +/** + * {接口说明}. + * + * @eo.name {接口名称} + * @eo.url {子路径,GET无子路径时留空} + * @eo.method get + * @eo.request-type formdata + */ +@GetMapping("/{sub-path}") +public {返回CO或DTO} {methodName}({QryCmd} cmd) { + return {service}.{method}(cmd); +} +``` + +**请求参数(QryCmd 字段)**: +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| userId | Long | 否 | 目标用户ID(不传则取当前登录用户) | + +**响应(CO 字段)**: +| 字段 | 类型 | 说明 | +|------|------|------| +| userId | Long | 用户ID | +| nickname | String | 昵称 | + +--- + +### 2. {写操作接口名称} + +```java +/** + * {接口说明}. + * + * @eo.name {接口名称} + * @eo.url /{sub-path} + * @eo.method post + * @eo.request-type json + */ +@PostMapping("/{sub-path}") +public {返回CO} {methodName}(@RequestBody @Validated {Cmd} cmd) { + return {service}.{method}(cmd); +} +``` + +**请求体(Cmd 字段)**: +| 字段 | 类型 | 必填 | 校验 | 说明 | +|------|------|------|------|------| +| activityId | Long | 是 | @NotNull | 活动ID | +| drawCount | Integer | 否 | @Min(1) @Max(10) | 抽奖次数 | + +**响应(CO 字段)**: +| 字段 | 类型 | 说明 | +|------|------|------| +| prizeId | Long | 奖品ID | +| prizeName | String | 奖品名称 | + +--- + +## 枚举值说明 + +| 枚举类 | 值 | 说明 | +|-------|----|------| +| StatusEnum | 0 | 正常 | +| StatusEnum | 1 | 禁用 | + +--- + +## 关联文件 +- Service 接口:`other-client/src/.../app/service/{模块}/{功能}Service.java` +- Cmd:`other-client/src/.../app/dto/cmd/{模块}/` +- CO:`other-client/src/.../app/dto/clientobject/{模块}/` +- CmdExe:`other-application/src/.../app/command/{模块}/` diff --git a/claude/likei-services.md b/claude/likei-services.md new file mode 100644 index 00000000..3057c4fe --- /dev/null +++ b/claude/likei-services.md @@ -0,0 +1,688 @@ +# Other 模块 DDD 架构说明文档 + +## 一、模块概览 + +Other 服务是一个综合性的业务模块,包含用户、房间、游戏、活动、家族、礼物、任务等多个子领域。采用标准的 DDD(领域驱动设计)+ CQRS 架构模式。 + +### 模块列表 + +``` +rc-service-other/ +├── other-domain # 领域层(核心业务实体) +├── other-infrastructure # 基础设施层(数据访问、外部服务) +├── other-client # 客户端接口层(DTO、Service接口) +├── other-application # 应用层(业务逻辑实现) +├── other-adapter # 适配层(REST API、Controller) +├── other-inner-endpoint # 内部服务端点(跨服务调用实现) +└── other-start # 启动模块(Spring Boot入口) +``` + +--- + +## 二、各模块详细说明 + +### 1. other-domain(领域层) +**作用**:定义核心领域模型和业务规则 +**依赖**:无外部依赖(最纯净的业务模型) +**路径**:`other-domain/src/main/java/com/red/circle/other/domain/` + +**职责**: +- 定义领域实体(Entity) +- 定义值对象(Value Object) +- 定义领域服务接口 +- 不包含任何基础设施相关代码 + +**典型文件**: +- 领域实体定义 +- 业务规则封装 + +--- + +### 2. other-infrastructure(基础设施层) +**作用**:提供技术基础设施支持 +**依赖**:`other-domain`、框架组件(MyBatis、Redis、MongoDB、RocketMQ) +**路径**:`other-infrastructure/src/main/java/com/red/circle/other/infra/` + +**目录结构**: +``` +infra/ +├── database/ # 数据访问 +│ ├── rds/ # MySQL 数据库 +│ │ ├── dao/ # MyBatis DAO(继承BaseDAO) +│ │ ├── entity/ # 数据库实体 +│ │ ├── service/ # 数据库服务封装 +│ │ └── query/ # 查询条件构建 +│ ├── mongo/ # MongoDB 数据库 +│ └── cache/ # Redis 缓存 +├── gateway/ # 网关实现(可选) +├── convertor/ # 对象转换器 +├── config/ # 配置类 +└── utils/ # 工具类 +``` + +**关键说明**: +- **DAO 命名规范**:`{实体名}DAO`,继承 `BaseDAO` +- **Service 命名规范**:`{功能}DatabaseService` +- **不是所有功能都需要 Gateway**,简单功能直接在 CmdExe 中调用 Infrastructure 的接口 + +--- + +### 3. other-client(客户端接口层) +**作用**:定义对外暴露的接口和数据模型 +**依赖**:无 +**路径**:`other-client/src/main/java/com/red/circle/other/app/` + +**目录结构**: +``` +app/ +├── dto/ # 数据传输对象 +│ ├── cmd/ # 命令对象(写操作) +│ │ └── {功能模块}/ +│ └── clientobject/ # 客户端对象(读操作返回值) +│ └── {功能模块}/ +├── service/ # 服务接口定义 +│ └── {功能模块}/ +└── enums/ # 枚举类 +``` + +**命名规范**: +- **Cmd(命令)**:用于写操作,如 `LotteryDrawCmd`、`UserProfileModifyCmd` +- **CO(客户端对象)**:用于读操作返回,如 `LotteryActivityCO`、`UserProfileCO` +- **QryCmd(查询命令)**:用于查询操作,如 `LotteryRecordQryCmd` + +**注解规范**: +- 使用 `@Data` + 文件格式注释 +- Cmd 需要时继承 `com.red.circle.common.business.dto.cmd.AppExtCommand` +- 分页查询继承 `com.red.circle.common.business.dto.PageQueryCmd` +- 校验注解使用 `jakarta.validation.constraints.*`(不用 javax) + +--- + +### 4. other-application(应用层) +**作用**:实现业务逻辑 +**依赖**:`other-client`、`other-infrastructure` +**路径**:`other-application/src/main/java/com/red/circle/other/app/` + +**目录结构**: +``` +app/ +├── command/ # 命令执行器 +│ └── {功能模块}/ +│ ├── {功能}CmdExe.java # 写操作执行器 +│ └── query/ # 查询执行器 +│ └── {功能}QryExe.java +├── service/ # 服务实现 +│ └── {功能模块}/ +│ └── {功能}ServiceImpl.java +├── convertor/ # 对象转换器(MapStruct) +├── listener/ # 事件监听器 +├── scheduler/ # 定时任务 +├── manager/ # 业务管理器(复杂业务编排) +├── common/ # 通用业务逻辑 +└── config/ # 应用配置 +``` + +**核心原则**: +- **ServiceImpl 调用 CmdExe**:ServiceImpl 是门面,具体业务由 CmdExe 实现 +- **CmdExe 命名规范**:`{功能名}CmdExe` 或 `{功能名}QryExe` +- **是否需要 Gateway**: + - ✅ 简单功能:CmdExe 直接调用 Infrastructure 的 DatabaseService + - ✅ 复杂功能:CmdExe 通过 Gateway 封装复杂的数据访问逻辑 + - 原则:**简单直接,复杂封装,不要过度设计** + +**代码质量要求**: +- 关键业务必须添加 `@Transactional` 事务 +- 金额操作必须保证幂等性(使用 bizNo) +- 重要操作记录日志(`@Slf4j`) +- 完善的参数校验和异常处理 + +--- + +### 5. other-adapter(适配层) +**作用**:对外提供 REST API +**依赖**:`other-application` +**路径**:`other-adapter/src/main/java/com/red/circle/other/adapter/app/` + +**目录结构**: +``` +adapter/app/ +└── {功能模块}/ + └── {功能名}RestController.java +``` + +**命名规范**: +- Controller 命名:`{功能名}RestController` +- 继承 `BaseController` +- 使用 `@RestController` + `@RequestMapping` + +**注解规范**: +- API 文档使用 `@eo.` 系列注解(不使用 Swagger) +- 路径规范:`/功能模块/资源`,如 `/activity/lottery` + +**职责**: +- 接收 HTTP 请求 +- 参数校验(`@Validated`) +- 调用 Service 层 +- 返回统一格式的响应 + +--- + +### 6. other-inner-endpoint(内部服务端点) +**作用**:提供跨服务调用的实现(供其他微服务通过 Feign 调用) +**依赖**:`other-application`、`other-inner-api` +**路径**:`other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/` + +**与 other-client 的区别**: +| 维度 | other-client | other-inner-endpoint | +|------|-------------|---------------------| +| 调用方 | 前端 App、Web | 其他微服务(如 wallet、live) | +| 传输协议 | HTTP REST | HTTP Feign | +| 接口定义位置 | `other-client/service/` | `other-inner-api/endpoint/` | +| 接口实现位置 | `other-application/service/` | `other-inner-endpoint/service/` | +| DTO 定义位置 | `other-client/dto/` | `other-inner-model/model/` | + +**典型场景**: +- 钱包服务调用 other 服务获取用户信息 +- 直播服务调用 other 服务更新房间状态 + +--- + +### 7. other-start(启动模块) +**作用**:Spring Boot 应用入口 +**依赖**:`other-adapter`、`other-inner-endpoint` +**路径**:`other-start/src/main/java/com/red/circle/` + +**职责**: +- 定义 Spring Boot 主类 +- 引入所有模块依赖 +- 配置文件(application.yml) + +--- + +## 三、跨模块通信说明 + +### 内部模块调用关系图 +``` +┌─────────────────────────────────────────────────┐ +│ other-start │ +│ (Spring Boot 入口) │ +└────────────┬────────────────────┬────────────────┘ + │ │ + ┌────────▼────────┐ ┌───────▼────────────┐ + │ other-adapter │ │ other-inner-endpoint│ + │ (REST API) │ │ (Feign 服务端) │ + └────────┬────────┘ └───────┬────────────┘ + │ │ + └────────┬───────────┘ + │ + ┌─────────▼──────────┐ + │ other-application │ + │ (业务逻辑层) │ + │ ├── CmdExe │ + │ ├── ServiceImpl │ + │ └── Manager │ + └─────────┬──────────┘ + │ + ┌─────────────┼─────────────┐ + │ │ │ +┌───────▼────────┐ ┌─▼──────────┐ ┌▼──────────┐ +│ other-client │ │ other-infra│ │other-domain│ +│ (接口+DTO) │ │ (数据访问) │ │ (实体) │ +└────────────────┘ └────────────┘ └───────────┘ +``` + +### 跨服务调用说明 + +**场景示例**:钱包服务需要调用 other 服务获取用户信息 + +1. **定义 API 接口**(在 `rc-inner-api/other-inner/other-inner-api/`): +```java +// endpoint 包下定义 Feign 客户端接口 +@FeignClient(name = "other-service") +public interface UserProfileClientService { + UserProfileDTO getByUserId(Long userId); +} +``` + +2. **定义数据模型**(在 `rc-inner-api/other-inner/other-inner-model/`): +```java +// model 包下定义传输对象 +public class UserProfileDTO { + private Long userId; + private String nickname; + // ... +} +``` + +3. **实现服务端点**(在 `other-inner-endpoint/`): +```java +@RestController +public class UserProfileClientServiceImpl implements UserProfileClientService { + @Autowired + private UserProfileService userProfileService; + + public UserProfileDTO getByUserId(Long userId) { + // 调用 application 层服务 + return userProfileService.getByUserId(userId); + } +} +``` + +4. **钱包服务调用**(在 wallet 服务中): +```java +@Service +public class WalletServiceImpl { + @Autowired + private UserProfileClientService userProfileClient; // Feign 客户端 + + public void someMethod() { + UserProfileDTO user = userProfileClient.getByUserId(123L); + } +} +``` + +--- + +## 四、新增功能开发流程 + +### 标准开发顺序(必须遵循) + +以"抽奖活动"为例,演示完整的开发流程: + +#### 1. 定义数据模型(other-client) +``` +other-client/src/main/java/com/red/circle/other/app/dto/ +├── cmd/activity/ +│ ├── LotteryDrawCmd.java # 抽奖命令 +│ └── LotteryRecordQryCmd.java # 查询抽奖记录 +└── clientobject/activity/ + ├── LotteryActivityCO.java # 活动信息 + └── LotteryDrawResultCO.java # 抽奖结果 +``` + +#### 2. 定义 Service 接口(other-client) +```java +// other-client/src/main/java/com/red/circle/other/app/service/activity/ +public interface LotteryActivityRestService { + LotteryDrawResultCO draw(LotteryDrawCmd cmd); + PageResult listMyRecords(LotteryRecordQryCmd cmd); +} +``` + +#### 3. 实现 CmdExe(other-application) +``` +other-application/src/main/java/com/red/circle/other/app/command/activity/ +├── LotteryDrawExe.java # 抽奖执行器 +└── query/ + └── LotteryRecordQryExe.java # 查询执行器 +``` + +**示例代码**: +```java +@Component +@RequiredArgsConstructor +public class LotteryDrawExe { + private final LotteryActivityDatabaseService lotteryDbService; + private final LotteryPrizeGrantService prizeService; + + @Transactional + public LotteryDrawResultCO execute(LotteryDrawCmd cmd) { + // 1. 参数校验 + validateTicket(cmd.getUserId()); + + // 2. 扣除抽奖券(直接调用 Infrastructure 的服务) + lotteryDbService.consumeTicket(cmd.getUserId(), cmd.getActivityId()); + + // 3. 随机抽奖 + LotteryPrize prize = prizeService.randomDraw(cmd.getActivityId()); + + // 4. 记录中奖 + lotteryDbService.saveDrawRecord(cmd.getUserId(), prize); + + // 5. 返回结果 + return convertToResult(prize); + } +} +``` + +#### 4. 实现 ServiceImpl(other-application) +```java +@Service +@RequiredArgsConstructor +public class LotteryActivityRestServiceImpl implements LotteryActivityRestService { + private final LotteryDrawExe lotteryDrawExe; + private final LotteryRecordQryExe recordQryExe; + + @Override + public LotteryDrawResultCO draw(LotteryDrawCmd cmd) { + return lotteryDrawExe.execute(cmd); + } + + @Override + public PageResult listMyRecords(LotteryRecordQryCmd cmd) { + return recordQryExe.query(cmd); + } +} +``` + +#### 5. 创建 Controller(other-adapter) +```java +@RestController +@RequestMapping("/activity/lottery") +@RequiredArgsConstructor +public class LotteryActivityRestController extends BaseController { + private final LotteryActivityRestService lotteryService; + + /** + * 执行抽奖 + * @eo.name 执行抽奖 + * @eo.url /draw + * @eo.method post + */ + @PostMapping("/draw") + public LotteryDrawResultCO draw(@RequestBody @Validated LotteryDrawCmd cmd) { + return lotteryService.draw(cmd); + } +} +``` + +#### 6. 数据访问层(other-infrastructure) + +**简单功能**(直接使用 DAO 和 DatabaseService): +```java +// DAO +public interface LotteryTicketDAO extends BaseDAO {} + +// DatabaseService +@Service +public class LotteryActivityDatabaseService { + @Autowired + private LotteryTicketDAO ticketDAO; + + public void consumeTicket(Long userId, Long activityId) { + // 直接操作数据库 + } +} +``` + +**复杂功能**(使用 Gateway 封装): +```java +// Gateway 接口 +public interface LotteryActivityGateway { + void consumeTicketWithLock(Long userId, Long activityId); +} + +// Gateway 实现 +@Component +public class LotteryActivityGatewayImpl implements LotteryActivityGateway { + @Autowired + private LotteryTicketDAO ticketDAO; + @Autowired + private RedisTemplate redisTemplate; + + @Override + public void consumeTicketWithLock(Long userId, Long activityId) { + // 分布式锁 + 数据库操作 + 缓存更新 + String lockKey = "lottery:lock:" + userId; + // ... 复杂逻辑 + } +} +``` + +#### 7. 跨服务调用(可选) + +如果需要被其他服务调用,创建 Inner API: + +``` +rc-inner-api/other-inner/ +├── other-inner-api/endpoint/activity/ +│ └── LotteryActivityClientService.java # Feign 接口 +├── other-inner-model/model/activity/ +│ └── LotteryDrawDTO.java # 数据模型 +└── other-inner-endpoint/service/activity/ + └── LotteryActivityClientServiceImpl.java # 实现 +``` + +--- + +## 五、文件路径快速参考 + +### 按功能类型查找路径 + +| 文件类型 | 路径模板 | 示例 | +|---------|---------|------| +| **Controller** | `other-adapter/src/main/java/com/red/circle/other/adapter/app/{模块}/` | `activity/LotteryActivityRestController.java` | +| **Service 接口** | `other-client/src/main/java/com/red/circle/other/app/service/{模块}/` | `activity/LotteryActivityRestService.java` | +| **Cmd** | `other-client/src/main/java/com/red/circle/other/app/dto/cmd/{模块}/` | `activity/LotteryDrawCmd.java` | +| **CO** | `other-client/src/main/java/com/red/circle/other/app/dto/clientobject/{模块}/` | `activity/LotteryDrawResultCO.java` | +| **CmdExe** | `other-application/src/main/java/com/red/circle/other/app/command/{模块}/` | `activity/LotteryDrawExe.java` | +| **QryExe** | `other-application/src/main/java/com/red/circle/other/app/command/{模块}/query/` | `activity/query/LotteryRecordQryExe.java` | +| **ServiceImpl** | `other-application/src/main/java/com/red/circle/other/app/service/{模块}/` | `activity/LotteryActivityRestServiceImpl.java` | +| **Gateway** | `other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/{模块}/` | `activity/LotteryActivityGatewayImpl.java` | +| **DAO** | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/` | `LotteryTicketDAO.java` | +| **Entity** | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/` | `LotteryTicket.java` | +| **DatabaseService** | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/` | `LotteryActivityDatabaseService.java` | +| **Inner API** | `rc-inner-api/other-inner/other-inner-api/endpoint/{模块}/` | `activity/LotteryActivityClientService.java` | +| **Inner Model** | `rc-inner-api/other-inner/other-inner-model/model/{模块}/` | `activity/LotteryDrawDTO.java` | +| **Inner Endpoint** | `other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/{模块}/` | `activity/LotteryActivityClientServiceImpl.java` | + +### 按模块查找路径 + +#### 常见功能模块 +- `activity` - 活动相关 +- `user` - 用户相关 +- `room` - 房间相关 +- `game` - 游戏相关 +- `family` - 家族相关 +- `gift` - 礼物相关 +- `task` - 任务相关 +- `material` - 素材/道具相关 + +--- + +## 六、核心开发规范 + +### 1. 命名规范 + +| 类型 | 命名规则 | 示例 | +|------|---------|------| +| Controller | `{功能}RestController` | `LotteryActivityRestController` | +| Service 接口 | `{功能}Service` | `LotteryActivityRestService` | +| Service 实现 | `{功能}ServiceImpl` | `LotteryActivityRestServiceImpl` | +| CmdExe | `{功能}CmdExe` / `{功能}Exe` | `LotteryDrawExe` | +| QryExe | `{功能}QryExe` | `LotteryRecordQryExe` | +| Cmd | `{功能}Cmd` | `LotteryDrawCmd` | +| QryCmd | `{功能}QryCmd` | `LotteryRecordQryCmd` | +| CO | `{功能}CO` | `LotteryDrawResultCO` | +| DAO | `{实体名}DAO` | `LotteryTicketDAO` | +| Entity | `{实体名}` | `LotteryTicket` | +| Gateway | `{功能}Gateway` + Impl | `LotteryActivityGateway` | + +### 2. 注解规范 + +#### DTO 层 +```java +@Data // Lombok +public class LotteryDrawCmd extends AppExtCommand { + @NotNull + private Long activityId; + + @Min(1) + @Max(10) + private Integer drawCount; +} +``` + +#### 分页查询 +```java +@Data +public class LotteryRecordQryCmd extends PageQueryCmd { + private Long activityId; +} +``` + +#### Controller 层 +```java +@RestController +@RequestMapping("/activity/lottery") +@RequiredArgsConstructor // Lombok 构造器注入 +public class LotteryActivityRestController extends BaseController { + + /** + * 执行抽奖 + * @eo.name 执行抽奖 + * @eo.url /draw + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/draw") + public LotteryDrawResultCO draw(@RequestBody @Validated LotteryDrawCmd cmd) { + return lotteryService.draw(cmd); + } +} +``` + +#### Service 层 +```java +@Service +@RequiredArgsConstructor +@Slf4j // 日志 +public class LotteryActivityRestServiceImpl implements LotteryActivityRestService { + + private final LotteryDrawExe lotteryDrawExe; + + @Override + @Transactional // 需要事务的方法 + public LotteryDrawResultCO draw(LotteryDrawCmd cmd) { + log.info("用户抽奖: userId={}, activityId={}", + cmd.getReqUserId(), cmd.getActivityId()); + return lotteryDrawExe.execute(cmd); + } +} +``` + +### 3. 分页返回 + +统一使用 `com.red.circle.framework.dto.PageResult`: + +```java +public PageResult listMyRecords(LotteryRecordQryCmd cmd) { + // 查询数据 + List records = queryRecords(cmd); + // 查询总数 + long total = countRecords(cmd); + + return PageResult.of(records, total, cmd.getPageNum(), cmd.getPageSize()); +} +``` + +### 4. 异常处理 + +使用业务异常,不直接抛出 RuntimeException: + +```java +if (ticket == null) { + throw new BusinessException("抽奖券不足"); +} +``` + +### 5. 事务控制 + +- **写操作**:必须添加 `@Transactional` +- **读操作**:不需要事务 +- **跨服务调用**:考虑分布式事务或最终一致性 + +--- + +## 七、关键设计原则 + +### 1. Gateway 使用原则 + +**何时使用 Gateway**: +- ✅ 需要分布式锁的场景 +- ✅ 需要缓存 + 数据库双写的场景 +- ✅ 需要多个数据源聚合的场景 +- ✅ 需要复杂的事务协调 +- ✅ 业务逻辑复杂,需要封装的场景 + +**何时不用 Gateway**: +- ❌ 简单的 CRUD 操作 +- ❌ 单表查询 +- ❌ 不需要缓存的简单操作 +- ❌ 逻辑简单清晰的场景 + +**原则**:简单直接,复杂封装,避免过度设计 + +### 2. 层次调用原则 + +``` +Controller → Service → CmdExe → Gateway/DatabaseService → DAO +``` + +- Controller 只调用 Service +- Service 只调用 CmdExe +- CmdExe 可直接调用 Infrastructure(简单场景)或通过 Gateway(复杂场景) +- 禁止跨层调用 + +### 3. 代码质量原则 + +参考主项目文档中的质量检查清单: + +- [ ] 命名清晰(避免 a、b、temp) +- [ ] 完整的注释 +- [ ] 参数校验(@Valid、@NotNull) +- [ ] 异常处理 +- [ ] 并发安全(金额操作) +- [ ] 幂等性(bizNo) +- [ ] 事务注解(@Transactional) +- [ ] 关键日志(log.info/error) +- [ ] 性能考虑(N+1、缓存) +- [ ] 安全防护(SQL 注入、XSS) + +--- + +## 八、常见问题 FAQ + +### Q1: 什么时候需要 Gateway? +A: 当业务逻辑涉及多个数据源、分布式锁、缓存同步等复杂场景时使用 Gateway。简单的 CRUD 直接使用 DatabaseService。 + +### Q2: CmdExe 和 ServiceImpl 的区别? +A: ServiceImpl 是门面,负责接口定义和调用编排。CmdExe 是具体的业务逻辑实现。一个 ServiceImpl 可能调用多个 CmdExe。 + +### Q3: 跨服务调用如何实现? +A: 通过 Inner API + Feign。在 `other-inner-api` 定义接口,在 `other-inner-endpoint` 实现,其他服务通过 Feign 客户端调用。 + +### Q4: 如何处理分布式事务? +A: 优先考虑最终一致性(如消息队列)。如果必须强一致,考虑 TCC 或 Saga 模式,但要评估复杂度。 + +### Q5: MongoDB 和 MySQL 如何选择? +A: +- MySQL:强一致性、事务、关系查询 +- MongoDB:高性能、灵活 schema、大数据量统计 + +--- + +## 九、总结 + +### 开发新功能的黄金路径 + +1. ✅ 先定义 DTO(Cmd、CO) +2. ✅ 定义 Service 接口 +3. ✅ 实现 CmdExe(核心业务逻辑) +4. ✅ 实现 ServiceImpl(调用 CmdExe) +5. ✅ 创建 Controller(暴露 API) +6. ✅ 根据需要创建 Gateway 或直接用 DatabaseService +7. ✅ 如需跨服务调用,添加 Inner API + +### 核心理念 + +- **领域驱动**:按业务领域划分模块 +- **分层清晰**:各层职责明确,禁止跨层调用 +- **简单优先**:不过度设计,够用即可 +- **质量第一**:代码清晰、测试完善、文档齐全 + +--- + +**文档版本**:v1.0 +**最后更新**:2025-01-15 +**维护者**:开发团队 \ No newline at end of file diff --git a/claude/modules/_TEMPLATE.md b/claude/modules/_TEMPLATE.md new file mode 100644 index 00000000..cda049ea --- /dev/null +++ b/claude/modules/_TEMPLATE.md @@ -0,0 +1,32 @@ +# 模块文档模板 + +> 复制此文件,重命名为 {module}.md,按实际情况填写 + +## 模块名称 +{模块中文名} / {模块英文名} + +## 功能概述 +> 一句话说明该模块的职责 + +## 核心实体 +| 实体 | 表/集合 | 说明 | +|------|--------|------| +| XxxEntity | t_xxx | ... | + +## 主要功能点 +- [ ] 功能1 +- [ ] 功能2 + +## 关键业务逻辑 +> 描述复杂逻辑、计算规则、状态流转等 + +## 对外接口(供其他模块调用) +```java +// 接口签名 + 说明 +``` + +## 依赖的其他模块 +- 依赖 xxx 模块的 xxx 功能 + +## 已知问题 / 注意事项 +- 注意点1 diff --git a/claude/modules/agency.md b/claude/modules/agency.md new file mode 100644 index 00000000..b17e9026 --- /dev/null +++ b/claude/modules/agency.md @@ -0,0 +1,31 @@ +# 工会/金币代理模块 / agency + +## 功能概述 +工会管理体系,包含工会创建/管理、主播归属、收益分成结算,以及金币代理商管理。 + +## 核心实体 +| 实体 | 表/集合 | 说明 | +|------|--------|------| +| Agency | t_agency | 工会信息 | +| AgencyAnchor | t_agency_anchor | 工会-主播关联 | +| CoinAgent | t_coin_agent | 金币代理商 | +| AgencyIncome | mongo: agency_income | 工会收益流水 | + +## 主要功能点 +- [ ] 工会创建/编辑/解散 +- [ ] 主播加入/退出工会 +- [ ] 工会收益结算(礼物分成) +- [ ] 金币代理商管理 +- [ ] 代理商充值佣金计算 + +## 关键业务逻辑 +- 收益分成比例:平台 / 主播 / 工会,比例可按工会单独配置 +- 主播同一时间只能归属一个工会 +- 代理商有充值额度限制,超额需申请 + +## 依赖的其他模块 +- gift 模块:礼物收益来源 +- bd 模块:BD 管辖工会范围 + +## 注意事项 +- 结算周期为月结,月初定时任务触发上月结算 diff --git a/claude/modules/user.md b/claude/modules/user.md new file mode 100644 index 00000000..46aa1f31 --- /dev/null +++ b/claude/modules/user.md @@ -0,0 +1,29 @@ +# 用户模块 / user + +## 功能概述 +用户基础信息管理,包含注册、登录、主播认证、用户画像。 + +## 核心实体 +| 实体 | 表/集合 | 说明 | +|------|--------|------| +| User | t_user | 用户基础信息 | +| AnchorInfo | t_anchor_info | 主播扩展信息 | +| UserFollow | t_user_follow | 关注关系 | + +## 用户角色 +| 角色 | 说明 | +|------|------| +| 普通用户 | 观看直播、送礼 | +| 主播 | 开播、收礼 | +| 工会长 | 管理工会 | +| 代理商 | 金币代理充值 | + +## 主要功能点 +- [ ] 用户注册/登录(手机号/第三方) +- [ ] 用户信息编辑 +- [ ] 主播申请与认证 +- [ ] 关注/粉丝关系 + +## 注意事项 +- 用户 Token 使用 JWT,存 Redis 做黑名单 +- 用户状态变更(封号/解封)需清除相关缓存 diff --git a/claude/tasks/_TEMPLATE.md b/claude/tasks/_TEMPLATE.md new file mode 100644 index 00000000..98b3c5e7 --- /dev/null +++ b/claude/tasks/_TEMPLATE.md @@ -0,0 +1,47 @@ +# 任务文件模板 + +> 复制此文件到 tasks/current/,命名格式:{YYYYMMDD}-{任务简称}.md +> 任务完成后移动到 tasks/done/ + +--- + +## 任务名称 +{任务名称} + +## 任务类型 +> 勾选对应类型 + +- [ ] 重构/加字段/小改动 +- [ ] 原有功能扩展 +- [ ] 新功能/新模块 +- [ ] 性能/代码优化 +- [ ] Bug 修复 +- [ ] 数据修复/脚本 +- [ ] 跨模块联动 +- [ ] 前后端联调 +- [ ] 基础设施/运维 + +## 涉及模块 +> 列出本次任务涉及的模块,并上传对应 modules/*.md + +- [ ] {module1} +- [ ] {module2} + +## 需求描述 +> 简洁描述要做什么,背景是什么 + +## 关键约束 +> 需要特别注意的边界条件、兼容性要求、性能要求等 + +## 涉及的表/集合 +> 列出会读写的表或集合 + +## 预期产出 +> 接口 / 代码文件 / SQL脚本 / 其他 + +## 完成记录 +> 任务完成后填写,方便归档复盘 + +- 完成时间: +- 改动文件: +- 备注: