lockFile = App::getRuntimePath() . 'migrate_traffic_pool_v2.lock';
}
protected function configure()
{
$this->setName('migrate:trafficPoolV2')
->setDescription('迁移数据到 V2 流量池系统')
->addOption('step', 's', Option::VALUE_OPTIONAL, '执行指定步骤(1-7),不指定则执行全部', null);
}
protected function execute(Input $input, Output $output)
{
// 检查锁文件
if (file_exists($this->lockFile)) {
$lockTime = filectime($this->lockFile);
if (time() - $lockTime < 7200) { // 2小时内
$output->writeln('迁移任务已在运行中,跳过本次执行');
return false;
}
unlink($this->lockFile);
}
file_put_contents($this->lockFile, time());
try {
$step = $input->getOption('step');
$adapter = new ChuKeBaoAdapter();
$output->writeln('====================================');
$output->writeln(' V2 流量池数据迁移开始');
$output->writeln('====================================');
$output->writeln('');
$startTime = microtime(true);
if ($step === null) {
// 执行完整迁移
$results = $this->runFullMigration($adapter, $output);
} else {
// 执行指定步骤
$results = $this->runStep((int)$step, $adapter, $output);
}
$endTime = microtime(true);
$duration = round($endTime - $startTime, 2);
$output->writeln('');
$output->writeln('====================================');
$output->writeln(' 迁移完成');
$output->writeln('====================================');
$output->writeln("耗时: {$duration} 秒");
$output->writeln('');
$output->writeln('结果统计:');
foreach ($results as $key => $value) {
$output->writeln(" - {$key}: {$value} 条");
}
return true;
} catch (\Exception $e) {
$output->writeln('迁移异常: ' . $e->getMessage() . '');
Log::error('V2流量池迁移异常:' . $e->getMessage() . "\n" . $e->getTraceAsString());
return false;
} finally {
if (file_exists($this->lockFile)) {
unlink($this->lockFile);
}
}
}
/**
* 执行完整迁移
*/
protected function runFullMigration(ChuKeBaoAdapter $adapter, Output $output)
{
$results = [
'friend_pool' => 0,
'friend_pool_company' => 0,
'friend_pool_source' => 0,
'chatroom_pool' => 0,
'chatroom_pool_company' => 0,
'chatroom_pool_source' => 0,
'pool_tags' => 0,
];
// === 好友数据迁移 ===
$output->writeln('【好友数据迁移】');
// Step 1: 好友同步到流量池总表
$output->writeln('[1/7] 同步好友到流量池总表 ck_traffic_pool ...');
$results['friend_pool'] = $adapter->syncToTrafficPoolV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool']}");
// Step 2: 好友同步到公司流量详情表
$output->writeln('[2/7] 同步好友到公司流量详情表 ck_traffic_pool_company ...');
$results['friend_pool_company'] = $adapter->syncToTrafficPoolCompanyV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool_company']}");
// Step 3: 好友同步到流量来源表
$output->writeln('[3/7] 同步好友到流量来源表 ck_traffic_pool_source ...');
$results['friend_pool_source'] = $adapter->syncToTrafficPoolSourceV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool_source']}");
// === 群成员数据迁移 ===
$output->writeln('');
$output->writeln('【群成员数据迁移】');
// Step 4: 群成员同步到流量池总表
$output->writeln('[4/7] 同步群成员到流量池总表 ck_traffic_pool ...');
$results['chatroom_pool'] = $adapter->syncChatroomMembersToTrafficPoolV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool']}");
// Step 5: 群成员同步到公司流量详情表
$output->writeln('[5/7] 同步群成员到公司流量详情表 ck_traffic_pool_company ...');
$results['chatroom_pool_company'] = $adapter->syncChatroomMembersToTrafficPoolCompanyV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool_company']}");
// Step 6: 群成员同步到流量来源表
$output->writeln('[6/7] 同步群成员到流量来源表 ck_traffic_pool_source ...');
$results['chatroom_pool_source'] = $adapter->syncChatroomMembersToTrafficPoolSourceV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool_source']}");
// === 标签数据迁移 ===
$output->writeln('');
$output->writeln('【标签数据迁移】');
// Step 7: 同步微信标签
$output->writeln('[7/7] 同步微信标签 ck_traffic_pool_tag ...');
$results['pool_tags'] = $adapter->syncWechatTagsToV2();
$output->writeln(" 完成,影响行数: {$results['pool_tags']}");
return $results;
}
/**
* 执行指定步骤
*/
protected function runStep(int $step, ChuKeBaoAdapter $adapter, Output $output)
{
$results = [];
switch ($step) {
case 1:
$output->writeln('[Step 1] 同步好友到流量池总表 ck_traffic_pool ...');
$results['friend_pool'] = $adapter->syncToTrafficPoolV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool']}");
break;
case 2:
$output->writeln('[Step 2] 同步好友到公司流量详情表 ck_traffic_pool_company ...');
$results['friend_pool_company'] = $adapter->syncToTrafficPoolCompanyV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool_company']}");
break;
case 3:
$output->writeln('[Step 3] 同步好友到流量来源表 ck_traffic_pool_source ...');
$results['friend_pool_source'] = $adapter->syncToTrafficPoolSourceV2();
$output->writeln(" 完成,影响行数: {$results['friend_pool_source']}");
break;
case 4:
$output->writeln('[Step 4] 同步群成员到流量池总表 ck_traffic_pool ...');
$results['chatroom_pool'] = $adapter->syncChatroomMembersToTrafficPoolV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool']}");
break;
case 5:
$output->writeln('[Step 5] 同步群成员到公司流量详情表 ck_traffic_pool_company ...');
$results['chatroom_pool_company'] = $adapter->syncChatroomMembersToTrafficPoolCompanyV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool_company']}");
break;
case 6:
$output->writeln('[Step 6] 同步群成员到流量来源表 ck_traffic_pool_source ...');
$results['chatroom_pool_source'] = $adapter->syncChatroomMembersToTrafficPoolSourceV2();
$output->writeln(" 完成,影响行数: {$results['chatroom_pool_source']}");
break;
case 7:
$output->writeln('[Step 7] 同步微信标签 ck_traffic_pool_tag ...');
$results['pool_tags'] = $adapter->syncWechatTagsToV2();
$output->writeln(" 完成,影响行数: {$results['pool_tags']}");
break;
default:
$output->writeln('无效的步骤编号,请输入 1-7');
$output->writeln('');
$output->writeln('步骤说明:');
$output->writeln(' 1 - 同步好友到流量池总表');
$output->writeln(' 2 - 同步好友到公司流量详情表');
$output->writeln(' 3 - 同步好友到流量来源表');
$output->writeln(' 4 - 同步群成员到流量池总表');
$output->writeln(' 5 - 同步群成员到公司流量详情表');
$output->writeln(' 6 - 同步群成员到流量来源表');
$output->writeln(' 7 - 同步微信标签');
break;
}
return $results;
}
}