requestNewsList($page, $size); if (!empty($news_list) && isset($news_list['code']) && $news_list['code'] == 1) { $data = $this->normalizeNewsList(isset($news_list['data']) ? $news_list['data'] : []); $count = isset($news_list['count']) ? intval($news_list['count']) : count($data); } else { $data = []; $count = 0; } View::assign('data', $data); View::assign('count', $count); View::assign('page', $page); View::assign('size', $size); $this->assignSeo([ 'title' => $page > 1 ? 'EVUS与美国签证新闻资讯 - 第' . $page . '页' : 'EVUS与美国签证新闻资讯', 'canonical_path' => '/home/news/index', 'canonical_query_keys' => ['page'], ]); return View::fetch(); } public function detail() { $id = Request::instance()->param('id'); if ( !is_scalar($id) || filter_var((string) $id, FILTER_VALIDATE_INT, [ 'options' => ['min_range' => 1], ]) === false ) { abort(404, '新闻不存在'); } $id = (int) $id; $info = $this->requestNewsDetail($id); if ($info === null) { abort(503, '新闻服务暂时不可用'); } if (empty($info) || !isset($info['code']) || $info['code'] != 1 || empty($info['data'])) { abort(404, '新闻不存在'); } $info_detail = $this->normalizeNewsItem($info['data']); $latest = $this->requestNewsList(1, 50); $latest_data = []; if (!empty($latest) && isset($latest['code']) && $latest['code'] == 1) { $latest_data = $this->normalizeNewsList(isset($latest['data']) ? $latest['data'] : [], true); } $nav = $this->resolveArticleNav($id, $latest_data); $article = $this->filterRelatedArticles($id, $latest_data, 8); View::assign('data', $info_detail); View::assign('last', $nav['last']); View::assign('next', $nav['next']); View::assign('article', $article); $seoService = new SeoMetaService(); $title = $seoService->descriptionFromHtml((string) $info_detail['title'], 60); $description = $seoService->descriptionFromHtml( (string) $info_detail['contents'] ); $seo = [ 'canonical_path' => '/home/news/detail', 'canonical_query_keys' => ['id'], ]; if ($title !== '') { $seo['title'] = $title; } if ($description !== '') { $seo['description'] = $description; } $this->assignSeo($seo); return View::fetch(); } private function requestNewsList($page, $size) { $response = Httpcurl::request(NEWS_LIST, 'post', [ 'model' => 'article', 'source_code' => DOMAIN, 'page' => $page, 'size' => $size, ]); return $this->decodeApiResponse($response, 'news list'); } private function requestNewsDetail($id) { $response = Httpcurl::request(NEWS_DETAIL, 'post', [ 'model' => 'article', 'id' => $id, ]); return $this->decodeApiResponse($response, 'news detail'); } private function decodeApiResponse($response, $scene) { if (!is_array($response) || !isset($response[0]) || !empty($response[3])) { Log::error($scene . ' api request failed: ' . json_encode($response)); return null; } $status_code = intval(isset($response[2]['http_code']) ? $response[2]['http_code'] : 0); if ($status_code < 200 || $status_code >= 300) { Log::error($scene . ' api returned HTTP status: ' . $status_code); return null; } $result = json_decode($response[0], true); Log::info(json_encode($result)); return is_array($result) ? $result : null; } private function normalizeNewsList($list, $short_date = false) { if (!is_array($list)) { return []; } $data = []; foreach ($list as $item) { $item = $this->normalizeNewsItem($item); if ($short_date) { $item['create_time'] = $this->formatDate($item['create_time']); } $data[] = $item; } return $data; } private function normalizeNewsItem($item) { if (!is_array($item)) { return []; } $item['id'] = isset($item['id']) ? $item['id'] : 0; $item['title'] = isset($item['title']) ? $item['title'] : ''; $contents = isset($item['contents']) ? $item['contents'] : (isset($item['content']) ? $item['content'] : ''); $item['contents'] = is_scalar($contents) ? str_replace('https://www.evus.gov/', '', (string) $contents) : ''; $item['create_time'] = isset($item['create_time']) ? $item['create_time'] : ''; return $item; } private function resolveArticleNav($id, $list) { $id = intval($id); $last = []; $next = []; foreach ($list as $item) { $item_id = intval(isset($item['id']) ? $item['id'] : 0); if ($item_id <= 0 || $item_id == $id) { continue; } if ($item_id < $id && (empty($last) || $item_id > intval($last['id']))) { $last = $item; } if ($item_id > $id && (empty($next) || $item_id < intval($next['id']))) { $next = $item; } } return ['last' => $last, 'next' => $next]; } private function filterRelatedArticles($id, $list, $limit) { $data = []; $id = intval($id); foreach ($list as $item) { if (intval($item['id']) == $id) { continue; } $data[] = $item; if (count($data) >= $limit) { break; } } return $data; } private function formatDate($date) { if (empty($date)) { return ''; } $timestamp = strtotime($date); return $timestamp ? date('Y-m-d', $timestamp) : $date; } }