option('dry-run'); $userId = $this->option('user'); $limit = (int) $this->option('limit'); $this->info('开始检查没有作物但土地状态不是空闲的问题...'); if ($dryRun) { $this->warn('运行在模拟模式,不会实际修改数据'); } try { // 获取需要修复的数据 $problematicLands = $this->getProblematicLands($userId, $limit); if ($problematicLands->isEmpty()) { $this->info('没有发现需要修复的数据'); return 0; } $this->info("发现 {$problematicLands->count()} 条需要修复的土地"); if ($dryRun) { $this->displayProblems($problematicLands); } else { $this->fixProblems($problematicLands); } if (!$dryRun) { $this->info("\n修复完成!"); } return 0; } catch (\Exception $e) { $this->error("修复过程中发生错误: {$e->getMessage()}"); Log::error('已铲除作物土地状态修复失败', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return 1; } } /** * 获取有问题的土地数据 * 查找没有作物(has_crop为0)但土地状态不是空闲的情况 * * @param string|null $userId * @param int $limit * @return \Illuminate\Support\Collection */ private function getProblematicLands(?string $userId, int $limit): \Illuminate\Support\Collection { // 查找has_crop为0但状态不是空闲的土地 $query = DB::table('farm_land_users') ->select([ 'id as land_id', 'user_id', 'status as land_status', 'has_crop' ]) ->where('has_crop', 0) // has_crop为0(没有作物) ->where('status', '!=', LAND_STATUS::IDLE->value) // 状态不是空闲 ->when($userId, function ($query, $userId) { return $query->where('user_id', $userId); }) ->limit($limit); $results = $query->get(); // 添加问题类型标识和额外信息 return $results->map(function ($item) { // 检查是否有未删除的作物(用于验证has_crop字段的正确性) $activeCrops = DB::table('farm_crops') ->where('land_id', $item->land_id) ->whereNull('deleted_at') ->count(); // 检查是否有软删除的作物 $deletedCrops = DB::table('farm_crops') ->where('land_id', $item->land_id) ->whereNotNull('deleted_at') ->count(); $item->active_crops_count = $activeCrops; $item->deleted_crops_count = $deletedCrops; $item->problem_type = $this->getProblemType($item); return $item; }); } /** * 获取问题类型 * * @param object $item * @return string */ private function getProblemType(object $item): string { if ($item->active_crops_count > 0) { return 'has_crop为0但实际有活跃作物'; } else { return 'has_crop为0且状态非空闲'; } } /** * 显示问题数据 * * @param \Illuminate\Support\Collection $items * @return void */ private function displayProblems(\Illuminate\Support\Collection $items): void { // 按问题类型分组显示 $groupedData = $items->groupBy('problem_type'); foreach ($groupedData as $problemType => $problemItems) { $this->info("\n=== {$problemType} ({$problemItems->count()} 条) ==="); $headers = ['土地ID', '用户ID', '当前土地状态', 'has_crop', '活跃作物数', '软删除作物数']; $rows = []; foreach ($problemItems as $item) { $rows[] = [ $item->land_id, $item->user_id, $this->getLandStatusName($item->land_status), $item->has_crop ? '是' : '否', $item->active_crops_count, $item->deleted_crops_count ]; } $this->table($headers, $rows); } } /** * 修复问题数据 * * @param \Illuminate\Support\Collection $items * @return void */ private function fixProblems(\Illuminate\Support\Collection $items): void { $fixedCount = 0; $failedCount = 0; foreach ($items as $item) { try { DB::transaction(function () use ($item) { $this->fixSingleLand($item); }); $fixedCount++; $this->info("✓ 修复土地 {$item->land_id} (用户 {$item->user_id}) - {$item->problem_type}"); } catch (\Exception $e) { $failedCount++; $this->error("✗ 修复土地 {$item->land_id} 失败: {$e->getMessage()}"); Log::error('单个土地状态修复失败', [ 'land_id' => $item->land_id, 'user_id' => $item->user_id, 'problem_type' => $item->problem_type, 'error' => $e->getMessage() ]); } } $this->info("修复完成: 成功 {$fixedCount} 条,失败 {$failedCount} 条"); } /** * 修复单个土地 * * @param object $item * @return void */ private function fixSingleLand(object $item): void { $land = FarmLand::lockForUpdate()->find($item->land_id); if (!$land) { throw new \Exception('土地不存在'); } $oldStatus = $land->status; $oldHasCrop = $land->has_crop; // 如果has_crop为0但状态不是空闲,将状态设置为空闲 $land->status = LAND_STATUS::IDLE->value; $land->updateHasCrop(); // 这会根据状态更新has_crop字段 $land->save(); Log::info('修复has_crop为0但状态非空闲的土地', [ 'land_id' => $land->id, 'user_id' => $land->user_id, 'active_crops_count' => $item->active_crops_count, 'deleted_crops_count' => $item->deleted_crops_count, 'old_status' => $oldStatus, 'new_status' => $land->status, 'old_has_crop' => $oldHasCrop, 'new_has_crop' => $land->has_crop, 'problem_type' => $item->problem_type ]); } /** * 获取土地状态名称 * * @param int $status * @return string */ private function getLandStatusName(int $status): string { return match ($status) { LAND_STATUS::IDLE->value => '空闲', LAND_STATUS::PLANTING->value => '种植中', LAND_STATUS::DISASTER->value => '灾害', LAND_STATUS::HARVESTABLE->value => '可收获', LAND_STATUS::WITHERED->value => '枯萎', default => '未知' }; } }