// // RoleFigureGenerateController.swift // Crush // // Created by Leon on 2025/7/21. // import UIKit import TZImagePickerController import Combine /// Step 4/4 首次生成封面专用,和编辑图片生成流程不一致 class RoleFigureGenerateController: CLViewController { weak var viewModel: RoleCreateViewModel! var generatedBatchNoAction: ((String, String, String, String?) -> Void)? // Data @Published var referenceImage:UIImage? private var subscriptions = Set() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. setupViews() setupDats() setupEvents() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {[weak self] in self?.container.scrollSelectedShow() } } private func setupViews() { } private func setupDats() { } private func setupEvents() { container.bottomButton.addTarget(self, action: #selector(bottomButtonTapped), for: .touchUpInside) container.referenceButton.addTarget(self, action: #selector(referenceButtonTapped), for: .touchUpInside) container.generate1Button.addTarget(self, action: #selector(tapAIGenerated), for: .touchUpInside) container.referenceButton.closeAction = {[weak self] _ in self?.referenceImage = nil } $referenceImage.sink {[weak self] image in self?.container.referenceButton.bindSuccessImage(image) }.store(in: &subscriptions) if let code = viewModel.requestParams.aiUserExt?.imageStyleCode, let desc = viewModel.requestParams.aiUserExt?.imageDesc{ container.figureDescriptionContent = desc container.selectStyleId = code }else if viewModel.editAIInfo != nil{ // 编辑模式恢复 restoreEditInfo(aiInfo: viewModel.editAIInfo) } } private func restoreEditInfo(aiInfo: AIUserModel?) { guard let info = aiInfo else { return } container.figureDescriptionContent = info.aiUserExt?.imageDesc ?? "" container.selectStyleId = info.aiUserExt?.imageStyleCode ?? "" container.selectStylePrompt = info.aiUserExt?.imageStyleDict?.prompt ?? "" } // MARK: - Action @objc private func bottomButtonTapped() { print("bottomButtonTapped") var params = viewModel.requestParams.toPartialDictionary(keys: ["sex", "birthday"]) //[String:Any]() // imageStylePrompt 形象风格提示词(预设的几种) let imageStylePrompt = container.selectStylePrompt let imageStyleCode = container.selectStyleId params.updateValue(imageStylePrompt, forKey: "imageStylePrompt") viewModel.requestParams.aiUserExt?.imageStyleCode = imageStyleCode // content:用户形象描述 or 生成的 let description = container.descriptionTextView.textView.text.trimmed params.updateValue(description, forKey: "content") viewModel.requestParams.aiUserExt?.imageDesc = description // imageReferenceUrl, 形象参考base64 var referenceBase64 = "" if let img = referenceImage { referenceBase64 = img.jpegBase64String(compressionQuality: 0.8)! params.updateValue(referenceBase64, forKey: "imageReferenceUrl") } if viewModel.editAIInfo != nil{ params.updateValue(false, forKey: "hl") } params.updateValue(AIImageGenerateType.CREATE_AI_IMAGE.rawValue, forKey: "type") Hud.showIndicator() AICowProvider.request(.imageGenerateCreateTask(params: params), modelType: AIUserImageTaskCreateResponse.self) {[weak self] result in Hud.hideIndicator() switch result { case .success(let success): if let response = success, let batchNo = response.batchNo{ self?.generatedBatchNoAction?(batchNo, imageStyleCode, description, referenceBase64) self?.viewModel.batchNo = batchNo self?.navigationController?.popToViewControllerType(type: RolePublishController.self) } case .failure(let failure): dlog(failure) } } } @objc private func tapAIGenerated(){ if container.figureDescriptionContent.count > 0{ let alert = Alert(title: "内容覆盖", text: "AI创建的内容会覆盖你已经填写的内容,请确认是否继续?") let action1 = AlertAction(title: "继续", actionStyle: .confirm) {[weak self] in self?.doGenerateAlbumDesc() } let action2 = AlertAction(title: "Cancel", actionStyle: .cancel) alert.addAction(action1) alert.addAction(action2) alert.show() }else{ doGenerateAlbumDesc() } } private func doGenerateAlbumDesc(){ var params = viewModel.requestParams.toPartialDictionary(keys: ["nickname", "sex", "birthday", "characterCode", "tagCode", "introduction"]) /// 形象描述 // 新需求: 总是覆盖 params.updateValue("GEN_AI_IMAGE_DESC_BY_NON", forKey: "ptType") if container.figureDescriptionContent.count > 0{ params.updateValue(container.figureDescriptionContent, forKey: "content") } Hud.showIndicator() AICowProvider.request(.aiContentGenerate(params: params), modelType: AIUserContentGenResponse.self) {[weak self] result in Hud.hideIndicator() switch result { case .success(let success): if let content = success?.content{ self?.container.figureDescriptionAIGenerated = content } case .failure: return } } } @objc private func referenceButtonTapped() { guard let picker = ImagePicker(maxImagesCount: 1, delegate: self) else { return } picker.allowPickingGif = false // picker.allowCrop = true // picker.allowPreview = true picker.showSelectBtn = false picker.needCircleCrop = true picker.cropRect = CGRect(origin: .init(x: 0, y: 0), size: CGSize(width: UIScreen.width, height: UIScreen.height)) picker.circleCropRadius = Int((UIScreen.width - 37*2) * 0.5) present(picker, animated: true, completion: nil) } } extension RoleFigureGenerateController:TZImagePickerControllerDelegate{ func imagePickerController(_: TZImagePickerController!, didFinishPickingPhotos photos: [UIImage]!, sourceAssets _: [Any]!, isSelectOriginalPhoto _: Bool, infos _: [[AnyHashable: Any]]!) { guard let img = photos.first else { return } referenceImage = img } }