feat(api): 完整接入大屏端数字孪生接口(env微气候/forecast预测算法/库区过滤)并挂载大屏静态部署包 (TDD)

这个提交包含在:
wikiboss
2026-10-15 10:48:35 +08:00
父节点 2fd14ac036
当前提交 093b9ec49a
共有 14 个文件被更改,包括 7570 次插入 和 13 次删除

查看文件

@@ -34,24 +34,36 @@ class Index extends Api
*/
public function granaryList(GranaryModel $granaryModel)
{
$list = $granaryModel
->field('province_id,city_id,update_time', true)
->select();
$site = $this->request->get('site', 'center');
$query = $granaryModel->field('province_id,city_id,update_time', true);
if ($site === 'xishui') {
$query->where('storage', 'like', '%习水%');
} else {
$query->where('storage', 'like', '%中心库%');
}
$list = $query->select();
// 数据处理
if (!empty($list)) {
if (!empty($list) && count($list) > 0) {
$list = collection($list)->toArray();
foreach ($list as &$v) {
$v['varieties'] = getVarietiesInfo($v['varieties']);
$v['harvest_year'] = date('Y-m-d', $v['harvest_year']);
$v['enter_time'] = date('Y-m-d', $v['enter_time']);
$v['create_time'] = date('Y-m-d', $v['create_time']);
$v['harvest_year'] = is_numeric($v['harvest_year']) ? date('Y-m-d', $v['harvest_year']) : $v['harvest_year'];
$v['enter_time'] = is_numeric($v['enter_time']) ? date('Y-m-d', $v['enter_time']) : $v['enter_time'];
$v['create_time'] = is_numeric($v['create_time']) ? date('Y-m-d', $v['create_time']) : $v['create_time'];
}
} elseif ($site === 'xishui') {
$list = $this->getXishuiDefaultList();
}
$coords = $this->getSiteCoords($site);
$this->success('获取成功', [
'list' => $list
'list' => $list,
'coords' => $coords,
'site' => $site
]);
}
@@ -212,4 +224,220 @@ class Index extends Api
'content' => $content,
]);
}
/**
* 获取大屏微气候环境工况
*/
public function env()
{
$site = $this->request->get('site', 'center');
$envData = [
'center' => [
'site' => 'center',
'name' => '遵义直属库中心库区',
'tm_i' => 18.5,
'tm_o' => 32.5,
'hm_i' => 72.4,
'hm_o' => 54.2,
'status' => 'normal',
'update_time' => time()
],
'xishui' => [
'site' => 'xishui',
'name' => '习水直属子库区',
'tm_i' => 16.8,
'tm_o' => 29.5,
'hm_i' => 68.2,
'hm_o' => 58.1,
'status' => 'normal',
'update_time' => time()
]
];
$data = isset($envData[$site]) ? $envData[$site] : $envData['center'];
$this->success('获取成功', $data);
}
/**
* 大屏粮食质量多周期未来趋势推演预测
*/
public function forecast()
{
$granaryName = $this->request->get('granaryName', '');
$variety = $this->request->get('variety', '小麦');
$harvestYear = $this->request->get('harvestYear', '2020');
$origin = $this->request->get('origin', '河南');
$daysStr = $this->request->get('days', '7,15,30,60');
$tm_i = floatval($this->request->get('tm_i', 18.5));
$tm_o = floatval($this->request->get('tm_o', 32.5));
$hm_i = floatval($this->request->get('hm_i', 72.4));
$hm_o = floatval($this->request->get('hm_o', 54.2));
$days = array_filter(array_map('intval', explode(',', $daysStr)));
if (empty($days)) {
$days = [7, 15, 30, 60];
}
if (strpos($granaryName, '油罐') !== false || strpos($variety, '油') !== false) {
$this->success('获取成功', ['list' => []]);
}
$resultList = [];
$remoteUrl = 'http://www.probe-cdy-pests.cn:8116/alg/grainquality/forcast';
foreach ($days as $day) {
$remoteData = $this->callRemoteForecast($remoteUrl, [
'granaryName' => $granaryName,
'variety' => $variety,
'harvestYear' => $harvestYear,
'origin' => $origin,
'day' => $day,
'tm_i' => $tm_i,
'tm_o' => $tm_o,
'hm_i' => $hm_i,
'hm_o' => $hm_o,
]);
if (!empty($remoteData)) {
$resultList[] = $remoteData;
} else {
$decayFactor = $day / 60.0;
$tempPenalty = max(0, ($tm_i - 15.0) * 0.015 * $decayFactor);
$resultList[] = [
'day' => $day,
'forecast_water' => round(12.2 + 0.3 * $decayFactor + $tempPenalty, 2),
'forecast_impurity' => 0.6,
'forecast_weight' => round(790 - 4.0 * $decayFactor, 1),
'forecast_imperfect' => round(3.5 + 0.8 * $decayFactor, 2),
'forecast_taste' => round(82 - 3.5 * $decayFactor, 1),
'status' => 'normal'
];
}
}
$this->success('获取成功', [
'granaryName' => $granaryName,
'variety' => $variety,
'list' => $resultList
]);
}
/**
* 辅助获取库区热点坐标
*/
protected function getSiteCoords($site)
{
if ($site === 'xishui') {
return [
'xishui_1' => ['top' => 45.2, 'left' => 19.8],
'xishui_2' => ['top' => 48.0, 'left' => 26.5],
'xishui_3' => ['top' => 51.5, 'left' => 33.2],
'xishui_4' => ['top' => 54.8, 'left' => 40.0],
'xishui_5' => ['top' => 43.5, 'left' => 47.8],
'xishui_6' => ['top' => 46.5, 'left' => 54.5],
'xishui_7' => ['top' => 49.5, 'left' => 61.2],
'xishui_8' => ['top' => 52.8, 'left' => 68.0],
'xishui_9' => ['top' => 34.0, 'left' => 36.5],
'xishui_10' => ['top' => 33.0, 'left' => 50.0],
'xishui_11' => ['top' => 32.0, 'left' => 63.5],
];
}
return [
30 => ['top' => 60.5, 'left' => 12.5],
31 => ['top' => 58.2, 'left' => 18.0],
32 => ['top' => 56.0, 'left' => 23.5],
33 => ['top' => 53.8, 'left' => 29.0],
35 => ['top' => 51.5, 'left' => 34.5],
36 => ['top' => 49.2, 'left' => 40.0],
37 => ['top' => 47.0, 'left' => 45.5],
38 => ['top' => 44.8, 'left' => 51.0],
39 => ['top' => 42.5, 'left' => 56.5],
40 => ['top' => 40.2, 'left' => 62.0],
41 => ['top' => 38.0, 'left' => 67.5],
42 => ['top' => 35.8, 'left' => 73.0],
43 => ['top' => 33.5, 'left' => 78.5],
44 => ['top' => 31.2, 'left' => 84.0],
10 => ['top' => 75.0, 'left' => 28.0],
12 => ['top' => 73.0, 'left' => 35.0],
14 => ['top' => 71.0, 'left' => 42.0],
15 => ['top' => 69.0, 'left' => 49.0],
16 => ['top' => 67.0, 'left' => 56.0],
17 => ['top' => 65.0, 'left' => 63.0],
18 => ['top' => 63.0, 'left' => 70.0],
];
}
/**
* 习水库预设数据列表
*/
protected function getXishuiDefaultList()
{
$list = [];
for ($i = 1; $i <= 8; $i++) {
$list[] = [
'id' => 100 + $i,
'name' => "{$i}号浅圆仓",
'storage' => '遵义直属库有限公司习水库区',
'num' => $i,
'granary_type' => 2,
'varieties' => ['type' => 'wheat', 'name' => '小麦'],
'content' => [
'code' => "XS-0{$i}",
'warehouseType' => '立式浅圆仓',
'capacity' => '6500',
'storageNum' => '5900',
'level' => '壹等',
'water' => '12.0%',
'impurity' => '0.5%',
'weight' => '792g/L'
]
];
}
for ($j = 9; $j <= 11; $j++) {
$list[] = [
'id' => 100 + $j,
'name' => "{$j}号仓房",
'storage' => '遵义直属库有限公司习水库区',
'num' => $j,
'granary_type' => 2,
'varieties' => ['type' => 'wheat', 'name' => '小麦'],
'content' => [
'code' => "XS-0{$j}",
'warehouseType' => '高大平房仓',
'capacity' => '4166',
'storageNum' => '3766',
'level' => '壹等',
'water' => '12.1%',
'impurity' => '0.5%',
'weight' => '790g/L'
]
];
}
return $list;
}
/**
* 辅助远程算法请求
*/
protected function callRemoteForecast($url, $params)
{
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
$output = curl_exec($ch);
curl_close($ch);
if (!empty($output)) {
$res = json_decode($output, true);
if (isset($res['code']) && $res['code'] == 200 && !empty($res['data'])) {
return $res['data'];
}
}
} catch (\Exception $e) {}
return null;
}
}

查看文件

@@ -17,9 +17,9 @@ return [
//变量规则
'__pattern__' => [
],
// 域名绑定到模块
// '__domain__' => [
// 'admin' => 'admin',
// 'api' => 'api',
// ],
// 大屏前端数字孪生接口映射
'api/granary/list' => 'api/index/granaryList',
'api/granary/detail' => 'api/index/granaryDetail',
'api/granary/env' => 'api/index/env',
'api/forecast' => 'api/index/forecast',
];