request->isAjax()) return $this->fetch(); $gid = $this->request->get('gid/d', 0); $page = max(1, $this->request->get('page/d', 1)); $query = $this->scopeRecords(Db::name('grain_forecast')); if ($gid) $query->where('gid', $gid); $total = $query->count(); $query = $this->scopeRecords(Db::name('grain_forecast')); if ($gid) $query->where('gid', $gid); $list = $query->field('request_key', true)->order('id DESC')->page($page, 15)->select(); $points = $list ? Db::name('grain_forecast_point')->where('forecast_id', 'in', array_column($list, 'id'))->select() : []; foreach ($list as &$row) { $row['measured'] = 0; $row['point_count'] = 0; foreach ($points as $point) { if ($point['forecast_id'] != $row['id']) continue; $row['point_count']++; $actual = json_decode($point['actual'], true) ?: []; $filled = count(array_filter($actual, function ($v) { return $v !== null && $v !== ''; })); if ($filled === count(GrainForecast::metrics($row['grain_type']))) $row['measured']++; } } unset($row); $granaries = array_values(array_filter(GranarySite::granaries($this->filterSites), function ($g) { return in_array($g['varieties'], ['小麦', '稻谷'], true); })); if (!empty($granaries)) { $gids = array_column($granaries, 'id'); $envRecords = Db::name('grain_forecast')->where('gid', 'in', $gids) ->field('gid,tm_i,hm_i,tm_o,hm_o,observed_date')->order('id DESC')->select(); $envMap = []; foreach ($envRecords as $rec) { if (!isset($envMap[$rec['gid']])) { $envMap[$rec['gid']] = [ 'tm_i' => (float)$rec['tm_i'], 'hm_i' => (float)$rec['hm_i'], 'tm_o' => (float)$rec['tm_o'], 'hm_o' => (float)$rec['hm_o'], 'observed_date' => $rec['observed_date'] ]; } } foreach ($granaries as &$g) { $g['last_env'] = isset($envMap[$g['id']]) ? $envMap[$g['id']] : null; } unset($g); } return json(['code' => 200, 'list' => $list, 'total' => $total, 'granaries' => $granaries]); } public function detail() { try { return json(['code' => 200, 'data' => (new GrainForecast())->detail($this->request->get('id/d', 0))]); } catch (\InvalidArgumentException $e) { return json(['code' => 400, 'msg' => $e->getMessage()]); } } public function add() { return $this->write(function ($service) { $id = $service->create($this->request->post(), $this->auth->id); $service->generate($id); return $id; }); } public function edit($ids = null) { return $this->write(function ($service) use ($ids) { $id = $this->request->post('id/d', $ids ?: 0); $id = $service->update($id, $this->request->post(), $this->auth->id); $service->generate($id); return $id; }); } public function dell($ids = null) { if (!$this->request->isPost()) return json(['code' => 405, 'msg' => '请使用POST提交']); $id = $this->request->post('id', $ids ?: $this->request->get('id')); if (empty($id)) return json(['code' => 400, 'msg' => '请指定要删除的记录编号']); try { $service = new GrainForecast(); $service->delete($id); return json(['code' => 200, 'msg' => '删除成功']); } catch (\InvalidArgumentException $e) { return json(['code' => 400, 'msg' => $e->getMessage()]); } catch (\Exception $e) { \think\Log::record('Grain forecast delete: ' . $e->getMessage(), 'error'); return json(['code' => 500, 'msg' => '删除失败,请刷新后重试']); } } public function del($ids = null) { return $this->dell($ids); } public function retry() { return $this->write(function ($service) { $id = $this->request->post('id/d', 0); $service->generate($id); return $id; }); } public function actual() { return $this->write(function ($service) { return $service->saveActual($this->request->post(), $this->auth->id); }); } protected function write($action) { if (!$this->request->isPost()) return json(['code' => 405, 'msg' => '请使用POST提交']); try { $service = new GrainForecast(); $id = $action($service); return json(['code' => 200, 'msg' => '保存成功', 'data' => $service->detail($id)]); } catch (\InvalidArgumentException $e) { return json(['code' => 400, 'msg' => $e->getMessage()]); } catch (\Exception $e) { \think\Log::record('Grain forecast: ' . $e->getMessage(), 'error'); return json(['code' => 500, 'msg' => '保存失败,请刷新查看记录后重试']); } } }