일반 화면(React)과 봇 화면(PHP)은 같은 레이아웃을 각각 렌더하는데 봇 화면 쪽 지원 범위가 뒤처져, 확장이 교체한 본문이 통째로 빈 채 나갔다 (공개 이슈 ). 같은 결손 계열을 전수 조사해 함께 닫는다. - 확장 주입 props 를 렌더 진입 시점에 해석해 자손 전체에 상속 → 게시글·답글 원글·댓글·페이지·상품 설명 5개 지점 복구 - 사용자 작성 HTML 정화기 신설 — isHtml 판정에 따라 이스케이프/정화. 미정화 상태에서 봇 경로로 저장형 스크립트가 실제 실행됐다 - 노드 키 패리티: conditions / type:iterator / responsive 매칭 규칙 / children 문자열 / text 우선순위 / $t:defer / 레이아웃 초기 상태 - 표현식: 단일 바인딩 판정 교체, ||·&& 를 값 반환(JS 시맨틱)으로, 비교식이 raw 경로에서 null 이 되던 문제 - 데이터소스: 엔드포인트 표현식 전면 해석 + 레이아웃 8곳 선언 보강 - 봇 페이지 캐시 1회 전량 무효화 업그레이드 스텝 지원 범위 SSoT 표를 문서에 고정하고, 한쪽만 고치는 것을 막는 검사 룰과 레이아웃 전수 순회 테스트로 잠갔다.
185 lines
6.7 KiB
JSON
185 lines
6.7 KiB
JSON
{
|
|
"version": "1.0.0",
|
|
"layout_name": "search/index",
|
|
"permissions": [],
|
|
"extends": "_user_base",
|
|
"meta": {
|
|
"seo": {
|
|
"enabled": true,
|
|
"extensions": [
|
|
{ "type": "module", "id": "sirsoft-ecommerce" }
|
|
],
|
|
"data_sources": ["searchResults"],
|
|
"page_type": "search",
|
|
"toggle_setting": "$module_settings:sirsoft-ecommerce:seo.seo_search_result",
|
|
"vars": {
|
|
"site_name": "$core_settings:general.site_name"
|
|
},
|
|
"priority": 0.3,
|
|
"changefreq": "daily",
|
|
"og": {
|
|
"type": "website",
|
|
"title": "{{_seo.search.title ?? ''}}"
|
|
},
|
|
"structured_data": {
|
|
"@type": "SearchResultsPage",
|
|
"name": "{{_seo.search.title ?? ''}}"
|
|
}
|
|
}
|
|
},
|
|
"state": {
|
|
"q": ""
|
|
},
|
|
"init_actions": [
|
|
{
|
|
"handler": "setState",
|
|
"params": {
|
|
"target": "global",
|
|
"searchActiveTab": "all",
|
|
"searchBoardFilter": "",
|
|
"searchSortBy": "relevance",
|
|
"searchPage": 1,
|
|
"_local": {
|
|
"q": "{{query?.q || ''}}"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"initGlobal": {
|
|
"searchActiveTab": "all",
|
|
"searchBoardFilter": "",
|
|
"searchSortBy": "relevance",
|
|
"searchPage": 1
|
|
},
|
|
"data_sources": [
|
|
{
|
|
"id": "searchResults",
|
|
"label_key": "$t:editor.data_source.searchResults",
|
|
"type": "api",
|
|
"endpoint": "/api/search?q={{query?.q}}&type={{_global.searchActiveTab ?? 'all'}}&board_slug={{_global.searchBoardFilter}}&sort={{_global.searchSortBy ?? 'relevance'}}&page={{_global.searchPage ?? 1}}&per_page={{(_global.searchActiveTab === 'products') ? 12 : 10}}",
|
|
"method": "GET",
|
|
"auto_fetch": true,
|
|
"loading_strategy": "progressive",
|
|
"condition": "{{query?.q}}",
|
|
"fallback": {
|
|
"data": {
|
|
"keyword": "",
|
|
"total": 0,
|
|
"results": {
|
|
"posts": {
|
|
"total": 0,
|
|
"items": []
|
|
},
|
|
"products": {
|
|
"total": 0,
|
|
"items": []
|
|
},
|
|
"pages": {
|
|
"total": 0,
|
|
"items": []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"slots": {
|
|
"content": [
|
|
{
|
|
"type": "layout",
|
|
"name": "Container",
|
|
"props": {
|
|
"className": "py-4"
|
|
},
|
|
"responsive": {
|
|
"desktop": {
|
|
"props": {
|
|
"className": "py-8"
|
|
}
|
|
}
|
|
},
|
|
"children": [
|
|
{
|
|
"comment": "페이지 헤더",
|
|
"type": "basic",
|
|
"name": "Div",
|
|
"props": {
|
|
"className": "mb-6"
|
|
},
|
|
"children": [
|
|
{
|
|
"type": "basic",
|
|
"name": "H1",
|
|
"props": {
|
|
"className": "text-2xl font-bold text-gray-900 dark:text-white flex items-center gap-2"
|
|
},
|
|
"children": [
|
|
{
|
|
"type": "basic",
|
|
"name": "Icon",
|
|
"props": {
|
|
"name": "search",
|
|
"size": "lg"
|
|
}
|
|
},
|
|
{
|
|
"type": "basic",
|
|
"name": "Span",
|
|
"text": "$t:search.title"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"partial": "partials/search/_search_input.json"
|
|
},
|
|
{
|
|
"partial": "partials/search/_search_tabs.json"
|
|
},
|
|
{
|
|
"partial": "partials/search/_search_filters.json"
|
|
},
|
|
{
|
|
"partial": "partials/search/_search_states.json"
|
|
},
|
|
{
|
|
"partial": "partials/search/_search_results.json"
|
|
},
|
|
{
|
|
"comment": "페이지네이션",
|
|
"type": "composite",
|
|
"name": "Pagination",
|
|
"if": "{{query?.q && (_global.searchActiveTab ?? 'all') !== 'all' && searchResults?.data?.last_page > 1}}",
|
|
"props": {
|
|
"currentPage": "{{searchResults.data.current_page}}",
|
|
"totalPages": "{{searchResults.data.last_page}}",
|
|
"className": "mt-6 flex justify-center"
|
|
},
|
|
"actions": [
|
|
{
|
|
"event": "onPageChange",
|
|
"handler": "sequence",
|
|
"actions": [
|
|
{
|
|
"handler": "setState",
|
|
"params": {
|
|
"target": "global",
|
|
"searchPage": "{{$args[0]}}"
|
|
}
|
|
},
|
|
{
|
|
"handler": "refetchDataSource",
|
|
"params": {
|
|
"dataSourceId": "searchResults"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
} |