feat(ios): 封面图底部半屏抽屉弹窗 + 左侧正方形卡片
- 封面图有独立中文标签"封面图" - 120×120 正方形虚线框,左侧对齐 - 点击弹出底部半屏 sheet(height: 220) - sheet 内:从相册选择(带图标+描述+箭头) - 顶部有指示条(灰色胶囊) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
11c0fe42b7
commit
481f513b11
@ -12,29 +12,28 @@ struct CreateLibraryPage: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) {
|
ZStack { Color.zxBg0.ignoresSafeArea(); VStack(spacing: 0) {
|
||||||
ScrollView { VStack(spacing: 20) {
|
ScrollView { VStack(spacing: 20) {
|
||||||
// 封面卡片
|
// 封面图
|
||||||
Button { showCoverSheet = true } label: {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
ZStack {
|
Text("封面图").font(.system(size: 12, weight: .semibold)).foregroundColor(Color.zxF035)
|
||||||
RoundedRectangle(cornerRadius: 14).fill(Color.zxFill004)
|
Button { showCoverSheet = true } label: {
|
||||||
.overlay(RoundedRectangle(cornerRadius: 14).stroke(Color.zxBorder008, lineWidth: 1))
|
ZStack {
|
||||||
if let img = coverImage {
|
RoundedRectangle(cornerRadius: 14).fill(Color.zxFill004)
|
||||||
Image(uiImage: img).resizable().scaledToFill().frame(height: 140).clipShape(RoundedRectangle(cornerRadius: 14))
|
.overlay(RoundedRectangle(cornerRadius: 14).stroke(style: StrokeStyle(lineWidth: 1.5, dash: [6, 4])).foregroundColor(Color.zxBorder01))
|
||||||
} else {
|
.frame(width: 120, height: 120)
|
||||||
VStack(spacing: 8) {
|
if let img = coverImage {
|
||||||
Image(systemName: "photo.on.rectangle.angled").font(.system(size: 28)).foregroundColor(Color.zxF04)
|
Image(uiImage: img).resizable().scaledToFill().frame(width: 120, height: 120).clipShape(RoundedRectangle(cornerRadius: 14))
|
||||||
Text("添加封面图").font(.system(size: 13, weight: .medium)).foregroundColor(Color.zxF04)
|
} else {
|
||||||
Text("从相册选择").font(.system(size: 11)).foregroundColor(Color.zxF03)
|
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)
|
||||||
}
|
|
||||||
.disabled(isUploadingCover)
|
|
||||||
.confirmationDialog("封面图", isPresented: $showCoverSheet) {
|
|
||||||
Button("从相册选择") { showCoverPicker = true }
|
|
||||||
Button("取消", role: .cancel) {}
|
|
||||||
}
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
HStack(spacing: 2) { Text("知识库名称").font(.system(size: 12, weight: .semibold)); Text("*").foregroundColor(.red) }.foregroundColor(Color.zxF035)
|
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
|
.onChange(of: coverPhotoItem) { _, item in
|
||||||
guard let item else { return }
|
guard let item else { return }
|
||||||
Task { await uploadCover(item) }
|
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 {
|
private func uploadCover(_ item: PhotosPickerItem) async {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user