拆分宣传页视图并扩充 Mock 数据,合作订单支持获客员备注名并修复线索图片网格尺寸。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-02 17:43:04 +08:00
parent 1b1e93b9ca
commit 328c4321f4
41 changed files with 2529 additions and 1436 deletions

View File

@ -16,6 +16,9 @@ struct CooperationAcquirerView: View {
@Environment(\.openURL) private var openURL
@StateObject private var viewModel = CooperationAcquirerViewModel()
@State private var showScanner = false
@State private var showRemarkAlert = false
@State private var remarkEditingAcquirer: CooperativeSaler?
@State private var remarkDraft = ""
let onBind: (Int) -> Void
var body: some View {
@ -31,6 +34,10 @@ struct CooperationAcquirerView: View {
ForEach(viewModel.acquirers, id: \.displayId) { acquirer in
CooperativeSalerCard(acquirer: acquirer) { phone in
dialPhone(phone)
} onEditRemark: {
remarkEditingAcquirer = acquirer
remarkDraft = acquirer.photogRemarkName
showRemarkAlert = true
}
}
}
@ -73,6 +80,44 @@ struct CooperationAcquirerView: View {
.task {
await reload(showLoading: true)
}
.alert("修改备注", isPresented: $showRemarkAlert) {
TextField("备注名", text: $remarkDraft)
Button("取消", role: .cancel) {
remarkEditingAcquirer = nil
}
Button("保存") {
// alert dismiss state
guard let acquirer = remarkEditingAcquirer else { return }
let saleUserId = acquirer.saleUserId
let draft = remarkDraft
showRemarkAlert = false
remarkEditingAcquirer = nil
Task {
await saveRemark(saleUserId: saleUserId, draft: draft)
}
}
} message: {
if let acquirer = remarkEditingAcquirer {
Text("\(acquirer.salerName.cooperationNonEmptyOrDefault(acquirer.name)) 设置备注名")
}
}
}
///
private func saveRemark(saleUserId: Int, draft: String) async {
guard saleUserId > 0 else { return }
await globalLoading.withOptionalLoading(true) {
do {
try await viewModel.updateRemark(
saleUserId: saleUserId,
remark: draft,
api: cooperationOrderAPI
)
toastCenter.show("备注已保存")
} catch {
toastCenter.show(error.localizedDescription)
}
}
}
private func reload(showLoading: Bool) async {

View File

@ -218,26 +218,37 @@ struct ReferralLeadImageGrid: View {
} else {
HStack(spacing: 8) {
ForEach(0..<3, id: \.self) { index in
if index < images.count, let url = URL(string: images[index]) {
imageCell(at: index)
}
}
}
}
/// 1:1 Kingfisher
@ViewBuilder
private func imageCell(at index: Int) -> some View {
Group {
if index < images.count, let url = URL(string: images[index]) {
RoundedRectangle(cornerRadius: 6)
.fill(CooperationOrderColors.imagePlaceholderBg)
.overlay {
KFImage(url)
.placeholder { CooperationOrderColors.imagePlaceholderBg }
.resizable()
.scaledToFill()
.frame(maxWidth: .infinity)
.aspectRatio(1, contentMode: .fit)
.clipShape(RoundedRectangle(cornerRadius: 6))
.contentShape(Rectangle())
.onTapGesture {
onImageTap(images, index)
}
} else {
Color.clear
.frame(maxWidth: .infinity)
.aspectRatio(1, contentMode: .fit)
}
}
} else {
Color.clear
}
}
.aspectRatio(1, contentMode: .fit)
.frame(maxWidth: .infinity)
.clipShape(RoundedRectangle(cornerRadius: 6))
.contentShape(Rectangle())
.onTapGesture {
guard index < images.count else { return }
onImageTap(images, index)
}
}
}
@ -290,35 +301,46 @@ struct AcquisitionOrderCard: View {
struct CooperativeSalerCard: View {
let acquirer: CooperativeSaler
let onDial: (String) -> Void
let onEditRemark: () -> Void
var body: some View {
HStack(alignment: .center, spacing: 0) {
Image(systemName: "person.fill")
.font(.system(size: 20))
.foregroundStyle(CooperationOrderColors.primary)
.padding(10)
.background(CooperationOrderColors.primary.opacity(0.08), in: RoundedRectangle(cornerRadius: 8))
ZStack(alignment: .topTrailing) {
HStack(alignment: .center, spacing: 0) {
Image(systemName: "person.fill")
.font(.system(size: 20))
.foregroundStyle(CooperationOrderColors.primary)
.padding(10)
.background(CooperationOrderColors.primary.opacity(0.08), in: RoundedRectangle(cornerRadius: 8))
VStack(alignment: .leading, spacing: 8) {
AcquirerInfoRow(
label: "获客员名称",
value: acquirer.displayName.isEmpty ? "" : acquirer.displayName,
emphasize: true
)
AcquirerPhoneInfoRow(phone: acquirer.displayPhone, onDial: onDial)
AcquirerInfoRow(
label: "绑定时间",
value: acquirer.displayBindTime.isEmpty ? "" : acquirer.displayBindTime
)
VStack(alignment: .leading, spacing: 8) {
AcquirerInfoRow(
label: "获客员名称",
value: acquirer.displayName.isEmpty ? "" : acquirer.displayName,
emphasize: true
)
AcquirerPhoneInfoRow(phone: acquirer.displayPhone, onDial: onDial)
AcquirerInfoRow(
label: "绑定时间",
value: acquirer.displayBindTime.isEmpty ? "" : acquirer.displayBindTime
)
}
.padding(.leading, 12)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.leading, 12)
.padding(.horizontal, 14)
.padding(.vertical, 16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.white, in: RoundedRectangle(cornerRadius: 10))
.shadow(color: Color.black.opacity(0.06), radius: 1, x: 0, y: 1)
Button("修改备注") {
onEditRemark()
}
.font(.system(size: 13))
.foregroundStyle(CooperationOrderColors.primary)
.padding(.top, 16)
.padding(.trailing, 14)
}
.padding(.horizontal, 14)
.padding(.vertical, 16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.white, in: RoundedRectangle(cornerRadius: 10))
.shadow(color: Color.black.opacity(0.06), radius: 1, x: 0, y: 1)
}
}