Merge branch 'deai2'
Co-Authored-By: Claude Fable 5.1 <[email protected]> # Conflicts: # apps/server/src/modules/acquisition-organize/services/organize.ts # apps/web/app/routes/console/sites.$siteId.tsx
This commit is contained in:
commit
12bc4664b6
247 files changed
+2658
-2148
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { type SearchAction, type SearchWork, tmdbImageUrl } from "@umt/contracts";
|
||||
import { ArrowRight, CornerDownLeft, Film, Globe, LoaderCircle, type LucideIcon, Search } from "lucide-react";
|
||||
import { CornerDownLeft, Film, Globe, LoaderCircle, type LucideIcon, Search } from "lucide-react";
|
||||
import { type ReactNode, useEffect, useId, useMemo, useRef, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import { useSearch } from "~/api/search.ts";
|
||||
@@ -111,7 +111,6 @@ function PaletteBody({ initial }: { initial: string }) {
|
||||
查看「<span className="font-medium">{term}</span>」的全部结果
|
||||
</span>
|
||||
),
|
||||
meta: "作品卡上可以选站点搜资源",
|
||||
hint: "打开",
|
||||
run: () => go(searchPagePath(term)),
|
||||
});
|
||||
@@ -254,10 +253,6 @@ function PaletteBody({ initial }: { initial: string }) {
|
||||
<div className="hidden items-center gap-4 border-t border-border/70 px-4 py-2 text-meta text-muted-foreground sm:flex">
|
||||
<span>↑↓ 选择</span>
|
||||
<span>↵ 打开</span>
|
||||
<span className="ml-auto inline-flex items-center gap-1">
|
||||
<ArrowRight className="h-3 w-3" />
|
||||
搜资源在作品详情页
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -412,7 +412,7 @@ function ReleaseRow({ r, onDownload }: { r: SearchRelease; onDownload: () => voi
|
||||
) : null}
|
||||
<Button variant="ghost" size="sm" onClick={() => delegateToAgent(r)}>
|
||||
<Bot />
|
||||
委托 Agent
|
||||
委托智能体
|
||||
</Button>
|
||||
<Button size="sm" onClick={onDownload}>
|
||||
<Download />
|
||||
|
||||
@@ -23,7 +23,7 @@ import { formatBytes } from "~/lib/utils.ts";
|
||||
// 与站点工作台同一套下载说明;请求走 POST /search/releases/{siteId}/{siteReleaseId}/plan(同 /acquisition-plans 流程)
|
||||
|
||||
const STEPS = [
|
||||
"生成下载计划,预留版本目标和预算;每个版本目标同时只有一个在途计划",
|
||||
"生成下载计划,预留收录版本和预算;每个收录版本同时只有一个在途计划",
|
||||
"已有相同资源或相同 hash 的任务时直接接管,不重复提交",
|
||||
"缓存卷超过硬阈值或读不到磁盘状态时无法提交",
|
||||
"提交前复核免费、做种等易变字段",
|
||||
@@ -109,11 +109,11 @@ export function SearchDownloadDialog({
|
||||
{!entityId ? (
|
||||
<p className="text-meta text-muted-foreground">资源未关联本地作品。先在「身份与元数据」指定。</p>
|
||||
) : slots.isPending ? (
|
||||
<p className="text-meta text-muted-foreground">正在读取版本目标…</p>
|
||||
<p className="text-meta text-muted-foreground">正在读取收录版本…</p>
|
||||
) : slotList.length ? (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<FilterSelect
|
||||
label="版本目标"
|
||||
label="收录版本"
|
||||
value={slotId}
|
||||
onChange={setSlotId}
|
||||
allLabel="自动匹配"
|
||||
@@ -124,7 +124,7 @@ export function SearchDownloadDialog({
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-meta text-muted-foreground">这个作品没有版本目标。先在订阅里新建。</p>
|
||||
<p className="text-meta text-muted-foreground">这个作品没有收录版本。先在订阅里新建。</p>
|
||||
)}
|
||||
{release.entityMatch === "alias" ? (
|
||||
<p className="text-meta text-warning">作品关联来自标题别名,尚未确认。</p>
|
||||
@@ -159,7 +159,7 @@ export function SearchDownloadDialog({
|
||||
}}
|
||||
>
|
||||
<Bot />
|
||||
委托 Agent
|
||||
委托智能体
|
||||
</Button>
|
||||
<Button onClick={go} disabled={plan.isPending || !!done || !entityId}>
|
||||
<Download />
|
||||
|
||||
@@ -15,7 +15,7 @@ export function slotSummary(h: LocalMediaHit): string {
|
||||
if (h.versionCount) parts.push(`${h.versionCount} 个版本`);
|
||||
if (h.downloadingCount) parts.push(`${h.downloadingCount} 个下载中`);
|
||||
const gaps = c.empty + c.attention + c.upgrade_pending;
|
||||
if (gaps) parts.push(`${gaps} 个版本目标未满足`);
|
||||
if (gaps) parts.push(`${gaps} 个收录版本未满足`);
|
||||
return parts.join(" · ") || "未订阅";
|
||||
}
|
||||
|
||||
|
||||
@@ -82,14 +82,14 @@ describe("站点选择", () => {
|
||||
});
|
||||
|
||||
describe("库内状态文案", () => {
|
||||
it("未收录 / 已建档 / 已收录 / 正在下载;版本目标满足与缺失", () => {
|
||||
expect(inventoryBadge(inv({})).label).toBe("未收录");
|
||||
expect(inventoryBadge(inv({ state: "tracked" })).label).toBe("已建档 · 未入库");
|
||||
expect(inventoryBadge(inv({ state: "owned", versionCount: 2 })).label).toBe("已收录 · 2 个版本");
|
||||
it("未收录 / 已建档 / 已收录 / 正在下载;收录版本满足与缺失", () => {
|
||||
expect(inventoryBadge(inv({})).label).toBe("不在媒体库");
|
||||
expect(inventoryBadge(inv({ state: "tracked" })).label).toBe("在媒体库 · 未下载");
|
||||
expect(inventoryBadge(inv({ state: "owned", versionCount: 2 })).label).toBe("已入库 · 2 个版本");
|
||||
expect(inventoryBadge(inv({ state: "downloading", downloadingCount: 1 })).label).toBe("正在下载 1 个");
|
||||
expect(
|
||||
slotLine(inv({ state: "owned", slotTotal: 2, slotSatisfied: 1, missing: [{ slotId: ID, name: "2160p" }] })),
|
||||
).toBe("版本目标满足 1/2 · 缺「2160p」");
|
||||
).toBe("收录版本满足 1/2 · 缺「2160p」");
|
||||
expect(slotLine(inv({}))).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -33,20 +33,20 @@ export function releaseSearchPath(w: { title: string; ref: string }, siteIds: st
|
||||
export function inventoryBadge(inv: WorkInventory): { label: string; tone: StatusTone } {
|
||||
switch (inv.state) {
|
||||
case "not_collected":
|
||||
return { label: "未收录", tone: "neutral" };
|
||||
return { label: "不在媒体库", tone: "neutral" };
|
||||
case "downloading":
|
||||
return { label: `正在下载 ${inv.downloadingCount} 个`, tone: "warning" };
|
||||
case "owned":
|
||||
return { label: `已收录 · ${inv.versionCount} 个版本`, tone: "success" };
|
||||
return { label: `已入库 · ${inv.versionCount} 个版本`, tone: "success" };
|
||||
default:
|
||||
return { label: "已建档 · 未入库", tone: "neutral" };
|
||||
return { label: "在媒体库 · 未下载", tone: "neutral" };
|
||||
}
|
||||
}
|
||||
|
||||
/** 版本目标满足情况一行:满足 a/b · 缺「x」「y」 */
|
||||
/** 收录版本满足情况一行:满足 a/b · 缺「x」「y」 */
|
||||
export function slotLine(inv: WorkInventory): string | null {
|
||||
if (inv.state === "not_collected" || inv.slotTotal === 0) return null;
|
||||
const parts = [`版本目标满足 ${inv.slotSatisfied}/${inv.slotTotal}`];
|
||||
const parts = [`收录版本满足 ${inv.slotSatisfied}/${inv.slotTotal}`];
|
||||
if (inv.missing.length) parts.push(`缺${inv.missing.map((m) => `「${m.name}」`).join("")}`);
|
||||
return parts.join(" · ");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user