success('请求成功'); } /** * 获取仓库列表 * @param GranaryModel $granaryModel * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function granaryList(GranaryModel $granaryModel) { $site = $this->request->get('site', 'center'); if (!GranarySite::valid($site)) $this->error('无效库区'); $query = $granaryModel->field('province_id,city_id,update_time', true); $query->where('site', $site); $list = $query->select(); // 数据处理 if (!empty($list) && count($list) > 0) { $list = collection($list)->toArray(); // Load saved rules in two queries rather than one query per granary. $tests = TestingModel::with(['testingParams']) ->where('gid', 'in', array_column($list, 'id')) ->order('is_demo ASC, test_date DESC, id DESC')->select(); $latestTests = []; foreach ($tests as $test) { $test = $test->toArray(); $testKey = $test['gid'] . ':' . $test['type']; if (!isset($latestTests[$testKey])) { $latestTests[$testKey] = $test; } } foreach ($list as &$v) { $v['varieties'] = getVarietiesInfo($v['varieties']); $testKey = $v['id'] . ':' . $v['varieties']['type']; $v['quality_test'] = isset($latestTests[$testKey]) ? $latestTests[$testKey] : null; $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']; // 顶层 capacity 与 storage_num 智能反填 $content = is_string($v['content']) ? json_decode($v['content'], true) : $v['content']; if (empty($v['capacity']) && !empty($content)) { $v['capacity'] = isset($content['capacity']) ? $content['capacity'] : (isset($content['tankCapacity']) ? $content['tankCapacity'] : null); } if ((empty($v['storage_num']) || $v['storage_num'] == '0') && !empty($content['storageNum'])) { $v['storage_num'] = $content['storageNum']; } } } $coords = $this->getSiteCoords($site); if ($site !== 'xishui' && is_array($list)) { foreach ($list as &$granary) { $granary['screen_coord'] = \app\common\library\GranaryScreen::resolve($granary, $coords); } unset($granary); } if ($site === 'xishui') { foreach ($list as &$granary) { $key = 'xishui_' . $granary['num']; $granary['screen_coord'] = isset($coords[$key]) ? $coords[$key] : null; } unset($granary); } $this->success('获取成功', [ 'list' => $list, 'coords' => $coords, 'site' => $site, 'site_name' => GranarySite::NAMES[$site], 'source' => 'database' ]); } /** * 仓库详情 * @param GranaryModel $granaryModel * @param TestingModel $testingModel * @param TestingParamsModel $testingParamsModel * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function granaryDetail(GranaryModel $granaryModel, TestingModel $testingModel, TestingParamsModel $testingParamsModel) { $id = $this->request->get('id'); $type = $this->request->get('type'); if (empty($id) || empty($type)) { $this->error('参数错误', [], 401); } $granary = $granaryModel->where(['id' => $id]) ->field('province_id,city_id,update_time', true) ->find(); if (empty($granary)) { $this->error('您要查看的仓库不存在', [], 402); } // 获取农作物最新检测参数 $test = $testingModel ->with(['testingParams']) ->where(['gid' => $id, 'type' => $type]) ->field(['id', 'type', 'test_date']) ->order('test_date DESC') ->find(); // 折线图统计数据 $seriesData = []; $xAxisData = []; if (!empty($test)) { $seriesData = Db::name('testing_params') ->where(['tid' => $test->id, 'name' => ['NEQ', '容重'], 'is_number' => 1]) ->field(['id', 'name', 'unit', 'color']) ->select(); $testList = Db::name('testing') ->field(['id', 'year']) ->where(['gid' => $id]) ->group('year') ->order('sort DESC') ->limit(6) ->select(); // 重新排序 // $yearArr = array_column($testList, 'year'); // array_multisort($yearArr, SORT_ASC, $testList); foreach ($testList as $index => $value) { // 获取季度 $list = Db::name('testing') ->where(['gid' => $id, 'year' => $value['year']]) ->field('season') ->select(); foreach ($list as $v) { switch ($v['season']) { case 1 : $season = '春季'; break; case 2 : $season = '秋季'; break; case 3 : $season = '满仓'; break; } array_push($xAxisData, $value['year'] . $season); } foreach ($seriesData as &$item) { // 获取参数数值 foreach ($list as $val) { $val = Db::name('testing_params')->where([ 'gid' => $id, 'name' => $item['name'], 'year' => $value['year'], 'season' => $val['season'], ])->value('val'); $item['data'][] = !empty($val) ? $val : 0; $item['color'] = getColorCode($item['name']); } } } } // 质检报告列表 $contentList = Db::name('content') ->where(['gid' => $id, 'status' => 1]) ->field(['id', 'type', 'test_date']) ->order('test_date ASC') ->select(); if (!empty($contentList)) { foreach ($contentList as &$v) { switch ($v['type']) { case 1 : $v['title'] = $v['test_date'] . '满仓验收'; break; case 2 : $v['title'] = $v['test_date'] . '春普'; break; case 3 : $v['title'] = $v['test_date'] . '秋普'; break; } } } // 时间处理 $granary->create_time = date('Y-m-d H:i:s', $granary->create_time); $this->success('获取成功', [ 'granary' => $granary, 'test' => $test, 'xAxisData' => $xAxisData, 'seriesData' => $seriesData, 'contentList' => $contentList ]); } /** * 获取质检报告详情 * @param ContentModel $contentModel * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function contentDetail(ContentModel $contentModel) { $id = $this->request->get('id'); if (empty($id)) { $this->error('参数错误', [], 401); } $content = $contentModel->getItem($id, [ 'id', 'content' ]); if (empty($content)) { $this->error('您要查看的质检报告不存在', [], 402); } $this->success('获取成功', [ 'content' => $content, ]); } /** * 获取大屏微气候环境工况 */ public function env() { = ->request->get('site', 'center'); if (!GranarySite::valid()) ->error('无效库区'); = [ '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() ] ]; = isset([]) ? [] : ['center']; // 优先读取该库区最新一条人工录入或设定的温湿度快照 try { = Db::name('grain_forecast') ->alias('f') ->join('granary g', 'f.gid = g.id') ->where('g.site', ) ->order('f.id DESC') ->field('f.tm_i, f.hm_i, f.tm_o, f.hm_o, f.update_time') ->find(); if () { ['tm_i'] = (float)['tm_i']; ['hm_i'] = (float)['hm_i']; ['tm_o'] = (float)['tm_o']; ['hm_o'] = (float)['hm_o']; ['update_time'] = (int)['update_time']; } } catch (\Exception ) { // 异常时安全兜底基准工况 } ->success('获取成功', ); } /** * 大屏粮食质量多周期未来趋势推演预测 */ 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 [ 101 => ['top' => 47.5, 'left' => 26.4, 'x' => 26.4, 'y' => 47.5], 102 => ['top' => 48.0, 'left' => 39.6, 'x' => 39.6, 'y' => 48.0], 103 => ['top' => 48.0, 'left' => 60.4, 'x' => 60.4, 'y' => 48.0], 104 => ['top' => 47.5, 'left' => 73.7, 'x' => 73.7, 'y' => 47.5], 105 => ['top' => 33.5, 'left' => 27.0, 'x' => 27.0, 'y' => 33.5], 106 => ['top' => 34.0, 'left' => 39.0, 'x' => 39.0, 'y' => 34.0], 107 => ['top' => 34.0, 'left' => 60.2, 'x' => 60.2, 'y' => 34.0], 108 => ['top' => 33.5, 'left' => 73.2, 'x' => 73.2, 'y' => 33.5], 109 => ['top' => 22.5, 'left' => 55.0, 'x' => 55.0, 'y' => 22.5], 110 => ['top' => 29.0, 'left' => 84.5, 'x' => 84.5, 'y' => 29.0], 111 => ['top' => 47.0, 'left' => 85.5, 'x' => 85.5, 'y' => 47.0], 'xishui_1' => ['top' => 47.5, 'left' => 26.4, 'x' => 26.4, 'y' => 47.5], 'xishui_2' => ['top' => 48.0, 'left' => 39.6, 'x' => 39.6, 'y' => 48.0], 'xishui_3' => ['top' => 48.0, 'left' => 60.4, 'x' => 60.4, 'y' => 48.0], 'xishui_4' => ['top' => 47.5, 'left' => 73.7, 'x' => 73.7, 'y' => 47.5], 'xishui_5' => ['top' => 33.5, 'left' => 27.0, 'x' => 27.0, 'y' => 33.5], 'xishui_6' => ['top' => 34.0, 'left' => 39.0, 'x' => 39.0, 'y' => 34.0], 'xishui_7' => ['top' => 34.0, 'left' => 60.2, 'x' => 60.2, 'y' => 34.0], 'xishui_8' => ['top' => 33.5, 'left' => 73.2, 'x' => 73.2, 'y' => 33.5], 'xishui_9' => ['top' => 22.5, 'left' => 55.0, 'x' => 55.0, 'y' => 22.5], 'xishui_10' => ['top' => 29.0, 'left' => 84.5, 'x' => 84.5, 'y' => 29.0], 'xishui_11' => ['top' => 47.0, 'left' => 85.5, 'x' => 85.5, 'y' => 47.0], ]; } $rawCenter = [ // 7 座立式储油罐 (含高位激光引线 stemY 错层防遮挡) 14 => ['top' => 12.8, 'left' => 4.8, 'stemX' => 2.8, 'stemY' => 20.3], 18 => ['top' => 18.5, 'left' => 6.5, 'stemY' => 21.0], 17 => ['top' => 9.2, 'left' => 9.6, 'stemY' => 18.4], 12 => ['top' => 15.8, 'left' => 10.5, 'stemY' => 22.0], 16 => ['top' => 12.2, 'left' => 13.7, 'stemY' => 22.4], 10 => ['top' => 16.0, 'left' => 16.9, 'stemY' => 23.1], 15 => ['top' => 13.0, 'left' => 19.8, 'stemY' => 19.8], // 14 栋粮食平房仓 44 => ['top' => 18.7, 'left' => 45.1], 43 => ['top' => 33.5, 'left' => 44.0], 35 => ['top' => 23.8, 'left' => 38.5], 42 => ['top' => 29.9, 'left' => 52.1], 36 => ['top' => 28.0, 'left' => 33.8], 41 => ['top' => 35.0, 'left' => 65.9], 33 => ['top' => 34.5, 'left' => 29.7], 37 => ['top' => 41.0, 'left' => 40.0], 38 => ['top' => 42.0, 'left' => 59.0], 40 => ['top' => 41.0, 'left' => 80.6], 39 => ['top' => 49.5, 'left' => 75.8], 32 => ['top' => 51.3, 'left' => 56.3], 31 => ['top' => 60.2, 'left' => 73.2], 30 => ['top' => 61.8, 'left' => 50.5], ]; $result = []; foreach ($rawCenter as $k => $c) { $row = [ 'top' => $c['top'], 'left' => $c['left'], 'x' => $c['left'], 'y' => $c['top'] ]; if (isset($c['stemX'])) $row['stemX'] = $c['stemX']; if (isset($c['stemY'])) $row['stemY'] = $c['stemY']; $result[$k] = $row; } return $result; } }