refactor(about): 重构关于页面样式与交互逻辑
- 优化技术栈展示区域,新增3D标签云效果 - 调整兴趣模块布局,增强移动端适配 - 改进统计区域响应式设计,统一白天/黑夜模式样式 - 新增移动端社交链接区域,优化触摸体验 - 引入防抖机制优化3D球体动画性能 - 增强评论系统UI,支持动态主题切换 - 完善移动端评论内容展开收起功能 - 优化Artalk评论初始化流程,提高加载效率 - 统一全局样式命名规范,提升代码可维护性 - 移除冗余CSS规则,精简样式文件体积 - 修复黑夜模式下文字渐变显示异常问题 - 改进多语言支持,增强国际化体验
This commit is contained in:
@@ -181,7 +181,7 @@ open about.html
|
|||||||
- [x] 添加骨架屏加载效果
|
- [x] 添加骨架屏加载效果
|
||||||
- [x] 实现数据缓存机制,提升页面加载速度
|
- [x] 实现数据缓存机制,提升页面加载速度
|
||||||
- [x] 添加淡入动画效果,提升用户体验
|
- [x] 添加淡入动画效果,提升用户体验
|
||||||
- [x] 实现 PWA 支持,支持离线访问
|
|
||||||
|
|
||||||
### 待完成
|
### 待完成
|
||||||
- [ ] 添加更多数据源(如 Twitter、知乎等)
|
- [ ] 添加更多数据源(如 Twitter、知乎等)
|
||||||
@@ -193,6 +193,7 @@ open about.html
|
|||||||
- [ ] 添加更多主题选项(如高对比度模式等)
|
- [ ] 添加更多主题选项(如高对比度模式等)
|
||||||
- [ ] 实现深色模式下的图片优化处理
|
- [ ] 实现深色模式下的图片优化处理
|
||||||
- [ ] 添加无障碍访问支持(ARIA 属性完善)
|
- [ ] 添加无障碍访问支持(ARIA 属性完善)
|
||||||
|
- [] 实现 PWA 支持,支持离线访问
|
||||||
|
|
||||||
## 🙏 鸣谢与致敬
|
## 🙏 鸣谢与致敬
|
||||||
|
|
||||||
|
|||||||
852
css/about.css
852
css/about.css
@@ -1076,7 +1076,14 @@ body {
|
|||||||
black 90%,
|
black 90%,
|
||||||
transparent 100%
|
transparent 100%
|
||||||
);
|
);
|
||||||
|
-webkit-mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent 0%,
|
||||||
|
black 10%,
|
||||||
|
black 90%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
/* 行内滚动动画由 .tech-row 控制 */
|
||||||
}
|
}
|
||||||
.tech-row {
|
.tech-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1827,15 +1834,15 @@ body {
|
|||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(5, 1fr);
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-item {
|
.stat-item {
|
||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-val {
|
.stat-val {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-key {
|
.stat-key {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
}
|
}
|
||||||
@@ -1848,22 +1855,18 @@ body {
|
|||||||
grid-template-rows: repeat(2, 1fr);
|
grid-template-rows: repeat(2, 1fr);
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-lang="en"] .stat-key {
|
[data-lang="en"] .stat-key {
|
||||||
font-size: 6px !important;
|
font-size: 6px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1025px) and (max-width: 1200px) {
|
@media (min-width: 1201px) {
|
||||||
.area-stats {
|
.area-stats {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
grid-template-rows: repeat(2, 1fr);
|
grid-template-rows: repeat(2, 1fr);
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-key {
|
|
||||||
font-size: 0.65rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移动端统计区域布局 */
|
/* 移动端统计区域布局 */
|
||||||
@@ -1873,375 +1876,346 @@ body {
|
|||||||
padding: 15px 10px;
|
padding: 15px 10px;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-item {
|
.stat-item {
|
||||||
padding: 8px 2px;
|
padding: 8px 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-val {
|
.stat-val {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-key {
|
.stat-key {
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Interests --- */
|
/* --- Mobile Social --- */
|
||||||
.area-interests {
|
.mobile-social {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.interest-list {
|
.ms-btn {
|
||||||
display: grid;
|
width: 40px;
|
||||||
grid-template-columns: 1fr 1fr;
|
height: 40px;
|
||||||
gap: 15px;
|
border-radius: 50%;
|
||||||
margin-top: 1rem;
|
background: rgba(128, 128, 128, 0.1);
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item {
|
|
||||||
background: rgba(255, 255, 255, 0.65);
|
|
||||||
padding: 12px;
|
|
||||||
border-radius: 12px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
|
||||||
transition: background 0.25s, box-shadow 0.25s, border-color 0.25s;
|
|
||||||
border: 1px solid rgba(128, 128, 128, 0.12);
|
|
||||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.9);
|
|
||||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.10);
|
|
||||||
border-color: rgba(108, 92, 231, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-emoji {
|
|
||||||
font-size: 1.6rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加 min-width: 0 防止溢出 */
|
|
||||||
.i-text strong {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
/* 为兴趣标签添加渐变色彩 */
|
|
||||||
background: var(--gradient-1);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text span:not(.i-emoji) {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
/* 为兴趣描述添加渐变色彩 */
|
|
||||||
background: var(--gradient-2);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PC端兴趣模块布局 */
|
|
||||||
@media (min-width: 1025px) {
|
|
||||||
.interest-list {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 15px;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item {
|
|
||||||
background: rgba(128, 128, 128, 0.05);
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
transition: background 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item:hover {
|
|
||||||
background: rgba(128, 128, 128, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-emoji {
|
|
||||||
font-size: 2rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 0;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加 min-width: 0 防止溢出 */
|
|
||||||
.i-text strong {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
background: none;
|
|
||||||
-webkit-background-clip: initial;
|
|
||||||
background-clip: initial;
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text span:not(.i-emoji) {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
background: none;
|
|
||||||
-webkit-background-clip: initial;
|
|
||||||
background-clip: initial;
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 黑夜模式样式增强 */
|
|
||||||
[data-theme="night"] .area-stats {
|
|
||||||
background: rgba(30, 30, 35, 0.55);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-item {
|
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-item:hover {
|
|
||||||
background: rgba(108, 92, 231, 0.2);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-val {
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 0 10px var(--accent-glow);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-key {
|
|
||||||
color: var(--text-secondary);
|
|
||||||
text-shadow: 0 0 5px rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .interest-item {
|
|
||||||
background: rgba(30, 30, 35, 0.35);
|
|
||||||
border-color: rgba(255, 255, 255, 0.08);
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .interest-item:hover {
|
|
||||||
background: rgba(30, 30, 35, 0.5);
|
|
||||||
border-color: var(--accent);
|
|
||||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .i-text strong {
|
|
||||||
background: var(--gradient-1) !important;
|
|
||||||
-webkit-background-clip: text !important;
|
|
||||||
background-clip: text !important;
|
|
||||||
-webkit-text-fill-color: transparent !important;
|
|
||||||
color: transparent !important;
|
|
||||||
text-shadow: 0 0 10px var(--accent-glow);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .i-text span:not(.i-emoji) {
|
|
||||||
background: var(--gradient-2) !important;
|
|
||||||
-webkit-background-clip: text !important;
|
|
||||||
background-clip: text !important;
|
|
||||||
-webkit-text-fill-color: transparent !important;
|
|
||||||
color: transparent !important;
|
|
||||||
text-shadow: 0 0 8px var(--accent-glow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* =========================================
|
|
||||||
4. Layout: Bento Grid (Responsive)
|
|
||||||
========================================= */
|
|
||||||
.main-container {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 120px auto 60px;
|
|
||||||
padding: 0 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bento-grid {
|
|
||||||
display: grid;
|
|
||||||
gap: 24px;
|
|
||||||
/* PC: 3 Col, 2 Row Main */
|
|
||||||
grid-template-columns: 320px 1fr 260px;
|
|
||||||
grid-template-rows: 240px 220px auto;
|
|
||||||
grid-template-areas:
|
|
||||||
"profile bio stats"
|
|
||||||
"profile bio mbti"
|
|
||||||
"tech tech interests";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Areas --- */
|
|
||||||
.area-profile {
|
|
||||||
grid-area: profile;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area-bio {
|
|
||||||
grid-area: bio;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area-stats {
|
|
||||||
grid-area: stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area-mbti {
|
|
||||||
grid-area: mbti;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area-tech {
|
|
||||||
grid-area: tech;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area-interests {
|
|
||||||
grid-area: interests;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Stats --- */
|
|
||||||
.area-stats {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(5, 1fr);
|
|
||||||
gap: 8px;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 16px;
|
|
||||||
background: rgba(255, 255, 255, 0.7);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
-webkit-backdrop-filter: blur(10px);
|
|
||||||
border: 1px solid rgba(128, 128, 128, 0.1);
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mbti-tags .tag {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mbti-tags .tag.tag-color-1 {
|
||||||
|
background: var(--gradient-1);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mbti-tags .tag.tag-color-2 {
|
||||||
|
background: var(--gradient-2);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mbti-tags .tag.tag-color-3 {
|
||||||
|
background: var(--gradient-3);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mbti-tags .tag.tag-color-4 {
|
||||||
|
background: var(--gradient-4);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Tech Stack (PC) --- */
|
||||||
|
.area-tech {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: 20px 25px;
|
||||||
|
border-bottom: 1px solid rgba(128,128,128,0.1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px;
|
}
|
||||||
border-radius: 12px;
|
.card-header h3 {
|
||||||
background: rgba(255, 255, 255, 0.9);
|
font-size: 1.1rem;
|
||||||
transition: all 0.3s ease;
|
color: var(--text-primary);
|
||||||
min-width: 0;
|
margin: 0;
|
||||||
text-align: center;
|
}
|
||||||
|
.card-subtitle {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background: var(--gradient-3);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-item:hover {
|
[data-theme="night"] .card-header h3 {
|
||||||
background: rgba(108, 92, 231, 0.1);
|
text-shadow: 0 0 10px var(--accent-glow);
|
||||||
transform: translateY(-3px);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-val {
|
.card-header h3 {
|
||||||
font-size: 1.5rem;
|
background: var(--gradient-2);
|
||||||
margin-bottom: 5px;
|
-webkit-background-clip: text;
|
||||||
text-align: center;
|
background-clip: text;
|
||||||
white-space: nowrap;
|
color: transparent;
|
||||||
|
font-style: inherit;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PC 3D Container */
|
||||||
|
.tech-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
min-height: 280px;
|
||||||
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-key {
|
.tech-tag-3d {
|
||||||
font-size: 0.75rem;
|
position: absolute;
|
||||||
color: var(--text-tertiary);
|
font-size: 0.85rem;
|
||||||
text-transform: uppercase;
|
font-weight: 600;
|
||||||
text-align: center;
|
color: var(--text-primary);
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
user-select: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
backface-visibility: hidden;
|
||||||
text-overflow: ellipsis;
|
will-change: transform;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: transparent !important;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
pointer-events: none; /* 禁用鼠标事件避免干扰 */
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC端统计区域响应式布局 */
|
/* 白天模式下为 tag-color 类增强可读性 */
|
||||||
@media (min-width: 1446px) {
|
[data-theme="day"] .tech-tag-3d.tag-color-1,
|
||||||
.area-stats {
|
[data-theme="day"] .tech-tag-mobile.tag-color-1 {
|
||||||
grid-template-columns: repeat(5, 1fr);
|
background: none !important;
|
||||||
gap: 8px;
|
-webkit-background-clip: initial !important;
|
||||||
}
|
background-clip: initial !important;
|
||||||
|
color: #0ea5e9 !important; /* 蓝色 */
|
||||||
|
-webkit-text-fill-color: #0ea5e9 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 平板端统计区域布局 */
|
[data-theme="day"] .tech-tag-3d.tag-color-2,
|
||||||
@media (min-width: 769px) and (max-width: 1024px) {
|
[data-theme="day"] .tech-tag-mobile.tag-color-2 {
|
||||||
.area-stats {
|
background: none !important;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
-webkit-background-clip: initial !important;
|
||||||
gap: 6px;
|
background-clip: initial !important;
|
||||||
}
|
color: #ef4444 !important; /* 红色 */
|
||||||
|
-webkit-text-fill-color: #ef4444 !important;
|
||||||
.stat-item {
|
|
||||||
padding: 10px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-val {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-key {
|
|
||||||
font-size: 0.7rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC端统计区域响应式布局 */
|
[data-theme="day"] .tech-tag-3d.tag-color-3,
|
||||||
@media (min-width: 1025px) and (max-width: 1445px) {
|
[data-theme="day"] .tech-tag-mobile.tag-color-3 {
|
||||||
.area-stats {
|
background: none !important;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
-webkit-background-clip: initial !important;
|
||||||
grid-template-rows: repeat(2, 1fr);
|
background-clip: initial !important;
|
||||||
gap: 12px;
|
color: #10b981 !important; /* 绿色 */
|
||||||
}
|
-webkit-text-fill-color: #10b981 !important;
|
||||||
|
|
||||||
[data-lang="en"] .stat-key {
|
|
||||||
font-size: 6px !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1025px) and (max-width: 1200px) {
|
[data-theme="day"] .tech-tag-3d.tag-color-4,
|
||||||
.area-stats {
|
[data-theme="day"] .tech-tag-mobile.tag-color-4 {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
background: none !important;
|
||||||
grid-template-rows: repeat(2, 1fr);
|
-webkit-background-clip: initial !important;
|
||||||
gap: 12px;
|
background-clip: initial !important;
|
||||||
}
|
color: #f59e0b !important; /* 黄色 */
|
||||||
|
-webkit-text-fill-color: #f59e0b !important;
|
||||||
.stat-key {
|
|
||||||
font-size: 0.65rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移动端统计区域布局 */
|
[data-theme="day"] .tech-tag-3d.tag-color-5,
|
||||||
@media (max-width: 768px) {
|
[data-theme="day"] .tech-tag-mobile.tag-color-5 {
|
||||||
.area-stats {
|
background: none !important;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
-webkit-background-clip: initial !important;
|
||||||
padding: 15px 10px;
|
background-clip: initial !important;
|
||||||
gap: 4px;
|
color: #8b5cf6 !important; /* 紫色 */
|
||||||
|
-webkit-text-fill-color: #8b5cf6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="day"] .tech-tag-3d.tag-color-6,
|
||||||
|
[data-theme="day"] .tech-tag-mobile.tag-color-6 {
|
||||||
|
background: none !important;
|
||||||
|
-webkit-background-clip: initial !important;
|
||||||
|
background-clip: initial !important;
|
||||||
|
color: #ec4899 !important; /* 粉色 */
|
||||||
|
-webkit-text-fill-color: #ec4899 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="day"] .tech-tag-3d.tag-color-7,
|
||||||
|
[data-theme="day"] .tech-tag-mobile.tag-color-7 {
|
||||||
|
background: none !important;
|
||||||
|
-webkit-background-clip: initial !important;
|
||||||
|
background-clip: initial !important;
|
||||||
|
color: #06b6d4 !important; /* 青色 */
|
||||||
|
-webkit-text-fill-color: #06b6d4 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="day"] .tech-tag-3d.tag-color-8,
|
||||||
|
[data-theme="day"] .tech-tag-mobile.tag-color-8 {
|
||||||
|
background: none !important;
|
||||||
|
-webkit-background-clip: initial !important;
|
||||||
|
background-clip: initial !important;
|
||||||
|
color: #f97316 !important; /* 橙色 */
|
||||||
|
-webkit-text-fill-color: #f97316 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="day"] .tech-tag-3d.tag-color-9,
|
||||||
|
[data-theme="day"] .tech-tag-mobile.tag-color-9 {
|
||||||
|
background: none !important;
|
||||||
|
-webkit-background-clip: initial !important;
|
||||||
|
background-clip: initial !important;
|
||||||
|
color: #6b7280 !important; /* 灰色 */
|
||||||
|
-webkit-text-fill-color: #6b7280 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="day"] .tech-tag-3d.tag-color-10,
|
||||||
|
[data-theme="day"] .tech-tag-mobile.tag-color-10 {
|
||||||
|
background: none !important;
|
||||||
|
-webkit-background-clip: initial !important;
|
||||||
|
background-clip: initial !important;
|
||||||
|
color: #1f2937 !important; /* 深灰 */
|
||||||
|
-webkit-text-fill-color: #1f2937 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 不同颜色的标签 */
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-1, .tech-tag-mobile.tag-color-1 {
|
||||||
|
background: var(--gradient-1);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-2, .tech-tag-mobile.tag-color-2 {
|
||||||
|
background: var(--gradient-2);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-3, .tech-tag-mobile.tag-color-3 {
|
||||||
|
background: var(--gradient-3);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-4, .tech-tag-mobile.tag-color-4 {
|
||||||
|
background: var(--gradient-4);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-5, .tech-tag-mobile.tag-color-5 {
|
||||||
|
background: var(--gradient-5);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 扩展更多渐变方案 */
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-6, .tech-tag-mobile.tag-color-6 {
|
||||||
|
background: var(--gradient-6);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-7, .tech-tag-mobile.tag-color-7 {
|
||||||
|
background: var(--gradient-7);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-8, .tech-tag-mobile.tag-color-8 {
|
||||||
|
background: var(--gradient-8);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-9, .tech-tag-mobile.tag-color-9 {
|
||||||
|
background: var(--gradient-9);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .tech-tag-3d.tag-color-10, .tech-tag-mobile.tag-color-10 {
|
||||||
|
background: var(--gradient-10);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 渐变文字兼容处理:支持时启用文字渐变,不支持时使用纯色 */
|
||||||
|
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
|
||||||
|
.tech-tag-3d,
|
||||||
|
.tech-tag-mobile {
|
||||||
|
background: none !important;
|
||||||
|
color: var(--text-primary) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-item {
|
.tech-tag-3d.tag-color-1,
|
||||||
padding: 8px 2px;
|
.tech-tag-3d.tag-color-2,
|
||||||
}
|
.tech-tag-3d.tag-color-3,
|
||||||
|
.tech-tag-3d.tag-color-4,
|
||||||
.stat-val {
|
.tech-tag-3d.tag-color-5,
|
||||||
font-size: 1.1rem;
|
.tech-tag-3d.tag-color-6,
|
||||||
margin-bottom: 3px;
|
.tech-tag-3d.tag-color-7,
|
||||||
}
|
.tech-tag-3d.tag-color-8,
|
||||||
|
.tech-tag-3d.tag-color-9,
|
||||||
.stat-key {
|
.tech-tag-3d.tag-color-10,
|
||||||
font-size: 0.6rem;
|
.tech-tag-mobile.tag-color-1,
|
||||||
|
.tech-tag-mobile.tag-color-2,
|
||||||
|
.tech-tag-mobile.tag-color-3,
|
||||||
|
.tech-tag-mobile.tag-color-4,
|
||||||
|
.tech-tag-mobile.tag-color-5,
|
||||||
|
.tech-tag-mobile.tag-color-6,
|
||||||
|
.tech-tag-mobile.tag-color-7,
|
||||||
|
.tech-tag-mobile.tag-color-8,
|
||||||
|
.tech-tag-mobile.tag-color-9,
|
||||||
|
.tech-tag-mobile.tag-color-10 {
|
||||||
|
background: none !important;
|
||||||
|
color: var(--text-primary) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2250,6 +2224,66 @@ body {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1025px) {
|
||||||
|
.interest-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 15px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.interest-item {
|
||||||
|
background: rgba(128, 128, 128, 0.05);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interest-item:hover {
|
||||||
|
background: rgba(128, 128, 128, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.i-emoji {
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
-webkit-text-fill-color: initial;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.i-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加 min-width: 0 防止溢出 */
|
||||||
|
.i-text strong {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: none;
|
||||||
|
-webkit-background-clip: initial;
|
||||||
|
background-clip: initial;
|
||||||
|
-webkit-text-fill-color: initial;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.i-text span:not(.i-emoji) {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
background: none;
|
||||||
|
-webkit-background-clip: initial;
|
||||||
|
background-clip: initial;
|
||||||
|
-webkit-text-fill-color: initial;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.interest-list {
|
.interest-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
@@ -2276,6 +2310,18 @@ body {
|
|||||||
border-color: rgba(108, 92, 231, 0.25);
|
border-color: rgba(108, 92, 231, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .interest-item {
|
||||||
|
background: rgba(30, 30, 35, 0.35);
|
||||||
|
border-color: rgba(255, 255, 255, 0.08);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="night"] .interest-item:hover {
|
||||||
|
background: rgba(30, 30, 35, 0.5);
|
||||||
|
border-color: var(--accent);
|
||||||
|
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
.i-emoji {
|
.i-emoji {
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
@@ -2312,120 +2358,9 @@ body {
|
|||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC端兴趣模块布局 */
|
/* 移动端社交链接 */
|
||||||
@media (min-width: 1025px) {
|
.mobile-social {
|
||||||
.interest-list {
|
display: none;
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 15px;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item {
|
|
||||||
background: rgba(128, 128, 128, 0.05);
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
transition: background 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interest-item:hover {
|
|
||||||
background: rgba(128, 128, 128, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-emoji {
|
|
||||||
font-size: 2rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 0;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 添加 min-width: 0 防止溢出 */
|
|
||||||
.i-text strong {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
background: none;
|
|
||||||
-webkit-background-clip: initial;
|
|
||||||
background-clip: initial;
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.i-text span:not(.i-emoji) {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
background: none;
|
|
||||||
-webkit-background-clip: initial;
|
|
||||||
background-clip: initial;
|
|
||||||
-webkit-text-fill-color: initial;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 黑夜模式样式增强 */
|
|
||||||
[data-theme="night"] .area-stats {
|
|
||||||
background: rgba(30, 30, 35, 0.55);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-item {
|
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-item:hover {
|
|
||||||
background: rgba(108, 92, 231, 0.2);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-val {
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 0 10px var(--accent-glow);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .stat-key {
|
|
||||||
color: var(--text-secondary);
|
|
||||||
text-shadow: 0 0 5px rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .interest-item {
|
|
||||||
background: rgba(30, 30, 35, 0.35);
|
|
||||||
border-color: rgba(255, 255, 255, 0.08);
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .interest-item:hover {
|
|
||||||
background: rgba(30, 30, 35, 0.5);
|
|
||||||
border-color: var(--accent);
|
|
||||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .i-text strong {
|
|
||||||
background: var(--gradient-1) !important;
|
|
||||||
-webkit-background-clip: text !important;
|
|
||||||
background-clip: text !important;
|
|
||||||
-webkit-text-fill-color: transparent !important;
|
|
||||||
color: transparent !important;
|
|
||||||
text-shadow: 0 0 10px var(--accent-glow);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="night"] .i-text span:not(.i-emoji) {
|
|
||||||
background: var(--gradient-2) !important;
|
|
||||||
-webkit-background-clip: text !important;
|
|
||||||
background-clip: text !important;
|
|
||||||
-webkit-text-fill-color: transparent !important;
|
|
||||||
color: transparent !important;
|
|
||||||
text-shadow: 0 0 8px var(--accent-glow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================================
|
/* =========================================
|
||||||
@@ -2845,6 +2780,13 @@ body {
|
|||||||
black 90%,
|
black 90%,
|
||||||
transparent 100%
|
transparent 100%
|
||||||
);
|
);
|
||||||
|
-webkit-mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent 0%,
|
||||||
|
black 20%,
|
||||||
|
black 80%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
.tech-row {
|
.tech-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
116
js/about.js
116
js/about.js
@@ -239,10 +239,10 @@ class DataManager {
|
|||||||
// 创建带超时的fetch函数
|
// 创建带超时的fetch函数
|
||||||
async fetchWithTimeout(url, options = {}) {
|
async fetchWithTimeout(url, options = {}) {
|
||||||
const { timeout = 5000 } = options;
|
const { timeout = 5000 } = options;
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const id = setTimeout(() => controller.abort(), timeout);
|
const id = setTimeout(() => controller.abort(), timeout);
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
signal: controller.signal
|
signal: controller.signal
|
||||||
@@ -363,7 +363,7 @@ class DataManager {
|
|||||||
<div class="repo-desc">${escapeHtml(dShort)}</div>
|
<div class="repo-desc">${escapeHtml(dShort)}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用requestAnimationFrame避免强制重排
|
// 使用requestAnimationFrame避免强制重排
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const pc = $('#projects-container');
|
const pc = $('#projects-container');
|
||||||
@@ -480,7 +480,7 @@ class DataManager {
|
|||||||
<div class="b-cat">${escapeHtml(cat)}</div>
|
<div class="b-cat">${escapeHtml(cat)}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用requestAnimationFrame避免强制重排
|
// 使用requestAnimationFrame避免强制重排
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const bc = $('#blog-container');
|
const bc = $('#blog-container');
|
||||||
@@ -567,30 +567,30 @@ class UIManager {
|
|||||||
// 发送按钮文字(多语言)
|
// 发送按钮文字(多语言)
|
||||||
sendBtn: isZh ? '发送' : 'Send',
|
sendBtn: isZh ? '发送' : 'Send',
|
||||||
loginBtn: isZh ? '发送' : 'Send',
|
loginBtn: isZh ? '发送' : 'Send',
|
||||||
|
|
||||||
// 主题支持
|
// 主题支持
|
||||||
darkMode: document.documentElement.getAttribute('data-theme') === 'night',
|
darkMode: document.documentElement.getAttribute('data-theme') === 'night',
|
||||||
|
|
||||||
// 编辑器增强配置
|
// 编辑器增强配置
|
||||||
editor: {
|
editor: {
|
||||||
// 启用 Markdown
|
// 启用 Markdown
|
||||||
markdown: true,
|
markdown: true,
|
||||||
|
|
||||||
// 表情面板
|
// 表情面板
|
||||||
emoji: {
|
emoji: {
|
||||||
// 使用默认表情包
|
// 使用默认表情包
|
||||||
preset: 'twemoji'
|
preset: 'twemoji'
|
||||||
},
|
},
|
||||||
|
|
||||||
// 启用 @ 用户提醒功能
|
// 启用 @ 用户提醒功能
|
||||||
mention: true,
|
mention: true,
|
||||||
|
|
||||||
// 自动聚焦(仅桌面端)
|
// 自动聚焦(仅桌面端)
|
||||||
autoFocus: !('ontouchstart' in window),
|
autoFocus: !('ontouchstart' in window),
|
||||||
|
|
||||||
// 限制编辑器高度
|
// 限制编辑器高度
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
|
|
||||||
// 工具栏
|
// 工具栏
|
||||||
toolbar: [
|
toolbar: [
|
||||||
'bold', 'italic', 'strike', 'link',
|
'bold', 'italic', 'strike', 'link',
|
||||||
@@ -599,7 +599,7 @@ class UIManager {
|
|||||||
'emoji', 'mention'
|
'emoji', 'mention'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// 评论格式化函数
|
// 评论格式化函数
|
||||||
commentFormatter: (comment) => {
|
commentFormatter: (comment) => {
|
||||||
// 美化时间显示
|
// 美化时间显示
|
||||||
@@ -607,21 +607,21 @@ class UIManager {
|
|||||||
const date = new Date(dateStr);
|
const date = new Date(dateStr);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const diffSec = Math.floor((now - date) / 1000);
|
const diffSec = Math.floor((now - date) / 1000);
|
||||||
|
|
||||||
if (diffSec < 60) return isZh ? '刚刚' : 'Just now';
|
if (diffSec < 60) return isZh ? '刚刚' : 'Just now';
|
||||||
if (diffSec < 3600) return isZh ? `${Math.floor(diffSec / 60)}分钟前` : `${Math.floor(diffSec / 60)} minutes ago`;
|
if (diffSec < 3600) return isZh ? `${Math.floor(diffSec / 60)}分钟前` : `${Math.floor(diffSec / 60)} minutes ago`;
|
||||||
if (diffSec < 86400) return isZh ? `${Math.floor(diffSec / 3600)}小时前` : `${Math.floor(diffSec / 3600)} hours ago`;
|
if (diffSec < 86400) return isZh ? `${Math.floor(diffSec / 3600)}小时前` : `${Math.floor(diffSec / 3600)} hours ago`;
|
||||||
|
|
||||||
const isToday = date.toDateString() === now.toDateString();
|
const isToday = date.toDateString() === now.toDateString();
|
||||||
if (isToday) return isZh ?
|
if (isToday) return isZh ?
|
||||||
`今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
|
`今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
|
||||||
`Today ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
`Today ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
const isYesterday = new Date(now - 86400000).toDateString() === date.toDateString();
|
const isYesterday = new Date(now - 86400000).toDateString() === date.toDateString();
|
||||||
if (isYesterday) return isZh ?
|
if (isYesterday) return isZh ?
|
||||||
`昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
|
`昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}` :
|
||||||
`Yesterday ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
`Yesterday ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
return date.toLocaleString(isZh ? 'zh-CN' : 'en-US', {
|
return date.toLocaleString(isZh ? 'zh-CN' : 'en-US', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: '2-digit',
|
month: '2-digit',
|
||||||
@@ -630,19 +630,19 @@ class UIManager {
|
|||||||
minute: '2-digit'
|
minute: '2-digit'
|
||||||
}).replace(/\//g, '-');
|
}).replace(/\//g, '-');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 如果是管理员,添加徽章
|
// 如果是管理员,添加徽章
|
||||||
if (comment.is_admin) {
|
if (comment.is_admin) {
|
||||||
comment.nick = `👑${comment.nick}`;
|
comment.nick = `👑${comment.nick}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新显示时间
|
// 更新显示时间
|
||||||
comment.create_date_formatted = formatTime(comment.date || comment.created_at || comment.create_date);
|
comment.create_date_formatted = formatTime(comment.date || comment.created_at || comment.create_date);
|
||||||
|
|
||||||
return comment;
|
return comment;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Artalk.init(artalkConfig);
|
Artalk.init(artalkConfig);
|
||||||
this.enhanceArtalkUI();
|
this.enhanceArtalkUI();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -667,13 +667,13 @@ class UIManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空容器
|
// 清空容器
|
||||||
const container = document.getElementById('artalk-container');
|
const container = document.getElementById('artalk-container');
|
||||||
if (container) {
|
if (container) {
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新初始化
|
// 重新初始化
|
||||||
this.initArtalk();
|
this.initArtalk();
|
||||||
}
|
}
|
||||||
@@ -681,15 +681,15 @@ class UIManager {
|
|||||||
enhanceArtalkUI() {
|
enhanceArtalkUI() {
|
||||||
const container = document.getElementById('artalk-container');
|
const container = document.getElementById('artalk-container');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
// 检测是否为移动端
|
// 检测是否为移动端
|
||||||
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
||||||
container.classList.toggle('atk-mobile', isMobile);
|
container.classList.toggle('atk-mobile', isMobile);
|
||||||
container.classList.toggle('atk-desktop', !isMobile);
|
container.classList.toggle('atk-desktop', !isMobile);
|
||||||
|
|
||||||
// 获取当前语言
|
// 获取当前语言
|
||||||
const lang = getStoredLanguage();
|
const lang = getStoredLanguage();
|
||||||
|
|
||||||
// 获取当前主题
|
// 获取当前主题
|
||||||
const currentTheme = document.documentElement.getAttribute('data-theme');
|
const currentTheme = document.documentElement.getAttribute('data-theme');
|
||||||
|
|
||||||
@@ -697,7 +697,7 @@ class UIManager {
|
|||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
this.enhanceMobileArtalk(container, lang);
|
this.enhanceMobileArtalk(container, lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听主题/语言变化
|
// 监听主题/语言变化
|
||||||
const themeObserver = new MutationObserver(() => {
|
const themeObserver = new MutationObserver(() => {
|
||||||
const newTheme = document.documentElement.getAttribute('data-theme');
|
const newTheme = document.documentElement.getAttribute('data-theme');
|
||||||
@@ -709,7 +709,7 @@ class UIManager {
|
|||||||
this.reloadArtalk();
|
this.reloadArtalk();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
themeObserver.observe(document.documentElement, {
|
themeObserver.observe(document.documentElement, {
|
||||||
attributes: true,
|
attributes: true,
|
||||||
attributeFilter: ['data-theme', 'data-lang']
|
attributeFilter: ['data-theme', 'data-lang']
|
||||||
@@ -723,32 +723,32 @@ class UIManager {
|
|||||||
container.querySelectorAll('.atk-comment-wrap .atk-content').forEach(el => {
|
container.querySelectorAll('.atk-comment-wrap .atk-content').forEach(el => {
|
||||||
// 检查是否已经处理过
|
// 检查是否已经处理过
|
||||||
if (el.dataset.mobileProcessed) return;
|
if (el.dataset.mobileProcessed) return;
|
||||||
|
|
||||||
// 检查内容是否超过3行才添加展开收起功能
|
// 检查内容是否超过3行才添加展开收起功能
|
||||||
const lineHeight = parseInt(window.getComputedStyle(el).lineHeight);
|
const lineHeight = parseInt(window.getComputedStyle(el).lineHeight);
|
||||||
const paddingTop = parseInt(window.getComputedStyle(el).paddingTop);
|
const paddingTop = parseInt(window.getComputedStyle(el).paddingTop);
|
||||||
const paddingBottom = parseInt(window.getComputedStyle(el).paddingBottom);
|
const paddingBottom = parseInt(window.getComputedStyle(el).paddingBottom);
|
||||||
const actualHeight = el.clientHeight - paddingTop - paddingBottom;
|
const actualHeight = el.clientHeight - paddingTop - paddingBottom;
|
||||||
|
|
||||||
// 如果内容高度超过3倍行高,则添加展开收起功能
|
// 如果内容高度超过3倍行高,则添加展开收起功能
|
||||||
if (actualHeight > lineHeight * 3) {
|
if (actualHeight > lineHeight * 3) {
|
||||||
// 添加移动端内容截断
|
// 添加移动端内容截断
|
||||||
el.classList.add('clamped');
|
el.classList.add('clamped');
|
||||||
el.style.setProperty('--max-lines', '3');
|
el.style.setProperty('--max-lines', '3');
|
||||||
|
|
||||||
// 创建展开/收起按钮
|
// 创建展开/收起按钮
|
||||||
const btn = document.createElement('button');
|
const btn = document.createElement('button');
|
||||||
btn.className = 'atk-expand-btn';
|
btn.className = 'atk-expand-btn';
|
||||||
const expandText = lang === 'zh' ? '展开' : 'Expand';
|
const expandText = lang === 'zh' ? '展开' : 'Expand';
|
||||||
const collapseText = lang === 'zh' ? '收起' : 'Collapse';
|
const collapseText = lang === 'zh' ? '收起' : 'Collapse';
|
||||||
btn.textContent = expandText;
|
btn.textContent = expandText;
|
||||||
|
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const isClamped = el.classList.toggle('clamped');
|
const isClamped = el.classList.toggle('clamped');
|
||||||
btn.textContent = isClamped ? expandText : collapseText;
|
btn.textContent = isClamped ? expandText : collapseText;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 将按钮插入到适当位置
|
// 将按钮插入到适当位置
|
||||||
const actionsElement = el.closest('.atk-comment').querySelector('.atk-actions');
|
const actionsElement = el.closest('.atk-comment').querySelector('.atk-actions');
|
||||||
if (actionsElement) {
|
if (actionsElement) {
|
||||||
@@ -757,23 +757,23 @@ class UIManager {
|
|||||||
el.parentNode.appendChild(btn);
|
el.parentNode.appendChild(btn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记为已处理
|
// 标记为已处理
|
||||||
el.dataset.mobileProcessed = '1';
|
el.dataset.mobileProcessed = '1';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始应用
|
// 初始应用
|
||||||
applyMobileStyles();
|
applyMobileStyles();
|
||||||
|
|
||||||
// 创建观察器以处理动态添加的评论
|
// 创建观察器以处理动态添加的评论
|
||||||
const observer = new MutationObserver(applyMobileStyles);
|
const observer = new MutationObserver(applyMobileStyles);
|
||||||
observer.observe(container, {
|
observer.observe(container, {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
attributes: false
|
attributes: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// 添加移动端特定的样式类
|
// 添加移动端特定的样式类
|
||||||
const theme = document.documentElement.getAttribute('data-theme');
|
const theme = document.documentElement.getAttribute('data-theme');
|
||||||
container.classList.add(`atk-theme-${theme || 'day'}`);
|
container.classList.add(`atk-theme-${theme || 'day'}`);
|
||||||
@@ -826,7 +826,7 @@ class UIManager {
|
|||||||
} else {
|
} else {
|
||||||
// PC: 3D Sphere
|
// PC: 3D Sphere
|
||||||
container.classList.remove('mobile-scroll');
|
container.classList.remove('mobile-scroll');
|
||||||
|
|
||||||
// 使用防抖优化尺寸计算
|
// 使用防抖优化尺寸计算
|
||||||
let resizeTimeout;
|
let resizeTimeout;
|
||||||
const updateContainerSize = () => {
|
const updateContainerSize = () => {
|
||||||
@@ -837,19 +837,19 @@ class UIManager {
|
|||||||
init3DSphere();
|
init3DSphere();
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化3D球体
|
// 初始化3D球体
|
||||||
const init3DSphere = () => {
|
const init3DSphere = () => {
|
||||||
// 清除之前的动画
|
// 清除之前的动画
|
||||||
if (container.__animToken) {
|
if (container.__animToken) {
|
||||||
cancelAnimationFrame(container.__animToken);
|
cancelAnimationFrame(container.__animToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空容器
|
// 清空容器
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
||||||
const tags = [];
|
const tags = [];
|
||||||
|
|
||||||
techStack.forEach((item, index) => {
|
techStack.forEach((item, index) => {
|
||||||
const el = document.createElement('a');
|
const el = document.createElement('a');
|
||||||
el.className = 'tech-tag-3d';
|
el.className = 'tech-tag-3d';
|
||||||
@@ -860,13 +860,13 @@ class UIManager {
|
|||||||
container.appendChild(el);
|
container.appendChild(el);
|
||||||
tags.push({el, x: 0, y: 0, z: 0});
|
tags.push({el, x: 0, y: 0, z: 0});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 动态半径,避免容器溢出,使用防抖优化
|
// 动态半径,避免容器溢出,使用防抖优化
|
||||||
let radius = Math.max(160, Math.min(container.offsetWidth, container.offsetHeight) / 2 - 24);
|
let radius = Math.max(160, Math.min(container.offsetWidth, container.offsetHeight) / 2 - 24);
|
||||||
const dtr = Math.PI / 180;
|
const dtr = Math.PI / 180;
|
||||||
let lasta = 1, lastb = 1;
|
let lasta = 1, lastb = 1;
|
||||||
let active = false, mouseX = 0, mouseY = 0;
|
let active = false, mouseX = 0, mouseY = 0;
|
||||||
|
|
||||||
// 初始化位置
|
// 初始化位置
|
||||||
tags.forEach((tag, i) => {
|
tags.forEach((tag, i) => {
|
||||||
let phi = Math.acos(-1 + (2 * i + 1) / tags.length);
|
let phi = Math.acos(-1 + (2 * i + 1) / tags.length);
|
||||||
@@ -875,7 +875,7 @@ class UIManager {
|
|||||||
tag.y = radius * Math.sin(theta) * Math.sin(phi);
|
tag.y = radius * Math.sin(theta) * Math.sin(phi);
|
||||||
tag.z = radius * Math.cos(phi);
|
tag.z = radius * Math.cos(phi);
|
||||||
});
|
});
|
||||||
|
|
||||||
container.onmouseover = () => active = true;
|
container.onmouseover = () => active = true;
|
||||||
container.onmouseout = () => active = false;
|
container.onmouseout = () => active = false;
|
||||||
container.onmousemove = (e) => {
|
container.onmousemove = (e) => {
|
||||||
@@ -886,7 +886,7 @@ class UIManager {
|
|||||||
mouseY = (e.clientY - (rect.top + rect.height / 2)) / 5;
|
mouseY = (e.clientY - (rect.top + rect.height / 2)) / 5;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
let a, b;
|
let a, b;
|
||||||
if (active) {
|
if (active) {
|
||||||
@@ -898,12 +898,12 @@ class UIManager {
|
|||||||
}
|
}
|
||||||
lasta = a;
|
lasta = a;
|
||||||
lastb = b;
|
lastb = b;
|
||||||
|
|
||||||
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) a = 0.5; // Keep spinning slowly
|
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) a = 0.5; // Keep spinning slowly
|
||||||
|
|
||||||
let sa = Math.sin(a * dtr), ca = Math.cos(a * dtr);
|
let sa = Math.sin(a * dtr), ca = Math.cos(a * dtr);
|
||||||
let sb = Math.sin(b * dtr), cb = Math.cos(b * dtr);
|
let sb = Math.sin(b * dtr), cb = Math.cos(b * dtr);
|
||||||
|
|
||||||
// 批量更新样式以减少重排
|
// 批量更新样式以减少重排
|
||||||
// 先收集所有需要更新的样式信息
|
// 先收集所有需要更新的样式信息
|
||||||
const updates = [];
|
const updates = [];
|
||||||
@@ -920,7 +920,7 @@ class UIManager {
|
|||||||
const zIndex = parseInt(scale * 100);
|
const zIndex = parseInt(scale * 100);
|
||||||
const left = tag.x + container.offsetWidth / 2 - tag.el.offsetWidth / 2;
|
const left = tag.x + container.offsetWidth / 2 - tag.el.offsetWidth / 2;
|
||||||
const top = tag.y + container.offsetHeight / 2 - tag.el.offsetHeight / 2;
|
const top = tag.y + container.offsetHeight / 2 - tag.el.offsetHeight / 2;
|
||||||
|
|
||||||
updates.push({
|
updates.push({
|
||||||
el: tag.el,
|
el: tag.el,
|
||||||
transform: `translate(${left}px, ${top}px) scale(${scale})`,
|
transform: `translate(${left}px, ${top}px) scale(${scale})`,
|
||||||
@@ -934,16 +934,16 @@ class UIManager {
|
|||||||
update.el.style.opacity = update.opacity;
|
update.el.style.opacity = update.opacity;
|
||||||
update.el.style.zIndex = update.zIndex;
|
update.el.style.zIndex = update.zIndex;
|
||||||
});
|
});
|
||||||
|
|
||||||
container.__animToken = requestAnimationFrame(update);
|
container.__animToken = requestAnimationFrame(update);
|
||||||
};
|
};
|
||||||
|
|
||||||
container.__animToken = requestAnimationFrame(update);
|
container.__animToken = requestAnimationFrame(update);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化3D球体
|
// 初始化3D球体
|
||||||
init3DSphere();
|
init3DSphere();
|
||||||
|
|
||||||
// 监听窗口大小变化
|
// 监听窗口大小变化
|
||||||
window.addEventListener('resize', updateContainerSize);
|
window.addEventListener('resize', updateContainerSize);
|
||||||
}
|
}
|
||||||
@@ -957,10 +957,10 @@ class UIManager {
|
|||||||
const fTheme = document.getElementById('fab-theme');
|
const fTheme = document.getElementById('fab-theme');
|
||||||
const fMusic = document.getElementById('fab-music');
|
const fMusic = document.getElementById('fab-music');
|
||||||
if (!main || !menu || !fLang || !fTheme || !fMusic) return;
|
if (!main || !menu || !fLang || !fTheme || !fMusic) return;
|
||||||
|
|
||||||
// 添加拖拽功能
|
// 添加拖拽功能
|
||||||
this.initDraggableFab();
|
this.initDraggableFab();
|
||||||
|
|
||||||
const updateLabels = () => {
|
const updateLabels = () => {
|
||||||
// 使用requestAnimationFrame避免强制重排
|
// 使用requestAnimationFrame避免强制重排
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
@@ -1098,7 +1098,7 @@ class UIManager {
|
|||||||
// 确保容器具有正确的主题类
|
// 确保容器具有正确的主题类
|
||||||
container.classList.remove('atk-theme-day', 'atk-theme-night');
|
container.classList.remove('atk-theme-day', 'atk-theme-night');
|
||||||
container.classList.add(`atk-theme-${theme || 'day'}`);
|
container.classList.add(`atk-theme-${theme || 'day'}`);
|
||||||
|
|
||||||
// 更新自定义元素的主题样式
|
// 更新自定义元素的主题样式
|
||||||
const customElements = container.querySelectorAll('.atk-expand-btn, .atk-pagination .atk-page-item');
|
const customElements = container.querySelectorAll('.atk-expand-btn, .atk-pagination .atk-page-item');
|
||||||
customElements.forEach(el => {
|
customElements.forEach(el => {
|
||||||
|
|||||||
Reference in New Issue
Block a user