cms_model = new CmsModel; } public function index() { if ($this->cmsConfig['site_searchtype'] == 'xunsearch') { $info = get_addon_info('xunsearch'); if (!$info || $info['status'] != 1) { return $this->error('请在后台插件管理中安装《迅搜搜索》并启用后再尝试'); } return $this->xunsearch(); } if ($this->cmsConfig['site_searchtype'] == 'meilisearch') { $info = get_addon_info('meilisearch'); if (!$info || $info['status'] != 1) { return $this->error('请在后台插件管理中安装《Meilisearch》并启用后再尝试'); } return $this->meilisearch(); } $seo = seo('', cms_t('site_search', '站内搜索')); $modelid = $this->request->param('modelid/d', 0); $q = $this->request->param('q/s', '', 'trim,safe_replace,strip_tags,htmlspecialchars'); $q = str_replace('%', '', $q); $time = $this->request->param('time/s', ''); $scope = $this->request->param('scope/s', 'site'); $tab = $this->request->param('tab/s', ''); try { $this->validate([ 'q' => $q, ], [ 'q|标题关键词' => 'chsDash|max:25', ]); } catch (ValidateException $e) { $this->error($e->getMessage()); } $begin = microtime(true); if ($time == 'day') { $search_time = time() - 86400; $sql_time = ' AND publish_time > ' . $search_time; } elseif ($time == 'week') { $search_time = time() - 604800; $sql_time = ' AND publish_time > ' . $search_time; } elseif ($time == 'month') { $search_time = time() - 2592000; $sql_time = ' AND publish_time > ' . $search_time; } elseif ($time == 'year') { $search_time = time() - 31536000; $sql_time = ' AND publish_time > ' . $search_time; } else { $search_time = 0; $sql_time = ''; } $shistory = session('shistory'); if (!$shistory) { $shistory = []; } if (!empty($q)) { array_unshift($shistory, $q); $shistory = array_slice(array_unique(array_filter($shistory)), 0, 10); session('shistory', $shistory); } $modellist = Models::where('status', 1)->where('module', 'cms')->column('*', 'id'); if (!$modellist) { return $this->error('没有可搜索模型~'); } $newsModelIds = [1]; $productModelIds = [2]; $helpModelIds = [9]; $tabModelMap = [ 'product' => $productModelIds, 'news' => $newsModelIds, 'help' => $helpModelIds, ]; $isSupportSearch = $scope === 'support_faq'; $defaultTab = in_array($tab, ['product', 'news', 'help'], true) ? $tab : ($isSupportSearch ? 'help' : 'product'); $allowedModelIds = array_merge($newsModelIds, $productModelIds, $helpModelIds); $currentLang = function_exists('cms_current_lang') ? (string)cms_current_lang() : ''; $currentPage = max(1, (int)$this->request->param('page/d', 1)); $perPage = 10; $pages = ''; $simplePages = []; $groupedResults = [ 'product' => [], 'news' => [], 'help' => [], ]; $groupCounts = [ 'product' => 0, 'news' => 0, 'help' => 0, ]; $buildSearchWhere = function ($modelKey, $modelMeta) use ($q, $currentLang, $sql_time) { $searchField = Db::name('cms_field')->where('modelid', $modelKey)->where('ifsystem', 1)->where('ifsearch', 1)->column('name'); $tableName = $modelMeta['tablename'] ?? ''; $extMatchedIds = []; $hasLangExtTable = false; if (!empty($tableName)) { $extTable = $tableName . '_data'; try { $extFields = array_map('strtolower', array_keys(Db::name($extTable)->getFields())); if (in_array('did', $extFields, true) && in_array('lang', $extFields, true) && !empty($currentLang)) { $hasLangExtTable = true; $extSearchFields = array_values(array_intersect($searchField ?: [], $extFields)); if (!in_array('title', $extSearchFields, true) && in_array('title', $extFields, true)) { $extSearchFields[] = 'title'; } $extSearchFields = array_unique(array_filter($extSearchFields)); if (!empty($extSearchFields)) { $dataWhereParts = []; foreach ($extSearchFields as $fieldName) { $dataWhereParts[] = "$fieldName like '%$q%'"; } if (!empty($dataWhereParts)) { $dataWhere = '(' . implode(' OR ', $dataWhereParts) . ") AND lang='" . addslashes($currentLang) . "'"; $extMatchedIds = Db::name($extTable)->whereRaw($dataWhere)->column('did'); $extMatchedIds = array_map('intval', array_filter((array)$extMatchedIds)); } } } } catch (\Throwable $e) { } } $whereParts = []; if ($hasLangExtTable && !empty($currentLang)) { if (!empty($extMatchedIds)) { $whereParts[] = 'id in (' . implode(',', $extMatchedIds) . ')'; } } else { foreach ($searchField as $fieldName) { $whereParts[] = "$fieldName like '%$q%'"; } if (!empty($extMatchedIds)) { $whereParts[] = 'id in (' . implode(',', $extMatchedIds) . ')'; } } if (empty($whereParts)) { return ''; } $where = '(' . implode(' OR ', $whereParts) . ')'; $where .= " AND status='1' $sql_time"; return $where; }; if ($modelid) { if (!array_key_exists($modelid, $modellist) || !in_array((int)$modelid, $allowedModelIds, true)) { $this->error('模型错误~'); } $where = $buildSearchWhere($modelid, $modellist[$modelid]); if ($where === '') { $this->error('没有设置搜索字段~'); } $list = $this->cms_model->getList($modelid, $where, true, '*', 'listorder DESC,id DESC', $perPage, true, false, ['strict_lang' => true]); if (method_exists($list, 'items')) { $items = $list->items(); foreach ($items as &$item) { if (!isset($item['modelid'])) { $item['modelid'] = (int)$modelid; } } unset($item); } $count = $list->total(); $pages = $list->render(); } else { foreach ($tabModelMap as $tabKey => $tabModelIds) { foreach ($tabModelIds as $tabModelId) { if (!array_key_exists($tabModelId, $modellist) || !in_array((int)$tabModelId, $allowedModelIds, true)) { continue; } $where = $buildSearchWhere($tabModelId, $modellist[$tabModelId]); if ($where === '') { continue; } $groupCounts[$tabKey] += (int)Db::name($modellist[$tabModelId]['tablename'])->whereRaw($where)->count(); } } $activeModelIds = $tabModelMap[$defaultTab] ?? []; $activeModelId = 0; foreach ($activeModelIds as $candidateModelId) { if (array_key_exists($candidateModelId, $modellist) && in_array((int)$candidateModelId, $allowedModelIds, true)) { $activeModelId = (int)$candidateModelId; break; } } if ($activeModelId > 0) { $activeWhere = $buildSearchWhere($activeModelId, $modellist[$activeModelId]); if ($activeWhere !== '') { $list = $this->cms_model->getList($activeModelId, $activeWhere, true, '*', 'listorder DESC,id DESC', $perPage, true, false, ['strict_lang' => true]); if (method_exists($list, 'items')) { $items = $list->items(); foreach ($items as &$item) { if (!isset($item['modelid'])) { $item['modelid'] = (int)$activeModelId; } } unset($item); } $count = $groupCounts[$defaultTab] ?? (method_exists($list, 'total') ? $list->total() : 0); $pages = $list->render(); } else { $list = collect([]); $count = 0; } } else { $list = collect([]); $count = 0; } $sourceItems = method_exists($list, 'all') ? $list->all() : (is_array($list) ? $list : []); $groupedResults[$defaultTab] = $sourceItems; } if ($modelid) { $sourceItems = method_exists($list, 'all') ? $list->all() : (is_array($list) ? $list : []); foreach ($sourceItems as $item) { $itemModelId = (int)($item['modelid'] ?? 0); if (in_array($itemModelId, $productModelIds, true)) { $groupedResults['product'][] = $item; } elseif (in_array($itemModelId, $newsModelIds, true)) { $groupedResults['news'][] = $item; } elseif (in_array($itemModelId, $helpModelIds, true)) { $groupedResults['help'][] = $item; } } $groupCounts = [ 'product' => count($groupedResults['product']), 'news' => count($groupedResults['news']), 'help' => count($groupedResults['help']), ]; } $end = microtime(true); $this->assign([ 'time' => $time, 'modelid' => $modelid, 'q' => $q, 'scope' => $scope, 'tab' => $tab, 'shistory' => $shistory, 'SEO' => $seo, 'list' => $list, 'count' => $count, 'modellist' => $modellist, 'search_time' => number_format(($end - $begin), 6), 'pages' => $pages, 'simplePages' => isset($simplePages) ? $simplePages : [], 'isSupportSearch' => $isSupportSearch, 'defaultTab' => $defaultTab, 'groupedResults' => $groupedResults, 'groupCounts' => $groupCounts, ]); if (!empty($q)) { return $this->fetch('/search_result'); } return $this->fetch('/search'); } public function xunsearch() { $seo = seo('', cms_t('site_search', '站内搜索')); $modelid = $this->request->param('modelid/d', 0); $q = $this->request->param('q/s', '', 'trim,safe_replace,strip_tags,htmlspecialchars'); $q = str_replace('%', '', $q); $time = $this->request->param('time/s', ''); $page = $this->request->get('page/d', 1); $pagesize = 5; $order = $this->request->get('order', ''); $fulltext = $this->request->get('fulltext/d', '1'); $fuzzy = $this->request->get('fuzzy/d', '0'); $synonyms = $this->request->get('synonyms/d', '0'); try { $this->validate([ 'q' => $q, ], [ 'q|标题关键词' => 'max:25', ]); } catch (ValidateException $e) { $this->error($e->getMessage()); } $search = FulltextSearch::setQuery($q, $fulltext, $fuzzy, $synonyms); if ($modelid > 0) { $search->addQueryString("modelid:({$modelid})"); } if ($time == 'day') { $search_time = time() - 86400; $search->addRange('publish_time', $search_time, time()); } elseif ($time == 'week') { $search_time = time() - 604800; $search->addRange('publish_time', $search_time, time()); } elseif ($time == 'month') { $search_time = time() - 2592000; $search->addRange('publish_time', $search_time, time()); } elseif ($time == 'year') { $search_time = time() - 31536000; $search->addRange('publish_time', $search_time, time()); } $modellist = Models::where('status', 1)->where('module', 'cms')->select()->toArray(); if (!$modellist) { return $this->error('没有可搜索模型~'); } $query = ['q' => $q, 'modelid' => $modelid]; $result = FulltextSearch::search($page, $pagesize, $order, $query); $hot = FulltextSearch::hot(); $this->assign([ 'time' => $time, 'modelid' => $modelid, 'q' => $q, 'SEO' => $seo, 'list' => $result['list'], 'count' => $result['count'], 'total' => $result['total'], 'search_time' => $result['search_time'], 'pages' => $result['list'] ? $result['list']->render() : '', 'search' => $result['search'], 'corrected' => $result['corrected'], 'related' => $result['related'], 'hot' => $hot, 'modellist' => $modellist, ]); if (!empty($q)) { return $this->fetch('/xunsearch_result'); } return $this->fetch('/search'); } public function meilisearch() { $seo = seo('', cms_t('site_search', '站内搜索')); $modelid = $this->request->param('modelid/d', 0); $q = $this->request->param('q/s', '', 'trim,safe_replace,strip_tags,htmlspecialchars'); $q = str_replace('%', '', $q); $time = $this->request->param('time/s', ''); $page = $this->request->get('page/d', 1); $pagesize = 5; $sort = $this->request->get('sort/s', ''); $order = $this->request->get('order/s', 'desc'); try { $this->validate([ 'q' => $q, ], [ 'q|标题关键词' => 'max:25', ]); } catch (ValidateException $e) { $this->error($e->getMessage()); } $query = $pagequery = ['q' => $q]; $modellist = Models::where('status', 1)->where('module', 'cms')->column('*', 'id'); if (!$modellist) { return $this->error('没有可搜索模型~'); } if ($modelid > 0) { $pagequery['modelid'] = $modelid; if (isset($query['filter'])) { $query['filter'] .= " AND modelid = {$modelid}"; } else { $query['filter'] = "modelid = {$modelid}"; } } if ($time) { $timeRanges = [ 'day' => time() - 86400, 'week' => time() - 604800, 'month' => time() - 2592000, 'year' => time() - 31536000, ]; $pagequery['time'] = $time; if (isset($timeRanges[$time])) { $search_time = $timeRanges[$time]; if (isset($query['filter'])) { $query['filter'] .= " AND publish_time >= {$search_time}"; } else { $query['filter'] = "publish_time >= {$search_time}"; } } } if ($sort) { $pagequery['sort'] = $sort; $pagequery['order'] = $order; } $query['attributesToHighlight'] = ['title', 'content']; $result = MeiliSearch::search($page, $pagesize, "{$sort},{$order}", $query, $pagequery); $this->assign([ 'SEO' => $seo, 'q' => $q, 'modelid' => $modelid, 'time' => $time, 'count' => $result['count'], 'search_time' => $result['search_time'], 'list' => $result['list'], 'pages' => $result['list'] ? $result['list']->render() : '', 'modellist' => $modellist, 'sort' => $sort, 'order' => $order, ]); if (!empty($q)) { return $this->fetch('/meilisearch_result'); } return $this->fetch('/search'); } }