diff --git a/backend/app/OpenApiSpec.php b/backend/app/OpenApiSpec.php index 846bf75..8a3be6a 100644 --- a/backend/app/OpenApiSpec.php +++ b/backend/app/OpenApiSpec.php @@ -200,6 +200,37 @@ use OpenApi\Attributes as OA; new OA\Property(property: 'created_at', type: 'string', format: 'date-time'), ] )] +#[OA\Schema( + schema: 'OperationLogList', + type: 'object', + description: '操作日志列表项', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1), + new OA\Property(property: 'user_id', type: 'integer', example: 1), + new OA\Property(property: 'action', type: 'string', example: 'user.create'), + new OA\Property(property: 'target_type', type: 'string', example: 'user'), + new OA\Property(property: 'target_id', type: 'integer', example: 5, nullable: true), + new OA\Property(property: 'description', type: 'string', example: '创建用户 test_user'), + new OA\Property(property: 'ip', type: 'string', example: '127.0.0.1', nullable: true), + new OA\Property(property: 'created_at', type: 'string', format: 'date-time'), + ] +)] +#[OA\Schema( + schema: 'OperationLogDetail', + type: 'object', + description: '操作日志详情(含完整操作详情 JSON)', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1), + new OA\Property(property: 'user_id', type: 'integer', example: 1), + new OA\Property(property: 'action', type: 'string', example: 'user.create'), + new OA\Property(property: 'target_type', type: 'string', example: 'user'), + new OA\Property(property: 'target_id', type: 'integer', example: 5, nullable: true), + new OA\Property(property: 'description', type: 'string', example: '创建用户 test_user'), + new OA\Property(property: 'detail', type: 'object', description: '操作详情 JSON', nullable: true), + new OA\Property(property: 'ip', type: 'string', example: '127.0.0.1', nullable: true), + new OA\Property(property: 'created_at', type: 'string', format: 'date-time'), + ] +)] class OpenApiSpec { } diff --git a/backend/docs/openapi.yaml b/backend/docs/openapi.yaml index a7dd07b..b5c2ae5 100644 --- a/backend/docs/openapi.yaml +++ b/backend/docs/openapi.yaml @@ -401,6 +401,141 @@ paths: security: - bearerAuth: [] + /api/v1/logs/operations: + get: + tags: + - 'Operation Logs' + summary: 操作日志列表 + description: '获取操作日志列表,支持分页、按用户/操作类型/目标类型/时间筛选。仅 admin 可访问。' + operationId: 36e862550729db3d302d110c8e10c58d + parameters: + - + name: page + in: query + required: false + schema: + type: integer + default: 1 + - + name: per_page + in: query + required: false + schema: + type: integer + default: 15 + maximum: 100 + - + name: user_id + in: query + description: '用户 ID 精确筛选' + required: false + schema: + type: integer + - + name: action + in: query + description: 操作类型精确筛选 + required: false + schema: + type: string + - + name: target_type + in: query + description: 目标类型精确筛选 + required: false + schema: + type: string + - + name: created_at_from + in: query + description: 创建时间起始(含) + required: false + schema: + type: string + format: date + example: '2026-01-01' + - + name: created_at_to + in: query + description: 创建时间截止(含) + required: false + schema: + type: string + format: date + example: '2026-12-31' + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + properties: + code: { type: integer, example: 0 } + message: { type: string, example: 获取成功 } + data: { properties: { items: { type: array, items: { $ref: '#/components/schemas/OperationLogList' } }, total: { type: integer, example: 100 }, page: { type: integer, example: 1 }, per_page: { type: integer, example: 15 } }, type: object } + type: object + '401': + description: 未认证 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: 无权限 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - + bearerAuth: [] + '/api/v1/logs/operations/{id}': + get: + tags: + - 'Operation Logs' + summary: 操作日志详情 + description: '获取操作日志详情,含完整操作详情 JSON。仅 admin 可访问。' + operationId: d4b0ae03fd3ef2dec4c8d6d910013ef2 + parameters: + - + name: id + in: path + description: '操作日志 ID' + required: true + schema: + type: integer + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + properties: + code: { type: integer, example: 0 } + message: { type: string, example: 获取成功 } + data: { $ref: '#/components/schemas/OperationLogDetail' } + type: object + '401': + description: 未认证 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: 无权限 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 数据不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: + - + bearerAuth: [] /orders: get: tags: @@ -4360,6 +4495,70 @@ components: type: string format: date-time type: object + OperationLogList: + description: 操作日志列表项 + properties: + id: + type: integer + example: 1 + user_id: + type: integer + example: 1 + action: + type: string + example: user.create + target_type: + type: string + example: user + target_id: + type: integer + example: 5 + nullable: true + description: + type: string + example: '创建用户 test_user' + ip: + type: string + example: 127.0.0.1 + nullable: true + created_at: + type: string + format: date-time + type: object + OperationLogDetail: + description: '操作日志详情(含完整操作详情 JSON)' + properties: + id: + type: integer + example: 1 + user_id: + type: integer + example: 1 + action: + type: string + example: user.create + target_type: + type: string + example: user + target_id: + type: integer + example: 5 + nullable: true + description: + type: string + example: '创建用户 test_user' + detail: + description: '操作详情 JSON' + type: object + nullable: true + ip: + type: string + example: 127.0.0.1 + nullable: true + created_at: + type: string + format: date-time + type: object securitySchemes: bearerAuth: type: http @@ -4379,6 +4578,9 @@ tags: - name: 'MQ Status' description: 消息队列状态监控 + - + name: 'Operation Logs' + description: 操作日志查看 - name: Orders description: 订单管理