From 28f9ee3e765ce88426df4b745777c0cda406c013 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Wed, 9 Jul 2025 16:37:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ContentLibraryController.php | 197 +++++++++++++++++- 1 file changed, 195 insertions(+), 2 deletions(-) diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 21389fc4..d3b8b1f0 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -762,7 +762,8 @@ class ContentLibraryController extends Controller // 查询条件:未删除且已开启的内容库 $where = [ ['isDel', '=', 0], // 未删除 - ['status', '=', 1] // 已开启 + ['status', '=', 1], // 已开启 + ['id', '=', 27] ]; // 查询符合条件的内容库 @@ -1411,6 +1412,35 @@ class ContentLibraryController extends Controller }elseif ($moment['type'] == 3){ //链接 $contentType = 2; + $urls = []; + $url = is_string($moment['urls']) ? json_decode($moment['urls'], true) : $moment['urls'] ?? []; + $url = $url[0]; + if(strpos($url, 'feishu.cn') !== false){ + $urls[] = [ + 'url' => $url, + 'image' => 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/3db2a5d7fe49011ab68175a42a5094ce.jpeg', + 'desc' => '点击查看详情' + ]; + }else{ + $urlInfo = $this->parseUrl($url); + if (!empty($urlInfo)) { + $urls[] = [ + 'url' => $url, + 'image' => $urlInfo['icon'], + 'desc' => $urlInfo['title'] + ]; + } else { + // 解析失败的处理 + $urls[] = [ + 'url' => $url, + 'image' => 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/ec039d96fad6eab1d960f207d3d9ca9f.jpeg', + 'desc' => '点击查看详情' + ]; + } + } + $moment['urls'] = $urls; + + }elseif ($moment['type'] == 15){ //视频 $contentType = 3; @@ -1727,4 +1757,167 @@ class ContentLibraryController extends Controller return []; } } -} \ No newline at end of file + + + + + /** + * 解析URL获取网页信息(内部调用) + * @param string $url 要解析的URL + * @return array 包含title、icon的数组,失败返回空数组 + */ + public function parseUrl($url) + { + if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) { + return []; + } + + try { + // 设置请求头,模拟浏览器访问 + $context = stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'header' => [ + 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding: gzip, deflate', + 'Connection: keep-alive', + 'Upgrade-Insecure-Requests: 1' + ], + 'timeout' => 10, + 'follow_location' => true, + 'max_redirects' => 3 + ] + ]); + + // 获取网页内容 + $html = @file_get_contents($url, false, $context); + + if ($html === false) { + return []; + } + + // 检测编码并转换为UTF-8 + $encoding = mb_detect_encoding($html, ['UTF-8', 'GBK', 'GB2312', 'BIG5', 'ASCII']); + if ($encoding && $encoding !== 'UTF-8') { + $html = mb_convert_encoding($html, 'UTF-8', $encoding); + } + + // 解析HTML + $dom = new \DOMDocument(); + @$dom->loadHTML($html, LIBXML_NOERROR | LIBXML_NOWARNING); + $xpath = new \DOMXPath($dom); + + $result = [ + 'title' => '', + 'icon' => '', + 'url' => $url + ]; + + // 提取标题 + $titleNodes = $xpath->query('//title'); + if ($titleNodes->length > 0) { + $result['title'] = trim($titleNodes->item(0)->textContent); + } + + // 提取图标 - 优先获取favicon + $iconNodes = $xpath->query('//link[@rel="icon"]/@href | //link[@rel="shortcut icon"]/@href | //link[@rel="apple-touch-icon"]/@href'); + if ($iconNodes->length > 0) { + $iconUrl = trim($iconNodes->item(0)->value); + $result['icon'] = $this->makeAbsoluteUrl($iconUrl, $url); + } else { + // 尝试获取Open Graph图片 + $ogImageNodes = $xpath->query('//meta[@property="og:image"]/@content'); + if ($ogImageNodes->length > 0) { + $result['icon'] = trim($ogImageNodes->item(0)->value); + } else { + // 默认favicon路径 + $result['icon'] = $this->makeAbsoluteUrl('/favicon.ico', $url); + } + } + + // 清理和验证数据 + $result['title'] = $this->cleanText($result['title']); + + return $result; + + } catch (\Exception $e) { + // 记录错误日志但不抛出异常 + \think\facade\Log::error('URL解析失败: ' . $e->getMessage() . ' URL: ' . $url); + return []; + } + } + + + + + + /** + * 将相对URL转换为绝对URL + * @param string $relativeUrl 相对URL + * @param string $baseUrl 基础URL + * @return string 绝对URL + */ + private function makeAbsoluteUrl($relativeUrl, $baseUrl) + { + if (empty($relativeUrl)) { + return ''; + } + + // 如果已经是绝对URL,直接返回 + if (filter_var($relativeUrl, FILTER_VALIDATE_URL)) { + return $relativeUrl; + } + + // 解析基础URL + $baseParts = parse_url($baseUrl); + if (!$baseParts) { + return $relativeUrl; + } + + // 处理以/开头的绝对路径 + if (strpos($relativeUrl, '/') === 0) { + return $baseParts['scheme'] . '://' . $baseParts['host'] . + (isset($baseParts['port']) ? ':' . $baseParts['port'] : '') . + $relativeUrl; + } + + // 处理相对路径 + $basePath = isset($baseParts['path']) ? dirname($baseParts['path']) : '/'; + if ($basePath === '.') { + $basePath = '/'; + } + + return $baseParts['scheme'] . '://' . $baseParts['host'] . + (isset($baseParts['port']) ? ':' . $baseParts['port'] : '') . + $basePath . '/' . $relativeUrl; + } + + /** + * 清理文本内容 + * @param string $text 要清理的文本 + * @return string 清理后的文本 + */ + private function cleanText($text) + { + if (empty($text)) { + return ''; + } + + // 移除HTML实体 + $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + // 移除多余的空白字符 + $text = preg_replace('/\s+/', ' ', $text); + + // 移除控制字符 + $text = preg_replace('/[\x00-\x1F\x7F]/', '', $text); + + return trim($text); + } + + + + +} \ No newline at end of file