feat: 新增站点公告系统与多项体验优化

此提交完成了以下核心功能与优化:
1. 新增站点公告全流程支持:包含公告模型、CRUD接口、管理后台页面、公告详情页与首页展示
2. 实现评论楼层化与回复嵌套:重构评论系统为树状结构,支持回复评论与层级限制
3. 添加用户在线状态追踪:异步更新用户最后活跃时间并做SQL限频
4. 优化用户体验:移动端浮动操作条、统一板块标签样式、用户页签到积分展示、注册即登录优化
5. 其他细节优化:SEO站点地图新增公告页、评论分页与统计、登录/注册表单增强等
This commit is contained in:
2026-09-13 21:38:01 +08:00
parent 9bae6f2513
commit 996a870015
41 changed files with 2846 additions and 786 deletions

View File

@@ -378,6 +378,80 @@ h1, h2, h3, h4 {
white-space: nowrap;
}
/* 帖子列表中的板块小标签:全站统一浅灰配色,避免每行多色眩目 */
.j13-board-tag {
display: inline-flex;
align-items: center;
padding: 0 7px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
line-height: 1.65;
background: var(--tint);
color: var(--ink-2);
white-space: nowrap;
transition: background 0.15s ease, color 0.15s ease;
}
.j13-board-tag:hover {
background: var(--accent-soft);
color: var(--accent);
}
/* 站点公告标签:预设色板(浅/暗成对,文字与底色均满足 AA 对比度) */
.j13-anno-tag {
display: inline-flex;
align-items: center;
max-width: 132px;
padding: 2px 10px;
border-radius: 999px;
font-size: 11px;
font-weight: 700;
line-height: 1.55;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.j13-anno-tag.is-blue { background: rgba(52, 81, 200, 0.12); color: #3451c8; }
.j13-anno-tag.is-green { background: rgba(19, 115, 51, 0.12); color: #137333; }
.j13-anno-tag.is-orange { background: rgba(165, 66, 10, 0.12); color: #a5420a; }
.j13-anno-tag.is-red { background: rgba(200, 40, 30, 0.1); color: #c8281e; }
.j13-anno-tag.is-purple { background: rgba(109, 71, 192, 0.12); color: #6d47c0; }
.j13-anno-tag.is-gray { background: rgba(82, 96, 122, 0.13); color: #52607a; }
.dark .j13-anno-tag.is-blue { background: rgba(169, 184, 255, 0.18); color: #a9b8ff; }
.dark .j13-anno-tag.is-green { background: rgba(88, 209, 138, 0.16); color: #58d18a; }
.dark .j13-anno-tag.is-orange { background: rgba(240, 135, 90, 0.17); color: #f0875a; }
.dark .j13-anno-tag.is-red { background: rgba(255, 107, 96, 0.16); color: #ff6b60; }
.dark .j13-anno-tag.is-purple { background: rgba(192, 168, 245, 0.18); color: #c0a8f5; }
.dark .j13-anno-tag.is-gray { background: rgba(170, 182, 207, 0.17); color: #aab6cf; }
/* 后台颜色选择器圆点 */
.j13-anno-dot {
width: 22px;
height: 22px;
border-radius: 999px;
border: 2px solid transparent;
cursor: pointer;
padding: 0;
transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.j13-anno-dot:hover { transform: scale(1.12); }
.j13-anno-dot[aria-pressed="true"] {
border-color: var(--panel);
box-shadow: 0 0 0 2px var(--accent);
}
.j13-anno-dot.is-blue { background: #3451c8; }
.j13-anno-dot.is-green { background: #137333; }
.j13-anno-dot.is-orange { background: #a5420a; }
.j13-anno-dot.is-red { background: #c8281e; }
.j13-anno-dot.is-purple { background: #6d47c0; }
.j13-anno-dot.is-gray { background: #52607a; }
.dark .j13-anno-dot.is-blue { background: #a9b8ff; }
.dark .j13-anno-dot.is-green { background: #58d18a; }
.dark .j13-anno-dot.is-orange { background: #f0875a; }
.dark .j13-anno-dot.is-red { background: #ff6b60; }
.dark .j13-anno-dot.is-purple { background: #c0a8f5; }
.dark .j13-anno-dot.is-gray { background: #aab6cf; }
/* ----- 分页 ----- */
.pager-btn {
background: var(--panel);
@@ -688,6 +762,147 @@ h1, h2, h3, h4 {
.prose-content hr { border: none; border-top: 1px solid var(--line); margin: 2.2rem 0; }
.prose-content strong { font-weight: 700; }
/* 评论区的 Markdown 紧凑排版:继承 prose-content 全部规则,仅收紧行距与间距 */
.prose-comment { font-size: 14.5px; line-height: 1.7; }
.prose-comment p { margin: 0.35rem 0; }
.prose-comment blockquote { margin: 0.5rem 0; padding: 0.45rem 0.9rem; }
.prose-comment pre { margin: 0.6rem 0; }
.prose-comment h1, .prose-comment h2, .prose-comment h3, .prose-comment h4 {
font-size: 1em;
margin: 0.6rem 0 0.3rem;
border-bottom: none;
font-weight: 700;
}
/* 移动端浮动操作条内的点赞按钮:放大到 44px 触控标准 */
.j13-bar-like .j13-like {
height: 44px;
padding: 0 14px;
font-size: 13px;
}
/* 评论楼层树:抖音风格
主评论全宽;子回复折叠在 panel-2 背景容器内,点击"展开 X 条回复"显示
子回复之间用淡分隔线;depth≥2 时昵称后显示 ▶ 被回复者 */
/* 子回复行:紧凑布局,头像 28px */
.cmt-reply-row {
padding: 8px 0;
border-top: 1px solid var(--line);
}
.cmt-reply-row:first-child {
border-top: none;
padding-top: 0;
}
/* 子回复昵称 */
.cmt-reply-name {
font-size: 13px;
font-weight: 600;
color: var(--ink-2);
}
/* 楼层号标签(主评论昵称旁) */
.cmt-floor-label {
font-size: 11.5px;
font-weight: 600;
color: var(--ink-3);
text-decoration: none;
padding: 1px 6px;
border-radius: 6px;
background: var(--tint);
transition: color 0.15s;
}
.cmt-floor-label:hover {
color: var(--accent);
}
/* 回复文字按钮:放在时间右侧,抖音风格 */
.cmt-reply-btn {
font-size: 12px;
font-weight: 500;
color: var(--ink-3);
background: none;
border: none;
padding: 0;
cursor: pointer;
}
.cmt-reply-btn:hover {
color: var(--accent);
}
/* 右三角箭头(回复子评论时) */
.cmt-reply-arrow {
color: var(--ink-3);
flex-shrink: 0;
}
/* 被回复者名称(可点击跳转) */
.cmt-reply-target {
font-size: 13px;
font-weight: 600;
color: var(--ink-2);
text-decoration: none;
white-space: nowrap;
}
.cmt-reply-target:hover {
color: var(--accent);
}
/* 子回复容器:背景与主评论区分,圆角 */
.cmt-replies-wrap {
margin-top: 8px;
padding: 4px 12px;
background: var(--panel-2);
border-radius: 12px;
}
/* 孙评论及更深:小幅缩进 + 细引导线 */
.cmt-children {
margin-top: 2px;
padding-left: 10px;
border-left: 1px solid var(--line);
}
/* 展开/收起按钮 */
.cmt-fold-btn {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 12.5px;
font-weight: 600;
color: var(--accent);
padding: 4px 10px;
border-radius: 99px;
background: var(--accent-soft);
border: none;
cursor: pointer;
transition: background 0.15s;
}
.cmt-fold-btn:hover {
background: color-mix(in srgb, var(--accent) 18%, transparent);
}
/* 评论内联回复表单:出现在目标评论正下方 */
.cmt-reply-form {
padding: 12px 14px;
border-radius: 14px;
background: var(--panel-2);
margin-top: 8px;
}
.cmt-reply-form .field {
font-size: 13.5px;
}
@media (max-width: 640px) {
.cmt-replies-wrap {
padding: 4px 8px;
}
.cmt-children {
padding-left: 8px;
}
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}