diff --git a/apps/web/app/components/sites/site-accounts-tab.tsx b/apps/web/app/components/sites/site-accounts-tab.tsx index 91394541..f1af41f0 100644 --- a/apps/web/app/components/sites/site-accounts-tab.tsx +++ b/apps/web/app/components/sites/site-accounts-tab.tsx @@ -118,7 +118,7 @@ function AccountBlock({ onConfirm={async () => { try { await del.mutateAsync(a.id); - toast.success(`已删除账号 ${a.label}`); + toast.success(`已删除账号「${a.label}」`); } catch (err) { toast.error(errorMessage(err, "删除失败")); throw err; @@ -260,7 +260,7 @@ function PasskeyForm({ site, label, has }: { site: SiteListItem; label: string; } }} > -

站点 Passkey(RSS 与下载链接用)

+

站点 Passkey

用于 RSS 和下载链接,不参与登录。{has ? "填写新值保存会替换。" : "还没有保存。"}

diff --git a/apps/web/app/components/sites/site-add-dialog.tsx b/apps/web/app/components/sites/site-add-dialog.tsx index 0ce87978..6048fe94 100644 --- a/apps/web/app/components/sites/site-add-dialog.tsx +++ b/apps/web/app/components/sites/site-add-dialog.tsx @@ -375,7 +375,7 @@ export function SiteAddDialog({ onClose, initialKind }: { onClose: () => void; i )}

- "未实测"的定义没有在真实站点上验证过,列表和登录可能失败。 + 标「未实测」的站点定义没有在真实站点上验证过,列表和登录可能失败。

) : step === 2 ? ( diff --git a/apps/web/app/components/sites/site-card.tsx b/apps/web/app/components/sites/site-card.tsx index 1d00e5f3..5a421bf7 100644 --- a/apps/web/app/components/sites/site-card.tsx +++ b/apps/web/app/components/sites/site-card.tsx @@ -183,7 +183,7 @@ function CheckButtons({ site, checks, compact }: Omit & { com size={compact ? "icon-sm" : "sm"} disabled={h || !site.enabled} aria-label="检测健康" - title={site.enabled ? "检测健康:首页连通 + 登录态,走站点限流" : "站点已停用"} + title={site.enabled ? "检测健康:首页能否打开、登录态是否有效,计入站点限流" : "站点已停用"} onClick={() => void checks.checkHealth(site)} > {h ? : } @@ -194,7 +194,7 @@ function CheckButtons({ site, checks, compact }: Omit & { com size={compact ? "icon-sm" : "sm"} disabled={l || !hasAccount} aria-label="刷新登录" - title={hasAccount ? "刷新登录:用凭证刷新登录状态并拉取用户数据" : "先填写凭证"} + title={hasAccount ? "刷新登录:用凭证重新登录并拉取用户数据" : "先填写凭证"} onClick={() => void checks.refreshLogin(site)} > {l ? : } @@ -289,7 +289,7 @@ function FeedSiteCard({ site, onDialog }: Omit) {
diff --git a/apps/web/app/components/sites/site-dialogs.tsx b/apps/web/app/components/sites/site-dialogs.tsx index b3d4b527..b02c3982 100644 --- a/apps/web/app/components/sites/site-dialogs.tsx +++ b/apps/web/app/components/sites/site-dialogs.tsx @@ -507,7 +507,7 @@ export function SiteEditSheet({ site, onClose }: { site: SiteListItem; onClose:
-

User-Agent 随凭证保存,在"更新凭证"里填写。

+

User-Agent 随凭证保存,在「更新凭证」里填写。

); @@ -544,9 +544,9 @@ export function DeleteSiteDialog({ }} >
    -
  • 站点、{site.accounts?.length ?? 0} 个账号和全部凭证删除
  • -
  • 已抓到的资源保留,标为"站点已关闭",不再产生新候选
  • -
  • 该站 RSS 停用;已有下载任务按原策略继续
  • +
  • 站点、{site.accounts?.length ?? 0} 个账号和全部凭证都会删除
  • +
  • 已抓到的资源保留,标为「站点已关闭」,不再进入收录评估
  • +
  • 这个站点的 RSS 停用;已有下载任务继续
  • 同一站点以后可以重新添加
diff --git a/apps/web/app/components/sites/site-failure-samples.tsx b/apps/web/app/components/sites/site-failure-samples.tsx index eec8592f..fb86a0ce 100644 --- a/apps/web/app/components/sites/site-failure-samples.tsx +++ b/apps/web/app/components/sites/site-failure-samples.tsx @@ -70,7 +70,7 @@ export function SiteFailureSamples({ siteId, items }: { siteId: string; items: S if (!items.length) return null; return (
-

最近的失败页面(已脱敏,留最近 5 份)

+

最近的失败页面(已脱敏,最多保留 5 份)

    {items.map((s) => ( diff --git a/apps/web/app/components/sites/site-feed-dialog.tsx b/apps/web/app/components/sites/site-feed-dialog.tsx index 79f2b7be..12d0dc6c 100644 --- a/apps/web/app/components/sites/site-feed-dialog.tsx +++ b/apps/web/app/components/sites/site-feed-dialog.tsx @@ -23,7 +23,7 @@ import { cn } from "~/lib/utils.ts"; const PURPOSES: { value: FeedPurpose; label: string; hint: string }[] = [ { value: "generic", label: "发现", hint: "全站新种,进入识别和收录评估" }, { value: "search", label: "追踪", hint: "按关键词、分类或收藏筛过的 RSS" }, - { value: "promotion", label: "促销", hint: "只含免费 / 促销种子的 RSS" }, + { value: "promotion", label: "促销", hint: "只含免费 / 促销资源的 RSS" }, ]; /** 首抓最多等 90 秒(站点限流排队);超时后提示去列表看 */ @@ -106,7 +106,7 @@ export function SiteFeedDialog({ - 添加 {site.name} RSS + 新建 RSS · {site.name} 地址加密保存,页面上只显示去掉 passkey 的地址。 @@ -219,7 +219,7 @@ export function SiteFeedDialog({

    - {account ? `账号 ${account.label}` : "该站没有账号,按地址里的 passkey 抓取"} · 解析器按站点定义 · 每 30 + {account ? `账号 ${account.label}` : "这个站点没有账号,按地址里的 passkey 抓取"} · 解析器按站点定义 · 每 30 分钟抓一次,可在 RSS 详情里改

    diff --git a/apps/web/app/components/sites/site-fields.test.ts b/apps/web/app/components/sites/site-fields.test.ts index 1cd408b1..6db87ba9 100644 --- a/apps/web/app/components/sites/site-fields.test.ts +++ b/apps/web/app/components/sites/site-fields.test.ts @@ -43,7 +43,7 @@ describe("cloudflareLine / cloudflareTechItems(CF-2)", () => { const until = new Date("2026-09-30T17:30:00+08:00"); const line = cloudflareLine(cfg({ lastChallengeAt: at, browserUntil: until.toISOString() }), now); const hm = `${String(until.getHours()).padStart(2, "0")}:${String(until.getMinutes()).padStart(2, "0")}`; - expect(line?.text).toBe(`Cloudflare:浏览器代理中,至 ${hm}`); + expect(line?.text).toBe(`Cloudflare:浏览器代抓中,到 ${hm}`); expect(cloudflareLine(cfg({ lastChallengeAt: at, lastSolvedBy: "vision" }), now)?.text).toBe( "Cloudflare:自动通过", ); @@ -63,8 +63,8 @@ describe("cloudflareLine / cloudflareTechItems(CF-2)", () => { }), ); expect(items.map((i) => i.label)).toEqual([ - "最近遇到挑战", - "挑战规则", + "最近遇到验证", + "验证规则", "处理结果", "最近通过方式", "cf_clearance 复用", diff --git a/apps/web/app/components/sites/site-fields.ts b/apps/web/app/components/sites/site-fields.ts index 394ee90d..1bc10232 100644 --- a/apps/web/app/components/sites/site-fields.ts +++ b/apps/web/app/components/sites/site-fields.ts @@ -158,7 +158,7 @@ export function healthMessage(h: SiteLastHealth | null): string | null { const HEALTH_REASON_TEXT: Record = { logged_in: "首页有登录标志", - user_data: "首页没找到登录标志,按用户数据解析成功判为已登录", + user_data: "首页没有登录标志,但用户数据解析成功,按已登录处理", login_page: "返回登录页", permission_page: "返回权限提示页", challenge: "疑似人机验证", @@ -198,7 +198,7 @@ export function cloudflareLine( if (st.browserUntil && Date.parse(st.browserUntil) > now.getTime()) { const t = new Date(st.browserUntil); const hm = `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`; - return { text: `Cloudflare:浏览器代理中,至 ${hm}`, tone: "neutral", takeover: false }; + return { text: `Cloudflare:浏览器代抓中,到 ${hm}`, tone: "neutral", takeover: false }; } if (st.lastSolvedBy) return { text: "Cloudflare:自动通过", tone: "success", takeover: false }; if (st.lastError) return { text: "Cloudflare:没能通过", tone: "warning", takeover: false }; @@ -206,8 +206,8 @@ export function cloudflareLine( } const CF_SOLVED_BY: Record = { - auto: "等它自动放行", - vision: "视觉子流程点了复选框", + auto: "自动放行", + vision: "自动点了验证复选框", human: "你在原站视图里通过", }; const CF_RESULT: Record = { @@ -227,8 +227,8 @@ export function cloudflareTechItems(config: unknown): { label: string; value: st if (!st?.lastChallengeAt) return []; const t = (v: string | null) => (v ? new Date(v).toLocaleString("zh-CN", { hour12: false }) : ""); return [ - { label: "最近遇到挑战", value: t(st.lastChallengeAt) }, - { label: "挑战规则", value: st.lastRule ?? "", mono: true }, + { label: "最近遇到验证", value: t(st.lastChallengeAt) }, + { label: "验证规则", value: st.lastRule ?? "", mono: true }, { label: "处理结果", value: st.lastResult ? `${CF_RESULT[st.lastResult] ?? st.lastResult}(${st.lastResult})` : "" }, { label: "最近通过方式", value: st.lastSolvedBy ? (CF_SOLVED_BY[st.lastSolvedBy] ?? st.lastSolvedBy) : "" }, { label: "最近通过时间", value: t(st.lastSolvedAt) }, @@ -236,7 +236,7 @@ export function cloudflareTechItems(config: unknown): { label: string; value: st label: "cf_clearance 复用", value: st.cfReuse === "ok" ? "有效(ok)" : st.cfReuse === "fails" ? "无效(fails)" : "", }, - { label: "浏览器代理至", value: t(st.browserUntil) }, + { label: "浏览器代抓到", value: t(st.browserUntil) }, { label: "最近尝试", value: t(st.lastAttemptAt) }, { label: "最近错误", value: st.lastError ?? "" }, ].filter((it) => it.value); @@ -317,7 +317,7 @@ export function loginFailureText( return { text: "登录失败:站点要求二次验证。填写 TOTP 密钥后重试,或改用 Cookie", suggestCookie: true }; case "challenge": return { - text: "站点要求人机验证(Cloudflare)。会用浏览器自动过,过不去时在铃铛里提醒你", + text: "站点要求人机验证(Cloudflare)。会先用浏览器自动通过,失败时在铃铛里提醒", suggestCookie: false, }; case "bad_credentials": @@ -333,11 +333,11 @@ export function loginFailureText( suggestCookie: false, }; case "network": - return { text: `连不上站点${message ? `:${message}` : ""}`, suggestCookie: false }; + return { text: `连不上站点${message ? `:${message}` : ""}`, suggestCookie: false }; case "unsupported": - return { text: message ?? "这个站点不支持该凭证类型的自动登录", suggestCookie: false }; + return { text: message ?? "这个站点不支持用这种凭证自动登录", suggestCookie: false }; default: - return { text: message ?? "登录失败,原因未知", suggestCookie: false }; + return { text: message ?? "登录失败", suggestCookie: false }; } } @@ -365,7 +365,7 @@ export const REASON_SHORT: Record = { two_factor: "需二次验证", bad_credentials: "密码错误", account_blocked: "账号封禁", - challenge: "Cloudflare 挑战", + challenge: "Cloudflare 验证", auth_expired: "凭证失效", network: "网络失败", unsupported: "不支持", diff --git a/apps/web/app/components/subtitles/subtitle-dialog.tsx b/apps/web/app/components/subtitles/subtitle-dialog.tsx index 344ae4dd..709fb254 100644 --- a/apps/web/app/components/subtitles/subtitle-dialog.tsx +++ b/apps/web/app/components/subtitles/subtitle-dialog.tsx @@ -470,7 +470,7 @@ function OnlinePanel({ ) : null} {data && !data.noSites && !data.results.length ? (

    - 没搜到(用了:{data.keywords.join("、") || "无"})。可以换个关键词,或去掉季集限制再试。 + 没有找到字幕(搜索词:{data.keywords.join("、") || "无"})。换个关键词,或去掉季集限制再试。

    ) : null} {data?.results.length ? (