diff --git a/application/api/controller/GiftBase.php b/application/api/controller/GiftBase.php
new file mode 100644
index 00000000..a58ec581
--- /dev/null
+++ b/application/api/controller/GiftBase.php
@@ -0,0 +1,301 @@
+giftModel = new GiveGiftBase();
+ }
+
+ /**
+ * 获取送礼记录
+ */
+ public function getGiftRecords()
+ {
+ $params = $this->request->param();
+
+ $where = [];
+ $options = [];
+
+ // 构建查询条件
+ if (!empty($params['from_id'])) {
+ $where['from_id'] = $params['from_id'];
+ }
+ if (!empty($params['user_id'])) {
+ $where['user_id'] = $params['user_id'];
+ }
+ if (!empty($params['gift_user'])) {
+ $where['gift_user'] = $params['gift_user'];
+ }
+ if (!empty($params['gift_id'])) {
+ $where['gift_id'] = $params['gift_id'];
+ }
+ if (!empty($params['type'])) {
+ $where['type'] = $params['type'];
+ }
+ if (!empty($params['from'])) {
+ $where['from'] = $params['from'];
+ }
+ if (!empty($params['gift_type'])) {
+ $where['gift_type'] = $params['gift_type'];
+ }
+
+ // 时间范围
+ if (!empty($params['start_time'])) {
+ $options['start_time'] = intval($params['start_time']);
+ }
+ if (!empty($params['end_time'])) {
+ $options['end_time'] = intval($params['end_time']);
+ }
+
+ // 分页参数
+ $options['page'] = $params['page'] ?? 1;
+ $options['limit'] = min($params['limit'] ?? 20, 100); // 限制最大100条
+
+ // 排序
+ if (!empty($params['order'])) {
+ $options['order'] = $params['order'];
+ }
+
+ // 查询数据
+ $result = $this->giftModel->getGiftRecords($where, $options);
+
+ Log::info("查询送礼记录,条件: " . json_encode($where) . ", 结果数: " . count($result['data']));
+
+ $this->success('获取成功', $result);
+ }
+
+ /**
+ * 房间送礼统计
+ */
+ public function getRoomStatistics()
+ {
+ $fromId = $this->request->param('from_id/d', 0);
+ $startTime = $this->request->param('start_time/d', strtotime('-7 days'));
+ $endTime = $this->request->param('end_time/d', time());
+
+ if (!$fromId) {
+ $this->error('房间ID不能为空');
+ }
+
+ // 尝试从缓存获取
+ $cacheKey = "gift:room:stats:{$fromId}:" . date('Ymd', $startTime) . '-' . date('Ymd', $endTime);
+ $cachedData = Cache::get($cacheKey);
+
+ if ($cachedData !== false) {
+ Log::info("从缓存获取房间统计: {$cacheKey}");
+ $this->success('获取成功', $cachedData);
+ }
+
+ $where = ['from_id' => $fromId];
+ $options = [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ ];
+
+ // 统计房间总数据
+ $totalStats = $this->giftModel->getGiftStatistics($where, $options);
+
+ // 按送礼人分组统计
+ $userStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'user_id'
+ ]));
+
+ // 按收礼人分组统计
+ $receiverStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'gift_user'
+ ]));
+
+ $result = [
+ 'room_id' => $fromId,
+ 'time_range' => [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ 'start_date' => date('Y-m-d H:i:s', $startTime),
+ 'end_date' => date('Y-m-d H:i:s', $endTime),
+ ],
+ 'total_stats' => $totalStats,
+ 'user_stats' => $userStats,
+ 'receiver_stats' => $receiverStats,
+ ];
+
+ // 缓存5分钟
+ Cache::set($cacheKey, $result, 300);
+
+ Log::info("房间统计计算完成: {$fromId}, 送礼人数: " . count($userStats) . ", 收礼人数: " . count($receiverStats));
+
+ $this->success('获取成功', $result);
+ }
+
+ /**
+ * 用户送礼统计
+ */
+ public function getUserStatistics()
+ {
+ $userId = $this->request->param('user_id/d', 0);
+ $startTime = $this->request->param('start_time/d', strtotime('-30 days'));
+ $endTime = $this->request->param('end_time/d', time());
+
+ if (!$userId) {
+ $this->error('用户ID不能为空');
+ }
+
+ $cacheKey = "gift:user:stats:{$userId}:" . date('Ymd', $startTime) . '-' . date('Ymd', $endTime);
+ $cachedData = Cache::get($cacheKey);
+
+ if ($cachedData !== false) {
+ Log::info("从缓存获取用户统计: {$cacheKey}");
+ $this->success('获取成功', $cachedData);
+ }
+
+ $where = ['user_id' => $userId];
+ $options = [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ ];
+
+ // 用户总送礼统计
+ $totalStats = $this->giftModel->getGiftStatistics($where, $options);
+
+ // 按房间分组统计
+ $roomStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'from_id'
+ ]));
+
+ // 按收礼人分组统计
+ $receiverStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'gift_user'
+ ]));
+
+ $result = [
+ 'user_id' => $userId,
+ 'time_range' => [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ 'start_date' => date('Y-m-d H:i:s', $startTime),
+ 'end_date' => date('Y-m-d H:i:s', $endTime),
+ ],
+ 'total_stats' => $totalStats,
+ 'room_stats' => $roomStats,
+ 'receiver_stats' => $receiverStats,
+ ];
+
+ // 缓存5分钟
+ Cache::set($cacheKey, $result, 300);
+
+ Log::info("用户统计计算完成: {$userId}, 房间数: " . count($roomStats) . ", 收礼人数: " . count($receiverStats));
+
+ $this->success('获取成功', $result);
+ }
+
+ /**
+ * 收礼统计
+ */
+ public function getReceiveStatistics()
+ {
+ $giftUser = $this->request->param('gift_user/d', 0);
+ $startTime = $this->request->param('start_time/d', strtotime('-30 days'));
+ $endTime = $this->request->param('end_time/d', time());
+
+ if (!$giftUser) {
+ $this->error('用户ID不能为空');
+ }
+
+ $cacheKey = "gift:receive:stats:{$giftUser}:" . date('Ymd', $startTime) . '-' . date('Ymd', $endTime);
+ $cachedData = Cache::get($cacheKey);
+
+ if ($cachedData !== false) {
+ Log::info("从缓存获取收礼统计: {$cacheKey}");
+ $this->success('获取成功', $cachedData);
+ }
+
+ $where = ['gift_user' => $giftUser];
+ $options = [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ ];
+
+ // 总收礼统计
+ $totalStats = $this->giftModel->getGiftStatistics($where, $options);
+
+ // 按房间分组统计
+ $roomStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'from_id'
+ ]));
+
+ // 按送礼人分组统计
+ $giverStats = $this->giftModel->getGiftStatistics($where, array_merge($options, [
+ 'group_by' => 'user_id'
+ ]));
+
+ $result = [
+ 'gift_user' => $giftUser,
+ 'time_range' => [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime,
+ 'start_date' => date('Y-m-d H:i:s', $startTime),
+ 'end_date' => date('Y-m-d H:i:s', $endTime),
+ ],
+ 'total_stats' => $totalStats,
+ 'room_stats' => $roomStats,
+ 'giver_stats' => $giverStats,
+ ];
+
+ // 缓存5分钟
+ Cache::set($cacheKey, $result, 300);
+
+ Log::info("收礼统计计算完成: {$giftUser}, 房间数: " . count($roomStats) . ", 送礼人数: " . count($giverStats));
+
+ $this->success('获取成功', $result);
+ }
+
+ /**
+ * 获取送礼趋势
+ */
+ public function getGiftTrend()
+ {
+ $params = $this->request->param();
+
+ $startTime = $params['start_time'] ?? strtotime('-7 days');
+ $endTime = $params['end_time'] ?? time();
+ $interval = $params['interval'] ?? 'day';
+
+ if (!in_array($interval, ['day', 'week', 'month'])) {
+ $interval = 'day';
+ }
+
+ $cacheKey = "gift:trend:" . date('Ymd', $startTime) . '-' . date('Ymd', $endTime) . ":{$interval}";
+ $cachedData = Cache::get($cacheKey);
+
+ if ($cachedData !== false) {
+ $this->success('获取成功', $cachedData);
+ }
+
+ $trendData = $this->giftModel->getTrendStatistics($startTime, $endTime, $interval);
+
+ // 缓存10分钟
+ Cache::set($cacheKey, $trendData, 600);
+
+ $this->success('获取成功', [
+ 'trend_data' => $trendData,
+ 'interval' => $interval,
+ 'time_range' => [
+ 'start_time' => $startTime,
+ 'end_time' => $endTime
+ ]
+ ]);
+ }
+}
\ No newline at end of file
diff --git a/application/api/controller/GiveGiftBase.php b/application/api/controller/GiveGiftBase.php
new file mode 100644
index 00000000..f96f445c
--- /dev/null
+++ b/application/api/controller/GiveGiftBase.php
@@ -0,0 +1,179 @@
+request->param();
+
+ // 验证必要参数
+ $required = ['user_id', 'gift_id', 'gift_user', 'from_id'];
+ foreach ($required as $field) {
+ if (empty($params[$field])) {
+ $this->error("{$field}不能为空");
+ }
+ }
+
+ // 构建送礼数据
+ $giftData = [
+ 'user_id' => intval($params['user_id']),
+ 'gift_id' => intval($params['gift_id']),
+ 'gift_type' => intval($params['gift_type'] ?? 1),
+ 'number' => intval($params['number'] ?? 1),
+ 'gift_user' => intval($params['gift_user']),
+ 'from_id' => intval($params['from_id']),
+ 'pit_number' => intval($params['pit_number'] ?? 0),
+ 'total_price' => floatval($params['total_price'] ?? 0),
+ 'type' => intval($params['type'] ?? 1),
+ 'from' => intval($params['from'] ?? 1),
+ 'createtime' => time(),
+ ];
+
+ // 验证价格
+ if ($giftData['total_price'] <= 0) {
+ $this->error('礼物总价值必须大于0');
+ }
+
+ // 验证数量
+ if ($giftData['number'] <= 0) {
+ $this->error('礼物数量必须大于0');
+ }
+
+ // 使用队列异步处理
+ $result = GiftQueue::push($giftData);
+
+ if ($result) {
+ // 记录日志
+ Log::info("用户送礼成功(队列),用户: {$giftData['user_id']}, 收礼人: {$giftData['gift_user']}, 房间: {$giftData['from_id']}");
+
+ // 立即返回成功,后台异步处理
+ $this->success('送礼成功,正在处理中', [
+ 'queue_status' => 'processing',
+ 'user_id' => $giftData['user_id'],
+ 'gift_user' => $giftData['gift_user'],
+ 'timestamp' => time()
+ ]);
+ } else {
+ Log::error("用户送礼失败(队列),用户: {$giftData['user_id']}, 收礼人: {$giftData['gift_user']}");
+ $this->error('送礼失败,请重试');
+ }
+ }
+
+ /**
+ * 批量送礼
+ */
+ public function batchGive()
+ {
+ $gifts = $this->request->param('gifts/a', []);
+
+ if (empty($gifts) || !is_array($gifts)) {
+ $this->error('礼物数据不能为空');
+ }
+
+ $successCount = 0;
+ $failCount = 0;
+ $giftList = [];
+
+ foreach ($gifts as $gift) {
+ // 验证必要参数
+ if (empty($gift['user_id']) || empty($gift['gift_user']) || empty($gift['from_id'])) {
+ $failCount++;
+ continue;
+ }
+
+ $giftData = [
+ 'user_id' => intval($gift['user_id']),
+ 'gift_id' => intval($gift['gift_id'] ?? 0),
+ 'gift_type' => intval($gift['gift_type'] ?? 1),
+ 'number' => intval($gift['number'] ?? 1),
+ 'gift_user' => intval($gift['gift_user']),
+ 'from_id' => intval($gift['from_id']),
+ 'pit_number' => intval($gift['pit_number'] ?? 0),
+ 'total_price' => floatval($gift['total_price'] ?? 0),
+ 'type' => intval($gift['type'] ?? 1),
+ 'from' => intval($gift['from'] ?? 1),
+ 'createtime' => time(),
+ ];
+
+ $giftList[] = $giftData;
+ }
+
+ // 批量加入队列
+ $result = GiftQueue::pushBatch($giftList);
+
+ Log::info("批量送礼提交,总计: {$result['total']}, 成功: {$result['success']}, 失败: {$result['failed']}");
+
+ $this->success("批量送礼提交成功", $result);
+ }
+
+ /**
+ * 获取队列状态
+ */
+ public function queueStatus()
+ {
+ $stats = GiftQueue::stats();
+
+ $this->success('获取成功', $stats);
+ }
+
+ /**
+ * 测试送礼接口(直接写入,用于测试)
+ */
+ public function testGive()
+ {
+ // 只有测试环境可用
+ if (config('app_debug') != true) {
+ $this->error('测试接口仅限开发环境使用');
+ }
+
+ $params = $this->request->param();
+
+ // 验证必要参数
+ $required = ['user_id', 'gift_id', 'gift_user', 'from_id'];
+ foreach ($required as $field) {
+ if (empty($params[$field])) {
+ $this->error("{$field}不能为空");
+ }
+ }
+
+ // 构建送礼数据
+ $giftData = [
+ 'user_id' => intval($params['user_id']),
+ 'gift_id' => intval($params['gift_id']),
+ 'gift_type' => intval($params['gift_type'] ?? 1),
+ 'number' => intval($params['number'] ?? 1),
+ 'gift_user' => intval($params['gift_user']),
+ 'from_id' => intval($params['from_id']),
+ 'pit_number' => intval($params['pit_number'] ?? 0),
+ 'total_price' => floatval($params['total_price'] ?? 0),
+ 'type' => intval($params['type'] ?? 1),
+ 'from' => intval($params['from'] ?? 1),
+ 'createtime' => time(),
+ ];
+
+ // 直接写入数据库(测试用)
+ $model = new \app\common\model\GiveGiftBase();
+ $result = $model->addGiftRecord($giftData);
+
+ if ($result) {
+ $this->success('测试送礼成功(直接写入)', [
+ 'id' => $result,
+ 'data' => $giftData
+ ]);
+ } else {
+ $this->error('测试送礼失败: ' . $model->getError());
+ }
+ }
+}
\ No newline at end of file
diff --git a/application/api/model/RoomAuction.php b/application/api/model/RoomAuction.php
index bdc28115..df88fdd6 100644
--- a/application/api/model/RoomAuction.php
+++ b/application/api/model/RoomAuction.php
@@ -92,6 +92,7 @@ class RoomAuction extends Model
$auction['relation_icon'] = db::name('vs_relation')->where('id',$auction['relation_id'])->value('icon');
$auction['base_image'] = db::name('vs_gift')->where('gid',$auction['gift_id'])->value('base_image');
$auction['gift_name'] = db::name('vs_gift')->where('gid',$auction['gift_id'])->value('gift_name');
+ $auction['gift_price'] = db::name('vs_gift')->where('gid',$auction['gift_id'])->value('gift_price');
$auction['time_day'] = $auction['time_day'] / 60 / 60;
}
// var_dump($auction);
diff --git a/application/common/command/GiftMigration.php b/application/common/command/GiftMigration.php
new file mode 100644
index 00000000..708ad173
--- /dev/null
+++ b/application/common/command/GiftMigration.php
@@ -0,0 +1,225 @@
+setName('gift:migration')
+ ->setDescription('送礼数据分表迁移工具')
+ ->addArgument('action', Argument::REQUIRED, '操作类型: init-tables, migrate, progress, verify, clean')
+ ->addOption('month', 'm', Option::VALUE_OPTIONAL, '指定年月,格式: 202401')
+ ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, '每批迁移数量', 1000)
+ ->addOption('start-id', 's', Option::VALUE_OPTIONAL, '起始ID', 0)
+ ->addOption('months', null, Option::VALUE_OPTIONAL, '创建几个月分表', 12);
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $action = $input->getArgument('action');
+ $month = $input->getOption('month');
+ $batchSize = $input->getOption('batch-size');
+ $startId = $input->getOption('start-id');
+ $months = $input->getOption('months');
+
+ Log::info("执行送礼数据迁移命令,动作: {$action}, 月份: {$month}");
+
+ switch ($action) {
+ case 'init-tables':
+ $this->initTables($output, $months);
+ break;
+
+ case 'migrate':
+ $this->migrateData($output, $month, $batchSize, $startId);
+ break;
+
+ case 'progress':
+ $this->showProgress($output);
+ break;
+
+ case 'verify':
+ $this->verifyData($output, $month);
+ break;
+
+ case 'clean':
+ $this->cleanOldData($output);
+ break;
+
+ default:
+ $output->writeln('未知操作类型');
+ break;
+ }
+ }
+
+ /**
+ * 初始化分表
+ */
+ protected function initTables(Output $output, $months)
+ {
+ $output->writeln('开始初始化分表...');
+
+ $results = GiftTableManager::initTables(null, $months);
+
+ $successCount = 0;
+ $failCount = 0;
+
+ foreach ($results as $tableMonth => $success) {
+ if ($success) {
+ $output->writeln("创建表 fa_vs_give_gift_{$tableMonth} 成功");
+ $successCount++;
+ } else {
+ $output->writeln("创建表 fa_vs_give_gift_{$tableMonth} 失败");
+ $failCount++;
+ }
+ }
+
+ $output->writeln("分表初始化完成,成功: {$successCount}, 失败: {$failCount}");
+ }
+
+ /**
+ * 迁移数据
+ */
+ protected function migrateData(Output $output, $month, $batchSize, $startId)
+ {
+ if ($month) {
+ // 迁移指定月份
+ $output->writeln("开始迁移 {$month} 数据...");
+ $result = GiftDataMigrator::migrateMonthData($month, $batchSize, $startId);
+
+ if ($result['success']) {
+ $output->writeln("{$month} 数据迁移成功");
+ $output->writeln("迁移总数: " . $result['total']);
+ $output->writeln("最后ID: " . $result['last_id']);
+ } else {
+ $output->writeln("{$month} 数据迁移失败: " . $result['message'] . "");
+ }
+ } else {
+ // 迁移所有数据
+ $output->writeln('开始迁移所有数据...');
+ $result = GiftDataMigrator::migrateAllData($batchSize);
+
+ if ($result['success']) {
+ $output->writeln("所有数据迁移成功");
+
+ // 显示每个月份的结果
+ foreach ($result['results'] as $month => $monthResult) {
+ $status = $monthResult['success'] ? '成功' : '失败';
+ $output->writeln("{$month}: {$status}, 数量: " . ($monthResult['total'] ?? 0));
+ }
+ } else {
+ $output->writeln("数据迁移失败: " . $result['message'] . "");
+ }
+ }
+ }
+
+ /**
+ * 显示迁移进度
+ */
+ protected function showProgress(Output $output)
+ {
+ $progress = GiftDataMigrator::getMigrationProgress();
+
+ $output->writeln("数据迁移进度:");
+ $output->writeln("原始表数据量: " . $progress['total']);
+ $output->writeln("已迁移数据量: " . $progress['migrated']);
+ $output->writeln("迁移进度: " . $progress['progress'] . "%");
+ $output->writeln("剩余数据: " . $progress['remaining']);
+
+ if ($progress['total'] > 0 && $progress['migrated'] > 0) {
+ $output->writeln("迁移进度正常");
+ } else {
+ $output->writeln("暂无迁移进度数据");
+ }
+ }
+
+ /**
+ * 验证数据
+ */
+ protected function verifyData(Output $output, $month)
+ {
+ if (!$month) {
+ // 验证所有月份
+ $tables = GiftTableManager::getAllTables();
+ foreach ($tables as $table) {
+ $month = substr($table['table_name'], -6);
+ $this->verifySingleMonth($output, $month);
+ }
+ } else {
+ $this->verifySingleMonth($output, $month);
+ }
+ }
+
+ /**
+ * 验证单个月份数据
+ */
+ protected function verifySingleMonth(Output $output, $month)
+ {
+ $output->writeln("验证 {$month} 数据一致性...");
+ $result = GiftDataMigrator::verifyMigration($month);
+
+ $output->writeln("原始表数据量: " . $result['source_count']);
+ $output->writeln("目标表数据量: " . $result['target_count']);
+ $output->writeln("数据量匹配: " . ($result['count_match'] ? '是' : '否'));
+
+ $output->writeln("原始表总价值: " . $result['source_total_price']);
+ $output->writeln("目标表总价值: " . $result['target_total_price']);
+ $output->writeln("总价值匹配: " . ($result['price_match'] ? '是' : '否'));
+
+ if ($result['count_match'] && $result['price_match']) {
+ $output->writeln("{$month} 数据验证通过");
+ } else {
+ $output->writeln("{$month} 数据验证失败");
+ }
+ }
+
+ /**
+ * 清理旧数据(迁移完成后)
+ */
+ protected function cleanOldData(Output $output)
+ {
+ $output->writeln("警告:此操作将清理原始表数据,请确认迁移已完成且验证通过!");
+ $output->writeln("输入 'yes' 继续: ");
+
+ $handle = fopen("php://stdin", "r");
+ $line = fgets($handle);
+ fclose($handle);
+
+ if (trim($line) != 'yes') {
+ $output->writeln("操作取消");
+ return;
+ }
+
+ // 备份原始表
+ $output->writeln("正在备份原始表...");
+ try {
+ Db::execute("DROP TABLE IF EXISTS `fa_vs_give_gift_old`");
+ Db::execute("CREATE TABLE `fa_vs_give_gift_old` LIKE `fa_vs_give_gift`");
+ Db::execute("INSERT INTO `fa_vs_give_gift_old` SELECT * FROM `fa_vs_give_gift`");
+ $output->writeln("原始表备份完成");
+ } catch (\Exception $e) {
+ $output->writeln("备份原始表失败: " . $e->getMessage() . "");
+ return;
+ }
+
+ // 清空原始表
+ $output->writeln("正在清空原始表...");
+ try {
+ Db::execute("TRUNCATE TABLE `fa_vs_give_gift`");
+ $output->writeln("原始表已清空");
+ } catch (\Exception $e) {
+ $output->writeln("清空原始表失败: " . $e->getMessage() . "");
+ }
+ }
+}
\ No newline at end of file
diff --git a/application/common/command/ProcessGiftQueue.php b/application/common/command/ProcessGiftQueue.php
new file mode 100644
index 00000000..48c35506
--- /dev/null
+++ b/application/common/command/ProcessGiftQueue.php
@@ -0,0 +1,111 @@
+setName('process:gift_queue')
+ ->setDescription('处理送礼队列')
+ ->addArgument('mode', Argument::OPTIONAL, '运行模式: once, daemon', 'once')
+ ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, '每次处理数量', 100)
+ ->addOption('sleep-time', 's', Option::VALUE_OPTIONAL, '处理间隔(毫秒)', 100)
+ ->addOption('max-runtime', 't', Option::VALUE_OPTIONAL, '最大运行时间(秒)', 0);
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $mode = $input->getArgument('mode');
+ $batchSize = $input->getOption('batch-size');
+ $sleepTime = $input->getOption('sleep-time');
+ $maxRuntime = $input->getOption('max-runtime');
+
+ $output->writeln("开始处理送礼队列...");
+ $output->writeln("模式: {$mode}, 批量大小: {$batchSize}, 间隔: {$sleepTime}ms");
+
+ $startTime = time();
+ $totalProcessed = 0;
+ $totalSuccess = 0;
+ $totalFailed = 0;
+
+ // 检查Redis连接
+ try {
+ $queueSize = GiftQueue::size();
+ $output->writeln("当前队列大小: {$queueSize}");
+ } catch (\Exception $e) {
+ $output->writeln("Redis连接失败: " . $e->getMessage() . "");
+ return;
+ }
+
+ do {
+ $queueSize = GiftQueue::size();
+
+ if ($queueSize == 0) {
+ if ($mode == 'once') {
+ $output->writeln("队列为空,处理完成");
+ break;
+ } else {
+ $output->writeln("队列为空,等待新数据...");
+ sleep(5);
+ continue;
+ }
+ }
+
+ $output->writeln("当前队列大小: {$queueSize}");
+
+ // 处理队列
+ $result = GiftQueue::process($batchSize);
+
+ $totalProcessed += $result['processed'];
+ $totalSuccess += $result['success'];
+ $totalFailed += $result['failed'];
+
+ $output->writeln(sprintf(
+ "处理完成:已处理 %d,成功 %d,失败 %d",
+ $result['processed'],
+ $result['success'],
+ $result['failed']
+ ));
+
+ // 休眠
+ usleep($sleepTime * 1000);
+
+ // 检查运行时间限制
+ if ($maxRuntime > 0 && (time() - $startTime) > $maxRuntime) {
+ $output->writeln("达到最大运行时间,停止处理");
+ break;
+ }
+
+ // 单次模式处理完成后退出
+ if ($mode == 'once' && $result['processed'] < $batchSize) {
+ $output->writeln("队列处理完成");
+ break;
+ }
+
+ } while ($mode == 'daemon');
+
+ $output->writeln("队列处理统计:");
+ $output->writeln("总计处理: {$totalProcessed}");
+ $output->writeln("成功: {$totalSuccess}");
+ $output->writeln("失败: {$totalFailed}");
+ $output->writeln("剩余队列大小: " . GiftQueue::size());
+
+ Log::info(sprintf(
+ "送礼队列处理统计: 总计 %d, 成功 %d, 失败 %d, 剩余 %d",
+ $totalProcessed,
+ $totalSuccess,
+ $totalFailed,
+ GiftQueue::size()
+ ));
+ }
+}
\ No newline at end of file
diff --git a/application/common/command/QueueMonitor.php b/application/common/command/QueueMonitor.php
new file mode 100644
index 00000000..2c2f9da1
--- /dev/null
+++ b/application/common/command/QueueMonitor.php
@@ -0,0 +1,64 @@
+setName('queue:monitor')
+ ->setDescription('监控队列状态')
+ ->addOption('interval', 'i', Option::VALUE_OPTIONAL, '监控间隔(秒)', 10);
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $interval = $input->getOption('interval');
+
+ $output->writeln("开始监控送礼队列状态,间隔: {$interval}秒");
+ $output->writeln("按 Ctrl+C 停止监控");
+
+ $history = [];
+ $maxHistory = 60;
+
+ while (true) {
+ try {
+ $stats = GiftQueue::stats();
+ $timestamp = date('H:i:s');
+
+ $output->writeln("[{$timestamp}] 队列大小: {$stats['queue_size']}, 失败队列: {$stats['failed_size']}, 状态: {$stats['status']}");
+
+ // 记录历史数据
+ $history[] = [
+ 'time' => $timestamp,
+ 'size' => $stats['queue_size'],
+ 'status' => $stats['status']
+ ];
+
+ if (count($history) > $maxHistory) {
+ array_shift($history);
+ }
+
+ // 检查队列是否积压
+ if ($stats['queue_size'] > 1000) {
+ $output->writeln("警告:队列积压严重!");
+ } elseif ($stats['queue_size'] > 100) {
+ $output->writeln("注意:队列正在积压");
+ }
+
+ sleep($interval);
+
+ } catch (\Exception $e) {
+ $output->writeln("监控异常: " . $e->getMessage() . "");
+ sleep($interval);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/application/common/library/GiftDataMigrator.php b/application/common/library/GiftDataMigrator.php
index 53604ec3..b73cb428 100644
--- a/application/common/library/GiftDataMigrator.php
+++ b/application/common/library/GiftDataMigrator.php
@@ -5,7 +5,7 @@ namespace app\common\library;
use think\Db;
use think\Exception;
-use think\facade\Log;
+use think\Log;
class GiftDataMigrator
{
diff --git a/application/common/library/GiftQueue.php b/application/common/library/GiftQueue.php
index 8ed0cb16..032a148e 100644
--- a/application/common/library/GiftQueue.php
+++ b/application/common/library/GiftQueue.php
@@ -5,7 +5,7 @@ namespace app\common\library;
use think\Cache;
use think\Db;
-use think\facade\Log;
+use think\Log;
use app\common\model\GiveGiftBase;
class GiftQueue
diff --git a/application/common/library/GiftTableManager.php b/application/common/library/GiftTableManager.php
index 497ceeb6..aea2ec38 100644
--- a/application/common/library/GiftTableManager.php
+++ b/application/common/library/GiftTableManager.php
@@ -5,7 +5,7 @@ namespace app\common\library;
use think\Db;
use think\Exception;
-use think\facade\Log;
+use think\Log;
class GiftTableManager
{
diff --git a/application/common/model/GiveGiftBase.php b/application/common/model/GiveGiftBase.php
index 8598f47d..1d680b87 100644
--- a/application/common/model/GiveGiftBase.php
+++ b/application/common/model/GiveGiftBase.php
@@ -5,7 +5,7 @@ namespace app\common\model;
use think\Model;
use think\Db;
-use think\facade\Log;
+use think\Log;
use app\common\library\GiftTableManager;
use app\common\library\Snowflake;