SyncTextbookSeries.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\TextbookSeries;
  4. use App\Services\TextbookApiService;
  5. use Illuminate\Console\Command;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Log;
  8. class SyncTextbookSeries extends Command
  9. {
  10. /**
  11. * The name and signature of the console command.
  12. *
  13. * @var string
  14. */
  15. protected $signature = 'sync:textbook-series {--dry-run : 仅显示将要同步的数据,不实际执行}';
  16. /**
  17. * The console command description.
  18. *
  19. * @var string
  20. */
  21. protected $description = '同步 MySQL 中的教材系列数据到题库服务';
  22. protected $apiService;
  23. /**
  24. * Execute the console command.
  25. */
  26. public function handle()
  27. {
  28. $this->apiService = app(TextbookApiService::class);
  29. $this->info('开始同步教材系列数据...');
  30. // 获取MySQL中的所有系列
  31. $mysqlSeries = DB::connection('mysql')
  32. ->table('textbook_series')
  33. ->orderBy('id')
  34. ->get();
  35. $this->info('MySQL中共有 ' . $mysqlSeries->count() . ' 个系列');
  36. // 获取题库服务中的所有系列
  37. try {
  38. $apiSeries = $this->apiService->getTextbookSeries();
  39. $existingIds = collect($apiSeries['data'] ?? [])->pluck('id')->toArray();
  40. } catch (\Exception $e) {
  41. $this->error('获取题库服务数据失败: ' . $e->getMessage());
  42. return 1;
  43. }
  44. $this->info('题库服务中已有 ' . count($existingIds) . ' 个系列');
  45. $dryRun = $this->option('dry-run');
  46. $syncedCount = 0;
  47. $errorCount = 0;
  48. foreach ($mysqlSeries as $series) {
  49. // 检查是否已存在
  50. if (in_array($series->id, $existingIds)) {
  51. $this->line("系列 {$series->id} ({$series->name}) 已存在,跳过");
  52. continue;
  53. }
  54. if ($dryRun) {
  55. $this->line("将同步: ID {$series->id}, 名称 {$series->name}, 别名 {$series->slug}");
  56. continue;
  57. }
  58. try {
  59. // 准备数据(指定ID以保持一致性)
  60. $data = [
  61. 'id' => $series->id, // 指定相同的ID
  62. 'name' => $series->name,
  63. 'slug' => $series->slug,
  64. 'publisher' => $series->publisher,
  65. 'region' => $series->region,
  66. 'stages' => json_decode($series->stages, true),
  67. 'is_active' => (bool)$series->is_active,
  68. 'sort_order' => (int)$series->sort_order,
  69. 'meta' => json_decode($series->meta, true),
  70. ];
  71. // 调用API创建
  72. $result = $this->apiService->createTextbookSeries($data);
  73. if (isset($result['data'])) {
  74. $this->info("✓ 同步成功: ID {$series->id}, 名称 {$series->name}");
  75. $syncedCount++;
  76. } else {
  77. $this->error("✗ 同步失败: ID {$series->id}, 名称 {$series->name}");
  78. $errorCount++;
  79. }
  80. } catch (\Exception $e) {
  81. $this->error("✗ 同步失败: ID {$series->id}, 错误: " . $e->getMessage());
  82. Log::error('同步系列失败', ['id' => $series->id, 'error' => $e->getMessage()]);
  83. $errorCount++;
  84. }
  85. }
  86. if (!$dryRun) {
  87. $this->newLine();
  88. $this->info("同步完成! 成功: {$syncedCount}, 失败: {$errorCount}");
  89. } else {
  90. $this->newLine();
  91. $this->info("dry-run 模式完成。如需实际同步,请去掉 --dry-run 参数");
  92. }
  93. return 0;
  94. }
  95. }