refactor: 拆分大文件(contracts 端点、整理服务、浏览器纯函数、整理弹窗来源)
- contracts/src/api.ts 2733 行 → api/*.ts 13 个领域文件 + shared.ts;api.ts 按原顺序合并 Api。 新旧对比:354 个端点内容与顺序一致,分组键与对外导出一致 - acquisition-organize/services/organize.ts 2645 行 → organize-types / -plan / -exec / -finalize / -records, organize.ts 保留为汇总入口,外部引用不变 - browser/service.ts 类外的纯函数(视图映射、原因文案、坐标换算、图片尺寸、出口代理)移到 session-view.ts, service.ts 照旧转出 - organize-wizard:来源解析 useResolvedSource 移到 source.ts,FormSelect 移到 form-select.tsx 只挪位置不改逻辑;typecheck、lint、test:all、web build、server 编译与编译产物自检通过。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c9e8120fc6
commit
8bec4bad5d
26 files changed
+5906
-5696
No files matched your search
@@ -0,0 +1,210 @@
|
||||
import { z } from "zod";
|
||||
import { MetadataEnrichOutput } from "../capabilities-io.ts";
|
||||
import { cursorPage, IdParam } from "../common.ts";
|
||||
import * as execution from "../execution.ts";
|
||||
import * as identity from "../identity.ts";
|
||||
import * as libraryVersions from "../library-versions.ts";
|
||||
import * as organization from "../organization.ts";
|
||||
import * as scrape from "../scrape.ts";
|
||||
import * as search from "../search.ts";
|
||||
import { ep, ReleaseIdentityResult, TaskAccepted } from "./shared.ts";
|
||||
|
||||
export const libraryApi = {
|
||||
// ── 待识别池 ──
|
||||
identityPool: {
|
||||
list: ep({
|
||||
method: "get",
|
||||
path: "/identity-pool",
|
||||
scope: "read",
|
||||
summary: "未识别资源(可按原始标题检索;候选不建正式作品)",
|
||||
query: identity.IdentityPoolQuery,
|
||||
response: cursorPage(identity.IdentityPoolItem),
|
||||
}),
|
||||
assign: ep({
|
||||
method: "post",
|
||||
path: "/identity-pool/{id}/assign",
|
||||
scope: "organize.execute",
|
||||
summary: "为未识别资源手动指定候选 / 本地作品 / 外部身份",
|
||||
params: IdParam,
|
||||
body: identity.ReleaseIdentityAssign,
|
||||
response: ReleaseIdentityResult,
|
||||
}),
|
||||
dismiss: ep({
|
||||
method: "post",
|
||||
path: "/identity-pool/{id}/dismiss",
|
||||
scope: "organize.execute",
|
||||
summary: "忽略未识别资源(不再自动复查)",
|
||||
params: IdParam,
|
||||
body: z.object({ note: z.string().max(2000).optional() }),
|
||||
response: identity.IdentityCandidate,
|
||||
}),
|
||||
retry: ep({
|
||||
method: "post",
|
||||
path: "/identity-pool/{id}/retry",
|
||||
scope: "organize.execute",
|
||||
summary: "立即重新识别",
|
||||
params: IdParam,
|
||||
response: TaskAccepted,
|
||||
}),
|
||||
// META-1 元数据补全:先看建议(metadata.enrich,不改作品),再在控制台应用
|
||||
enrich: ep({
|
||||
method: "post",
|
||||
path: "/identity-pool/{id}/enrich",
|
||||
scope: "organize.execute",
|
||||
summary: "元数据补全建议(网页搜索 + 白名单网页 + 模型抽取;不改作品;同一标题 7 天内返回上次结果)",
|
||||
params: IdParam,
|
||||
body: identity.EnrichRequest,
|
||||
response: MetadataEnrichOutput,
|
||||
}),
|
||||
enrichApply: ep({
|
||||
method: "post",
|
||||
path: "/identity-pool/{id}/enrich/apply",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "应用元数据补全建议:建本地临时作品(或并入同名作品)并关联未识别资源(只接受控制台管理员会话)",
|
||||
params: IdParam,
|
||||
body: identity.EnrichApplyInput,
|
||||
response: identity.EnrichApplyResult,
|
||||
}),
|
||||
// META-2 补全命中率(按来源类别)
|
||||
enrichStats: ep({
|
||||
method: "get",
|
||||
path: "/identity/enrich-stats",
|
||||
scope: "read",
|
||||
summary: "元数据补全命中率(最近 N 天,按来源类别:百科、平台、豆瓣摘要、其它网站摘要)",
|
||||
query: identity.EnrichStatsQuery,
|
||||
response: identity.EnrichStats,
|
||||
}),
|
||||
},
|
||||
|
||||
// ── 媒体库 / 库存 / 首页 ──
|
||||
library: {
|
||||
list: ep({
|
||||
method: "get",
|
||||
path: "/library",
|
||||
scope: "read",
|
||||
summary: "媒体库列表(已登记资产或正在追踪的作品)",
|
||||
query: organization.LibraryListQuery,
|
||||
response: cursorPage(organization.LibraryItem),
|
||||
}),
|
||||
get: ep({
|
||||
method: "get",
|
||||
path: "/library/{id}",
|
||||
scope: "read",
|
||||
summary: "作品详情:实际路径、身份映射、元数据来源、各收录版本、候选拒绝理由、下载历史与校验结果",
|
||||
params: IdParam,
|
||||
response: organization.LibraryDetail,
|
||||
}),
|
||||
versions: ep({
|
||||
method: "get",
|
||||
path: "/library/{id}/versions",
|
||||
scope: "read",
|
||||
summary: "作品的入库版本:每季每集的本地文件版本与规格、季 / 作品汇总、与版本目标的比对",
|
||||
params: IdParam,
|
||||
query: libraryVersions.LibraryVersionsQuery,
|
||||
response: libraryVersions.LibraryVersions,
|
||||
}),
|
||||
scrape: ep({
|
||||
method: "post",
|
||||
path: "/library/{id}/scrape",
|
||||
scope: "organize.execute",
|
||||
summary: "刮削:把作品的 NFO 与图片写进媒体库目录(后台任务 scrapeMedia;覆盖方式缺省按设置)",
|
||||
params: IdParam,
|
||||
body: scrape.LibraryScrapeRequest,
|
||||
response: scrape.LibraryScrapeResult,
|
||||
}),
|
||||
reconcile: ep({
|
||||
method: "post",
|
||||
path: "/library/reconcile",
|
||||
scope: "admin",
|
||||
summary: "立即做一轮资产对账(库根哨兵 + 增量 stat;不删记录、不补下载)",
|
||||
body: z.object({ libraryRootId: z.uuid().optional() }),
|
||||
response: z.object({ runId: z.uuid(), stats: z.record(z.string(), z.unknown()) }),
|
||||
}),
|
||||
},
|
||||
inventory: {
|
||||
overlay: ep({
|
||||
method: "get",
|
||||
path: "/inventory",
|
||||
scope: "read",
|
||||
summary: "库存叠加(站点工作台):按作品返回已有版本 / 收录版本缺口 / 下载中",
|
||||
query: organization.InventoryQuery,
|
||||
response: organization.InventoryResponse,
|
||||
}),
|
||||
mediaServers: ep({
|
||||
method: "get",
|
||||
path: "/inventory/media-servers",
|
||||
scope: "read",
|
||||
summary: "Emby 兼容库存查询(多实例;接口失败/截断 = unknown,不等于缺失)",
|
||||
query: organization.MediaServerInventoryQuery,
|
||||
response: organization.MediaServerInventory,
|
||||
}),
|
||||
},
|
||||
dashboard: {
|
||||
get: ep({
|
||||
method: "get",
|
||||
path: "/dashboard",
|
||||
scope: "read",
|
||||
summary: "首页聚合:自动化概览/当前工作/需要我处理/缓存与保留/来源健康/最近产出",
|
||||
response: organization.Dashboard,
|
||||
}),
|
||||
},
|
||||
downloadCache: {
|
||||
cleanup: ep({
|
||||
method: "post",
|
||||
path: "/download-cache/cleanup",
|
||||
scope: "admin",
|
||||
summary: "立即按阈值清理下载缓存(只清已验证入库且满足保留/H&R 的纳管任务)",
|
||||
body: z.object({ downloaderInstanceId: z.uuid().optional() }),
|
||||
response: z.object({ report: z.record(z.string(), z.unknown()) }),
|
||||
}),
|
||||
},
|
||||
|
||||
// ── 全局搜索(W9-G):顶栏搜索 / 命令面板 / 资源结果页 ──
|
||||
search: {
|
||||
all: ep({
|
||||
method: "get",
|
||||
path: "/search",
|
||||
scope: "read",
|
||||
summary:
|
||||
"全局搜索聚合:本地作品 / TMDB 候选 / 跨站资源(15s 超时、并发合并、30s 缓存、库存叠加)/ 页面与操作;每组带 tookMs",
|
||||
query: search.SearchQuery,
|
||||
response: search.SearchResponse,
|
||||
}),
|
||||
releases: ep({
|
||||
method: "get",
|
||||
path: "/search/releases",
|
||||
scope: "read",
|
||||
summary: "跨站资源结果页:站点/分辨率/来源/大小/免费/H&R 筛选、排序、游标;与 /search 共用缓存",
|
||||
query: search.ReleaseSearchQuery,
|
||||
response: search.ReleaseSearchPage,
|
||||
}),
|
||||
plan: ep({
|
||||
method: "post",
|
||||
path: "/search/releases/{siteId}/{siteReleaseId}/plan",
|
||||
scope: "organize.execute",
|
||||
summary: "从搜索结果直接下载:定位资源后走 POST /acquisition-plans 同一流程",
|
||||
params: search.SearchReleaseParams,
|
||||
body: search.SearchReleasePlanRequest,
|
||||
response: execution.ManualAcquisitionResult,
|
||||
}),
|
||||
tmdbDetail: ep({
|
||||
method: "get",
|
||||
path: "/media/tmdb/{type}/{id}",
|
||||
scope: "read",
|
||||
summary:
|
||||
"仅 TMDB 作品的详情:TMDB 信息与季列表、本地库存对比、是否已建档、搜资源的查询词;include=mediaServers 同时查 Emby",
|
||||
params: search.TmdbMediaParams,
|
||||
query: search.TmdbMediaQuery,
|
||||
response: search.TmdbMediaDetail,
|
||||
}),
|
||||
tmdbSeason: ep({
|
||||
method: "get",
|
||||
path: "/media/tmdb/tv/{id}/season/{season}",
|
||||
scope: "read",
|
||||
summary: "仅 TMDB 剧集的季详情与每集信息(标题 / 简介按语言回退链;走 TMDB 请求缓存)",
|
||||
params: search.TmdbSeasonParams,
|
||||
response: search.TmdbSeasonDetailView,
|
||||
}),
|
||||
},
|
||||
} as const;
|
||||
Reference in new issue
Block a user