2026-05-27 19:01:30 +08:00

311 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: likei-dev
description: Likei Services 项目开发 Skill。接到任何功能需求、Bug 修复、重构任务时触发。执行完整的「需求分析 → 读文件 → 编码 → 提交 → Review → 修复循环 → 汇总」工作流,直到代码无问题为止。适用于 rc-service-other、rc-service-wallet、rc-service-order、rc-auth、rc-inner-api 等模块的开发工作。
---
# Likei Services 开发 Skill
## 核心工作流(每次接到需求必须严格按此顺序执行)
```
1. 读文件 → 理解现有结构和上下文
2. 设计方案 → 列出改动文件、核心思路,询问用户是否同意,等待确认后再继续
3. 编码 → 按规范写代码
4. git add → 暂存变更(指定文件,禁止 git add .
5. git commit → 提交(默认不 push除非用户明确要求
6. git show → diff review逐文件检查
7. 发现问题? → 修复 → 追加 commit → 再次 review
8. 无问题 → 输出汇总,询问是否 push
```
**循环终止条件**git diff review 所有文件均无逻辑漏洞、无原逻辑改动、无字段错误、无 NPE 风险。
> **数据库变更规则**:设计方案中若涉及 MySQL 表结构变更(新增字段、修改索引等)或 MongoDB 索引变更,必须在方案里直接给出可执行的 SQL / MongoDB Shell 语句,不能只描述变更内容。
---
## 第一步:读文件(禁止跳过)
接到需求后,**先读,不要直接写代码**。
### 必读文件
- 需求涉及的所有现有业务文件Controller / ServiceImpl / Cmd / CO 等)
- 同模块至少一个 peer 文件,用于对齐命名和代码风格
- 涉及对接文档时,仔细比对每个字段
### 按需读取的规范文档
| 场景 | 文档 |
|------|------|
| 工具类、Redis key、MongoDB 操作 | `D:\workspace\likei-services\项目工具类说明.md` |
| DDD 分层、模块结构 | `D:\workspace\likei-services\OTHER模块DDD架构说明.md` |
| 排行榜 season/cycle 相关 | `D:\workspace\likei-services\ranking-season-cycle.md` |
读完后先说明:**要改哪些文件、改什么**,再动手编码。
---
## 第二步:编码规范
### 分层架构(严格遵守,禁止跨层调用)
```
Controllerother-adapter
↓ 只调用 Service 接口
ServiceImplother-application
↓ 只调用 CmdExe / Gateway / DatabaseService
CmdExe / Gatewayother-application / other-infrastructure
DAO / MongoTemplate / Redisother-infrastructure
```
### 文件路径速查other 模块)
| 类型 | 路径模板 |
|------|----------|
| Controller | `other-adapter/src/main/java/com/red/circle/other/adapter/app/{模块}/` |
| Service 接口 | `other-client/src/main/java/com/red/circle/other/app/service/{模块}/` |
| Cmd | `other-client/src/main/java/com/red/circle/other/app/dto/cmd/{模块}/` |
| CO | `other-client/src/main/java/com/red/circle/other/app/dto/clientobject/{模块}/` |
| CmdExe | `other-application/src/main/java/com/red/circle/other/app/command/{模块}/` |
| QryExe | `other-application/src/main/java/com/red/circle/other/app/command/{模块}/query/` |
| ServiceImpl | `other-application/src/main/java/com/red/circle/other/app/service/{模块}/` |
| DatabaseService | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/` |
| DAO | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/` |
| Entity | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/` |
| Redis Key 枚举 | `other-infrastructure/src/main/java/com/red/circle/other/infra/database/cache/key/{模块}/` |
| Inner API 接口 | `rc-inner-api/other-inner/other-inner-api/endpoint/{模块}/` |
| Inner Endpoint 实现 | `other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/{模块}/` |
### 命名规范
| 类型 | 命名规则 |
|------|----------|
| Controller | `{功能}RestController` |
| Service 接口 | `{功能}Service` |
| ServiceImpl | `{功能}ServiceImpl` |
| CmdExe | `{功能}CmdExe``{功能}Exe` |
| QryExe | `{功能}QryExe` |
| Cmd写操作入参 | `{功能}Cmd` |
| CO读操作返回 | `{功能}CO` |
| DAO | `{实体名}DAO`,继承 `BaseDAO<T>` |
### 注解规范
```java
// Cmd / CO / DTO@Data需要时加 @Builder @NoArgsConstructor @AllArgsConstructor
// 校验注解jakarta.validation.constraints.*(禁止用 javax.validation
// 注入方式:@RequiredArgsConstructor构造器注入禁止 @Autowired 字段注入)
// 日志:@Slf4j查询接口不加 log.info只在关键业务节点记录
// 事务:@Transactional 只加在 public 方法,不加在 private 方法Spring AOP 限制)
// API 文档:@eo.name / @eo.url / @eo.method不使用 Swagger 注解)
// 作者:@author tf
// 分页查询 Cmd继承 PageQueryCmd不手写分页参数
// 写操作 Cmd需要时继承 AppExtCommand含 reqUserId 等公共字段)
```
### 常用外部工具类(外部 jar禁止在项目中搜索源码
| 类名 | 包路径 | 用途 |
|------|--------|------|
| `RedisService` | `com.red.circle.component.redis.service.RedisService` | Redis含 setIfAbsent/increment/expire |
| `IdWorkerUtils` | `com.red.circle.tool.core.sequence.IdWorkerUtils` | 雪花 IDgetId()/getIdStr() |
| `ZonedDateTimeUtils` | `com.red.circle.other.infra.utils.ZonedDateTimeUtils` | Riyadh 时区工具 |
| `ZonedId` | `com.red.circle.tool.core.date.ZonedId` | 时区枚举ASIA_RIYADH / ASIA_SHANGHAI |
| `ArithmeticUtils` | `com.red.circle.tool.core.num.ArithmeticUtils` | 金额计算 |
| `AppExtCommand` | `com.red.circle.common.business.dto.cmd.AppExtCommand` | Cmd 基类 |
| `PageQueryCmd` | `com.red.circle.common.business.dto.PageQueryCmd` | 分页查询基类 |
| `PageResult` | `com.red.circle.framework.dto.PageResult` | 分页结果封装 |
### 关键业务规则
- **时区**:所有时间统计和调度使用 Asia/Riyadh
- **AR 分区判断**:使用 `RegionConstants.AR_REGION_IDS`,分区值为 `"AR"``"OTHER"`
- **Integer 比较**:用 `Objects.equals()``Integer.valueOf(x).equals(y)`,禁止 `==`
- **MQ createTime**:发送时设为 `new Date()`,不用业务时间戳
- **RocketMQ 幂等 key**:在业务执行**成功后**写入 Redis不能在执行前
- **金额**:使用 `PennyAmount`(以分为单位),展示时用 `getDollarAmount()`
- **Response 空检查**调用外部服务walletGoldClient / authClient 等)后必须判断 `isSuccess()``getBody() != null`
### 编码完成后自检清单
- [ ] 命名清晰,无 a、b、tmp 等无意义变量
- [ ] 无跨层调用
- [ ] 所有外部服务返回值有空检查
- [ ] Integer / Long 比较未使用 `==`
- [ ] 金额操作有幂等保护bizNo / requestId / orderId
- [ ] 幂等标记在业务成功后写入
- [ ] 关键业务有 `@Transactional`public 方法)
- [ ] 异常信息有意义,不直接 `new RuntimeException("error")`
- [ ] 新代码未破坏原有逻辑
---
## 第三步git 操作
### 环境信息
```
git 可执行文件D:\datasource\git\bin\git.exe
项目根目录: D:\workspace\likei-services
工作范围: D:\workspace\likei-services 及其子目录(禁止操作父目录)
```
### 标准命令模板
```cmd
# add指定文件路径禁止 git add .
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services add {相对路径1} {相对路径2}
# 查看状态
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services status
# 查看最近提交
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -5
# diff review必须用 git show不用 git diff HEAD
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services show {hash}
# push
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services push origin {branch}
```
### commit 命令(必须用 PowerShell避免中文解析失败
```powershell
& 'D:\datasource\git\bin\git.exe' -C 'D:\workspace\likei-services' commit -m 'message in english'
```
> commit 后 PowerShell 输出不稳定,**不能直接从 commit 输出中读取 hash**。commit 完成后立即用以下命令确认:
> ```cmd
> D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -1
> ```
### commit message 规范(英文,禁止中文)
| 类型 | 格式 |
|------|------|
| 新功能 | `feat: add xxx` |
| Bug 修复 | `fix: xxx null check` |
| 重构 | `refactor: extract xxx` |
| 配置变更 | `chore: update xxx config` |
---
## 第四步Review 检查项git show 后必须逐文件核对)
### 字段映射
- Cmd 字段与对接文档/需求是否**完全一致**,无遗漏
- CO / 响应字段与文档是否一致
- `@JsonProperty` 是否正确处理下划线命名(如 `game_infos`
- 类型是否正确(`Integer` vs `Long``int` vs `long`
### 原逻辑保护
- 原有业务流程(广播、排行榜、任务、日志等)是否完整保留
- 重构时条件判断位置移动是否导致行为变化(如 type 判断从方法内移到方法外)
- 注释掉的代码是否被意外删除
- 原有 error log 是否被移除
### 空指针防御
- 外部服务返回值是否有 `isSuccess()` + `getBody() != null` 双重检查
- `Integer` / `Long` 类型是否用了 `==` 比较(必须用 `Objects.equals`
- `Optional` 链是否有 `.orElse()` 兜底
- 外部接口返回的集合类型为 `Collection` 时,调用 `subList` / `sort` / `indexOf``List` 专有方法前必须先转为 `new ArrayList<>(collection)`
### 幂等与并发
- `changeBalance` / 余额变动类接口是否有幂等保护Redis `setIfAbsent` 或 requestId 标记)
- 幂等标记是否在钱包调用**成功后**写入(不是之前)
- 幂等 TTL 是否合理(建议 ≥ 600s
- 重复请求命中幂等时的返回值是否正确
### 架构合规
- 业务逻辑是否在正确的层Controller 不写逻辑Infrastructure 不写业务)
- 是否有跨层调用
- 公共逻辑是否抽到合适的位置(如 `GameEventService`
### 发现问题时的处理流程
1. 明确说明:哪个文件、哪行、什么问题、为什么
2. 直接修复代码,不只是建议
3. `git add` 修改的文件
4. 追加 commitmessage 说明修复内容)
5. 再次 `git show` review确认问题消失
6. 重复直到所有问题清零
---
## 第五步汇总输出Review 无问题后输出)
```markdown
## 本次变更汇总
### 涉及文件
| 文件 | 操作 | 变更内容 |
|------|------|----------|
| XxxController.java | 修改 | 错误码对齐 v4 协议 |
| XxxCmd.java | 新增 | v4 请求字段定义 |
### 关键逻辑说明
- ...
### Commits
- {hash} {message}
- {hash} {message}
### Review 结论
✅ 字段映射完整,与文档一致
✅ 原有业务逻辑完整保留
✅ 外部服务返回值均有空检查
✅ Integer 比较已用 Objects.equals
✅ 幂等保护正常TTL 合理
✅ 架构分层合规,无跨层调用
```
然后询问用户:**是否需要 push 到远端?**
---
## 附:常见问题处理
### 新建文件 vs 编辑文件
- **新建文件**:必须用 `Filesystem:write_file``edit_file` 只能操作已存在的文件,对新路径会报 ENOENT。
- **编辑已有文件**:优先用 `Filesystem:edit_file`;遇到编码匹配失败时改用 `Desktop Commander:write_file`rewrite 模式,超过 30 行分块写入)。
### git commit 报错cmd 下 -m 后内容被拆分为多个参数)
**根本原因**:在 cmd 下直接执行 `git commit -m "message with spaces"`cmd 会将双引号内的空格当作参数分隔符,导致 message 被拆成多个 pathspec 参数报错。无论是否含中文,只要 message 含空格就会出错。
**正确做法(必须严格遵守)**
1. add 用 cmd + 完整 git 路径 + `-C` 指定仓库:
```cmd
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services add {相对路径}
```
2. commit **必须**切换到 PowerShell用单引号包裹 message且只用英文
```powershell
& 'D:\datasource\git\bin\git.exe' -C 'D:\workspace\likei-services' commit -m 'feat: add xxx'
```
3. commit 完成后用 cmd 确认 hash
```cmd
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services log --oneline -1
```
**禁止行为**
- ❌ 禁止在 cmd 下执行 `git commit -m "有空格的message"`
- ❌ 禁止用 `cd /d xxx && git commit`PATH 中的 git 不保证可用)
- ❌ 禁止省略 `-C D:\workspace\likei-services`(依赖 cwd 不可靠)
- ✅ commit message 必须用中文PowerShell 单引号包裹中文没有问题
### git show 无输出exit 0
说明 hash 是最新提交HEAD 和它相同,改用:
```cmd
D:\datasource\git\bin\git.exe -C D:\workspace\likei-services show {完整hash}
```
### 搜索 Java 文件
使用 `Filesystem:search_files`,必须加 `excludePatterns: ["target"]` 排除构建产物。
### 批量读文件
优先用 `Filesystem:read_multiple_files` 一次读多个,减少工具调用轮次。
### 新目录下创建文件
先用 `Filesystem:create_directory` 建目录,再写文件;`impl` 子目录不会自动创建。
### 文件超长(>100 行)需要写入
`Desktop Commander:write_file` 分块写:首块 `mode: rewrite`,后续块 `mode: append`,每块不超过 30 行。