Files
UHD_Media_Tool/apps/web/app/components/rules/labels.ts
T
rootandClaude Opus 5.5 52402864d6 style(copy): punctuation rules and site-wide fix with a CI check (QA U11)
- glossary: 10 punctuation rules (full-width in Chinese, CJK/Latin spacing,
  full-width parens around Chinese, single ellipsis, 「」 quotes, period rules)
- scripts/check-copy-punctuation.mjs: checks string literals, templates and JSX
  text (not comments, types, keys, match/compare strings); --fix, --strict,
  --by-file; wired into deno task ci as check:copy in warn mode
- --fix applied to web, server and contracts; files other lanes were editing
  (subscriptions, sites, browser, agent, auth/account, inventory) left for them
- tests updated for the changed messages

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:09:29 +08:00

64 lines
2.7 KiB
TypeScript

import type { RuleGroup, RuleGroupKind, RuleGroupScope, RuleGroupSource } from "@umt/contracts";
import { MEDIA_KIND } from "~/components/library/labels.ts";
import { exprToString } from "./expr.ts";
// 规则页文案:类型 / 来源 / 作用范围 / 默认链 / 抑制原因
export const RULE_KIND: Record<RuleGroupKind, { label: string; hint: string }> = {
acquisition: { label: "订阅", hint: "订阅与版本目标挑资源时用" },
upgrade: { label: "洗版", hint: "版本目标开了升级时额外叠加" },
search: { label: "搜索", hint: "手动搜索与 Agent 搜索资源时用" },
};
export const SUPPRESS_NOTE = "停用或删除会留下抑制记录,Agent 不会自动加回;重新启用或手动新建同样的规则后解除。";
export const RULE_SOURCE: Record<RuleGroupSource, string> = {
manual: "手动",
chat: "对话",
agent: "Agent",
};
export const DEFAULT_CHAIN_LABEL: Record<RuleGroupKind, string> = {
acquisition: "订阅默认",
upgrade: "洗版默认",
search: "搜索默认",
};
export const SUPPRESS_REASON: Record<string, string> = {
deleted: "删除",
disabled: "停用",
"status:disabled": "停用",
"status:deleted": "删除",
edited: "修改语义",
};
export const suppressReason = (r: string | null) => (r ? (SUPPRESS_REASON[r] ?? r) : "未注明");
/** 作用范围摘要:空 = 全部;旧数据里的 mediaKinds 同 mediaTypes */
export function scopeText(scope: RuleGroupScope): string {
const s = scope as RuleGroupScope & { mediaKinds?: string[] };
const parts: string[] = [];
const kinds = s.mediaTypes ?? s.mediaKinds;
if (kinds?.length) parts.push(kinds.map((k) => MEDIA_KIND[k as keyof typeof MEDIA_KIND] ?? k).join("、"));
if (s.entityIds?.length) parts.push(`${s.entityIds.length} 个作品`);
if (s.siteIds?.length) parts.push(`${s.siteIds.length} 个站点`);
if (s.subscriptionId) parts.push("订阅私有");
return parts.length ? parts.join(" · ") : "全部";
}
/** 单条规则(偏好标签形态):不在默认链、不是订阅私有,层 + 硬排除合计一条;旧偏好标签迁来的都算 */
export function isTagLike(g: RuleGroup): boolean {
if (g.defaultOrder !== null || g.scope.subscriptionId) return false;
if (g.legacyKind) return true;
return g.layers.length + g.hardExcludes.length === 1;
}
/** 标签上的一句规则摘要 */
export function ruleSummary(g: RuleGroup): string {
const parts: string[] = [];
if (g.layers.length)
parts.push(`${g.ladderRequired ? "要求" : "偏好"} ${g.layers.map((l) => exprToString(l.expr)).join(" > ")}`);
for (const h of g.hardExcludes) parts.push(`排除 ${exprToString(h)}`);
if (parts.length) return parts.join(";");
return g.legacyKind ? "旧偏好标签,没有可评估的条件" : "没有条件";
}