Browse Source

feat(search): 搜索页面更新

master
peijunlei 2 weeks ago
parent
commit
c5563c50db
  1. 285
      app/controller/frontend/SearchController.php
  2. 64
      public/themes/dist_static/static/css/search.css
  3. 71
      public/themes/dist_static/static/js/search.js
  4. 2
      public/themes/website/1/zh/demo/download.html
  5. 136
      public/themes/website/1/zh/demo/single_search.html

285
app/controller/frontend/SearchController.php

@ -4,40 +4,132 @@
namespace app\controller\frontend; namespace app\controller\frontend;
use app\exception\ModelEmptyException;
use app\exception\ModelException;
use app\model\Category; use app\model\Category;
use app\model\CategorySubContent; use app\model\CategorySubContent;
use app\model\SubContent; use app\model\SubContent;
use app\model\SysSetting; use app\model\SysSetting;
use app\service\ContentService;
use app\validate\ContentValidate;
use think\exception\ValidateException;
use think\facade\Db;
class SearchController extends BaseController class SearchController extends BaseController
{ {
/** 产品根栏目 */
private const PRODUCT_CATE_ID = 333;
/** 新闻根栏目 */
private const NEWS_CATE_ID = 361;
// 下载中心
private const DOWNLOAD_CATE_ID = 356;
/** 常见问题根栏目 */
private const FAQ_CATE_ID = 357;
// 视频教程
private const VIDEO_CATE_ID = 358;
//产品公告
private const ANNOUNCEMENT_CATE_ID = 359;
/** /**
* 按栏目标题映射搜索 Tab 类型
* 获取栏目自身及全部子栏目 ID
*/ */
private function resolveSearchType(string $title): string
private function getCategoryTreeIds(int $rootId): array
{ {
if ($title === '') {
return 'other';
$category = new Category();
$root = $category->where([
'id' => $rootId,
'seller_id' => $this->sellerId,
'website_id' => $this->siteId,
])->find();
if (empty($root)) {
return [$rootId];
} }
if (mb_strpos($title, '产品') !== false) {
return 'product';
$root = $root->toArray();
$parentPath = ($root['path'] ?? '') . $root['id'] . '-';
$childIds = $category->where([
['seller_id', '=', $this->sellerId],
['website_id', '=', $this->siteId],
['path', 'like', $parentPath . '%'],
])->column('id');
return array_values(array_unique(array_merge(
[(int)$root['id']],
array_map('intval', $childIds ?: [])
)));
}
/**
* 按栏目 ID 取关联内容 ID
*/
private function getContentIdsByCategoryIds(array $cateIds): array
{
if (empty($cateIds)) {
return [];
} }
if (mb_strpos($title, '解决方案') !== false || mb_strpos($title, '方案') !== false) {
return 'solution';
$cateSub = new CategorySubContent();
$ids = $cateSub->where([
['seller_id', '=', $this->siteId],
['category_id', 'in', $cateIds],
])->column('sub_content_id');
return array_values(array_unique(array_map('intval', $ids ?: [])));
}
/**
* 关键词命中的内容 ID
*/
private function getMatchedContentIds(array $subIds, string $keywords, bool $hasKeyword): array
{
$query = (new SubContent())->where([
'seller_id' => $this->sellerId,
'is_del' => 1,
])->whereIn('id', $subIds ?: [0]);
if ($hasKeyword) {
$query = $query->whereLike('title|description|sub_title', '%' . $keywords . '%');
} }
if (mb_strpos($title, '新闻') !== false) {
return 'news';
$ids = $query->column('id');
return array_map('intval', $ids ?: []);
}
/**
* 统一格式化为 Y-m-d
*/
private function formatSearchDate($time): string
{
if ($time === null || $time === '') {
return '';
} }
if (mb_strpos($title, '常见问题') !== false || mb_stripos($title, 'FAQ') !== false || mb_strpos($title, '问题') !== false) {
return 'faq';
if (is_numeric($time)) {
return date('Y-m-d', (int)$time);
} }
return 'other';
$ts = strtotime((string)$time);
return $ts ? date('Y-m-d', $ts) : substr((string)$time, 0, 10);
}
/**
* 解析搜索结果类型
*/
private function resolveSearchKind(int $contentId, array $sets): array
{
if (isset($sets['product'][$contentId])) {
return ['product', '产品'];
}
if (isset($sets['news'][$contentId])) {
return ['news', '新闻'];
}
if (isset($sets['faq'][$contentId])) {
return ['faq', '常见问题'];
}
if (isset($sets['download'][$contentId])) {
return ['download', '下载中心'];
}
if (isset($sets['video'][$contentId])) {
return ['video', '视频'];
}
if (isset($sets['announce'][$contentId])) {
return ['announce', '公告'];
}
return ['content', '内容'];
} }
/** /**
@ -70,99 +162,120 @@ class SearchController extends BaseController
//搜索 //搜索
$param = $this->request->param(); $param = $this->request->param();
$keywords = $param['q'] ?? ''; $keywords = $param['q'] ?? '';
$hasKeyword = !empty($param['q']);
$type = $param['type'] ?? 'all'; $type = $param['type'] ?? 'all';
if (!in_array($type, ['all', 'product', 'solution', 'news', 'faq'], true)) {
if (!in_array($type, ['all', 'product', 'other', 'news', 'faq'], true)) {
$type = 'all'; $type = 'all';
} }
$this->assign('keywords', $keywords); $this->assign('keywords', $keywords);
$this->assign('sr_type', $type); $this->assign('sr_type', $type);
// 获取可以查询的栏目
$category = new Category();
$categories = $category -> getAllCustomArrayData(['is_search' => 1],'id desc','id')['data'];
// status: 1 正常 2 禁用
// $categories = $category -> getAllCustomArrayData(['status' => 1],'id desc','id')['data'];
// $categories = $category -> getAllCustomArrayData(['status' => 1],'id desc','id')['data'];
$cateIds = array_column($categories,'id');
$cateTypeMap = [];
foreach ($categories as $cate) {
$cateTypeMap[(int)$cate['id']] = $this->resolveSearchType((string)($cate['title'] ?? ''));
}
// 全部:可搜索栏目(is_search=1)
$categoryModel = new Category();
$searchCategories = $categoryModel->getAllCustomArrayData(['is_search' => 1], 'id desc', 'id')['data'];
$searchCateIds = array_column($searchCategories, 'id');
$cateSub = new CategorySubContent(); $cateSub = new CategorySubContent();
$cateSubWhere = [
['seller_id','=',$this->siteId],
['category_id','in',$cateIds]
];
$cateSubCon = $cateSub->getAllCategorySubContent($cateSubWhere)['data'];
$subIds = array_column($cateSubCon,'sub_content_id');
// 内容 -> 首个栏目(与列表展示 category[0] 一致)
$contentCateMap = [];
foreach ($cateSubCon as $row) {
$sid = (int)$row['sub_content_id'];
if (!isset($contentCateMap[$sid])) {
$contentCateMap[$sid] = (int)$row['category_id'];
}
}
$searchSubIds = array_column($cateSub->getAllCategorySubContent([
['seller_id', '=', $this->siteId],
['category_id', 'in', $searchCateIds ?: [0]],
])['data'], 'sub_content_id');
$SubContent = new SubContent();
$baseWhere = ['seller_id' => $this->sellerId, 'is_del' => 1];
// 各 Tab 固定根栏目(含子栏目)
$productContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::PRODUCT_CATE_ID));
$newsContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::NEWS_CATE_ID));
$faqContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::FAQ_CATE_ID));
// 关键词命中的全量 ID(用于 Tab 全量统计)
$countQuery = (new SubContent())->where($baseWhere)->whereIn('id', $subIds ?: [0]);
if (!empty($param['q'])) {
$countQuery = $countQuery->whereLike('title|description|sub_title', '%' . $keywords . '%');
}
$matchedIds = $countQuery->column('id');
// 其他 = 下载中心 + 视频 + 公告
$downloadContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::DOWNLOAD_CATE_ID));
$videoContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::VIDEO_CATE_ID));
$announceContentIds = $this->getContentIdsByCategoryIds($this->getCategoryTreeIds(self::ANNOUNCEMENT_CATE_ID));
$otherContentIds = array_values(array_unique(array_merge(
$downloadContentIds,
$videoContentIds,
$announceContentIds
)));
$allMatchedIds = $this->getMatchedContentIds($searchSubIds, $keywords, $hasKeyword);
$productMatchedIds = $this->getMatchedContentIds($productContentIds, $keywords, $hasKeyword);
$newsMatchedIds = $this->getMatchedContentIds($newsContentIds, $keywords, $hasKeyword);
$faqMatchedIds = $this->getMatchedContentIds($faqContentIds, $keywords, $hasKeyword);
$otherMatchedIds = $this->getMatchedContentIds($otherContentIds, $keywords, $hasKeyword);
$srCounts = [ $srCounts = [
'all' => count($matchedIds),
'product' => 0,
'solution' => 0,
'news' => 0,
'faq' => 0,
'all' => count($allMatchedIds),
'product' => count($productMatchedIds),
'other' => count($otherMatchedIds),
'news' => count($newsMatchedIds),
'faq' => count($faqMatchedIds),
]; ];
foreach ($matchedIds as $mid) {
$cid = $contentCateMap[(int)$mid] ?? 0;
$itemType = $cateTypeMap[$cid] ?? 'other';
if (isset($srCounts[$itemType])) {
$srCounts[$itemType]++;
}
}
$this->assign('sr_counts', $srCounts); $this->assign('sr_counts', $srCounts);
// 按 Tab 类型筛选列表用的内容 ID
$listSubIds = $matchedIds;
if ($type !== 'all') {
$listSubIds = [];
foreach ($matchedIds as $mid) {
$cid = $contentCateMap[(int)$mid] ?? 0;
if (($cateTypeMap[$cid] ?? 'other') === $type) {
$listSubIds[] = (int)$mid;
}
}
// 列表:全部不变;其余按对应栏目查
if ($type === 'product') {
$listSubIds = $productMatchedIds;
} elseif ($type === 'news') {
$listSubIds = $newsMatchedIds;
} elseif ($type === 'faq') {
$listSubIds = $faqMatchedIds;
} elseif ($type === 'other') {
$listSubIds = $otherMatchedIds;
} else {
$listSubIds = $allMatchedIds;
} }
$baseWhere = ['seller_id' => $this->sellerId, 'is_del' => 1];
$content = (new SubContent())->with(['thumbnail'=>function($q){ $content = (new SubContent())->with(['thumbnail'=>function($q){
$q->field('id,name,url,type'); $q->field('id,name,url,type');
},'category'])->where($baseWhere)->whereIn('id', $listSubIds ?: [0]); },'category'])->where($baseWhere)->whereIn('id', $listSubIds ?: [0]);
$param['siteId'] = $this->siteId;
$param['sellerId'] = $this->sellerId;
$productIdSet = array_flip($productContentIds);
$newsIdSet = array_flip($newsContentIds);
$faqIdSet = array_flip($faqContentIds);
$downloadIdSet = array_flip($downloadContentIds);
$videoIdSet = array_flip($videoContentIds);
$announceIdSet = array_flip($announceContentIds);
$kindSets = [
'product' => $productIdSet,
'news' => $newsIdSet,
'faq' => $faqIdSet,
'download' => $downloadIdSet,
'video' => $videoIdSet,
'announce' => $announceIdSet,
];
$tabKindMap = [
'product' => ['product', '产品'],
'news' => ['news', '新闻'],
'faq' => ['faq', '常见问题'],
];
$data = $content $data = $content
->order('id','desc') ->order('id','desc')
->paginate([ ->paginate([
'page' => $param['page'] ?? 1, 'page' => $param['page'] ?? 1,
'list_rows' => $param['limit'] ?? 10, 'list_rows' => $param['limit'] ?? 10,
])->each(function (&$item)use($param){
if(!empty($item['category'])) {
$item['category'] = $item->toArray()['category'];
$item['category_id'] = $item['category'][0]['id'];
])->each(function (&$item) use ($type, $tabKindMap, $kindSets) {
$row = $item->toArray();
if (!empty($row['category'])) {
$item['category'] = $row['category'];
$item['category_id'] = $row['category'][0]['id'] ?? 0;
}
$item['thumbnail'] = $row['thumbnail'] ?? null;
$item['url'] = $row['url'] ?? '';
$rawContent = $row['content'] ?? '';
// 与 ContentService / 常见问题页一致:先解码再交给模板 strip_tags
$item['content'] = $rawContent !== '' ? htmlspecialchars_decode((string)$rawContent) : '';
$item['sr_date'] = $this->formatSearchDate($row['publish_time'] ?? ($row['create_time'] ?? ''));
if (isset($tabKindMap[$type])) {
[$kind, $name] = $tabKindMap[$type];
} else {
[$kind, $name] = $this->resolveSearchKind((int)($row['id'] ?? 0), $kindSets);
if ($kind === 'content' && !empty($row['category'][0]['title'])) {
$name = $row['category'][0]['title'];
}
} }
$item['thumbnail'] = $item->toArray()['thumbnail'];
$item['sr_kind'] = $kind;
$item['sr_tab_name'] = $name;
}); });
$append = ['q' => $keywords]; $append = ['q' => $keywords];
if ($type !== 'all') { if ($type !== 'all') {

64
public/themes/dist_static/static/css/search.css

@ -231,6 +231,70 @@
color: var(--color-primary); color: var(--color-primary);
} }
/* 分类型:统一左右布局,仅叠加交互样式(视频播放与视频教程页一致) */
.sr-item--video .sr-item__media--video {
position: relative;
padding: 0;
border: 0;
background: transparent;
cursor: pointer;
overflow: hidden;
text-align: left;
appearance: none;
-webkit-appearance: none;
}
.sr-item--video .v-card__media {
width: 100%;
height: 100%;
aspect-ratio: auto;
border-radius: inherit;
}
.sr-item--video .v-card__cover {
object-fit: cover;
}
.sr-item--video .sr-item__media--video:hover .v-card__cover {
transform: scale(1.04);
}
.sr-item--video .sr-item__media--video:hover .v-card__play {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
.sr-item--video .v-card__play img,
.sr-item--video .sr-item__media:hover .v-card__play img {
width: 1rem;
height: auto;
margin-left: 0.125rem;
object-fit: contain;
transform: none;
}
.sr-item--faq .sr-item__faq {
margin: 0;
border-bottom: 0;
border-top: none;
}
.sr-item--faq .f-item__trigger {
padding-left: 0;
padding-right: 0;
}
.sr-item--faq .f-item__panel > .f-item__a {
min-height: 0;
}
.sr-item--faq .f-item.is-open .f-item__a {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
.sr-item__more--download img,
.sr-item__more--product .s-product-card__arrow {
display: block;
width: 1.25rem;
height: auto;
flex-shrink: 0;
}
.sr-item__more--download:hover,
.sr-item__more--product:hover {
color: var(--color-primary);
}
@media (max-width: 992px) { @media (max-width: 992px) {
.sr-page { .sr-page {
padding-top: calc(var(--header-h) + 32Px); padding-top: calc(var(--header-h) + 32Px);

71
public/themes/dist_static/static/js/search.js

@ -1,13 +1,74 @@
import "./common.js"; import "./common.js";
import "./pagination.js"; import "./pagination.js";
//#region js/search.js //#region js/search.js
function initHotTags() {
$(".sr-hot__tag").on("click", function() {
const keyword = ($(this).attr("data-keyword") || $(this).text() || "").trim();
if (!keyword) return;
const $form = $(".sr-search");
$form.find(".s-search__input").val(keyword);
const form = $form.get(0);
if (!form) return;
if (typeof form.requestSubmit === "function") form.requestSubmit();
else form.submit();
});
}
function initFaqAccordion() {
$(".sr-list .f-item__trigger").on("click", function() {
const $item = $(this).closest(".f-item");
const willOpen = !$item.hasClass("is-open");
$(".sr-list .f-item.is-open").not($item).removeClass("is-open").find(".f-item__trigger").attr("aria-expanded", "false");
$item.toggleClass("is-open", willOpen);
$(this).attr("aria-expanded", willOpen ? "true" : "false");
});
}
function initVideoModal() {
const modal = document.getElementById("v-modal");
const video = document.getElementById("v-modal-video");
const titleEl = document.getElementById("v-modal-title");
if (!modal || !video || !titleEl) return;
let lastFocus = null;
const openModal = (src, title) => {
if (!src) return;
lastFocus = document.activeElement;
titleEl.textContent = title || "视频播放";
if (video.getAttribute("src") !== src) video.src = src;
modal.hidden = false;
document.body.style.overflow = "hidden";
if (window.lenis?.stop) window.lenis.stop();
video.play().catch(() => {});
modal.querySelector(".v-modal__close")?.focus();
};
const closeModal = () => {
video.pause();
video.removeAttribute("src");
video.load();
modal.hidden = true;
document.body.style.overflow = "";
if (window.lenis?.start) window.lenis.start();
if (lastFocus && typeof lastFocus.focus === "function") lastFocus.focus();
};
document.querySelectorAll(".sr-item--video [data-video-src]").forEach((card) => {
card.addEventListener("click", () => {
const title =
card.closest(".sr-item")?.querySelector(".sr-item__title")?.textContent?.trim() ||
card.getAttribute("aria-label")?.replace(/^播放[::]/, "").trim() ||
"视频播放";
openModal(card.getAttribute("data-video-src") || "", title);
});
});
modal.querySelectorAll("[data-v-modal-close]").forEach((el) => {
el.addEventListener("click", closeModal);
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && !modal.hidden) closeModal();
});
}
$(function() { $(function() {
const q = new URLSearchParams(window.location.search).get("q")?.trim() || ""; const q = new URLSearchParams(window.location.search).get("q")?.trim() || "";
if (q) $(".sr-search .s-search__input").val(q); if (q) $(".sr-search .s-search__input").val(q);
$(".sr-hot__tag").on("click", function() {
const keyword = $(this).attr("data-keyword") || $(this).text().trim();
$(".sr-search .s-search__input").val(keyword);
$(".sr-search").trigger("submit");
});
initHotTags();
initFaqAccordion();
initVideoModal();
}); });
//#endregion //#endregion

2
public/themes/website/1/zh/demo/download.html

@ -105,7 +105,7 @@
</div> </div>
<div class="d-list"> <div class="d-list">
{hcTaglib:contentPage mainField="*" subField="*" name="hc_content" limit="12" item="vo"} {hcTaglib:contentPage mainField="*" subField="*" name="hc_content" limit="12" item="vo"}
<a class="d-item" target="_blank" href="{$vo.url ?? ''}" download>
<a class="d-item" href="{$vo.url ?? ''}" download="{$vo.title}">
<div class="d-item__main"> <div class="d-item__main">
<img class="d-item__pdf" src="data:image/svg+xml,%3csvg%20viewBox='0%200%2032%2032'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20width='32.000000'%20height='32.000000'%20fill='none'%3e%3crect%20id='PDF%201'%20width='32.000000'%20height='32.000000'%20x='0.000000'%20y='0.000000'%20/%3e%3cpath%20id='矢量%20508'%20d='M28.1766%2028.9602C28.1766%2029.3602%2028.0164%2029.7441%2027.7285%2030.032C27.4402%2030.3199%2027.0566%2030.4801%2026.6562%2030.4801L5.32852%2030.4801C4.92852%2030.4801%204.52852%2030.3199%204.25664%2030.032C3.96875%2029.7437%203.80859%2029.3602%203.80859%2028.9602L3.80859%201.51992C3.80859%201.11992%203.96836%200.719922%204.25664%200.448047C4.52852%200.160156%204.92891%200%205.32852%200L18.4168%200C18.8168%200%2019.2168%200.160156%2019.5047%200.448047L27.7445%208.68828C28.0324%208.97617%2028.1926%209.36016%2028.1926%209.77617L28.1926%2028.9602L28.1766%2028.9602Z'%20fill='rgb(235,236,240)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20509'%20d='M28.1766%2028.96L28.1766%2030.4799C28.1766%2030.8799%2028.0164%2031.2799%2027.7285%2031.5518C27.4402%2031.84%2027.0566%2031.9998%2026.6562%2031.9998L5.32852%2031.9998C4.48047%2031.9998%203.80859%2031.3119%203.80859%2030.4799L3.80859%2028.96C3.80859%2029.36%203.96836%2029.7439%204.25664%2030.0318C4.54453%2030.3197%204.92852%2030.4799%205.32852%2030.4799L26.6566%2030.4799C27.5047%2030.4799%2028.1766%2029.792%2028.1766%2028.96L28.1766%2028.96Z'%20fill='rgb(193,199,208)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20510'%20d='M3.80781%2016.7682L3.80781%2013.7119L0.751953%2016.7682L3.80781%2016.7682ZM28.1758%2016.7682L28.2078%2013.7119L31.2477%2016.7682L28.1758%2016.7682L28.1758%2016.7682Z'%20fill='rgb(211,0,0)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20511'%20d='M28.1762%209.77617L28.1762%209.98398L19.9359%209.98398C19.0879%209.98398%2018.416%209.29609%2018.416%208.46406L18.416%200C18.816%200%2019.216%200.160156%2019.5039%200.448047L27.7602%208.68828C28.032%208.97617%2028.1922%209.36016%2028.1762%209.77617Z'%20fill='rgb(193,199,208)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20512'%20d='M15.7164%2019.0972L14.4629%2019.0972L14.4629%2023.5655L15.6941%2023.5655C17.0926%2023.5655%2017.8484%2022.7776%2017.8484%2021.2577C17.8484%2019.9351%2017.157%2019.1147%2015.7164%2019.0972ZM8.59219%2019.0995L6.79883%2019.0995L6.79883%2020.9983L8.59219%2020.9983C9.32695%2020.9983%209.79141%2020.7464%209.79141%2020.0362C9.79141%2019.4573%209.43555%2019.0995%208.59219%2019.0995L8.59219%2019.0995Z'%20fill='rgb(255,29,29)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20513'%20d='M0.767578%2016.7681L0.767578%2024.3681C0.767578%2024.7841%200.927344%2025.1681%201.21562%2025.456C1.4875%2025.7442%201.8875%2025.904%202.2875%2025.904L29.7117%2025.904C30.5438%2025.904%2031.2316%2025.2321%2031.2316%2024.3841L31.2316%2016.7681L0.767578%2016.7681ZM8.72617%2022.3454L6.79844%2022.3454L6.79844%2024.9103L5.05469%2024.9103L5.05469%2017.7618L8.75352%2017.7618C10.4156%2017.7618%2011.5207%2018.6021%2011.5207%2020.0087C11.5207%2021.4153%2010.4797%2022.3454%208.72617%2022.3454L8.72617%2022.3454ZM15.9223%2024.9103L12.7277%2024.9103L12.7277%2017.7618L15.959%2017.7618C18.3676%2017.7618%2019.6855%2019.3251%2019.6855%2021.211C19.6855%2023.4993%2018.0027%2024.9103%2015.9223%2024.9103ZM26.9953%2019.1419L22.8473%2019.1419L22.8473%2020.7677L26.7164%2020.7677L26.7164%2022.1579L22.8473%2022.1579L22.8473%2024.9099L21.1125%2024.9099L21.1125%2017.7614L26.9953%2017.7614L26.9953%2019.1415L26.9953%2019.1419Z'%20fill='rgb(239,67,53)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20514'%20d='M8.75313%2017.7617L5.05469%2017.7617L5.05469%2024.9102L6.79844%2024.9102L6.79844%2022.3453L8.72617%2022.3453C10.4797%2022.3453%2011.5207%2021.4703%2011.5207%2020.0086C11.5207%2018.5469%2010.4156%2017.7617%208.75352%2017.7617L8.75313%2017.7617ZM8.59141%2020.9984L6.79805%2020.9984L6.79805%2019.0996L8.59141%2019.0996C9.43477%2019.0996%209.79063%2019.4574%209.79063%2020.0363C9.79063%2020.7461%209.32578%2020.9984%208.59141%2020.9984L8.59141%2020.9984ZM15.959%2017.7617L12.7277%2017.7617L12.7277%2024.9102L15.9223%2024.9102C18.0027%2024.9102%2019.6855%2023.4992%2019.6855%2021.2109C19.6855%2019.325%2018.368%2017.7617%2015.959%2017.7617ZM15.6934%2023.5656L14.4621%2023.5656L14.4621%2019.0973L15.7156%2019.0973C17.1559%2019.1152%2017.8477%2019.9355%2017.8477%2021.2578C17.8477%2022.7777%2017.0918%2023.5656%2015.6934%2023.5656ZM21.1125%2024.9102L22.8473%2024.9102L22.8473%2022.1582L26.7164%2022.1582L26.7164%2020.768L22.8473%2020.768L22.8473%2019.1422L26.9953%2019.1422L26.9953%2017.7617L21.1125%2017.7617L21.1125%2024.9102Z'%20fill='rgb(255,255,255)'%20fill-rule='nonzero'%20/%3e%3c/svg%3e" alt="" width="32" height="32" /> <img class="d-item__pdf" src="data:image/svg+xml,%3csvg%20viewBox='0%200%2032%2032'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20width='32.000000'%20height='32.000000'%20fill='none'%3e%3crect%20id='PDF%201'%20width='32.000000'%20height='32.000000'%20x='0.000000'%20y='0.000000'%20/%3e%3cpath%20id='矢量%20508'%20d='M28.1766%2028.9602C28.1766%2029.3602%2028.0164%2029.7441%2027.7285%2030.032C27.4402%2030.3199%2027.0566%2030.4801%2026.6562%2030.4801L5.32852%2030.4801C4.92852%2030.4801%204.52852%2030.3199%204.25664%2030.032C3.96875%2029.7437%203.80859%2029.3602%203.80859%2028.9602L3.80859%201.51992C3.80859%201.11992%203.96836%200.719922%204.25664%200.448047C4.52852%200.160156%204.92891%200%205.32852%200L18.4168%200C18.8168%200%2019.2168%200.160156%2019.5047%200.448047L27.7445%208.68828C28.0324%208.97617%2028.1926%209.36016%2028.1926%209.77617L28.1926%2028.9602L28.1766%2028.9602Z'%20fill='rgb(235,236,240)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20509'%20d='M28.1766%2028.96L28.1766%2030.4799C28.1766%2030.8799%2028.0164%2031.2799%2027.7285%2031.5518C27.4402%2031.84%2027.0566%2031.9998%2026.6562%2031.9998L5.32852%2031.9998C4.48047%2031.9998%203.80859%2031.3119%203.80859%2030.4799L3.80859%2028.96C3.80859%2029.36%203.96836%2029.7439%204.25664%2030.0318C4.54453%2030.3197%204.92852%2030.4799%205.32852%2030.4799L26.6566%2030.4799C27.5047%2030.4799%2028.1766%2029.792%2028.1766%2028.96L28.1766%2028.96Z'%20fill='rgb(193,199,208)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20510'%20d='M3.80781%2016.7682L3.80781%2013.7119L0.751953%2016.7682L3.80781%2016.7682ZM28.1758%2016.7682L28.2078%2013.7119L31.2477%2016.7682L28.1758%2016.7682L28.1758%2016.7682Z'%20fill='rgb(211,0,0)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20511'%20d='M28.1762%209.77617L28.1762%209.98398L19.9359%209.98398C19.0879%209.98398%2018.416%209.29609%2018.416%208.46406L18.416%200C18.816%200%2019.216%200.160156%2019.5039%200.448047L27.7602%208.68828C28.032%208.97617%2028.1922%209.36016%2028.1762%209.77617Z'%20fill='rgb(193,199,208)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20512'%20d='M15.7164%2019.0972L14.4629%2019.0972L14.4629%2023.5655L15.6941%2023.5655C17.0926%2023.5655%2017.8484%2022.7776%2017.8484%2021.2577C17.8484%2019.9351%2017.157%2019.1147%2015.7164%2019.0972ZM8.59219%2019.0995L6.79883%2019.0995L6.79883%2020.9983L8.59219%2020.9983C9.32695%2020.9983%209.79141%2020.7464%209.79141%2020.0362C9.79141%2019.4573%209.43555%2019.0995%208.59219%2019.0995L8.59219%2019.0995Z'%20fill='rgb(255,29,29)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20513'%20d='M0.767578%2016.7681L0.767578%2024.3681C0.767578%2024.7841%200.927344%2025.1681%201.21562%2025.456C1.4875%2025.7442%201.8875%2025.904%202.2875%2025.904L29.7117%2025.904C30.5438%2025.904%2031.2316%2025.2321%2031.2316%2024.3841L31.2316%2016.7681L0.767578%2016.7681ZM8.72617%2022.3454L6.79844%2022.3454L6.79844%2024.9103L5.05469%2024.9103L5.05469%2017.7618L8.75352%2017.7618C10.4156%2017.7618%2011.5207%2018.6021%2011.5207%2020.0087C11.5207%2021.4153%2010.4797%2022.3454%208.72617%2022.3454L8.72617%2022.3454ZM15.9223%2024.9103L12.7277%2024.9103L12.7277%2017.7618L15.959%2017.7618C18.3676%2017.7618%2019.6855%2019.3251%2019.6855%2021.211C19.6855%2023.4993%2018.0027%2024.9103%2015.9223%2024.9103ZM26.9953%2019.1419L22.8473%2019.1419L22.8473%2020.7677L26.7164%2020.7677L26.7164%2022.1579L22.8473%2022.1579L22.8473%2024.9099L21.1125%2024.9099L21.1125%2017.7614L26.9953%2017.7614L26.9953%2019.1415L26.9953%2019.1419Z'%20fill='rgb(239,67,53)'%20fill-rule='nonzero'%20/%3e%3cpath%20id='矢量%20514'%20d='M8.75313%2017.7617L5.05469%2017.7617L5.05469%2024.9102L6.79844%2024.9102L6.79844%2022.3453L8.72617%2022.3453C10.4797%2022.3453%2011.5207%2021.4703%2011.5207%2020.0086C11.5207%2018.5469%2010.4156%2017.7617%208.75352%2017.7617L8.75313%2017.7617ZM8.59141%2020.9984L6.79805%2020.9984L6.79805%2019.0996L8.59141%2019.0996C9.43477%2019.0996%209.79063%2019.4574%209.79063%2020.0363C9.79063%2020.7461%209.32578%2020.9984%208.59141%2020.9984L8.59141%2020.9984ZM15.959%2017.7617L12.7277%2017.7617L12.7277%2024.9102L15.9223%2024.9102C18.0027%2024.9102%2019.6855%2023.4992%2019.6855%2021.2109C19.6855%2019.325%2018.368%2017.7617%2015.959%2017.7617ZM15.6934%2023.5656L14.4621%2023.5656L14.4621%2019.0973L15.7156%2019.0973C17.1559%2019.1152%2017.8477%2019.9355%2017.8477%2021.2578C17.8477%2022.7777%2017.0918%2023.5656%2015.6934%2023.5656ZM21.1125%2024.9102L22.8473%2024.9102L22.8473%2022.1582L26.7164%2022.1582L26.7164%2020.768L22.8473%2020.768L22.8473%2019.1422L26.9953%2019.1422L26.9953%2017.7617L21.1125%2017.7617L21.1125%2024.9102Z'%20fill='rgb(255,255,255)'%20fill-rule='nonzero'%20/%3e%3c/svg%3e" alt="" width="32" height="32" />
<span class="d-item__name">{$vo.title}</span> <span class="d-item__name">{$vo.title}</span>

136
public/themes/website/1/zh/demo/single_search.html

@ -48,6 +48,8 @@
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/common.css"> <link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/common.css">
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/pagination.css"> <link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/pagination.css">
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/empty.css"> <link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/empty.css">
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/faq.css">
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/video.css">
<link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/search.css"> <link rel="stylesheet" crossorigin href="/themes/dist_static/static/css/search.css">
</head> </head>
@ -79,7 +81,7 @@
{/hcTaglib:category} {/hcTaglib:category}
{volist name="descriptionArr" id="one"} {volist name="descriptionArr" id="one"}
<button type="button" class="sr-hot__tag" data-keyword="HMI">{$one}</button>
<button type="button" class="sr-hot__tag" data-keyword="{$one}">{$one}</button>
{/volist} {/volist}
</div> </div>
@ -89,9 +91,9 @@
{php} {php}
$sr_type_cur = $sr_type ?? 'all'; $sr_type_cur = $sr_type ?? 'all';
$sr_q = $keywords ?? ''; $sr_q = $keywords ?? '';
$sr_counts = $sr_counts ?? ['all' => 0, 'product' => 0, 'solution' => 0, 'news' => 0, 'faq' => 0];
$sr_counts = $sr_counts ?? ['all' => 0, 'product' => 0, 'news' => 0, 'faq' => 0, 'other' => 0];
$sr_tabs = []; $sr_tabs = [];
foreach (['all', 'product', 'solution', 'news', 'faq'] as $tabType) {
foreach (['all', 'product', 'news', 'faq', 'other'] as $tabType) {
$query = ['type' => $tabType]; $query = ['type' => $tabType];
if ($sr_q !== '') { if ($sr_q !== '') {
$query['q'] = $sr_q; $query['q'] = $sr_q;
@ -108,10 +110,6 @@
href="{$sr_tabs.product}"> href="{$sr_tabs.product}">
产品 ( <span data-count="product">{$sr_counts.product}</span> ) 产品 ( <span data-count="product">{$sr_counts.product}</span> )
</a> </a>
<a class="sr-tabs__item {if $sr_type_cur=='solution'}is-active{/if}" role="tab" aria-selected="{if $sr_type_cur=='solution'}true{else /}false{/if}"
href="{$sr_tabs.solution}">
解决方案 ( <span data-count="solution">{$sr_counts.solution}</span> )
</a>
<a class="sr-tabs__item {if $sr_type_cur=='news'}is-active{/if}" role="tab" aria-selected="{if $sr_type_cur=='news'}true{else /}false{/if}" <a class="sr-tabs__item {if $sr_type_cur=='news'}is-active{/if}" role="tab" aria-selected="{if $sr_type_cur=='news'}true{else /}false{/if}"
href="{$sr_tabs.news}"> href="{$sr_tabs.news}">
新闻 ( <span data-count="news">{$sr_counts.news}</span> ) 新闻 ( <span data-count="news">{$sr_counts.news}</span> )
@ -120,45 +118,132 @@
href="{$sr_tabs.faq}"> href="{$sr_tabs.faq}">
常见问题 ( <span data-count="faq">{$sr_counts.faq}</span> ) 常见问题 ( <span data-count="faq">{$sr_counts.faq}</span> )
</a> </a>
<a class="sr-tabs__item {if $sr_type_cur=='other'}is-active{/if}" role="tab" aria-selected="{if $sr_type_cur=='other'}true{else /}false{/if}"
href="{$sr_tabs.other}">
其他 ( <span data-count="other">{$sr_counts.other}</span> )
</a>
</div> </div>
<div class="sr-list"> <div class="sr-list">
{volist name="list" id="vo"} {volist name="list" id="vo"}
{php} {php}
$sr_date = '';
$sr_time = $vo['publish_time'] ?? ($vo['create_time'] ?? '');
if (!empty($sr_time)) {
$sr_date = is_numeric($sr_time) ? date('Y-m-d', (int)$sr_time) : $sr_time;
$sr_kind = $vo['sr_kind'] ?? 'content';
$sr_date = $vo['sr_date'] ?? '';
if ($sr_date === '') {
$sr_time = $vo['publish_time'] ?? ($vo['create_time'] ?? '');
if ($sr_time !== '' && $sr_time !== null) {
if (is_numeric($sr_time)) {
$sr_date = date('Y-m-d', (int)$sr_time);
} else {
$ts = strtotime((string)$sr_time);
$sr_date = $ts ? date('Y-m-d', $ts) : substr((string)$sr_time, 0, 10);
}
}
} }
$sr_cid = $vo['category_id'] ?? ($vo['category'][0]['id'] ?? 0); $sr_cid = $vo['category_id'] ?? ($vo['category'][0]['id'] ?? 0);
$sr_thumb = is_array($vo['thumbnail'] ?? null) ? ($vo['thumbnail']['url'] ?? '') : ''; $sr_thumb = is_array($vo['thumbnail'] ?? null) ? ($vo['thumbnail']['url'] ?? '') : '';
$sr_url = hcUrl('detail/index', ['id' => $vo['id'], 'cid' => $sr_cid]); $sr_url = hcUrl('detail/index', ['id' => $vo['id'], 'cid' => $sr_cid]);
$sr_file = $vo['url'] ?? '';
$sr_title = $vo['title'] ?? '';
$sr_type_name = $vo['sr_tab_name'] ?? '内容';
$sr_show_desc = ($sr_kind === 'news' || $sr_kind === 'content');
$sr_show_more = ($sr_kind === 'news' || $sr_kind === 'content');
{/php} {/php}
<article class="sr-item" data-keywords="{$vo.title}">
<article class="sr-item sr-item--{$sr_kind}" data-keywords="{$sr_title}" data-kind="{$sr_kind}">
{if $sr_kind == 'video'}
<button type="button" class="sr-item__media sr-item__media--video" data-video-src="{$sr_file}" aria-label="播放:{$sr_title}">
<span class="v-card__media">
<img class="v-card__cover" src="{$sr_thumb}" alt="" width="300" height="200" loading="lazy" />
<span class="v-card__play" aria-hidden="true">
<img src="data:image/svg+xml,%3csvg%20viewBox='0%200%2013.5386%2016'%20xmlns='http://www.w3.org/2000/svg'%20width='13.538574'%20height='16.000000'%20fill='none'%3e%3cpath%20d='M8.86093%201.45695L15.1085%2012.0297C15.5024%2012.6963%2015.0219%2013.5384%2014.2476%2013.5384L1.75245%2013.5384C0.978149%2013.5384%200.497614%2012.6963%200.891523%2012.0297L7.13907%201.45695C7.52614%200.801924%208.47387%200.801924%208.86093%201.45695Z'%20fill='rgb(255,255,255)'%20fill-rule='evenodd'%20transform='matrix(0,1,-1,0,13.5386,0)'%20/%3e%3c/svg%3e" alt="" width="14" height="16" />
</span>
</span>
</button>
{elseif $sr_kind == 'download' /}
<a class="sr-item__media" href="{$sr_file}" download="{$sr_title}">
<img src="{$sr_thumb}" alt="" width="300" height="200" loading="lazy" />
</a>
{elseif $sr_kind == 'announce' /}
<a class="sr-item__media" href="{$sr_file}" target="_blank" rel="noopener">
<img src="{$sr_thumb}" alt="" width="300" height="200" loading="lazy" />
</a>
{else /}
<a class="sr-item__media" href="{$sr_url}"> <a class="sr-item__media" href="{$sr_url}">
<img src="{$sr_thumb}" alt="" width="300" height="200" loading="lazy" /> <img src="{$sr_thumb}" alt="" width="300" height="200" loading="lazy" />
</a> </a>
{/if}
<div class="sr-item__body"> <div class="sr-item__body">
<div class="sr-item__main"> <div class="sr-item__main">
<div class="sr-item__meta"> <div class="sr-item__meta">
<span class="sr-item__type">{if !empty($vo['category'][0]['title'])}{$vo.category.0.title}{else /}内容{/if}</span>
<span class="sr-item__type">{$sr_type_name}</span>
<span class="sr-item__sep" aria-hidden="true"></span> <span class="sr-item__sep" aria-hidden="true"></span>
<time class="sr-item__date" datetime="{$sr_date}">{$sr_date}</time> <time class="sr-item__date" datetime="{$sr_date}">{$sr_date}</time>
</div> </div>
{if $sr_kind == 'faq'}
<div class="f-item sr-item__faq">
<button type="button" class="f-item__trigger" aria-expanded="false">
<span class="f-item__q">
<span class="f-item__dot" aria-hidden="true"></span>
<span class="f-item__title">{$sr_title}</span>
</span>
<span class="f-item__icon" aria-hidden="true"></span>
</button>
<div class="f-item__panel">
<p class="f-item__a">
{$vo.content|strip_tags}
</p>
</div>
</div>
{else /}
<h2 class="sr-item__title"> <h2 class="sr-item__title">
<a href="{$sr_url}">{$vo.title}</a>
{if $sr_kind == 'video'}
{$sr_title}
{elseif $sr_kind == 'download' /}
<a href="{$sr_file}" download="{$sr_title}">{$sr_title}</a>
{elseif $sr_kind == 'announce' /}
<a href="{$sr_file}" target="_blank" rel="noopener">{$sr_title}</a>
{else /}
<a href="{$sr_url}">{$sr_title}</a>
{/if}
</h2> </h2>
{/if}
{if $sr_show_desc}
{notempty name="vo.description"} {notempty name="vo.description"}
<p class="sr-item__desc">{$vo.description}</p> <p class="sr-item__desc">{$vo.description}</p>
{/notempty} {/notempty}
{/if}
</div> </div>
{if $sr_kind == 'download'}
<a class="sr-item__more sr-item__more--download" href="{$sr_file}" download="{$sr_title}">
<span>立即下载</span>
<img src="data:image/svg+xml,%3csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20fill='none'%3e%3cpath%20d='M16.667%209.333H22V22H2V9.333h5.333'%20stroke='rgb(46,53,58)'%20stroke-linejoin='round'%20stroke-width='1.5'/%3e%3cpath%20d='M16%2014l-4%204-4-4M12%202v16'%20stroke='rgb(239,67,53)'%20stroke-width='1.5'/%3e%3c/svg%3e" alt="" width="20" height="20" />
</a>
{elseif $sr_kind == 'product' /}
<a class="sr-item__more sr-item__more--product" href="{$sr_url}">
<span>了解产品</span>
<span class="s-product-card__arrow" aria-hidden="true">
<img src="data:image/svg+xml,%3csvg%20viewBox='0%200%2012.2529%2011.314'%20xmlns='http://www.w3.org/2000/svg'%20width='12.252930'%20height='11.313965'%20fill='none'%3e%3cpath%20d='M5.18202%201.41422L6.59622%200L12.2531%205.65686L12.2529%205.65702L10.8389%207.07108L6.59608%2011.3139L5.18186%209.89966L8.4245%206.65702L-0%206.65702L0%204.657L8.42482%204.65702L5.18202%201.41422Z'%20fill='rgb(239,67,53)'%20fill-rule='evenodd'/%3e%3c/svg%3e" alt="" width="12" height="11" />
</span>
</a>
{elseif $sr_kind == 'announce' /}
<a class="sr-item__more" href="{$sr_file}" target="_blank" rel="noopener">
<span>探索更多</span>
<svg viewBox="0 0 16.502 6.66113" xmlns="http://www.w3.org/2000/svg" width="16.501953" height="6.661133" fill="none">
<path d="M0 2.83057L16 2.83057L16 3.83057L0 3.83057L0 2.83057ZM15.2929 3.33057L12.818 0.855693C12.62 0.657703 12.62 0.346575 12.818 0.148586C13.016 -0.0494041 13.3271 -0.0494046 13.5251 0.148585L16.3536 2.97701C16.5515 3.175 16.5515 3.48613 16.3536 3.68412L13.5251 6.51255C13.3271 6.71054 13.016 6.71054 12.818 6.51255C12.62 6.31456 12.62 6.00343 12.818 5.80544L15.2929 3.33057Z" fill="rgb(102,102,102)" fill-rule="nonzero" />
</svg>
</a>
{elseif $sr_show_more /}
<a class="sr-item__more" href="{$sr_url}"> <a class="sr-item__more" href="{$sr_url}">
<span>探索更多</span> <span>探索更多</span>
<svg viewBox="0 0 16.502 6.66113" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.501953" height="6.661133" fill="none" customFrame="#000000">
<path id="箭头 2" d="M0 2.83057L16 2.83057L16 3.83057L0 3.83057L0 2.83057ZM15.2929 3.33057L12.818 0.855693C12.62 0.657703 12.62 0.346575 12.818 0.148586C13.016 -0.0494041 13.3271 -0.0494046 13.5251 0.148585L16.3536 2.97701C16.5515 3.175 16.5515 3.48613 16.3536 3.68412L13.5251 6.51255C13.3271 6.71054 13.016 6.71054 12.818 6.51255C12.62 6.31456 12.62 6.00343 12.818 5.80544L15.2929 3.33057Z" fill="rgb(102,102,102)" fill-rule="nonzero" />
</svg>
<svg viewBox="0 0 16.502 6.66113" xmlns="http://www.w3.org/2000/svg" width="16.501953" height="6.661133" fill="none">
<path d="M0 2.83057L16 2.83057L16 3.83057L0 3.83057L0 2.83057ZM15.2929 3.33057L12.818 0.855693C12.62 0.657703 12.62 0.346575 12.818 0.148586C13.016 -0.0494041 13.3271 -0.0494046 13.5251 0.148585L16.3536 2.97701C16.5515 3.175 16.5515 3.48613 16.3536 3.68412L13.5251 6.51255C13.3271 6.71054 13.016 6.71054 12.818 6.51255C12.62 6.31456 12.62 6.00343 12.818 5.80544L15.2929 3.33057Z" fill="rgb(102,102,102)" fill-rule="nonzero" />
</svg>
</a> </a>
{/if}
</div> </div>
</article> </article>
{/volist} {/volist}
@ -175,6 +260,21 @@
{else /} {else /}
{$list_page|raw} {$list_page|raw}
{/if} {/if}
<div class="v-modal" id="v-modal" hidden>
<div class="v-modal__backdrop" data-v-modal-close></div>
<div class="v-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="v-modal-title">
<div class="v-modal__head">
<h2 class="v-modal__title" id="v-modal-title">视频播放</h2>
<button type="button" class="v-modal__close" data-v-modal-close aria-label="关闭">
<img src="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%3e%3cpath%20d='M1.5%201.5L14.5%2014.5M14.5%201.5L1.5%2014.5'%20stroke='%23fff'%20stroke-width='1.5'%20stroke-linecap='round'/%3e%3c/svg%3e" alt="" width="16" height="16" aria-hidden="true" />
</button>
</div>
<div class="v-modal__body">
<video class="v-modal__video" id="v-modal-video" controls playsinline></video>
</div>
</div>
</div>
</div> </div>
</main> </main>

Loading…
Cancel
Save