make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); use Illuminate\Support\Facades\DB; $arguments = array_slice($argv, 1); if (array_diff($arguments, ['--apply'])) { fwrite(STDERR, "用法:php scripts/news-review.php [--apply]\n"); exit(1); } $apply = in_array('--apply', $arguments, true); try { $result = DB::transaction(function () use ($apply) { // Same lock as the collector: prevents collection starting during the update. $control = DB::table('company_news_control')->where('id', 1)->lockForUpdate()->first(); if (!$control) throw new RuntimeException('缺少采集控制记录,请先执行迁移'); if ($control->active_batch_id) throw new RuntimeException('存在未完成的采集批次,请先完成该批次'); $settings = DB::table('company_news_settings')->where('id', 1)->lockForUpdate()->first(); $codes = json_decode($settings->retained_categories ?? '[]', true, 512, JSON_THROW_ON_ERROR); if (!is_array($codes) || !$codes) throw new RuntimeException('尚未选择留存分类,请先保存分类设置'); foreach ($codes as $code) { if (!is_string($code)) throw new RuntimeException('分类代码格式异常,未执行更新'); } $counts = ['categories' => count(array_unique($codes)), 'total' => 0, 'retained' => 0, 'discarded' => 0, 'changed' => 0]; $query = DB::table('company_news')->select('id', 'categories', 'review_status')->orderBy('id'); if ($apply) $query->lockForUpdate(); $query->chunkById(200, function ($rows) use ($codes, $apply, &$counts) { foreach ($rows as $row) { $categories = json_decode($row->categories ?? '[]', true, 512, JSON_THROW_ON_ERROR) ?? []; if (!is_array($categories)) throw new RuntimeException('新闻 '.$row->id.' 分类格式异常,已取消本次操作'); $status = array_intersect(array_column($categories, 'code'), $codes) ? 'retained' : 'discarded'; $counts['total']++; $counts[$status]++; if ($row->review_status === $status) continue; $counts['changed']++; if (!$apply) continue; DB::table('company_news')->where('id', $row->id)->update(['review_status' => $status]); DB::table('company_news_logs')->insert([ 'news_id' => $row->id, 'actor_id' => null, 'action' => 'review', 'detail' => json_encode([ 'source' => 'news-review.php:按保存的分类设置批量更新', 'from' => $row->review_status, 'to' => $status, 'category_codes' => $codes, ], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 'created_at' => now(), ]); } }); return $counts; }); echo $apply ? "更新完成\n" : "仅预览,未修改任何新闻\n"; echo "已选分类:{$result['categories']}\n新闻总数:{$result['total']}\n分类后已留存:{$result['retained']}\n分类后不留存:{$result['discarded']}\n"; echo ($apply ? '实际修改:' : '预计修改:').$result['changed']."\n"; if (!$apply) echo "确认后执行:php scripts/news-review.php --apply\n"; } catch (Throwable $error) { fwrite(STDERR, '执行失败:'.$error->getMessage()."\n"); exit(1); }