feat: 完善主题功能并适配插件 (v1.1.5)

功能新增
- 新增页面布局契约 templates/layout.html,插件前台页面可复用主题外观,避免回退到 Halo fallback 布局
- 新增微信读书页面模板 (weread.html),集成 halo-weread-plugin 书架
- 新增订阅页面模板 (page_subscriptions.html)
- 新增欢迎弹窗组件(IP 地理定位,多 API 容错)
- 新增点击特效组件(9 种效果)
- 页脚新增全站统计,支持开关与统计项配置,默认开启

插件适配
- 适配 extra-api:文章字数改服务端统计、正文可选中英混排与服务端代码高亮
- 修正各页面插件应用市场链接与插件名

修复
- 修复文章正文图片/视频无法居中(正文样式移至全局,scoped 样式对 Thymeleaf 注入内容无效)
- 修复正文 H1-H6 字号过大,重排层级与移动端断点
- 修复 th: 属性中文字符串缺少引号导致的 Thymeleaf 解析异常(/links、/moments 500)
- 修复 JS 内联表达式与 Thymeleaf 内联语法冲突,全部内联脚本加 th:inline="none"
- 修复移除 i18n 后 steam 页 Elvis 表达式回归问题
- 修正订阅页 th:attr 引号嵌套错误

优化
- Hero 移除灰色遮罩,下滑箭头改为可点击平滑滚动
- 优化目录样式:移除圆点与下拉箭头,支持两行显示,修复长目录截断
- 移除 i18n 多语言支持

清理
- 移除未使用的 Vue/图标依赖与废弃脚本、重复资源
This commit is contained in:
2026-09-26 11:18:52 +08:00
parent 9d0bfcfb4f
commit 430d107d44
78 changed files with 2959 additions and 36075 deletions
+158
View File
@@ -0,0 +1,158 @@
---
import Layout from "../layouts/Layout.astro";
---
<Layout wide>
<Fragment slot="head">
<title th:text="|${theme.config?.weread?.weread_page_title ?: '书架'} - ${site.title}|"></title>
</Fragment>
<section class="wi-weread">
<div class="wi-container">
<div class="wi-weread__header">
<h1
class="wi-weread__title"
th:text="${theme.config?.weread?.weread_page_title ?: '书架'}"
>
书架
</h1>
<p
class="wi-weread__subtitle"
th:if="${theme.config?.weread?.weread_page_subtitle}"
th:text="${theme.config?.weread?.weread_page_subtitle}"
>
我在读的书
</p>
<span class="wi-page-accent"></span>
</div>
<th:block th:if="${pluginFinder.available('halo-weread-plugin')}">
<div
class="wi-weread__shelf"
id="weread-shelf-wrapper"
th:attr="data-endpoint=@{/halo-weread-plugin/shelf-html}"
>
<p class="wi-weread__loading">正在展开书架…</p>
</div>
</th:block>
<div
class="wi-weread__empty"
th:unless="${pluginFinder.available('halo-weread-plugin')}"
>
<p>
该功能需要安装「微信读书(WeRead)信息展示」插件,<a
href="https://github.com/yeora26/halo-weread-plugin"
target="_blank"
rel="noopener noreferrer"
>前往插件仓库了解</a
>
</p>
</div>
</div>
</section>
<script is:inline th:inline="none">
(function () {
var container = document.getElementById("weread-shelf-wrapper");
if (!container) return;
var endpoint =
container.getAttribute("data-endpoint") ||
"/halo-weread-plugin/shelf-html";
fetch(endpoint)
.then(function (res) {
if (!res.ok) throw new Error("HTTP " + res.status);
return res.text();
})
.then(function (html) {
container.innerHTML = html;
/* innerHTML 插入的脚本不会执行,需要重建后才会运行 */
var oldScripts = container.querySelectorAll("script");
Array.prototype.forEach.call(oldScripts, function (oldScript) {
var script = document.createElement("script");
script.textContent = oldScript.textContent;
oldScript.parentNode.replaceChild(script, oldScript);
});
})
.catch(function () {
container.innerHTML =
'<p class="wi-weread__loading">书架暂时无法展开,请稍后再试。</p>';
});
})();
</script>
</Layout>
<style>
.wi-weread {
padding-block: 2rem 3rem;
}
.wi-weread__header {
text-align: center;
margin-bottom: var(--space-2xl);
}
.wi-weread__title {
font-family: var(--font-sans);
font-size: var(--text-3xl);
font-weight: 700;
color: var(--ink);
letter-spacing: var(--tracking-tight);
margin-bottom: var(--space-sm);
}
.wi-weread__subtitle {
font-size: var(--text-base);
color: var(--ink-3);
line-height: var(--leading-relaxed);
}
.wi-weread__shelf {
min-height: 200px;
}
.wi-weread__loading {
text-align: center;
color: var(--ink-3);
font-size: var(--text-sm);
padding: var(--space-2xl) 0;
}
.wi-weread__empty {
text-align: center;
padding: var(--space-2xl) var(--space-lg);
border: 1px dashed var(--rule);
border-radius: var(--radius-lg, 16px);
color: var(--ink-3);
font-size: var(--text-sm);
}
.wi-weread__empty a {
color: var(--accent);
text-decoration: none;
}
.wi-weread__empty a:hover {
text-decoration: underline;
}
/* 插件返回的书架内容:收敛为与主题一致的卡片观感 */
.wi-weread__shelf :global(img) {
max-width: 100%;
height: auto;
border-radius: 8px;
}
.wi-weread__shelf :global(a) {
color: var(--accent);
}
@media (max-width: 768px) {
.wi-weread__title {
font-size: var(--text-2xl);
}
}
</style>