You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
3.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
/**
* Preview: php scripts/news-review.php
* Apply: php scripts/news-review.php --apply
* Uses saved category settings; changes only review_status and appends audit logs.
*/
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit('CLI only');
}
require dirname(__DIR__).'/vendor/autoload.php';
$app = require dirname(__DIR__).'/bootstrap/app.php';
$app->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);
}