feat: 管理台搜索/分区刷新、评论人员体系、相关项目,修复内容源自动获取,完善 MCP 自描述
Build and Deploy / build (push) Successful in 1m32s
Build and Deploy / deploy (push) Successful in 26s

管理台:
- 内容管理新增名称搜索(title/slug/url/description),状态与翻页链接保留搜索词
- 菜单改为真实链接,每次点击重新向后台取数渲染分区,不再依赖手动刷新
- 内容管理每页固定 20 条
- pending 条目按钮改为「预览」,active 为「查看」

评论体系:
- 评论提交新增必填联系方式(手机号/邮箱),前端不做展示
- 首次评论以「昵称+联系方式」建档,之后需匹配且未被禁用
- 后台评论管理新增联系方式列;新增评论人员管理页,可启用/禁用/改名/删除
- 评论昵称输入框不再预置 admin

相关项目:
- 新增 entry_relations 双向关联,详情页侧栏展示并写入机读 JSON
- 编辑页可添加/移除关联

内容源自动获取:
- 修复 rss 适配器把 feed url 当成条目 url 的根本问题,支持 Atom link/href 与相对链接
- eryajf-weekly 限定正文容器取链接,修正项目说明的提取与「(opens new window)」清理
- pipeline 增加轮内去重与单条失败隔离;scheduler 对非法 cron 明确告警

MCP:
- 重写 instructions 为八节说明,新增 usage 工具返回结构化接入文档
- 补全各工具的参数、用途与返回格式说明;baseUrl 取自当次请求
- 首页 MCP 区块与 README 同步补充写入示例与踩坑清单

测试: 新增 comments/relations/admin/ingest-adapters 用例,共 29 个全部通过
This commit is contained in:
cheney
2026-10-27 11:22:26 +08:00
parent 3f7b48325f
commit 806761103b
29 changed files with 1727 additions and 133 deletions
+25
View File
@@ -150,14 +150,39 @@
});
}
var CONTACT_EMAIL = /^[^\s@]+@[^\s@]+\.[A-Za-z]{2,}$/;
var CONTACT_PHONE = /^1[3-9]\d{9}$/;
function validContact(v) {
var s = String(v == null ? "" : v).trim();
return CONTACT_EMAIL.test(s) || CONTACT_PHONE.test(s);
}
var commentForm = document.querySelector(".comment-form[data-entry-id]");
if (commentForm) {
var contactInput = commentForm.querySelector("[name=contact]");
if (contactInput) {
contactInput.addEventListener("input", function () {
if (contactInput.value.trim() && validContact(contactInput.value)) {
contactInput.setCustomValidity("");
} else {
contactInput.setCustomValidity("请填写正确的手机号或邮箱(不会公开显示)");
}
});
}
commentForm.addEventListener("submit", function (e) {
e.preventDefault();
var contact = contactInput ? contactInput.value.trim() : "";
if (!validContact(contact)) {
toast("请填写正确的联系方式:手机号或邮箱");
if (contactInput) contactInput.focus();
return;
}
if (!commentForm.reportValidity()) return;
postJson("/api/comments", {
entryId: Number(commentForm.getAttribute("data-entry-id")),
authorName: commentForm.querySelector("[name=authorName]").value,
contact: contact,
body: commentForm.querySelector("[name=body]").value,
})
.then(function () {