From a3e8a5cf5dee932ba56355c43d574f34c997b5c3 Mon Sep 17 00:00:00 2001 From: Nick Zeng Date: Fri, 13 Mar 2026 14:50:06 +0800 Subject: [PATCH] add mq controller --- backend/app/Command/AppMqStatus.php | 282 +- .../Controller/Api/V1/MqStatusController.php | 96 + backend/app/OpenApiSpec.php | 26 + backend/app/Service/MqStatusService.php | 192 + backend/storage/openapi.json | 6829 +++++++++++++++++ .../System/MqStatusControllerTest.php | 101 + .../Unit/Service/MqStatusServiceTest.php | 101 + 7 files changed, 7424 insertions(+), 203 deletions(-) create mode 100644 backend/app/Controller/Api/V1/MqStatusController.php create mode 100644 backend/app/Service/MqStatusService.php create mode 100644 backend/storage/openapi.json create mode 100644 backend/test/Cases/Integration/System/MqStatusControllerTest.php create mode 100644 backend/test/Cases/Unit/Service/MqStatusServiceTest.php diff --git a/backend/app/Command/AppMqStatus.php b/backend/app/Command/AppMqStatus.php index 8e6a27d..470659a 100644 --- a/backend/app/Command/AppMqStatus.php +++ b/backend/app/Command/AppMqStatus.php @@ -4,21 +4,15 @@ declare(strict_types=1); namespace App\Command; +use App\Service\MqStatusService; use Hyperf\Command\Command as HyperfCommand; use Hyperf\Command\Annotation\Command; use Psr\Container\ContainerInterface; -use PhpAmqpLib\Connection\AMQPStreamConnection; -use Hyperf\Contract\ConfigInterface; use Symfony\Component\Console\Input\InputOption; #[Command] class AppMqStatus extends HyperfCommand { - /** - * 业务队列类型 - */ - private const QUEUE_TYPES = ['orders', 'products', 'refunds', 'inventory']; - public function __construct(protected ContainerInterface $container) { parent::__construct('app:mq:status'); @@ -59,116 +53,62 @@ class AppMqStatus extends HyperfCommand $this->line(''); try { - $config = $this->container->get(ConfigInterface::class); - $consumerConfig = $config->get('amqp.default_consumer'); - - // 创建连接 - $connection = new AMQPStreamConnection( - $consumerConfig['host'], - $consumerConfig['port'], - $consumerConfig['user'], - $consumerConfig['password'], - $consumerConfig['vhost'], - false, - 'AMQPLAIN', - null, - 'en_US', - $consumerConfig['params']['connection_timeout'] ?? 3.0, - $consumerConfig['params']['read_write_timeout'] ?? 3.0, - null, - $consumerConfig['params']['keepalive'] ?? false, - $consumerConfig['params']['heartbeat'] ?? 0 - ); - - $channel = $connection->channel(); + $service = $this->container->get(MqStatusService::class); // 获取 --queue 参数 - $filterQueue = $this->input->getOption('queue'); - - // 确定要显示的队列组 - $queueTypes = $filterQueue - ? [$filterQueue] - : self::QUEUE_TYPES; + $filter_queue = $this->input->getOption('queue'); // 验证队列类型 - if ($filterQueue && !in_array($filterQueue, self::QUEUE_TYPES)) { - $this->error("Invalid queue type: {$filterQueue}"); - $this->line("Valid types: " . implode(', ', self::QUEUE_TYPES)); - $channel->close(); - $connection->close(); + if ($filter_queue && !in_array($filter_queue, $service->getValidQueueTypes())) { + $this->error("Invalid queue type: {$filter_queue}"); + $this->line("Valid types: " . implode(', ', $service->getValidQueueTypes())); return 1; } - $totalMessages = 0; - $totalConsumers = 0; - $allQueueNames = []; - - // 收集主业务队列和死信队列的数据 - $businessQueuesData = []; - $deadLetterQueuesData = []; - - foreach ($queueTypes as $type) { - $groupData = $this->fetchQueueGroupData($channel, $type); - - foreach ($groupData as $queueInfo) { - // 区分主队列和重试队列(死信队列) - if (str_ends_with($queueInfo['queue'], '.retry.queue')) { - $deadLetterQueuesData[] = $queueInfo; - } else { - $businessQueuesData[] = $queueInfo; - } - - if (is_numeric($queueInfo['messages'])) { - $totalMessages += $queueInfo['messages']; - } - if (is_numeric($queueInfo['consumers'])) { - $totalConsumers += $queueInfo['consumers']; - } - $allQueueNames[] = $queueInfo['queue']; - } - } + // 通过 Service 获取队列状态数据 + $status = $service->getStatus($filter_queue); // 显示主业务队列表格 - $this->displayBusinessQueues($businessQueuesData, $filterQueue); + $this->displayBusinessQueues($status['business_queues'], $filter_queue); // 显示死信队列(重试队列) - if (!empty($deadLetterQueuesData)) { + if (!empty($status['retry_queues'])) { $this->line(''); - $this->displayDeadLetterQueues($deadLetterQueuesData, $filterQueue); + $this->displayDeadLetterQueues($status['retry_queues'], $filter_queue); } // 显示共享的错误队列 - if (!$filterQueue) { + if (!empty($status['error_queue'])) { $this->line(''); - $errorQueueData = $this->fetchQueueData($channel, 'errors.queue'); - $this->displaySharedQueues([$errorQueueData]); - - if (is_numeric($errorQueueData['messages'])) { - $totalMessages += $errorQueueData['messages']; - } - if (is_numeric($errorQueueData['consumers'])) { - $totalConsumers += $errorQueueData['consumers']; - } - $allQueueNames[] = $errorQueueData['queue']; + $this->displaySharedQueues([$status['error_queue']]); } - // 关闭连接 - $channel->close(); - $connection->close(); - // 显示汇总信息 $this->line(''); $this->info("=== Summary ==="); - $this->line("Total messages: {$totalMessages}"); - $this->line("Total active consumers: {$totalConsumers}"); + $this->line("Total messages: {$status['summary']['total_messages']}"); + $this->line("Total active consumers: {$status['summary']['total_consumers']}"); $this->line(''); + + // 列出所有监控的队列名称 + $all_queue_names = []; + foreach ($status['business_queues'] as $q) { + $all_queue_names[] = $q['queue']; + } + foreach ($status['retry_queues'] as $q) { + $all_queue_names[] = $q['queue']; + } + if (!empty($status['error_queue'])) { + $all_queue_names[] = $status['error_queue']['queue']; + } + $this->line('Queues monitored:'); - foreach ($allQueueNames as $queueName) { - $this->line(" - {$queueName}"); + foreach ($all_queue_names as $queue_name) { + $this->line(" - {$queue_name}"); } return 0; - } catch (\Exception $e) { + } catch (\Throwable $e) { $this->error('Failed to fetch queue status: ' . $e->getMessage()); $this->line('Trace: ' . $e->getTraceAsString(), 'comment'); return 1; @@ -176,96 +116,41 @@ class AppMqStatus extends HyperfCommand } /** - * 获取队列组数据(主队列 + 重试队列) + * 将 Service 返回的 status 枚举值转为 CLI ANSI 格式 */ - private function fetchQueueGroupData($channel, string $type): array + private function formatStatus(string $status): string { - $queues = [ - "{$type}.queue", // 主业务队列 - "{$type}.retry.queue", // 重试队列 - ]; - - $groupData = []; - foreach ($queues as $queueName) { - $groupData[] = $this->fetchQueueData($channel, $queueName); - } - - return $groupData; - } - - /** - * 获取单个队列的数据 - */ - private function fetchQueueData($channel, string $queueName): array - { - try { - // 使用 passive=true 来获取队列信息而不创建队列 - [$queue, $messageCount, $consumerCount] = $channel->queue_declare( - $queueName, - true, // passive - true, // durable - false, // exclusive - false // auto_delete - ); - - return [ - 'queue' => $queueName, - 'messages' => $messageCount, - 'consumers' => $consumerCount, - 'status' => $this->getQueueStatus($messageCount, $consumerCount), - ]; - } catch (\Exception $e) { - return [ - 'queue' => $queueName, - 'messages' => 'N/A', - 'consumers' => 'N/A', - 'status' => 'Error: ' . $e->getMessage() . '', - ]; - } - } - - /** - * 获取队列状态描述 - */ - private function getQueueStatus(int $messageCount, int $consumerCount): string - { - if ($messageCount > 100) { - return '⚠ High Load'; - } elseif ($messageCount > 10) { - return '⚡ Processing'; - } elseif ($messageCount > 0) { - return '✓ Active'; - } else { - return '✓ Empty'; - } + return match ($status) { + 'high_load' => '⚠ High Load', + 'processing' => '⚡ Processing', + 'active' => '✓ Active', + 'empty' => '✓ Empty', + 'error' => '✗ Error', + default => $status, + }; } /** * 显示业务队列(合并所有队列组)- 转置显示 */ - private function displayBusinessQueues(array $allGroupsData, ?string $filterQueue): void + private function displayBusinessQueues(array $all_groups_data, ?string $filter_queue): void { - // 构建标题 - $title = $filterQueue - ? "Business Queues (Filtered: {$filterQueue})" + $title = $filter_queue + ? "Business Queues (Filtered: {$filter_queue})" : "Business Queues"; $this->line("=== {$title} ==="); - // 构建表头 - 使用简化的队列名称(去掉 .queue) $headers = ['Metric']; - foreach ($allGroupsData as $queueInfo) { - $queueName = $queueInfo['queue']; - // 去掉 .queue 后缀 - $simpleName = str_replace('.queue', '', $queueName); - $headers[] = $simpleName; + foreach ($all_groups_data as $queue_info) { + $simple_name = str_replace('.queue', '', $queue_info['queue']); + $headers[] = $simple_name; } - // 构建行数据 - 转置显示 $rows = [ - $this->buildMetricRow('Messages', $allGroupsData, 'messages'), - $this->buildMetricRow('Consumers', $allGroupsData, 'consumers'), - $this->buildMetricRow('Status', $allGroupsData, 'status'), + $this->buildMetricRow('Messages', $all_groups_data, 'messages'), + $this->buildMetricRow('Consumers', $all_groups_data, 'consumers'), + $this->buildMetricRow('Status', $all_groups_data, 'status'), ]; $this->table($headers, $rows); @@ -275,34 +160,29 @@ class AppMqStatus extends HyperfCommand /** * 显示死信队列(重试队列)- 转置显示 */ - private function displayDeadLetterQueues(array $queuesData, ?string $filterQueue): void + private function displayDeadLetterQueues(array $queues_data, ?string $filter_queue): void { - $title = $filterQueue - ? "Dead Letter Queues (Filtered: {$filterQueue})" + $title = $filter_queue + ? "Dead Letter Queues (Filtered: {$filter_queue})" : "Dead Letter Queues (Retry Queues)"; $this->line("=== {$title} ==="); - // 构建表头 $headers = ['Metric']; - foreach ($queuesData as $queueInfo) { - $queueName = $queueInfo['queue']; - // 去掉 .queue 后缀,保留 retry 标识 - $simpleName = str_replace('.queue', '', $queueName); - $headers[] = $simpleName; + foreach ($queues_data as $queue_info) { + $simple_name = str_replace('.queue', '', $queue_info['queue']); + $headers[] = $simple_name; } - // 构建行数据 $rows = [ - $this->buildMetricRow('Messages', $queuesData, 'messages'), - $this->buildMetricRow('Consumers', $queuesData, 'consumers'), - $this->buildMetricRow('Status', $queuesData, 'status'), + $this->buildMetricRow('Messages', $queues_data, 'messages'), + $this->buildMetricRow('Consumers', $queues_data, 'consumers'), + $this->buildMetricRow('Status', $queues_data, 'status'), ]; $this->table($headers, $rows); - // 添加说明 - if (!empty($queuesData) && $this->hasMessages($queuesData)) { + if (!empty($queues_data) && $this->hasMessages($queues_data)) { $this->line('ℹ These queues receive messages from DLX when main queue processing fails'); } } @@ -310,30 +190,25 @@ class AppMqStatus extends HyperfCommand /** * 显示共享队列(errors.queue)- 转置显示 */ - private function displaySharedQueues(array $queuesData): void + private function displaySharedQueues(array $queues_data): void { $this->line("=== Shared Queues ==="); - // 构建表头 $headers = ['Metric']; - foreach ($queuesData as $queueInfo) { - $queueName = $queueInfo['queue']; - // 去掉 .queue 后缀 - $simpleName = str_replace('.queue', '', $queueName); - $headers[] = $simpleName; + foreach ($queues_data as $queue_info) { + $simple_name = str_replace('.queue', '', $queue_info['queue']); + $headers[] = $simple_name; } - // 构建行数据 $rows = [ - $this->buildMetricRow('Messages', $queuesData, 'messages'), - $this->buildMetricRow('Consumers', $queuesData, 'consumers'), - $this->buildMetricRow('Status', $queuesData, 'status'), + $this->buildMetricRow('Messages', $queues_data, 'messages'), + $this->buildMetricRow('Consumers', $queues_data, 'consumers'), + $this->buildMetricRow('Status', $queues_data, 'status'), ]; $this->table($headers, $rows); - // 添加说明 - if (!empty($queuesData) && $this->hasMessages($queuesData)) { + if (!empty($queues_data) && $this->hasMessages($queues_data)) { $this->line('ℹ Error queue contains messages that exceeded max retry count'); } } @@ -341,10 +216,10 @@ class AppMqStatus extends HyperfCommand /** * 检查队列中是否有消息 */ - private function hasMessages(array $queuesData): bool + private function hasMessages(array $queues_data): bool { - foreach ($queuesData as $queueInfo) { - if (is_numeric($queueInfo['messages']) && $queueInfo['messages'] > 0) { + foreach ($queues_data as $queue_info) { + if (is_numeric($queue_info['messages']) && $queue_info['messages'] > 0) { return true; } } @@ -354,15 +229,16 @@ class AppMqStatus extends HyperfCommand /** * 构建指标行数据 */ - private function buildMetricRow(string $metricName, array $queuesData, string $field): array + private function buildMetricRow(string $metric_name, array $queues_data, string $field): array { - $row = [$metricName]; + $row = [$metric_name]; - foreach ($queuesData as $queueInfo) { - $value = $queueInfo[$field]; + foreach ($queues_data as $queue_info) { + $value = $queue_info[$field]; - // 根据字段类型格式化显示 - if ($field === 'messages' || $field === 'consumers') { + if ($field === 'status') { + $row[] = $this->formatStatus((string) $value); + } elseif ($field === 'messages' || $field === 'consumers') { $row[] = $this->formatNumber($value); } else { $row[] = $value; @@ -375,7 +251,7 @@ class AppMqStatus extends HyperfCommand /** * 格式化数字显示 */ - private function formatNumber($value): string + private function formatNumber(mixed $value): string { if (!is_numeric($value)) { return (string) $value; diff --git a/backend/app/Controller/Api/V1/MqStatusController.php b/backend/app/Controller/Api/V1/MqStatusController.php new file mode 100644 index 0000000..c2f3301 --- /dev/null +++ b/backend/app/Controller/Api/V1/MqStatusController.php @@ -0,0 +1,96 @@ + []]], + tags: ['MQ Status'], + parameters: [ + new OA\Parameter( + name: 'queue', + in: 'query', + required: false, + description: '队列类型筛选(orders/products/refunds/inventory)', + schema: new OA\Schema(type: 'string', enum: ['orders', 'products', 'refunds', 'inventory']) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: '获取成功', + content: new OA\JsonContent(properties: [ + new OA\Property(property: 'code', type: 'integer', example: 0), + new OA\Property(property: 'message', type: 'string', example: '获取成功'), + new OA\Property(property: 'data', ref: '#/components/schemas/MqQueueStatus'), + ]) + ), + new OA\Response(response: 400, description: '无效的队列类型参数', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), + new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), + new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), + new OA\Response(response: 500, description: 'RabbitMQ 连接异常', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), + ] + )] + #[RequestMapping(path: "status", methods: "GET")] + public function status(): ResponseInterface|array + { + $queue_type = $this->request->input('queue'); + + // 校验队列类型参数 + if ($queue_type !== null && !in_array($queue_type, $this->mqStatusService->getValidQueueTypes(), true)) { + return $this->response->json([ + 'code' => 400, + 'message' => "无效的队列类型: {$queue_type},可选值: " . implode(', ', $this->mqStatusService->getValidQueueTypes()), + 'data' => null, + ])->withStatus(400); + } + + try { + $data = $this->mqStatusService->getStatus($queue_type); + + return [ + 'code' => 0, + 'message' => '获取成功', + 'data' => $data, + ]; + } catch (\Throwable $e) { + return $this->response->json([ + 'code' => 500, + 'message' => 'RabbitMQ 连接异常: ' . $e->getMessage(), + 'data' => null, + ])->withStatus(500); + } + } +} diff --git a/backend/app/OpenApiSpec.php b/backend/app/OpenApiSpec.php index 056af09..f330a52 100644 --- a/backend/app/OpenApiSpec.php +++ b/backend/app/OpenApiSpec.php @@ -52,6 +52,32 @@ use OpenApi\Attributes as OA; new OA\Property(property: 'data', type: 'object', nullable: true), ] )] +#[OA\Schema( + schema: 'MqQueueInfo', + type: 'object', + description: '单个队列的状态信息', + properties: [ + new OA\Property(property: 'queue', type: 'string', example: 'orders.queue', description: '队列名称'), + new OA\Property(property: 'messages', description: '消息数量(异常时为 N/A)', oneOf: [new OA\Schema(type: 'integer'), new OA\Schema(type: 'string')], example: 5), + new OA\Property(property: 'consumers', description: '消费者数量(异常时为 N/A)', oneOf: [new OA\Schema(type: 'integer'), new OA\Schema(type: 'string')], example: 1), + new OA\Property(property: 'status', type: 'string', enum: ['high_load', 'processing', 'active', 'empty', 'error'], example: 'active', description: '队列状态'), + ] +)] +#[OA\Schema( + schema: 'MqQueueStatus', + type: 'object', + description: '消息队列全量状态', + properties: [ + new OA\Property(property: 'business_queues', type: 'array', items: new OA\Items(ref: '#/components/schemas/MqQueueInfo'), description: '业务队列列表'), + new OA\Property(property: 'retry_queues', type: 'array', items: new OA\Items(ref: '#/components/schemas/MqQueueInfo'), description: '重试队列列表'), + new OA\Property(property: 'error_queue', ref: '#/components/schemas/MqQueueInfo', description: '错误队列(筛选时为空数组)'), + new OA\Property(property: 'summary', properties: [ + new OA\Property(property: 'total_messages', type: 'integer', example: 7, description: '消息总数'), + new OA\Property(property: 'total_consumers', type: 'integer', example: 1, description: '消费者总数'), + ], type: 'object', description: '汇总统计'), + new OA\Property(property: 'fetched_at', type: 'string', format: 'date-time', example: '2026-03-13 12:00:00', description: '数据获取时间'), + ] +)] class OpenApiSpec { } diff --git a/backend/app/Service/MqStatusService.php b/backend/app/Service/MqStatusService.php new file mode 100644 index 0000000..fc6acfd --- /dev/null +++ b/backend/app/Service/MqStatusService.php @@ -0,0 +1,192 @@ + + */ + public function getValidQueueTypes(): array + { + return self::QUEUE_TYPES; + } + + /** + * 获取队列状态 + * + * @param string|null $queue_type 筛选队列类型(orders/products/refunds/inventory) + * @return array{business_queues: array, retry_queues: array, error_queue: array, summary: array, fetched_at: string} + */ + public function getStatus(?string $queue_type = null): array + { + $consumer_config = $this->config->get('amqp.default_consumer'); + + $connection = new AMQPStreamConnection( + $consumer_config['host'], + $consumer_config['port'], + $consumer_config['user'], + $consumer_config['password'], + $consumer_config['vhost'], + false, + 'AMQPLAIN', + null, + 'en_US', + $consumer_config['params']['connection_timeout'] ?? 3.0, + $consumer_config['params']['read_write_timeout'] ?? 3.0, + null, + $consumer_config['params']['keepalive'] ?? false, + $consumer_config['params']['heartbeat'] ?? 0 + ); + + $channel = $connection->channel(); + + try { + $queue_types = $queue_type ? [$queue_type] : self::QUEUE_TYPES; + + $business_queues = []; + $retry_queues = []; + $total_messages = 0; + $total_consumers = 0; + + foreach ($queue_types as $type) { + $group_data = $this->fetchQueueGroupData($channel, $type); + + foreach ($group_data as $queue_info) { + if (str_ends_with($queue_info['queue'], '.retry.queue')) { + $retry_queues[] = $queue_info; + } else { + $business_queues[] = $queue_info; + } + + if (is_numeric($queue_info['messages'])) { + $total_messages += $queue_info['messages']; + } + if (is_numeric($queue_info['consumers'])) { + $total_consumers += $queue_info['consumers']; + } + } + } + + // 错误队列仅在未筛选时返回 + $error_queue = []; + if ($queue_type === null) { + $error_queue = $this->fetchQueueData($channel, 'errors.queue'); + + if (is_numeric($error_queue['messages'])) { + $total_messages += $error_queue['messages']; + } + if (is_numeric($error_queue['consumers'])) { + $total_consumers += $error_queue['consumers']; + } + } + + return [ + 'business_queues' => $business_queues, + 'retry_queues' => $retry_queues, + 'error_queue' => $error_queue, + 'summary' => [ + 'total_messages' => $total_messages, + 'total_consumers' => $total_consumers, + ], + 'fetched_at' => date('Y-m-d H:i:s'), + ]; + } finally { + $channel->close(); + $connection->close(); + } + } + + /** + * 获取队列组数据(主队列 + 重试队列) + * + * @return array + */ + private function fetchQueueGroupData(mixed $channel, string $type): array + { + $queues = [ + "{$type}.queue", + "{$type}.retry.queue", + ]; + + $group_data = []; + foreach ($queues as $queue_name) { + $group_data[] = $this->fetchQueueData($channel, $queue_name); + } + + return $group_data; + } + + /** + * 获取单个队列的数据 + * + * @return array{queue: string, messages: int|string, consumers: int|string, status: string} + */ + private function fetchQueueData(mixed $channel, string $queue_name): array + { + try { + // 使用 passive=true 获取队列信息而不创建队列 + [, $message_count, $consumer_count] = $channel->queue_declare( + $queue_name, + true, // passive + true, // durable + false, // exclusive + false // auto_delete + ); + + return [ + 'queue' => $queue_name, + 'messages' => $message_count, + 'consumers' => $consumer_count, + 'status' => $this->getQueueStatus($message_count), + ]; + } catch (\Throwable $e) { + return [ + 'queue' => $queue_name, + 'messages' => 'N/A', + 'consumers' => 'N/A', + 'status' => 'error', + ]; + } + } + + /** + * 根据消息数量判断队列状态 + * + * @return string 状态枚举:high_load/processing/active/empty + */ + public function getQueueStatus(int $message_count): string + { + if ($message_count > 100) { + return 'high_load'; + } + if ($message_count > 10) { + return 'processing'; + } + if ($message_count > 0) { + return 'active'; + } + return 'empty'; + } +} diff --git a/backend/storage/openapi.json b/backend/storage/openapi.json new file mode 100644 index 0000000..4e0c28d --- /dev/null +++ b/backend/storage/openapi.json @@ -0,0 +1,6829 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Datahub API", + "description": "Datahub API documentation", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api/v1", + "description": "API v1" + } + ], + "paths": { + "/api/v1/mq/status": { + "get": { + "tags": [ + "MQ Status" + ], + "summary": "获取消息队列状态", + "description": "查询 RabbitMQ 各队列的消息数、消费者数和运行状态。支持按队列类型筛选。仅 admin 角色可访问。", + "operationId": "3f5b041034fafc9738ecf65f166b6193", + "parameters": [ + { + "name": "queue", + "in": "query", + "description": "队列类型筛选(orders/products/refunds/inventory)", + "required": false, + "schema": { + "type": "string", + "enum": [ + "orders", + "products", + "refunds", + "inventory" + ] + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "$ref": "#/components/schemas/MqQueueStatus" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "无效的队列类型参数", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "无权限", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "RabbitMQ 连接异常", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/orders": { + "get": { + "tags": [ + "Orders" + ], + "summary": "订单列表", + "description": "获取订单列表,支持分页、多维度筛选和时间范围筛选。返回业务字段,不含 raw/hash。", + "operationId": "7e493d0464138129e7e1f0e7ebee178b", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "order_status_id", + "in": "query", + "description": "订单状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "平台订单 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-01-01" + } + }, + { + "name": "created_date_to", + "in": "query", + "description": "创建时间截止(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-12-31" + } + }, + { + "name": "paid_date_from", + "in": "query", + "description": "付款时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-01-01" + } + }, + { + "name": "paid_date_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/Order" + } + }, + "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": [] + } + ] + } + }, + "/orders/{id}": { + "get": { + "tags": [ + "Orders" + ], + "summary": "订单详情", + "description": "获取订单详情,返回所有业务字段、ext 和关联的 order_items,不含 raw/hash。", + "operationId": "aff126ce9a5cef811fea88ceba395fdc", + "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": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Order" + }, + { + "properties": { + "order_items": { + "description": "关联订单子项", + "type": "array", + "items": { + "type": "object" + } + } + }, + "type": "object" + } + ] + } + }, + "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": [] + } + ] + } + }, + "/order-items": { + "get": { + "tags": [ + "Order Items" + ], + "summary": "订单项列表", + "description": "获取订单项列表,支持分页和多维度筛选。OrderItem 无 raw/hash 字段,仅提供 Normal 接口。", + "operationId": "894b5ea5fad8ecc3159e628333252260", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "order_id", + "in": "query", + "description": "内部订单 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "平台订单 ID 精确筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_product_id", + "in": "query", + "description": "平台商品 ID 精确筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "product_sku", + "in": "query", + "description": "SKU 编码精确筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-01-01" + } + }, + { + "name": "created_date_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/OrderItem" + } + }, + "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": [] + } + ] + } + }, + "/order-items/{id}": { + "get": { + "tags": [ + "Order Items" + ], + "summary": "订单项详情", + "description": "获取订单项详情,返回完整字段和关联的父订单摘要信息。", + "operationId": "a808f2d76861f46925baef81c52da14f", + "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": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/OrderItem" + }, + { + "properties": { + "parent_order": { + "description": "父订单摘要信息", + "type": "object", + "nullable": true + } + }, + "type": "object" + } + ] + } + }, + "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": [] + } + ] + } + }, + "/products": { + "get": { + "tags": [ + "Products" + ], + "summary": "产品列表", + "description": "获取产品列表,支持分页、多维度筛选。返回业务字段,不含 raw/hash。", + "operationId": "934e471439896276d2897b4b5132c077", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "status_id", + "in": "query", + "description": "产品状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_item_id", + "in": "query", + "description": "平台商品 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "description": "商品名称模糊搜索", + "required": false, + "schema": { + "type": "string" + } + } + ], + "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/Product" + } + }, + "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": [] + } + ] + } + }, + "/products/{id}": { + "get": { + "tags": [ + "Products" + ], + "summary": "产品详情", + "description": "获取产品详情,返回所有业务字段和 ext,不含 raw/hash。", + "operationId": "7d7422e8293b23608368a4a9000f8096", + "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/Product" + } + }, + "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": [] + } + ] + } + }, + "/raw/orders": { + "get": { + "tags": [ + "Orders (Raw)" + ], + "summary": "订单列表(Raw)", + "description": "获取订单原始数据列表。返回关键标识 + hash,不含 raw 字段本身(太大)。筛选参数与 Normal 接口一致。", + "operationId": "562f4be5afd7463d1c9c9c653bdd0c35", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "order_status_id", + "in": "query", + "description": "订单状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "平台订单 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "created_date_to", + "in": "query", + "description": "创建时间截止(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "paid_date_from", + "in": "query", + "description": "付款时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "paid_date_to", + "in": "query", + "description": "付款时间截止(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "properties": { + "items": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "order_status_id": { + "type": "integer" + }, + "hash": { + "type": "string" + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "total": { + "type": "integer" + }, + "page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + } + }, + "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": [] + } + ] + } + }, + "/raw/orders/{id}": { + "get": { + "tags": [ + "Orders (Raw)" + ], + "summary": "订单详情(Raw)", + "description": "获取订单原始数据详情。返回关键标识 + 完整 raw + hash + ext。", + "operationId": "6c9b613233d2ef2a708d51523149d84b", + "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": { + "properties": { + "id": { + "type": "integer" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "order_status_id": { + "type": "integer" + }, + "raw": { + "description": "平台原始数据", + "type": "object" + }, + "hash": { + "type": "string" + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "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": [] + } + ] + } + }, + "/raw/products": { + "get": { + "tags": [ + "Products (Raw)" + ], + "summary": "产品列表(Raw)", + "description": "获取产品原始数据列表。返回关键标识 + hash,不含 raw 字段本身(太大)。筛选参数与 Normal 接口一致。", + "operationId": "770fd6e9caf314efbc05aa0277c7e811", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "status_id", + "in": "query", + "description": "产品状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_item_id", + "in": "query", + "description": "平台商品 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "description": "商品名称模糊搜索", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "properties": { + "items": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "platform_item_id": { + "type": "string" + }, + "platform_model_id": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "hash": { + "type": "string" + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "total": { + "type": "integer" + }, + "page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + } + }, + "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": [] + } + ] + } + }, + "/raw/products/{id}": { + "get": { + "tags": [ + "Products (Raw)" + ], + "summary": "产品详情(Raw)", + "description": "获取产品原始数据详情。返回关键标识 + 完整 raw + hash + ext。", + "operationId": "e0ba90775ff4ceb4fe459b8272a63624", + "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": { + "properties": { + "id": { + "type": "integer" + }, + "platform_item_id": { + "type": "string" + }, + "platform_model_id": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string", + "nullable": true + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "raw": { + "description": "平台原始数据", + "type": "object" + }, + "hash": { + "type": "string" + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "type": "object" + } + }, + "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": [] + } + ] + } + }, + "/raw/refunds": { + "get": { + "tags": [ + "Refunds (Raw)" + ], + "summary": "退款列表(Raw)", + "description": "获取退款原始数据列表。返回关键标识 + hash,不含 raw 字段本身(太大)。筛选参数与 Normal 接口一致。", + "operationId": "04e3c7e28df6496b975c24618933c6dd", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_status_id", + "in": "query", + "description": "退款状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_type_id", + "in": "query", + "description": "退款类型 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_refund_id", + "in": "query", + "description": "平台退款 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "关联平台订单 ID 筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "created_date_to", + "in": "query", + "description": "创建时间截止(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "properties": { + "items": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "platform_refund_id": { + "type": "string" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "refund_status_id": { + "type": "integer" + }, + "hash": { + "type": "string" + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "total": { + "type": "integer" + }, + "page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + } + }, + "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": [] + } + ] + } + }, + "/raw/refunds/{id}": { + "get": { + "tags": [ + "Refunds (Raw)" + ], + "summary": "退款详情(Raw)", + "description": "获取退款原始数据详情。返回关键标识 + 完整 raw + hash + ext。", + "operationId": "884b7753642515815a193abb0cae88c9", + "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": { + "properties": { + "id": { + "type": "integer" + }, + "platform_refund_id": { + "type": "string" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "refund_status_id": { + "type": "integer" + }, + "raw": { + "description": "平台原始数据", + "type": "object" + }, + "hash": { + "type": "string" + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "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": [] + } + ] + } + }, + "/raw/refund-items": { + "get": { + "tags": [ + "Refund Items (Raw)" + ], + "summary": "退款项列表(Raw)", + "description": "获取退款项原始数据列表。返回关键标识,不含 raw 字段本身(太大)。筛选参数与 Normal 接口一致。", + "operationId": "b1af2757230f49948c934063da9d627a", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_id", + "in": "query", + "description": "父退款 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_status_id", + "in": "query", + "description": "退款状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_type_id", + "in": "query", + "description": "退款类型 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_refund_id", + "in": "query", + "description": "平台退款子项 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "关联平台订单 ID 筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_product_id", + "in": "query", + "description": "平台商品 ID 精确筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "created_date_to", + "in": "query", + "description": "创建时间截止(含)", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "properties": { + "items": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "platform_refund_id": { + "type": "string" + }, + "platform_parent_refund_id": { + "type": "string" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "refund_status_id": { + "type": "integer" + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "total": { + "type": "integer" + }, + "page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + } + }, + "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": [] + } + ] + } + }, + "/raw/refund-items/{id}": { + "get": { + "tags": [ + "Refund Items (Raw)" + ], + "summary": "退款项详情(Raw)", + "description": "获取退款项原始数据详情。返回关键标识 + 完整 raw + ext。", + "operationId": "6a82a9938eef667456c5a8948b984eb3", + "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": { + "properties": { + "id": { + "type": "integer" + }, + "platform_refund_id": { + "type": "string" + }, + "platform_parent_refund_id": { + "type": "string" + }, + "platform_order_id": { + "type": "string" + }, + "store_id": { + "type": "integer" + }, + "company_id": { + "type": "integer" + }, + "platform_id": { + "type": "integer" + }, + "refund_status_id": { + "type": "integer" + }, + "raw": { + "description": "平台原始子项数据", + "type": "object" + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "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": [] + } + ] + } + }, + "/refunds": { + "get": { + "tags": [ + "Refunds" + ], + "summary": "退款列表", + "description": "获取退款列表,支持分页、按退款状态/类型/时间范围筛选。返回业务字段,不含 raw/hash。", + "operationId": "bd68a8b63be96fc4bc13a7f914db8e6f", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_status_id", + "in": "query", + "description": "退款状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_type_id", + "in": "query", + "description": "退款类型 ID 精确筛选(1=未发货前退款 2=退货退款 3=退货后部分退款 4=无须退货退款 5=闪电退款)", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_refund_id", + "in": "query", + "description": "平台退款 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "关联平台订单 ID 筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-01-01" + } + }, + { + "name": "created_date_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/Refund" + } + }, + "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": [] + } + ] + } + }, + "/refunds/{id}": { + "get": { + "tags": [ + "Refunds" + ], + "summary": "退款详情", + "description": "获取退款详情,返回所有业务字段和 ext,不含 raw/hash。", + "operationId": "6009f4876a61b01d12a288fcfe78444c", + "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/Refund" + } + }, + "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": [] + } + ] + } + }, + "/refund-items": { + "get": { + "tags": [ + "Refund Items" + ], + "summary": "退款项列表", + "description": "获取退款项列表,支持分页、按退款单/退款状态/类型/时间范围筛选。返回业务字段,不含 raw。", + "operationId": "ad798f6022c7e5b289827884ef582bc2", + "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": "company_id", + "in": "query", + "description": "公司 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "平台 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "store_id", + "in": "query", + "description": "店铺 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_id", + "in": "query", + "description": "父退款 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_status_id", + "in": "query", + "description": "退款状态 ID 精确筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "refund_type_id", + "in": "query", + "description": "退款类型 ID 精确筛选(1=仅退款 2=退货退款 3=补偿退款)", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_refund_id", + "in": "query", + "description": "平台退款子项 ID 精确搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_order_id", + "in": "query", + "description": "关联平台订单 ID 筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "platform_product_id", + "in": "query", + "description": "平台商品 ID 精确筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "created_date_from", + "in": "query", + "description": "创建时间起始(含)", + "required": false, + "schema": { + "type": "string", + "format": "date", + "example": "2026-01-01" + } + }, + { + "name": "created_date_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/RefundItem" + } + }, + "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": [] + } + ] + } + }, + "/refund-items/{id}": { + "get": { + "tags": [ + "Refund Items" + ], + "summary": "退款项详情", + "description": "获取退款项详情,返回所有业务字段和 ext,不含 raw。", + "operationId": "de6cf91ff904e528cba6f1b43f829a2c", + "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/RefundItem" + } + }, + "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": [] + } + ] + } + }, + "/me/api-keys": { + "get": { + "tags": [ + "ApiKeys" + ], + "summary": "API Key 列表", + "description": "列出当前用户的所有 API Keys", + "operationId": "c01c1650a1944005fe5b51f72bacbbd4", + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "key_prefix": { + "type": "string" + }, + "last_used_at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "expires_at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "enabled": { + "type": "boolean" + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "post": { + "tags": [ + "ApiKeys" + ], + "summary": "生成 API Key", + "description": "生成新的 API Key,需用户已启用 api_key_enabled。明文仅在生成时返回一次", + "operationId": "12fd3adae0626962960533c85569d1b1", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "Production Key", + "maxLength": 100 + }, + "expires_at": { + "description": "过期时间,不传则永不过期", + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "生成成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "生成成功" + }, + "data": { + "properties": { + "plain_key": { + "description": "明文 Key,仅此次可见", + "type": "string" + }, + "api_key": { + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "key_prefix": { + "type": "string" + }, + "expires_at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "enabled": { + "type": "boolean" + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "未启用 API Key 功能", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/me/api-keys/{id}": { + "delete": { + "tags": [ + "ApiKeys" + ], + "summary": "删除 API Key", + "description": "删除 API Key", + "operationId": "7356615676c0ac3874f8657b49154931", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "API Key ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "删除成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "删除成功" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "API Key 不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/register": { + "post": { + "tags": [ + "Auth" + ], + "summary": "用户注册", + "description": "注册新用户,需提供用户名、密码和邮箱", + "operationId": "b099deca54ae9ddc3ee7e2261b6fc125", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "username", + "password", + "email" + ], + "properties": { + "username": { + "type": "string", + "example": "new_user", + "maxLength": 20, + "minLength": 3 + }, + "password": { + "type": "string", + "example": "Pass_1234", + "maxLength": 32, + "minLength": 6 + }, + "email": { + "type": "string", + "format": "email", + "example": "user@example.com", + "maxLength": 100 + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "注册成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "注册成功" + }, + "data": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "username": { + "type": "string", + "example": "new_user" + }, + "email": { + "type": "string", + "example": "user@example.com" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或唯一性冲突", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/login": { + "post": { + "tags": [ + "Auth" + ], + "summary": "用户登录", + "description": "使用用户名和密码登录,返回 access_token 和 refresh_token", + "operationId": "383bcb1269d6dcce4609dc1f5d3ef129", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "username", + "password" + ], + "properties": { + "username": { + "type": "string", + "example": "admin" + }, + "password": { + "type": "string", + "example": "Pass_1234" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "登录成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "登录成功" + }, + "data": { + "properties": { + "access_token": { + "type": "string" + }, + "refresh_token": { + "type": "string" + }, + "token_type": { + "type": "string", + "example": "Bearer" + }, + "expires_in": { + "type": "integer", + "example": 7200 + }, + "user": { + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "用户名或密码错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "账号已被禁用", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/refresh": { + "get": { + "tags": [ + "Auth" + ], + "summary": "刷新 Access Token", + "description": "使用 refresh_token 获取新的 access_token,同时轮换 refresh_token", + "operationId": "fc18486b361cc4791acbafd8a2f25fff", + "parameters": [ + { + "name": "refresh_token", + "in": "query", + "description": "Refresh Token", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Token 刷新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "Token 刷新成功" + }, + "data": { + "properties": { + "access_token": { + "type": "string" + }, + "refresh_token": { + "type": "string" + }, + "token_type": { + "type": "string", + "example": "Bearer" + }, + "expires_in": { + "type": "integer", + "example": 7200 + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "缺少 refresh_token 参数", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "refresh_token 无效或已过期", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "账号已被禁用", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/me": { + "get": { + "tags": [ + "Auth" + ], + "summary": "获取当前用户信息", + "description": "获取当前用户信息", + "operationId": "f03c8d46af839b7dbd0b659647cab574", + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "username": { + "type": "string", + "example": "admin" + }, + "email": { + "type": "string", + "example": "admin@example.com" + }, + "status": { + "type": "integer", + "example": 1 + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/me/profile": { + "put": { + "tags": [ + "Auth" + ], + "summary": "更新个人信息", + "description": "当前用户更新自己的 email 和 ext 字段", + "operationId": "01c6d8f425109cd3dfff51d1d69cd55c", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "new@example.com", + "maxLength": 100 + }, + "ext": { + "type": "object", + "example": { + "nickname": "user" + }, + "nullable": true + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "个人信息更新成功" + }, + "data": { + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或唯一性冲突", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/me/password": { + "put": { + "tags": [ + "Auth" + ], + "summary": "修改密码", + "description": "修改当前用户密码,需验证旧密码。修改成功后清除 refresh_token,需重新登录", + "operationId": "c3ca37414997ba697e6c11173d9bc483", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "old_password", + "new_password" + ], + "properties": { + "old_password": { + "type": "string", + "example": "OldPass_1234" + }, + "new_password": { + "type": "string", + "example": "NewPass_5678", + "maxLength": 32, + "minLength": 6 + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "密码修改成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "密码修改成功,请重新登录" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或旧密码不正确", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/logout": { + "get": { + "tags": [ + "Auth" + ], + "summary": "退出登录", + "description": "退出登录,清除 refresh_token 并注销当前 JWT token", + "operationId": "dc5f3d60e870dd8b211f88cd97635158", + "responses": { + "200": { + "description": "退出成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "退出成功" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/companies": { + "get": { + "tags": [ + "Companies" + ], + "summary": "公司列表", + "description": "获取公司列表,支持按 name/label 模糊搜索,受 scope 过滤", + "operationId": "e3e4d8f38acabbb4c061ba987d6e14dc", + "parameters": [ + { + "name": "name", + "in": "query", + "description": "公司名称模糊搜索(匹配 name 或 label)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "acme" + }, + "label": { + "type": "string", + "example": "阿克米公司" + }, + "enabled": { + "type": "boolean", + "example": true + }, + "ext": { + "type": "object", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/users/{id}/data-scope": { + "get": { + "tags": [ + "DataScope" + ], + "summary": "查看用户数据权限", + "description": "返回用户的 scope 列表(含实体名称)和解析后的 store_ids", + "operationId": "0215f552f5c2315b8b93d030ef72db76", + "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": { + "properties": { + "user_id": { + "type": "integer", + "example": 1 + }, + "role": { + "type": "string", + "example": "admin" + }, + "scopes": { + "type": "array", + "items": { + "properties": { + "scope_type": { + "type": "string", + "example": "company" + }, + "scope_id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "示例公司" + } + }, + "type": "object" + } + }, + "resolved_store_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "example": [ + 1, + 2, + 3 + ] + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "put": { + "tags": [ + "DataScope" + ], + "summary": "设置用户数据权限", + "description": "全量替换用户的 scope 绑定,并重建 bitmap", + "operationId": "4ff88235674fa406239c90406f051994", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "用户 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "scopes" + ], + "properties": { + "scopes": { + "type": "array", + "items": { + "required": [ + "scope_type", + "scope_id" + ], + "properties": { + "scope_type": { + "type": "string", + "example": "company", + "enum": [ + "company", + "platform", + "store" + ] + }, + "scope_id": { + "type": "integer", + "example": 1 + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "数据权限更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "数据权限更新成功" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败(无效 scope_type 等)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/platforms": { + "get": { + "tags": [ + "Platforms" + ], + "summary": "平台列表", + "description": "获取全部平台列表(全局数据,不过滤)", + "operationId": "5ff5cb3822eee3a87c0387f6a5ad4637", + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "developer_id": { + "type": "integer", + "example": 1 + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/roles": { + "get": { + "tags": [ + "Roles" + ], + "summary": "角色列表", + "description": "获取所有角色,包含每个角色的用户数", + "operationId": "9a543d6f94510bc9ca9208afc0b4715c", + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "editor" + }, + "users_count": { + "type": "integer", + "example": 5 + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/users/{id}/role": { + "put": { + "tags": [ + "Roles" + ], + "summary": "分配用户角色", + "description": "为指定用户分配角色,administrator 不允许降级自己的角色", + "operationId": "49884e2548d00ed9b195e873b2dd3934", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "用户 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "role_id" + ], + "properties": { + "role_id": { + "description": "角色 ID", + "type": "integer", + "example": 2 + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "角色分配成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "角色分配成功" + }, + "data": { + "$ref": "#/components/schemas/User" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "不允许降级自己的管理员角色", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户或角色不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/roles/{id}/route-groups": { + "get": { + "tags": [ + "Roles" + ], + "summary": "查看角色已授权的路由组", + "description": "获取指定角色已授权的路由组列表", + "operationId": "25aba1fb2a9a4cc81e1bf06c716deda9", + "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": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "角色不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "put": { + "tags": [ + "Roles" + ], + "summary": "设置角色的路由组授权", + "description": "全量替换指定角色的路由组授权,administrator 角色不允许修改", + "operationId": "1e1f0c23e58bc994ea055407eb469a37", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "角色 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "group_ids" + ], + "properties": { + "group_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "example": [ + 1, + 3, + 5 + ] + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "路由组授权更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "路由组授权更新成功" + }, + "data": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "administrator 角色不允许修改或参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "角色不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/roles/{id}/route-overrides": { + "get": { + "tags": [ + "Roles" + ], + "summary": "查看角色的路由覆盖", + "description": "获取指定角色的路由覆盖列表,包含路由详情", + "operationId": "7766effa17b431f2bcd67b1f434ee042", + "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": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "role_id": { + "type": "integer" + }, + "route_id": { + "type": "integer" + }, + "allowed": { + "type": "boolean" + }, + "route": { + "type": "object" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "角色不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "put": { + "tags": [ + "Roles" + ], + "summary": "设置角色的路由覆盖", + "description": "全量替换指定角色的路由覆盖规则,administrator 角色不允许修改", + "operationId": "7ab36e126b6eb4e7631cc7b51b5d2779", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "角色 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "overrides" + ], + "properties": { + "overrides": { + "type": "array", + "items": { + "required": [ + "route_id", + "allowed" + ], + "properties": { + "route_id": { + "description": "路由 ID", + "type": "integer", + "example": 12 + }, + "allowed": { + "description": "是否允许", + "type": "boolean", + "example": false + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "路由覆盖更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "路由覆盖更新成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer" + }, + "role_id": { + "type": "integer" + }, + "route_id": { + "type": "integer" + }, + "allowed": { + "type": "boolean" + }, + "route": { + "type": "object" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "route_id 重复、不存在或 administrator 角色不允许修改", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "角色不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/route-groups": { + "get": { + "tags": [ + "RouteGroups" + ], + "summary": "路由组列表", + "description": "返回所有路由组,包含每组的路由数量", + "operationId": "dc2a90e0b1d08db3762003eac4f93598", + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "user-management" + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true + }, + "description": { + "type": "string", + "example": "用户相关路由", + "nullable": true + }, + "sort_order": { + "type": "integer", + "example": 0 + }, + "routes_count": { + "type": "integer", + "example": 5 + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "post": { + "tags": [ + "RouteGroups" + ], + "summary": "创建路由组", + "description": "创建路由组", + "operationId": "5796b5d8d366ca24bd7b850510fdc77d", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "user-management", + "maxLength": 100 + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true, + "maxLength": 200 + }, + "description": { + "type": "string", + "example": "用户相关路由", + "nullable": true + }, + "sort_order": { + "type": "integer", + "example": 0, + "default": 0 + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "创建成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "创建成功" + }, + "data": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "user-management" + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "sort_order": { + "type": "integer", + "example": 0 + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或名称重复", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/route-groups/{id}": { + "put": { + "tags": [ + "RouteGroups" + ], + "summary": "更新路由组", + "description": "更新路由组", + "operationId": "08ab6c0eb639ed8c3c7b2aa5151f3f8b", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "路由组 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "name": { + "type": "string", + "example": "user-management", + "maxLength": 100 + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true, + "maxLength": 200 + }, + "description": { + "type": "string", + "example": "用户相关路由", + "nullable": true + }, + "sort_order": { + "type": "integer", + "example": 0 + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "更新成功" + }, + "data": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "user-management" + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "sort_order": { + "type": "integer", + "example": 0 + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或名称重复", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "路由组不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "delete": { + "tags": [ + "RouteGroups" + ], + "summary": "删除路由组", + "description": "删除路由组,组内路由 group_id 自动设为 NULL,role_route_groups 关联自动级联删除", + "operationId": "2b870b541944a9318469fafc2ad83834", + "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": "删除成功" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "路由组不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/routes": { + "get": { + "tags": [ + "RouteGroups" + ], + "summary": "路由列表", + "description": "获取全部路由列表,含分组信息,支持按 group_id、method、path 筛选", + "operationId": "06fcdb734181d39362a999d1599a5e66", + "parameters": [ + { + "name": "group_id", + "in": "query", + "description": "路由组 ID,传 0 或 \"ungrouped\" 筛选未分组路由", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "method", + "in": "query", + "description": "HTTP 方法筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "path", + "in": "query", + "description": "路径模糊搜索", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "method": { + "type": "string", + "example": "GET" + }, + "path": { + "type": "string", + "example": "/api/v1/users" + }, + "group_id": { + "type": "integer", + "example": 1, + "nullable": true + }, + "group": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "user-management" + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true + } + }, + "type": "object", + "nullable": true + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/routes/{id}/group": { + "put": { + "tags": [ + "RouteGroups" + ], + "summary": "分配路由到路由组", + "description": "将路由分配到指定路由组,传 group_id=null 表示从分组中移出", + "operationId": "10daee20cc95a281bc0bc3716df103aa", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "路由 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "group_id" + ], + "properties": { + "group_id": { + "description": "路由组 ID,传 null 移出分组", + "type": "integer", + "example": 1, + "nullable": true + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "分配成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "分配成功" + }, + "data": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "method": { + "type": "string", + "example": "GET" + }, + "path": { + "type": "string", + "example": "/api/v1/users" + }, + "group_id": { + "type": "integer", + "example": 1, + "nullable": true + }, + "group": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "user-management" + }, + "label": { + "type": "string", + "example": "用户管理", + "nullable": true + } + }, + "type": "object", + "nullable": true + } + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "路由或目标路由组不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/stores": { + "get": { + "tags": [ + "Stores" + ], + "summary": "店铺列表", + "description": "获取店铺列表,受 scope 过滤,支持 company_id/platform_id 筛选及 name 模糊搜索", + "operationId": "36279ef5f2735b2624e99a82ebc3dccc", + "parameters": [ + { + "name": "company_id", + "in": "query", + "description": "按公司 ID 筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "platform_id", + "in": "query", + "description": "按平台 ID 筛选", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "name", + "in": "query", + "description": "按店铺名称模糊搜索", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "获取成功" + }, + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 1 + }, + "platform_store_id": { + "type": "string", + "example": "SHOP-001" + }, + "name": { + "type": "string", + "example": "my-store" + }, + "label": { + "type": "string", + "example": "我的店铺" + }, + "enabled": { + "type": "boolean", + "example": true + }, + "warehouse_id": { + "type": "integer", + "example": 1 + }, + "currency_id": { + "type": "integer", + "example": 1 + }, + "timezone": { + "type": "integer", + "example": 8 + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + } + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/users": { + "get": { + "tags": [ + "Users" + ], + "summary": "用户列表", + "description": "获取用户列表,支持分页、按 username/email 模糊搜索、按 status 精确筛选", + "operationId": "4f028975120b69092c0eae73bb36bcac", + "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": "username", + "in": "query", + "description": "用户名模糊搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "email", + "in": "query", + "description": "邮箱模糊搜索", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "状态筛选(0=禁用,1=启用)", + "required": false, + "schema": { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + } + ], + "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/User" + } + }, + "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" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "post": { + "tags": [ + "Users" + ], + "summary": "创建用户", + "description": "创建用户", + "operationId": "0b5969ce7b77ccaa0b2e9b551e302980", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "username", + "password", + "email" + ], + "properties": { + "username": { + "type": "string", + "example": "new_user", + "maxLength": 20, + "minLength": 3 + }, + "password": { + "type": "string", + "example": "Pass_1234", + "maxLength": 32, + "minLength": 6 + }, + "email": { + "type": "string", + "format": "email", + "example": "new@example.com", + "maxLength": 100 + }, + "status": { + "type": "integer", + "default": 1, + "enum": [ + 0, + 1 + ] + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "创建成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "创建成功" + }, + "data": { + "$ref": "#/components/schemas/User" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或唯一性冲突", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/users/{id}": { + "get": { + "tags": [ + "Users" + ], + "summary": "用户详情", + "description": "用户详情", + "operationId": "b0770c8ad8eb11c5493fe9643c657673", + "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/User" + } + }, + "type": "object" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + }, + "put": { + "tags": [ + "Users" + ], + "summary": "更新用户信息", + "description": "更新用户的 username、email 或 ext 字段,不支持修改密码", + "operationId": "c5ee224e653aac218896c93ecc3f9b67", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "用户 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "username": { + "type": "string", + "example": "updated_user", + "maxLength": 20, + "minLength": 3 + }, + "email": { + "type": "string", + "format": "email", + "example": "updated@example.com", + "maxLength": 100 + }, + "ext": { + "type": "object", + "example": { + "nickname": "Tester" + }, + "nullable": true + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "更新成功" + }, + "data": { + "$ref": "#/components/schemas/User" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败或唯一性冲突", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/users/{id}/status": { + "patch": { + "tags": [ + "Users" + ], + "summary": "更新用户状态", + "description": "启用或禁用用户", + "operationId": "c1ad72b12757d083cf0aebbf2f3787fd", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "用户 ID", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "required": [ + "status" + ], + "properties": { + "status": { + "description": "0=禁用,1=启用", + "type": "integer", + "enum": [ + 0, + 1 + ] + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "状态更新成功", + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "状态更新成功" + }, + "data": { + "$ref": "#/components/schemas/User" + } + }, + "type": "object" + } + } + } + }, + "400": { + "description": "参数校验失败", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "未认证", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "用户不存在", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + } + }, + "components": { + "schemas": { + "Order": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 2 + }, + "store_id": { + "type": "integer", + "example": 100 + }, + "order_status_id": { + "type": "integer", + "example": 1 + }, + "platform_order_id": { + "type": "string", + "example": "ORD-20260101-001" + }, + "buyer_user_id": { + "type": "string", + "example": "buyer_123", + "nullable": true + }, + "payment_method_id": { + "type": "integer", + "example": 1 + }, + "presale": { + "type": "boolean", + "example": false + }, + "total_amount": { + "type": "number", + "format": "decimal", + "example": 199.99 + }, + "total_paid": { + "type": "number", + "format": "decimal", + "example": 189.99 + }, + "total_discount": { + "type": "number", + "format": "decimal", + "example": 10 + }, + "total_received": { + "type": "number", + "format": "decimal", + "example": 189.99 + }, + "freight_fee": { + "type": "number", + "format": "decimal", + "example": 0 + }, + "tax_fee": { + "type": "number", + "format": "decimal", + "example": 0 + }, + "discount_fee": { + "type": "number", + "format": "decimal", + "example": 10 + }, + "commission_fee": { + "type": "number", + "format": "decimal", + "example": 5 + }, + "coupon_amount": { + "type": "number", + "format": "decimal", + "example": 0 + }, + "voucher_amount": { + "type": "number", + "format": "decimal", + "example": 0 + }, + "order_type_id": { + "type": "integer", + "example": 1 + }, + "hash": { + "type": "string", + "example": "a1b2c3d4e5f6..." + }, + "raw": { + "description": "平台原始数据", + "type": "object", + "nullable": true + }, + "ext": { + "description": "扩展字段", + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "paid_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "shipping_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "OrderItem": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 2 + }, + "store_id": { + "type": "integer", + "example": 100 + }, + "order_id": { + "type": "integer", + "example": 1000 + }, + "platform_order_id": { + "type": "string", + "example": "ORD-20260101-001" + }, + "sub_order_id": { + "type": "string", + "example": "SUB-001", + "nullable": true + }, + "sub_order_type_id": { + "type": "integer", + "example": 1 + }, + "product_id": { + "type": "integer", + "example": 500 + }, + "platform_product_id": { + "type": "string", + "example": "PROD-001" + }, + "product_sku": { + "type": "string", + "example": "SKU-ABC-001", + "nullable": true + }, + "product_barcode": { + "type": "string", + "example": "6901234567890", + "nullable": true + }, + "unit_price": { + "type": "number", + "format": "decimal", + "example": 49.99 + }, + "quantity": { + "type": "integer", + "example": 2 + }, + "discount": { + "type": "number", + "format": "decimal", + "example": 5 + }, + "total": { + "type": "number", + "format": "decimal", + "example": 94.98 + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "ext": { + "description": "扩展字段", + "type": "object", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "Product": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 2 + }, + "store_id": { + "type": "integer", + "example": 100 + }, + "status_id": { + "type": "integer", + "example": 1 + }, + "type_id": { + "type": "integer", + "example": 1 + }, + "platform_item_id": { + "type": "string", + "example": "ITEM-001" + }, + "platform_model_id": { + "type": "string", + "example": "MODEL-A", + "nullable": true + }, + "name": { + "type": "string", + "example": "iPhone 16 Pro", + "nullable": true + }, + "price": { + "type": "number", + "format": "decimal", + "example": 99.99 + }, + "currency": { + "type": "string", + "example": "CNY" + }, + "num": { + "type": "integer", + "example": 100 + }, + "hash": { + "type": "string", + "example": "a1b2c3d4e5f6..." + }, + "raw": { + "description": "平台原始数据", + "type": "object", + "nullable": true + }, + "ext": { + "description": "扩展字段", + "type": "object", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "Refund": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 2 + }, + "store_id": { + "type": "integer", + "example": 100 + }, + "order_id": { + "type": "integer", + "example": 500, + "nullable": true + }, + "platform_order_id": { + "type": "string", + "example": "ORD-20260101-001" + }, + "platform_refund_id": { + "type": "string", + "example": "RF-20260115-001" + }, + "refund_status_id": { + "type": "integer", + "example": 1 + }, + "refund_type_id": { + "type": "integer", + "example": 2 + }, + "reason": { + "type": "string", + "example": "商品质量问题", + "nullable": true + }, + "buyer_user_id": { + "type": "string", + "example": "buyer_123", + "nullable": true + }, + "refund_amount": { + "type": "number", + "format": "decimal", + "example": 99.99 + }, + "freight_refund": { + "type": "number", + "format": "decimal", + "example": 10 + }, + "refund_total": { + "type": "number", + "format": "decimal", + "example": 109.99 + }, + "currency": { + "type": "string", + "example": "CNY" + }, + "hash": { + "type": "string", + "example": "a1b2c3d4e5f6..." + }, + "raw": { + "description": "平台原始数据", + "type": "object", + "nullable": true + }, + "ext": { + "description": "扩展字段", + "type": "object", + "nullable": true + }, + "order_created_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "order_paid_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completed_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "RefundItem": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "company_id": { + "type": "integer", + "example": 1 + }, + "platform_id": { + "type": "integer", + "example": 2 + }, + "store_id": { + "type": "integer", + "example": 100 + }, + "refund_id": { + "type": "integer", + "example": 50 + }, + "platform_parent_refund_id": { + "type": "string", + "example": "PRF-001", + "nullable": true + }, + "platform_refund_id": { + "type": "string", + "example": "RF-ITEM-001" + }, + "refund_status_id": { + "type": "integer", + "example": 1 + }, + "refund_type_id": { + "type": "integer", + "example": 2 + }, + "reason": { + "type": "string", + "example": "商品质量问题", + "nullable": true + }, + "currency": { + "type": "string", + "example": "CNY" + }, + "buyer_user_id": { + "type": "string", + "example": "buyer_123", + "nullable": true + }, + "platform_order_id": { + "type": "string", + "example": "ORD-20260101-001" + }, + "platform_sub_order_id": { + "type": "string", + "example": "SUB-001", + "nullable": true + }, + "platform_product_id": { + "type": "string", + "example": "PROD-001", + "nullable": true + }, + "quantity": { + "type": "integer", + "example": 1 + }, + "refund_amount": { + "type": "number", + "format": "decimal", + "example": 99.99 + }, + "raw": { + "description": "平台原始子项数据", + "type": "object", + "nullable": true + }, + "ext": { + "description": "扩展字段", + "type": "object", + "nullable": true + }, + "order_created_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "order_paid_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_date": { + "type": "string", + "format": "date-time" + }, + "updated_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completed_date": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "User": { + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "username": { + "type": "string", + "example": "user_1234" + }, + "email": { + "type": "string", + "example": "user@example.com" + }, + "status": { + "type": "integer", + "example": 1 + }, + "role_id": { + "type": "integer", + "example": 1, + "nullable": true + }, + "api_key_enabled": { + "type": "boolean", + "example": false + }, + "ext": { + "type": "object", + "example": { + "nickname": "user" + }, + "nullable": true + }, + "refresh_token_expires_at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "type": "object" + }, + "ApiResponse": { + "properties": { + "code": { + "type": "integer", + "example": 0 + }, + "message": { + "type": "string", + "example": "success" + }, + "data": { + "type": "object", + "nullable": true + } + }, + "type": "object" + }, + "PaginatedData": { + "properties": { + "items": { + "type": "array", + "items": {} + }, + "total": { + "type": "integer", + "example": 0 + }, + "page": { + "type": "integer", + "example": 1 + }, + "per_page": { + "type": "integer", + "example": 15 + } + }, + "type": "object" + }, + "ErrorResponse": { + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad request" + }, + "data": { + "type": "object", + "nullable": true + } + }, + "type": "object" + }, + "MqQueueInfo": { + "description": "单个队列的状态信息", + "properties": { + "queue": { + "description": "队列名称", + "type": "string", + "example": "orders.queue" + }, + "messages": { + "description": "消息数量(异常时为 N/A)", + "example": 5, + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ] + }, + "consumers": { + "description": "消费者数量(异常时为 N/A)", + "example": 1, + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ] + }, + "status": { + "description": "队列状态", + "type": "string", + "example": "active", + "enum": [ + "high_load", + "processing", + "active", + "empty", + "error" + ] + } + }, + "type": "object" + }, + "MqQueueStatus": { + "description": "消息队列全量状态", + "properties": { + "business_queues": { + "description": "业务队列列表", + "type": "array", + "items": { + "$ref": "#/components/schemas/MqQueueInfo" + } + }, + "retry_queues": { + "description": "重试队列列表", + "type": "array", + "items": { + "$ref": "#/components/schemas/MqQueueInfo" + } + }, + "error_queue": { + "$ref": "#/components/schemas/MqQueueInfo" + }, + "summary": { + "description": "汇总统计", + "properties": { + "total_messages": { + "description": "消息总数", + "type": "integer", + "example": 7 + }, + "total_consumers": { + "description": "消费者总数", + "type": "integer", + "example": 1 + } + }, + "type": "object" + }, + "fetched_at": { + "description": "数据获取时间", + "type": "string", + "format": "date-time", + "example": "2026-03-13 12:00:00" + } + }, + "type": "object" + } + }, + "securitySchemes": { + "bearerAuth": { + "type": "http", + "bearerFormat": "JWT", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "name": "X-API-Key", + "in": "header" + } + } + }, + "tags": [ + { + "name": "MQ Status", + "description": "消息队列状态监控" + }, + { + "name": "Orders", + "description": "订单管理" + }, + { + "name": "Order Items", + "description": "订单项管理" + }, + { + "name": "Products", + "description": "产品管理" + }, + { + "name": "Orders (Raw)", + "description": "订单原始数据" + }, + { + "name": "Products (Raw)", + "description": "产品原始数据" + }, + { + "name": "Refunds (Raw)", + "description": "退款原始数据" + }, + { + "name": "Refund Items (Raw)", + "description": "退款项原始数据" + }, + { + "name": "Refunds", + "description": "退款管理" + }, + { + "name": "Refund Items", + "description": "退款项管理" + }, + { + "name": "ApiKeys", + "description": "API Key 管理" + }, + { + "name": "Auth", + "description": "认证与个人信息" + }, + { + "name": "Companies", + "description": "公司管理" + }, + { + "name": "DataScope", + "description": "用户数据范围管理" + }, + { + "name": "Platforms", + "description": "平台管理" + }, + { + "name": "Roles", + "description": "角色与授权管理" + }, + { + "name": "RouteGroups", + "description": "路由组管理" + }, + { + "name": "Stores", + "description": "店铺管理" + }, + { + "name": "Users", + "description": "用户管理" + } + ] +} \ No newline at end of file diff --git a/backend/test/Cases/Integration/System/MqStatusControllerTest.php b/backend/test/Cases/Integration/System/MqStatusControllerTest.php new file mode 100644 index 0000000..dcafbe6 --- /dev/null +++ b/backend/test/Cases/Integration/System/MqStatusControllerTest.php @@ -0,0 +1,101 @@ +get('/api/v1/mq/status', [], $this->authHeaders()); + + // RabbitMQ 可能不可用,接受 200 或 500 + $status = $response->getStatusCode(); + if ($status === 500) { + // 连接不可用时返回 500,仍验证响应格式 + $response->assertJsonStructure(['code', 'message', 'data']); + $this->assertSame(500, $response->json('code')); + return; + } + + $response->assertStatus(200); + $response->assertJsonPath('code', 0); + $response->assertJsonPath('message', '获取成功'); + $response->assertJsonStructure([ + 'code', + 'message', + 'data' => [ + 'business_queues', + 'retry_queues', + 'error_queue', + 'summary' => [ + 'total_messages', + 'total_consumers', + ], + 'fetched_at', + ], + ]); + } + + // ========== 队列类型筛选 ========== + + public function test_mq_status_with_valid_queue_filter(): void + { + $response = $this->get('/api/v1/mq/status', ['queue' => 'orders'], $this->authHeaders()); + + $status = $response->getStatusCode(); + if ($status === 500) { + // RabbitMQ 不可用,跳过具体数据验证 + return; + } + + $response->assertStatus(200); + $response->assertJsonPath('code', 0); + + $data = $response->json('data'); + + // 筛选时 business_queues 仅包含 orders.queue + foreach ($data['business_queues'] as $queue) { + $this->assertStringContainsString('orders', $queue['queue']); + } + + // 筛选时 error_queue 为空数组(仅全量查询时返回) + $this->assertEmpty($data['error_queue']); + } + + // ========== 无效参数 ========== + + public function test_mq_status_with_invalid_queue_returns_400(): void + { + $response = $this->get('/api/v1/mq/status', ['queue' => 'invalid_type'], $this->authHeaders()); + + $response->assertStatus(400); + $this->assertSame(400, $response->json('code')); + $this->assertStringContainsString('无效的队列类型', $response->json('message')); + } + + // ========== 认证检查 ========== + + public function test_mq_status_without_token_returns_401(): void + { + $response = $this->get('/api/v1/mq/status'); + + $response->assertStatus(401); + } +} diff --git a/backend/test/Cases/Unit/Service/MqStatusServiceTest.php b/backend/test/Cases/Unit/Service/MqStatusServiceTest.php new file mode 100644 index 0000000..d11a979 --- /dev/null +++ b/backend/test/Cases/Unit/Service/MqStatusServiceTest.php @@ -0,0 +1,101 @@ +createMock(ConfigInterface::class); + $this->service = new MqStatusService($config); + } + + // ========== getValidQueueTypes ========== + + public function test_get_valid_queue_types_returns_correct_list(): void + { + $types = $this->service->getValidQueueTypes(); + + $this->assertIsArray($types); + $this->assertContains('orders', $types); + $this->assertContains('products', $types); + $this->assertContains('refunds', $types); + $this->assertContains('inventory', $types); + $this->assertCount(4, $types); + } + + // ========== getQueueStatus 状态判定 ========== + + public function test_status_high_load_when_messages_over_100(): void + { + $this->assertSame('high_load', $this->service->getQueueStatus(101)); + $this->assertSame('high_load', $this->service->getQueueStatus(500)); + $this->assertSame('high_load', $this->service->getQueueStatus(10000)); + } + + public function test_status_processing_when_messages_over_10(): void + { + $this->assertSame('processing', $this->service->getQueueStatus(11)); + $this->assertSame('processing', $this->service->getQueueStatus(50)); + $this->assertSame('processing', $this->service->getQueueStatus(100)); + } + + public function test_status_active_when_messages_over_0(): void + { + $this->assertSame('active', $this->service->getQueueStatus(1)); + $this->assertSame('active', $this->service->getQueueStatus(5)); + $this->assertSame('active', $this->service->getQueueStatus(10)); + } + + public function test_status_empty_when_no_messages(): void + { + $this->assertSame('empty', $this->service->getQueueStatus(0)); + } + + // ========== 边界值测试 ========== + + public function test_status_boundary_at_exactly_100(): void + { + // 100 条消息 → processing(> 10 且 <= 100) + $this->assertSame('processing', $this->service->getQueueStatus(100)); + } + + public function test_status_boundary_at_exactly_10(): void + { + // 10 条消息 → active(> 0 且 <= 10) + $this->assertSame('active', $this->service->getQueueStatus(10)); + } + + public function test_status_boundary_at_exactly_1(): void + { + $this->assertSame('active', $this->service->getQueueStatus(1)); + } + + // ========== QUEUE_TYPES 常量 ========== + + public function test_queue_types_constant_matches_valid_types(): void + { + $this->assertSame( + MqStatusService::QUEUE_TYPES, + $this->service->getValidQueueTypes() + ); + } +}