docs(plan): v0.2 adds Pi subagents and scheduled-jobs board
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
b839ed4056
commit
16ab2a6c84
97 files changed
+592
-648
No files matched your search
@@ -37,7 +37,7 @@ import { Tone } from "./parts.tsx";
|
||||
// ── 改外部映射 ──
|
||||
|
||||
const IdentityForm = EntityIdentitySet.extend({
|
||||
externalId: z.string().trim().regex(/^\d+$/, "TMDB id 是纯数字"),
|
||||
externalId: z.string().trim().regex(/^\d+$/, "TMDB ID 只能是数字"),
|
||||
});
|
||||
|
||||
export function IdentityDialog({
|
||||
@@ -90,7 +90,7 @@ export function IdentityDialog({
|
||||
toast.success(`已改为 TMDB ${r.data.entityType}:${r.data.externalId}${r.data.lock ? ",并加人工锁" : ""}`);
|
||||
onOpenChange(false);
|
||||
},
|
||||
onError: (err) => toast.error(errorMessage(err, "改映射失败")),
|
||||
onError: (err) => toast.error(errorMessage(err, "修改失败")),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -100,15 +100,15 @@ export function IdentityDialog({
|
||||
<Dialog open={open} onOpenChange={(o) => !set.isPending && onOpenChange(o)}>
|
||||
<DialogContent className="max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>改外部映射</DialogTitle>
|
||||
<DialogTitle>修改外部身份</DialogTitle>
|
||||
<DialogDescription>
|
||||
旧的同类型 TMDB 映射会退役并留下修订记录;新映射直接确认。加人工锁后自动匹配与刷新不再改动它。
|
||||
同类型的旧 TMDB 身份会退役,保留修订记录。加人工锁后,自动匹配和刷新不再改动。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form onSubmit={submit} className="grid gap-3">
|
||||
{usable.length ? (
|
||||
<div className="grid gap-1.5">
|
||||
<p className="text-caption font-medium text-foreground">从候选中选</p>
|
||||
<p className="text-caption font-medium text-foreground">候选</p>
|
||||
<ul className="grid gap-1.5">
|
||||
{usable.map((c) => (
|
||||
<li key={c.id}>
|
||||
@@ -164,7 +164,7 @@ export function IdentityDialog({
|
||||
<div className="flex items-center justify-between gap-3 rounded-lg border border-border px-3 py-2">
|
||||
<div className="min-w-0">
|
||||
<p className="text-caption font-medium text-foreground">加人工锁</p>
|
||||
<p className="text-meta text-muted-foreground">自动匹配不得覆盖人工锁定的关系</p>
|
||||
<p className="text-meta text-muted-foreground">自动匹配不会覆盖</p>
|
||||
</div>
|
||||
<Switch checked={lock} onCheckedChange={setLock} aria-label="加人工锁" />
|
||||
</div>
|
||||
@@ -174,7 +174,7 @@ export function IdentityDialog({
|
||||
</Button>
|
||||
<Button type="submit" disabled={set.isPending}>
|
||||
{set.isPending ? <LoaderCircle className="animate-spin" /> : null}
|
||||
保存映射
|
||||
保存
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
@@ -186,7 +186,7 @@ export function IdentityDialog({
|
||||
// ── 字段覆盖并锁定 ──
|
||||
|
||||
const FieldForm = z.object({
|
||||
value: z.string().trim().min(1, "请填写值"),
|
||||
value: z.string().trim().min(1, "填写值"),
|
||||
reason: z.string().max(2000).optional(),
|
||||
});
|
||||
|
||||
@@ -227,7 +227,7 @@ export function FieldLockDialog({
|
||||
if (field === "year") {
|
||||
const n = Number(r.data.value);
|
||||
if (!Number.isInteger(n) || n < 1870 || n > 2200) {
|
||||
setErrors({ value: "年份需为 1870–2200 的整数" });
|
||||
setErrors({ value: "年份须是 1870–2200 的整数" });
|
||||
return;
|
||||
}
|
||||
v = n;
|
||||
@@ -250,7 +250,7 @@ export function FieldLockDialog({
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>锁定字段:{field ? (ENTITY_FIELD_LABEL[field] ?? field) : ""}</DialogTitle>
|
||||
<DialogDescription>保存为人工值并加锁,之后刷新元数据不会改写这个字段;不影响已绑定的路径。</DialogDescription>
|
||||
<DialogDescription>锁定后刷新元数据不改这个字段。已绑定的路径不变。</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form onSubmit={submit} className="grid gap-3">
|
||||
<FormField label="值" htmlFor={`${id}-v`} error={errors.value} required>
|
||||
@@ -381,13 +381,13 @@ export function MergeDialog({
|
||||
<Dialog open={open && !confirm} onOpenChange={(o) => !o && onOpenChange(false)}>
|
||||
<DialogContent className="max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>合并到另一作品</DialogTitle>
|
||||
<DialogTitle>合并作品</DialogTitle>
|
||||
<DialogDescription>
|
||||
「{entity.title}」会标为已合并,旧 ID 跳转到目标作品;订阅、资产与历史引用一并转到目标。错误合并可以再修订。
|
||||
「{entity.title}」会标为已合并,旧 ID 跳转到目标作品,订阅、资产和历史记录一并转过去。合并错了可以再修订。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<EntityPicker value={target} onChange={setTarget} excludeId={entity.id} />
|
||||
<FormField label="原因" htmlFor="merge-reason" hint="写入审计与跳转记录">
|
||||
<FormField label="原因" htmlFor="merge-reason" hint="写入审计日志">
|
||||
<Input
|
||||
id="merge-reason"
|
||||
value={reason}
|
||||
@@ -411,10 +411,10 @@ export function MergeDialog({
|
||||
setConfirm(o);
|
||||
if (!o && !merge.isSuccess) return;
|
||||
}}
|
||||
title="确认合并?"
|
||||
title="合并作品?"
|
||||
description={
|
||||
target
|
||||
? `把「${entity.title}」合并到「${target.title}${target.year ? ` (${target.year})` : ""}」。合并后本页将跳转到目标作品。`
|
||||
? `把「${entity.title}」合并到「${target.title}${target.year ? ` (${target.year})` : ""}」,完成后跳转到目标作品。`
|
||||
: ""
|
||||
}
|
||||
confirmLabel="合并"
|
||||
|
||||
Reference in new issue
Block a user