refactor(rules): outcome→文案映射移出视图文件,落回 outcome 类型旁

This commit is contained in:
Qiu Yuzhou
2026-10-03 19:04:40 +08:00
parent 16a2384498
commit edb2c08933
3 changed files with 82 additions and 45 deletions
@@ -27,6 +27,55 @@ struct RuleDocumentCommit: Sendable {
let document: CustomRuleDocument?
}
// MARK: - 结果呈现文案
// outcome→文案映射与 outcome 类型同住,供状态行与编辑器两个视图共享。
extension RulesCommitFeedback {
var summary: String {
guard outcome.isSuccess else { return outcome.rulesMessage }
let count: String
switch operation {
case .enablement(let enabled):
count = String.localizedStringWithFormat(
RulesCopy.text(enabled ? "已启用 %lld 条规则" : "已禁用 %lld 条规则"), Int64(changedCount))
case .add: count = RulesCopy.text("已新增规则")
case .edit: count = RulesCopy.text("已编辑规则")
case .delete:
count = String.localizedStringWithFormat(
RulesCopy.text("已删除 %lld 条自定义规则"), Int64(changedCount))
}
return count + " · " + RulesCopy.text("已保存")
}
}
extension CustomRuleUpdateOutcome {
var rulesMessage: String {
switch self {
case .saved: RulesCopy.text("已保存")
case .persistenceFailed: RulesCopy.text("保存失败,规则未更改")
case .busy: RulesCopy.text("正在更新规则…")
case .invalidDocument, .rejected: RulesCopy.text("无法更新规则")
}
}
var failureDetail: String? {
switch self {
case .invalidDocument(let detail): detail
case .rejected(let rejected): rejected.map(\.explanation).joined(separator: "\n")
default: nil
}
}
var nextStep: String? {
switch self {
case .persistenceFailed, .busy: "请重试规则操作。"
case .invalidDocument, .rejected: "请检查规则数据后再操作。"
default: nil
}
}
}
// MARK: - 自定义规则命令面
extension ProxyRuntimeController {
@@ -103,48 +103,3 @@ struct RulesCollectionIssuesView: View {
}
}
}
extension RulesCommitFeedback {
var summary: String {
guard outcome.isSuccess else { return outcome.rulesMessage }
let count: String
switch operation {
case .enablement(let enabled):
count = String.localizedStringWithFormat(
RulesCopy.text(enabled ? "已启用 %lld 条规则" : "已禁用 %lld 条规则"), Int64(changedCount))
case .add: count = RulesCopy.text("已新增规则")
case .edit: count = RulesCopy.text("已编辑规则")
case .delete:
count = String.localizedStringWithFormat(
RulesCopy.text("已删除 %lld 条自定义规则"), Int64(changedCount))
}
return count + " · " + RulesCopy.text("已保存")
}
}
extension CustomRuleUpdateOutcome {
var rulesMessage: String {
switch self {
case .saved: RulesCopy.text("已保存")
case .persistenceFailed: RulesCopy.text("保存失败,规则未更改")
case .busy: RulesCopy.text("正在更新规则…")
case .invalidDocument, .rejected: RulesCopy.text("无法更新规则")
}
}
var failureDetail: String? {
switch self {
case .invalidDocument(let detail): detail
case .rejected(let rejected): rejected.map(\.explanation).joined(separator: "\n")
default: nil
}
}
var nextStep: String? {
switch self {
case .persistenceFailed, .busy: "请重试规则操作。"
case .invalidDocument, .rejected: "请检查规则数据后再操作。"
default: nil
}
}
}
@@ -58,6 +58,39 @@ final class RulesPresentationTests: XCTestCase {
XCTAssertNil(workflow.selectedRelationshipRow)
}
func testOutcomeCopyMappingCoversEveryCase() throws {
XCTAssertEqual(CustomRuleUpdateOutcome.saved.rulesMessage, RulesCopy.text("已保存"))
XCTAssertEqual(
CustomRuleUpdateOutcome.persistenceFailed.rulesMessage, RulesCopy.text("保存失败,规则未更改"))
XCTAssertEqual(
CustomRuleUpdateOutcome.persistenceFailed.nextStep, RulesCopy.text("请重试规则操作。"))
XCTAssertNil(CustomRuleUpdateOutcome.persistenceFailed.failureDetail)
XCTAssertEqual(CustomRuleUpdateOutcome.busy.rulesMessage, RulesCopy.text("正在更新规则…"))
let invalid = CustomRuleUpdateOutcome.invalidDocument(detail: "detail-1")
XCTAssertEqual(invalid.rulesMessage, RulesCopy.text("无法更新规则"))
XCTAssertEqual(invalid.failureDetail, "detail-1")
XCTAssertEqual(invalid.nextStep, RulesCopy.text("请检查规则数据后再操作。"))
let rejected = CustomRuleUpdateOutcome.rejected([
RejectedCustomRule(
rule: CustomRule(action: .direct, match: try RuleMatch(domainExact: "a.test")),
reason: .duplicate, explanation: "r1"),
RejectedCustomRule(
rule: CustomRule(action: .direct, match: try RuleMatch(domainExact: "b.test")),
reason: .duplicate, explanation: "r2"),
])
XCTAssertEqual(rejected.failureDetail, "r1\nr2")
XCTAssertEqual(rejected.nextStep, RulesCopy.text("请检查规则数据后再操作。"))
XCTAssertNil(CustomRuleUpdateOutcome.saved.failureDetail)
XCTAssertNil(CustomRuleUpdateOutcome.saved.nextStep)
let success = RulesCommitFeedback(
outcome: .saved, operation: .enablement(true), changedCount: 3)
XCTAssertEqual(
success.summary,
RulesCopy.text("已启用 3 条规则") + " · " + RulesCopy.text("已保存"))
let failure = RulesCommitFeedback(outcome: .busy, operation: .delete, changedCount: 1)
XCTAssertEqual(failure.summary, RulesCopy.text("正在更新规则…"))
}
}
private final class ReportFixtureLoader: @unchecked Sendable {