mirror of
https://gitee.com/guoyifanA/qiu-mo-jetbrains-help.git
synced 2026-09-21 22:30:45 +08:00
增加黑夜模式
This commit is contained in:
@@ -272,6 +272,104 @@ body {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 暗黑模式样式 */
|
||||||
|
html.dark {
|
||||||
|
filter: invert(1) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 只有在没有View Transition时才使用CSS过渡 */
|
||||||
|
html:not(.view-transition-active) {
|
||||||
|
transition: filter 300ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark img,
|
||||||
|
html.dark video,
|
||||||
|
html.dark .avatar,
|
||||||
|
html.dark .image,
|
||||||
|
html.dark .thumb,
|
||||||
|
html.dark [class*="icon-"],
|
||||||
|
html.dark .product-icon {
|
||||||
|
filter: invert(1) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主题切换按钮样式 */
|
||||||
|
.theme-toggle {
|
||||||
|
position: relative;
|
||||||
|
width: 50px;
|
||||||
|
height: 26px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
left: 2px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .theme-toggle::before {
|
||||||
|
transform: translateX(24px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .theme-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
color: white;
|
||||||
|
z-index: 1;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .sun-icon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .moon-icon {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .theme-toggle .sun-icon {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .theme-toggle .moon-icon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* View Transition API 动画样式 */
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
mix-blend-mode: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-old(root) {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-new(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark::view-transition-old(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark::view-transition-new(root) {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* 移动端优化 */
|
/* 移动端优化 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.license-code-display {
|
.license-code-display {
|
||||||
@@ -279,13 +377,13 @@ body {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification {
|
.notification {
|
||||||
right: 10px;
|
right: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-code {
|
.config-code {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
@@ -293,36 +391,56 @@ body {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-section {
|
.config-section {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
margin: 12px 0;
|
margin: 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 配置步骤移动端优化 */
|
/* 配置步骤移动端优化 */
|
||||||
.config-step-mobile {
|
.config-step-mobile {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
space-y: 12px;
|
space-y: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-step-mobile .config-step-content {
|
.config-step-mobile .config-step-content {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 首页内容移动端优化 */
|
/* 首页内容移动端优化 */
|
||||||
.home-section {
|
.home-section {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-title {
|
.home-title {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-subtitle {
|
.home-subtitle {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 主题切换按钮移动端优化 */
|
||||||
|
.theme-toggle {
|
||||||
|
width: 45px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle::before {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .theme-toggle::before {
|
||||||
|
transform: translateX(21px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .theme-icon {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,17 @@
|
|||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<button @click="showConfigModal = true" class="p-2 text-gray-600 hover:text-purple-600 transition-colors" title="配置">
|
<div class="flex items-center space-x-3">
|
||||||
<i class="fas fa-cog"></i>
|
<!-- 主题切换按钮 -->
|
||||||
</button>
|
<div @click="toggleTheme($event)" class="theme-toggle" title="切换主题">
|
||||||
|
<i class="fas fa-sun theme-icon sun-icon"></i>
|
||||||
|
<i class="fas fa-moon theme-icon moon-icon"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button @click="showConfigModal = true" class="p-2 text-gray-600 hover:text-purple-600 transition-colors" title="配置">
|
||||||
|
<i class="fas fa-cog"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,16 +64,19 @@ const App = {
|
|||||||
this.loadProducts()
|
this.loadProducts()
|
||||||
this.loadPlugins()
|
this.loadPlugins()
|
||||||
this.setDefaultExpiryDate()
|
this.setDefaultExpiryDate()
|
||||||
|
|
||||||
|
// 加载主题设置
|
||||||
|
Utils.loadTheme()
|
||||||
|
|
||||||
// 监听滚动事件
|
// 监听滚动事件
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
|
||||||
this.showBackToTop = scrollTop > 300
|
this.showBackToTop = scrollTop > 300
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听滚动事件
|
// 监听滚动事件
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
|
|
||||||
// 保存函数引用以便清理
|
// 保存函数引用以便清理
|
||||||
this._handleScroll = handleScroll
|
this._handleScroll = handleScroll
|
||||||
},
|
},
|
||||||
@@ -239,6 +242,11 @@ const App = {
|
|||||||
top: 0,
|
top: 0,
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 主题切换
|
||||||
|
toggleTheme(event) {
|
||||||
|
Utils.toggleTheme(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,78 @@ const Utils = {
|
|||||||
const date = new Date()
|
const date = new Date()
|
||||||
date.setFullYear(date.getFullYear() + 1)
|
date.setFullYear(date.getFullYear() + 1)
|
||||||
return date.toISOString().split('T')[0]
|
return date.toISOString().split('T')[0]
|
||||||
|
},
|
||||||
|
|
||||||
|
// 主题切换功能
|
||||||
|
toggleTheme(event) {
|
||||||
|
// 检查浏览器是否支持 View Transition API
|
||||||
|
if (!document.startViewTransition) {
|
||||||
|
// 不支持则直接切换主题,不添加动画
|
||||||
|
document.documentElement.classList.toggle('dark')
|
||||||
|
this.saveTheme()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记正在使用View Transition,避免CSS过渡冲突
|
||||||
|
document.documentElement.classList.add('view-transition-active')
|
||||||
|
|
||||||
|
const transition = document.startViewTransition(() => {
|
||||||
|
document.documentElement.classList.toggle('dark')
|
||||||
|
this.saveTheme()
|
||||||
|
})
|
||||||
|
|
||||||
|
transition.ready.then(() => {
|
||||||
|
const { clientX, clientY } = event
|
||||||
|
|
||||||
|
const endRadius = Math.hypot(Math.max(clientX, innerWidth - clientX), Math.max(clientY, innerHeight - clientY))
|
||||||
|
|
||||||
|
const clipPath = [`circle(0px at ${clientX}px ${clientY}px)`, `circle(${endRadius}px at ${clientX}px ${clientY}px)`]
|
||||||
|
|
||||||
|
const isDark = document.documentElement.classList.contains('dark')
|
||||||
|
|
||||||
|
document.documentElement.animate(
|
||||||
|
{
|
||||||
|
clipPath: isDark ? clipPath.reverse() : clipPath
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 450,
|
||||||
|
easing: 'ease-in',
|
||||||
|
pseudoElement: isDark ? '::view-transition-old(root)' : '::view-transition-new(root)'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 动画完成后移除标记类
|
||||||
|
transition.finished.finally(() => {
|
||||||
|
document.documentElement.classList.remove('view-transition-active')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 保存主题设置
|
||||||
|
saveTheme() {
|
||||||
|
const isDark = document.documentElement.classList.contains('dark')
|
||||||
|
localStorage.setItem('theme', isDark ? 'dark' : 'light')
|
||||||
|
},
|
||||||
|
|
||||||
|
// 加载主题设置
|
||||||
|
loadTheme() {
|
||||||
|
const savedTheme = localStorage.getItem('theme')
|
||||||
|
if (savedTheme === 'dark') {
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
} else if (savedTheme === 'light') {
|
||||||
|
document.documentElement.classList.remove('dark')
|
||||||
|
} else {
|
||||||
|
// 如果没有保存的主题,检查系统偏好
|
||||||
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
|
if (prefersDark) {
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取当前主题
|
||||||
|
getCurrentTheme() {
|
||||||
|
return document.documentElement.classList.contains('dark') ? 'dark' : 'light'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user