- 删除 docs/plan 下 00–18 的计划、评审、验收、发布记录与升级证据,docs/spikes 与 spikes 验证代码
(保留 spikes/movieclaw-src 本地克隆),以及 4 份一次性审查 / 调研;全部可在 ceb66f8 查到
- MP 对照移到 docs/porting/moviepilot-v3-comparison.md;经验教训改为 docs/plan/lessons.md(补第 25 条)
- docs/plan/README.md:文档放哪、当前状态、待办
- 引用改写:代码注释指向在维护的文档,其余注明已删除与 git 位置;清掉原有 6 个失效链接
- README 开头改为当前状态与入口;CHANGELOG 补齐 0.3.8–0.3.14 与工程变更
Co-Authored-By: Claude Opus 5.5 <[email protected]>
237 lines
21 KiB
Markdown
237 lines
21 KiB
Markdown
# 订阅重做 + 规则页(对标 MoviePilot v3)
|
||
|
||
> 需求来源:`00-first-version-plan`(已删除,见 git `ceb66f8`) §8 第 3、4 条(订阅重做、收录策略 + 偏好标签合一)。命名模板另见 `naming-template.md`。
|
||
> 上游行为账本:`docs/porting/moviepilot-subscribe.md`;差距清单:`05-subscription-gap`(已删除,见 git `ceb66f8`);规则关键字核对:`docs/porting/mp-rust-logic-parity.md` §6。上游 `jxxghp/MoviePilot` v3 @ `e6820a8`,只记行为,不复制源码。
|
||
|
||
## 0. MP 要点与我们的现状
|
||
|
||
**MP 订阅页**(`pages/subscribe.vue`、`views/subscribe/SubscribeListView.vue`、`components/cards/SubscribeCard.vue`)
|
||
- 按类型分路由:电影 / 电视剧 / 音乐;每类 Tab「我的订阅 / 热门 / 分享」。
|
||
- 筛选(剧集):全部 / 洗版 / 未开始 / 订阅中 / 待定 / 暂停 / 已完成。归类顺序:洗版 → P 待定 → S 暂停 → `lack_episode==0` 已完成 → `completed_episode>0` 订阅中 → 未开始。没有分组,只有筛选。
|
||
- 排序:自定义拖拽 / 上次更新 / 添加时间 / 缺集数(剧集),按类型记在本地。批量:全选、启用、暂停、删除。
|
||
- 卡片:背景图 + 海报、年份、名称 + 季(S0 显示"特别篇")、进度 `total−lack / total`、洗版进度条(已洗版/已下载双段)、洗版角标、状态角标(只显示 暂停 / 待定)、用户名、上次更新(相对时间)。**不显示**站点、下载器、规则组。
|
||
- 菜单:编辑 / 搜索 / 暂停·启用 / 重置 / 分享 / 媒体详情 / 文件统计 / 取消订阅。
|
||
- 编辑对话框两 Tab。基础:搜索关键词、总集数、开始集数、质量/分辨率/特效、订阅站点、下载器、保存路径、洗版、全集洗版、用 ImdbID 搜索。进阶:包含、排除、优先级规则组、剧集组、指定季、自定义类别、识别词。"默认订阅规则"用同一对话框,按类型存 `Default{Movie|Tv}SubscribeConfig`。
|
||
- 文件统计对话框:按集两 Tab「下载文件 / 媒体库文件」。选季对话框:每季显示集数、缺失/已订阅,可选 普通 / 分集洗版 / 全集洗版。日历:月视图,事件按 `air_date` 聚合,入库状态 无 / 部分 / 完整。
|
||
- 进度口径:`lack_episode` 存库(普通 = 媒体库缺集;洗版 = 范围内 note 与 pri 都没有的集),`completed_episode` 响应时派生(洗版按 pri==100 计)。
|
||
|
||
**MP 规则**(`app/application/rules.py:510-656`、`modules/filter/__init__.py`、`views/setting/AccountSettingRule.vue`)
|
||
- 内置规则 = 正则原子,默认匹配 `标题+副标题+标签`,可限定字段;可带 `tmdb` 条件(命中即放行,CNSUB/CNVOI 用 `original_language`)。自定义规则字段:id、name、include、exclude、size_range(MB,剧集按每集)、seeders、publish_time,同 id 覆盖内置。
|
||
- 规则组 = `name + rule_string + media_type + category`;`>` 分层,层内 `! > & > |` 与括号;第 1 层 pri=100 逐层 −1,一层不中即过滤。多组按 media_type/category 取适用组后**串联 AND**,pri 取**最后一组**。
|
||
- 默认组:订阅默认、洗版默认、搜索默认,各为组名列表;订阅 `filter_groups` 非空则覆盖默认。
|
||
- UI:三张卡片(自定义规则 / 优先级规则组 / 下载优先规则);规则组编辑 = 组名 + 媒体类型 + 分类 + 可拖拽"优先级 N"层卡片,每层多选 chips(内置 + 自定义 + "排除:X"),保存时层内 `&`、层间 `>`;`|` 与括号只能靠导入字符串。JSON 导入/分享。
|
||
|
||
**我们**
|
||
- 订阅 = 本地作品 + 季单元 + `season_scope` + `params`;条件在版本目标(Slot);状态 active/paused/pending/completed/cancelled;已有 `/progress`、`/search`、`/episode-total`、历史。订阅页是表格 + 详情抽屉,进度只算**第一个**版本目标(`subscriptionProgress` 取 `slots[0]`)。
|
||
- 版本目标已有:硬条件(`SlotHardConditions`,含 include/exclude、站点、做种、免费)、优先级阶梯 `soft.tiers[]`(层内字段 AND)、三种洗版模式、分集质量账本 `slot_unit`。
|
||
- 收录策略(`policy_revision kind=acquisition`,草案→发布→回滚,含 newTitle / defaultSlots)与偏好标签(`preference_tag` + 抑制记录)是两页;**偏好标签没接入评估**(差距 #17)。
|
||
- 阶梯层内只能 AND 结构化字段;MP 的 SPECSUB/CNVOI/HKVOI/GZ/ATMOS/60FPS/3D/UHD、跨字段 OR 表达不了(parity §6:43 条样例 ✔22 ~6 ✗15)。
|
||
|
||
## 1. 订阅总览
|
||
|
||
路由 `/console/subscriptions`,页头 Tab:**剧集 / 电影 / 综艺 / 日历(P2)**,选中项写 URL(`?kind=`)。视图切换 卡片 / 列表(记本地)。
|
||
|
||
### 1.1 分组(派生,不新增状态值)
|
||
|
||
| 分组 | 条件(按顺序判定) | 对应 MP |
|
||
| --- | --- | --- |
|
||
| 暂停 | `status=paused` | S |
|
||
| 待定 | `status=pending`(未建档 / 无 TMDB 身份),或任一范围内季 `totalKnown=false` | P |
|
||
| 已完成 | `status=completed`,或 continuous 订阅所有版本目标在范围内全覆盖且 total 已知(卡片仍追下一季时显示"等待新季") | lack=0 |
|
||
| 追更中 | active 且至少一个单元已入库或在途 | 订阅中 |
|
||
| 待搜索 | active 且没有任何已入库/在途单元 | 未开始 |
|
||
|
||
"洗版中"不单列分组,作为徽标(任一版本目标开升级且未达顶档)与筛选项。`cancelled` 不在总览,只在"订阅历史"。
|
||
|
||
默认按分组折叠展示(待定、追更中、待搜索、已完成、暂停),组内按**上次更新**倒序。也可切成平铺 + 排序:上次更新 / 下次搜索 / 缺集数 / 添加时间 / 名称。筛选:分组、洗版中、站点、规则组、来源(用户/Agent/策略)、关键词;全部进 URL query(`use-query-state.ts`)。
|
||
|
||
**上次更新** = `subscription.last_progress_at`(新列):任一关联版本目标的单元转为 已入库 / 在途,或总集数变化时写入;为空取 `created_at`。与 MP `last_update` 同义(MP 在下载添加时更新)。
|
||
|
||
### 1.2 卡片字段
|
||
|
||
| 区 | 字段 | 数据 |
|
||
| --- | --- | --- |
|
||
| 封面 | 占位块:类型图标 + 标题首字(暂无海报;有 TMDB poster_path 后再接) | — |
|
||
| 标题行 | 名称、年份、类型标签;剧集加季(`S1`,S0 显示"特别篇",following_seasons 显示"S2 起") | 实体、季单元 |
|
||
| 进度 | `已入库/总`,总未知显示 `?`;下方细条:已入库、在途两段;多版本时显示主版本数字,悬浮列出每个版本 | overview.progress |
|
||
| 版本徽标 | 每个版本目标一个:名称 + 状态色(已齐 / 缺 N / 在途 N / 洗版中 pri a→目标 b) | overview.slots |
|
||
| 元信息 | 上次更新(相对时间)、下次搜索(或"搜索已关")、站点范围(≤2 个名 + "+N";空 = 全部站点)、规则组(同样折叠) | |
|
||
| 状态角标 | 仅 暂停 / 待定 / 洗版中(同 MP 只标异常态) | |
|
||
| 操作菜单 | 立即搜索、查看对比、编辑、暂停/启用、重置(P2)、删除;点卡片 = 查看对比 | |
|
||
|
||
批量模式:勾选后 立即搜索 / 暂停 / 启用 / 删除(删除走确认,写审计)。空态:"还没有订阅。从媒体库或 Agent 添加。"
|
||
|
||
## 2. 对比视图(订阅详情)
|
||
|
||
路由 `/console/subscriptions/:id`(取代抽屉;抽屉保留为列表页快速预览)。页头:标题、状态、进度、操作按钮;下方三块:**覆盖矩阵**、**版本目标**、**记录**(搜索记录、候选评估、订阅历史)。
|
||
|
||
### 2.1 覆盖矩阵
|
||
|
||
- 列 = 集,按季分段(季标题显示 `已入库/总 · 总集数来源 · 锁定`,可点"设置总集数");行 = 版本目标,每个一行;首行"库内任一版本"汇总。
|
||
- 电影:每个版本目标一格。
|
||
|
||
| 格状态 | 显示 | 来源 |
|
||
| --- | --- | --- |
|
||
| 已入库·达标 | 实心,文字 `2160p REMUX` | slot_unit + asset |
|
||
| 已入库·可升级 | 实心 + 角点,悬浮 `pri 97 → 目标 100` | slot_unit.pri < targetPri |
|
||
| 在途 | 斜纹,计划状态(已预留/下载中/核验中) | 在途计划 unit_keys |
|
||
| 延后 | 空心 + 时钟 | slot_deferral |
|
||
| 缺失 | 空心红框 | computeUnitGaps |
|
||
| 疑似缺失 | 虚线红框 | total 未知时的集号空洞 |
|
||
| 未播出 | 灰,显示播出日期 | content_unit.air_date > 今天 |
|
||
| 范围外 | 淡灰 | episodeRange / season_scope |
|
||
|
||
点格打开侧栏:资产位置(链到文件管理)、质量与 pri、来源资源与下载任务、该单元的候选评估(接受/拒绝理由 trace)、操作"搜索此集""为此版本补全"。
|
||
|
||
### 2.2 多版本与自动补全
|
||
|
||
- 每个版本目标一行,行尾:缺失数、在途数、"补全此版本"按钮、自动补全状态。
|
||
- **自动补全其他版本**:订阅级开关 `params.autoFill: "inherit" | "on" | "off"`,缺省 inherit → 取引用规则组/订阅默认值的 `autoFill`(系统缺省 on)。
|
||
- on:非主版本目标像主版本一样独立评估、搜索、下载缺失单元。
|
||
- off:非主版本目标只登记缺失,不自动建计划;RSS 来的合格资源记为"延后(未开自动补全)";手动"补全此版本"或 Agent 调 `download.plan` 仍可下。
|
||
- 主版本 = 版本目标排序第一个(可在版本目标区拖动)。
|
||
- **补全预算** `params.fillBudget {bytesPerDay?, unitsPerDay?}`:只约束非主版本的自动补全计划,计入全局每日预算;超出记延后,次日由 `slots.reevaluate` 重评。计划优先级用 `upgrade` 档(低于追更)。
|
||
|
||
## 3. 新建 / 编辑订阅表单
|
||
|
||
对话框两 Tab,同 MP 分"基础 / 进阶"。"订阅默认值"(按类型)用同一表单的默认模式,存规则页 §6.4。
|
||
|
||
| 区 | 字段(界面) | MP 字段 | 我们存放 | 默认 / 显示条件 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 基础 | 作品(搜索本地作品或 TMDB) | media_id / name | `mediaEntityId` / `titleQuery` | 必填 |
|
||
| | 类型 | type | `mediaKind` | 由作品带出 |
|
||
| | 季 / 季范围 | season | `seasonUnitId` + `seasonScope` | 剧集;缺省最新季 + 接续后续季(Agent 来源缺省仅本季) |
|
||
| | 开始集 / 结束集 | start_episode | `params.episodeRange {start,end}` | 剧集 |
|
||
| | 总集数(可锁定) | total_episode / manual_total_episode | `POST /episode-total` | 剧集;显示来源 |
|
||
| | 方式 | — | `mode` once / continuous | 电影缺省 once |
|
||
| | 优先级 | — | `priority` | tracking |
|
||
| | 站点范围 | sites | `params.siteIds` | 空 = 全部启用站点 |
|
||
| | 下载器 | downloader | `params.downloaderInstanceId` | 空 = 默认实例 |
|
||
| | 库根 | save_path(整理去向部分) | `params.libraryRootId`(新) | 空 = 按类型默认库根 |
|
||
| | 版本目标 | best_version / best_version_full | 子表:名称 + 规则组 + 升级(关 / 按集 / 整季 / 电影)+ 目标 pri | 缺省取订阅默认值 |
|
||
| 进阶 | 规则组 | filter_groups | `params.ruleGroupIds`(作用于全部版本目标)+ 版本目标 `rule_group_ids` | 空 = 订阅默认组 |
|
||
| | 包含 / 排除 | include / exclude | 订阅私有规则组(`scope.subscriptionId`,不在列表页显示) | 正则白名单校验 |
|
||
| | 分辨率 / 来源 / 特效 | resolution / quality / effect | 同上,写进私有规则组 hard | |
|
||
| | 搜索关键词 | keyword | `params.keywords[]`(新,追加到标题/别名检索词) | |
|
||
| | 主动搜索间隔 | —(全局) | `params.searchIntervalHours` | 24;0 = 关 |
|
||
| | 自动补全 / 补全预算 | — | `params.autoFill`、`params.fillBudget` | inherit |
|
||
| | 截止时间 | — | `params.stopAfter` | |
|
||
| | 下载保存路径 | save_path | `params.downloadSavePath`(新,P2) | 空 = 实例默认 |
|
||
| 不做 | 剧集组 episode_group | | P2(需 TMDB episode group 适配) | |
|
||
| | ImdbID 搜索 search_imdbid | | P2 `params.searchByImdb` | |
|
||
| | 自定义类别 media_category | | 用命名模板 `category` | |
|
||
| | 识别词 custom_words | | 放身份层(实体别名/集偏移),表单给链接 | |
|
||
|
||
保存:创建时同实体同季已有 active 订阅 → 返回 409 并给"打开已有订阅"(差距 #18)。
|
||
|
||
## 4. 日历(P2)
|
||
|
||
`/console/subscriptions?kind=calendar`:月视图,事件 = 追踪中订阅范围内集单元的 `air_date`(同日同剧聚合为 `E03–E04`),电影取上映日期;颜色 = 该日事件 已入库 / 部分 / 未入库 / 未播出。数据来自 `refreshMetadata` 写入的集单元 `air_date`(需补:目前只写季单元总集数,不建集单元)。接口 `GET /subscriptions/calendar?from&to`。
|
||
|
||
## 5. 后端与 contracts
|
||
|
||
| 端点 | 用途 | 新/改 |
|
||
| --- | --- | --- |
|
||
| `GET /subscriptions/overview?kind&group&sort&siteId&ruleGroupId&q&cursor` | 卡片数据:分组、进度、每版本摘要、上次更新、下次搜索、站点、规则组 | 新 |
|
||
| `GET /subscriptions/{id}/coverage` | 覆盖矩阵:季 × 集 × 版本目标 | 新(取代 `/progress`,后者保留一版兼容) |
|
||
| `POST /subscriptions/batch` | `{ids, action: search\|pause\|resume\|delete}` | 新 |
|
||
| `POST /subscriptions/{id}/slots/{slotId}/fill` | 手动补全某版本(可带 unitKeys) | 新 |
|
||
| `POST /subscriptions/{id}/reset` | 清在途预留、重评(保留资产) | 新(差距 #24) |
|
||
| `GET /subscriptions/calendar` | 日历 | 新,P2 |
|
||
| `PATCH /subscriptions/{id}` | params 新键:`ruleGroupIds keywords libraryRootId autoFill fillBudget downloadSavePath` | 改 |
|
||
|
||
contracts(`policy.ts`):`SubscriptionOverviewItem`、`SubscriptionCoverage {seasons[{seasonNumber,total,totalKnown,source,locked,episodes[{episode,airDate}]}], rows[{slotId|null,name,primary,autoFill,cells[{unitKey,state,quality,pri,planId,assetId}]}]}`、`SubscriptionBatch`、`SubscriptionParams` 扩键;规则页见 §6.6。
|
||
|
||
**覆盖矩阵查询**:一次取 作品全部集单元 → 左连 `asset_unit_coverage`(库内任一版本)、`slot_unit`(按版本目标)、在途计划 `unit_keys`、`slot_deferral`;在服务里用 `computeUnitGaps` 逐版本目标算状态。总览用一条聚合 SQL 出每订阅 × 版本目标的 已入库/在途/总 计数,避免 N+1;超 200 条订阅走游标分页。
|
||
|
||
DB:`subscription.last_progress_at`;`acquisition_slot.rule_group_ids uuid[]`、`acquisition_slot.position int`(主版本排序);`rule_group`、`rule_atom` 两表(§6);偏好标签迁移。
|
||
|
||
定时任务(沿用注册表):`subscriptions.search`、`subscriptions.metadata`(补:建集单元与 air_date;完成前强制刷新 = 差距 #8)、`slots.reevaluate`(补:按 `autoFill` 与 `fillBudget` 过滤非主版本)。不新增任务。
|
||
|
||
## 6. 规则页(收录策略 + 偏好标签合一)
|
||
|
||
路由 `/console/rules`,页名"规则"。Tab:**规则组 / 自定义规则 / 默认值 / 收录策略 / 抑制记录**。`/console/preferences` 重定向到 `/console/rules?tab=groups`(带 `origin` 筛选时透传);术语表加"规则组",弃用"偏好标签"(对话与 Agent 产生的规则组以"来源"区分)。
|
||
|
||
### 6.1 规则组结构
|
||
|
||
| 字段 | 含义 |
|
||
| --- | --- |
|
||
| name、description | 名称必填唯一;说明一句 |
|
||
| hard | 硬条件(必须 / 排除),即 `SlotHardConditions`,再加 `atoms {require[], exclude[]}` 引用原子 |
|
||
| ladder | 优先级阶梯:有序层,每层一个布尔表达式 `expr`(原子 + `! & |` + 括号);第 k 层(0 起)命中 pri = 100 − k |
|
||
| ladderRequired | 一层不中即拒绝(MP 语义,缺省 true;从 MP 串导入时固定 true) |
|
||
| scope | `mediaKinds[]`、`entityIds[]`、`siteIds[]`、`subscriptionId`(私有组);空 = 全部 |
|
||
| origin | manual / conversation / agent_inferred(沿用偏好标签来源) |
|
||
| status、revision、fingerprint、evidence | 同偏好标签;每次修改 revision+1 并写审计,评估 trace 记 `组id@revision` |
|
||
| autoFill | 引用本组的订阅缺省是否自动补全其他版本 |
|
||
|
||
**原子**(`rule_atom`):内置(只读)+ 自定义。自定义原子字段对齐 MP 自定义规则:`id`(大写字母数字)、`name`、`include[]`、`exclude[]`、`matchFields`(title/subtitle/labels,缺省全部)、`unitSizeMB {min,max}`(剧集按每集)、`minSeeders`、`publishDelayMinutes {min,max}`、`free`。同 id 不允许覆盖内置(偏离 MP,避免静默改义)。
|
||
|
||
### 6.2 内置原子(对齐 MP 关键字)
|
||
|
||
| 原子 | 语义 | 我们的判定 |
|
||
| --- | --- | --- |
|
||
| 4K / 1080P / 720P | 分辨率 | `resolution` 字段 |
|
||
| BLU | 蓝光原盘 | `source = BluRay-Disc`(先修 parity our_bug:Blu-ray+AVC/HEVC 无 x26x 判原盘) |
|
||
| BLURAY | 标题含 Blu-ray | 来源属蓝光族(原盘/REMUX/压制) |
|
||
| REMUX / WEBDL | Remux;WEB-DL 或 WEBRip | `source` 字段 |
|
||
| UHD | 标题含 UHD/UltraHD | `parsed.uhd` |
|
||
| H265 / H264 | 编码 | `videoCodec` |
|
||
| HDR / DOLBY / SDR | HDR 类;杜比视界;SDR | `hdr` 字段(HDR = 任一非 DV HDR,同 MP 正则口径做差分) |
|
||
| ATMOS | 全景声 | `audio` 含 Atmos |
|
||
| 60FPS / 3D | 帧率;3D | `fps>=60`;正则 `3D` |
|
||
| CNSUB | 中字 | `subtitles` 含 zh(补 CHS/CHT/GB/BIG5);作品原语言 zh 时直接满足(MP tmdb 放行) |
|
||
| SPECSUB | 特效字幕 | 正则 `特效`(标题+副标题+标签) |
|
||
| CNVOI / HKVOI | 国语配音 / 粤语 | 正则;CNVOI 作品原语言 zh 时满足 |
|
||
| GZ | 官种 | 只看站点标签 `官方/官种/官组` |
|
||
| FREE | 免费 | `downloadVolumeFactor = 0` |
|
||
| 音乐 13 条(HIRES/FLAC/…) | — | 不做 |
|
||
|
||
### 6.3 MP 规则串 ↔ 结构化
|
||
|
||
- 规则组编辑页有"规则串"输入框(高级):输入 `SPECSUB & CNSUB > CNSUB & 4K > 1080P & !BLU` 实时解析,下方同步画出层卡片;反过来编辑层卡片时规则串随之更新(规范化:原子大写、层内按 `|` 优先级加最少括号)。
|
||
- 解析错误逐条给位置:未知原子(给相近名)、括号不配对、空层。音乐原子报"不支持"。
|
||
- 层卡片编辑:每层是 chips 行,chip = 原子或取反原子;层内 chips 之间可切换 `且/或`,支持"加括号组";拖动层即改优先级(同 MP),层标题显示 `优先级 1 · pri 100`。
|
||
- 测试:"用最近资源测试"对 200 条近期资源跑本组,显示每条命中层/被拒原因,和 MP trace 同粒度;也可粘贴标题测试。
|
||
- JSON 导入/导出兼容 MP 格式(`name/rule_string/media_type`,自定义规则 7 字段),media_type 映射到 `mediaKinds`,category 丢弃并提示。
|
||
|
||
### 6.4 引用关系与默认值
|
||
|
||
- 版本目标 `rule_group_ids`(有序)+ 订阅 `params.ruleGroupIds`;评估时编译为 SlotSpec:hard 取交集;各组按 scope 过滤后**全部须命中某层**,pri 取**最后一个**带阶梯的组(同 MP),界面在该组上标"决定优先级"。
|
||
- 版本目标自身的 hard/soft 字段保留,视为一个匿名组排在最前。
|
||
- 默认值 Tab:按类型设 **订阅默认规则组**、**洗版默认规则组**(版本目标开升级时额外叠加)、**搜索默认规则组**(手动搜索与 Agent `release.search`)、订阅默认表单(§3 默认模式:站点、下载器、库根、版本目标模板、自动补全)。
|
||
- 收录策略 Tab:现有策略工作区原样搬入(草案→预览→发布→回滚、newTitle、defaultSlots);`SlotTemplate` 增加 `ruleGroupIds`。
|
||
- Agent:能力 `rules.list` 读规则组;新增/修改走 `rules.propose`(origin=agent_inferred,生成待处理事项,批准后生效);命中有效抑制记录的指纹直接拒绝。对话中用户明确说的偏好 origin=conversation,直接生效并可撤销。
|
||
|
||
### 6.5 偏好标签迁移
|
||
|
||
| 旧 kind | 新规则组 |
|
||
| --- | --- |
|
||
| hard | hard 条件,ladder 空 |
|
||
| soft | ladder 单层(或按 rule 顺序多层),`ladderRequired=false` |
|
||
| version | 规则组 + 在"默认值"里挂到对应版本目标模板 |
|
||
| target | 转收录策略 newTitle scope,原标签留一条只读规则组作说明 |
|
||
|
||
指纹、来源、证据、修订历史、抑制记录原样迁移(抑制按新组指纹重算一次,旧指纹保留作别名)。迁移后偏好标签接入评估,关闭差距 #17。
|
||
|
||
### 6.6 规则接口
|
||
|
||
`GET/POST /rule-groups`、`GET/PATCH/DELETE /rule-groups/{id}`、`GET /rule-groups/{id}/revisions`、`POST /rule-groups/parse {ruleString}` → `{ladder, errors[]}`、`POST /rule-groups/render {ladder}` → `{ruleString}`、`POST /rule-groups/{id}/test {sourceReleaseIds?|titles?}`、`GET/POST/PATCH/DELETE /rule-atoms`、`GET/PUT /rule-defaults`、`POST /rule-groups/import`、`GET /rule-groups/export`。抑制记录接口沿用 `/preference-suppressions`(改名 alias `/rule-suppressions`)。
|
||
|
||
domain:`slot/rule-expr.ts`(词法/解析/求值/规范化输出)、`slot/atoms.ts`(内置原子表)、`SlotTierRule.expr?`;`mapping/slot.ts` 编译规则组 → SlotSpec。差分:`filter-cases.json#rules` 43 条全部重跑,目标 ✗ 从 15 降到 1(只剩音乐)。
|
||
|
||
## 7. 实施拆分与估算
|
||
|
||
| 包 | 内容 | 估 | 依赖 |
|
||
| --- | --- | --- | --- |
|
||
| R1 domain | rule-expr 解析/求值/串互转、内置原子(含 BLU/CHS 修正)、多组编译、差分样例 | M 2 天 | — |
|
||
| R2 server 规则 | 迁移(rule_group、rule_atom、slot.rule_group_ids)、CRUD/parse/render/test/import、偏好标签迁移、评估接入、Agent `rules.propose` | L 3 天 | R1 |
|
||
| R3 web 规则页 | 5 个 Tab、层卡片编辑 + 规则串双向、测试面板、`/preferences` 重定向、术语表 | L 3 天 | R2 |
|
||
| S1 server 订阅 | last_progress_at、overview 聚合、coverage 矩阵、batch、fill、reset、params 新键、autoFill/fillBudget 调度、查重 409、集单元与 air_date | L 3 天 | R2(ruleGroupIds) |
|
||
| S2 web 总览 | 类型 Tab、分组/排序/筛选、卡片、批量 | M 1.5 天 | S1 |
|
||
| S3 web 详情 | 覆盖矩阵 + 格侧栏、版本目标区(排序、补全、自动补全)、编辑表单(两 Tab、默认模式) | L 2.5 天 | S1 |
|
||
| S4 日历(P2) | 接口 + 月视图 | M 1 天 | S1 |
|
||
|
||
并行:R1 与 S1 的非规则部分可同时开工;R3 与 S2/S3 可并行。合计约 15 人日(不含 P2 约 14)。
|
||
验收:`subscription.test.ts` 加 覆盖矩阵、自动补全 off 不建计划、补全预算延后、多组 pri 取最后组;e2e 加"双版本订阅一版齐一版缺 → 矩阵正确 → 手动补全"。
|