1
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# 管理端接入
|
# 管理端接入
|
||||||
|
|
||||||
|
## 删除材料与不使用
|
||||||
|
|
||||||
|
“报销类型”中的垃圾桶会确认后调用材料类型删除接口,立即从全局材料列表及所有报销类型的材料规则中删除该材料,不删除历史报销附件。即使材料已选“不使用”,也保留删除入口。删除失败不会在本机假装移除;成功后保留其他尚未保存的规则编辑。
|
||||||
|
|
||||||
|
“不使用”只改变当前报销类型是否需要此材料,需要点击“保存规则”生效,不删除材料类型。
|
||||||
|
|
||||||
## 多附件兼容
|
## 多附件兼容
|
||||||
|
|
||||||
项目管理详情现在展示每个材料分类下的全部附件,并支持逐份预览、下载和 ZIP 导出。新版本同时解码旧服务的单附件对象和新服务的附件数组;多附件服务上线时需同步重新构建 Mac 应用。本地 OCR 和 Office 导出不受此次改动影响。
|
项目管理详情现在展示每个材料分类下的全部附件,并支持逐份预览、下载和 ZIP 导出。新版本同时解码旧服务的单附件对象和新服务的附件数组;多附件服务上线时需同步重新构建 Mac 应用。本地 OCR 和 Office 导出不受此次改动影响。
|
||||||
|
|||||||
@@ -386,8 +386,11 @@ private final class AdminRedirectGuard: NSObject, URLSessionTaskDelegate, @unche
|
|||||||
guard access?.platform == true else { throw AdminFailure(message: "只有平台管理员可以删除上传材料类型") }
|
guard access?.platform == true else { throw AdminFailure(message: "只有平台管理员可以删除上传材料类型") }
|
||||||
let encoded = kind.kind.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? kind.kind
|
let encoded = kind.kind.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? kind.kind
|
||||||
let _: Bool = try await request("/api/admin/upload-kinds/\(encoded)", method: "DELETE")
|
let _: Bool = try await request("/api/admin/upload-kinds/\(encoded)", method: "DELETE")
|
||||||
uploadKinds = try await request("/api/upload-kinds")
|
uploadKinds.removeAll { $0.kind == kind.kind }
|
||||||
policies = try await request("/api/expense-policies")
|
for index in policies.indices {
|
||||||
|
policies[index].materials.removeAll { $0.kind == kind.kind }
|
||||||
|
policies[index].requiredKinds.removeAll { $0 == kind.kind }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func export(_ ids: Set<String>) async throws {
|
func export(_ ids: Set<String>) async throws {
|
||||||
guard !ids.isEmpty, ids.count <= 20 else { throw AdminFailure(message: "每次请选择 1 至 20 笔申请") }
|
guard !ids.isEmpty, ids.count <= 20 else { throw AdminFailure(message: "每次请选择 1 至 20 笔申请") }
|
||||||
|
|||||||
@@ -636,14 +636,17 @@ struct AdminView: View {
|
|||||||
} label: { Image(systemName: "pencil") }
|
} label: { Image(systemName: "pencil") }
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
.help("编辑当前类型材料")
|
.help("编辑当前类型材料")
|
||||||
|
}
|
||||||
Button {
|
Button {
|
||||||
removeMaterial(policy: policy, kind: kind.kind)
|
confirm("删除材料类型“\(kind.name)”?将从所有报销类型的材料规则中移除,历史报销附件保留。此操作立即生效;仅暂停使用请选择“不使用”并保存规则。") {
|
||||||
|
try await model.deleteUploadKind(kind)
|
||||||
if editingPolicyMaterialKind == kind.kind { resetPolicyMaterialEditor() }
|
if editingPolicyMaterialKind == kind.kind { resetPolicyMaterialEditor() }
|
||||||
|
}
|
||||||
} label: { Image(systemName: "trash") }
|
} label: { Image(systemName: "trash") }
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
.tint(.red)
|
.tint(.red)
|
||||||
.help("从当前报销类型移除")
|
.help("删除材料类型(所有报销类型生效,历史附件保留)")
|
||||||
}
|
.disabled(model.access?.platform != true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Divider()
|
Divider()
|
||||||
@@ -765,10 +768,6 @@ struct AdminView: View {
|
|||||||
}
|
}
|
||||||
policy.wrappedValue.requiredKinds = policy.wrappedValue.materials.filter(\.required).map(\.kind)
|
policy.wrappedValue.requiredKinds = policy.wrappedValue.materials.filter(\.required).map(\.kind)
|
||||||
}
|
}
|
||||||
private func removeMaterial(policy: Binding<AdminExpensePolicy>, kind: String) {
|
|
||||||
policy.wrappedValue.materials.removeAll { $0.kind == kind }
|
|
||||||
policy.wrappedValue.requiredKinds = policy.wrappedValue.materials.filter(\.required).map(\.kind)
|
|
||||||
}
|
|
||||||
private func resetPolicyMaterialEditor() {
|
private func resetPolicyMaterialEditor() {
|
||||||
editingPolicyMaterialKind = ""
|
editingPolicyMaterialKind = ""
|
||||||
newPolicyMaterialName = ""
|
newPolicyMaterialName = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user