导入入口(拖拽 + 路径输入 + 目标实例)与导出(格式选择 + 预检)的**界面层**,
数据面镜像 M111/M112 的管线报告(presenter DTO),进度整块复用下载页的安装面板。
## 落了什么
- pages/content/packui*:入口 / 进度块 / 结果块 / 导出预检块(每文件 ≤400)
- 拖拽区(hover 变主色描边)+ 路径输入框 + 目标实例 chips
- 进度:一行「步骤 n/5 · 解包覆盖内容」+ **下载页那块安装面板**(不另画进度条)
- 结果:三态(Success/Partial/Failed)+ 缺文件逐条(Warn/Tertiary)+ 冲突逐条
(成因 + 本次处置 + 可展开三方 SHA-1)+ 致命块(Error/ErrorContainer)
- 导出:mrpack / CF 二选一 + 包名/版本/路径 + 预检「将内联 N 个文件 · 无法导出 M 项」
+ 逐条无法导出项 + 已知损失 + 确认写盘
- presenter/src/dto/pack{,/format,/import,/conflict,/export}.rs:镜像 core 报告的 DTO
(三态、五阶段、三分类、十一条原因,全部 from_slug 与 core 稳定码逐字对齐)
- i18n:81 条 Pack* 键(content_entries! 尾部追加;golden.rs 同序同文)
- app/update.rs:FileDropped / FileHovered / FilesHoveredLeft → 内容库页(本版唯一的选文件通道)
- M109 的四个文件各一处插入:mod 声明 + Pack(..) 变体 + pack 字段 + 正列插入点
## 边界(如实)
- 没有系统文件选择框:依赖树里无对话框依赖,加它要动根 Cargo.toml + 许可门禁 +
Linux 后端选型(影响单文件产物)。入口是拖拽 + 路径输入,原因写在界面上。
- 冲突没有逐文件决策:core 的 ConflictPolicy 是整次导入一个全局档,ConflictFile 是事后账。
本批给「逐文件看 + 整体翻档(以包为准重新导入)」,文案明写「两者都留(改名)暂不支持」。
默认一律 KeepUser——绝不默认覆盖用户改过的文件。
- 本批按钮半通:拖拽/路径/格式/实例/展开都真生效;「点导入真的开跑」「预检/确认写盘」
要等第二批的 AppCommand 与事件通道(M109 rebase 到新 main 后按新形状写一次)。
48 lines
1.8 KiB
Rust
48 lines
1.8 KiB
Rust
//! 整合包格式:探测结果与导出目标共用一个枚举。
|
||
//!
|
||
//! `slug()` 与 core 的格式 id **逐字一致**(`curseforge` / `modrinth` / `multimc`),
|
||
//! `from_slug` 是反向唯一入口——翻译发生在 `host::addon`,页面侧只认这两个函数。
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 整合包格式(探测结果与导出目标共用一个枚举)。
|
||
///
|
||
/// MultiMC / Prism 只**导入**不导出(core 的有意省略),所以导出侧两个入口是
|
||
/// [`Self::Modrinth`] / [`Self::Curseforge`]。
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||
pub enum PackFormatView {
|
||
/// CurseForge:`manifest.json` + `overrides/`。
|
||
Curseforge,
|
||
/// Modrinth:`.mrpack`(`modrinth.index.json` + `overrides/`)。
|
||
Modrinth,
|
||
/// MultiMC / Prism:`mmc-pack.json` + `.minecraft/`(**只读**)。
|
||
Multimc,
|
||
}
|
||
|
||
impl PackFormatView {
|
||
/// 导出菜单里可选的两个(顺序 = 画出来的顺序)。
|
||
pub const EXPORTABLE: [PackFormatView; 2] =
|
||
[PackFormatView::Modrinth, PackFormatView::Curseforge];
|
||
|
||
/// 稳定 slug(与 core 的格式 id 逐字一致,**不要改名**)。
|
||
#[must_use]
|
||
pub const fn slug(self) -> &'static str {
|
||
match self {
|
||
Self::Curseforge => "curseforge",
|
||
Self::Modrinth => "modrinth",
|
||
Self::Multimc => "multimc",
|
||
}
|
||
}
|
||
|
||
/// 从 core 的格式 id 反解(`None` = 不认识的 id,调用方按「未知」处理,别猜)。
|
||
#[must_use]
|
||
pub fn from_slug(slug: &str) -> Option<Self> {
|
||
match slug {
|
||
"curseforge" => Some(Self::Curseforge),
|
||
"modrinth" => Some(Self::Modrinth),
|
||
"multimc" => Some(Self::Multimc),
|
||
_ => None,
|
||
}
|
||
}
|
||
}
|