Commit 1eddfd64 by Lizh

docs: 添加 /api/v2 全量迁移实现计划(31 个任务)

Co-Authored-By: Claude <noreply@anthropic.com>
parent 7ad10679
# /api/v2 全量迁移 实现计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将 custom-back 中 64 个 `/api/v2` 端点完整迁移到 custom-server,含目录重构
**Architecture:** 5 步执行:目录重构 → 登录鉴权 → RBAC 管理 → ComposeServer → CountryCode+Warehouse。遵循 DDD 分层(Entity→Mapper→DomainService→AppService→Controller),复用已有的 Domain 层基础
**Tech Stack:** Spring Boot 4.0.5, Java 17, MyBatis-Plus 3.5.8, JJWT 0.12.x, BCrypt, Redisson, WebClient
## Global Constraints
- Spring Boot 版本必须是 4.0.5,不允许修改
- 代码注释和日志输出必须使用中文
- 变量名和函数名使用英文,小驼峰命名法
- 响应格式统一使用 `R<T>`,分页使用 MyBatis-Plus `IPage<T>`
- 鉴权使用 `@RequiresPermissions` 注解
- 实体映射使用 `BeanMapper` (Jackson SNAKE_CASE)
- API 前缀使用 `/api/v2/`
- 不重复实现已有功能,直接复用 Domain 层已有的 Entity/Mapper/DomainService
- 不在代码中硬编码密码或密钥
---
## Step 0:目录重构
### 概述
将现有 controller、app/service、domain/service 三层按业务域拆分子包。**仅移动文件 + 修正 package/import,不改变任何逻辑。**
### Task 0.1: Controller 层重构
- [ ] 创建 `custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/product/` 目录
- [ ] 移动 5 个 Controller 到 `product/` 子包(使用 `git mv`
- [ ] 修改每个文件的 package 声明为 `com.jomalls.custom.webapp.controller.product`
- [ ] HealthController 保持不动(`controller/` 顶层)
**移动文件列表**
```
CustomProductInfoController.java → product/CustomProductInfoController.java
CustomProductItemController.java → product/CustomProductItemController.java
ProductTemplateInfoController.java → product/ProductTemplateInfoController.java
SysBillRuleController.java → product/SysBillRuleController.java
LogCustomProductController.java → product/LogCustomProductController.java
```
### Task 0.2: App Service 层重构
- [ ] 创建 `custom-server-app/src/main/java/com/jomalls/custom/app/service/product/impl/` 目录
- [ ] 移动 6 组 AppService(接口 + 实现,共 12 文件)到 `product/` 子包
- [ ] 修改接口 package → `com.jomalls.custom.app.service.product`
- [ ] 修改实现类 package → `com.jomalls.custom.app.service.product.impl`
- [ ] 修正实现类中对接口的 import
- [ ] PermissionService + Impl 保持不动(`service/` 顶层)
**移动文件列表**
```
接口:
CustomProductInfoService.java → product/
CustomProductItemService.java → product/
ProductTemplateInfoService.java → product/
SysBillRuleService.java → product/
LogCustomProductService.java → product/
DiyUserService.java → product/
实现:
impl/CustomProductInfoServiceImpl.java → product/impl/
impl/CustomProductItemServiceImpl.java → product/impl/
impl/ProductTemplateInfoServiceImpl.java → product/impl/
impl/SysBillRuleServiceImpl.java → product/impl/
impl/LogCustomProductServiceImpl.java → product/impl/
impl/DiyUserServiceImpl.java → product/impl/
```
### Task 0.3: Domain Service 层重构
- [ ] 创建 5 个子包目录:`product/impl/`, `diy/impl/`, `system/impl/`, `warehouse/impl/`, `misc/impl/`
- [ ] 移动 33 组(66 文件)到对应子包
**分类清单**
| 目标子包 | 服务 |
|----------|------|
| `product/` | CustomProductInfo, CustomProductItem, CustomProductImage, CustomProductRemark, CustomProductCnRemark, CustomProductInfoProperty, CustomProductBlacklist, CustomProductCraftRel, CustomProductWarehouseRel, CustomProductDiyUserRel, CustomProductFactoryPriceRel, CustomProductFactoryPriceIntervalRel, ProductTemplateInfo, ProductTemplateItem, ProductTemplateRemark, ProductTemplateInfoProperty, ProductTemplateItemSpec, LogCustomProduct, LogProductTemplate |
| `diy/` | DbDiy, DbDiyXiaoguotu, DbDiyUser |
| `system/` | SysUser, SysUserOld, SysRole, SysMenu, SysUserRole, SysRoleMenu, SysRoleDept, SysBillRule |
| `warehouse/` | CustomWarehouseInfo, CustomProductWarehouseRel |
| `misc/` | CraftCenter, ProductFactoryRel |
- [ ] 修改所有 66 个文件的 package 声明
- [ ] 修正所有实现类的 import(接口引用路径变更)
### Task 0.4: 修正 App Service Impl 中的 DomainService 引用
- [ ] 修正 `CustomProductInfoServiceImpl.java` 的 DomainService import(~20 个改为显式导入)
- [ ] 修正 `CustomProductItemServiceImpl.java` 的 DomainService import(~10 个)
- [ ] 修正 `ProductTemplateInfoServiceImpl.java` 的 DomainService import(~10 个)
- [ ] 修正 `LogCustomProductServiceImpl.java` 的 DomainService import(1 个)
> **关键**:将 `import com.jomalls.custom.domain.service.*` → 按子包分别显式导入
### Task 0.5: 编译验证与提交
- [ ] 运行 `mvn clean compile -DskipTests`
- [ ] 预期:BUILD SUCCESS,0 errors
- [ ] 如有编译错误,修正后重新编译
- [ ] `git add -A && git commit -m "refactor: 按业务域拆分 controller/appService/domainService 子包"`
---
## Step 1:P0 登录鉴权(4 端点)
### Task 1.1: TokenHandle 新增 createToken() + expireTime 字段
**文件**`custom-server-core/src/main/java/com/jomalls/custom/security/TokenHandle.java`
- [ ] 新增 `expireTime` 字段:`@Value("${token.expireTime:720}") private int expireTime; // 分钟`
- [ ] 新增 `createToken(LoginUser loginUser)` 方法
- [ ] 新增 imports:`Jwts`, `Keys`, `SecretKey`, `UUID`, `StandardCharsets`, `Date`
方法逻辑:
1. 生成 UUID 作为 redisKey
2. 设置 loginUser 的 token/loginTime/expireTime
3. 将 LoginUser JSON 存入 Redis(`login_tokens:{uuid}`,expireTime 分钟过期)
4. 生成 JWT(claims: login_user_key=uuid, id, account, deptId, permissions)
5. 使用 JJWT 0.12.x 标准签名(HS512, secret.getBytes(UTF_8))
```java
public String createToken(LoginUser loginUser) {
String token = UUID.randomUUID().toString();
loginUser.setToken(token);
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(System.currentTimeMillis() + expireTime * 60 * 1000L);
// 存入 Redis(custom-back 兼容路径)
if (stringRedisTemplate != null) {
String redisKey = REDIS_TOKEN_PREFIX + token;
stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(loginUser),
expireTime * 60, java.util.concurrent.TimeUnit.SECONDS);
}
// 生成 JWT(JJWT 0.12.x 标准)
byte[] keyBytes = secret.getBytes(java.nio.charset.StandardCharsets.UTF_8);
SecretKey signingKey = Keys.hmacShaKeyFor(keyBytes);
return Jwts.builder()
.claim("login_user_key", token)
.claim("id", loginUser.getUserId())
.claim("account", loginUser.getUsername())
.claim("deptId", loginUser.getDeptId())
.claim("permissions", loginUser.getPermissions())
.expiration(new Date(loginUser.getExpireTime()))
.signWith(signingKey)
.compact();
}
```
### Task 1.2: 新增 PasswordEncoder Bean
**新建**`custom-server-starter/src/main/java/com/jomalls/custom/config/SecurityConfig.java`
```java
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
```
- [ ] 新建 `SecurityConfig.java`
- [ ] `BCryptPasswordEncoder` 来自 `spring-security-crypto`(Spring Boot 自带)
### Task 1.3: 新增 SysRoleDomainService.selectRoleKeysByUserId()
**修改**
- `SysRoleDomainService.java` — 接口新增 `Set<String> selectRoleKeysByUserId(Long userId);`
- `SysRoleDomainServiceImpl.java` — 实现方法
- `SysRoleMapper.java` — 新增 `List<SysRoleEntity> selectRoleListByUserId(@Param("userId") Long userId);`
- `SysRoleMapper.xml` — 新增 SQL:`SELECT r.* FROM sys_role r LEFT JOIN sys_user_role ur ON r.role_id = ur.role_id WHERE ur.user_id = #{userId} AND r.status = '0' AND r.del_flag = '0'`
- [ ] 新增 `SysRoleDomainService.selectRoleKeysByUserId()`
- [ ] 新增 Mapper 方法 + XML SQL
### Task 1.4: 新增 SysMenuDomainService.selectMenuTreeByUserId()
**修改**
- `SysMenuDomainService.java` — 接口新增 `List<SysMenuEntity> selectMenuTreeByUserId(Long userId);`
- `SysMenuDomainServiceImpl.java` — 实现方法
- `SysMenuMapper.java` — 新增 `List<SysMenuEntity> selectMenuTreeByUserId(@Param("userId") Long userId);`
- `SysMenuMapper.xml` — 新增 SQL:管理员(`userId=1`)返回全部菜单,普通用户按角色权限过滤,排除按钮类型
- [ ] 新增 `SysMenuDomainService.selectMenuTreeByUserId()`
- [ ] 新增 Mapper 方法 + XML SQL
### Task 1.5: 确认 SysMenuEntity 字段完整性
- [ ] 检查 `SysMenuEntity.java` 是否包含:menuId, menuName, parentId, orderNum, path, component, routeName, query, isFrame, isCache, menuType, visible, status, perms, icon, delFlag
- [ ] 如有缺失字段,根据 `sys_menu` 表结构补充
### Task 1.6: 新建 VO(RouterVO / MetaVO / LoginUserInfoVO / SysUserVO)
**新建 4 个文件**
- `app/vo/RouterVO.java` — name, path, hidden, redirect, component, alwaysShow, meta, children
- `app/vo/MetaVO.java` — title, icon, isCache, isFrame
- `app/vo/LoginUserInfoVO.java` — user(SysUserVO), roles(Set), permissions(Set)
- `app/vo/SysUserVO.java` — userId, deptId, userName, nickName, email, phonenumber, sex, avatar, status, loginIp, loginDate, pwdUpdateDate, createTime, remark, dept(SysDeptVO)
- [ ] 新建 4 个 VO 文件,遵循 `@Data` + `@JsonInclude(NON_NULL)` + `@JsonProperty` 模式
### Task 1.7: 新建 SysLoginService
**新建 2 个文件**
- `app/service/system/SysLoginService.java` — login(String, String):String, getInfo():LoginUserInfoVO, getRouters():List<RouterVO>
- `app/service/system/impl/SysLoginServiceImpl.java`
核心逻辑:
**login()**: 查询用户(by userName) → 校验delFlag/status → BCrypt验证密码 → 查权限 → createToken
**getInfo()**: SecurityUtils.getLoginUser() → 查用户 → BeanMapper映射SysUserVO → 查角色(selectRoleKeysByUserId) → 返回LoginUserInfoVO
**getRouters()**: 查菜单树(selectMenuTreeByUserId) → 递归构建RouterVO树 → 过滤按钮类型 → 排序
- [ ] 新建 `SysLoginService.java` 接口
- [ ] 新建 `SysLoginServiceImpl.java`(@Service, @RequiredArgsConstructor 构造器注入)
- [ ] 递归构建路由树(private buildRouterTree方法)
### Task 1.8: 新建 SysLoginController
**新建**`webapp/controller/system/SysLoginController.java`
4 个端点:
- `POST /api/v2/login` — @RequestBody Map(body含username/password) → R<Map<String,String>>(token)
- `GET /api/v2/getInfo` → R<LoginUserInfoVO>
- `GET /api/v2/getRouters` → R<List<RouterVO>>
- `POST /api/v2/logout` → R<Void>
- [ ] 新建 `SysLoginController.java`(@RestController, @RequiredArgsConstructor)
### Task 1.9: P0 编译验证与提交
- [ ] `mvn clean compile -DskipTests`
- [ ] 预期:BUILD SUCCESS
- [ ] `git add -A && git commit -m "feat: P0 登录鉴权 — login/getInfo/getRouters/logout 4 端点"`
---
## Step 2:P1 RBAC 管理(46 端点)
### Task 2.1: 新建 Entity(SysDept / SysPost / SysUserPost)
**新建 3 个文件**
- `dal/entity/SysDeptEntity.java` — 表 `sys_dept`,字段:deptId, parentId, ancestors, deptName, orderNum, leader, phone, email, status, delFlag, createBy, createTime, updateBy, updateTime
- `dal/entity/SysPostEntity.java` — 表 `sys_post`,字段:postId, postCode, postName, postSort, status, createBy, createTime, updateBy, updateTime, remark
- `dal/entity/SysUserPostEntity.java` — 表 `sys_user_post`,字段:userId, postId
- [ ] 新建 3 个 Entity,遵循 @Data + @TableName + @TableId(AUTO) + Serializable 模式
### Task 2.2: 新建 Mapper + XML
**新建 6 个文件**
- `dal/mapper/SysDeptMapper.java` + `resources/mapper/SysDeptMapper.xml`
- `dal/mapper/SysPostMapper.java` + `resources/mapper/SysPostMapper.xml`
- `dal/mapper/SysUserPostMapper.java` + `resources/mapper/SysUserPostMapper.xml`
每个 Mapper 继承 `com.jomalls.custom.service.BaseMapper<T>`
XML 自定义 SQL:
- SysDeptMapper: selectDeptList(含筛选+排序), selectDeptListExcludeChild, hasChildByDeptId, checkDeptExistUser
- SysPostMapper: selectPostList(筛选+分页)
- SysUserPostMapper: MyBatis-Plus 基础 CRUD
- [ ] 新建 3 个 Mapper 接口 + 3 个 XML
### Task 2.3: 新建 DomainService(SysDept / SysPost)
**新建 4 个文件**
- `domain/service/system/SysDeptDomainService.java` + `impl/SysDeptDomainServiceImpl.java`
- `domain/service/system/SysPostDomainService.java` + `impl/SysPostDomainServiceImpl.java`
接口继承 `IBaseService<EntityType>`,实现继承 `BaseServiceImpl<MapperType, EntityType>`
- [ ] 新建 SysDeptDomainService(含 buildDeptTree 树构建方法)
- [ ] 新建 SysPostDomainService
### Task 2.4: 新建 AppService(5 组:User/Role/Menu/Dept/Post)
**新建 10 个文件**(5 接口 + 5 实现):
```
app/service/system/SysUserService.java + impl/SysUserServiceImpl.java
app/service/system/SysRoleService.java + impl/SysRoleServiceImpl.java
app/service/system/SysMenuService.java + impl/SysMenuServiceImpl.java
app/service/system/SysDeptService.java + impl/SysDeptServiceImpl.java
app/service/system/SysPostService.java + impl/SysPostServiceImpl.java
```
**SysUserService** 方法(14 端点对应):
- `IPage<SysUserEntity> pageList(SysUserEntity, Page)` — 分页+多条件筛选
- `SysUserEntity getInfo(Long)` — 详情+角色+岗位
- `void add(SysUserEntity)` — BCrypt密码+插入关联
- `void edit(SysUserEntity)` — 更新+同步关联
- `void remove(Long[])` — 批量逻辑删除
- `void resetPwd(Long, String)` — 重置密码
- `void changeStatus(Long, String)` — 状态切换
- `SysUserEntity profile()` — 个人信息
- `void updateProfile(SysUserEntity)` — 修改个人信息
- `void updatePwd(String, String)` — 修改密码
- `List<Long> getAuthRoleList(Long)` — 已授权角色
- `void insertAuthRole(Long, Long[])` — 保存授权(先删后插)
- 头像上传
**SysRoleService** 方法(13 端点对应):
- `IPage<SysRoleEntity> pageList(SysRoleEntity, Page)`
- `SysRoleEntity getInfo(Long)`
- `void add(SysRoleEntity)` — 含role_menu关联
- `void edit(SysRoleEntity)`
- `void dataScope(SysRoleEntity)` — role_dept关联
- `void changeStatus(Long, String)`
- `void remove(Long[])`
- `IPage<SysUserEntity> allocatedList(SysUserEntity, Page)` — 已授权用户
- `IPage<SysUserEntity> unallocatedList(SysUserEntity, Page)` — 未授权用户
- `void cancelAuthUser(Long, Long)` — 取消单个
- `void cancelAuthUserAll(Long, Long[])` — 批量取消
- `void selectAuthUserAll(Long, Long[])` — 批量授权
- `List<SysDeptEntity> deptTree(Long)` — 角色部门树
**SysMenuService** 方法(7 端点对应):
- `List<SysMenuEntity> list(SysMenuEntity)` — 树形列表
- `SysMenuEntity getInfo(Long)`
- `List<TreeSelectVO> treeselect()` — 下拉树
- `Map<String,Object> roleMenuTreeselect(Long)` — 角色菜单树(含checkedKeys)
- `void add(SysMenuEntity)`
- `void edit(SysMenuEntity)`
- `void remove(Long)` — 检测子菜单
**SysDeptService** 方法(6 端点对应):
- `List<SysDeptEntity> list(SysDeptEntity)` — 树形
- `List<SysDeptEntity> listExcludeChild(Long)`
- `SysDeptEntity getInfo(Long)`
- `void add(SysDeptEntity)`
- `void edit(SysDeptEntity)`
- `void remove(Long)` — 检测子部门+用户
**SysPostService** 方法(5 端点对应):
- `IPage<SysPostEntity> pageList(SysPostEntity, Page)`
- `SysPostEntity getInfo(Long)`
- `void add(SysPostEntity)`
- `void edit(SysPostEntity)`
- `void remove(Long[])`
- [ ] 新建 5 个 Service 接口 + 5 个实现类
### Task 2.5: 新建 Controller(5 个:User/Role/Menu/Dept/Post)
**新建 5 个文件**
```
webapp/controller/system/SysUserController.java (14 端点)
webapp/controller/system/SysRoleController.java (13 端点)
webapp/controller/system/SysMenuController.java (7 端点)
webapp/controller/system/SysDeptController.java (6 端点)
webapp/controller/system/SysPostController.java (5 端点)
```
每个 Controller 遵循统一模式:
- `@RestController` + `@RequestMapping("/api/v2/system/xxx")` + `@RequiredArgsConstructor` + `@Tag`
- 注入对应的 AppService
- 分页端点使用 `@RequestParam pageNum/pageSize``new Page<>(pageNum, pageSize)``R.ok(IPage)`
- 鉴权使用 `@RequiresPermissions("system:xxx:xxx")`
- 响应统一使用 `R<T>`
- [ ] 新建 5 个 Controller
### Task 2.6: 新建 VO(TreeSelectVO)
- [ ] 新建 `app/vo/TreeSelectVO.java` — id(Long), label(String), children(List<TreeSelectVO>)
### Task 2.7: P1 编译验证与提交
- [ ] `mvn clean compile -DskipTests`
- [ ] `git add -A && git commit -m "feat: P1 RBAC — 用户/角色/菜单/部门/岗位 46 端点"`
---
## Step 3:P2 ComposeServer + Log(8 端点)
### Task 3.1: 新建 Entity
**新建 2 个文件**
- `dal/entity/SysComposeServerEntity.java` — 表 `compose_server`,字段:id, title, host, remark, status, createTime。@TableField(exist=false): status0Count, status1Count
- `dal/entity/SysComposeServerLogEntity.java` — 表 `compose_server_log`,字段:id, composeServerId, batchNumber, subOrderNumbers, status, post, result, costTime, createTime。@TableField(exist=false): host
- [ ] 新建 2 个 Entity
### Task 3.2: 新建 Mapper + XML
**新建 4 个文件**
- `dal/mapper/SysComposeServerMapper.java` + `resources/mapper/SysComposeServerMapper.xml`
- `dal/mapper/SysComposeServerLogMapper.java` + `resources/mapper/SysComposeServerLogMapper.xml`
关键 SQL:
- selectServerList(含title模糊筛选)
- getAllServerHost(只返回正常状态的)
- updateStatusById
- selectServerLogList(LEFT JOIN host, 含多维筛选)
- deleteByIdList(**修正**:DELETE FROM compose_server_log,非 compose_server)
- [ ] 新建 2 个 Mapper + 2 个 XML
- [ ] 修正 custom-back bug:deleteByIdList 删除正确的表
### Task 3.3: 新建 DomainService
**新建 4 个文件**
- `domain/service/misc/SysComposeServerDomainService.java` + `impl/SysComposeServerDomainServiceImpl.java`
- `domain/service/misc/SysComposeServerLogDomainService.java` + `impl/SysComposeServerLogDomainServiceImpl.java`
- [ ] 新建 2 组 DomainService
### Task 3.4: 新建 AppService
**新建 4 个文件**
- `app/service/system/SysComposeServerService.java` + `impl/SysComposeServerServiceImpl.java`
- `app/service/system/SysComposeServerLogService.java` + `impl/SysComposeServerLogServiceImpl.java`
**关键逻辑**
- selectServerList 中填充 status0Count/status1Count 统计
- add 时校验 title/host 非空,强制 status=1
- deleteById 时级联删除关联日志
- 分页使用 MyBatis-Plus Page
- [ ] 新建 2 组 AppService
### Task 3.5: 新建 Controller
**新建 2 个文件**
- `webapp/controller/system/SysComposeServerController.java`(6 端点)
- `webapp/controller/system/SysComposeServerLogController.java`(2 端点)
- [ ] 新建 2 个 Controller
### Task 3.6: P2 编译验证与提交
- [ ] `mvn clean compile -DskipTests`
- [ ] `git add -A && git commit -m "feat: P2 ComposeServer — 服务器管理+日志 8 端点"`
---
## Step 4:P3 CountryCode + Warehouse(6 端点)
### Task 4.1: SaasAdminService 新增 getCountryCodeAll()
**修改**`custom-server-integrate/src/main/java/com/jomalls/custom/integrate/service/SaasAdminService.java`
- [ ] 新增 `getAllCountryCode()` 方法:
1. 先查 Redis 缓存(key `country_code:all`
2. 缓存未命中 → WebClient 调外部 manage API
3. 写入 Redis 缓存 1 小时
4. 返回 List<BaseCountryCodeVO>
- [ ] 新建 `app/vo/BaseCountryCodeVO.java`
### Task 4.2: 新建 BaseCountryCodeService + Controller
**新建 4 个文件**
- `app/service/system/BaseCountryCodeService.java` + `impl/BaseCountryCodeServiceImpl.java`
- `webapp/controller/system/BaseCountryCodeController.java`(2 端点)
端点:
- `GET /api/v2/countryCode/map` → Map<String,String> (countryCode→nameCn)
- `GET /api/v2/countryCode/all` → List<BaseCountryCodeVO>
- [ ] 新建 4 个文件
### Task 4.3: 新建 Warehouse AppService + Controller
**新建 3 个文件**(复用已有的 Entity/Mapper/DomainService):
- `app/service/warehouse/CustomWarehouseInfoService.java` + `impl/CustomWarehouseInfoServiceImpl.java`
- `webapp/controller/warehouse/CustomWarehouseInfoController.java`(5 端点)
端点:
- `GET /api/v2/customWarehouse/statusList` → 状态枚举
- `GET /api/v2/customWarehouse/list` → 分页查询
- `POST /api/v2/customWarehouse` → 新增
- `PUT /api/v2/customWarehouse` → 修改
- `DELETE /api/v2/customWarehouse/{ids}` → 批量删除
- [ ] 新建 3 个文件
### Task 4.4: P3 编译验证与提交
- [ ] `mvn clean compile -DskipTests`
- [ ] `git add -A && git commit -m "feat: P3 CountryCode + Warehouse — 国家代码+仓库管理 6 端点"`
---
## 整体验证清单
### 编译验证(每步必须通过)
```bash
mvn clean compile -DskipTests
# 每个 Step 结束 + 最终 = 6 次编译验证
```
### 启动验证
```bash
mvn -pl custom-server-starter spring-boot:run
# 访问 http://localhost:40071/swagger-ui/index.html
# 验证所有 64+22=86 端点出现在 Swagger UI
```
### 功能验证
| 端点组 | 端点 | 验证方式 |
|--------|------|---------|
| P0 login | 1 | POST /api/v2/login body={username,password} → 拿 token |
| P0 getInfo | 1 | GET /api/v2/getInfo Header:Authorization: Bearer {token} |
| P0 getRouters | 1 | GET /api/v2/getRouters → 树形路由 |
| P1 用户 | 14 | 全 CRUD + 授权角色 + 部门树 |
| P1 角色 | 13 | 全 CRUD + 授权用户 |
| P1 菜单 | 7 | 树形CRUD |
| P1 部门 | 6 | 树形CRUD |
| P1 岗位 | 5 | CRUD |
| P2 Server | 6 | CRUD + 状态 + host列表 |
| P2 Log | 2 | 分页 + 批量删除 |
| P3 Country | 2 | map + all |
| P3 Warehouse | 5 | CRUD + statusList |
---
## 总结
| Step | 任务 | 新建 | 修改 | 提交信息 |
|------|------|------|------|---------|
| 0 | 目录重构 | 0 | ~83 | `refactor: 按业务域拆分子包` |
| 1 | P0 登录 | ~12 | 6 | `feat: P0 登录鉴权 4 端点` |
| 2 | P1 RBAC | ~40 | 0 | `feat: P1 RBAC 46 端点` |
| 3 | P2 Compose | ~16 | 0 | `feat: P2 ComposeServer 8 端点` |
| 4 | P3 其他 | ~12 | 1 | `feat: P3 CountryCode+Warehouse 6 端点` |
| **合计** | **31 任务** | **~80** | **~90** | 6 次提交 |
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment