Files
UHD_Media_Tool/packages/contracts/src/api/content.ts
T
rootandClaude Opus 5.5 8bec4bad5d 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]>
2026-10-02 17:40:43 +08:00

202 lines
5.6 KiB
TypeScript

import { z } from "zod";
import * as assets from "../assets.ts";
import { Id, IdParam } from "../common.ts";
import * as content from "../content.ts";
import * as identity from "../identity.ts";
import {
crud,
del,
ep,
FieldOverrideResult,
FieldParam,
IdentityRevisionList,
R,
TaskAccepted,
UnitFieldOverrideResult,
UnitFieldParam,
} from "./shared.ts";
export const contentApi = {
// ── 内容 / 身份 ──
mediaEntities: {
...crud(
"/media-entities",
"作品",
{
row: content.MediaEntity,
create: content.MediaEntityCreate,
update: content.MediaEntityUpdate,
filters: {
kind: content.MediaKind.optional(),
status: content.MediaEntityStatus.optional(),
q: z.string().max(200).optional(),
},
},
R,
),
merge: ep({
method: "post",
path: "/media-entities/{id}/merge",
scope: "admin",
summary: "合并重复作品(保留旧 ID 跳转)",
params: IdParam,
body: z.object({ intoId: Id, reason: z.string().max(2000) }),
response: content.MediaEntity,
}),
detail: ep({
method: "get",
path: "/media-entities/{id}/detail",
scope: "read",
summary: "作品详情:外部身份、别名、内容单元、字段来源与覆盖(旧 ID 自动跳转)",
params: IdParam,
response: content.MediaEntityDetail,
}),
setIdentity: ep({
method: "post",
path: "/media-entities/{id}/identities",
scope: "organize.execute",
summary: "人工纠错外部映射:旧映射退役(留修订),新映射 accepted + 人工锁",
params: IdParam,
body: identity.EntityIdentitySet,
response: z.object({
mediaEntityId: Id,
changed: z.boolean(),
identityId: Id.optional(),
retired: z.array(Id).optional(),
}),
}),
refresh: ep({
method: "post",
path: "/media-entities/{id}/refresh",
scope: "organize.execute",
summary:
"刷新元数据(字段级;用户锁优先,不动路径)。标题 / 简介按设置 metadata.languages 回退;full=1 拉取全部季的每集信息",
params: IdParam,
query: z.object({ full: z.enum(["0", "1", "true", "false"]).optional() }),
response: TaskAccepted,
}),
setField: ep({
method: "put",
path: "/media-entities/{id}/fields/{field}",
scope: "organize.execute",
summary: "覆盖作品字段并锁定(自动刷新不再改写)",
params: FieldParam,
body: content.FieldOverrideInput,
response: FieldOverrideResult,
}),
clearField: ep({
method: "delete",
path: "/media-entities/{id}/fields/{field}",
scope: "organize.execute",
summary: "取消字段覆盖与锁定",
params: FieldParam,
response: FieldOverrideResult,
}),
},
contentUnits: {
...crud(
"/content-units",
"内容单元",
{
row: content.ContentUnit,
update: content.ContentUnitUpdate,
filters: { mediaEntityId: Id.optional(), seasonNumber: z.coerce.number().int().optional() },
},
R,
),
setField: ep({
method: "put",
path: "/content-units/{id}/fields/{field}",
scope: "organize.execute",
summary: "覆盖季 / 集字段并锁定(元数据刷新不再改写)",
params: UnitFieldParam,
body: content.FieldOverrideInput,
response: UnitFieldOverrideResult,
}),
clearField: ep({
method: "delete",
path: "/content-units/{id}/fields/{field}",
scope: "organize.execute",
summary: "取消季 / 集字段覆盖与锁定",
params: UnitFieldParam,
response: UnitFieldOverrideResult,
}),
},
titleAliases: {
...crud(
"/title-aliases",
"别名",
{
row: content.TitleAlias,
create: content.TitleAliasCreate,
filters: { mediaEntityId: Id.optional(), q: z.string().max(200).optional() },
},
R,
),
remove: del("/title-aliases/{id}", "删除别名"),
},
externalIdentities: {
...crud(
"/external-identities",
"外部身份",
{
row: identity.ExternalIdentity,
create: identity.ExternalIdentityCreate,
update: identity.ExternalIdentityUpdate,
filters: {
mediaEntityId: Id.optional(),
provider: z.string().optional(),
status: identity.IdentityStatus.optional(),
},
},
R,
),
revisions: ep({
method: "get",
path: "/external-identities/{id}/revisions",
scope: "read",
summary: "身份修订历史",
params: IdParam,
response: IdentityRevisionList,
}),
},
// ── 文件(只读;写入只经整理/对账流程,不开放直接改) ──
mediaAssets: crud(
"/media-assets",
"资产",
{
row: assets.MediaAsset,
filters: { mediaEntityId: Id.optional(), status: assets.AssetStatus.optional() },
},
R,
),
assetUnitCoverage: crud(
"/asset-unit-coverage",
"资产覆盖",
{
row: assets.AssetUnitCoverage,
filters: { mediaAssetId: Id.optional(), contentUnitId: Id.optional() },
},
R,
),
assetLocations: crud(
"/asset-locations",
"资产位置",
{
row: assets.AssetLocation,
filters: { mediaAssetId: Id.optional(), status: assets.LocationStatus.optional() },
},
R,
),
pathBindings: crud(
"/path-bindings",
"路径绑定",
{
row: assets.PathBinding,
filters: { mediaEntityId: Id.optional(), status: assets.BindingStatus.optional() },
},
R,
),
} as const;