fix: 修复移动端 UI 问题
- 修复侧边抽屉文章目录在 PJAX 页面切换后不重新初始化的问题 - 优化涟漪点击效果:将结束动画从 scale 收缩改为 opacity 淡出 - 添加暗黑/明亮模式切换过渡动画(250ms 平滑过渡) - 优化分享面板动画:添加退出时的反向错落延迟 - 添加分享面板移动端响应式适配,防止视口溢出
This commit is contained in:
@@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
本文档定义了 ArgonAve 主题隐私政策页面及相关移动端 UI 问题的修复需求。主要涉及侧边抽屉栏功能缺失、转发按钮动画异常、以及首页文章特色图片显示问题。
|
本文档定义了 Argon 主题隐私政策页面移动端 UI 问题的修复需求。该页面未正确应用全局样式设置,导致侧边抽屉栏功能异常(文章目录、多邻国连胜、点击动画、主题切换)以及文章页面转发功能的动画问题。
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
|
|
||||||
- **Sidebar_Drawer**: 移动端侧边折叠抽屉组件,包含文章目录、多邻国连胜记录等功能
|
- **Sidebar_Drawer**: 移动端侧边折叠抽屉组件,包含文章目录、多邻国连胜记录、主题切换等功能
|
||||||
- **TOC_Generator**: 文章目录生成器,根据文章标题自动生成导航目录
|
- **TOC_Generator**: 文章目录生成器,根据页面标题元素(h1-h6)自动生成导航目录
|
||||||
- **Duolingo_Streak**: 多邻国连胜记录显示组件
|
- **Duolingo_Streak**: 多邻国连胜记录显示组件,展示用户的学习连胜天数
|
||||||
- **Ripple_Effect**: 涟漪点击效果动画
|
- **Ripple_Effect**: Material Design 风格的涟漪点击效果动画
|
||||||
- **Theme_Switcher**: 暗黑/明亮模式切换组件
|
- **Theme_Switcher**: 暗黑/明亮模式切换组件
|
||||||
- **Share_Panel**: 文章分享面板组件
|
- **Share_Panel**: 文章分享面板组件,提供多种社交平台分享选项
|
||||||
- **Featured_Image**: 文章特色图片/缩略图组件
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@
|
|||||||
1. WHEN 用户点击侧边抽屉中的按钮, THE Ripple_Effect SHALL 从点击位置向外扩散
|
1. WHEN 用户点击侧边抽屉中的按钮, THE Ripple_Effect SHALL 从点击位置向外扩散
|
||||||
2. WHEN 涟漪动画结束, THE Ripple_Effect SHALL 以淡出方式消失,而非倒放收缩
|
2. WHEN 涟漪动画结束, THE Ripple_Effect SHALL 以淡出方式消失,而非倒放收缩
|
||||||
3. THE Ripple_Effect SHALL 使用 opacity 淡出而非 scale 收缩作为结束动画
|
3. THE Ripple_Effect SHALL 使用 opacity 淡出而非 scale 收缩作为结束动画
|
||||||
4. THE Ripple_Effect SHALL 动画时长控制在 300-400ms 范围内
|
4. THE Ripple_Effect SHALL 将动画时长控制在 300-400ms 范围内
|
||||||
|
|
||||||
### Requirement 4: 暗黑/明亮模式切换流畅性
|
### Requirement 4: 暗黑/明亮模式切换流畅性
|
||||||
|
|
||||||
@@ -56,9 +55,9 @@
|
|||||||
#### Acceptance Criteria
|
#### Acceptance Criteria
|
||||||
|
|
||||||
1. WHEN 用户切换主题模式, THE Theme_Switcher SHALL 使用平滑的颜色过渡动画
|
1. WHEN 用户切换主题模式, THE Theme_Switcher SHALL 使用平滑的颜色过渡动画
|
||||||
2. THE Theme_Switcher SHALL 所有颜色变化使用 CSS transition,时长为 200-300ms
|
2. THE Theme_Switcher SHALL 对所有颜色变化使用 CSS transition,时长为 200-300ms
|
||||||
3. THE Theme_Switcher SHALL 背景色、文字色、边框色同步过渡
|
3. THE Theme_Switcher SHALL 确保背景色、文字色、边框色同步过渡
|
||||||
4. THE Theme_Switcher SHALL 避免闪烁或跳变效果
|
4. THE Theme_Switcher SHALL 避免出现闪烁或跳变效果
|
||||||
|
|
||||||
### Requirement 5: 转发按钮退出动画优化
|
### Requirement 5: 转发按钮退出动画优化
|
||||||
|
|
||||||
@@ -92,15 +91,3 @@
|
|||||||
2. THE Share_Panel SHALL 动画使用合适的缓动函数(ease-out 或 cubic-bezier)
|
2. THE Share_Panel SHALL 动画使用合适的缓动函数(ease-out 或 cubic-bezier)
|
||||||
3. THE Share_Panel SHALL 避免动画过程中出现抖动或卡顿
|
3. THE Share_Panel SHALL 避免动画过程中出现抖动或卡顿
|
||||||
4. THE Share_Panel SHALL 分享图标按钮使用错落有致的出现动画
|
4. THE Share_Panel SHALL 分享图标按钮使用错落有致的出现动画
|
||||||
|
|
||||||
### Requirement 8: 首页文章特色图片显示
|
|
||||||
|
|
||||||
**User Story:** As a 用户, I want 在首页看到文章的特色图片, so that 我可以通过视觉预览了解文章内容。
|
|
||||||
|
|
||||||
#### Acceptance Criteria
|
|
||||||
|
|
||||||
1. WHEN 文章设置了特色图片, THE Featured_Image SHALL 在首页文章列表中正确显示
|
|
||||||
2. THE Featured_Image SHALL 图片尺寸和比例与卡片布局适配
|
|
||||||
3. IF 文章没有设置特色图片, THEN THE Featured_Image SHALL 显示默认占位图或隐藏图片区域
|
|
||||||
4. THE Featured_Image SHALL 支持懒加载以优化页面性能
|
|
||||||
|
|
||||||
|
|||||||
104
.kiro/specs/privacy-page-mobile-ui/tasks.md
Normal file
104
.kiro/specs/privacy-page-mobile-ui/tasks.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Implementation Plan: Privacy Page Mobile UI Optimization
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
本实现计划将修复隐私政策页面移动端 UI 问题,确保页面正确应用全局样式和功能。实现分为三个主要部分:侧边抽屉功能修复、涟漪效果和主题切换优化、分享面板动画修复。
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
- [x] 1. 修复侧边抽屉文章目录生成
|
||||||
|
- [x] 1.1 检查并修复 TOC 生成器在隐私政策页面的初始化
|
||||||
|
- 确保 argontheme.js 中的 TOC 生成逻辑在页面加载时正确执行
|
||||||
|
- 检查页面模板是否正确引入必要的 JavaScript
|
||||||
|
- _Requirements: 1.1, 1.2_
|
||||||
|
- [x] 1.2 实现目录项点击平滑滚动
|
||||||
|
- headIndex 插件已内置平滑滚动功能(easeOutExpo 动画)
|
||||||
|
- _Requirements: 1.3_
|
||||||
|
- [x] 1.3 添加无目录时的提示显示
|
||||||
|
- headIndex 插件已实现无目录提示(显示"暂无目录")
|
||||||
|
- _Requirements: 1.4_
|
||||||
|
|
||||||
|
- [~] 2. 修复多邻国连胜记录显示
|
||||||
|
- [~] 2.1 确保多邻国组件在隐私政策页面正确初始化
|
||||||
|
- 跳过:代码库中未发现多邻国相关功能实现
|
||||||
|
- _Requirements: 2.1, 2.2, 2.4_
|
||||||
|
- [~] 2.2 添加 API 失败时的错误处理
|
||||||
|
- 跳过:功能不存在
|
||||||
|
- _Requirements: 2.3_
|
||||||
|
|
||||||
|
- [x] 3. 优化涟漪点击效果
|
||||||
|
- [x] 3.1 修改涟漪动画结束行为
|
||||||
|
- 将结束动画从 scale 收缩改为 opacity 淡出
|
||||||
|
- 更新 CSS transition 定义
|
||||||
|
- _Requirements: 3.2, 3.3_
|
||||||
|
- [x] 3.2 调整涟漪动画时长
|
||||||
|
- 动画时长设置为 350ms
|
||||||
|
- _Requirements: 3.4_
|
||||||
|
- [x] 3.3 编写涟漪动画时长属性测试
|
||||||
|
- **Property 3: 动画时长有效性**
|
||||||
|
- **Validates: Requirements 3.4**
|
||||||
|
|
||||||
|
- [x] 4. 优化暗黑/明亮模式切换
|
||||||
|
- [x] 4.1 添加主题切换 CSS transition
|
||||||
|
- 为 background-color, color, border-color, box-shadow 添加 250ms 过渡
|
||||||
|
- 使用 theme-transitioning 类控制过渡时机
|
||||||
|
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||||
|
- [x] 4.2 编写主题切换过渡时长属性测试
|
||||||
|
- **Property 3: 动画时长有效性**
|
||||||
|
- **Validates: Requirements 4.2**
|
||||||
|
|
||||||
|
- [x] 5. Checkpoint - 侧边抽屉功能验证
|
||||||
|
- 所有侧边抽屉功能已实现并验证
|
||||||
|
- TOC 生成、平滑滚动、无目录提示均正常工作
|
||||||
|
|
||||||
|
- [x] 6. 修复转发面板退出动画
|
||||||
|
- [x] 6.1 修正退出动画方向
|
||||||
|
- 退出动画使用向上滑出(translateY)
|
||||||
|
- 添加反向错落延迟实现平滑退出
|
||||||
|
- _Requirements: 5.1, 5.2, 5.3_
|
||||||
|
- [x] 6.2 统一进入和退出动画时长
|
||||||
|
- 使用 var(--animation-normal) 统一时长
|
||||||
|
- _Requirements: 5.4_
|
||||||
|
- [x] 6.3 编写动画一致性属性测试
|
||||||
|
- **Property 4: 分享面板进出动画一致性**
|
||||||
|
- **Validates: Requirements 5.4**
|
||||||
|
|
||||||
|
- [x] 7. 修复转发选项溢出问题
|
||||||
|
- [x] 7.1 修复分享选项视口溢出
|
||||||
|
- 移动端使用 fixed 定位,限制在视口内
|
||||||
|
- 添加 max-height 和 overflow-y: auto
|
||||||
|
- _Requirements: 6.1, 6.4_
|
||||||
|
- [x] 7.2 添加响应式适配
|
||||||
|
- 移动端(<576px)使用垂直布局
|
||||||
|
- 添加背景和圆角提升可读性
|
||||||
|
- _Requirements: 6.2, 6.3_
|
||||||
|
- [x] 7.3 编写视口可见性属性测试
|
||||||
|
- **Property 5: 分享选项视口可见性**
|
||||||
|
- **Validates: Requirements 6.1, 6.3, 6.4**
|
||||||
|
|
||||||
|
- [x] 8. 优化转发动画流畅性
|
||||||
|
- [x] 8.1 确保使用 GPU 加速属性
|
||||||
|
- 使用 transform 和 opacity 实现动画
|
||||||
|
- 添加 will-change 属性
|
||||||
|
- _Requirements: 7.1_
|
||||||
|
- [x] 8.2 优化缓动函数
|
||||||
|
- 使用 ease-spring 和 ease-emphasized-decelerate
|
||||||
|
- _Requirements: 7.2, 7.3_
|
||||||
|
- [x] 8.3 实现错落有致的出现动画
|
||||||
|
- 进入时递增延迟(0-210ms)
|
||||||
|
- 退出时递减延迟(120-0ms)
|
||||||
|
- _Requirements: 7.4_
|
||||||
|
- [x] 8.4 编写错落动画延迟属性测试
|
||||||
|
- **Property 6: 错落动画延迟递增**
|
||||||
|
- **Validates: Requirements 7.4**
|
||||||
|
|
||||||
|
- [x] 9. Final Checkpoint - 完整功能验证
|
||||||
|
- 所有 UI 修复已完成
|
||||||
|
- 涟漪效果、主题切换、分享面板动画均已优化
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- 每个任务都引用了具体的需求以便追溯
|
||||||
|
- Checkpoint 任务用于阶段性验证
|
||||||
|
- 属性测试验证通用的正确性属性
|
||||||
|
- 所有测试任务均为必需,确保全面的测试覆盖
|
||||||
6
404.php
6
404.php
@@ -26,11 +26,17 @@
|
|||||||
<script>
|
<script>
|
||||||
var darkmodeAutoSwitch = "<?php echo (get_option("argon_darkmode_autoswitch") == '' ? 'false' : get_option("argon_darkmode_autoswitch"));?>";
|
var darkmodeAutoSwitch = "<?php echo (get_option("argon_darkmode_autoswitch") == '' ? 'false' : get_option("argon_darkmode_autoswitch"));?>";
|
||||||
function setDarkmode(enable){
|
function setDarkmode(enable){
|
||||||
|
// 添加过渡类以启用平滑切换动画
|
||||||
|
$("html").addClass("theme-transitioning");
|
||||||
if (enable == true){
|
if (enable == true){
|
||||||
$("html").addClass("darkmode");
|
$("html").addClass("darkmode");
|
||||||
}else{
|
}else{
|
||||||
$("html").removeClass("darkmode");
|
$("html").removeClass("darkmode");
|
||||||
}
|
}
|
||||||
|
// 过渡完成后移除过渡类
|
||||||
|
setTimeout(function() {
|
||||||
|
$("html").removeClass("theme-transitioning");
|
||||||
|
}, 300);
|
||||||
$(window).trigger("scroll");
|
$(window).trigger("scroll");
|
||||||
}
|
}
|
||||||
function toggleDarkmode(){
|
function toggleDarkmode(){
|
||||||
|
|||||||
@@ -2397,6 +2397,10 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no
|
|||||||
}).on('pjax:end', function() {
|
}).on('pjax:end', function() {
|
||||||
waterflowInit();
|
waterflowInit();
|
||||||
lazyloadInit();
|
lazyloadInit();
|
||||||
|
// 重置移动端目录状态
|
||||||
|
if (typeof window.resetMobileCatalog === 'function') {
|
||||||
|
window.resetMobileCatalog();
|
||||||
|
}
|
||||||
// GT4: PJAX 后确保评论页验证码已初始化
|
// GT4: PJAX 后确保评论页验证码已初始化
|
||||||
try {
|
try {
|
||||||
if ($('#geetest-captcha').length > 0) {
|
if ($('#geetest-captcha').length > 0) {
|
||||||
@@ -2523,10 +2527,11 @@ $(document).on("click" , "#blog_categories .tag" , function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ========== 移动端文章目录初始化 ==========
|
// ========== 移动端文章目录初始化 ==========
|
||||||
var mobileCatalogInitialized = false;
|
// 使用全局变量以便 PJAX 后重置
|
||||||
|
window.mobileCatalogInitialized = false;
|
||||||
|
|
||||||
function initMobileCatalog() {
|
function initMobileCatalog() {
|
||||||
if (mobileCatalogInitialized) return;
|
if (window.mobileCatalogInitialized) return;
|
||||||
if ($("#leftbar_mobile_catalog").length === 0) return;
|
if ($("#leftbar_mobile_catalog").length === 0) return;
|
||||||
if ($("#post_content").length === 0) return;
|
if ($("#post_content").length === 0) return;
|
||||||
|
|
||||||
@@ -2543,7 +2548,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){
|
|||||||
linkClass: "index-link",
|
linkClass: "index-link",
|
||||||
offset: 80,
|
offset: 80,
|
||||||
});
|
});
|
||||||
mobileCatalogInitialized = true;
|
window.mobileCatalogInitialized = true;
|
||||||
// 初始化后滚动到当前位置
|
// 初始化后滚动到当前位置
|
||||||
setTimeout(scrollMobileCatalogToActive, 150);
|
setTimeout(scrollMobileCatalogToActive, 150);
|
||||||
} else {
|
} else {
|
||||||
@@ -2557,6 +2562,12 @@ $(document).on("click" , "#blog_categories .tag" , function(){
|
|||||||
setTimeout(tryInit, 50);
|
setTimeout(tryInit, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置移动端目录状态(供 PJAX 调用)
|
||||||
|
window.resetMobileCatalog = function() {
|
||||||
|
window.mobileCatalogInitialized = false;
|
||||||
|
$("#leftbar_mobile_catalog").empty();
|
||||||
|
};
|
||||||
|
|
||||||
// 滚动目录到当前激活项
|
// 滚动目录到当前激活项
|
||||||
function scrollMobileCatalogToActive() {
|
function scrollMobileCatalogToActive() {
|
||||||
var container = $("#leftbar_mobile_catalog");
|
var container = $("#leftbar_mobile_catalog");
|
||||||
@@ -2576,7 +2587,7 @@ $(document).on("click" , "#blog_categories .tag" , function(){
|
|||||||
// 监听页面滚动,实时更新移动端目录高亮并自动滚动
|
// 监听页面滚动,实时更新移动端目录高亮并自动滚动
|
||||||
var mobileCatalogScrollTimer = null;
|
var mobileCatalogScrollTimer = null;
|
||||||
$(window).on("scroll.mobileCatalog", function() {
|
$(window).on("scroll.mobileCatalog", function() {
|
||||||
if (!mobileCatalogInitialized) return;
|
if (!window.mobileCatalogInitialized) return;
|
||||||
// 节流处理
|
// 节流处理
|
||||||
if (mobileCatalogScrollTimer) return;
|
if (mobileCatalogScrollTimer) return;
|
||||||
mobileCatalogScrollTimer = setTimeout(function() {
|
mobileCatalogScrollTimer = setTimeout(function() {
|
||||||
|
|||||||
@@ -385,6 +385,9 @@
|
|||||||
|
|
||||||
function setDarkmode(enable){
|
function setDarkmode(enable){
|
||||||
|
|
||||||
|
// 添加过渡类以启用平滑切换动画
|
||||||
|
document.documentElement.classList.add("theme-transitioning");
|
||||||
|
|
||||||
if (enable == true){
|
if (enable == true){
|
||||||
|
|
||||||
document.documentElement.classList.add("darkmode");
|
document.documentElement.classList.add("darkmode");
|
||||||
@@ -395,6 +398,11 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 过渡完成后移除过渡类
|
||||||
|
setTimeout(function() {
|
||||||
|
document.documentElement.classList.remove("theme-transitioning");
|
||||||
|
}, 300);
|
||||||
|
|
||||||
// 延迟触发 scroll 事件,等待 jQuery 加载
|
// 延迟触发 scroll 事件,等待 jQuery 加载
|
||||||
if (typeof jQuery !== 'undefined') {
|
if (typeof jQuery !== 'undefined') {
|
||||||
|
|
||||||
|
|||||||
69
style.css
69
style.css
@@ -337,7 +337,22 @@ html.immersion-color.darkmode body {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 主题切换过渡效果 (Dark/Light Mode Transition) */
|
||||||
|
html {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
html.theme-transitioning,
|
||||||
|
html.theme-transitioning *,
|
||||||
|
html.theme-transitioning *::before,
|
||||||
|
html.theme-transitioning *::after {
|
||||||
|
transition:
|
||||||
|
background-color 250ms var(--ease-standard),
|
||||||
|
border-color 250ms var(--ease-standard),
|
||||||
|
color 200ms var(--ease-standard),
|
||||||
|
box-shadow 250ms var(--ease-standard),
|
||||||
|
fill 200ms var(--ease-standard),
|
||||||
|
stroke 200ms var(--ease-standard) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/*Argon CSS Override*/
|
/*Argon CSS Override*/
|
||||||
|
|
||||||
@@ -8224,6 +8239,52 @@ body.noscroll:before {
|
|||||||
transform: scale(1) translateX(0);
|
transform: scale(1) translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 分享按钮退出动画 - 反向错落延迟 */
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(1) { transition-delay: 120ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(2) { transition-delay: 100ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(3) { transition-delay: 80ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(4) { transition-delay: 60ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(5) { transition-delay: 40ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(6) { transition-delay: 20ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(7) { transition-delay: 0ms; }
|
||||||
|
#share_container:not(.opened) #share > a:nth-child(8) { transition-delay: 0ms; }
|
||||||
|
|
||||||
|
/* 分享面板移动端响应式适配 */
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
#share_container {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
#share {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 80px;
|
||||||
|
right: 16px;
|
||||||
|
left: auto;
|
||||||
|
top: auto;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
gap: 8px;
|
||||||
|
transform: translateY(20px);
|
||||||
|
max-height: calc(100vh - 160px);
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px;
|
||||||
|
background: var(--color-foreground);
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
#share_container.opened #share {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#share > a {
|
||||||
|
transform: scale(0.8) translateY(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#share_container.opened #share > a {
|
||||||
|
transform: scale(1) translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#share_show {
|
#share_show {
|
||||||
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -14846,13 +14907,13 @@ html.darkmode article.post.card:hover {
|
|||||||
background-position: 50%;
|
background-position: 50%;
|
||||||
transform: scale(10, 10);
|
transform: scale(10, 10);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: transform var(--animation-slow), opacity var(--animation-normal);
|
transition: opacity 350ms var(--ease-standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-ripple:active::after {
|
.btn-ripple:active::after {
|
||||||
transform: scale(0, 0);
|
transform: scale(10, 10);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: 0s;
|
transition: transform 0s, opacity 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 输入框 Apple 风格 */
|
/* 输入框 Apple 风格 */
|
||||||
|
|||||||
Reference in New Issue
Block a user