Files
cunkebao_v3/Server/application/command/MigrateTrafficPoolV2Command.php
2026-02-02 11:00:26 +08:00

236 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\command;
use think\facade\Log;
use think\console\Input;
use think\console\Output;
use think\console\Command;
use think\console\input\Option;
use think\facade\App;
use WeChatDeviceApi\Adapters\ChuKeBao\Adapter as ChuKeBaoAdapter;
/**
* V2 流量池数据迁移命令
*
* 使用方法:
* php think migrate:trafficPoolV2 # 执行完整迁移
* php think migrate:trafficPoolV2 --step=1 # 只执行第1步好友同步到流量池总表
* php think migrate:trafficPoolV2 --step=2 # 只执行第2步好友同步到公司流量详情表
* php think migrate:trafficPoolV2 --step=3 # 只执行第3步好友同步到流量来源表
* php think migrate:trafficPoolV2 --step=4 # 只执行第4步群成员同步到流量池总表
* php think migrate:trafficPoolV2 --step=5 # 只执行第5步群成员同步到公司流量详情表
* php think migrate:trafficPoolV2 --step=6 # 只执行第6步群成员同步到流量来源表
* php think migrate:trafficPoolV2 --step=7 # 只执行第7步同步微信标签
*
* 执行前请确保已运行 SQL 迁移脚本创建了 V2 版本的表
*/
class MigrateTrafficPoolV2Command extends Command
{
protected $lockFile;
public function __construct()
{
parent::__construct();
$this->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('<error>迁移任务已在运行中,跳过本次执行</error>');
return false;
}
unlink($this->lockFile);
}
file_put_contents($this->lockFile, time());
try {
$step = $input->getOption('step');
$adapter = new ChuKeBaoAdapter();
$output->writeln('<info>====================================</info>');
$output->writeln('<info> V2 流量池数据迁移开始</info>');
$output->writeln('<info>====================================</info>');
$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('<info>====================================</info>');
$output->writeln('<info> 迁移完成</info>');
$output->writeln('<info>====================================</info>');
$output->writeln("耗时: {$duration}");
$output->writeln('');
$output->writeln('<comment>结果统计:</comment>');
foreach ($results as $key => $value) {
$output->writeln(" - {$key}: {$value}");
}
return true;
} catch (\Exception $e) {
$output->writeln('<error>迁移异常: ' . $e->getMessage() . '</error>');
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('<comment>【好友数据迁移】</comment>');
// Step 1: 好友同步到流量池总表
$output->writeln('<comment>[1/7] 同步好友到流量池总表 ck_traffic_pool ...</comment>');
$results['friend_pool'] = $adapter->syncToTrafficPoolV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool']}</info>");
// Step 2: 好友同步到公司流量详情表
$output->writeln('<comment>[2/7] 同步好友到公司流量详情表 ck_traffic_pool_company ...</comment>');
$results['friend_pool_company'] = $adapter->syncToTrafficPoolCompanyV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool_company']}</info>");
// Step 3: 好友同步到流量来源表
$output->writeln('<comment>[3/7] 同步好友到流量来源表 ck_traffic_pool_source ...</comment>');
$results['friend_pool_source'] = $adapter->syncToTrafficPoolSourceV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool_source']}</info>");
// === 群成员数据迁移 ===
$output->writeln('');
$output->writeln('<comment>【群成员数据迁移】</comment>');
// Step 4: 群成员同步到流量池总表
$output->writeln('<comment>[4/7] 同步群成员到流量池总表 ck_traffic_pool ...</comment>');
$results['chatroom_pool'] = $adapter->syncChatroomMembersToTrafficPoolV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool']}</info>");
// Step 5: 群成员同步到公司流量详情表
$output->writeln('<comment>[5/7] 同步群成员到公司流量详情表 ck_traffic_pool_company ...</comment>');
$results['chatroom_pool_company'] = $adapter->syncChatroomMembersToTrafficPoolCompanyV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool_company']}</info>");
// Step 6: 群成员同步到流量来源表
$output->writeln('<comment>[6/7] 同步群成员到流量来源表 ck_traffic_pool_source ...</comment>');
$results['chatroom_pool_source'] = $adapter->syncChatroomMembersToTrafficPoolSourceV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool_source']}</info>");
// === 标签数据迁移 ===
$output->writeln('');
$output->writeln('<comment>【标签数据迁移】</comment>');
// Step 7: 同步微信标签
$output->writeln('<comment>[7/7] 同步微信标签 ck_traffic_pool_tag ...</comment>');
$results['pool_tags'] = $adapter->syncWechatTagsToV2();
$output->writeln("<info> 完成,影响行数: {$results['pool_tags']}</info>");
return $results;
}
/**
* 执行指定步骤
*/
protected function runStep(int $step, ChuKeBaoAdapter $adapter, Output $output)
{
$results = [];
switch ($step) {
case 1:
$output->writeln('<comment>[Step 1] 同步好友到流量池总表 ck_traffic_pool ...</comment>');
$results['friend_pool'] = $adapter->syncToTrafficPoolV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool']}</info>");
break;
case 2:
$output->writeln('<comment>[Step 2] 同步好友到公司流量详情表 ck_traffic_pool_company ...</comment>');
$results['friend_pool_company'] = $adapter->syncToTrafficPoolCompanyV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool_company']}</info>");
break;
case 3:
$output->writeln('<comment>[Step 3] 同步好友到流量来源表 ck_traffic_pool_source ...</comment>');
$results['friend_pool_source'] = $adapter->syncToTrafficPoolSourceV2();
$output->writeln("<info> 完成,影响行数: {$results['friend_pool_source']}</info>");
break;
case 4:
$output->writeln('<comment>[Step 4] 同步群成员到流量池总表 ck_traffic_pool ...</comment>');
$results['chatroom_pool'] = $adapter->syncChatroomMembersToTrafficPoolV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool']}</info>");
break;
case 5:
$output->writeln('<comment>[Step 5] 同步群成员到公司流量详情表 ck_traffic_pool_company ...</comment>');
$results['chatroom_pool_company'] = $adapter->syncChatroomMembersToTrafficPoolCompanyV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool_company']}</info>");
break;
case 6:
$output->writeln('<comment>[Step 6] 同步群成员到流量来源表 ck_traffic_pool_source ...</comment>');
$results['chatroom_pool_source'] = $adapter->syncChatroomMembersToTrafficPoolSourceV2();
$output->writeln("<info> 完成,影响行数: {$results['chatroom_pool_source']}</info>");
break;
case 7:
$output->writeln('<comment>[Step 7] 同步微信标签 ck_traffic_pool_tag ...</comment>');
$results['pool_tags'] = $adapter->syncWechatTagsToV2();
$output->writeln("<info> 完成,影响行数: {$results['pool_tags']}</info>");
break;
default:
$output->writeln('<error>无效的步骤编号,请输入 1-7</error>');
$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;
}
}