feat(permission): 新增获取权限详情接口(GET /api/permission/:id)相关文档与实现

This commit is contained in:
HeXiaoLong:Suanier 2025-07-08 23:42:18 +08:00
parent 64cf3415ab
commit a8f20a70fb
6 changed files with 214 additions and 16 deletions

View File

@ -18,6 +18,8 @@ import { permissionService } from './permission.service';
import { tags } from '@/constants/swaggerTags'; import { tags } from '@/constants/swaggerTags';
import { GetPermissionTreeQuerySchema, SortPermissionSchema } from './permission.schema'; import { GetPermissionTreeQuerySchema, SortPermissionSchema } from './permission.schema';
import { GetPermissionTreeResponsesSchema, SortPermissionResponsesSchema } from './permission.response'; import { GetPermissionTreeResponsesSchema, SortPermissionResponsesSchema } from './permission.response';
import { GetPermissionDetailParamsSchema } from './permission.schema';
import { GetPermissionDetailResponsesSchema } from './permission.response';
export const permissionController = new Elysia() export const permissionController = new Elysia()
/** /**
@ -115,4 +117,23 @@ export const permissionController = new Elysia()
}, },
response: SortPermissionResponsesSchema, response: SortPermissionResponsesSchema,
} }
)
/**
*
* @route GET /api/permission/:id
* @description
*/
.get(
'/:id',
async ({ params }) => permissionService.getPermissionDetail(params.id),
{
params: GetPermissionDetailParamsSchema,
detail: {
summary: '获取权限详情',
description: '查询指定权限的详细信息包括权限名称、类型、状态、module、排序等',
tags: [tags.permission],
operationId: 'getPermissionDetail',
},
response: GetPermissionDetailResponsesSchema,
}
); );

View File

@ -697,3 +697,104 @@ CREATE TABLE sys_permission (
- 排序操作应该有loading状态 - 排序操作应该有loading状态
- 失败时回滚前端显示状态 - 失败时回滚前端显示状态
- 成功后实时更新权限树显示 - 成功后实时更新权限树显示
---
### 7. 获取权限详情接口 (GET /api/permission/:id)
#### 业务逻辑
1. **接口用途**
- 根据权限ID获取单个权限的详细信息。
- 用于权限管理页面的详情查看、编辑前数据回显等场景。
2. **参数验证**
- 验证id格式bigint字符串前端需以字符串传递防止精度丢失
- 验证id是否存在。
3. **业务规则**
- 仅查询单条权限数据,不包含子权限。
- 返回所有主要字段(见响应结构)。
- 若权限不存在返回404。
- 若权限被禁用status=0仍可查询详情。
4. **数据处理**
- 查询sys_permission表按id精确查找。
- 字段类型转换bigint字段以字符串返回。
- 返回完整的权限信息包括id、pid、level、permission_key、name、description、type、api_path_key、page_path_key、module、sort、icon、status、created_at、updated_at。
5. **错误处理**
- 权限不存在404 Not Found
- id格式错误400 Bad Request
6. **安全性**
- 需具备权限管理相关权限方可访问。
- 记录操作日志。
7. **性能考虑**
- id字段为主键查询效率高。
- 单条数据查询,无性能瓶颈。
#### 响应结构
**成功响应 (200)**
```json
{
"code": 200,
"message": "获取权限详情成功",
"data": {
"id": "123456789",
"pid": "0",
"level": 1,
"permission_key": "user:create",
"name": "创建用户",
"description": "创建新用户的权限",
"type": 3,
"api_path_key": "/api/user/create",
"page_path_key": null,
"module": "user",
"sort": 1,
"icon": null,
"status": 1,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
```
**错误响应 (404)**
```json
{
"code": 404,
"message": "权限不存在",
"data": null
}
```
**错误响应 (400)**
```json
{
"code": 400,
"message": "参数格式错误",
"data": null
}
```
#### 测试用例
1. **正常获取权限详情**
- 输入存在的权限ID
- 预期:返回对应权限的详细信息
2. **权限不存在**
- 输入不存在的权限ID
- 预期返回404错误
3. **ID格式错误**
- 输入非bigint格式的ID
- 预期返回400错误
#### 注意事项
- 前端传递ID需为字符串防止大数精度丢失。
- 查询结果不包含子权限,仅为单条详情。
- 可用于详情页、编辑页的数据回显。
- 需做好权限校验,防止越权访问。

View File

@ -337,3 +337,30 @@ export const SortPermissionResponsesSchema = {
/** 权限排序成功响应数据类型 */ /** 权限排序成功响应数据类型 */
export type SortPermissionSuccessType = Static<typeof SortPermissionResponsesSchema[200]>; export type SortPermissionSuccessType = Static<typeof SortPermissionResponsesSchema[200]>;
/**
*
* @description Controller中定义所有可能的响应格式
*/
export const GetPermissionDetailResponsesSchema = {
200: responseWrapperSchema(CreatePermissionSuccessSchema),
404: responseWrapperSchema(
t.Object({
error: t.String({
description: '资源不存在',
examples: ['权限不存在'],
}),
}),
),
400: responseWrapperSchema(
t.Object({
error: t.String({
description: '参数错误',
examples: ['参数格式错误'],
}),
}),
),
};
/** 获取权限详情成功响应数据类型 */
export type GetPermissionDetailSuccessType = Static<typeof GetPermissionDetailResponsesSchema[200]>;

View File

@ -169,6 +169,21 @@ export const DeletePermissionParamsSchema = t.Object({
/** 删除权限参数类型 */ /** 删除权限参数类型 */
export type DeletePermissionParams = Static<typeof DeletePermissionParamsSchema>; export type DeletePermissionParams = Static<typeof DeletePermissionParamsSchema>;
/**
* Schema
* @description GET /api/permission/:id
*/
export const GetPermissionDetailParamsSchema = t.Object({
id: t.String({
pattern: '^[1-9]\\d*$',
description: '权限IDbigint字符串必须为正整数',
examples: ['1', '100', '123456789'],
}),
});
/** 获取权限详情参数类型 */
export type GetPermissionDetailParams = Static<typeof GetPermissionDetailParamsSchema>;
/** /**
* Schema * Schema
*/ */

View File

@ -442,7 +442,7 @@ export class PermissionService {
const duplicateIds = body.permissions const duplicateIds = body.permissions
.filter(p => duplicateSorts.includes(p.sort)) .filter(p => duplicateSorts.includes(p.sort))
.map(p => p.id); .map(p => p.id);
throw new BusinessError('排序值重复', 409); throw new BusinessError(`排序值重复:${duplicateIds.join(', ')}`, 409);
} }
// 3. 获取分布式锁 - 使用第一个权限的ID作为锁的一部分 // 3. 获取分布式锁 - 使用第一个权限的ID作为锁的一部分
@ -507,7 +507,6 @@ export class PermissionService {
.update(sysPermission) .update(sysPermission)
.set({ .set({
sort: permData.sort, sort: permData.sort,
updatedAt: new Date().toISOString()
}) })
.where(eq(sysPermission.id, permData.id)); .where(eq(sysPermission.id, permData.id));
}); });
@ -544,6 +543,41 @@ export class PermissionService {
await lock.release(); await lock.release();
} }
} }
/**
*
* @param id IDbigint字符串
* @returns Promise<CreatePermissionSuccessType>
* @throws BusinessError
*/
public async getPermissionDetail(id: string): Promise<CreatePermissionSuccessType> {
if (!/^[1-9]\d*$/.test(id)) {
throw new BusinessError('参数格式错误', 400);
}
const permArr = await db().select().from(sysPermission).where(eq(sysPermission.id, id)).limit(1);
if (!permArr || permArr.length === 0) {
throw new BusinessError('权限不存在', 404);
}
const perm = permArr[0]!;
Logger.info(`获取权限详情:${id}`);
return successResponse({
id: String(perm.id),
pid: String(perm.pid),
level: perm.level,
permissionKey: perm.permissionKey,
name: perm.name,
description: perm.description,
type: perm.type,
apiPathKey: perm.apiPathKey,
pagePathKey: perm.pagePathKey,
module: perm.module,
sort: perm.sort,
icon: perm.icon,
status: perm.status,
createdAt: perm.createdAt,
updatedAt: perm.updatedAt,
}, '获取权限详情成功');
}
} }
export const permissionService = new PermissionService(); export const permissionService = new PermissionService();

