refactor(web): 下载盘、RSS、订阅、设置与待处理的剩余去噪项(DEAI-2)
- 下载面板:下载盘只显示「已用 x / 总量」与进度条,暂停线 / 在途 / 预留 / 可清理 / 做种保留收进详情; 阈值文案统一「暂停线 / 恢复线 / 下载盘满暂停」 - RSS 页去掉与站点页重复的站点表,节标题「RSS 地址」;用途只在非通用时显示 - 订阅:一条都没有时不铺筛选;表单里「空 = 24;0 = 关」等等式改成 placeholder + 一句说明 - 设置:浏览器服务、元数据识别、MCP 说明去掉组件名与实现细节;会话目录与 fake 脚本只在开发构建显示; API Key scope 前加中文名;命名模板变量去掉「MP 无」 - 待处理顶部计数卡改成一行筛选按钮 - 智能体悬浮按钮只在没有侧栏的窄屏出现,抽屉打开时不再显示「收起」胶囊 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
57ce40168d
commit
2c8c33c31c
15 files changed
+185
-237
No files matched your search
@@ -86,7 +86,7 @@ function McpServerBlock() {
|
||||
section="agent"
|
||||
anchor="mcp"
|
||||
title="MCP 服务端"
|
||||
description="外部智能体用 API Key 经 MCP 调用同一套能力。授权、审计、幂等与控制台一致,有副作用的工具没有持续授权或单次审批时被拒绝。"
|
||||
description="外部程序用 API Key 经 MCP 调用和智能体同一套能力,授权与审计规则相同。"
|
||||
>
|
||||
{status.isPending ? (
|
||||
<LoadingState rows={3} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AgentToolsBlock } from "./agent-tools.tsx";
|
||||
import { WEBSEARCH_CARD } from "./agent-websearch.tsx";
|
||||
import { PiUpstreamsBlock } from "./pi-upstreams.tsx";
|
||||
import type { FieldValue } from "./resource-section.tsx";
|
||||
import type { FieldSpec, FieldValue } from "./resource-section.tsx";
|
||||
import { num, str } from "./resource-section.tsx";
|
||||
import { type CardSpec, n, SettingsCard, SettingsGate } from "./settings-card.tsx";
|
||||
|
||||
@@ -140,53 +140,58 @@ const INVESTIGATE_CARD: CardSpec = {
|
||||
}),
|
||||
};
|
||||
|
||||
const DEV_ONLY_FIELDS = new Set(["agent.sessionDir", "agent.fakeScript"]);
|
||||
|
||||
const ADVANCED_CARD: CardSpec = {
|
||||
anchor: "advanced",
|
||||
title: "高级",
|
||||
fields: [
|
||||
{ name: "agent.goalPollSec", label: "目标轮询间隔(秒)", kind: "number", hint: "等下载、入库结束时的检查间隔" },
|
||||
{
|
||||
name: "agent.goalWaitHours",
|
||||
label: "目标最长等待(小时)",
|
||||
kind: "number",
|
||||
hint: "超时后按「仍在等待」汇报结束",
|
||||
},
|
||||
{
|
||||
name: "agent.optionsTimeoutSec",
|
||||
label: "方案选择等待(秒)",
|
||||
kind: "number",
|
||||
hint: "智能体给出方案后等你选择的最长时间",
|
||||
},
|
||||
{
|
||||
name: "agent.optionsTimeoutAction",
|
||||
label: "超时未选",
|
||||
kind: "select",
|
||||
options: [
|
||||
{ value: "recommended", label: "自动选推荐项" },
|
||||
{ value: "stop", label: "不选,智能体收尾" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "agent.approvalTimeoutSec",
|
||||
label: "会话内审批有效期(秒)",
|
||||
kind: "number",
|
||||
hint: "步骤处的审批卡过期未批准,按拒绝处理",
|
||||
},
|
||||
{
|
||||
name: "agent.sessionDir",
|
||||
label: "会话目录",
|
||||
kind: "text",
|
||||
wide: true,
|
||||
placeholder: "留空用 DATA_DIR/agent-sessions",
|
||||
hint: "绝对路径,api 与 worker 都要可读写;有运行中的会话时不要改",
|
||||
},
|
||||
{
|
||||
name: "agent.fakeScript",
|
||||
label: "fake 脚本(JSON)",
|
||||
kind: "textarea",
|
||||
hint: "只对 fake 模型服务生效,留空用内置演示脚本;格式见 docs/runbook/agent.md",
|
||||
},
|
||||
],
|
||||
// 会话目录与 fake 脚本是开发调试项,生产构建不显示(DEAI-2)
|
||||
fields: (
|
||||
[
|
||||
{ name: "agent.goalPollSec", label: "目标轮询间隔(秒)", kind: "number", hint: "等下载、入库结束时的检查间隔" },
|
||||
{
|
||||
name: "agent.goalWaitHours",
|
||||
label: "目标最长等待(小时)",
|
||||
kind: "number",
|
||||
hint: "超时后按「仍在等待」汇报结束",
|
||||
},
|
||||
{
|
||||
name: "agent.optionsTimeoutSec",
|
||||
label: "方案选择等待(秒)",
|
||||
kind: "number",
|
||||
hint: "智能体给出方案后等你选择的最长时间",
|
||||
},
|
||||
{
|
||||
name: "agent.optionsTimeoutAction",
|
||||
label: "超时未选",
|
||||
kind: "select",
|
||||
options: [
|
||||
{ value: "recommended", label: "自动选推荐项" },
|
||||
{ value: "stop", label: "不选,智能体收尾" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "agent.approvalTimeoutSec",
|
||||
label: "会话内审批有效期(秒)",
|
||||
kind: "number",
|
||||
hint: "步骤处的审批卡过期未批准,按拒绝处理",
|
||||
},
|
||||
{
|
||||
name: "agent.sessionDir",
|
||||
label: "会话目录",
|
||||
kind: "text",
|
||||
wide: true,
|
||||
placeholder: "留空用 DATA_DIR/agent-sessions",
|
||||
hint: "绝对路径,api 与 worker 都要可读写;有运行中的会话时不要改",
|
||||
},
|
||||
{
|
||||
name: "agent.fakeScript",
|
||||
label: "fake 脚本(JSON)",
|
||||
kind: "textarea",
|
||||
hint: "只对 fake 模型服务生效,留空用内置演示脚本;格式见 docs/runbook/agent.md",
|
||||
},
|
||||
] as FieldSpec[]
|
||||
).filter((f) => import.meta.env.DEV || !DEV_ONLY_FIELDS.has(f.name)),
|
||||
fromSettings: (s) => ({
|
||||
"agent.goalPollSec": n(s.agent.goalPollSec),
|
||||
"agent.goalWaitHours": n(s.agent.goalWaitHours),
|
||||
|
||||
@@ -25,10 +25,10 @@ import { SettingsBlock } from "./settings-block.tsx";
|
||||
// ─── API Key ───
|
||||
|
||||
const SCOPES: { value: ApiScope; label: string; hint: string }[] = [
|
||||
{ value: "read", label: "read", hint: "只读查询全部数据" },
|
||||
{ value: "organize.read", label: "organize.read", hint: "只读整理记录,供外部增量同步" },
|
||||
{ value: "organize.execute", label: "organize.execute", hint: "发起整理" },
|
||||
{ value: "admin", label: "admin", hint: "全部管理权限,含改设置" },
|
||||
{ value: "read", label: "只读 · read", hint: "只读查询全部数据" },
|
||||
{ value: "organize.read", label: "读整理记录 · organize.read", hint: "只读整理记录,供外部增量同步" },
|
||||
{ value: "organize.execute", label: "执行整理 · organize.execute", hint: "发起整理" },
|
||||
{ value: "admin", label: "管理员 · admin", hint: "全部管理权限,含改设置" },
|
||||
];
|
||||
|
||||
function CreatedKeyDialog({ plaintext, onClose }: { plaintext: string | null; onClose: () => void }) {
|
||||
@@ -200,7 +200,7 @@ export function ApiKeysSection() {
|
||||
checked={on}
|
||||
onChange={() => setScopes((xs) => (on ? xs.filter((x) => x !== s.value) : [...xs, s.value]))}
|
||||
/>
|
||||
<code className="text-caption">{s.label}</code>
|
||||
<span className="text-caption">{s.label}</span>
|
||||
<span className="text-meta text-muted-foreground">{s.hint}</span>
|
||||
</label>
|
||||
);
|
||||
@@ -250,7 +250,7 @@ function ScopeLegend() {
|
||||
{SCOPES.map((s) => (
|
||||
<div key={s.value} className="contents">
|
||||
<dt>
|
||||
<code className="rounded-tight bg-foreground/[0.06] px-1.5 py-0.5">{s.label}</code>
|
||||
<span className="rounded-tight bg-foreground/[0.06] px-1.5 py-0.5">{s.label}</span>
|
||||
</dt>
|
||||
<dd className="text-muted-foreground">{s.hint}</dd>
|
||||
</div>
|
||||
|
||||
@@ -97,7 +97,7 @@ export function BrowserProvidersBlock() {
|
||||
section="sites"
|
||||
anchor="browser"
|
||||
title="浏览器服务"
|
||||
description="原站视图和智能体打开站点网页用的 camofox-browser。部署自带的一台由环境变量登记(camofox-env)。"
|
||||
description="打开站点网页用(原站视图、智能体)。随部署提供的一台显示为内置。"
|
||||
plain
|
||||
>
|
||||
<ResourceSection<BrowserProviderView>
|
||||
|
||||
@@ -202,21 +202,20 @@ function ImageCacheStatus() {
|
||||
const IDENTITY_CARD: CardSpec = {
|
||||
anchor: "identity",
|
||||
title: "资源识别",
|
||||
description:
|
||||
"缺省只在资源命中订阅或本地作品别名、新作品收录规则前置条件通过、你手动识别或搜索时查 TMDB;其余进未识别资源,不进待处理。",
|
||||
description: "默认只在资源命中订阅、作品别名或新作品规则,或你手动识别和搜索时查 TMDB;其余放进未识别,不进待处理。",
|
||||
fields: [
|
||||
{
|
||||
name: "identity.eagerTmdbLookup",
|
||||
label: "每条新资源都查 TMDB",
|
||||
kind: "switch",
|
||||
hint: "旧行为。每条资源约 1–2 次搜索 + 命中时 1 次详情(识别缓存命中为 0);每小时 100 条的 RSS 约每天 2400–7200 次请求,站点独有的短剧 / 综艺多半查不到",
|
||||
hint: "每条新资源都查一次 TMDB。RSS 量大时每天可能上千次请求,站点独有的短剧和综艺多半查不到",
|
||||
wide: true,
|
||||
},
|
||||
{
|
||||
name: "identity.autoEnrich",
|
||||
label: "TMDB 查不到时自动补全元数据",
|
||||
kind: "switch",
|
||||
hint: "资源命中订阅或新作品收录规则、TMDB 却没有结果时,自动搜索网页出一份补全建议(每条资源一次,不建作品)。每次约 1–2 次网页搜索、最多读 3 个网页、1 次 模型服务调用",
|
||||
hint: "资源命中订阅或新作品规则、TMDB 却查不到时,搜索网页出一份补全建议(每条资源一次,不建作品)。每次最多读 3 个网页,调用一次模型服务",
|
||||
wide: true,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user