Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a08782a959 | ||
|
|
28b1f90b26 |
@@ -11,7 +11,7 @@
|
|||||||
## 特点
|
## 特点
|
||||||
|
|
||||||
1. **响应式设计** — 适配桌面端与移动端,支持暗色模式,移动端使用动态视口单位适配地址栏
|
1. **响应式设计** — 适配桌面端与移动端,支持暗色模式,移动端使用动态视口单位适配地址栏
|
||||||
2. **插件兼容性** — 适配 10 款常用 Halo 插件,安装即用;提供页面布局契约,插件前台页面自动复用主题外观
|
2. **插件兼容性** — 适配 11 款常用 Halo 插件,安装即用;提供页面布局契约,插件前台页面自动复用主题外观
|
||||||
3. **内置灯箱** — 主题内置 LightGallery 灯箱,支持 EXIF 信息展示;安装 lightgallery.js 插件后自动禁用
|
3. **内置灯箱** — 主题内置 LightGallery 灯箱,支持 EXIF 信息展示;安装 lightgallery.js 插件后自动禁用
|
||||||
4. **可配置性** — 17 个设置分组、122 个配置项,几乎所有模块可独立开关
|
4. **可配置性** — 17 个设置分组、122 个配置项,几乎所有模块可独立开关
|
||||||
5. **性能优化** — 服务端字数统计(API 扩展包)、图片懒加载与响应式缩略图、滚动吸附、CSS/HTML 压缩
|
5. **性能优化** — 服务端字数统计(API 扩展包)、图片懒加载与响应式缩略图、滚动吸附、CSS/HTML 压缩
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
| [Steam 信息展示](https://github.com/Tim0x0/halo-plugin-steam) | `PluginSteam` | `/steam` | Steam 游戏库页面,含用户资料、统计数据、最近游玩、游戏库分页 |
|
| [Steam 信息展示](https://github.com/Tim0x0/halo-plugin-steam) | `PluginSteam` | `/steam` | Steam 游戏库页面,含用户资料、统计数据、最近游玩、游戏库分页 |
|
||||||
| [微信读书](https://github.com/yeora26/halo-weread-plugin) | `halo-weread-plugin` | 自定义页面 | 书架展示页面,见下方「自定义页面模板」 |
|
| [微信读书](https://github.com/yeora26/halo-weread-plugin) | `halo-weread-plugin` | 自定义页面 | 书架展示页面,见下方「自定义页面模板」 |
|
||||||
| [记得](https://github.com/yyliucha/plugin-important-dates) | `plugin-important-dates` | `/important-dates` | 重要日期 / 牵挂的人 / 爱车双视图页面,见下方「扩展页面」 |
|
| [记得](https://github.com/yyliucha/plugin-important-dates) | `plugin-important-dates` | `/important-dates` | 重要日期 / 牵挂的人 / 爱车双视图页面,见下方「扩展页面」 |
|
||||||
|
| [文章组件](https://github.com/acanyo/plugin-content-widgets) | `plugin-content-widgets` | 文章内 | 提示框、标签页、时间线等内容组件,主题已映射 `--xhhao-com-*` 变量,自动跟随明暗模式 |
|
||||||
| [API 扩展包](https://github.com/HowieHz/halo-plugin-extra-api) | `extra-api` | 全站 | 服务端字数统计、中英文混排排版、可选服务端代码高亮 |
|
| [API 扩展包](https://github.com/HowieHz/halo-plugin-extra-api) | `extra-api` | 全站 | 服务端字数统计、中英文混排排版、可选服务端代码高亮 |
|
||||||
|
|
||||||
> **注意**:插件需要单独安装,安装后主题会自动适配对应页面。若未安装某插件,对应页面或功能自动隐藏/降级,不会报错。
|
> **注意**:插件需要单独安装,安装后主题会自动适配对应页面。若未安装某插件,对应页面或功能自动隐藏/降级,不会报错。
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.1.10",
|
"version": "1.1.12",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.12.0"
|
"node": ">=22.12.0"
|
||||||
|
|||||||
@@ -236,24 +236,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processMomentsMedia(container) {
|
function processMomentsMedia(container) {
|
||||||
|
// 注意:不要用 <a> 包裹瞬间图片。九宫格布局依赖
|
||||||
|
// .wi-moments-page__card-media 的直接子元素数量(:has/:nth-child/:only-child),
|
||||||
|
// 每张图各自包一层 <a> 后,img 永远是「唯一子元素」,全部图片都会退化成单列大图。
|
||||||
|
// 直接把 img 本身作为 lightgallery 项即可(data-src 提供原图)。
|
||||||
var images = container.querySelectorAll('img');
|
var images = container.querySelectorAll('img');
|
||||||
images.forEach(function(img) {
|
images.forEach(function(img) {
|
||||||
var src = img.getAttribute('src');
|
var src = img.getAttribute('src');
|
||||||
if (!src) return;
|
if (!src) return;
|
||||||
|
img.classList.add('wi-lightgallery-item');
|
||||||
var parentA = img.closest('a');
|
if (!img.getAttribute('data-src')) {
|
||||||
if (parentA) {
|
img.setAttribute('data-src', src);
|
||||||
parentA.classList.add('wi-lightgallery-item');
|
|
||||||
if (!parentA.getAttribute('data-src')) {
|
|
||||||
parentA.setAttribute('data-src', src);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var a = document.createElement('a');
|
|
||||||
a.setAttribute('href', src);
|
|
||||||
a.setAttribute('data-src', src);
|
|
||||||
a.classList.add('wi-lightgallery-item');
|
|
||||||
img.parentNode.insertBefore(a, img);
|
|
||||||
a.appendChild(img);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
document.documentElement.setAttribute("data-color-scheme", isDark ? "dark" : "light");
|
document.documentElement.setAttribute("data-color-scheme", isDark ? "dark" : "light");
|
||||||
localStorage.setItem("wi-theme", isDark ? "dark" : "light");
|
localStorage.setItem("wi-theme", isDark ? "dark" : "light");
|
||||||
var tc = document.querySelector('meta[name="theme-color"]');
|
var tc = document.querySelector('meta[name="theme-color"]');
|
||||||
if (tc) tc.setAttribute("content", isDark ? "#1a1614" : "#faf7f2");
|
if (tc) tc.setAttribute("content", isDark ? "#1e1c1a" : "#faf7f2");
|
||||||
updateIcons();
|
updateIcons();
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
document.documentElement.classList.remove("wi-theme-transition");
|
document.documentElement.classList.remove("wi-theme-transition");
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const fragmentAttr = layoutFragment ? "html (head, content)" : undefined;
|
|||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
document.documentElement.setAttribute("data-color-scheme", "dark");
|
document.documentElement.setAttribute("data-color-scheme", "dark");
|
||||||
var tc = document.querySelector('meta[name="theme-color"]');
|
var tc = document.querySelector('meta[name="theme-color"]');
|
||||||
if (tc) tc.setAttribute("content", "#1a1614");
|
if (tc) tc.setAttribute("content", "#1e1c1a");
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.remove("dark");
|
document.documentElement.classList.remove("dark");
|
||||||
document.documentElement.setAttribute("data-color-scheme", "light");
|
document.documentElement.setAttribute("data-color-scheme", "light");
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
<article
|
<article
|
||||||
class="wi-id__car"
|
class="wi-id__car"
|
||||||
th:each="c : ${cars}"
|
th:each="c : ${cars}"
|
||||||
th:classappend="${(carSkinEnabled != null and carSkinEnabled) ? 'wi-id__car--' + c.skin : 'wi-id__car--neutral'}"
|
th:classappend="${carSkinEnabled != null and carSkinEnabled ? 'wi-id-skin-' + c.skin : 'wi-id-skin-neutral'}"
|
||||||
>
|
>
|
||||||
<div class="wi-id__car-head">
|
<div class="wi-id__car-head">
|
||||||
<button
|
<button
|
||||||
@@ -332,7 +332,11 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="wi-id__grid" th:unless="${#lists.isEmpty(people)}">
|
<div class="wi-id__grid" th:unless="${#lists.isEmpty(people)}">
|
||||||
<article class="wi-id__memo" th:each="p : ${people}">
|
<article class="wi-id__memo wi-id__memo--person" th:each="p : ${people}">
|
||||||
|
<div class="wi-id__memo-days" th:if="${p.daysUntil >= 0}">
|
||||||
|
<strong th:text="${p.daysUntil}">61</strong>
|
||||||
|
<span th:text="'天后'">天后</span>
|
||||||
|
</div>
|
||||||
<div class="wi-id__person">
|
<div class="wi-id__person">
|
||||||
<span class="wi-id__avatar">
|
<span class="wi-id__avatar">
|
||||||
<span
|
<span
|
||||||
@@ -367,22 +371,14 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="wi-id__memo-foot">
|
<p class="wi-id__memo-date wi-id__memo-date--foot">
|
||||||
<span class="wi-id__memo-date">
|
|
||||||
生日 <span th:text="${p.birthdayText}">1999-10-**</span>
|
生日 <span th:text="${p.birthdayText}">1999-10-**</span>
|
||||||
<span
|
<span
|
||||||
th:if="${p.nextSolarDate != null}"
|
th:if="${p.nextSolarDate != null}"
|
||||||
th:text="|(${p.nextSolarDate})|"
|
th:text="|(${p.nextSolarDate})|"
|
||||||
>(2026-10-**)</span
|
>(2026-10-**)</span
|
||||||
>
|
>
|
||||||
</span>
|
</p>
|
||||||
<span
|
|
||||||
class="wi-id__memo-count"
|
|
||||||
th:if="${p.daysUntil >= 0}"
|
|
||||||
th:text="|${p.daysUntil} 天后|"
|
|
||||||
>61 天后</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -732,14 +728,14 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
|
|
||||||
.wi-id__title {
|
.wi-id__title {
|
||||||
font-size: var(--text-4xl);
|
font-size: var(--text-4xl);
|
||||||
margin-bottom: var(--space-xs);
|
margin-bottom: var(--space-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__subtitle {
|
.wi-id__subtitle {
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
color: var(--ink-3);
|
color: var(--ink-3);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
margin-block-end: 0;
|
margin-bottom: var(--space-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-page-accent {
|
.wi-page-accent {
|
||||||
@@ -879,10 +875,22 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
|
|
||||||
.wi-id__grid {
|
.wi-id__grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
|
grid-template-columns: repeat(3, 1fr);
|
||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.wi-id__grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.wi-id__grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== 便签卡片(重要日期 / 人) ===== */
|
/* ===== 便签卡片(重要日期 / 人) ===== */
|
||||||
.wi-id__memo {
|
.wi-id__memo {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -984,6 +992,11 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
color: var(--ink-3);
|
color: var(--ink-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wi-id__memo--person .wi-id__person {
|
||||||
|
/* 右上角是倒计时数字,人物行留出空间避免重叠 */
|
||||||
|
padding-right: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
.wi-id__person {
|
.wi-id__person {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1022,23 +1035,12 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__memo-foot {
|
/* 生日一行放下:日期本身不折行,放不下时整行换行而不是把日期拆开 */
|
||||||
display: flex;
|
.wi-id__memo-date--foot {
|
||||||
align-items: baseline;
|
margin: 12px 0 0;
|
||||||
justify-content: space-between;
|
white-space: nowrap;
|
||||||
gap: 10px;
|
overflow: hidden;
|
||||||
margin-top: 10px;
|
text-overflow: ellipsis;
|
||||||
}
|
|
||||||
|
|
||||||
.wi-id__memo-foot .wi-id__memo-date {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wi-id__memo-count {
|
|
||||||
flex: none;
|
|
||||||
font-size: var(--text-sm);
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__badges {
|
.wi-id__badges {
|
||||||
@@ -1206,53 +1208,53 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 皮肤(插件设置「座驾卡片皮肤」开启时生效) */
|
/* 皮肤(插件设置「座驾卡片皮肤」开启时生效) */
|
||||||
.wi-id__car--cool {
|
.wi-id-skin-cool {
|
||||||
background: linear-gradient(150deg, #111827, #0f172a 55%, #1e3a8a);
|
background: linear-gradient(150deg, #111827, #0f172a 55%, #1e3a8a);
|
||||||
color: #e5e7eb;
|
color: #e5e7eb;
|
||||||
border-color: rgba(148, 163, 184, 0.4);
|
border-color: rgba(148, 163, 184, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cool .wi-id__car-name,
|
.wi-id-skin-cool .wi-id__car-name,
|
||||||
.wi-id__car--cool .wi-id__car-sub,
|
.wi-id-skin-cool .wi-id__car-sub,
|
||||||
.wi-id__car--cool .wi-id__badge {
|
.wi-id-skin-cool .wi-id__badge {
|
||||||
color: #e5e7eb;
|
color: #e5e7eb;
|
||||||
border-color: rgba(147, 197, 253, 0.6);
|
border-color: rgba(147, 197, 253, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cool .wi-id__event {
|
.wi-id-skin-cool .wi-id__event {
|
||||||
background: rgba(96, 165, 250, 0.18);
|
background: rgba(96, 165, 250, 0.18);
|
||||||
color: #bfdbfe;
|
color: #bfdbfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cool .wi-id__event.is-soon {
|
.wi-id-skin-cool .wi-id__event.is-soon {
|
||||||
background: rgba(251, 191, 36, 0.18);
|
background: rgba(251, 191, 36, 0.18);
|
||||||
color: #fde68a;
|
color: #fde68a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cool .wi-id__event.is-overdue {
|
.wi-id-skin-cool .wi-id__event.is-overdue {
|
||||||
background: rgba(248, 113, 113, 0.2);
|
background: rgba(248, 113, 113, 0.2);
|
||||||
color: #fecaca;
|
color: #fecaca;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cute {
|
.wi-id-skin-cute {
|
||||||
background: linear-gradient(150deg, #fff1f7, #ffe4ef 55%, #fdf2f8);
|
background: linear-gradient(150deg, #fff1f7, #ffe4ef 55%, #fdf2f8);
|
||||||
color: #831843;
|
color: #831843;
|
||||||
border-color: rgba(244, 114, 182, 0.4);
|
border-color: rgba(244, 114, 182, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cute .wi-id__car-name,
|
.wi-id-skin-cute .wi-id__car-name,
|
||||||
.wi-id__car--cute .wi-id__car-sub,
|
.wi-id-skin-cute .wi-id__car-sub,
|
||||||
.wi-id__car--cute .wi-id__badge {
|
.wi-id-skin-cute .wi-id__badge {
|
||||||
color: #831843;
|
color: #831843;
|
||||||
border-color: rgba(236, 72, 153, 0.55);
|
border-color: rgba(236, 72, 153, 0.55);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--cute .wi-id__event {
|
.wi-id-skin-cute .wi-id__event {
|
||||||
background: rgba(236, 72, 153, 0.12);
|
background: rgba(236, 72, 153, 0.12);
|
||||||
color: #9d174d;
|
color: #9d174d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-id__car--neutral {
|
.wi-id-skin-neutral {
|
||||||
background: var(--bg-raised);
|
background: var(--bg-raised);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1348,7 +1350,6 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.wi-id__grid,
|
|
||||||
.wi-id__cars {
|
.wi-id__cars {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
@@ -1356,5 +1357,9 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
.wi-id__memo-title {
|
.wi-id__memo-title {
|
||||||
margin-right: 56px;
|
margin-right: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wi-id__memo--person .wi-id__memo-title {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+97
-16
@@ -53,9 +53,13 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="wi-links__card"
|
class="wi-links__card"
|
||||||
|
th:with="verification=${link.status?.verification},
|
||||||
|
accessState=${verification?.access?.state != null ? verification.access.state.name() : null},
|
||||||
|
backlinkState=${verification?.backlink != null and verification.backlink.state != null ? verification.backlink.state.name() : null}"
|
||||||
>
|
>
|
||||||
<div class="wi-links__card-glow"></div>
|
<div class="wi-links__card-glow"></div>
|
||||||
<div class="wi-links__card-inner">
|
<div class="wi-links__card-inner">
|
||||||
|
<span class="wi-links__avatar-wrap">
|
||||||
<img
|
<img
|
||||||
th:if="${link.spec.logo}"
|
th:if="${link.spec.logo}"
|
||||||
th:src="${link.spec.logo}"
|
th:src="${link.spec.logo}"
|
||||||
@@ -70,6 +74,18 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
th:text="${#strings.substring(link.spec.displayName, 0, 1)}"
|
th:text="${#strings.substring(link.spec.displayName, 0, 1)}"
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 反链 / 可达性检测徽章(plugin-links 后台「友链检测」产生,未检测过则不显示) -->
|
||||||
|
<span
|
||||||
|
class="wi-links__check wi-links__check--ok"
|
||||||
|
th:if="${accessState == 'ACCESSIBLE' and backlinkState != 'MISSING'}"
|
||||||
|
th:title="${backlinkState == 'FOUND' ? '访问正常 · 反链有效' : '访问正常'}"
|
||||||
|
></span>
|
||||||
|
<span
|
||||||
|
class="wi-links__check wi-links__check--bad"
|
||||||
|
th:if="${accessState == 'INACCESSIBLE' or backlinkState == 'MISSING'}"
|
||||||
|
th:title="${accessState == 'INACCESSIBLE' ? '站点访问异常' : '未检测到反链'}"
|
||||||
|
></span>
|
||||||
|
</span>
|
||||||
<div class="wi-links__info">
|
<div class="wi-links__info">
|
||||||
<span
|
<span
|
||||||
class="wi-links__name"
|
class="wi-links__name"
|
||||||
@@ -87,26 +103,37 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
友链申请:表单 POST 到插件的 /links/apply/submit,插件以 303 回跳 /links,
|
||||||
|
并带上 applied(success / error / disabled)、message、field、value 四个查询参数。
|
||||||
|
|
||||||
|
注意(踩过坑):th:attr 的赋值里不能调用 #lists 等表达式对象的方法,
|
||||||
|
Thymeleaf 会对 th:attr 走受限求值并抛
|
||||||
|
"Instantiation of new objects and access to static classes or parameters is forbidden"。
|
||||||
|
取值逻辑一律先在 th:with 里算成变量,再用 th:value 之类的单值属性输出。
|
||||||
|
-->
|
||||||
<div
|
<div
|
||||||
class="wi-links__apply"
|
class="wi-links__apply"
|
||||||
th:if="${theme.config?.links?.links_apply_form_enabled != false}"
|
th:if="${theme.config?.links?.links_apply_form_enabled != false}"
|
||||||
th:with="applied=${param.applied != null and !#lists.isEmpty(param.applied) and param.applied[0] == 'true'},
|
th:with="appliedList=${param?.applied},
|
||||||
applyMsg=${param.message != null and !#lists.isEmpty(param.message) ? param.message[0] : null}"
|
applied=${appliedList != null and appliedList.length > 0 ? appliedList[0] : null},
|
||||||
|
messageList=${param?.message},
|
||||||
|
applyMsg=${messageList != null and messageList.length > 0 ? messageList[0] : null},
|
||||||
|
fieldList=${param?.field},
|
||||||
|
applyField=${fieldList != null and fieldList.length > 0 ? fieldList[0] : null},
|
||||||
|
valueList=${param?.value},
|
||||||
|
applyValue=${valueList != null and valueList.length > 0 ? valueList[0] : null}"
|
||||||
>
|
>
|
||||||
<h2 class="wi-links__apply-title" th:text="'申请友链'">申请友链</h2>
|
<h2 class="wi-links__apply-title" th:text="'申请友链'">申请友链</h2>
|
||||||
<p
|
<p
|
||||||
class="wi-links__apply-result"
|
class="wi-links__apply-result"
|
||||||
th:if="${applied}"
|
th:if="${applied != null}"
|
||||||
th:text="'申请已提交,等待站长审核 🌙'"
|
th:classappend="${applied == 'success'} ? 'wi-links-check-ok' : 'wi-links-check-error'"
|
||||||
|
th:text="${applyMsg != null ? applyMsg : '申请已提交,等待站长审核 🌙'}"
|
||||||
role="status"
|
role="status"
|
||||||
></p>
|
></p>
|
||||||
<p
|
|
||||||
class="wi-links__apply-result wi-links__apply-result--error"
|
|
||||||
th:if="${not applied and applyMsg != null}"
|
|
||||||
th:text="${applyMsg}"
|
|
||||||
role="alert"
|
|
||||||
></p>
|
|
||||||
|
|
||||||
|
<th:block th:unless="${applied == 'disabled'}">
|
||||||
<form
|
<form
|
||||||
class="wi-links__apply-form"
|
class="wi-links__apply-form"
|
||||||
method="post"
|
method="post"
|
||||||
@@ -116,11 +143,24 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
<div class="wi-links__apply-row">
|
<div class="wi-links__apply-row">
|
||||||
<label class="wi-links__apply-field">
|
<label class="wi-links__apply-field">
|
||||||
<span th:text="'站点名称 *'">站点名称 *</span>
|
<span th:text="'站点名称 *'">站点名称 *</span>
|
||||||
<input type="text" name="displayName" required maxlength="50" placeholder="你的站点名称" th:attr="value=${param.value != null and !#lists.isEmpty(param.value) ? param.value[0] : ''}" />
|
<input
|
||||||
|
type="text"
|
||||||
|
name="displayName"
|
||||||
|
required
|
||||||
|
maxlength="50"
|
||||||
|
placeholder="你的站点名称"
|
||||||
|
th:value="${applyField == 'displayName' ? applyValue : null}"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="wi-links__apply-field">
|
<label class="wi-links__apply-field">
|
||||||
<span th:text="'站点链接 *'">站点链接 *</span>
|
<span th:text="'站点链接 *'">站点链接 *</span>
|
||||||
<input type="url" name="url" required placeholder="https://" />
|
<input
|
||||||
|
type="url"
|
||||||
|
name="url"
|
||||||
|
required
|
||||||
|
placeholder="https://"
|
||||||
|
th:value="${applyField == 'url' ? applyValue : null}"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="wi-links__apply-row">
|
<div class="wi-links__apply-row">
|
||||||
@@ -160,12 +200,19 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
title="点击刷新验证码"
|
title="点击刷新验证码"
|
||||||
onclick="this.src=this.src.split('?')[0]+'?ts='+Date.now()"
|
onclick="this.src=this.src.split('?')[0]+'?ts='+Date.now()"
|
||||||
th:onerror="|this.closest('.wi-links__apply').classList.add('wi-links__apply--unavailable')|"
|
onerror="var c=this.closest('.wi-links__apply');if(c)c.classList.add('wi-links__apply--unavailable')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="wi-links__apply-submit" type="submit" th:text="'提交申请'">提交申请</button>
|
<button
|
||||||
|
class="wi-links__apply-submit"
|
||||||
|
type="submit"
|
||||||
|
th:text="'提交申请'"
|
||||||
|
>
|
||||||
|
提交申请
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
</th:block>
|
||||||
<p
|
<p
|
||||||
class="wi-links__apply-unavailable-tip"
|
class="wi-links__apply-unavailable-tip"
|
||||||
th:text="'友链申请暂未开放。'"
|
th:text="'友链申请暂未开放。'"
|
||||||
@@ -299,11 +346,18 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
margin-bottom: var(--space-md);
|
margin-bottom: var(--space-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-links__apply-result--error {
|
.wi-links__apply-result--ok,
|
||||||
|
.wi-links-check-ok {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wi-links__apply-result--error,
|
||||||
|
.wi-links-check-error {
|
||||||
color: #e6162d;
|
color: #e6162d;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark .wi-links__apply-result--error {
|
html.dark .wi-links__apply-result--error,
|
||||||
|
html.dark .wi-links-check-error {
|
||||||
color: #ff6b6b;
|
color: #ff6b6b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,6 +568,13 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
border-color: color-mix(in srgb, var(--accent) 40%, var(--glass-border));
|
border-color: color-mix(in srgb, var(--accent) 40%, var(--glass-border));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wi-links__avatar-wrap {
|
||||||
|
position: relative;
|
||||||
|
flex: none;
|
||||||
|
display: inline-flex;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.wi-links__avatar {
|
.wi-links__avatar {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
@@ -524,6 +585,26 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
transition: transform var(--duration-normal) var(--ease-out-expo);
|
transition: transform var(--duration-normal) var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 反链 / 可达性检测徽章:绿色正常,红色异常 */
|
||||||
|
.wi-links__check {
|
||||||
|
position: absolute;
|
||||||
|
right: -3px;
|
||||||
|
bottom: -3px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid var(--bg);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wi-links__check--ok {
|
||||||
|
background: #22c55e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wi-links__check--bad {
|
||||||
|
background: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
.wi-links__card:hover .wi-links__avatar {
|
.wi-links__card:hover .wi-links__avatar {
|
||||||
transform: scale(1.08);
|
transform: scale(1.08);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -715,8 +715,9 @@ import LightGallery from "../components/LightGallery.astro";
|
|||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-moments-page__masonry-media:has(.wi-moments-page__masonry-image:nth-child(4)) {
|
/* 微信九宫格规则:4 张时 2x2 排布 */
|
||||||
grid-template-columns: repeat(3, 1fr);
|
.wi-moments-page__masonry-media:has(.wi-moments-page__masonry-image:nth-child(4)):not(:has(.wi-moments-page__masonry-image:nth-child(5))) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-moments-page__masonry-footer {
|
.wi-moments-page__masonry-footer {
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
.wi-messageboard {
|
.wi-messageboard {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--space-lg);
|
gap: var(--space-lg);
|
||||||
margin-top: calc(-1 * 100px - var(--space-lg));
|
|
||||||
padding-top: 100px;
|
|
||||||
padding-block-end: 1rem;
|
padding-block-end: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +68,8 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
opacity: 0.18;
|
opacity: 0.18;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -0.15em;
|
top: 0.05em;
|
||||||
left: 0.15em;
|
left: 0.2em;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -897,15 +897,15 @@ import LightGallery from "../components/LightGallery.astro";
|
|||||||
|
|
||||||
.wi-post__body {
|
.wi-post__body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 1.05rem;
|
font-size: clamp(1.05rem, 1rem + 0.25vw, 1.15rem);
|
||||||
line-height: 1.8;
|
line-height: 1.85;
|
||||||
color: #3d3530;
|
color: #3d3530;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark .wi-post__body {
|
html.dark .wi-post__body {
|
||||||
color: #d4cdc4;
|
color: #d9d2c9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 正文本身及内部元素样式统一放在全局样式 src/styles/_content.scss,
|
/* 正文本身及内部元素样式统一放在全局样式 src/styles/_content.scss,
|
||||||
|
|||||||
+14
-5
@@ -94,7 +94,7 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* 头部结构与订阅/图库/友链等页面保持一致:居中标题 + 副标题 + 强调线 */
|
/* 头部结构与订阅/图库/友链/记得等页面保持一致:居中标题 + 副标题 + 强调线 */
|
||||||
.wi-weread {
|
.wi-weread {
|
||||||
padding-block: 1rem 3rem;
|
padding-block: 1rem 3rem;
|
||||||
}
|
}
|
||||||
@@ -106,14 +106,23 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
|
|
||||||
.wi-weread__title {
|
.wi-weread__title {
|
||||||
font-size: var(--text-4xl);
|
font-size: var(--text-4xl);
|
||||||
margin-bottom: var(--space-xs);
|
margin-bottom: var(--space-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-weread__subtitle {
|
.wi-weread__subtitle {
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
color: var(--ink-3);
|
color: var(--ink-3);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
margin-block-end: 0;
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wi-page-accent {
|
||||||
|
display: block;
|
||||||
|
width: 48px;
|
||||||
|
height: 3px;
|
||||||
|
margin: var(--space-sm) auto 0;
|
||||||
|
border-radius: 9999px;
|
||||||
|
background: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wi-weread__shelf {
|
.wi-weread__shelf {
|
||||||
@@ -188,7 +197,7 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
--wr-ink: var(--ink);
|
--wr-ink: var(--ink);
|
||||||
--wr-muted: var(--ink-2);
|
--wr-muted: var(--ink-2);
|
||||||
--wr-bg: var(--bg-raised);
|
--wr-bg: var(--bg-raised);
|
||||||
--wr-line: #4a4238;
|
--wr-line: #4a443c;
|
||||||
--wr-fill: color-mix(in srgb, var(--ink) 8%, transparent);
|
--wr-fill: color-mix(in srgb, var(--ink) 8%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +216,7 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
--wr-ink: var(--ink);
|
--wr-ink: var(--ink);
|
||||||
--wr-muted: var(--ink-2);
|
--wr-muted: var(--ink-2);
|
||||||
--wr-bg: var(--bg-raised);
|
--wr-bg: var(--bg-raised);
|
||||||
--wr-line: #4a4238;
|
--wr-line: #4a443c;
|
||||||
--wr-fill: color-mix(in srgb, var(--ink) 8%, transparent);
|
--wr-fill: color-mix(in srgb, var(--ink) 8%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-19
@@ -21,24 +21,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html.dark {
|
html.dark {
|
||||||
--bg: #1a1614;
|
/* 暗色基准:偏中性、只保留一丝暖意,避免大面积黄褐底色带来的闷感 */
|
||||||
--bg-raised: #26211d;
|
--bg: #1e1c1a;
|
||||||
--bg-overlay: rgba(26, 22, 20, 0.85);
|
--bg-raised: #292623;
|
||||||
--ink: #ede6de;
|
--bg-overlay: rgba(30, 28, 26, 0.85);
|
||||||
--ink-2: #a2978c;
|
--ink: #e9e4dd;
|
||||||
|
--ink-2: #aaa096;
|
||||||
/* 深色背景下人眼对低对比更敏感,次要文字与分隔线比浅色模式略提亮 */
|
/* 深色背景下人眼对低对比更敏感,次要文字与分隔线比浅色模式略提亮 */
|
||||||
--ink-3: #6f6459;
|
--ink-3: #7c7268;
|
||||||
--rule: #38322b;
|
--rule: #3b362f;
|
||||||
--accent: #e8955f;
|
--accent: #e89a64;
|
||||||
--accent-hover: #f0a872;
|
--accent-hover: #f2ad79;
|
||||||
--accent-bg: #2a1e16;
|
--accent-bg: #2c231b;
|
||||||
--mist-pink: #2e2420;
|
--mist-pink: #2e2823;
|
||||||
--sea-salt: #2e2822;
|
--sea-salt: #302b26;
|
||||||
--caramel: #a08878;
|
--caramel: #a38b7b;
|
||||||
--glass-bg: rgba(26, 22, 20, 0.72);
|
--glass-bg: rgba(30, 28, 26, 0.72);
|
||||||
--glass-border: rgba(46, 40, 34, 0.5);
|
--glass-border: rgba(59, 54, 47, 0.5);
|
||||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
|
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.24);
|
||||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.25);
|
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||||
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.35);
|
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
--shadow-glow: 0 0 40px rgba(232, 149, 95, 0.12);
|
--shadow-glow: 0 0 40px rgba(232, 154, 100, 0.12);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,37 +33,37 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: clamp(1.45rem, 1.3rem + 0.7vw, 1.75rem);
|
font-size: clamp(1.6rem, 1.4rem + 1vw, 2rem);
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
margin-bottom: 0.7em;
|
margin-bottom: 0.7em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: clamp(1.3rem, 1.2rem + 0.5vw, 1.5rem);
|
font-size: clamp(1.42rem, 1.3rem + 0.6vw, 1.68rem);
|
||||||
margin-top: 1.9em;
|
margin-top: 1.9em;
|
||||||
margin-bottom: 0.65em;
|
margin-bottom: 0.65em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size: clamp(1.15rem, 1.08rem + 0.35vw, 1.28rem);
|
font-size: clamp(1.24rem, 1.16rem + 0.4vw, 1.4rem);
|
||||||
margin-top: 1.7em;
|
margin-top: 1.7em;
|
||||||
margin-bottom: 0.6em;
|
margin-bottom: 0.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-size: clamp(1.05rem, 1rem + 0.25vw, 1.13rem);
|
font-size: clamp(1.1rem, 1.05rem + 0.25vw, 1.2rem);
|
||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
font-size: 1rem;
|
font-size: 1.04rem;
|
||||||
margin-top: 1.4em;
|
margin-top: 1.4em;
|
||||||
margin-bottom: 0.45em;
|
margin-bottom: 0.45em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h6 {
|
h6 {
|
||||||
font-size: 0.95rem;
|
font-size: 0.98rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--ink-3);
|
color: var(--ink-3);
|
||||||
margin-top: 1.4em;
|
margin-top: 1.4em;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/* ==========================================================================
|
||||||
|
「文章组件」插件(plugin-content-widgets)主题适配
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
插件自带样式与挂载逻辑,主题只需要把它的 --xhhao-com-* 变量
|
||||||
|
映射到主题变量上:组件即可自动跟随主题的暖色 / 暗色模式。
|
||||||
|
变量清单见插件 README:https://github.com/acanyo/plugin-content-widgets
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--xhhao-com-text-1: var(--ink);
|
||||||
|
--xhhao-com-text-2: var(--ink-2);
|
||||||
|
--xhhao-com-bg: var(--bg);
|
||||||
|
--xhhao-com-bg-card: var(--bg-raised);
|
||||||
|
--xhhao-com-bg-2: var(--bg-raised);
|
||||||
|
--xhhao-com-border: var(--rule);
|
||||||
|
--xhhao-com-primary: var(--accent);
|
||||||
|
--xhhao-com-shadow: rgb(15 23 42 / 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 组件自带的浅色 fallback 偏冷灰,暗色下显突兀;
|
||||||
|
变量跟随主题后,暗色模式自动生效,无需单独覆盖。 */
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
@use 'comment';
|
@use 'comment';
|
||||||
@use 'search';
|
@use 'search';
|
||||||
@use 'lightgallery';
|
@use 'lightgallery';
|
||||||
|
@use 'widgets';
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ spec:
|
|||||||
description: 微信读书书架(依赖微信读书插件)
|
description: 微信读书书架(依赖微信读书插件)
|
||||||
screenshot:
|
screenshot:
|
||||||
file: weread.html
|
file: weread.html
|
||||||
version: "1.1.10"
|
version: "1.1.12"
|
||||||
requires: ">=2.24.0"
|
requires: ">=2.24.0"
|
||||||
license:
|
license:
|
||||||
- name: "GPL-3.0"
|
- name: "GPL-3.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user