Files
zyt/server/app/command/MobileRecordingCosMigrate.php
2026-11-09 14:51:31 +08:00

46 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace app\command;
use app\adminapi\logic\tcm\MobileRecordingMediaLogic;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Option;
use think\facade\Db;
/** Explicit privileged migration. Never implicitly moves all legacy patient media on deployment. */
final class MobileRecordingCosMigrate extends Command
{
protected function configure()
{
$this->setName('mobile-recording:cos-migrate')->setDescription('分批迁移历史本地完整录音/文字至COS')
->addOption('dry-run', null, Option::VALUE_NONE, '只统计,不读取内容、不调用COS')
->addOption('limit', null, Option::VALUE_REQUIRED, '每批1至100条', '20')
->addOption('after', null, Option::VALUE_REQUIRED, '上一批输出的32位不透明cursor', '');
}
protected function execute(Input $input, Output $output): int
{
try {
$after = (string) $input->getOption('after');
if ($after !== '' && !preg_match('/^[a-f0-9]{32}$/D', $after)) { throw new \InvalidArgumentException('Invalid cursor'); }
$query = Db::name('mobile_recording_upload')->alias('u')
->leftJoin([Db::name('mobile_recording_object')->getTable() => 'o'], 'o.upload_id=u.upload_id')
->where('u.state', 'complete')->whereRaw('(o.upload_id IS NULL OR o.state IN (\'pending\',\'finalizing\',\'verifying\'))');
if ($after !== '') { $query->where('u.upload_id', '>', $after); }
$ids = $query->order('u.upload_id')->limit(max(1, min(100, (int) $input->getOption('limit'))))->column('u.upload_id');
$counts = ['selected' => count($ids), 'migrated' => 0, 'deferred' => 0, 'next_cursor' => $ids ? end($ids) : ''];
if (!$input->getOption('dry-run')) {
foreach ($ids as $id) {
try { MobileRecordingMediaLogic::migrateLocal($id); $counts['migrated']++; }
catch (\Throwable $e) { $counts['deferred']++; }
}
}
$output->writeln('MOBILE_RECORDING_COS_MIGRATE ' . json_encode($counts));
return 0;
} catch (\Throwable $e) { $output->writeln('MOBILE_RECORDING_COS_MIGRATE storage_or_configuration_error'); return 1; }
}
}