191 lines
7.1 KiB
Swift
191 lines
7.1 KiB
Swift
//
|
||
// RoleFigureGenerateController.swift
|
||
// Crush
|
||
//
|
||
// Created by Leon on 2025/7/21.
|
||
//
|
||
|
||
import UIKit
|
||
import TZImagePickerController
|
||
import Combine
|
||
|
||
/// Step 4/4 首次生成封面专用,和编辑图片生成流程不一致
|
||
class RoleFigureGenerateController: CLViewController<RoleFigureGenerateView> {
|
||
|
||
weak var viewModel: RoleCreateViewModel!
|
||
|
||
var generatedBatchNoAction: ((String, String, String, String?) -> Void)?
|
||
|
||
// Data
|
||
@Published var referenceImage:UIImage?
|
||
private var subscriptions = Set<AnyCancellable>()
|
||
|
||
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
|
||
}
|
||
|
||
|
||
}
|