diff --git a/assets/css/frontend/comment-tools.css b/assets/css/frontend/comment-tools.css index e46ff0b3..dba32dbe 100644 --- a/assets/css/frontend/comment-tools.css +++ b/assets/css/frontend/comment-tools.css @@ -1,140 +1,10 @@ /** * AKSRT Comment Tools * - * 评论工具栏样式:表情、代码、图片上传、快捷回复。 - * 所有选择器均带 .comment- 或 .aksrt-comment- 命名空间。 + * 评论内容中的代码块样式。工具栏(表情/代码/图片/快捷回复)的 UI + * 由 assets/css/frontend/comments/shell.css 按 zibll 选择器提供。 */ -/* ========== 评论工具栏 ========== */ -.comment-toolbar { - display: flex; - align-items: center; - gap: 4px; - padding: 6px 8px; - margin-bottom: 8px; - background: var(--surface-secondary, #f8f9fa); - border: 1px solid var(--color-line, #e8e8e8); - border-radius: 8px; -} - -.comment-toolbar__btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - border: none; - border-radius: 6px; - background: transparent; - color: var(--text-secondary, #666); - font-size: 14px; - cursor: pointer; - transition: background-color 0.15s ease, color 0.15s ease; -} - -.comment-toolbar__btn:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); - color: var(--color-primary); -} - -.comment-toolbar__btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.comment-toolbar__separator { - width: 1px; - height: 20px; - margin: 0 4px; - background: var(--color-line, #e8e8e8); -} - -/* Server-side toolbar gating (comment_smilie / comment_code / comment_img): - the .comment-toolbar__btn display rule outranks the UA [hidden] rule, so an - attribute-qualified selector is needed to honor the rendered hidden state. */ -.comment-toolbar__btn[hidden], -.comment-toolbar__separator[hidden] { - display: none; -} - -/* ========== 表情选择器 ========== */ -.comment-emoji-picker { - position: absolute; - bottom: 100%; - left: 0; - z-index: 100; - width: 320px; - max-height: 240px; - padding: 12px; - background: var(--surface-page, #fff); - border: 1px solid var(--color-line, #e8e8e8); - border-radius: 8px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); - overflow-y: auto; -} - -.comment-emoji-picker__grid { - display: grid; - grid-template-columns: repeat(8, 1fr); - gap: 4px; -} - -.comment-emoji-picker__item { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - border: none; - border-radius: 4px; - background: transparent; - font-size: 18px; - cursor: pointer; - transition: background-color 0.1s ease; -} - -.comment-emoji-picker__item:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); -} - -/* ========== 快捷回复 ========== */ -.comment-quick-reply { - padding: 8px 12px; - margin-top: 8px; - background: var(--surface-secondary, #f8f9fa); - border: 1px solid var(--color-line, #e8e8e8); - border-radius: 8px; -} - -.comment-quick-reply__title { - font-size: 12px; - font-weight: 600; - color: var(--text-secondary, #666); -} - -.comment-quick-reply__templates { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-top: 6px; -} - -.comment-quick-reply__template { - padding: 4px 10px; - border: 1px solid var(--color-line, #e8e8e8); - border-radius: 16px; - background: var(--surface-page, #fff); - font-size: 12px; - color: var(--text-secondary, #666); - cursor: pointer; - transition: border-color 0.15s ease, color 0.15s ease; -} - -.comment-quick-reply__template:hover { - border-color: var(--color-primary); - color: var(--color-primary); -} - /* ========== 评论代码块 ========== */ .comment-form textarea code, .comment-content code { diff --git a/assets/css/frontend/comments/mobile-item.css b/assets/css/frontend/comments/mobile-item.css index 63f4ecd5..9ac7217d 100644 --- a/assets/css/frontend/comments/mobile-item.css +++ b/assets/css/frontend/comments/mobile-item.css @@ -1,112 +1,175 @@ -/* Zibll 1:1 FixedInput / virtual-input / item chrome */ -.virtual-input { display: none; } -@media (max-width: 767.98px) { - .virtual-input { - display: flex; align-items: center; gap: 10px; - padding: 10px 12px; margin-bottom: 12px; border-radius: 999px; - background: var(--surface-1, #fff); - box-shadow: var(--shadow-sm, 0 1px 4px rgba(0,0,0,.06)); - cursor: pointer; - } - .virtual-input .avatar-img { width: 32px; height: 32px; border-radius: 50%; } - .virtual-input .simulation { flex: 1; color: var(--color-ink-4, #999); font-size: 13px; } - #respond.mobile-fixed { - position: fixed; left: 0; right: 0; bottom: 0; z-index: 1050; - background: var(--surface-1, #fff); - border-radius: 12px 12px 0 0; - box-shadow: 0 -8px 28px rgba(0,0,0,.12); - padding: 12px 14px max(12px, env(safe-area-inset-bottom)); - transform: translateY(110%); transition: transform .25s ease; - max-height: 85vh; overflow: auto; - } - #respond.mobile-fixed.show { transform: translateY(0); } - #respond.mobile-fixed .fixed-body { - position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: -1; - opacity: 0; pointer-events: none; transition: opacity .2s ease; - } - #respond.mobile-fixed.show .fixed-body { opacity: 1; pointer-events: auto; } - #respond.mobile-fixed .comt-title { display: none; } -} -.comment-header .author-box { display: flex; align-items: center; gap: 8px; width: 100%; } -.comment-header .author-box name, -.comment-header .author-box .flex1 { flex: 1; min-width: 0; } -/* Keep name + level badge on one line; clamp the name so the badge never wraps. */ -.comment-header .author-box name { flex-wrap: nowrap; } -.comment-header .author-box .aksrt-comment__author { max-width: 14em; } -.comment-header .aksrt-comment__like, -.comment-header .action-comment-like { - margin-left: auto; display: inline-flex; align-items: center; gap: 4px; - color: var(--color-ink-3, #888); text-decoration: none; font-size: 13px; -} -.comment-header .aksrt-comment__like.is-active { color: var(--color-primary, #2060ef); } -.comt-meta { - display: flex; flex-wrap: wrap; align-items: center; gap: 8px; - font-size: 12px; margin-top: 6px; -} -.comt-meta .reply-link a, .comt-meta .comment-reply-link { color: var(--color-ink-3, #777); } -.comment-action-dropdown .dropdown-menu { min-width: 140px; padding: 6px 0; } -.comment-action-dropdown .dropdown-menu a { - display: block; padding: 6px 14px; color: var(--color-ink, #333); - text-decoration: none; font-size: 13px; -} -.comment-action-dropdown .dropdown-menu a:hover { background: var(--surface-2, #f5f5f5); } -.smilie-icon { width: 30px; height: 30px; vertical-align: -8px; display: inline-block; } -.comment-inline-img, .comment-content .box-img { - max-width: 260px; max-height: 350px; border-radius: 6px; display: block; margin: 6px 0; -} -.comment-code { - background: var(--surface-2, #f6f8fa); padding: 10px 12px; border-radius: 6px; - overflow: auto; font-size: 12px; -} -.commentlist .children { margin-left: 86px; padding-left: 0; list-style: none; } -.commentlist .children .children { margin-left: 23px; } -.commentlist .children .comt-avatar, -.commentlist .children .avatar-img.comt-avatar { width: 26px !important; height: 26px !important; } -.input-expand-wrap { display: inline-block; position: relative; } -.input-expand-wrap .dropdown-menu, -.input-expand-wrap .dropdown-smilie { - display: none; position: absolute; bottom: 100%; left: 0; z-index: 20; - background: var(--surface-1, #fff); box-shadow: 0 6px 24px rgba(0,0,0,.12); - border-radius: 8px; padding: 8px; -} -.input-expand-wrap.open > .dropdown-menu, -.input-expand-wrap.open .dropdown-smilie, -.dropup.open > .dropdown-menu { display: block; } -.dropdown-smilie { - display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; - max-width: 280px; max-height: 200px; overflow: auto; -} -.dropdown-smilie a img { width: 28px; height: 28px; } -.quick-reply-item { - display: block; padding: 6px 10px; color: var(--color-ink, #333); - text-decoration: none; font-size: 13px; -} -.quick-reply-item:hover { background: var(--surface-2, #f5f5f5); } -.comt-ctrl { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; } -.comt-tips-left { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; flex: 1; } -.comt-tips-right { margin-left: auto; display: flex; align-items: center; gap: 8px; } -#comments .comt-title { width: 90px; } -#comments .comt-title .comt-avatar img, -#comments .comt-avatar .avatar-img { width: 60px; height: 60px; border-radius: 50%; } -#comments .comt-box #comment { min-height: 88px; resize: vertical; } -@media (min-width: 768px) { .hide-pc { display: none !important; } } +/* ============================================================ + * AKSRT Comments — Zibll 1:1 移动端 + FixedInput / virtual-input + * + * 移动端规则来源:zibll/css/main.css 移动端媒体查询中的评论段。 + * ============================================================ */ -/* IP geo badges */ -.comt-meta .comment-city-badge, -.comt-meta .aksrt-ip-geo-badge { - margin-left: 0.35em; - vertical-align: middle; +.virtual-input { + display: none; } -.aksrt-author-hero__identity .aksrt-ip-geo-badge, -.uc-header__meta .aksrt-ip-geo-badge, -.article-avatar .aksrt-ip-geo-badge { - margin: 2px 0; - vertical-align: middle; + +/* 移动端虚拟输入条 + 吸底表单(FixedInput) */ +@media (max-width: 767.98px) { + .virtual-input { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + margin-bottom: 12px; + border-radius: 999px; + background: var(--surface-1, #fff); + box-shadow: var(--shadow-sm, 0 1px 4px rgba(0, 0, 0, .06)); + cursor: pointer; + } + + .virtual-input .avatar, + .virtual-input .avatar-img { + width: 32px; + height: 32px; + border-radius: 50%; + } + + .virtual-input .simulation { + flex: 1; + color: var(--color-ink-4, #999); + font-size: 13px; + } + + #respond.mobile-fixed { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 1050; + background: var(--surface-1, #fff); + border-radius: 12px 12px 0 0; + box-shadow: 0 -8px 28px rgba(0, 0, 0, .12); + padding: 12px 14px max(12px, env(safe-area-inset-bottom)); + transform: translateY(110%); + transition: transform .25s ease; + max-height: 85vh; + overflow: auto; + } + + #respond.mobile-fixed.show { + transform: translateY(0); + } + + #respond.mobile-fixed .fixed-body { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, .35); + z-index: -1; + opacity: 0; + pointer-events: none; + transition: opacity .2s ease; + } + + #respond.mobile-fixed.show .fixed-body { + opacity: 1; + pointer-events: auto; + } + + #respond.mobile-fixed .comt-title { + display: none; + } + + /* ---- zibll 移动端评论规则 ---- */ + #comments .comt-title { + display: none; + } + + #comments .comt-box { + width: 100%; + padding: 0; + } + + #comments .list-inline { + padding: 15px 0; + margin: 0; + } + + #comments .comment-signarea h3 { + font-size: 13px; + } + + #comments .comt-tips-left .but svg, + #comments .comt-tips-left .but .fa { + margin: 0; + } + + #comments .hide-sm { + display: none !important; + } + + #comments .btn-input-expand { + width: 31px; + padding: 0; + height: 31px; + line-height: 31px; + } + + #postcomments .comment-header { + font-size: 14px; + } + + #postcomments .comt-meta { + font-size: 12px; + } + + #postcomments .comment .list-inline > li { + padding: 0; + } + + #postcomments .comment .list-inline > li + li { + padding-left: 10px; + } + + #postcomments .avatar-img { + --this-size: 36px; + margin-right: 10px; + } + + #postcomments .commentlist > .comment > .list-inline .comment-footer { + margin-left: 45px; + margin-top: -15px; + } + + #postcomments .children { + margin-left: 0; + } + + #postcomments .children .children { + margin-left: 13px; + } + + #postcomments .children .list-inline { + padding: 15px; + } + + #comments .pagenav a, + #comments .pagination ul > li { + display: none; + } + + #comments .pagenav a.next, + #comments .pagenav a.prev { + display: inline-block; + } + + #comments .pagenav .page-numbers { + font-size: 12px; + margin: 2px; + min-width: 28px; + } + + #postcomments .post_ajax_loader .ml20 { + margin-left: 5px; + } } -.aksrt-author-hero__identity { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 0.35rem; - margin-top: 0.35rem; + +@media (min-width: 768px) { + .hide-pc { + display: none !important; + } } diff --git a/assets/css/frontend/comments/shell.css b/assets/css/frontend/comments/shell.css index 0c349678..50e6c782 100644 --- a/assets/css/frontend/comments/shell.css +++ b/assets/css/frontend/comments/shell.css @@ -1,787 +1,696 @@ /* ============================================================ - * AKSRT Comments — v4.0 Zibll-Inspired + * AKSRT Comments — Zibll 1:1 移植 * - * 功能: - * - 评论表单(头像 + 输入框 + 操作栏) - * - 评论列表(嵌套回复 + 头像 + 时间) - * - 排序/过滤栏 - * - 空状态 - * - 移动端固定底部输入框(可选) + * 来源:zibll/css/main.css L9412–9751(评论模块 + 分页)及评论所依赖的 + * 基础组件(title-theme / dropdown-menu / line-form / tab-nav-theme / + * 工具栏下拉 / placeholder 骨架)。除 Zibll 原生 #comments/#postcomments + * 作用域外,缺失的全局基础类一律以 #comments 前缀作用域移植,避免影响 + * 主题其它模块。 * ============================================================ */ -/* ============================================================ - * 评论区容器 - * ============================================================ */ -.comments-area { - margin: 0; - padding: 0; - /* 对齐 zibll: 45px */ - --aksrt-comment-avatar: 45px; - --aksrt-comment-avatar-form: 45px; - --aksrt-comment-indent: 48px; +/*------评论模块------*/ +#comments .comment-box .comments-closed, +#comments .action-text, +#comments #cancel-comment-reply-link { + display: none; } -/* 评论标题 */ -.comments-header { - margin-bottom: 16px; +#comments #postcomments .action-text, +#comments #postcomments #cancel-comment-reply-link { + display: inline-block; } -.comments-title { - font-size: 1rem; - font-weight: 700; - margin: 0; - display: flex; - align-items: center; - gap: 8px; - color: var(--color-ink); +#comments .comt-title { + width: 90px; } -.comments-title i { - color: var(--color-primary); - font-size: 16px; +#comments .comt-title .comt-avatar .avatar { + width: 60px; + height: 60px; } -.comments-count { - font-size: 0.8125rem; - font-weight: 400; - color: var(--color-ink-4); +#comments #postcomments .comt-title { + display: none; } -/* ============================================================ - * 登录提示 - * ============================================================ */ -.comment-login-prompt { - margin-bottom: 20px; +#respond:not(.mobile-fixed) #postcomments .comt-box { + padding: 5px 5px 4px 5px; + background: var(--main-bg-color); + border-radius: 4px; + margin-top: 12px; } -.comment-login-prompt__inner { - display: flex; - align-items: center; - gap: 12px; - padding: 16px 18px; - border-radius: var(--main-radius, var(--radius, 8px)); - background: var(--surface-1); - border: none; - box-shadow: var(--shadow-sm); - font-size: 14px; - color: var(--color-ink-4); +#comments #postcomments .comt-ctrl .but { + margin-bottom: 2px; } -.comment-login-prompt__inner i { - font-size: 16px; - color: var(--color-ink-4); +#comments .list-inline { + padding: 15px; + margin-left: 0; } -.comment-login-prompt__btns { - margin-left: auto; - display: flex; - gap: 8px; +#comments .list-inline > li { + vertical-align: middle; } -/* ============================================================ - * 评论表单 - * ============================================================ */ -.comment-respond { - margin-bottom: 20px; -} - -.comment-form__inner { - display: flex; - gap: 10px; - align-items: flex-start; -} - -.comment-form__avatar { - flex-shrink: 0; -} - -.comment-form__avatar img { - width: var(--aksrt-comment-avatar-form); - height: var(--aksrt-comment-avatar-form); - border-radius: 50%; - object-fit: cover; -} - -.comment-form__avatar-placeholder { - width: var(--aksrt-comment-avatar-form); - height: var(--aksrt-comment-avatar-form); - border-radius: 50%; - background: var(--surface-3); - display: flex; - align-items: center; - justify-content: center; - color: var(--color-ink-4); -} - -.comment-form__body { - flex: 1; - min-width: 0; -} - -.comment-form__reply-info { - font-size: 0.8125rem; - color: var(--color-ink-4); - margin-bottom: 8px; - display: flex; - align-items: center; - gap: 8px; -} - -.comment-form__cancel-reply { - color: var(--color-error, #ef4444); - font-size: 12px; -} - -.comment-form__textarea { +#comment { + margin-bottom: 5px; width: 100%; - min-height: 96px; - resize: vertical; - border-radius: 10px; - border: 1px solid var(--color-line); - padding: 12px 14px; - font-size: 14px; - background: var(--surface-4, var(--main-bg-color, var(--surface-1))); - color: var(--color-ink); - transition: border-color 0.2s ease, box-shadow 0.2s ease; } -.comment-form__textarea:focus { - outline: none; - border-color: var(--color-primary); - box-shadow: 0 0 0 3px var(--color-primary-soft); +.comment-signarea { + background: var(--main-shadow); } -.comment-form__actions { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 10px; - gap: 8px; +#respond + #postcomments .comment-filter, +.comment-signarea + #postcomments .comment-filter { + margin-top: 20px; } -.comment-form__tools { - display: flex; - gap: 8px; +#postcomments .tab-nav-theme { + margin-top: 0; } -.comment-form__submit-area { - display: flex; - align-items: center; - gap: 8px; - margin-left: auto; - flex-wrap: wrap; - justify-content: flex-end; +#postcomments .tab-nav-theme li { + padding-bottom: 1px; } -.comment-form__guest { - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 6px; +#postcomments .tab-nav-theme li::before { + bottom: -2px; } -.comment-form__guest-toggle { - background: none; - border: 0; - padding: 0; - cursor: pointer; - color: var(--muted-color, #8b9198); - white-space: nowrap; -} - -.comment-form__guest-toggle:hover, -.comment-form__guest-toggle[aria-expanded="true"] { - color: var(--focus-color, #f04494); -} - -.comment-form__guest-fields { - display: flex; - gap: 6px; - align-items: center; - max-height: 0; - overflow: hidden; - opacity: 0; - transition: max-height 0.2s ease, opacity 0.15s ease; -} - -.comment-form__guest-fields.is-open, -.comment-form__guest-fields:not([hidden]) { - max-height: 48px; - opacity: 1; -} - -.comment-form__guest-field { - width: 110px; - height: 30px; - font-size: 12px; - padding: 0 8px; -} - -.comt-box .comt-textarea, -.comt-box #comment { - min-height: 72px; - padding: 10px 12px; - border-radius: 8px; - font-size: 13px; - line-height: 1.5; - margin-bottom: 6px; -} - -.comt-ctrl { - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; -} - -.comment-form__submit { - height: 30px; - padding: 0 12px; - font-size: 13px; -} - -.comment-form__submit { - display: inline-flex; - align-items: center; - gap: 6px; -} - -/* ============================================================ - * 排序/过滤栏 - * ============================================================ */ -.comment-filter { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 0; - margin-bottom: 12px; - border-bottom: 1px solid var(--color-line); -} - -.comment-filter__tabs { - display: flex; - list-style: none; - margin: 0; - padding: 0; - gap: 4px; -} - -.comment-filter__tabs li a { +.smilie-icon { + width: 30px !important; display: inline-block; - padding: 4px 12px; - border-radius: 4px; - font-size: 13px; - font-weight: 500; - color: var(--color-ink-4); - text-decoration: none; - transition: background 0.15s ease, color 0.15s ease; + padding: 3px; } -.comment-filter__tabs li a:hover { - background: var(--surface-3); - color: var(--color-ink); +#postcomments .comment-footer { + position: relative; } -.comment-filter__tabs li.active a { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); - color: var(--color-primary); - font-weight: 600; -} - -/* Zibll-compatible class names used by aksrt-comments.php */ -.comment-order-box { - display: flex; - list-style: none; - margin: 0; - padding: 0; - gap: 4px; -} -.comment-order-box li a, -.comment-order-box .comment-orderby { - display: inline-block; - padding: 4px 12px; - border-radius: 4px; - font-size: 13px; - font-weight: 500; - color: var(--color-ink-4); - text-decoration: none; - transition: background 0.15s ease, color 0.15s ease; -} -.comment-order-box li a:hover, -.comment-order-box .comment-orderby:hover { - background: var(--surface-3); - color: var(--color-ink); -} -.comment-order-box li.active a, -.comment-order-box li.active .comment-orderby { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); - color: var(--color-primary); - font-weight: 600; -} -.btn-only-author, -.comment-author-filter { - display: inline-flex; - align-items: center; - padding: 4px 12px; - border-radius: 999px; - border: 1px solid var(--color-line); - background: var(--surface-1); - color: var(--color-ink-3); - font-size: 12px; - font-weight: 600; - text-decoration: none; - transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; -} -.btn-only-author:hover, -.comment-author-filter:hover { - border-color: var(--color-primary); - color: var(--color-primary); -} -.btn-only-author.active, -.comment-author-filter.active { - border-color: var(--color-primary); - background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); - color: var(--color-primary); -} - -/* ============================================================ - * 评论列表 - * ============================================================ */ -.comment-list { - list-style: none; - margin: 0; - padding: 0; -} - -.comment-list .comment { - padding: 16px 0; - border-bottom: 1px solid var(--color-line); -} - -.comment-list .comment:last-child { - border-bottom: none; -} - -/* 嵌套回复 — 对齐 zibll: 86px 缩进 + 灰色背景 */ -.comment-list .children { - list-style: none; - margin: 0; - margin-left: 86px; -} - -.comment-list .children .comment { - padding: 14px 16px; - background: var(--surface-4, rgba(0, 0, 0, 0.03)); - border: 1px solid var(--color-line-soft); - border-radius: var(--radius-lg); -} - -/* 深层嵌套缩进递减 */ -.comment-list .children .children { - margin-left: 13px; -} - -/* 评论项内部结构(由 aksrt_comment_callback 渲染) */ -.aksrt-comment__body { - display: flex; - gap: 12px; -} - -.aksrt-comment__avatar { - flex-shrink: 0; -} - -.aksrt-comment__avatar img { - width: var(--aksrt-comment-avatar); - height: var(--aksrt-comment-avatar); - border-radius: 50%; - object-fit: cover; +#postcomments .avatar-img { + --this-size: 45px; margin-right: 20px; } -.aksrt-comment__content { - flex: 1; - min-width: 0; +#postcomments .children .avatar-img { + --this-size: 26px; + vertical-align: 2px; + margin-right: 6px; } -.aksrt-comment__header { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 6px; - flex-wrap: wrap; +#postcomments .commentlist > .comment > .list-inline .author-box { + align-items: start; } -.aksrt-comment__author { - font-weight: 600; - font-size: 14px; - color: var(--color-ink); +#postcomments .commentlist > .comment > .list-inline .comment-footer { + margin-left: 65px; + margin-top: -25px; } -.aksrt-comment__author a { +#postcomments .comment .list-inline > .comt-main { + width: 100%; +} + +#postcomments .commentlist .comment + .comment { + border-top: 1px solid var(--main-border-color); +} + +#postcomments .comment .list-inline > li { + padding: 10px; + vertical-align: top; +} + +#postcomments .comment-header { + font-size: 15px; + position: relative; +} + +#postcomments .action count { + margin-left: 4px; +} + +#postcomments .comt-meta > span:not(:empty) { + margin-right: 10px; + vertical-align: middle; +} + +#postcomments .comt-meta > span a { color: inherit; } -.aksrt-comment__author a:hover { - color: var(--color-primary); +#postcomments .comt-meta > span .but { + padding: 0.2em 0.8em; } -.aksrt-comment__badge { - font-size: 10px; - padding: 1px 6px; - border-radius: 3px; - background: var(--color-primary-soft, rgba(240, 68, 148, 0.12)); - color: var(--color-primary); - font-weight: 500; +#postcomments .comment-approve-link.unapprove { + color: #e87725; } -.aksrt-comment__time { - font-size: 12px; - color: var(--color-ink-4); +#postcomments .comment-approve-link.approve { + color: #3695ff; } -.aksrt-comment__text { - font-size: 14px; - line-height: 1.6; - color: var(--color-ink); - margin: 0 0 8px; +#postcomments .comt-meta > span .comment-trash-link { + color: #ff4b4b; +} + +#postcomments .children { + margin-left: 86px; + background: var(--main-shadow); + border-radius: var(--main-radius); + margin-bottom: 6px; +} + +#postcomments .children .children { + margin-left: 23px; +} + +#postcomments .children .avatar-icontag { + font-size: 8px; + height: 14px; + width: 14px; +} + +.content-after-box, +.comment-content { word-wrap: break-word; white-space: pre-wrap; } -/* 对齐 zibll: 评论内图片限制 */ -.aksrt-comment__text img:not(.smilie-icon) { +.comment-content .enlighter-default { + margin-bottom: 0; + opacity: 0.9; +} + +#postcomments .comment-content img:not(.smilie-icon) { max-width: 260px; max-height: 350px; + display: block; + width: auto; + height: auto; } -.aksrt-comment__text p { - margin: 0 0 8px; +.virtual-input { + display: none; } -.aksrt-comment__text p:last-child { - margin-bottom: 0; -} - -.aksrt-comment__actions { - display: flex; - gap: 12px; - font-size: 12px; -} - -.aksrt-comment__actions a, -.aksrt-comment__actions button { - color: var(--color-ink-4); - background: none; - border: none; - padding: 0; - cursor: pointer; - font-size: 12px; - display: inline-flex; - align-items: center; - gap: 4px; - transition: color 0.15s ease; -} - -.aksrt-comment__actions a:hover, -.aksrt-comment__actions button:hover { - color: var(--color-primary); -} - -/* 嵌套回复中的头像更小 */ -/* 对齐 zibll: 嵌套头像 26px */ -.children .aksrt-comment__avatar img { - width: 26px; - height: 26px; - margin-right: 6px; - vertical-align: 2px; -} - -/* ============================================================ - * 空状态 - * ============================================================ */ -.comments-empty { - text-align: center; - padding: 40px 20px; -} - -.comments-empty__icon { - font-size: 48px; - color: var(--color-ink-4); - opacity: 0.4; - margin-bottom: 12px; -} - -.comments-empty__text { - font-size: 1rem; - font-weight: 600; - color: var(--color-ink-4); - margin: 0 0 4px; -} - -.comments-empty__hint { - font-size: 0.8125rem; - color: var(--color-ink-4); +.commentlist .no-more, +#comments .theme-pagination.pagenav { margin: 0; + padding-bottom: 10px; } -.comments-closed { +/*--------AJAX翻页按钮-----*/ +#comments .theme-pagination { + margin: 20px 0; +} + +#comments .chat-next a, +#comments .theme-pagination .ajax-next a, +#comments .theme-pagination .order-ajax-next a { + border-radius: 30px; + padding: 5px 15px; + color: var(--muted-color); + opacity: 0.6; + display: inline-block; +} + +#comments .chat-next a:hover, +#comments .theme-pagination .ajax-next a:hover, +#comments .theme-pagination .order-ajax-next a:hover { + background: var(--main-border-color); + opacity: 1; +} + +#comments .chat-next a .fa, +#comments .theme-pagination .ajax-next .fa, +#comments .theme-pagination .ajax-next .icon, +#comments .theme-pagination .order-ajax-next .fa, +#comments .theme-pagination .order-ajax-next .icon { + margin-right: 15px; + transition: 0.3s; +} + +#comments .chat-next a:hover .fa, +#comments .theme-pagination .ajax-next a:hover .fa, +#comments .theme-pagination .ajax-next a:hover .icon, +#comments .theme-pagination .order-ajax-next a:hover .fa, +#comments .theme-pagination .order-ajax-next a:hover .icon { + margin-right: 8px; +} + +/*--------数字分页按钮-----*/ +#comments .pagenav { + overflow: hidden; text-align: center; - font-size: 14px; - color: var(--color-ink-4); - padding: 20px; + padding: 20px 0; + transition: 0.2s; + line-height: 1.4; } -/* ============================================================ - * 评论分页 - * ============================================================ */ -.comment-pagination { - text-align: center; - padding: 16px 0; +#comments .pagenav .current, +#comments .pagenav .page-numbers, +#comments .pagenav a { + padding: 6px 9px 5px; + color: var(--muted-color); + display: inline-block; + border-radius: 3px; + background-color: var(--main-border-color); + margin: 3px; + min-width: 31px; } -/* ============================================================ - * 移动端适配 - * ============================================================ */ -@media (max-width: 767px) { - .comment-form__inner { - flex-direction: column; - gap: 8px; - } - - .comment-form__avatar { - display: none; - } - - .comment-form__submit-area { - flex-wrap: wrap; - } - - .comment-form__guest-field { - width: 100%; - } - - .comment-list .children { - margin-left: 0; - } - - .children .aksrt-comment__avatar img { - width: 36px; - height: 36px; - } - - /* 移动端评论输入吸底 — 模仿 zibll mobile-fixed */ - .comment-respond.comment-form--mobile-fixed { - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: var(--z-sticky, 200); - background: var(--surface-1); - border-top: 1px solid var(--color-line); - box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08); - padding: 12px 16px; - padding-bottom: max(12px, env(safe-area-inset-bottom)); - } - - .comment-respond.comment-form--mobile-fixed .comment-form__textarea { - min-height: 44px; - max-height: 120px; - } - - .comment-respond.comment-form--mobile-fixed .comment-form__submit-area { - margin-top: 8px; - } - - /* 当评论区可见时隐藏吸底输入框 */ - .comment-respond.comment-form--mobile-fixed.is-visible { - display: none; - } +#comments .pagenav .current { + background-color: var(--focus-color) !important; + color: #fff !important; } -/* ============================================================ - * 暗色模式 - * ============================================================ */ -html.dark .comment-form__textarea, -body.dark-theme .comment-form__textarea { - background: var(--surface-2); - border-color: var(--color-line); +#comments .pagenav a:hover { + opacity: 0.7; } -.theme-dark .comment-login-prompt__inner, -html.dark .comment-login-prompt__inner, -body.dark-theme .comment-login-prompt__inner { - background: var(--surface-1); -} - -/* ============================================================ - * 评论操作按钮(编辑/删除/审核) - * ============================================================ */ -.aksrt-comment-actions { - display: flex; - align-items: center; - gap: 8px; - margin-top: 8px; -} - -.aksrt-comment-action-btn { +#comments .pagenav .pag-jump { display: inline-flex; align-items: center; - gap: 4px; - padding: 3px 10px; - border: 1px solid var(--color-line, rgba(50, 50, 50, 0.1)); - border-radius: var(--radius, 8px); - background: var(--surface-1, #fff); - color: var(--color-ink-3, #777); - font-size: 12px; - font-weight: 500; - cursor: pointer; - transition: all 0.15s ease; -} - -.aksrt-comment-action-btn:hover { - border-color: var(--color-primary); - color: var(--color-primary); - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); -} - -.aksrt-comment-action-btn--danger:hover { - border-color: var(--color-error); - color: var(--color-error); - background: rgba(239, 68, 68, 0.08); -} - -.aksrt-comment-action-btn--success:hover { - border-color: var(--color-success); - color: var(--color-success); - background: rgba(16, 185, 129, 0.08); -} - -.aksrt-comment-edit-form { - margin: 8px 0; -} - -.aksrt-comment-edit-textarea { - width: 100%; - min-height: 80px; - padding: 8px 12px; - border: 1px solid var(--color-line, #ddd); - border-radius: var(--radius, 8px); - font-size: 14px; - font-family: var(--font-body); - color: var(--color-ink); - background: var(--surface-1, #fff); - resize: vertical; - transition: border-color 0.15s; -} - -.aksrt-comment-edit-textarea:focus { - outline: none; - border-color: var(--color-primary); -} - -/* ============================================================ - * 评论互动:点赞 / 置顶 / 内联管理动作(统一合同) - * 这些动作均渲染在 .aksrt-comment__actions 内,复用其文字链按钮样式, - * 仅补充点赞激活态、置顶徽章与危险/成功色提示。 - * ============================================================ */ -.aksrt-comment__like.is-active, -.aksrt-comment__like.is-active i { - color: var(--color-primary); -} - -.aksrt-comment__like-count { - font-variant-numeric: tabular-nums; -} - -.aksrt-comment__action--danger:hover { - color: var(--color-error, #ef4444); -} - -.aksrt-comment__action--success:hover { - color: var(--color-success, #10b981); -} - -/* 置顶徽章 */ -.aksrt-comment__badge--pinned { - background: var(--color-warning-soft, rgba(245, 158, 11, 0.14)); - color: var(--color-warning, #d97706); - display: inline-flex; - align-items: center; - gap: 3px; -} - -/* 置顶评论容器高亮 */ -.aksrt-comment--pinned > .aksrt-comment__body { position: relative; } -.comment-list .comment.aksrt-comment--pinned { - background: var(--color-warning-soft, rgba(245, 158, 11, 0.06)); - border-radius: var(--radius, 8px); - padding-left: 12px; - padding-right: 12px; +#comments .pagenav .pag-jump .jump-icon { + z-index: 1; } -/* zibll compat: emoji icon forced 30px */ -.comment-content .smilie-icon, -.comment-form .smilie-icon { - width: 30px !important; +#comments .pagenav .pag-jump .jump-icon:hover { + color: var(--focus-color); } -/* zibll compat: code block in comments */ -.comment-content .enlighter-default { - margin-bottom: 0; - opacity: 0.9; +#comments .pagenav .pag-jump .jump-input { + opacity: 0; + height: 100%; + width: 100%; + border-radius: 3px; + position: absolute; + left: 0; + top: 0; + transition: 0.2s; + padding: 5px 22px 5px 5px; } +#comments .pagenav .jump-input:focus, +#comments .pagenav .pag-jump:hover .jump-input { + opacity: 1; +} -/* Identity chips + 神评 */ -.aksrt-identity-chip { - display: inline-flex; - align-items: center; - gap: 3px; - vertical-align: middle; - max-width: 9em; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; +/* ============================================================ + * 评论依赖的基础组件(zibll main.css,作用域 #comments) + * ============================================================ */ + +/* 标题(zibll .title-theme) */ +#comments .title-theme { + position: relative; + padding-left: 1.2em; + font-size: 15px; } -.aksrt-identity-chip--comment { - font-size: 11px; - padding: 0 6px; + +#comments .title-theme small { + font-size: 80%; + opacity: 0.7; + margin-left: 0.4em; } -.medal-icon.img-icon, -.aksrt-identity-medal { - display: inline-block; - width: auto; - height: 1.1em; - max-width: 6em; - object-fit: contain; - vertical-align: -.15em; - margin-left: 4px; + +#comments .title-theme::before { + position: absolute; + content: ''; + width: 4px; + background: var(--theme-color); + top: 10%; + left: 2px; + bottom: 10%; + border-radius: 5px; + box-shadow: 1px 1px 3px -1px var(--theme-color); } -.aksrt-identity-medal--comment { - width: auto; - height: 1em; + +/* 下拉菜单(zibll .dropdown-menu) */ +#comments .dropdown-menu { + border-color: transparent; + background: var(--main-bg-color); + --this-color: var(--main-color); + color: var(--this-color); + box-shadow: 0 0 10px 8px var(--main-shadow); + min-width: 100px; + opacity: 0; + transform: translateY(6px); + transition: 0.3s; + display: block; + margin-top: 6px; + visibility: hidden; + list-style: none !important; + z-index: 992; + border-radius: var(--main-radius); } -.aksrt-comment__badge--hot { - color: #ea580c; - background: rgba(234, 88, 12, 0.1); - border-radius: 999px; - padding: 0 6px; - margin-left: 4px; - font-size: 11px; + +#comments .dropdown-menu a { + border-radius: var(--mini-radius); } -.aksrt-comment__header .author-box { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 4px; + +#comments .dropup { + position: relative; } -/* Inline name + level badge stay on one line; only the outer author-box wraps. */ -.aksrt-comment__header name, -.aksrt-comment__header .author-box > name { - flex-wrap: nowrap; - white-space: nowrap; + +#comments span.dropup, +#comments span.dropdown { + display: inline-block; +} + +#comments .dropup .dropdown-menu { + bottom: 100%; + margin-bottom: 6px; + margin-top: 0; + transform: translateY(-6px); +} + +#comments .open > .dropdown-menu, +#comments .dropdown.open > .dropdown-menu { + visibility: unset; + opacity: 1; + transform: translateY(0); +} + +#comments .dropdown-menu > li > a { + color: var(--this-color); + padding: 6px 20px; + text-shadow: none; + display: block; +} + +#comments .dropdown-menu > li > a:hover { + background: var(--focus-color-opacity05); +} + +/* 游客信息 line-form(zibll .line-form / .scale-placeholder / .line-form-input) */ +#comments .line-form { + position: relative; +} + +#comments .line-form .abs-right { + margin-top: 3px; +} + +#comments .line-form-input { + outline: 0 !important; + border: none; + display: block; + width: 100%; + padding: 1em 2em 0.4em 0.3em; + opacity: 0.8; + transition: 0.3s; + background: transparent !important; +} + +#comments .line-form-input::-webkit-input-placeholder { + color: var(--muted-2-color); +} + +#comments .line-form-input:focus { + opacity: 1; +} + +#comments .scale-placeholder { + position: absolute; + bottom: 5px; + opacity: 0.5; + transition: 0.2s; + padding-left: 4px; + transform-origin: left top; + user-select: none; + pointer-events: none; + backface-visibility: hidden; + z-index: 1; + cursor: text; +} + +#comments .scale-placeholder.is-focus, +#comments input:focus ~ .scale-placeholder { + transform: translateY(-20px); + font-size: 11px; +} + +#comments input:focus ~ .scale-placeholder { + color: var(--focus-color); + opacity: 0.9; +} + +/* 排序筛选标签(zibll .tab-nav-theme) */ +#comments .tab-nav-theme { + border-bottom: 1px solid var(--main-border-color); + padding-bottom: 6px; + margin: 8px 0 5px; + list-style: none; +} + +#comments .tab-nav-theme li, +#comments .tab-nav-theme ul { + list-style: none; +} + +#comments .tab-nav-theme li { + position: relative; + display: inline-block; + padding: 0 8px 6px; +} + +#comments .tab-nav-theme li::before { + content: ''; + position: absolute; + width: 20px; + height: 2px; + background: var(--theme-color); + border-radius: 5px; + left: 0; + right: 0; + margin: auto; + bottom: 5px; + opacity: 0; + transition: 0.4s; +} + +#comments .tab-nav-theme li.active::before { + opacity: 1; +} + +#comments .tab-nav-theme li a { + color: var(--muted-color); + display: inline-block; +} + +#comments .tab-nav-theme li.active a { + color: var(--focus-color); +} + +/* 置顶徽章(zibll badge.badge-topping) */ +#comments badge.badge-topping { + min-width: 1.4em; + padding: 0 2px; + line-height: 1.4em; + border-radius: 0.45em 2px; + display: inline-flex; + align-items: center; + justify-content: center; + text-align: center; + color: #fff; +} + +/* 工具栏下拉(zibll .dropdown-smilie / .dropdown-code / .dropdown-image / .dropdown-link / quick) */ +#comments .dropdown-smilie { + width: 260px; + height: 300px; + padding: 8px 10px; + white-space: inherit; + text-align: center; +} + +#comments .dropdown-smilie .smilie-icon { + display: inline-block; + padding: 3px; + width: 38px !important; +} + +#comments .dropdown-smilie .smilie-icon img { + width: 30px; + height: 30px; + display: block; +} + +#comments .dropdown-quick-often { + width: 260px; +} + +#comments .dropdown-quick-often .scroll-y { + max-height: 280px; +} + +#comments .dropdown-quick-often .list-inline { + padding: 0 10px !important; +} + +#comments .quick-reply-item { + padding: 6px 0; + color: var(--muted-color); + margin: 0 10px; + cursor: pointer; +} + +#comments .quick-reply-item + .quick-reply-item { + border-top: 1px solid var(--main-border-color); +} + +#comments .quick-reply-item:hover { + color: var(--focus-color); +} + +#comments .dropdown-link, +#comments .dropdown-code, +#comments .dropdown-image { + width: 250px; + padding: 8px 10px; +} + +#comments .dropdown-menu .dropdown-link, +#comments .dropdown-menu .dropdown-code, +#comments .dropdown-menu .dropdown-image, +#comments .dropdown-menu .dropdown-quick-often { + box-shadow: none; + background: transparent; + min-width: 0; + opacity: 1; + visibility: unset; + transform: none; + margin: 0; + display: block; +} + +#comments .scroll-y { + overflow-y: auto; +} + +/* 占位骨架(zibll .placeholder) */ +#comments .placeholder { + background: linear-gradient(118deg, rgba(121, 121, 121, 0.1) 25%, rgba(121, 121, 121, 0.2) 37%, rgba(121, 121, 121, 0.1) 63%); + opacity: 1; + border-radius: 4px; + animation: aksrt-comment-placeholder 1.5s ease infinite !important; + background-size: 400% 100% !important; +} + +#comments .placeholder.k2 { + height: 20px; +} + +#comments .placeholder.s1 { + width: 70px; + height: 15px; + display: inline-block; +} + +#comments .placeholder.radius { + border-radius: 50%; + width: 45px; + height: 45px; +} + +#comments .post_ajax_loader { + display: none; +} + +@keyframes aksrt-comment-placeholder { + 0% { + background-position: 100% 50%; + } + 100% { + background-position: 0 50%; + } +} + +/* 工具类(zibll,作用域 #comments) */ +#comments .text-right { + text-align: right; +} + +#comments .hide-sm { + display: inline; +} + +#comments .pw-1em { + padding-left: 1em; + padding-right: 1em; +} + +#comments .p2-10 { + padding: 2px 10px; +} + +#comments .padding-6 { + padding: 6px; +} + +#comments .mb6 { + margin-bottom: 6px; +} + +/* 评论作者行布局补充(zibll author-box / name) */ +#comments .comment-header .author-box { + display: flex; + align-items: center; +} + +#comments .comment-header name { + display: flex; + align-items: center; + min-width: 0; +} + +#comments .comment-header name a, +#comments .comment-header name b { + max-width: 14em; +} + +#comments .comment-header .action-comment-like { + text-decoration: none; + color: var(--muted-2-color); +} + +#comments .comment-header .action-comment-like.actived, +#comments .comment-header .action-comment-like.actived .fa { + color: var(--focus-color); +} + +#comments .comt-meta { + font-size: 12px; +} + +#comments .comt-meta .dropdown-menu a { + display: block; +} + +/* 身份徽章(AKSRT 渲染于 内,随 zibll ml3 间距) */ +#comments .comment-header .aksrt-identity-chip { + display: inline-flex; + align-items: center; + gap: 3px; + vertical-align: middle; + max-width: 9em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 11px; +} + +#comments .comment-header .aksrt-identity-medal { + display: inline-block; + width: auto; + height: 1.1em; + max-width: 6em; + object-fit: contain; + vertical-align: -0.15em; } diff --git a/assets/css/frontend/empty-state.css b/assets/css/frontend/empty-state.css index 09622f5a..a4c85c88 100644 --- a/assets/css/frontend/empty-state.css +++ b/assets/css/frontend/empty-state.css @@ -56,29 +56,6 @@ font-size: 12px; } -/* 评论空状态 */ -.comments-empty { - text-align: center; - padding: 40px 20px; -} - -.comments-empty__icon { - font-size: 48px; - color: var(--surface-3, #e8e8e8); - margin-bottom: 12px; -} - -.comments-empty__text { - font-size: 14px; - color: var(--color-ink-3, #777); - margin-bottom: 4px; -} - -.comments-empty__hint { - font-size: 12px; - color: var(--color-ink-4, #999); -} - /* 搜索空状态 */ .search-empty { text-align: center; diff --git a/assets/js/comment-ajax.js b/assets/js/comment-ajax.js index 67fb1e3d..a02de105 100644 --- a/assets/js/comment-ajax.js +++ b/assets/js/comment-ajax.js @@ -5,11 +5,11 @@ * Edit uses moveForm (#respond) via comment-move-form.js — not inline textarea. * Submit owned by assets/js/core/comments.js (single submit contract). * - * Markup (aksrt_comment_callback): - * li.aksrt-comment[data-comment-id] - * .comment-header .aksrt-comment__like[data-comment-action=like] + * Markup (aksrt_comment_callback, zibll DOM): + * li.comment#comment-{id} + * .comment-header .action-comment-like[data-comment-action=like] > count * .comment-content#comment-content-{id} - * .comt-meta [data-comment-action=pin|approve|hold|spam|delete] + * .comt-meta [data-comment-action=pin|approve|hold|delete] * * @package AKSRT */ @@ -19,8 +19,8 @@ if (!window.aksrtData) return; - var COMMENT_SELECTOR = '.aksrt-comment, .comment'; - var CONTENT_SELECTOR = '.aksrt-comment__text, .comment-content'; + var COMMENT_SELECTOR = 'li.comment'; + var CONTENT_SELECTOR = '.comment-content'; var REST_BASE = (aksrtData.siteUrl || '').replace(/\/$/, '') + '/wp-json/aksrt/v1'; var REST_NONCE = aksrtData.restNonce || ''; @@ -48,6 +48,10 @@ var commentEl = actionBtn.closest(COMMENT_SELECTOR); if (!commentEl) return; + // 操作后收起 ⋮ 菜单 + var openMenu = actionBtn.closest('span.dropdown.open'); + if (openMenu) openMenu.classList.remove('open'); + var commentId = getCommentId(commentEl); if (!commentId) return; @@ -75,14 +79,9 @@ var count = (result.data && result.data.count) || 0; btn.setAttribute('data-active', active ? '1' : '0'); btn.setAttribute('aria-pressed', active ? 'true' : 'false'); - btn.classList.toggle('is-active', active); - var icon = btn.querySelector('i'); - if (icon) { icon.classList.toggle('fa', active); icon.classList.toggle('fa', !active); } - var countEl = btn.querySelector('.aksrt-comment__like-count'); - if (countEl) { - countEl.textContent = String(count); - if (count > 0) { countEl.removeAttribute('hidden'); } else { countEl.setAttribute('hidden', ''); } - } + btn.classList.toggle('actived', active); + var countEl = btn.querySelector('count'); + if (countEl) countEl.textContent = String(count); }) .catch(function () { notyf('网络错误', 'danger'); }) .finally(function () { btn.dataset.busy = ''; }); @@ -103,7 +102,7 @@ }); setTimeout(function () { commentEl.remove(); - var countEl = document.querySelector('.comments-count'); + var countEl = document.querySelector('#comments .title-theme small'); if (countEl) { var m = (countEl.textContent || '').match(/(\d+)/); if (m) { @@ -134,8 +133,7 @@ if (!result.success) { notyf((result.data && result.data.message) || result.message || '操作失败', 'danger'); return; } var pinned = !!(result.data && result.data.pinned); btn.setAttribute('data-pinned', pinned ? '1' : '0'); - btn.innerHTML = ' ' + (pinned ? '取消置顶' : '置顶'); - commentEl.classList.toggle('aksrt-comment--pinned', pinned); + btn.innerHTML = '' + (pinned ? '取消置顶' : '设置置顶'); syncPinnedBadge(commentEl, pinned); notyf(result.message || (pinned ? '评论已置顶。' : '已取消置顶。'), 'success'); }) @@ -143,15 +141,15 @@ } function syncPinnedBadge(commentEl, pinned) { - var header = commentEl.querySelector('.aksrt-comment__header, .comment-header'); - if (!header) return; - var badge = header.querySelector('.aksrt-comment__badge--pinned'); + var name = commentEl.querySelector('.comment-header name'); + if (!name) return; + var badge = name.querySelector('badge.badge-topping'); if (pinned && !badge) { - badge = document.createElement('span'); - badge.className = 'aksrt-comment__badge aksrt-comment__badge--pinned'; - badge.innerHTML = ' 置顶'; - var time = header.querySelector('.aksrt-comment__time'); - header.insertBefore(badge, time || null); + badge = document.createElement('badge'); + badge.className = 'badge-topping jb-blue mr6 flex0'; + badge.title = '置顶评论'; + badge.innerHTML = ''; + name.insertBefore(badge, name.firstChild); } else if (!pinned && badge) { badge.remove(); } diff --git a/assets/js/comment-tools.js b/assets/js/comment-tools.js index fedf4f02..83efdef6 100644 --- a/assets/js/comment-tools.js +++ b/assets/js/comment-tools.js @@ -49,7 +49,7 @@ } if (!key) return; insertAtCursor(findTextarea(sm), '[g=' + key + ']'); - var wrap = sm.closest('.dropup, .input-expand-wrap'); + var wrap = sm.closest('span.dropup'); if (wrap) wrap.classList.remove('open'); return; } @@ -66,7 +66,7 @@ } insertAtCursor(findTextarea(codeBtn), '[code]\n' + code + '\n[/code]\n'); if (ta) ta.value = ''; - var w = codeBtn.closest('.dropup, .input-expand-wrap'); + var w = codeBtn.closest('span.dropup'); if (w) w.classList.remove('open'); return; } @@ -83,7 +83,7 @@ } insertAtCursor(findTextarea(imgBtn), '[img=' + url + ']'); if (input) input.value = ''; - var iw = imgBtn.closest('.dropup, .input-expand-wrap'); + var iw = imgBtn.closest('span.dropup'); if (iw) iw.classList.remove('open'); return; } @@ -117,7 +117,7 @@ e.preventDefault(); var phrase = q.getAttribute('data-text') || q.textContent || ''; insertAtCursor(findTextarea(q), phrase); - var qw = q.closest('.dropup, .input-expand-wrap'); + var qw = q.closest('span.dropup'); if (qw) qw.classList.remove('open'); } }); diff --git a/assets/js/core/comment-move-form.js b/assets/js/core/comment-move-form.js index 1a3fd75b..ad364f03 100644 --- a/assets/js/core/comment-move-form.js +++ b/assets/js/core/comment-move-form.js @@ -145,7 +145,9 @@ if (submit) submit.disabled = false; }); } else { - setActionText('回复评论'); + var nameEl = comm ? comm.querySelector('.comment-header name') : null; + var author = nameEl ? (nameEl.textContent || '').trim() : ''; + setActionText(author ? ('回复 @' + author) : '回复评论'); ensureEditField(respond, 0); if (textarea) { textarea.focus(); @@ -195,25 +197,22 @@ } }); - // Dropup toggles (guest / expand). + // Dropup / dropdown toggles (guest info, expand toolbar, action menu). document.addEventListener('click', function (e) { - var t = e.target && e.target.closest ? e.target.closest('[data-toggle-class="open"]') : null; + var t = e.target && e.target.closest ? e.target.closest('[data-toggle-class="open"], span.dropup > a.but, [data-toggle="dropdown"]') : null; if (!t) return; - var targetSel = t.getAttribute('data-target'); - if (!targetSel) return; + var wrap = t.closest('span.dropup, span.dropdown'); + if (!wrap) return; + // 点击已在打开的下拉内部(表情/快捷项等)不切换 + if (wrap.classList.contains('open') && t.parentElement !== wrap) return; e.preventDefault(); - var wrap = t.closest('.dropup, .input-expand-wrap, #comment-user-info') || t.parentElement; - var panel = targetSel.charAt(0) === '#' || targetSel.charAt(0) === '.' - ? (wrap && wrap.querySelector(targetSel)) || document.querySelector(targetSel) - : null; - if (wrap) wrap.classList.toggle('open'); - if (panel && panel !== wrap) panel.classList.toggle('open'); + wrap.classList.toggle('open'); }); // Close dropups on outside click. document.addEventListener('click', function (e) { - if (e.target.closest && e.target.closest('.dropup, .input-expand-wrap, [data-toggle-class="open"]')) return; - document.querySelectorAll('.dropup.open, .input-expand-wrap.open, #comment-user-info.open').forEach(function (n) { + if (e.target.closest && e.target.closest('span.dropup.open, span.dropdown.open')) return; + document.querySelectorAll('span.dropup.open, span.dropdown.open').forEach(function (n) { n.classList.remove('open'); }); }); diff --git a/assets/js/core/comments.js b/assets/js/core/comments.js index 3f2c1763..6b163e4a 100644 --- a/assets/js/core/comments.js +++ b/assets/js/core/comments.js @@ -97,13 +97,13 @@ } function updateCommentCount(delta) { - var countEl = document.querySelector('.comments-count'); + var countEl = document.querySelector('#comments .title-theme small'); if (!countEl) return; var text = countEl.textContent || ''; var match = text.match(/(\d+)/); if (!match) return; var nextCount = Math.max(0, parseInt(match[1], 10) + delta); - countEl.textContent = '共 ' + nextCount + ' 条'; + countEl.textContent = text.replace(match[1], String(nextCount)); } function handleResponse(responseText, statusCode) { try { @@ -316,9 +316,9 @@ newComment.style.opacity = '0'; newComment.style.transition = 'max-height 0.4s ease, opacity 0.3s ease'; if (isReply && parentId) { - var parentComment = document.querySelector('#comment-' + parentId + ', [data-comment-id="' + parentId + '"]'); + var parentComment = document.querySelector('#comment-' + parentId); if (parentComment) { - var children = parentComment.querySelector('.children'); + var children = parentComment.querySelector(':scope > .children'); if (!children) { children = document.createElement('ol'); children.className = 'children'; @@ -354,8 +354,15 @@ } function prependToCommentList(el) { - var list = document.querySelector('.commentlist, #comment-list > ol, #comment-list'); - if (list) list.insertBefore(el, list.firstChild); + var list = document.querySelector('#comments .commentlist'); + if (!list) return; + // 插到筛选栏之后、最新评论之前 + var filter = list.querySelector('.comment-filter'); + if (filter && filter.nextSibling) { + list.insertBefore(el, filter.nextSibling); + } else { + list.insertBefore(el, list.firstChild); + } } function restoreRespondPosition() { @@ -471,66 +478,27 @@ function getCurrentAuthorOnly() { var url = new URL(window.location.href); if (url.searchParams.get("aksrt_author_only") === "1") return true; - var btn = document.querySelector("#comments .comment-author-filter"); + var btn = document.querySelector("#comments .btn-only-author"); return !!(btn && btn.classList.contains("active") && btn.dataset.authorOnly === "0"); } function applyFragmentPayload(commentsArea, data, urlState) { - if (!commentsArea || !data) return; + if (!commentsArea || !data || !data.html) return; - if (data.filter_html) { - var currentFilter = commentsArea.querySelector(".comment-filter"); - var temp = document.createElement("div"); - temp.innerHTML = data.filter_html; - var newFilter = temp.firstElementChild; - if (newFilter) { - if (currentFilter) currentFilter.replaceWith(newFilter); - else { - var listAnchor = commentsArea.querySelector("#postcomments, #comment-list"); - if (listAnchor && listAnchor.parentNode) { - listAnchor.parentNode.insertBefore(newFilter, listAnchor); - } - } - } - } + // data.html 是完整的
(含筛选、列表、分页) + var tempList = document.createElement("div"); + tempList.innerHTML = data.html; + var newListWrap = tempList.querySelector("#postcomments"); + if (!newListWrap) return; var currentListWrap = commentsArea.querySelector("#postcomments"); - var currentList = commentsArea.querySelector("#comment-list"); - var currentEmpty = commentsArea.querySelector(".comments-empty"); - var tempList = document.createElement("div"); - tempList.innerHTML = data.html || ""; - var newListWrap = tempList.querySelector("#postcomments"); - var newEmpty = tempList.querySelector(".comments-empty"); - - if (newListWrap) { - if (currentListWrap) currentListWrap.replaceWith(newListWrap); - else if (currentList) currentList.replaceWith(newListWrap); - else commentsArea.appendChild(newListWrap); - if (currentEmpty) currentEmpty.remove(); - } else if (newEmpty) { - if (currentListWrap) currentListWrap.remove(); - if (currentList) currentList.remove(); - if (currentEmpty) currentEmpty.replaceWith(newEmpty); - else commentsArea.appendChild(newEmpty); + if (currentListWrap) { + currentListWrap.replaceWith(newListWrap); + } else { + commentsArea.appendChild(newListWrap); } - var currentPagination = commentsArea.querySelector(".aksrt-comment-pagination, .comment-navigation, .pagenav.ajax-pag"); - if (data.pagination_html) { - var ptemp = document.createElement("div"); - ptemp.innerHTML = data.pagination_html; - var newPag = ptemp.firstElementChild; - if (newPag) { - if (currentPagination) currentPagination.replaceWith(newPag); - else { - var list = commentsArea.querySelector("#postcomments, #comment-list"); - if (list && list.parentNode) list.parentNode.insertBefore(newPag, list.nextSibling); - } - } - } else if (currentPagination) { - currentPagination.remove(); - } - - var currentCount = commentsArea.querySelector(".comments-count"); + var currentCount = commentsArea.querySelector(".title-theme small"); if (currentCount && data.count_text) currentCount.textContent = data.count_text; if (urlState && window.history && typeof window.history.replaceState === "function") { @@ -562,20 +530,30 @@ } /* ====== 评论列表动态刷新 ====== */ + function showListLoading(commentsArea) { + var list = commentsArea.querySelector(".commentlist"); + if (!list) return; + // 保留筛选栏,清空条目并显示 zibll 骨架 + var filter = list.querySelector(".comment-filter"); + var loader = list.querySelector(".post_ajax_loader"); + var skeleton = loader ? loader.cloneNode(true) : null; + Array.prototype.slice.call(list.children).forEach(function (child) { + if (child !== filter && child !== loader) child.remove(); + }); + if (skeleton) { + skeleton.style.display = "block"; + skeleton.removeAttribute("hidden"); + list.appendChild(skeleton); + } + } + function reloadCommentList() { var commentsArea = document.getElementById('comments'); - var listContainer = document.getElementById('comment-list'); - if (!commentsArea && !listContainer) { + if (!commentsArea) { window.location.reload(); return; } - if (listContainer) { - listContainer.innerHTML = '
  • ' + - '
    ' + - '
    ' + - '
    ' + - '
  • '; - } + showListLoading(commentsArea); fetchCommentFragment({ order: getCurrentCommentOrder(), @@ -583,7 +561,7 @@ page: 1 }).then(function (json) { if (json && json.success && json.data) { - applyFragmentPayload(commentsArea || document, json.data, null); + applyFragmentPayload(commentsArea, json.data, null); return; } throw new Error('fragment failed'); @@ -622,13 +600,7 @@ commentsArea.dataset.orderInit = "1"; function renderLoadingState() { - var listContainer = commentsArea.querySelector("#comment-list"); - if (!listContainer) return; - listContainer.innerHTML = '
  • ' + - '
    ' + - '
    ' + - '
    ' + - '
  • '; + showListLoading(commentsArea); } function applyCommentOrder(order) { if (order !== "newest" && order !== "oldest" && order !== "hottest") { @@ -685,7 +657,7 @@ if (!target || typeof target.closest !== "function") return; // 「只看作者」同时带 comment-orderby,需优先于排序按钮判断 - var authorBtn = target.closest(".comment-author-filter"); + var authorBtn = target.closest(".btn-only-author"); if (authorBtn && commentsArea.contains(authorBtn)) { e.preventDefault(); applyAuthorFilter(authorBtn.getAttribute("data-author-only") || "0"); @@ -701,40 +673,33 @@ } - function initGuestFields() { - var root = document.getElementById("comments") || document; - root.querySelectorAll("[data-aksrt-guest-toggle]").forEach(function (btn) { - if (btn.dataset.aksrtGuestBound === "1") return; - btn.dataset.aksrtGuestBound = "1"; - var wrap = btn.closest(".comment-form__guest"); - var fields = wrap ? wrap.querySelector("[data-aksrt-guest-fields]") : null; - if (!fields) return; - btn.addEventListener("click", function (e) { - e.preventDefault(); - var open = btn.getAttribute("aria-expanded") === "true"; - btn.setAttribute("aria-expanded", open ? "false" : "true"); - if (open) { - fields.setAttribute("hidden", ""); - fields.classList.remove("is-open"); - } else { - fields.removeAttribute("hidden"); - fields.classList.add("is-open"); - var first = fields.querySelector("input"); - if (first) first.focus(); - } - }); - // Auto-open if browser restored values or validation fails later. - var form = btn.closest("form"); - if (form) { - form.addEventListener("invalid", function () { - fields.removeAttribute("hidden"); - fields.classList.add("is-open"); - btn.setAttribute("aria-expanded", "true"); - }, true); - } + /* ====== 数字分页跳页(zibll pag-jump) ====== */ + function jumpToCommentPage(page) { + page = parseInt(page, 10) || 1; + var url = new URL(window.location.href); + url.searchParams.set("cpage", String(page)); + url.hash = "comments"; + window.location.href = url.toString(); + } + + function initCommentPageJump() { + document.addEventListener("click", function (e) { + var jump = e.target.closest ? e.target.closest("#comments .pag-jump") : null; + if (!jump) return; + e.preventDefault(); + var input = jump.querySelector(".jump-input"); + if (input) jumpToCommentPage(input.value); + }); + document.addEventListener("keydown", function (e) { + if (e.key !== "Enter") return; + var input = e.target; + if (!input || !input.classList || !input.classList.contains("jump-input")) return; + if (!input.closest("#comments .pagenav")) return; + e.preventDefault(); + jumpToCommentPage(input.value); }); } - window.AksrtFrontend.register("aksrt-comment-system", function () { initCommentSystem(); initGuestFields(); }); + window.AksrtFrontend.register("aksrt-comment-system", function () { initCommentSystem(); initCommentPageJump(); }); window.AksrtFrontend.register("aksrt-comment-order", function (root) { initCommentOrder(root); }); })(); diff --git a/assets/js/core/pagination.js b/assets/js/core/pagination.js index c3566ee0..e9aaa804 100644 --- a/assets/js/core/pagination.js +++ b/assets/js/core/pagination.js @@ -42,8 +42,8 @@ target = target.previousElementSibling; } if (isComment) { - var commentList = document.getElementById("comment-list") || - (container.parentElement && container.parentElement.querySelector("#comment-list, .commentlist, ol.commentlist")); + var commentList = container.closest("#comment-list, .commentlist, ol.commentlist") || + document.getElementById("comment-list"); if (commentList) target = commentList; } if (!target && container.parentElement) { @@ -167,6 +167,8 @@ while (newItems.length > 0) { if (homepagePanel && container.parentNode === target) { target.insertBefore(newItems[0], container); + } else if (container.parentNode === target) { + target.insertBefore(newItems[0], container); } else { target.appendChild(newItems[0]); } diff --git a/inc/helpers/aksrt-comments.php b/inc/helpers/aksrt-comments.php index eec7a103..58b69920 100644 --- a/inc/helpers/aksrt-comments.php +++ b/inc/helpers/aksrt-comments.php @@ -321,7 +321,7 @@ if (!function_exists('aksrt_comments_render_list_fragment')) : /** * Fragment payload for order/author/page AJAX. * - * @return array{html:string,filter_html:string,pagination_html:string,count_text:string,total:int,max_pages:int,page:int,order:string,author_only:bool,empty:bool} + * @return array{html:string,items_html:string,count_text:string,total:int,max_pages:int,page:int,order:string,author_only:bool,empty:bool} */ function aksrt_comments_render_list_fragment(int $post_id, array $args = []): array { $result = aksrt_comments_query_for_post($post_id, $args); @@ -351,42 +351,36 @@ if (!function_exists('aksrt_comments_render_list_fragment')) : ]; ob_start(); - if (function_exists('aksrt_comments_render_filter') && !empty($ctx['corderby_enabled'])) { - aksrt_comments_render_filter($ctx); - } - $filter_html = (string) ob_get_clean(); - - ob_start(); - if ($items_html === '' && function_exists('aksrt_comments_render_empty')) { - aksrt_comments_render_empty($ctx); + echo '
      '; + if ($items_html === '') { + if (function_exists('aksrt_comments_render_empty')) { + aksrt_comments_render_empty($ctx); + } + echo ''; } else { - echo '
        '; + if (function_exists('aksrt_comments_render_filter') && !empty($ctx['corderby_enabled'])) { + aksrt_comments_render_filter($ctx); + } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- rendered comment markup. echo $items_html; - echo '
      '; + if (function_exists('aksrt_render_comment_pagination') && $max_pages > 1) { + $pages_filter = static function () use ($max_pages) { + return $max_pages; + }; + add_filter('get_comment_pages_count', $pages_filter); + aksrt_render_comment_pagination(); + remove_filter('get_comment_pages_count', $pages_filter); + } } + echo '
    '; $list_html = (string) ob_get_clean(); - ob_start(); - if (function_exists('aksrt_render_comment_pagination') && $max_pages > 1) { - // Temporarily override page counts via filter. - $pages_filter = static function () use ($max_pages) { - return $max_pages; - }; - add_filter('get_comment_pages_count', $pages_filter); - aksrt_render_comment_pagination(); - remove_filter('get_comment_pages_count', $pages_filter); - } - $pagination_html = (string) ob_get_clean(); - wp_reset_postdata(); return [ 'html' => $list_html, 'items_html' => $items_html, - 'filter_html' => $filter_html, - 'pagination_html' => $pagination_html, - 'count_text' => sprintf(__('共 %d 条', 'aksrt'), $total), + 'count_text' => sprintf(__('共%s条', 'aksrt'), (string) $total), 'total' => $total, 'max_pages' => $max_pages, 'page' => $page, @@ -406,30 +400,32 @@ if (!function_exists('aksrt_comments_render_signarea')) : */ function aksrt_comments_render_signarea(array $ctx): void { $oauth_providers = is_array($ctx['oauth_providers'] ?? null) ? $ctx['oauth_providers'] : []; + $login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url(get_permalink()) : wp_login_url(get_permalink()); ?>
    - - - +

    -
    +
    +

    -
    +
    -
    +
    - ID, $avatar_size, '', '', ['class' => 'avatar-img comt-avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + ID, 60, '', '', ['class' => 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

    display_name); ?>

    - 'avatar-img comt-avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + 'avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
    -

    +

    - + -
    +
    -
    - +
    > - + @@ -571,8 +569,8 @@ if (!function_exists('aksrt_comments_render_filter')) : $post_author_id = (int) $ctx['post_author_id']; ?>
    -
      -
    • +
        +
      • @@ -580,7 +578,7 @@ if (!function_exists('aksrt_comments_render_filter')) :
      0) : ?> - + @@ -589,69 +587,34 @@ if (!function_exists('aksrt_comments_render_filter')) : } endif; -if (!function_exists('aksrt_comments_render_list')) : +if (!function_exists('aksrt_get_comment_ajax_loader')) : /** - * Comment list + pagination. + * Hidden skeleton loader shown while AJAX pagination runs (zibll parity). * - * @param array $ctx Comments context. + * @return string */ - function aksrt_comments_render_list(array $ctx): void { - ?> -
      -
        - 'ol', - 'short_ping' => true, - 'avatar_size' => (int) $ctx['avatar_size'], - 'max_depth' => (int) $ctx['max_depth'], - 'callback' => 'aksrt_comment_callback', - 'reverse_top_level' => !empty($ctx['reverse_comments']), - 'reverse_children' => !empty($ctx['reverse_comments']), - ]); - ?> -
      -
      -
    '; + return ''; } endif; if (!function_exists('aksrt_comments_render_empty')) : /** - * Empty state. + * Empty state (zibll: zib_get_null('暂无评论内容', 40, 'null.svg', 'comment comment-null')). * * @param array $ctx Comments context. */ function aksrt_comments_render_empty(array $ctx): void { - $closed = !comments_open(); $text = (string) ($ctx['empty_text'] ?? __('暂无评论内容', 'aksrt')); - if ($closed) { - $text = __('评论已关闭', 'aksrt'); - } elseif (!empty($ctx['author_only'])) { + if (!empty($ctx['author_only'])) { $text = __('暂无作者评论', 'aksrt'); } - $hint = $closed - ? __('本文评论已关闭,仅可浏览历史留言', 'aksrt') - : (!empty($ctx['author_only']) - ? __('切换到「查看全部」可浏览其他评论', 'aksrt') - : __('成为第一个评论者吧', 'aksrt')); if (function_exists('aksrt_get_null')) { - echo aksrt_get_null($text, 40, 'null.svg', 'comment comment-null comments-empty', 220); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo '

    ' . esc_html($hint) . '

    '; + echo aksrt_get_null($text, 40, 'null.svg', 'comment comment-null', 280); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped return; } - ?> -
    -
    - -
    -

    -

    -
    -

    ' . esc_html($text) . '

    '; } endif; @@ -676,17 +639,15 @@ if (!function_exists('aksrt_comments_render')) : set_query_var('aksrt_comment_order', (string) $ctx['order']); set_query_var('aksrt_comment_settings', $ctx['settings']); - $avatar_size = max(45, (int) $ctx['avatar_size']); $count = (int) $ctx['comment_count']; $count_label = $count > 0 ? sprintf(__('共%s条', 'aksrt'), (string) $count) : __('抢沙发', 'aksrt'); ?> -
    +
    -
    - - +
    + ' . esc_html($count_label) . ''; ?>
    @@ -699,26 +660,49 @@ if (!function_exists('aksrt_comments_render')) : - 0 || !empty($ctx['author_only']) || have_comments()); - if ($show_filter) { - aksrt_comments_render_filter($ctx); - } - ?> +
    +
      + 0 || !empty($ctx['author_only']) || have_comments()); + if ($show_filter) { + aksrt_comments_render_filter($ctx); + } - - - - - - - - -

      - + if (have_comments()) { + aksrt_comments_render_list_items($ctx); + } elseif (!post_password_required()) { + aksrt_comments_render_empty($ctx); + echo ''; + } + ?> +
    +
    $ctx Comments context. + */ + function aksrt_comments_render_list_items(array $ctx): void { + wp_list_comments([ + 'type' => 'comment', + 'style' => 'ol', + 'avatar_size' => (int) $ctx['avatar_size'], + 'max_depth' => (int) $ctx['max_depth'], + 'callback' => 'aksrt_comment_callback', + 'reverse_top_level' => !empty($ctx['reverse_comments']), + 'reverse_children' => !empty($ctx['reverse_comments']), + ]); + echo aksrt_get_comment_ajax_loader(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + if (function_exists('aksrt_render_comment_pagination')) { + aksrt_render_comment_pagination(); + } + } +endif; diff --git a/inc/helpers/comments/content.php b/inc/helpers/comments/content.php index c4755851..42e583e5 100644 --- a/inc/helpers/comments/content.php +++ b/inc/helpers/comments/content.php @@ -114,6 +114,17 @@ if (!function_exists('aksrt_render_comment_content')) : ['
    ', '
    '], (string) $rendered ); + // [link=url target=_blank]text[/link] / [link=url]text[/link] + $rendered = preg_replace( + '/\[link=(https?:\/\/[^\s\[\]]+) target=_blank\]([^\[]*)\[\/link\]/i', + '$2', + (string) $rendered + ); + $rendered = preg_replace( + '/\[link=(https?:\/\/[^\s\[\]]+)\]([^\[]*)\[\/link\]/i', + '$2', + (string) $rendered + ); // [g=key] $rendered = preg_replace_callback( '/\[g=([^\]]+)\]/i', diff --git a/inc/helpers/comments/form-parts.php b/inc/helpers/comments/form-parts.php index f3c8cd57..7214376e 100644 --- a/inc/helpers/comments/form-parts.php +++ b/inc/helpers/comments/form-parts.php @@ -1,6 +1,9 @@ 'avatar-img']); + $avatar = get_avatar($user_id, 36, '', '', ['class' => 'avatar']); if ($placeholder === '') { $placeholder = __('说点什么吧...', 'aksrt'); } - $html = '
    '; + $html = '
    '; $html .= '
    '; $html .= $avatar; $html .= '
    ' . esc_html($placeholder) . '
    '; @@ -33,46 +37,27 @@ endif; if (!function_exists('aksrt_get_input_expand_but')) : /** - * zibll-style expand toolbar button + dropdown. + * zibll-style expand toolbar button + dropdown (zibll: zib_get_input_expand_but). * - * @param string $type smilie|code|image|quick|upload. - * @param mixed $arg1 Type-specific. - * @param array $ctx Optional context (upload enabled, phrases). + * @param string $type smilie|code|image|quick|link. + * @param mixed $arg1 Type-specific arg. + * @param array $ctx Optional context (upload, phrases). + * @return string */ function aksrt_get_input_expand_but(string $type = 'smilie', $arg1 = null, array $ctx = []): string { + $but = ''; + $dropdown = ''; + switch ($type) { - case 'smilie': - $map = function_exists('aksrt_comment_smilie_map') ? aksrt_comment_smilie_map() : []; - $icons = ''; - foreach ($map as $key => $url) { - $icons .= ''; - } - $but = '' . esc_html__('表情', 'aksrt') . ''; - $drop = ''; - return '' . $but . $drop . ''; - - case 'code': - $but = '' . esc_html__('代码', 'aksrt') . ''; - $drop = ''; - return '' . $but . $drop . ''; - - case 'image': - $upload = !empty($arg1) || !empty($ctx['upload']); - $but = '' . esc_html__('图片', 'aksrt') . ''; - $upload_btn = $upload - ? '' - : ''; - $drop = ''; - return '' . $but . $drop . ''; + case 'link': + $but = '' . esc_html__('链接', 'aksrt') . ''; + $dropdown = ''; + break; case 'quick': $phrases = []; @@ -81,30 +66,65 @@ if (!function_exists('aksrt_get_input_expand_but')) : } elseif (!empty($ctx['quick_phrases']) && is_array($ctx['quick_phrases'])) { $phrases = $ctx['quick_phrases']; } - if (empty($phrases)) { - $phrases = [ - __('不错,学习了', 'aksrt'), - __('感谢分享', 'aksrt'), - __('期待更新', 'aksrt'), - ]; - } - $items = ''; + $sys_lists = ''; foreach ($phrases as $p) { - $items .= '' . esc_html((string) $p) . ''; + $sys_lists .= '
    ' . esc_html((string) $p) . '
    '; } - $but = '' . esc_html__('快捷', 'aksrt') . ''; - $drop = ''; - return '' . $but . $drop . ''; + if ($sys_lists === '') { + $sys_lists = '
    ' . esc_html__('系统暂无快捷回复', 'aksrt') . '
    '; + } + + $but = '' . esc_html__('快捷回复', 'aksrt') . ''; + $dropdown = ''; + break; + + case 'smilie': + $map = function_exists('aksrt_comment_smilie_map') ? aksrt_comment_smilie_map() : []; + $smilie_icon = ''; + foreach ($map as $key => $url) { + $smilie_icon .= '[' . esc_attr((string) $key) . ']'; + } + $but = '' . esc_html__('表情', 'aksrt') . ''; + $dropdown = ''; + break; + + case 'code': + $but = '' . esc_html__('代码', 'aksrt') . ''; + $dropdown = ''; + break; + + case 'image': + $upload = !empty($arg1) || !empty($ctx['upload']); + $but = '' . esc_html__('图片', 'aksrt') . ''; + + $dropdown = ''; + break; default: return ''; } + + $con = $but . ''; + return '' . $con . ''; } endif; if (!function_exists('aksrt_render_comment_expand_toolbar')) : /** - * Render left-side expand tools based on settings. + * Render left-side expand tools based on settings (zibll order: smilie/code/image/link/quick). * * @param array $ctx Comments context. */ diff --git a/inc/helpers/comments/item.php b/inc/helpers/comments/item.php index 79c509b6..2c1d3372 100644 --- a/inc/helpers/comments/item.php +++ b/inc/helpers/comments/item.php @@ -1,6 +1,9 @@ 0 ? (string) $like_count : ''; + $classes = 'action action-comment-like muted-2-color flex0 ml10' . ($is_liked ? ' actived' : ''); + return sprintf( - '', + '%5$s', esc_attr($classes), - $is_liked ? '1' : '0', $comment_id, + $is_liked ? '1' : '0', $is_liked ? 'true' : 'false', - $is_liked ? 'fa' : 'fa', - $like_count > 0 ? '' : ' hidden', - esc_html($count_attr) + esc_html((string) $like_count) ); } endif; +if (!function_exists('aksrt_get_comment_avatar_box')) : + /** + * Comment avatar box (zibll: zib_get_comment_avatar_box). + * + * @param WP_Comment $comment Comment. + * @param string $class Classes for the avatar wrapper. + * @param bool $link Wrap in a link when a target URL exists. + * @return string + */ + function aksrt_get_comment_avatar_box(WP_Comment $comment, string $class = 'avatar-img comt-avatar', bool $link = true): string { + $user_id = (int) $comment->user_id; + $size = 45; + $avatar = $user_id > 0 + ? get_avatar($user_id, $size, '', '', ['class' => 'avatar']) + : get_avatar($comment->comment_author_email, $size, '', '', ['class' => 'avatar']); + $html = '' . $avatar . ''; + + if (!$link) { + return $html; + } + if ($user_id > 0) { + $url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id); + return '' . $html . ''; + } + if (!empty($comment->comment_author_url)) { + return '' . $html . ''; + } + return $html; + } +endif; + if (!function_exists('aksrt_get_comments_user_name_html')) : /** - * Name row: topping + author link + identity + author/hot badges. + * Name row (zibll: zib_get_comments_user_name) — topping + author + badges. * * @param WP_Comment $comment Comment. * @param array $settings Display settings. + * @return string */ function aksrt_get_comments_user_name_html(WP_Comment $comment, array $settings = []): string { $user_id = (int) $comment->user_id; @@ -51,55 +88,65 @@ if (!function_exists('aksrt_get_comments_user_name_html')) : $topping = ''; if ($is_pinned) { - $topping = ''; + $topping = ''; } + $user_name = ''; if ($user_id > 0) { $user = get_userdata($user_id); - $display = $user instanceof WP_User ? $user->display_name : get_comment_author($comment); - $url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id); - $name = '' . esc_html($display) . ''; - if (function_exists('aksrt_render_user_identity_chips')) { - $name .= aksrt_render_user_identity_chips($user_id, 'comment'); + if ($user instanceof WP_User) { + $url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id); + $user_name = '' . esc_html($user->display_name) . ''; + if (function_exists('aksrt_render_user_identity_chips')) { + $user_name .= aksrt_render_user_identity_chips($user_id, 'comment'); + } } - } else { - $name = '' . esc_html(get_comment_author($comment)) . ''; + } elseif (!empty($comment->comment_author_url)) { + $user_name = '' . esc_html($comment->comment_author) . ''; } - $badges = ''; + $user_name = $user_name !== '' ? $user_name : '' . esc_html($comment->comment_author) . ''; + + $badge = ''; if ($show_author_tag && $is_post_author) { - $badges .= '' . esc_html__('作者', 'aksrt') . ''; - } - if (function_exists('aksrt_is_blog_comment_hot') && aksrt_is_blog_comment_hot($comment)) { - $badges .= ' ' . esc_html__('神评', 'aksrt') . ''; + $badge .= '' . esc_html__('作者', 'aksrt') . ''; } - return '' . $topping . $name . $badges . ''; + return '' . $topping . $user_name . $badge . ''; } endif; if (!function_exists('aksrt_get_comment_header_html')) : /** + * Comment header (zibll: zib_get_comment_header). + * * @param WP_Comment $comment Comment. * @param array $settings Settings. + * @return string */ function aksrt_get_comment_header_html(WP_Comment $comment, array $settings = []): string { - $avatar_size = max(24, (int) ($settings['avatar_size'] ?? 45)); $like_enabled = !isset($settings['like_enabled']) || !empty($settings['like_enabled']); - $avatar = get_avatar($comment, $avatar_size, '', '', ['class' => 'avatar-img comt-avatar']); + $avatar = aksrt_get_comment_avatar_box($comment, 'avatar-img comt-avatar'); $name = aksrt_get_comments_user_name_html($comment, $settings); $like = aksrt_get_comment_like_html($comment, $like_enabled); - $inner = '
    ' . $avatar . $name . $like . '
    '; - return '
    ' . $inner . '
    '; + + $html = '
    '; + $html .= $avatar; + $html .= $name; + $html .= $like; + $html .= '
    '; + + return '
    ' . $html . '
    '; } endif; if (!function_exists('aksrt_get_comments_action_dropdown_html')) : /** - * More menu: pin / edit / approve / delete (REST-driven via data-comment-action). + * More-actions menu (zibll: zib_get_comments_action_list) — pin / edit / approve / delete. * * @param WP_Comment $comment Comment. * @param int $depth Depth. + * @return string */ function aksrt_get_comments_action_dropdown_html(WP_Comment $comment, int $depth = 0): string { $perms = function_exists('aksrt_comment_action_permissions') @@ -107,95 +154,86 @@ if (!function_exists('aksrt_get_comments_action_dropdown_html')) : : ['can_edit' => false, 'can_delete' => false, 'can_moderate' => false, 'can_pin' => false]; $is_pinned = function_exists('aksrt_is_comment_pinned') && aksrt_is_comment_pinned($comment); $is_pending = '0' === (string) $comment->comment_approved; - $is_spam = 'spam' === (string) $comment->comment_approved; $lists = ''; if (!empty($perms['can_pin']) && (int) $comment->comment_parent === 0) { - $label = $is_pinned ? __('取消置顶', 'aksrt') : __('设置置顶', 'aksrt'); - $lists .= '
  • ' . esc_html($label) . '
  • '; + $label = $is_pinned ? __('取消置顶', 'aksrt') : __('设置置顶', 'aksrt'); + $lists .= '
  • ' . esc_html($label) . '
  • '; } if (!empty($perms['can_edit'])) { - $lists .= '
  • ' . esc_html__('编辑', 'aksrt') . '
  • '; + $lists .= '
  • ' . esc_html__('编辑', 'aksrt') . '
  • '; } if (!empty($perms['can_moderate'])) { - if ($is_pending) { - $lists .= '
  • ' . esc_html__('批准', 'aksrt') . '
  • '; - } elseif (!$is_spam) { - $lists .= '
  • ' . esc_html__('驳回', 'aksrt') . '
  • '; - } - $lists .= '
  • ' . esc_html__('垃圾', 'aksrt') . '
  • '; + $text = $is_pending ? __('批准', 'aksrt') : __('驳回', 'aksrt'); + $class = $is_pending ? 'approve' : 'unapprove'; + $action = $is_pending ? 'approve' : 'hold'; + $lists .= '
  • ' . esc_html($text) . '
  • '; } if (!empty($perms['can_delete'])) { - $lists .= '
  • ' . esc_html__('删除', 'aksrt') . '
  • '; + $lists .= '
  • ' . esc_html__('删除', 'aksrt') . '
  • '; } if ($lists === '') { return ''; } - return '' - . '' - . '' - . ''; + $icon_a = ''; + + return '' . $icon_a . ''; } endif; if (!function_exists('aksrt_get_comment_footer_html')) : /** - * comt-meta: time-ago · city · @parent · approve · reply · dropdown. + * comt-meta row (zibll: zib_get_comment_footer). * * @param WP_Comment $comment Comment. * @param array $args wp_list_comments args. * @param int $depth Depth. * @param array $settings Settings. + * @return string */ function aksrt_get_comment_footer_html(WP_Comment $comment, array $args, int $depth, array $settings = []): string { $is_pending = '0' === (string) $comment->comment_approved; - // Time ago. - $absolute = date_i18n('Y-m-d H:i:s', strtotime((string) $comment->comment_date)); + $badg_approve = ''; + if ($is_pending) { + $badg_approve = '' . esc_html__('待审核', 'aksrt') . ''; + } + $badg_approve = '' . $badg_approve . ''; + + $absolute = date_i18n(__('Y年m月d日 H:i:s', 'aksrt'), strtotime((string) $comment->comment_date)); $ago = function_exists('aksrt_time_ago') ? aksrt_time_ago((string) $comment->comment_date) : human_time_diff(strtotime((string) $comment->comment_date), current_time('timestamp')) . __('前', 'aksrt'); $time_html = '' . esc_html($ago) . ''; - // City. $city_html = function_exists('aksrt_get_comment_city_badge_html') ? aksrt_get_comment_city_badge_html($comment) : ''; - // @ parent. $parent_html = ''; if ((int) $comment->comment_parent > 0) { $parent_author = get_comment_author((int) $comment->comment_parent); $parent_html = '@' . esc_html($parent_author) . ''; } - // Pending badge. - $approve_html = ''; - if ($is_pending) { - $approve_html .= '' . esc_html__('待审核', 'aksrt') . ''; - } - $approve_html .= ''; - - // Reply. $reply_html = ''; if (!$is_pending && $depth > 0) { $max_depth = (int) ($args['max_depth'] ?? get_option('thread_comments_depth', 5)); $link = get_comment_reply_link( - array_merge( - $args, - [ - 'add_below' => 'div-comment', - 'reply_text' => __('回复', 'aksrt'), - 'depth' => $depth, - 'max_depth' => $max_depth, - ] - ), + [ + 'add_below' => 'div-comment', + 'reply_text' => __('回复', 'aksrt'), + 'login_text' => __('回复', 'aksrt'), + 'depth' => $depth, + 'max_depth' => $max_depth, + ], $comment ); if ($link) { - // Ensure data-commentid for moveForm path. + // 去掉 WP 内联 onclick(addComment.moveForm),回复由 comment-move-form.js 事件委托处理。 + $link = preg_replace('/ onclick="[^"]*"/i', '', $link); if (strpos($link, 'data-commentid') === false) { $link = str_replace( 'comment-reply-link', @@ -208,15 +246,49 @@ if (!function_exists('aksrt_get_comment_footer_html')) : } $actions = aksrt_get_comments_action_dropdown_html($comment, $depth); - $info = $time_html . $city_html . $parent_html . $approve_html . $reply_html; + $info = $time_html . $city_html . $parent_html . $badg_approve . $reply_html; - return '
    ' . $info . $actions . '
    '; + return '
    ' . $info . $actions . '
    '; + } +endif; + +if (!function_exists('aksrt_get_comments_list_html')) : + /** + * Single comment item HTML (zibll: zib_get_comments_list). + * + * @param WP_Comment $comment Comment. + * @param array $args Args. + * @param int $depth Depth. + * @param array $settings Settings. + * @return string + */ + function aksrt_get_comments_list_html(WP_Comment $comment, array $args = [], int $depth = 0, array $settings = []): string { + $comment_id = (int) $comment->comment_ID; + $con = function_exists('aksrt_render_comment_content') + ? aksrt_render_comment_content((string) get_comment_text($comment)) + : wp_kses_post((string) get_comment_text($comment)); + $header = aksrt_get_comment_header_html($comment, $settings); + $footer = aksrt_get_comment_footer_html($comment, $args, $depth, $settings); + + $html = '
  • '; + $html .= '
      '; + $html .= '
    • '; + $html .= $header; + $html .= ''; + $html .= '
    • '; + $html .= '
    '; + return $html; } endif; if (!function_exists('aksrt_comment_callback')) : /** - * Canonical comment list item renderer (zibll structure). + * Canonical wp_list_comments callback (zibll: zib_comments_list). + * + * The closing
  • is emitted by the walker after children. * * @param WP_Comment $comment Comment. * @param array $args Args. @@ -230,37 +302,7 @@ if (!function_exists('aksrt_comment_callback')) : $settings = \AKSRT\Settings\Settings::get_comment_display_settings(); } - $comment_id = (int) $comment->comment_ID; - $depth_class = 'aksrt-depth-' . min((int) ($settings['nested_depth'] ?? 3), (int) $depth); - $is_pinned = function_exists('aksrt_is_comment_pinned') && aksrt_is_comment_pinned($comment); - $is_pending = '0' === (string) $comment->comment_approved; - $li_classes = trim($depth_class . ($is_pinned ? ' aksrt-comment--pinned' : '')); - - $header = aksrt_get_comment_header_html($comment, $settings); - $footer = aksrt_get_comment_footer_html($comment, $args, (int) $depth, $settings); - - if ($is_pending) { - $body = '

    ' . esc_html__('您的评论正在等待审核。', 'aksrt') . '

    '; - } else { - $body = function_exists('aksrt_render_comment_content') - ? aksrt_render_comment_content((string) get_comment_text($comment)) - : wp_kses_post((string) get_comment_text($comment)); - } - - echo '
  • '; - echo '
      '; - echo '
    • '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- composed helpers escape. - echo $header; - echo ''; - echo '
    • '; - echo '
    '; - // Closing
  • is emitted by Walker_Comment after children. + echo aksrt_get_comments_list_html($comment, is_array($args) ? $args : [], (int) $depth, $settings); } endif; diff --git a/inc/helpers/template-tags/search-meta.php b/inc/helpers/template-tags/search-meta.php index d2de7e3d..f2f321f3 100644 --- a/inc/helpers/template-tags/search-meta.php +++ b/inc/helpers/template-tags/search-meta.php @@ -491,75 +491,84 @@ endif; if (!function_exists('aksrt_render_comment_pagination')) { /** - * 渲染评论列表分页(根据后台配置选择模式) + * 渲染评论列表分页(zibll 标记:数字 pagenav / ajax_lists 加载更多) */ function aksrt_render_comment_pagination(): void { - $comment_pagination_mode = class_exists('\AKSRT\Settings\Settings') - ? \AKSRT\Settings\Settings::get_comment_pagination_mode() - : 'numbered'; + $settings = class_exists('\AKSRT\Settings\Settings') + ? \AKSRT\Settings\Settings::get_comment_display_settings() + : []; + $mode = (string) ($settings['pagination_mode'] ?? 'numbered'); - if ($comment_pagination_mode === 'numbered') { - $pagination_links = paginate_comments_links([ - 'echo' => false, - 'prev_text' => __('上一页', 'aksrt'), - 'next_text' => __('下一页', 'aksrt'), - 'type' => 'plain', - ]); + global $wp_query; + $max_pages = (int) get_comment_pages_count(); + if (empty($max_pages)) { + $max_pages = isset($wp_query->max_num_comment_pages) ? (int) $wp_query->max_num_comment_pages : 1; + } + $paged = (int) get_query_var('cpage', 0); + $paged = $paged > 0 ? $paged : 1; - if (empty($pagination_links)) { + if ($mode === 'ajax_lists') { + $next_page = $paged + 1; + if ($next_page > $max_pages || $max_pages <= 1) { return; } - global $wp_query; - $max_pages = get_comment_pages_count(); - $current_page = max(1, get_query_var('cpage', 1)); - - echo ''; + $author_only = isset($_GET['aksrt_author_only']) && (int) wp_unslash($_GET['aksrt_author_only']) === 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $ias = !empty($settings['paging_ajax_ias']); + $ias_max = (int) ($settings['paging_ajax_ias_max'] ?? 3); + $next = get_comments_pagenum_link($next_page, $max_pages); + + $classes = 'theme-pagination ias-pagenav pagenav aksrt-comment-pagination'; + $ias_attr = ''; + if ($ias && ($paged <= $ias_max || !$ias_max)) { + $classes .= ' lazyload'; + $ias_attr = ' lazyload-action="ias"'; + } + + printf( + '', + esc_attr($classes), + $ias_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 固定字面量。 + esc_attr((string) $next_page), + esc_attr((string) $max_pages), + esc_attr((string) get_the_ID()), + esc_attr($order), + $author_only ? '1' : '0', + esc_url($next), + esc_html__('加载更多', 'aksrt') + ); return; } - // load_more / infinite 模式 - $post_id = get_the_ID(); - $total = (int) get_comments_number($post_id); - $per_page = (int) get_option('comments_per_page', 50); - $max_pages = $per_page > 0 ? ceil($total / $per_page) : 1; - $current_page = max(1, get_query_var('cpage', 1)); - $comment_order = (string) get_query_var('aksrt_comment_order', 'newest'); - if (!in_array($comment_order, ['newest', 'oldest', 'hottest'], true)) { - $comment_order = 'newest'; - } - $author_only = isset($_GET['aksrt_author_only']) && (int) $_GET['aksrt_author_only'] === 1; + // 数字分页(zibll:paginate_links + 跳页输入框) + $is_mobile = wp_is_mobile(); + $args = [ + 'base' => add_query_arg('cpage', '%#%', get_permalink()), + 'type' => 'array', + 'mid_size' => $is_mobile ? 1 : 2, + 'prev_text' => '' . __('上一页', 'aksrt') . '', + 'next_text' => '' . __('下一页', 'aksrt') . '', + 'total' => $max_pages, + 'current' => $paged, + 'add_fragment' => '#comments', + ]; - if ($current_page >= $max_pages || $total <= $per_page) { + $array = paginate_links($args); + if (!$array) { return; } - ?> -
    - - - - -
    - 8) { + $array[] = '' . __('跳转', 'aksrt') . ''; + } + + echo ''; } } diff --git a/src/Core/ScriptsPart1c.php b/src/Core/ScriptsPart1c.php index 0650e15a..e9d3202c 100644 --- a/src/Core/ScriptsPart1c.php +++ b/src/Core/ScriptsPart1c.php @@ -476,10 +476,8 @@ trait ScriptsPart1c { } // Page navigation (TOC highlight, smooth scroll, doc search) - // 评论回复脚本 - if (is_singular() && comments_open() && get_option('thread_comments')) { - wp_enqueue_script('comment-reply'); - } + // 评论回复脚本:由 assets/js/core/comment-move-form.js 提供(zibll 同款机制), + // 不加载 WP comment-reply,避免两套 moveForm 冲突。 $runtime_routes = $this->resolve_frontend_routes();