diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css
index e780c329..ee9e5123 100644
--- a/themes/Ying/assets/css/main.css
+++ b/themes/Ying/assets/css/main.css
@@ -4607,19 +4607,15 @@ input[type=submit] {
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
+/* 评论徽章(博主/置顶等)的尺寸与配色统一由 layouts/partials/artalk.html 里的
+ .atk-cmt-badge 规则管理。这里保留兼容但不再强制 padding/font-size,避免
+ !important 覆盖导致博主/置顶徽章比其他徽章高 2px、宽 2px。 */
.atk-pinned-badge {
- background-color: var(--text-highlight-color) !important;
- color: #fff !important;
- border-radius: 3px !important;
- font-size: 12px !important;
- padding: 1px 5px !important;
+ border-radius: 3px;
}
.atk-badge {
- background-color: #999 !important; /* 普通徽章颜色 */
- color: #fff !important;
- border-radius: 3px !important;
- padding: 1px 5px !important;
+ border-radius: 3px;
}
/* Emoticons & Images */
diff --git a/themes/Ying/assets/js/modules/artalk.js b/themes/Ying/assets/js/modules/artalk.js
index 38ae2995..68f88983 100644
--- a/themes/Ying/assets/js/modules/artalk.js
+++ b/themes/Ying/assets/js/modules/artalk.js
@@ -672,8 +672,10 @@ artalk.on('comment-rendered', function(node) {
var linkMatch = matchBadge(linkMap, host, nickLower);
var feedMatch = matchBadge(feedMap, host, nickLower);
- // 官方系统徽章(博主等)由 Artalk 渲染在 .atk-badge-wrap,把它挪进
- // 昵称元素内,保证视觉顺序:系统徽章 > 头衔 > 友链 > 友圈 > 官职
+ // 系统徽章(博主/置顶)由 Artalk 渲染在 .atk-badge-wrap 里,头衔/友链/友圈/官职
+ // 则是直接插进昵称的 —— 两套 DOM 会导致尺寸与垂直对齐都不一致。这里把包装层
+ // 拆掉,让所有徽章都成为昵称的直接子元素,视觉顺序:
+ // 系统徽章 > 头衔 > 友链 > 友圈 > 官职
var badgeWrap = el.querySelector('.atk-badge-wrap');
if (badgeWrap && badgeWrap.parentNode !== nickEl) nickEl.appendChild(badgeWrap);
@@ -691,6 +693,20 @@ artalk.on('comment-rendered', function(node) {
if (data.rank_count != null) tip += ' (' + data.rank_count + '条评论)';
injectBadge(nickEl, 'atk-rank-badge', data.rank_name, tip, data.rank_color || '', data.rank_bg || '');
}
+
+ // 5) 拆掉 .atk-badge-wrap 包装层:把 博主/置顶 提成昵称的直接子元素(保持原顺序)
+ var wrap = nickEl.querySelector('.atk-badge-wrap');
+ if (wrap && wrap.parentNode) {
+ var wrapParent = wrap.parentNode;
+ while (wrap.firstChild) wrapParent.insertBefore(wrap.firstChild, wrap);
+ wrapParent.removeChild(wrap);
+ }
+ // 6) 所有徽章挂同一个类,几何样式(尺寸/内边距/圆角/字重/对齐)只由
+ // .atk-cmt-badge 一处定义,从此不会有"两种徽章尺寸不一致"的问题
+ var allBadges = nickEl.querySelectorAll(
+ '.atk-badge, .atk-pinned-badge, .atk-title-badge, .atk-link-badge, .atk-feed-badge, .atk-rank-badge'
+ );
+ for (var bi = 0; bi < allBadges.length; bi++) allBadges[bi].classList.add('atk-cmt-badge');
} catch (e) { /* 徽章注入失败不影响评论 */ }
// ── 友链申请入口卡片:评论内容就是约定 URL(https://usj.cc/link-apply)时,
@@ -716,7 +732,9 @@ artalk.on('comment-rendered', function(node) {
var avImg = el2.querySelector('.atk-avatar img');
var avatarSrc = avImg ? avImg.getAttribute('src') : '';
var nickEl2 = el2.querySelector('.atk-nick');
- var sysBadge = (nickEl2 || el2).querySelector('.atk-badge-wrap');
+ // wrap 已在上面拆掉,博主徽章现在是昵称的直接子元素
+ var sysBadge = (nickEl2 || el2).querySelector('.atk-badge') ||
+ el2.querySelector('.atk-badge');
var nickText = String(d2.nick || '博主');
// 隐藏评论常规元素(头像列/昵称行/页脚操作),整条变成一张卡片
@@ -730,40 +748,67 @@ artalk.on('comment-rendered', function(node) {
if (meta) meta.style.display = 'none';
var main = el2.querySelector('.atk-main') || el2;
- main.style.marginLeft = '0'; // 卡片占满整行,原头像列不再占位(修复错位)
-
var contentEl = main.querySelector('.atk-content');
+ // 卡片挂在 .atk-comment 这一级,而不是塞进 .atk-content 里:
+ // .atk-main 被主题锁了 margin-left:34px !important(头像缩进),塞在里面
+ // 卡片永远比评论输入框窄一圈;提到 .atk-comment 这一级就能和输入框同宽对齐。
+ var commentEl = el2.querySelector('.atk-comment') || main.parentElement || el2;
+ if (main && main !== el2) main.style.display = 'none'; // 常规内容整块隐藏
+
+ var FL_DESC = '想和我交换友链?点击申请,审核结果会邮件通知你';
var card = document.createElement('div');
- card.className = 'atk-fl-apply';
+ card.className = 'atk-fl-card'; // 独立类名:容器用的是 atk-fl-apply 做标记
// 跟随评论列表原生观感:白底 + 细边框,只有按钮带主题色
card.style.cssText = 'display:flex;align-items:center;gap:12px;padding:12px 14px;margin:2px 0;' +
'background:var(--bg-card,#fff);border:1px solid var(--border-main,#eeeeee);' +
'border-radius:10px;transition:border-color .2s,background .2s;';
card.innerHTML =
- '
' +
+ '
' +
'' +
- '' +
+ '' +
'' + nickText.replace(/' +
'' +
- '想和我交换友链?点击申请,审核结果会邮件通知你' +
+ '' +
+ '' +
+ '' +
'' +
- '申请友链';
+ '申请友链';
// 昵称行追加官方徽章(博主),样式与评论区徽章一致
if (sysBadge) {
var bw = sysBadge.cloneNode(true);
- bw.style.marginLeft = '2px';
+ bw.style.marginLeft = '0';
var nickRow = card.querySelector('span > span');
nickRow.appendChild(bw);
}
- if (contentEl) {
- contentEl.innerHTML = '';
- contentEl.appendChild(card);
- contentEl.style.cursor = 'pointer';
- } else {
- main.appendChild(card);
- }
+ // 卡片直接挂在评论节点(.atk-comment)下:宽度与评论输入框一致
+ if (contentEl) contentEl.innerHTML = '';
+ commentEl.appendChild(card);
+
+ // ── 打字机效果(PJAX 安全:卡片被移除/替换时定时器自动停止) ──
+ // 注意:不要用 prefers-reduced-motion 跳过打字 —— Windows 关闭"动画效果"
+ // 或部分浏览器默认就会报告 reduce,会导致效果完全不出现。这里始终打字。
+ try {
+ var typedEl = card.querySelector('.atk-fl-typed');
+ var caretEl = card.querySelector('.atk-fl-caret');
+ var alive = function () { return card.isConnected !== undefined ? card.isConnected : document.body.contains(card); };
+ if (typedEl) {
+ var ti = 0;
+ setTimeout(function () {
+ if (!alive()) return;
+ var timer = setInterval(function () {
+ if (!alive()) { clearInterval(timer); return; } // PJAX 切页后自动停止
+ ti += 1;
+ typedEl.textContent = FL_DESC.slice(0, ti);
+ if (ti >= FL_DESC.length) {
+ clearInterval(timer);
+ if (caretEl) caretEl.style.display = 'none';
+ }
+ }, 42);
+ }, 320); // 等入场动画播完再打字,观感更自然
+ }
+ } catch (e) {}
el2.addEventListener('click', function () {
if (window.flApplyOpenModal) window.flApplyOpenModal();
diff --git a/themes/Ying/layouts/page/comment.html b/themes/Ying/layouts/page/comment.html
index 4b1de925..44ab980e 100644
--- a/themes/Ying/layouts/page/comment.html
+++ b/themes/Ying/layouts/page/comment.html
@@ -46,10 +46,19 @@
'background:var(--bg-input,#fff);color:inherit;font-family:inherit}' +
'#flApplyBox input:focus,#flApplyBox textarea:focus{outline:none;border-color:var(--theme-main,#07c160);' +
'box-shadow:0 0 0 3px var(--theme-main-20,rgba(7,193,96,.2))}' +
- '#flSubmit{width:100%;background:var(--theme-main,#07c160);border:none;color:#fff;padding:10px;' +
- 'border-radius:6px;font-size:14px;cursor:pointer;transition:filter .2s}' +
+ /* 主题 main.css 有一条全局 button 归一化规则(margin-left:23%; margin-top:10px;
+ border:1px solid; background:#222),会把提交按钮推右溢出弹窗 → 这里用 id 选择器压过它 */
+ '#flSubmit{display:block;width:100%;margin:0;background:var(--theme-main,#07c160);border:none;color:#fff;' +
+ 'padding:11px 0;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:filter .2s}' +
'#flSubmit:hover{filter:brightness(1.06)}' +
- '#flSubmit:disabled{opacity:.6;cursor:default}';
+ '#flSubmit:disabled{opacity:.6;cursor:default}' +
+ /* 弹窗滚动条:细一点、跟随主题色,别用系统那根粗滚动条 */
+ '#flApplyBox{overflow-x:hidden;scrollbar-width:thin;scrollbar-color:rgba(140,150,160,.45) transparent}' +
+ '#flApplyBox::-webkit-scrollbar{width:6px;height:6px}' +
+ '#flApplyBox::-webkit-scrollbar-track{background:transparent}' +
+ '#flApplyBox::-webkit-scrollbar-thumb{background:rgba(140,150,160,.45);border-radius:3px}' +
+ '[data-theme="dark"] #flApplyBox{scrollbar-color:rgba(200,205,212,.35) transparent}' +
+ '[data-theme="dark"] #flApplyBox::-webkit-scrollbar-thumb{background:rgba(200,205,212,.35)}';
document.head.appendChild(style);
mask = document.createElement('div');
diff --git a/themes/Ying/layouts/partials/artalk.html b/themes/Ying/layouts/partials/artalk.html
index 5c919c23..367522a6 100644
--- a/themes/Ying/layouts/partials/artalk.html
+++ b/themes/Ying/layouts/partials/artalk.html
@@ -15,24 +15,30 @@
border-color: var(--frame-dark-color);
background: transparent;
}
- /* ================= 评论徽章规格 =================
- 几何完全沿用原设计:inline-block + margin-left:4px + padding 0 6px
- + 12px/500 字重 + line-height:18px + 1px 描边 + 3px 圆角。
- 注意:不要覆盖 Artalk 自带的 margin-right:6px,否则徽章会挤在一起。 */
- .atk-comment>.atk-main>.atk-header .atk-badge,
- .atk-comment>.atk-main>.atk-header .atk-pinned-badge,
- .atk-comment>.atk-main>.atk-header .atk-title-badge,
- .atk-comment>.atk-main>.atk-header .atk-link-badge,
- .atk-comment>.atk-main>.atk-header .atk-feed-badge,
- .atk-comment>.atk-main>.atk-header .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;
+ /* ================= 评论徽章统一规格(单一来源) =================
+ 几何沿用原设计:inline-block + margin-left:4px + padding 0 6px + 12px/500
+ + line-height:18px + 1px 描边 + 3px 圆角。
+ artalk.js 会把所有徽章(博主/置顶/头衔/友链/友圈/官职)都挂上 .atk-cmt-badge
+ 并拆掉 Artalk 的 .atk-badge-wrap 包装层,所以几何只在这里定义一次,
+ 不会再出现两种 DOM / 两种尺寸。各类型只保留配色差异。
+ 注:margin-right 清零是为了不叠加 Artalk 给"非最后一个徽章"的 6px 右间距
+ (否则 徽章→徽章 间距一宽一窄,看起来不齐)。 */
+ .atk-comment .atk-cmt-badge,
+ .atk-comment .atk-badge,
+ .atk-comment .atk-pinned-badge,
+ .atk-comment .atk-title-badge,
+ .atk-comment .atk-link-badge,
+ .atk-comment .atk-feed-badge,
+ .atk-comment .atk-rank-badge {
+ display: inline-block !important;
+ margin-left: 4px !important;
+ margin-right: 0 !important;
+ padding: 0 6px !important;
+ font-size: 12px !important;
+ font-weight: 600 !important;
+ border-radius: 3px !important;
+ line-height: 18px !important;
+ vertical-align: middle !important;
pointer-events: none;
white-space: nowrap;
}
@@ -50,37 +56,24 @@
color: #6b7280;
background: rgba(107,114,128,0.08);
border: 1px solid rgba(107,114,128,0.15);
- font-weight: 600;
}
.atk-title-badge {
- font-weight: 600;
color: #b8860b;
background: rgba(184,134,11,0.08);
border: 1px solid rgba(184,134,11,0.22);
}
- /* 博主(.atk-badge):浅底描边(与友链/友圈/官职同风格)
+ /* 博主(.atk-badge):实底 —— 白字 + 浅黑底
(!important 是为了盖掉 Artalk 写在元素上的内联背景色) */
- .atk-comment>.atk-main>.atk-header .atk-badge {
- border: 1px solid rgba(55,65,81,0.18);
- font-weight: 600;
- color: #374151 !important;
- background: rgba(55,65,81,0.06) !important;
+ .atk-comment .atk-badge {
+ border: 1px solid #333333;
+ color: #ffffff !important;
+ background: #333333 !important;
}
- [data-theme="dark"] .atk-comment>.atk-main>.atk-header .atk-badge {
- border-color: rgba(229,231,235,0.2);
- color: #e5e7eb !important;
- background: rgba(229,231,235,0.08) !important;
- }
- /* 置顶徽章:浅底红字描边(与友链/友圈同风格,比实底红更协调、不刺眼) */
- .atk-comment>.atk-main>.atk-header .atk-pinned-badge {
- border: 1px solid rgba(217,83,79,0.18);
- color: #d9534f !important;
- background: rgba(217,83,79,0.08) !important;
- }
- [data-theme="dark"] .atk-comment>.atk-main>.atk-header .atk-pinned-badge {
- border-color: rgba(217,83,79,0.28);
- color: #f0918d !important;
- background: rgba(217,83,79,0.14) !important;
+ /* 置顶徽章:实底 —— 白字 + 浅红底(比 #d9534f / #ff6262 更浅,不刺眼) */
+ .atk-comment .atk-pinned-badge {
+ border: 1px solid #e05a5a;
+ color: #ffffff !important;
+ background: #e05a5a !important;
}
/* ---- 暗色模式配色 ---- */
[data-theme="dark"] .atk-link-badge {
@@ -103,6 +96,51 @@
background: rgba(251,191,36,0.12);
border-color: rgba(251,191,36,0.2);
}
+ /* ================= 友链申请入口卡片 =================
+ PJAX 下每次切页评论区都会重建卡片 → 入场动画与打字机自然重播;
+ 打字机定时器在 artalk.js 里会检测卡片是否还在文档中(切页后自动停)。 */
+ .atk-fl-card {
+ animation: flApplyIn .5s cubic-bezier(.22, 1, .36, 1) both;
+ }
+ @keyframes flApplyIn {
+ from { opacity: 0; transform: translateY(12px) scale(.98); }
+ to { opacity: 1; transform: none; }
+ }
+ .atk-fl-card:hover {
+ border-color: var(--theme-main-30, rgba(7,193,96,.3)) !important;
+ }
+ /* 打字机光标 */
+ .atk-fl-card .atk-fl-caret {
+ display: inline-block;
+ width: 1px;
+ height: 1em;
+ margin-left: 2px;
+ vertical-align: -2px;
+ background: currentColor;
+ animation: flCaret .9s steps(1, end) infinite;
+ }
+ @keyframes flCaret {
+ 0%, 49% { opacity: 1; }
+ 50%, 100% { opacity: 0; }
+ }
+ /* 申请友链按钮:轻微上浮 + 主题色投影 */
+ .atk-fl-card .atk-fl-btn {
+ transition: transform .2s ease, box-shadow .2s ease;
+ }
+ .atk-fl-card:hover .atk-fl-btn {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px var(--theme-main-20, rgba(7,193,96,.2));
+ }
+ .atk-fl-card .atk-fl-btn:active {
+ transform: translateY(0);
+ }
+ /* 尊重系统"减弱动态效果":只关掉入场动画和按钮位移,
+ 打字机与光标保留(打字机是文字渐显,不属于会造成不适的位移类动效) */
+ @media (prefers-reduced-motion: reduce) {
+ .atk-fl-card { animation: none; }
+ .atk-fl-card .atk-fl-btn { transition: none; }
+ .atk-fl-card:hover .atk-fl-btn { transform: none; box-shadow: none; }
+ }
.atk-main {
backface-visibility: hidden;
will-change: transform;