diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css
index de415ad8..ca938f6d 100644
--- a/themes/Ying/assets/css/main.css
+++ b/themes/Ying/assets/css/main.css
@@ -236,7 +236,7 @@ code::-webkit-scrollbar {
}
.code-expand-btn {
- display: none;
+ display: flex;
position: absolute;
bottom: 10px;
left: 50%;
@@ -256,9 +256,11 @@ code::-webkit-scrollbar {
padding: 0;
}
-/* Show button when collapsed */
-.code-fold-container.collapsed .code-expand-btn {
- display: flex;
+.code-fold-container:not(.collapsed) .code-expand-btn {
+ position: sticky;
+ bottom: 10px;
+ margin: 10px auto 0;
+ transform: none;
}
/* Button Pill Style */
@@ -433,12 +435,48 @@ table td {
}
blockquote {
- margin-left: 4px;
- font-weight: 300;
- border-left: 3.8px solid rgb(80 80 80);
- background-color: rgba(51 51 51/5%);
- padding-left: 20px;
- word-break: break-all;
+ position: relative;
+ margin: 1.2rem 0;
+ padding: 14px 17px 14px 20px;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ border-left: 4px solid rgba(0, 0, 0, 0.72);
+ border-radius: 12px;
+ background: linear-gradient(135deg, rgba(0, 0, 0, 0.02), rgba(0, 0, 0, 0.01));
+ color: rgba(30, 30, 30, 0.92);
+ font-size: 0.95em;
+ font-weight: 400;
+ line-height: 1.68;
+ word-break: break-word;
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
+}
+
+blockquote::before {
+ content: "“";
+ position: absolute;
+ top: -8px;
+ left: 13px;
+ color: rgba(0, 0, 0, 0.08);
+ font-size: 42px;
+ line-height: 1;
+ font-family: Georgia, serif;
+ pointer-events: none;
+}
+
+blockquote p {
+ position: relative;
+ margin: 0.25rem 0 !important;
+}
+
+[data-theme="dark"] blockquote {
+ border-color: rgba(148, 163, 184, 0.18);
+ border-left-color: rgba(168, 181, 205, 0.82);
+ background: linear-gradient(135deg, rgba(30, 41, 59, 0.92), rgba(15, 23, 42, 0.78));
+ color: rgba(226, 232, 240, 0.96);
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
+}
+
+[data-theme="dark"] blockquote::before {
+ color: rgba(203, 213, 225, 0.16);
}
a {
@@ -567,16 +605,22 @@ ul {
}
.header-avatar {
- display: flex;
+ display: inline-flex;
align-items: center;
justify-content: center;
+ gap: 10px;
margin-right: 16px;
- padding: 0;
+ padding: 8px 10px 8px 8px;
+ border-radius: 999px;
cursor: pointer;
+ -webkit-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: transparent;
}
.avatar-theme-tip {
- margin-left: 10px;
+ margin-left: 0;
+ pointer-events: none;
padding: 4px 12px;
border-radius: 999px;
background: #111827;
@@ -1416,52 +1460,6 @@ ul {
background: rgba(0,0,0,0.7);
}
-/* Expandable Code Blocks */
-.highlight.collapsed {
- max-height: 300px;
- position: relative;
-}
-
-.highlight.collapsed::after {
- content: "";
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 80px;
- background: linear-gradient(to bottom, transparent, #f6f8fa);
- pointer-events: none;
-}
-
-[data-theme="dark"] .highlight.collapsed::after {
- background: linear-gradient(to bottom, transparent, #282a36);
-}
-
-.expand-btn-container {
- text-align: center;
- position: absolute;
- bottom: 0;
- width: 100%;
- padding: 10px;
- z-index: 5;
- display: none;
-}
-
-.highlight.collapsed .expand-btn-container {
- display: block;
-}
-
-.expand-btn {
- background: var(--link-color);
- color: white;
- border: none;
- padding: 5px 15px;
- border-radius: 20px;
- cursor: pointer;
- font-size: 12px;
- box-shadow: 0 2px 5px rgba(0,0,0,0.2);
-}
-
[data-theme="dark"] .highlight {
background: #282a36; /* Night Mode: Dark BG (Dracula) */
color: #f8f8f2; /* Night Mode: Light Text */
@@ -3018,59 +3016,6 @@ input[type=submit] {
box-shadow: none;
}
-.post-content .sen-image-frame[data-title]::after,
-.entry-content .sen-image-frame[data-title]::after {
- content: attr(data-title);
- position: absolute;
- left: 10px;
- bottom: 10px;
- max-width: calc(100% - 20px);
- padding: 5px 10px;
- border-radius: 4px;
- border: 1px solid rgba(0, 0, 0, 0.08);
- background: rgba(255, 255, 255, 0.72);
- color: rgba(0, 0, 0, 0.82);
- -webkit-backdrop-filter: blur(16px) saturate(180%);
- backdrop-filter: blur(16px) saturate(180%);
- font-size: 13px;
- font-weight: 500;
- letter-spacing: 0.03em;
- line-height: 1.2;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- pointer-events: none;
- opacity: 0;
- transform: translateY(4px) translateZ(0);
- transition: opacity 0.4s 0.2s cubic-bezier(0.22, 0.61, 0.36, 1),
- transform 0.4s 0.2s cubic-bezier(0.22, 0.61, 0.36, 1);
- will-change: transform, opacity;
-}
-
-.post-content .sen-image-frame.is-visible[data-title]::after,
-.entry-content .sen-image-frame.is-visible[data-title]::after {
- opacity: 1;
- transform: translateY(0) translateZ(0);
-}
-
-[data-theme="dark"] .post-content .sen-image-frame[data-title]::after,
-[data-theme="dark"] .entry-content .sen-image-frame[data-title]::after {
- border-color: rgba(255, 255, 255, 0.12);
- background: rgba(0, 0, 0, 0.62);
- color: rgba(255, 255, 255, 0.92);
-}
-
-@media screen and (max-width: 768px) {
- .post-content .sen-image-frame[data-title]::after,
- .entry-content .sen-image-frame[data-title]::after {
- left: 8px;
- bottom: 8px;
- max-width: calc(100% - 16px);
- padding: 4px 8px;
- font-size: 12px;
- }
-}
-
/* 设置进度条的背景色 */
.bar {
background: #2aae67 !important;
@@ -3582,8 +3527,8 @@ input[type=submit] {
.floating-tools a {
width: 42px;
height: 42px;
- background: rgba(255, 255, 255, 0.68);
- color: rgba(0, 0, 0, 0.75);
+ background: rgba(255, 255, 255, 0.94);
+ color: rgba(24, 24, 27, 0.86);
border-radius: 50%;
font-size: 20px;
cursor: pointer;
@@ -3591,30 +3536,30 @@ input[type=submit] {
display: flex;
justify-content: center;
align-items: center;
- -webkit-backdrop-filter: blur(16px) saturate(180%);
- backdrop-filter: blur(16px) saturate(180%);
- border: 1px solid rgba(255, 255, 255, 0.5);
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.07);
+ -webkit-backdrop-filter: none;
+ backdrop-filter: none;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ box-shadow: 0 6px 18px rgba(15, 23, 42, 0.12);
transform: translateZ(0);
- transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
+ transition: background 0.2s ease, transform 0.2s ease;
}
.floating-tools a:hover {
- background: rgba(255, 255, 255, 0.88);
+ background: #fff;
transform: translateZ(0) translateY(-2px);
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 10px 24px rgba(15, 23, 42, 0.16);
}
[data-theme="dark"] .floating-tools a {
- background: rgba(30, 30, 35, 0.62);
- color: rgba(220, 220, 230, 0.78);
- border-color: rgba(255, 255, 255, 0.1);
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.22);
+ background: rgba(30, 41, 59, 0.94);
+ color: rgba(241, 245, 249, 0.9);
+ border-color: rgba(148, 163, 184, 0.22);
+ box-shadow: 0 8px 22px rgba(0, 0, 0, 0.34);
}
[data-theme="dark"] .floating-tools a:hover {
- background: rgba(45, 45, 50, 0.78);
- box-shadow: 0 4px 18px rgba(0, 0, 0, 0.32);
+ background: rgba(51, 65, 85, 0.98);
+ box-shadow: 0 12px 26px rgba(0, 0, 0, 0.42);
}
/* ── ViewImage — Apple-style lightbox ── */
@@ -3710,7 +3655,7 @@ input[type=submit] {
.img-grid {
display: grid;
gap: 4px;
- margin: 0.6rem 0;
+ margin: 0.2rem 0;
}
.img-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
@@ -3740,17 +3685,23 @@ input[type=submit] {
border-radius: 4px;
}
-/* Suppress title overlay inside grids */
-.img-grid .sen-image-frame[data-title]::after {
- display: none;
-}
-
-/* Mobile: reduce to 2 columns */
-@media screen and (max-width: 480px) {
+/* Mobile: reduce columns for smaller screens */
+@media screen and (max-width: 640px) {
.img-grid.cols-3,
.img-grid.cols-4 {
grid-template-columns: repeat(2, 1fr);
}
+ .img-grid .sen-image-frame {
+ aspect-ratio: auto;
+ }
+}
+
+@media screen and (max-width: 400px) {
+ .img-grid.cols-2,
+ .img-grid.cols-3,
+ .img-grid.cols-4 {
+ grid-template-columns: 1fr;
+ }
}
/* ── Toast ── */
@@ -3777,8 +3728,8 @@ input[type=submit] {
transform: translateY(-10px);
transition: opacity 0.28s ease, transform 0.28s ease;
pointer-events: auto;
- -webkit-backdrop-filter: blur(20px) saturate(180%);
- backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(4px);
+ backdrop-filter: blur(4px);
will-change: transform, opacity;
}
@@ -3814,8 +3765,8 @@ input[type=submit] {
[data-theme="dark"] .ying-toast--info {
background: rgba(159, 196, 244, 0.22);
color: #f3f7fd;
- -webkit-backdrop-filter: blur(24px) saturate(180%);
- backdrop-filter: blur(24px) saturate(180%);
+ -webkit-backdrop-filter: blur(4px);
+ backdrop-filter: blur(4px);
}
@media screen and (max-width: 480px) {
@@ -4545,8 +4496,7 @@ hr,
color 0.5s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.5s cubic-bezier(0.4, 0, 0.2, 1),
fill 0.5s cubic-bezier(0.4, 0, 0.2, 1),
- opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1),
- box-shadow 0.5s cubic-bezier(0.4, 0, 0.2, 1) !important;
+ opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
/* --- Transition Effects (Deprecated old block) --- */
diff --git a/themes/Ying/assets/js/modules/artalk.js b/themes/Ying/assets/js/modules/artalk.js
index 2ea5a0ed..4cf0d0f5 100644
--- a/themes/Ying/assets/js/modules/artalk.js
+++ b/themes/Ying/assets/js/modules/artalk.js
@@ -154,75 +154,257 @@ window.initArtalk = function() {
setTimeout(saveConf, 2000);
setTimeout(saveConf, 5000);
- // Handle list-loaded event for lazy loading avatars and animations
- artalk.on('list-loaded', function() {
- if (window.artalkConfig.aiComment) {
- var ai = window.artalkConfig.aiComment;
- var listBody = document.querySelector('.atk-list .atk-list-body');
- if (listBody && !listBody.querySelector('.atk-ai-comment')) {
- var aiCommentHtml = `
-
- `;
- listBody.insertAdjacentHTML('afterbegin', aiCommentHtml);
-
- // Hide "No Comment" placeholder if it exists
- var noComment = document.querySelector('.atk-list-no-comment');
- if (noComment) {
- noComment.style.display = 'none';
- }
- }
- }
+ // ── Badge system: 友链 / 友圈 / 评论等级 ──
+var badgesInjected = false;
- // Add staggered animation to the comment list
- var list = document.querySelector('.atk-list');
- if (list) {
- list.setAttribute('uk-scrollspy', 'target: > .atk-comment-wrap; cls: uk-animation-slide-bottom-small; delay: 50');
- }
+var normalizeHost = function(h) {
+ return (h || '').replace(/^www\./, '');
+};
- // Apply granular animations to inner elements
- document.querySelectorAll('.atk-comment-wrap:not(.atk-ai-comment)').forEach(function(wrap) {
- var avatar = wrap.querySelector('.atk-avatar');
- if (avatar) avatar.setAttribute('uk-scrollspy', 'cls: uk-animation-scale-up; delay: 200');
-
- var main = wrap.querySelector('.atk-main');
- if (main) main.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-right-small; delay: 300');
-
- var nick = wrap.querySelector('.atk-nick');
- if (nick) nick.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-top-small; delay: 350');
- });
-
- // Find all avatars in the comment list
- // We let lazyload.js handle the avatars automatically by calling lazyLoadAgain()
- // which will find these new images, set the placeholder, and observe them.
-
- // Trigger lazy load update
- if (window.lazyLoadAgain) {
- window.lazyLoadAgain();
- }
-
- // Force hide "No Comment" if AI comment exists
- if (window.artalkConfig.aiComment) {
- var noComment = document.querySelector('.atk-list-no-comment');
- var aiComment = document.querySelector('.atk-ai-comment');
- if (aiComment && noComment) {
- noComment.style.display = 'none';
- }
- }
+var buildMap = function(data) {
+ var hosts = new Map();
+ var names = new Map();
+ if (data && data.hosts) {
+ data.hosts.forEach(function(item) {
+ if (item.host) hosts.set(item.host, item.title || item.host);
});
+ }
+ if (data && data.names) {
+ data.names.forEach(function(n) {
+ if (n.lower) names.set(n.lower, n.title);
+ });
+ }
+ return { hosts: hosts, names: names };
+};
+
+var linkMap = null;
+var feedMap = null;
+
+// Comment rank table — Song dynasty 九品十八阶
+var RANK_TABLE = [
+ { min: 2000, title: '正一品·太师', short: '太师', color: '#b8860b', bg: 'rgba(184,134,11,0.22)' },
+ { min: 1400, title: '从一品·太尉', short: '太尉', color: '#b8860b', bg: 'rgba(184,134,11,0.18)' },
+ { min: 1050, title: '正二品·参知政事', short: '参知政事', color: '#7c3aed', bg: 'rgba(124,58,237,0.18)' },
+ { min: 800, title: '从二品·节度使', short: '节度使', color: '#7c3aed', bg: 'rgba(124,58,237,0.15)' },
+ { min: 600, title: '正三品·御史中丞', short: '御史中丞', color: '#a855f7', bg: 'rgba(168,85,247,0.15)' },
+ { min: 480, title: '从三品·秘书监', short: '秘书监', color: '#a855f7', bg: 'rgba(168,85,247,0.12)' },
+ { min: 380, title: '正四品·谏议大夫', short: '谏议大夫', color: '#c084fc', bg: 'rgba(192,132,252,0.12)' },
+ { min: 300, title: '从四品·侍读学士', short: '侍读学士', color: '#c084fc', bg: 'rgba(192,132,252,0.10)' },
+ { min: 240, title: '正五品·给事中', short: '给事中', color: '#dc2626', bg: 'rgba(220,38,38,0.15)' },
+ { min: 190, title: '从五品·知州', short: '知州', color: '#dc2626', bg: 'rgba(220,38,38,0.12)' },
+ { min: 150, title: '正六品·侍御史', short: '侍御史', color: '#ef4444', bg: 'rgba(239,68,68,0.12)' },
+ { min: 115, title: '从六品·通判', short: '通判', color: '#ef4444', bg: 'rgba(239,68,68,0.10)' },
+ { min: 85, title: '正七品·知县', short: '知县', color: '#059669', bg: 'rgba(5,150,105,0.15)' },
+ { min: 60, title: '从七品·殿中侍御史', short: '殿中侍御史', color: '#059669', bg: 'rgba(5,150,105,0.12)' },
+ { min: 40, title: '正八品·大理评事', short: '大理评事', color: '#10b981', bg: 'rgba(16,185,129,0.12)' },
+ { min: 25, title: '从八品·录事参军', short: '录事参军', color: '#10b981', bg: 'rgba(16,185,129,0.10)' },
+ { min: 15, title: '正九品·主簿', short: '主簿', color: '#a16207', bg: 'rgba(161,98,7,0.15)' },
+ { min: 5, title: '从九品·司户参军', short: '司户参军', color: '#a16207', bg: 'rgba(161,98,7,0.12)' },
+ { min: 0, title: '庶民', short: '庶民', color: '#9ca3af', bg: 'rgba(156,163,175,0.12)' }
+];
+
+var getRank = function(count) {
+ for (var i = 0; i < RANK_TABLE.length; i++) {
+ if (count >= RANK_TABLE[i].min) return RANK_TABLE[i];
+ }
+ return RANK_TABLE[RANK_TABLE.length - 1];
+};
+
+// localStorage-based cross-page user comment counter with page dedup
+var USER_COUNT_KEY = 'atk_user_counts_v2';
+var loadUserCounts = function() {
+ try {
+ var raw = localStorage.getItem(USER_COUNT_KEY);
+ return raw ? JSON.parse(raw) : { _pages: {} };
+ } catch(e) { return { _pages: {} }; }
+};
+var saveUserCounts = function(counts) {
+ try { localStorage.setItem(USER_COUNT_KEY, JSON.stringify(counts)); } catch(e) {}
+};
+var getPageKey = function() {
+ return window.artalkConfig ? (window.artalkConfig.pageKey || window.location.pathname) : window.location.pathname;
+};
+
+var processBadges = function() {
+ if (!linkMap && !feedMap) return;
+
+ var data = loadUserCounts();
+ var pageKey = getPageKey();
+ var pages = data._pages || {};
+ var isNewPage = !pages[pageKey];
+
+ // Count per-user comments on current page
+ var pageCounts = {};
+ document.querySelectorAll('.atk-comment-wrap:not(.atk-ai-comment)').forEach(function(wrap) {
+ var nickEl = wrap.querySelector('.atk-nick');
+ if (!nickEl) return;
+ var name = (nickEl.textContent || '').trim();
+ if (name) pageCounts[name] = (pageCounts[name] || 0) + 1;
+ });
+
+ // Accumulate: only add counts if this page hasn't been processed before
+ var userCounts = {};
+ for (var name in pageCounts) {
+ var prev = data[name] || 0;
+ if (isNewPage) {
+ data[name] = prev + pageCounts[name];
+ }
+ userCounts[name] = data[name];
+ }
+ if (isNewPage) {
+ pages[pageKey] = true;
+ data._pages = pages;
+ }
+ saveUserCounts(data);
+
+ document.querySelectorAll('.atk-comment-wrap:not(.atk-ai-comment)').forEach(function(wrap) {
+ var nickEl = wrap.querySelector('.atk-nick');
+ var avatarEl = wrap.querySelector('.atk-avatar');
+ if (!nickEl) return;
+
+ var nickText = (nickEl.textContent || '').trim();
+ var nickLower = nickText.toLowerCase();
+ var nickLink = nickEl.querySelector('a[href]');
+ var commentHost = null;
+ if (nickLink) {
+ try { commentHost = normalizeHost(new URL(nickLink.getAttribute('href')).hostname); } catch(e) {}
+ }
+
+ // 1. 友链 badge (green gradient) — from /api/links?all=1
+ if (linkMap && !nickEl.querySelector('.atk-link-badge')) {
+ var linkMatch = null;
+ if (commentHost && linkMap.hosts.has(commentHost)) {
+ linkMatch = linkMap.hosts.get(commentHost);
+ } else if (linkMap.names.has(nickLower)) {
+ linkMatch = linkMap.names.get(nickLower);
+ }
+ if (linkMatch) {
+ var lb = document.createElement('span');
+ lb.className = 'atk-link-badge';
+ lb.textContent = '友链';
+ lb.title = '友链: ' + linkMatch;
+ nickEl.appendChild(lb);
+ }
+ }
+
+ // 2. 友圈 badge (gold gradient) — from /api/feeds
+ if (feedMap && !nickEl.querySelector('.atk-feed-badge')) {
+ var feedMatch = null;
+ if (commentHost && feedMap.hosts.has(commentHost)) {
+ feedMatch = feedMap.hosts.get(commentHost);
+ } else if (feedMap.names.has(nickLower)) {
+ feedMatch = feedMap.names.get(nickLower);
+ }
+ if (feedMatch) {
+ var fb = document.createElement('span');
+ fb.className = 'atk-feed-badge';
+ fb.textContent = '友圈';
+ fb.title = '友圈: ' + feedMatch;
+ nickEl.appendChild(fb);
+ }
+ }
+
+ // 3. Comment rank badge — inline next to name
+ if (!nickEl.querySelector('.atk-rank-badge')) {
+ var count = userCounts[nickText] || 0;
+ var rank = getRank(count);
+ var rb = document.createElement('span');
+ rb.className = 'atk-rank-badge';
+ rb.textContent = rank.short;
+ rb.title = rank.title + ' (' + count + '条评论)';
+ var idx = RANK_TABLE.indexOf(rank);
+ if (idx > 0) {
+ var next = RANK_TABLE[idx - 1];
+ var diff = next.min - count;
+ if (diff > 0) {
+ var progress = Math.round((count - rank.min) / (next.min - rank.min) * 100);
+ rb.title += ' — 距' + next.short + '还差' + diff + '条 (' + progress + '%)';
+ }
+ }
+ nickEl.appendChild(rb);
+ }
+ });
+};
+
+var injectAllBadges = function() {
+ if (badgesInjected) return;
+ badgesInjected = true;
+
+ if (window.friendLinks) linkMap = buildMap(window.friendLinks);
+ if (window.friendFeeds) feedMap = buildMap(window.friendFeeds);
+
+ if (linkMap || feedMap) {
+ processBadges();
+ }
+};
+
+artalk.on('list-loaded', function() {
+ // Badge injection
+ badgesInjected = false;
+ setTimeout(injectAllBadges, 300);
+
+ if (window.artalkConfig.aiComment) {
+ var ai = window.artalkConfig.aiComment;
+ var listBody = document.querySelector('.atk-list .atk-list-body');
+ if (listBody && !listBody.querySelector('.atk-ai-comment')) {
+ var aiCommentHtml = `
+
+ `;
+ listBody.insertAdjacentHTML('afterbegin', aiCommentHtml);
+
+ var noComment = document.querySelector('.atk-list-no-comment');
+ if (noComment) {
+ noComment.style.display = 'none';
+ }
+ }
+ }
+
+ // Add staggered animation to the comment list
+ var list = document.querySelector('.atk-list');
+ if (list) {
+ list.setAttribute('uk-scrollspy', 'target: > .atk-comment-wrap; cls: uk-animation-slide-bottom-small; delay: 50');
+ }
+
+ // Apply granular animations to inner elements
+ document.querySelectorAll('.atk-comment-wrap:not(.atk-ai-comment)').forEach(function(wrap) {
+ var avatar = wrap.querySelector('.atk-avatar');
+ if (avatar) avatar.setAttribute('uk-scrollspy', 'cls: uk-animation-scale-up; delay: 200');
+
+ var main = wrap.querySelector('.atk-main');
+ if (main) main.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-right-small; delay: 300');
+
+ var nick = wrap.querySelector('.atk-nick');
+ if (nick) nick.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-top-small; delay: 350');
+ });
+
+ // Trigger lazy load update
+ if (window.lazyLoadAgain) {
+ window.lazyLoadAgain();
+ }
+
+ // Force hide "No Comment" if AI comment exists
+ if (window.artalkConfig.aiComment) {
+ var noComment = document.querySelector('.atk-list-no-comment');
+ var aiComment = document.querySelector('.atk-ai-comment');
+ if (aiComment && noComment) {
+ noComment.style.display = 'none';
+ }
+ }
+});
} catch (e) {
console.error('Artalk init failed:', e);
diff --git a/themes/Ying/assets/js/modules/utils.js b/themes/Ying/assets/js/modules/utils.js
index 0f77b14b..850b37b3 100644
--- a/themes/Ying/assets/js/modules/utils.js
+++ b/themes/Ying/assets/js/modules/utils.js
@@ -1,43 +1,41 @@
function themeSweep(newTheme, callback) {
- var veil = document.createElement('div');
- var gradient = newTheme === 'dark'
- ? 'linear-gradient(135deg,rgba(2,6,23,0.18),rgba(15,23,42,0.55) 45%,rgba(30,41,59,0.36))'
- : 'linear-gradient(135deg,rgba(255,247,237,0.28),rgba(252,250,245,0.62) 45%,rgba(254,243,199,0.32))';
+ // View Transition API — browser-native crossfade, zero JS animation overhead.
+ // Same principle as image lightbox transitions. Chrome/Edge 111+, Opera 97+.
+ if (document.startViewTransition) {
+ document.startViewTransition(function() { callback(); });
+ return;
+ }
- veil.style.cssText =
+ // Fallback: lightweight overlay for Safari / Firefox
+ var oldTheme = document.documentElement.getAttribute('data-theme');
+ var tint = oldTheme === 'dark'
+ ? 'rgba(15,23,42,0.95)'
+ : 'rgba(255,255,255,0.95)';
+
+ var overlay = document.createElement('div');
+ overlay.style.cssText =
'position:fixed;inset:0;z-index:9999;pointer-events:none;' +
- 'background:' + gradient + ';' +
- 'opacity:0;transition:opacity 0.42s cubic-bezier(0.22,0.61,0.36,1);' +
+ 'background:' + tint + ';opacity:1;' +
+ 'transition:opacity 0.22s ease;' +
'will-change:opacity;contain:paint;';
- document.body.appendChild(veil);
+ document.body.appendChild(overlay);
var cleaned = false;
function cleanup() {
if (cleaned) return;
cleaned = true;
- if (veil.parentNode) veil.parentNode.removeChild(veil);
+ if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
}
- var applied = false;
- function applyTheme() {
- if (applied) return;
- applied = true;
- callback();
- veil.style.opacity = '0';
- }
+ callback();
+ overlay.offsetWidth;
+ overlay.style.opacity = '0';
- veil.offsetWidth;
- veil.style.opacity = '1';
-
- setTimeout(applyTheme, 300);
- veil.addEventListener('transitionend', function(e) {
- if (!applied || e.propertyName !== 'opacity') return;
+ overlay.addEventListener('transitionend', function(e) {
+ if (e.propertyName !== 'opacity') return;
cleanup();
});
- setTimeout(function() {
- applyTheme();
- cleanup();
- }, 950);
+ setTimeout(cleanup, 380);
}
// Toast Message Helper
@@ -85,23 +83,36 @@ window.initThemeToggle = function() {
window.initCodeFold = function() {
var codeBlocks = document.querySelectorAll('.highlight');
codeBlocks.forEach(function(block) {
- if (block.offsetHeight > 360) {
- if (block.parentNode.classList.contains('code-fold-container')) return;
+ var wrapper = block.parentNode && block.parentNode.classList.contains('code-fold-container') ? block.parentNode : null;
+ if (!wrapper && block.scrollHeight <= 360 && block.offsetHeight <= 360) return;
- var wrapper = document.createElement('div');
+ if (!wrapper) {
+ wrapper = document.createElement('div');
wrapper.className = 'code-fold-container collapsed';
block.parentNode.insertBefore(wrapper, block);
wrapper.appendChild(block);
+ }
- var btn = document.createElement('button');
+ var btn = wrapper.querySelector(':scope > .code-expand-btn');
+ if (!btn) {
+ btn = document.createElement('button');
+ btn.type = 'button';
btn.className = 'code-expand-btn';
- btn.innerHTML = ' 展开代码 ';
- btn.onclick = function() {
- wrapper.classList.remove('collapsed');
- btn.style.display = 'none';
- };
wrapper.appendChild(btn);
}
+
+ var syncButton = function() {
+ var collapsed = wrapper.classList.contains('collapsed');
+ btn.innerHTML = collapsed
+ ? ' 展开代码 '
+ : ' 收起代码 ';
+ };
+
+ btn.onclick = function() {
+ wrapper.classList.toggle('collapsed');
+ syncButton();
+ };
+ syncButton();
});
};
diff --git a/themes/Ying/layouts/partials/artalk.html b/themes/Ying/layouts/partials/artalk.html
index 445309ad..bda89eb6 100644
--- a/themes/Ying/layouts/partials/artalk.html
+++ b/themes/Ying/layouts/partials/artalk.html
@@ -26,6 +26,69 @@
color: #ffffff !important;
background: #ff6262 !important;
}
+ .atk-link-badge,
+ .atk-feed-badge,
+ .atk-rank-badge {
+ display: inline-block;
+ margin-left: 4px;
+ padding: 0 6px;
+ font-size: 12px;
+ font-weight: 500;
+ border-radius: 3px;
+ line-height: 18px;
+ vertical-align: middle;
+ pointer-events: none;
+ white-space: nowrap;
+ }
+ .atk-link-badge {
+ color: #059669;
+ background: rgba(5,150,105,0.08);
+ border: 1px solid rgba(5,150,105,0.15);
+ }
+ .atk-feed-badge {
+ color: #d97706;
+ background: rgba(217,119,6,0.08);
+ border: 1px solid rgba(217,119,6,0.15);
+ }
+ .atk-rank-badge {
+ color: #fff;
+ background: #3b82f6;
+ border: none;
+ font-weight: 600;
+ }
+ [data-theme="dark"] .atk-link-badge {
+ color: #34d399;
+ background: rgba(52,211,153,0.12);
+ border-color: rgba(52,211,153,0.2);
+ }
+ [data-theme="dark"] .atk-feed-badge {
+ color: #fbbf24;
+ background: rgba(251,191,36,0.12);
+ border-color: rgba(251,191,36,0.2);
+ }
+ [data-theme="dark"] .atk-rank-badge {
+ background: #2563eb;
+ }
+
+ /* 覆盖 Artalk 原版 .atk-badge(博主)/ .atk-pinned-badge(置顶)尺寸 */
+ .atk-comment>.atk-main>.atk-header .atk-badge {
+ font-size: 12px;
+ padding: 0 6px;
+ font-weight: 500;
+ line-height: 18px;
+ border-radius: 3px;
+ vertical-align: middle;
+ color: #fff !important;
+ background: #1a1a1a !important;
+ }
+ .atk-comment>.atk-main>.atk-header .atk-pinned-badge {
+ font-size: 12px;
+ padding: 0 6px;
+ font-weight: 500;
+ line-height: 18px;
+ border-radius: 3px;
+ vertical-align: middle;
+ }