View File

@ -98,21 +98,21 @@ CREATE TABLE sys_permission (
### 3.6 权限排序接口 ### 3.6 权限排序接口
- [ ] 6.0 创建权限排序接口 (PUT /api/permission/sort) - [x] 6.0 创建权限排序接口 (PUT /api/permission/sort)
- [ ] 6.1 更新 `permission.docs.md` - 添加权限排序业务逻辑文档 - [x] 6.1 更新 `permission.docs.md` - 添加权限排序业务逻辑文档
- [ ] 6.2 更新 `permission.schema.ts` - 定义权限排序Schema - [x] 6.2 更新 `permission.schema.ts` - 定义权限排序Schema
- [ ] 6.3 更新 `permission.response.ts` - 定义权限排序响应格式 - [x] 6.3 更新 `permission.response.ts` - 定义权限排序响应格式
- [ ] 6.4 更新 `permission.service.ts` - 实现权限排序业务逻辑 - [x] 6.4 更新 `permission.service.ts` - 实现权限排序业务逻辑
- [ ] 6.5 更新 `permission.controller.ts` - 实现权限排序路由 - [x] 6.5 更新 `permission.controller.ts` - 实现权限排序路由
### 3.7 获取权限详情接口 ### 3.7 获取权限详情接口
- [ ] 7.0 创建获取权限详情接口 (GET /api/permission/:id) - [x] 7.0 创建获取权限详情接口 (GET /api/permission/:id)
- [ ] 7.1 更新 `permission.docs.md` - 添加获取权限详情业务逻辑文档 - [x] 7.1 更新 `permission.docs.md` - 添加获取权限详情业务逻辑文档
- [ ] 7.2 更新 `permission.schema.ts` - 定义获取权限详情Schema - [x] 7.2 更新 `permission.schema.ts` - 定义获取权限详情Schema
- [ ] 7.3 更新 `permission.response.ts` - 定义获取权限详情响应格式 - [x] 7.3 更新 `permission.response.ts` - 定义获取权限详情响应格式
- [ ] 7.4 更新 `permission.service.ts` - 实现获取权限详情业务逻辑 - [x] 7.4 更新 `permission.service.ts` - 实现获取权限详情业务逻辑
- [ ] 7.5 更新 `permission.controller.ts` - 实现获取权限详情路由 - [x] 7.5 更新 `permission.controller.ts` - 实现获取权限详情路由
## 4. 相关文件 ## 4. 相关文件