船舶更新

This commit is contained in:
2025-06-10 09:04:40 +08:00
parent ca2ecf41fc
commit f2f5f100e5
10 changed files with 1152 additions and 0 deletions
+145
View File
@@ -0,0 +1,145 @@
<?php
namespace app\command;
use app\model\LogisticsShip;
use app\model\LogisticsShipHis;
use app\service\ShipService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use support\Log;
class UpdateShipInfoCommand extends Command
{
protected static $defaultName = 'update:ship-info';
protected static $defaultDescription = '更新船舶信息 - 每三天执行一次';
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('开始更新船舶信息...');
try {
// 查询需要更新的船舶
// 如果logistics_ship表有status字段,查询status为2的船舶
// 如果没有status字段,可以查询所有船舶或者根据其他条件筛选
$ships = $this->getShipsToUpdate();
if ($ships->isEmpty()) {
$output->writeln('没有找到需要更新的船舶');
return self::SUCCESS;
}
$output->writeln("找到 {$ships->count()} 艘需要更新的船舶");
$successCount = 0;
$errorCount = 0;
foreach ($ships as $ship) {
try {
$output->write("正在更新船舶 {$ship->mmsi} (ID: {$ship->id})... ");
// 获取船舶MMSI号,这里假设使用IMO作为MMSI
$mmsi = $ship->mmsi;
// 通过ShipService获取船舶最新信息
$shipInfo = ShipService::getShipInfo($mmsi);
if (!$shipInfo['success']) {
$output->writeln("失败: " . $shipInfo['message']);
$errorCount++;
continue;
}
$apiData = $shipInfo['data']['data'] ?? null;
if (!$apiData) {
$output->writeln("失败: API返回数据为空");
$errorCount++;
continue;
}
// 保存当前船舶信息到历史表
$this->saveToHistory($ship);
// 更新船舶信息
$updateData = $this->mapApiDataToShip($apiData);
$ship->fill($updateData);
$ship->save();
$output->writeln("成功");
$successCount++;
// 添加延迟避免API请求过于频繁
sleep(1);
} catch (\Exception $e) {
$output->writeln("失败: " . $e->getMessage());
$errorCount++;
Log::error("更新船舶信息失败", [
'ship_id' => $ship->id,
'imo' => $ship->IMO,
'error' => $e->getMessage()
]);
}
}
$output->writeln("更新完成!成功: {$successCount}, 失败: {$errorCount}");
} catch (\Exception $e) {
$output->writeln("执行失败: " . $e->getMessage());
Log::error("船舶信息更新任务执行失败", [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return self::FAILURE;
}
return self::SUCCESS;
}
/**
* 获取需要更新的船舶列表
* @return \Illuminate\Database\Eloquent\Collection
*/
private function getShipsToUpdate()
{
return LogisticsShip::where('status', 1)->get();
}
/**
* 保存船舶信息到历史表
* @param LogisticsShip $ship
*/
private function saveToHistory(LogisticsShip $ship): void
{
$historyData = $ship->toArray();
$historyData['ship_id'] = $ship->id;
unset($historyData['id']); // 移除主键,让数据库自动生成
LogisticsShipHis::create($historyData);
}
/**
* 将API数据映射到船舶表字段
* @param array $apiData
* @return array
*/
private function mapApiDataToShip(array $apiData): array
{
return [
'IMO' => $apiData['imo'] ?? '',
'call_sign' => $apiData['call_sign'] ?? '',
'ship_name' => $apiData['ship_name'] ?? '',
'ship_cnname' => $apiData['ship_cnname'] ?? '',
'wail' => $apiData['call_sign'] ?? '',
'dest' => $apiData['dest'] ?? '',
'length' => $apiData['length'] ?? '',
'width' => $apiData['width'] ?? '',
'lat' => $apiData['lat'] ?? '',
'lng' => $apiData['lng'] ?? '',
'eta_utc' => $apiData['eta_utc'] ?? null,
'last_time_utc' => $apiData['last_time_utc'] ?? null,
'updated_at' => date('Y-m-d H:i:s')
];
}
}
+62
View File
@@ -2,6 +2,7 @@
namespace app\controller;
use app\command\UpdateShipInfoCommand;
use app\model\LogisticsShip;
use app\model\LogisticsShipHis;
use app\model\Vehicle;
@@ -18,6 +19,9 @@ use app\service\OssService;
// use plugin\admin\app\model\Location;
use app\service\ShipService;
use app\service\TranslatorService;
use support\Log;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use util\Util;
use support\Request;
use support\Cache;
@@ -253,6 +257,64 @@ class VehicleController
return Util::success($result);
}
public function shipList(Request $request){
$navigate = LogisticsShip::where(['status' => 0])->get();
$pending = LogisticsShip::where(['status' => 1])->get();
$result = ['navigate' => $navigate,'pending' => $pending];
return Util::success($result);
}
public function add(Request $request){
try {
Log::info('开始执行船舶信息更新任务');
// 通过ShipService获取船舶最新信息
$shipInfo = ShipService::getShipInfo($request->get('mmsi'));
$apiData = $shipInfo['data']['data'] ?? null;
$ship = new LogisticsShip();
$updateData = $this->mapApiDataToShip($apiData);
$updateData['mmsi'] = $request->get('mmsi');
$ship->fill($updateData);
$res = $ship->save();
if($res){
return Util::success($res,'成功');
} else{
return Util::fail($res,'成功');
}
} catch (\Exception $e) {
Log::error('船舶信息更新任务执行异常', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
}
}
/**
* 将API数据映射到船舶表字段
* @param array $apiData
* @return array
*/
private function mapApiDataToShip(array $apiData): array
{
return [
'IMO' => $apiData['imo'] ?? '',
'call_sign' => $apiData['call_sign'] ?? '',
'ship_name' => $apiData['ship_name'] ?? '',
'ship_cnname' => $apiData['ship_cnname'] ?? '',
'dest' => $apiData['dest'] ?? '',
'length' => $apiData['length'] ?? '',
'width' => $apiData['width'] ?? '',
'lat' => $apiData['lat'] ?? '',
'lng' => $apiData['lng'] ?? '',
'eta_utc' => $apiData['eta_utc'] ?? null,
'last_time_utc' => $apiData['last_time_utc'] ?? null,
'updated_at' => date('Y-m-d H:i:s')
];
}
/**
* Get a specific vehicle with its location
*/
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace app\process;
use app\command\UpdateShipInfoCommand;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Workerman\Crontab\Crontab;
use Workerman\Timer;
use Workerman\Worker;
use support\Log;
class ShipUpdateScheduler extends Worker
{
public function onWorkerStart()
{
new Crontab('0 5 */3 * *', function(){
$this->runShipUpdateCommand();
});
// 每三天执行一次船舶信息更新
// 3天 = 3 * 24 * 60 * 60 = 259200秒
// Timer::add(259200, function() {
// $this->runShipUpdateCommand();
// });
//
// // 启动时也执行一次,确保有数据
// $this->runShipUpdateCommand();
//
// Log::info('船舶信息更新调度器已启动');
}
/**
* 执行船舶信息更新命令
*/
private function runShipUpdateCommand()
{
try {
Log::info('开始执行船舶信息更新任务');
$command = new UpdateShipInfoCommand();
$input = new ArrayInput([]);
$output = new BufferedOutput();
$exitCode = $command->run($input, $output);
if ($exitCode === 0) {
Log::info('船舶信息更新任务执行成功: ' . $output->fetch());
} else {
Log::error('船舶信息更新任务执行失败: ' . $output->fetch());
}
} catch (\Exception $e) {
Log::error('船舶信息更新任务执行异常', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
}
}
}