<%- include('partials/head') %> <%- include('partials/topbar', { active: 'admin' }) %>

// table: entries · 状态 active | greyed | pending · 预览 = 按当前状态模拟前台展示

内容管理

全部收录条目。灰掉 = 暂不可见但保留数据;删除为物理删除,需确认。

已选 0 项
<% if (entries.length === 0) { %> <% } %> <% for (const e of entries) { %> <% } %>
标题 类型 状态 更新时间 操作
当前筛选下没有条目
<%= e.title %>
<%= (e.tags || []).join(' · ') || '—' %>
<%= e.type %> <% if (e.status === 'active') { %>active <% } else if (e.status === 'pending') { %>pending <% } else { %><%= e.status %><% } %> <%= fmtDate(e.updated_at) %>
编辑 预览 <% if (e.status !== 'active') { %> <% } else { %> <% } %> <% if (isAdmin) { %> <% } %>

// tree: tags · 拖到某个标签上 = 移为其子级;拖到下方空白处 = 移回顶层标签组

标签管理

前台预览

标签树 (可直接拖动节点调整层级,变更即时生效)

加载中…

按住节点拖动:落到某个标签上 = 变为它的子级 · 落到下方空白处 = 移回顶层

规则说明

标签可无限嵌套,列表页按组过滤时会自动包含所有后代标签的条目。

拖动标签到另一标签上可快速调整层级;拖到空白处可移回顶层。
删除父标签时其子标签自动上移一级,关联关系解除。

// table: comments

评论管理

<% for (const c of comments) { %> <% } %>
评论者内容所属条目时间操作
<%= c.author_name %><% if (c.username) { %> @<%= c.username %><% } %> <%= c.body.slice(0, 80) %><%= c.body.length > 80 ? '…' : '' %> <%= c.entry_title %> <%= fmtDate(c.created_at) %>
<% if (isAdmin) { %><% } %>

// sources: human + ai + feed · 自动拉取经 ingest/ 采集层进入待核验队列

内容源管理

<% for (const s of sources) { if (s.kind === 'human') continue; %>

<%= s.name %> kind: <%= s.kind %> · 已收录 <%= Number(s.entry_count) %> 条

<% if (s.kind === 'ai') { %>
AI 录入接口启用 <%= s.enabled ? 'ON' : 'OFF' %>

设置新的 X-Ingest-Key(留空 = 关闭通道)

调用方式:POST /api/ingest/entry · header X-Ingest-Key · 新条目默认 pending

<% } else { %>
启用定时拉取

名称

拉取地址 / 计划(cron)

适配器

<% } %>
<% } %>

新增拉取源

<% if (isAdmin) { %>

// table: accounts · role: admin | editor

账号管理

<% for (const u of users) { %> <% } %>
ID用户名角色状态最后登录操作
#<%= u.id %> <%= u.username %> <%= u.role %> <%= u.status %> <%= u.last_login_at ? fmtDate(u.last_login_at) : '从未登录' %>
<% if (u.id !== user.id) { %> <% } %>

用户名

初始密码

角色

<% } %>
<%- include('partials/footer-bar') %>