feat(ios): 封面图底部半屏抽屉弹窗 + 左侧正方形卡片

- 封面图有独立中文标签"封面图"
- 120×120 正方形虚线框,左侧对齐
- 点击弹出底部半屏 sheet(height: 220)
- sheet 内:从相册选择(带图标+描述+箭头)
- 顶部有指示条(灰色胶囊)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wangdl 2026-05-28 11:00:20 +08:00
parent 11c0fe42b7
commit 481f513b11

View File

@ -12,29 +12,28 @@ struct CreateLibraryPage: View {
var body: some View {
ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) {
ScrollView { VStack(spacing: 20) {
//
Button { showCoverSheet = true } label: {
ZStack {
RoundedRectangle(cornerRadius: 14).fill(Color.zxFill004)
.overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1))
if let img = coverImage {
Image(uiImage: img).resizable().scaledToFill().frame(height: 140).clipShape(RoundedRectangle(cornerRadius: 14))
} else {
VStack(spacing: 8) {
Image(systemName: "photo.on.rectangle.angled").font(.system(size: 28)).foregroundColor(Color.zxF04)
Text("添加封面图").font(.system(size: 13, weight: .medium)).foregroundColor(Color.zxF04)
Text("从相册选择").font(.system(size: 11)).foregroundColor(Color.zxF03)
//
VStack(alignment: .leading, spacing: 8) {
Text("封面图").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035)
Button { showCoverSheet = true } label: {
ZStack {
RoundedRectangle(cornerRadius: 14).fill(Color.zxFill004)
.overlay(RoundedRectangle(cornerRadius: 14).stroke(style: StrokeStyle(lineWidth: 1.5, dash: [6, 4])).foregroundColor(Color.zxBorder01))
.frame(width: 120, height: 120)
if let img = coverImage {
Image(uiImage: img).resizable().scaledToFill().frame(width: 120, height: 120).clipShape(RoundedRectangle(cornerRadius: 14))
} else {
VStack(spacing: 6) {
Image(systemName: "camera.fill").font(.system(size: 22)).foregroundColor(Color.zxF04)
Text("上传").font(.system(size: 11)).foregroundColor(Color.zxF04)
}
}
if isUploadingCover { RoundedRectangle(cornerRadius: 14).fill(Color.black.opacity(0.4)).frame(width: 120, height: 120); ProgressView().tint(.white) }
}
if isUploadingCover { RoundedRectangle(cornerRadius: 14).fill(Color.black.opacity(0.4)); ProgressView().tint(.white) }
}
.frame(height: 140)
}
.disabled(isUploadingCover)
.confirmationDialog("封面图", isPresented: $showCoverSheet) {
Button("从相册选择") { showCoverPicker = true }
Button("取消", role: .cancel) {}
.disabled(isUploadingCover)
}
.frame(maxWidth: .infinity, alignment: .leading)
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 2) { Text("知识库名称").font(.system(size: 12, weight: .semibold)); Text("*").foregroundColor(.red) }.foregroundColor(Color.zxF035)
@ -78,6 +77,35 @@ struct CreateLibraryPage: View {
.onChange(of: coverPhotoItem) { _, item in
guard let item else { return }
Task { await uploadCover(item) }
}
.sheet(isPresented: $showCoverSheet) {
VStack(spacing: 0) {
RoundedRectangle(cornerRadius: 3).fill(Color.zxF03).frame(width: 36, height: 5).padding(.top, 12).padding(.bottom, 16)
Text("封面图").font(.system(size: 16, weight: .semibold)).foregroundColor(Color.zxF0).padding(.bottom, 20)
Button {
showCoverSheet = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { showCoverPicker = true }
} label: {
HStack(spacing: 12) {
Image(systemName: "photo.on.rectangle").font(.system(size: 20)).foregroundColor(Color.zxPrimary).frame(width: 40, height: 40).background(Color.zxPrimarySoft).clipShape(RoundedRectangle(cornerRadius: 10))
VStack(alignment: .leading, spacing: 2) {
Text("从相册选择").font(.system(size: 15, weight: .medium)).foregroundColor(Color.zxF0)
Text("选择一张图片作为封面").font(.system(size: 12)).foregroundColor(Color.zxF04)
}
Spacer()
Image(systemName: "chevron.right").font(.system(size: 14)).foregroundColor(Color.zxF03)
}
.padding(.horizontal, 16).padding(.vertical, 14)
.background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius: 14))
}
.foregroundColor(.primary)
.padding(.horizontal, 20)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.zxBg0)
.presentationDetents([.height(220)])
.presentationDragIndicator(.hidden)
}}
private func uploadCover(_ item: PhotosPickerItem) async {