119 lines
8.5 KiB
HTML
119 lines
8.5 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
|
||
<head th:replace="~{${themeBase} + '/fragments/head' :: head}"></head>
|
||
<body>
|
||
<header th:replace="~{${themeBase} + '/fragments/header' :: header}"></header>
|
||
|
||
<main class="cg-home" id="main-content">
|
||
<!-- 首页轮播位(cms_banner position=home;设计尺寸 1920×560,见 theme.json bannerSize)——页面级固定槽位,布局模式同样保留 -->
|
||
<section class="cg-banner" th:if="${!#lists.isEmpty(banners)}" aria-label="焦点图片">
|
||
<div class="cg-banner-slides">
|
||
<a class="cg-banner-slide" th:each="b, stat : ${banners}"
|
||
th:classappend="${stat.first} ? 'active'"
|
||
th:href="${b.linkUrl}" th:title="${b.title}">
|
||
<img th:src="${b.imageUrl}" th:alt="${b.title}">
|
||
<span class="cg-banner-cap" th:text="${b.title}">标题</span>
|
||
</a>
|
||
</div>
|
||
<button class="cg-banner-arrow prev" type="button" aria-label="上一张" th:if="${#lists.size(banners) > 1}">‹</button>
|
||
<button class="cg-banner-arrow next" type="button" aria-label="下一张" th:if="${#lists.size(banners) > 1}">›</button>
|
||
<div class="cg-banner-dots" th:if="${#lists.size(banners) > 1}">
|
||
<button th:each="b, stat : ${banners}" th:classappend="${stat.first} ? 'active'"
|
||
th:aria-label="${'第' + (stat.count) + '张'}"></button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 首页布局模式(docs/16 §4.4 · v2 手册 §A.3 P-A3):home_layout 落库后按区块序列渲染。
|
||
本包为 A 档:8 形态 + quick_links/notice_bar 全部自持(fragments/home-blocks.html),
|
||
compact/image_wall/links 三处不再借 themes/common 的 plb 骨架(借骨架 = 换肤只换页头页脚,手册 §2.2 事故根因);
|
||
只有白名单外的未知类型才落 common 兜底骨架——故 common 的 :: style 样式段必须引入(R-32:本包此前缺这段,兜底区块裸奔)。
|
||
注意坑④:th:replace(优先级 100)先于 th:case(300)执行——case 必须放父元素、replace 放子元素。 -->
|
||
<th:block th:if="${layoutBlocks != null}">
|
||
<th:block th:replace="~{'themes/common/fragments/home-blocks' :: style}" />
|
||
<th:block th:replace="~{'themes/common/fragments/home-blocks' :: previewScript}" />
|
||
<!-- D-8(docs/20):骨架共享入场动效 + count-up;主题参数 animation=off 关闭 -->
|
||
<th:block th:if="${themeParams == null or themeParams['animation'] != 'off'}" th:replace="~{'themes/common/fragments/home-blocks' :: motionScript}" />
|
||
<th:block th:each="block : ${layoutBlocks}">
|
||
<div class="plb-anchor" th:attr="data-plb-id=${block['id']}" style="display:contents">
|
||
<th:block th:switch="${block.type}">
|
||
<th:block th:case="'article_list'">
|
||
<th:block th:switch="${block.homeStyle}">
|
||
<th:block th:case="'news_grid'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: news_grid(${block})}" /></th:block>
|
||
<th:block th:case="'media_focus'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: media_focus(${block})}" /></th:block>
|
||
<th:block th:case="'compact'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: compact(${block})}" /></th:block>
|
||
<th:block th:case="'image_wall'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: image_wall(${block})}" /></th:block>
|
||
<th:block th:case="*"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: card(${block})}" /></th:block>
|
||
</th:block>
|
||
</th:block>
|
||
<th:block th:case="'ticker'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: ticker(${block})}" /></th:block>
|
||
<th:block th:case="'gallery'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: gallery(${block})}" /></th:block>
|
||
<th:block th:case="'links'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: links(${block})}" /></th:block>
|
||
<th:block th:case="'quick_links'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: quick_links(${block})}" /></th:block>
|
||
<th:block th:case="'notice_bar'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: notice_bar(${block})}" /></th:block>
|
||
<th:block th:case="*"><th:block th:replace="~{'themes/common/fragments/home-blocks' :: render(${block})}" /></th:block>
|
||
</th:block>
|
||
</div>
|
||
</th:block>
|
||
</th:block>
|
||
|
||
<!-- 回落分支(docs/16 D2):无 home_layout 时按现状渲染(布局模式下渲染端数据源已清空,双保险不漏段) -->
|
||
<th:block th:unless="${layoutBlocks != null}">
|
||
<!-- 要闻速递横条:置顶文章横向无缝滚动(hover 暂停) -->
|
||
<section class="cg-ticker" th:if="${!#lists.isEmpty(topArticles)}" aria-label="要闻速递">
|
||
<div class="cg-container cg-ticker-inner">
|
||
<span class="cg-ticker-label">要闻速递</span>
|
||
<div class="cg-ticker-viewport">
|
||
<div class="cg-ticker-track">
|
||
<a class="cg-ticker-item" th:each="item : ${topArticles}" th:href="${url.article(item.id)}">
|
||
<span class="cg-ticker-dot" aria-hidden="true"></span>
|
||
<span th:text="${item.title}">要闻标题</span>
|
||
</a>
|
||
<a class="cg-ticker-item" th:each="item : ${topArticles}" th:href="${url.article(item.id)}" aria-hidden="true">
|
||
<span class="cg-ticker-dot" aria-hidden="true"></span>
|
||
<span th:text="${item.title}">要闻标题</span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 一级栏目区块(docs/12):按栏目 homeStyle 三种形态渲染,栏目顺序即首页板块顺序 -->
|
||
<th:block th:each="block : ${categoryBlocks}">
|
||
<th:block th:switch="${block.homeStyle}">
|
||
<th:block th:case="'news_grid'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: news_grid(${block})}" /></th:block>
|
||
<th:block th:case="'media_focus'"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: media_focus(${block})}" /></th:block>
|
||
<th:block th:case="*"><th:block th:replace="~{${themeBase} + '/fragments/home-blocks' :: card(${block})}" /></th:block>
|
||
</th:block>
|
||
</th:block>
|
||
|
||
<!-- 线上展厅(cms_banner position=gallery;设计尺寸 800×520;每行列数由主题参数 galleryCols 控制) -->
|
||
<section class="cg-gallery" th:if="${!#lists.isEmpty(galleryBanners)}" aria-label="线上展厅">
|
||
<div class="cg-container">
|
||
<div class="cg-gallery-head">
|
||
<h2 th:text="${site.config['gallery_title'] ?: '线上展厅'}">线上展厅</h2>
|
||
<p class="cg-gallery-sub" th:text="${site.config['gallery_subtitle'] ?: 'Online Exhibition Hall'}">Online Exhibition Hall</p>
|
||
</div>
|
||
<div class="cg-gallery-stage"
|
||
th:classappend="${'cg-gallery-cols-' + (themeParams['galleryCols'] ?: '4')}"
|
||
th:attr="data-cols=${themeParams['galleryCols'] ?: '4'}">
|
||
<div class="cg-gallery-track">
|
||
<a class="cg-gallery-item" th:each="g : ${galleryBanners}" th:href="${g.linkUrl}"
|
||
th:title="${g.title}">
|
||
<img th:src="${g.imageUrl}" th:alt="${g.title}">
|
||
<span class="cg-gallery-cap" th:if="${!#strings.isEmpty(g.title)}"
|
||
th:text="${g.title}">作品标题</span>
|
||
</a>
|
||
</div>
|
||
<button class="cg-gallery-arrow prev" type="button" aria-label="上一页" th:if="${#lists.size(galleryBanners) > 1}">‹</button>
|
||
<button class="cg-gallery-arrow next" type="button" aria-label="下一页" th:if="${#lists.size(galleryBanners) > 1}">›</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</th:block>
|
||
</main>
|
||
|
||
<footer th:replace="~{${themeBase} + '/fragments/footer' :: footer}"></footer>
|
||
<script th:src="${url.asset('js/main.js')}"></script>
|
||
</body>
|
||
</html>
|