feat: 管理端板块管理与旧版数据导入,补充部署运营文档

- 新增管理端板块管理页面与后端接口(admin_board)
- 新增旧版数据导入:legacyimport 服务、导入面板、importusers 命令行工具
- 聊天用户卡片、板块图标等 UI 组件与界面优化
- 补充 about/公告/1Panel 部署等文档
- gitignore 排除 dist/ 构建产物与 .agents/ 本地工具目录
This commit is contained in:
2026-09-24 03:37:44 +08:00
parent c1f6a6636b
commit 3e55b5d230
53 changed files with 5078 additions and 409 deletions

View File

@@ -3167,6 +3167,7 @@ body:has([data-admin-viewport]) {
justify-content: space-between;
gap: 0.75rem;
padding: 0 1rem;
/* 半透明 + 毛玻璃:后台画布镂空透出全站画布层,顶栏与画布融为一体 */
background: color-mix(in srgb, var(--bg) 88%, transparent);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
@@ -3253,6 +3254,11 @@ body:has([data-admin-viewport]) {
padding-top: 0;
}
/* 公告/单页编辑器吸顶操作栏:同上,必须留在未分层区域才能压过 .admin-canvas 的媒体查询内边距 */
.admin-canvas:has(.admin-doc-editor) {
padding-top: 0;
}
/* 移动端导航抽屉 */
.admin-drawer {
position: fixed;
@@ -3441,6 +3447,12 @@ select:focus-visible {
color: transparent;
caret-color: var(--ink);
}
/* 框选时 ::selection 前景色会盖过透明字色,露出底层真实文本(@用户名);
这里保持字形透明 + 半透明高亮,让镜像层的 @昵称 透出(宽度已补偿对齐) */
.j13-chat-composer-input.has-value::selection {
background: color-mix(in srgb, var(--accent) 24%, transparent);
color: transparent;
}
.j13-chat-composer-input.has-value::placeholder {
color: transparent;
}
@@ -3525,20 +3537,18 @@ a.j13-mention-token:hover {
background: var(--accent);
color: var(--accent-on) !important;
}
/* 输入镜像层:不加粗/不加 padding,避免与透明 textarea 字宽错位 */
/* 输入镜像层:token 仅蓝色文字(胶囊样式只在发出后的气泡里显示);
基础胶囊色带 !important,此处需同权重覆盖 */
.j13-chat-composer-mirror .j13-mention-token {
display: inline;
padding: 0;
margin: 0;
line-height: inherit;
font-weight: inherit;
border-radius: 999px;
font-weight: 500;
border-radius: 0;
box-shadow: none;
background: color-mix(in srgb, var(--accent) 82%, #000);
}
.dark .j13-chat-composer-mirror .j13-mention-token {
background: var(--accent);
color: var(--accent-on) !important;
background: transparent !important;
color: var(--accent) !important;
}
@layer components {
@@ -3772,10 +3782,7 @@ a.j13-mention-token:hover {
font-size: 12.5px;
}
/* 站点设置:限宽左对齐,不写入后台公共主容器 */
.admin-canvas:has(.admin-settings-page) {
background: var(--bg);
}
/* 站点设置:限宽左对齐,不写入后台公共主容器(画布保持镂空,与其他管理页一致) */
@media (min-width: 1920px) {
.admin-canvas:has(.admin-settings-page) {
padding-left: 3rem; /* 宽屏距主导航最多约 48px;1024+ 默认 2rem */
@@ -3803,9 +3810,11 @@ a.j13-mention-token:hover {
top: 0;
align-self: start;
z-index: 5;
/* 滚动时盖住右侧内容,避免透出 */
background: var(--bg);
padding-block: 0.15rem 0.5rem;
/* 画布镂空后导航改白色卡片:盖住滚动内容,并与右侧设置组卡片同语言 */
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--r);
padding: 0.5rem 0.4rem;
margin-block: -0.15rem;
}
.admin-settings-nav {
@@ -4773,10 +4782,7 @@ a.j13-mention-token:hover {
outline-offset: 2px;
}
/* 单页管理:列表与编辑各自限宽,不套用设置页 1120px */
.admin-canvas:has(.admin-doc-page) {
background: var(--bg);
}
/* 单页/公告管理:限宽左对齐,不套用设置页 1120px;画布保持镂空,与其他管理页一致 */
.admin-doc-page {
width: 100%;
margin-inline: 0;
@@ -4785,56 +4791,126 @@ a.j13-mention-token:hover {
.admin-doc-list {
max-width: 1240px;
}
/* 编辑器本身通栏:吸顶栏背景/分隔线才能横贯整个画布,不在 1440px 处被切断 */
.admin-doc-editor {
max-width: 1440px;
container-type: inline-size;
container-name: doc-editor;
}
.admin-doc-head {
/* 编辑器吸顶操作栏:返回/标题/状态 + 发布状态/撤销/保存,滚动时始终可见。
画布镂空透出全站画布层,操作栏用白色块(同用户管理吸顶栏),滚动时干净盖住内容 */
.admin-doc-sticky {
position: sticky;
top: 0;
z-index: 20;
margin-inline: -1rem;
padding: 0.6rem 1rem;
background: var(--panel);
border-bottom: 1px solid var(--line);
}
@media (min-width: 640px) {
.admin-doc-sticky {
margin-inline: -1.5rem;
padding-inline: 1.5rem;
}
}
@media (min-width: 1024px) {
.admin-doc-sticky {
margin-inline: -2rem;
padding-inline: 2rem;
}
}
/* 栏内内容与下方 1440px 内容区对齐(编辑器已通栏) */
.admin-doc-sticky-inner {
display: flex;
align-items: flex-start;
align-items: center;
justify-content: space-between;
gap: 0.75rem 1rem;
margin-bottom: 1.25rem;
gap: 0.5rem 1rem;
flex-wrap: wrap;
max-width: 1440px;
margin-right: auto;
}
.admin-doc-sticky-title {
display: flex;
align-items: center;
gap: 0.55rem;
flex: 1 1 auto;
min-width: 0;
}
.admin-doc-sticky-icon {
width: 2rem;
height: 2rem;
border-radius: 0.65rem;
background: var(--accent-soft);
color: var(--accent);
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.admin-doc-sticky-title h1 {
margin: 0;
font-size: 17px;
line-height: 1.3;
font-weight: 750;
letter-spacing: -0.01em;
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.admin-doc-back {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.3rem;
min-width: 2rem;
min-height: 2rem;
font-size: 13px;
padding: 0 0.6rem;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--panel);
font-size: 12.5px;
color: var(--ink-2);
text-decoration: none;
flex-shrink: 0;
transition: border-color 0.15s ease, color 0.15s ease;
}
.admin-doc-back:hover {
color: var(--accent);
border-color: var(--accent);
}
.admin-doc-back:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 0.4rem;
}
.admin-doc-head-title {
@media (max-width: 420px) {
.admin-doc-back-text {
display: none;
}
}
.admin-doc-sticky-actions {
display: flex;
align-items: center;
gap: 0.6rem;
gap: 0.45rem 0.55rem;
flex-wrap: wrap;
margin-top: 0.15rem;
}
.admin-doc-head-title h1 {
margin: 0;
font-size: 22px;
line-height: 1.25;
font-weight: 800;
letter-spacing: -0.02em;
color: var(--ink);
.admin-doc-sticky-actions .btn {
min-height: 2.25rem;
}
.admin-doc-status {
margin: 0 0 0 0.15rem;
font-size: 12.5px;
color: var(--ink-3);
}
.admin-doc-status.is-error {
color: var(--danger);
}
.admin-doc-split {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1.25rem;
align-items: start;
max-width: 1440px;
}
.admin-doc-main {
min-width: 0;
@@ -4850,6 +4926,18 @@ a.j13-mention-token:hover {
line-height: 1.4;
color: var(--ink-2);
}
.admin-doc-label-value {
margin-left: 0.4rem;
font-weight: 600;
color: var(--ink-3);
}
/* 主栏标题输入:正文中最大的输入项,突出「先起标题」 */
.admin-doc-title .admin-field-input {
font-size: 16.5px;
font-weight: 650;
letter-spacing: -0.01em;
min-height: 2.9rem;
}
.admin-doc-hint {
margin: 0.35rem 0 0;
font-size: 12.5px;
@@ -4857,6 +4945,75 @@ a.j13-mention-token:hover {
color: var(--ink-3);
overflow-wrap: anywhere;
}
/* 编辑页主栏整块铺纯白(含标题与正文编辑区):画布镂空后编辑区域需要干净的白底,
右栏设置卡同为白卡,两卡之间露出纹饰画布 */
.admin-doc-editor .admin-doc-main {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 12px;
padding: 1.1rem 1.1rem 1.2rem;
}
/* 编辑器自带白卡边框在纯白主栏内会形成双层描边,扁平化融入主卡 */
.admin-doc-editor .admin-doc-main .j13-md-editor:not(.is-fullscreen) {
background: transparent;
border: 0;
border-radius: 0;
padding: 0;
}
/* 板块管理:低信息密度列表 —— 策略/状态/帖数并入板块元信息行,6 列并 3 列并限宽,
避免宽屏下名称列吞掉全部富余空间而显得空旷 */
.boards-panel {
max-width: 60rem;
}
.boards-head,
.boards-row {
display: grid;
grid-template-columns: 44px minmax(0, 1fr) auto;
gap: 0.75rem;
align-items: center;
padding-inline: 1rem;
}
.boards-head {
padding-block: 0.65rem;
font-size: 11.5px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--ink-3);
border-bottom: 1px solid var(--line);
}
.boards-row {
padding-block: 0.8rem;
}
.boards-row + .boards-row {
border-top: 1px solid var(--line);
}
.boards-actions {
justify-self: end;
}
.boards-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.45rem;
margin-top: 0.4rem;
}
.boards-meta-posts {
font-size: 11.5px;
color: var(--ink-3);
font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
.boards-head {
display: none;
}
.boards-row {
grid-template-columns: 40px minmax(0, 1fr);
}
.boards-actions {
grid-column: 2;
justify-self: start;
}
}
.admin-doc-md .j13-md-editor:not(.is-fullscreen) {
height: clamp(16rem, calc(100dvh - 22rem), 40rem);
min-height: 0;
@@ -4875,7 +5032,7 @@ a.j13-mention-token:hover {
border: 1px solid var(--line);
border-radius: 12px;
background: var(--panel);
padding: 0.85rem 0.9rem 1rem;
padding: 0.9rem 1rem 1.05rem;
}
.admin-doc-rail > summary {
cursor: pointer;
@@ -4886,15 +5043,39 @@ a.j13-mention-token:hover {
min-height: 2.25rem;
display: flex;
align-items: center;
position: relative;
padding-right: 1.5rem;
user-select: none;
}
.admin-doc-rail > summary::-webkit-details-marker {
display: none;
}
/* 折叠箭头:桌面双栏时 summary 隐藏,仅移动端单栏可见 */
.admin-doc-rail > summary::after {
content: "";
position: absolute;
right: 0.35rem;
top: 50%;
width: 0.42rem;
height: 0.42rem;
border-right: 1.5px solid var(--ink-3);
border-bottom: 1.5px solid var(--ink-3);
transform: translateY(-70%) rotate(45deg);
transition: transform 0.15s ease;
}
.admin-doc-rail[open] > summary::after {
transform: translateY(-30%) rotate(-135deg);
}
.admin-doc-rail-body {
display: flex;
flex-direction: column;
gap: 1rem;
padding-top: 0.35rem;
padding-top: 0.25rem;
}
/* 设置项分组:细分隔线代替卡片套卡片 */
.admin-doc-rail-body > * + * {
margin-top: 1.05rem;
padding-top: 1.05rem;
border-top: 1px solid var(--line);
}
.admin-doc-field {
min-width: 0;
@@ -4949,6 +5130,21 @@ a.j13-mention-token:hover {
flex-wrap: wrap;
gap: 0.45rem;
}
/* 标签胶囊实时预览:色块下方一条安静的展示条,与前台同款 j13-anno-tag */
.admin-doc-tagpreview {
display: flex;
align-items: center;
gap: 0.55rem;
margin-top: 0.7rem;
padding: 0.6rem 0.75rem;
border-radius: 0.7rem;
background: var(--bg);
}
.admin-doc-tagpreview::after {
content: attr(data-note);
font-size: 12px;
color: var(--ink-3);
}
.admin-doc-colors .j13-anno-dot {
width: 2.25rem;
height: 2.25rem;
@@ -4963,26 +5159,6 @@ a.j13-mention-token:hover {
color: var(--ink);
font-size: 14px;
}
.admin-doc-actions {
min-width: 0;
}
.admin-doc-actions-btns {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.6rem 0.75rem;
}
.admin-doc-actions .btn {
min-height: 2.5rem;
}
.admin-doc-status {
margin: 0;
font-size: 12.5px;
color: var(--ink-3);
}
.admin-doc-status.is-error {
color: var(--danger);
}
.admin-doc-table-wrap {
min-width: 0;
}
@@ -5129,11 +5305,11 @@ a.j13-mention-token:hover {
cursor: not-allowed;
}
@container doc-editor (min-width: 64rem) {
/* 双栏阈值取 72rem:保证吸顶操作栏单行放下,右侧设置栏再入列 */
@container doc-editor (min-width: 72rem) {
.admin-doc-split {
grid-template-columns: minmax(0, 1fr) 19rem;
column-gap: 1.5rem;
row-gap: 0.85rem;
grid-template-columns: minmax(0, 1fr) 20rem;
column-gap: 1.75rem;
}
.admin-doc-main {
grid-column: 1;
@@ -5141,10 +5317,12 @@ a.j13-mention-token:hover {
}
.admin-doc-rail {
grid-column: 2;
grid-row: 1 / span 2;
grid-row: 1;
align-self: start;
position: sticky;
top: 0;
max-height: calc(100dvh - 6rem);
/* 吸顶操作栏(约 3.7rem)之下留出呼吸空隙 */
top: 4.5rem;
max-height: calc(100dvh - 10rem);
overflow: auto;
}
.admin-doc-rail > summary {
@@ -5153,9 +5331,10 @@ a.j13-mention-token:hover {
.admin-doc-rail:not([open]) > .admin-doc-rail-body {
display: flex;
}
.admin-doc-actions {
grid-column: 1;
grid-row: 2;
/* 现代浏览器(Chrome 131+)对关闭的 details 用 content-visibility 隐藏内容,
上一条 display 规则救不回来;桌面双栏强制可见,防止移动端折叠后拉宽窗口设置凭空消失 */
.admin-doc-rail:not([open])::details-content {
content-visibility: visible;
}
}
@@ -6118,7 +6297,8 @@ a.j13-mention-token:hover {
transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.j13-anno-dot:hover { transform: scale(1.12); }
.j13-anno-dot[aria-pressed="true"] {
.j13-anno-dot[aria-pressed="true"],
.j13-anno-dot[aria-checked="true"] {
border-color: var(--panel);
box-shadow: 0 0 0 2px var(--accent);
}
@@ -8499,7 +8679,7 @@ html.j13-reduce-chrome .j13-att-card.is-fresh {
transition: none !important;
}
/* 头像配色(浅/暗各自保证可读) */
/* 头像/板块配色(浅/暗各自保证可读) */
.av-0 { background: rgba(52, 81, 200, 0.12); color: #3451c8; }
.av-1 { background: rgba(10, 99, 117, 0.12); color: #0a6375; }
.av-2 { background: rgba(109, 71, 192, 0.12); color: #6d47c0; }
@@ -8508,6 +8688,14 @@ html.j13-reduce-chrome .j13-att-card.is-fresh {
.av-5 { background: rgba(171, 56, 93, 0.12); color: #ab385d; }
.av-6 { background: rgba(133, 88, 0, 0.14); color: #855800; }
.av-7 { background: rgba(82, 96, 122, 0.13); color: #52607a; }
.av-8 { background: rgba(5, 150, 105, 0.13); color: #059669; }
.av-9 { background: rgba(2, 132, 199, 0.13); color: #0284c7; }
.av-10 { background: rgba(67, 56, 202, 0.13); color: #4338ca; }
.av-11 { background: rgba(190, 24, 93, 0.13); color: #be185d; }
.av-12 { background: rgba(180, 83, 9, 0.14); color: #b45309; }
.av-13 { background: rgba(77, 124, 3, 0.14); color: #4d7c03; }
.av-14 { background: rgba(157, 23, 158, 0.13); color: #9d179e; }
.av-15 { background: rgba(159, 0, 51, 0.13); color: #9f0033; }
.dark .av-0 { background: rgba(169, 184, 255, 0.18); color: #a9b8ff; }
.dark .av-1 { background: rgba(92, 201, 224, 0.18); color: #5cc9e0; }
.dark .av-2 { background: rgba(192, 168, 245, 0.18); color: #c0a8f5; }
@@ -8516,6 +8704,14 @@ html.j13-reduce-chrome .j13-att-card.is-fresh {
.dark .av-5 { background: rgba(240, 147, 181, 0.18); color: #f093b5; }
.dark .av-6 { background: rgba(224, 178, 89, 0.18); color: #e0b259; }
.dark .av-7 { background: rgba(170, 182, 207, 0.18); color: #aab6cf; }
.dark .av-8 { background: rgba(110, 231, 183, 0.18); color: #6ee7b7; }
.dark .av-9 { background: rgba(125, 211, 252, 0.18); color: #7dd3fc; }
.dark .av-10 { background: rgba(165, 180, 252, 0.18); color: #a5b4fc; }
.dark .av-11 { background: rgba(251, 113, 133, 0.18); color: #fb7185; }
.dark .av-12 { background: rgba(252, 211, 77, 0.18); color: #fcd34d; }
.dark .av-13 { background: rgba(190, 242, 100, 0.18); color: #bef264; }
.dark .av-14 { background: rgba(232, 121, 249, 0.18); color: #e879f9; }
.dark .av-15 { background: rgba(248, 113, 113, 0.18); color: #f87171; }
/* ============================================================
微交互