This commit is contained in:
2025-06-09 11:37:32 +08:00
parent 0eec194a96
commit e5ae751512
8 changed files with 479 additions and 16 deletions
+97 -7
View File
@@ -2,6 +2,8 @@
namespace app\controller;
use app\model\LogisticsShip;
use app\model\LogisticsShipHis;
use app\model\Vehicle;
use app\model\VehicleEn;
use app\model\VehicleRu;
@@ -14,6 +16,7 @@ use app\model\LocationAr;
use app\service\OssService;
// use plugin\admin\app\model\Location;
use app\service\ShipService;
use app\service\TranslatorService;
use util\Util;
use support\Request;
@@ -47,28 +50,42 @@ class VehicleController
{
$lang = $request->post('lang', 'zh');
$status = $request->post('status', '4');
// 接收请求参数(Webman自动注入)
$page = $request->post('page', 1); // 默认第1页
$pageSize = $request->post('pageSize', 30); // 默认每页30条
$where = [];
if($status == 1){
$status = [5,6];
}elseif ($status == 2){
$status = [4];
}elseif ($status == 3){
$status = [1,2,3,7,8];
$where[] = ['vin' ,'!=', null];
}elseif ($status == 4){
$status = [1,2,3,7,8];
$where[] = ['vin' ,'=', null];
}
switch ($lang) {
case 'zh':
$vehicles = Vehicle::with('location')->with('finalLocation') ->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$vehicles = Vehicle::with('location')->with('finalLocation')->where($where)->whereIn('status',$status)->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new Location();
break;
case 'en':
$vehicles = VehicleEn::with('location')->with('finalLocation')->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$vehicles = VehicleEn::with('location')->with('finalLocation')->where($where)->whereIn('status',$status)->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationEn();
break;
case 'ru':
$vehicles = VehicleRu::with('location')->with('finalLocation')->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$vehicles = VehicleRu::with('location')->with('finalLocation')->where($where)->whereIn('status',$status)->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationRu();
break;
case 'ar':
$vehicles = VehicleAr::with('location')->with('finalLocation')->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$vehicles = VehicleAr::with('location')->with('finalLocation')->where($where)->whereIn('status',$status)->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationAr();
break;
}
@@ -118,6 +135,73 @@ class VehicleController
if(is_numeric($vehicle->status)) {
$vehicle->status = $this->status[$lang][$vehicle->status]??$this->status[$lang][0];
}
// if(!empty($vehicle['img_url'])) {
// $img_url = Cache::get('img_dib_'.$vehicle->id);
// if ($img_url) {
// $vehicle['img_url'] = $img_url;
// } else {
// $ossservice = empty($ossservice)?new OssService():$ossservice;
// $img_url = $ossservice->generatePrivateUrl($vehicle['img_url'],86400);
// $vehicle['img_url'] = $img_url;
// Cache::set('img_dib_'.$vehicle->id, $img_url, 86390);
// }
// }else{
// $vehicle['img_url'] = '';
// }
if(!empty($vehicle['ship_id'])){
$vehicle['ship'] = LogisticsShip::find($vehicle['ship_id'])->toArray();
}
}
unset($vehicle);
// =================================== new ===================================== end
$count = Vehicle::where($where)->whereIn('status',$status)->count();
$result = ['list' => $vehicles,'count'=>$count];
return Util::success($result);
}
public function ship(Request $request,$id){
// $res = ShipService::getShipInfo('413399120');
// return Util::success($res);
$lang = $request->post('lang', 'zh');
// 接收请求参数(Webman自动注入)
$page = $request->post('page', 1); // 默认第1页
$pageSize = $request->post('pageSize', 30); // 默认每页30条
// var_dump($id);die;
switch ($lang) {
case 'zh':
$vehicles = Vehicle::with('location')->with('finalLocation')->where(['ship_id' => $id])->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new Location();
break;
case 'en':
$vehicles = VehicleEn::with('location')->with('finalLocation')->where(['ship_id' => $id])->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationEn();
break;
case 'ru':
$vehicles = VehicleRu::with('location')->with('finalLocation')->where(['ship_id' => $id])->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationRu();
break;
case 'ar':
$vehicles = VehicleAr::with('location')->with('finalLocation')->where(['ship_id' => $id])->offset(($page-1)*$pageSize) ->limit($pageSize)->get();
$hz = new LocationAr();
break;
}
// 组装数据
foreach ($vehicles as &$vehicle) {
if (isset($vehicle->vin)) {
$vehicle->vin = $this->maskVin($vehicle->vin);
}
$vehicle->purchase_location='';
$vehicle->procedure_location='';
$vehicle->fbo_destination = isset($arr[$vehicle->fbo_locations_id]) ? $arr[$vehicle->fbo_locations_id]['name'] : '';
$vehicle->status_val = $vehicle->status;
if(is_numeric($vehicle->status)) {
$vehicle->status = $this->status[$lang][$vehicle->status]??$this->status[$lang][0];
}
if(!empty($vehicle['img_url'])) {
$img_url = Cache::get('img_dib_'.$vehicle->id);
if ($img_url) {
@@ -131,11 +215,17 @@ class VehicleController
}else{
$vehicle['img_url'] = '';
}
if(!empty($vehicle['ship_id'])){
$vehicle['ship'] = LogisticsShip::find($vehicle['ship_id'])->toArray();
}
}
unset($vehicle);
// =================================== new ===================================== end
$count = Vehicle::count();
$result = ['list' => $vehicles,'count'=>$count];
$logisticsShip = LogisticsShip::where(['id' => $id])->first();
$logisticsShipHis = LogisticsShipHis::where(['ship_id'=> $id])->get();
$count = Vehicle::where(['ship_id' => $id])->count();
$result = ['list' => $vehicles,'ship' => $logisticsShip,'ship_his' => $logisticsShipHis,'count'=>$count];
return Util::success($result);
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace app\model;
use support\Model;
class LogisticsShip extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'logistics_ship';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
//批量赋值黑名单
protected $guarded = ['created_at', 'updated_at'];
/**
* Get the location that owns the vehicle.
*/
public function vehicles()
{
return $this->belongsTo(Vehicle::class, 'ship_id', 'id');
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace app\model;
use support\Model;
class LogisticsShipHis extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'logistics_ship_his';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
//批量赋值黑名单
protected $guarded = ['created_at', 'updated_at'];
/**
* Get the location that owns the vehicle.
*/
public function ship()
{
return $this->belongsTo(Vehicle::class, 'ship_id', 'id');
}
}
+6
View File
@@ -46,4 +46,10 @@ class Vehicle extends Model
{
return $this->belongsTo(Location::class, 'final_locations_id', 'id');
}
public function ship()
{
return $this->hasOne(Vehicle::class, 'ship_id', 'id');
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace app\service;
use app\util\HttpClient;
class ShipService
{
private const API_BASE_URL = 'https://api.shipxy.com/apicall/v3';
private const API_KEY = 'ab107a0254494d61a25749028c0f09c2';
/**
* 获取单个船舶信息
* @param string $mmsi 船舶MMSI号
* @return array 返回船舶信息
*/
public static function getShipInfo(string $mmsi): array
{
$url = self::API_BASE_URL . '/GetSingleShip';
$query = [
'key' => self::API_KEY,
'mmsi' => $mmsi
];
$response = HttpClient::get($url, $query);
// 检查API响应状态
if (!$response['status']) {
return [
'success' => false,
'message' => '请求失败: ' . $response['message'],
'data' => null
];
}
// 检查API业务状态
if (isset($response['data']['status']) && $response['data']['status'] !== 0) {
return [
'success' => false,
'message' => '获取船舶信息失败: ' . ($response['data']['msg'] ?? '未知错误'),
'data' => null
];
}
return [
'success' => true,
'message' => '获取成功',
'data' => $response['data']
];
}
}
+227
View File
@@ -0,0 +1,227 @@
<?php
namespace app\util;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
class HttpClient
{
/**
* @var Client Guzzle客户端实例
*/
private static $client;
/**
* 获取Guzzle客户端单例
* @return Client
*/
private static function getClient(): Client
{
if (!self::$client) {
self::$client = new Client([
'timeout' => 10, // 默认超时时间10秒
'verify' => false, // 不验证SSL证书(生产环境建议设为true)
'http_errors' => false, // 不抛出HTTP异常,自己处理
]);
}
return self::$client;
}
/**
* 发送GET请求
* @param string $url 请求地址
* @param array $query 查询参数
* @param array $headers 请求头
* @return array
*/
public static function get(string $url, array $query = [], array $headers = []): array
{
$options = [
'query' => $query,
'headers' => $headers
];
return self::request('GET', $url, $options);
}
/**
* 发送POST请求
* @param string $url 请求地址
* @param array|string $data 请求数据
* @param array $headers 请求头
* @param string $contentType 内容类型(form/json/xml)
* @return array
*/
public static function post(string $url, $data = [], array $headers = [], string $contentType = 'form'): array
{
$options = ['headers' => $headers];
switch ($contentType) {
case 'json':
$options['json'] = $data;
$options['headers']['Content-Type'] = 'application/json';
break;
/*case 'xml':
$options['body'] = is_array($data) ? self::arrayToXml($data) : $data;
$options['headers']['Content-Type'] = 'application/xml';
break;*/
default: // form
$options['form_params'] = $data;
$options['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
}
return self::request('POST', $url, $options);
}
/**
* 发送PUT请求
* @param string $url 请求地址
* @param array|string $data 请求数据
* @param array $headers 请求头
* @return array
*/
public static function put(string $url, $data = [], array $headers = []): array
{
$options = [
'json' => $data,
'headers' => $headers
];
return self::request('PUT', $url, $options);
}
/**
* 发送DELETE请求
* @param string $url 请求地址
* @param array $data 请求数据
* @param array $headers 请求头
* @return array
*/
public static function delete(string $url, array $data = [], array $headers = []): array
{
$options = [
'json' => $data,
'headers' => $headers
];
return self::request('DELETE', $url, $options);
}
/**
* 发送HTTP请求
* @param string $method 请求方法
* @param string $url 请求地址
* @param array $options 请求选项
* @return array
*/
public static function request(string $method, string $url, array $options = []): array
{
try {
$response = self::getClient()->request($method, $url, $options);
return self::formatResponse($response);
} catch (GuzzleException $e) {
return [
'status' => false,
'code' => $e->getCode(),
'message' => $e->getMessage(),
'data' => null
];
}
}
/**
* 上传文件
* @param string $url 请求地址
* @param array $files 文件数组 [['name' => 'field_name', 'path' => 'file_path']]
* @param array $form 其他表单数据
* @param array $headers 请求头
* @return array
*/
public static function upload(string $url, array $files, array $form = [], array $headers = []): array
{
$multipart = [];
// 添加文件
foreach ($files as $file) {
if (file_exists($file['path'])) {
$multipart[] = [
'name' => $file['name'],
'contents' => fopen($file['path'], 'r'),
'filename' => basename($file['path'])
];
}
}
// 添加其他表单数据
foreach ($form as $name => $value) {
$multipart[] = [
'name' => $name,
'contents' => $value
];
}
$options = [
'multipart' => $multipart,
'headers' => $headers
];
return self::request('POST', $url, $options);
}
/**
* 格式化响应
* @param ResponseInterface $response
* @return array
*/
private static function formatResponse(ResponseInterface $response): array
{
$contents = $response->getBody()->getContents();
$contentType = $response->getHeaderLine('Content-Type');
$data = $contents;
if (strpos($contentType, 'application/json') !== false) {
$data = json_decode($contents, true) ?? $contents;
}
return [
'status' => $response->getStatusCode() === 200,
'code' => $response->getStatusCode(),
'message' => $response->getReasonPhrase(),
'data' => $data,
'headers' => $response->getHeaders()
];
}
/**
* 数组转XML
* @param array $data
* @param string $rootNode
* @return string
*/
private static function arrayToXml(array $data, string $rootNode = 'root'): string
{
$xml = new \SimpleXMLElement('<' . $rootNode . '/>');
self::addDataToXml($xml, $data);
return $xml->asXML();
}
/**
* 递归添加数据到XML
* @param \SimpleXMLElement $xml
* @param array $data
*/
private static function addDataToXml(\SimpleXMLElement $xml, array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
if (is_numeric($key)) {
$key = 'item';
}
$subNode = $xml->addChild($key);
self::addDataToXml($subNode, $value);
} else {
$xml->addChild($key, htmlspecialchars($value));
}
}
}
}
+2 -1
View File
@@ -38,7 +38,8 @@
"workerman/crontab": "^1.0",
"webman/redis": "dev-main",
"illuminate/events": "^12.14",
"webman/redis-queue": "^1.3"
"webman/redis-queue": "^1.3",
"guzzlehttp/guzzle": "^7.9"
},
"suggest": {
"ext-event": "For better performance. "
Generated
+14 -8
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5890526c12c278e535143c406c9f1b88",
"content-hash": "6cd3f9d702599d003e58cc41b6635fac",
"packages": [
{
"name": "aliyuncs/oss-sdk-php",
@@ -418,17 +418,23 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.9.3",
"version": "7.9.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
"reference": "d281ed313b989f213357e3be1a179f02196ac99b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"shasum": ""
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
"reference": "d281ed313b989f213357e3be1a179f02196ac99b",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-json": "*",
@@ -524,7 +530,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.9.3"
"source": "https://github.com/guzzle/guzzle/tree/7.9.2"
},
"funding": [
{
@@ -540,7 +546,7 @@
"type": "tidelift"
}
],
"time": "2025-03-27T13:37:11+00:00"
"time": "2024-07-24T11:22:20+00:00"
},
{
"name": "guzzlehttp/promises",