角色列表数据请求

This commit is contained in:
mh 2025-11-06 19:27:24 +08:00
parent 2d4c80e084
commit 1f79e82668
8 changed files with 243 additions and 72 deletions

View File

@ -437,6 +437,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_TEAM = 6GS5RC7C89;
@ -460,8 +461,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.personal.ChinaTravel;
PRODUCT_BUNDLE_IDENTIFIER = com.person.ChinaTravel;
PRODUCT_NAME = Visual_Novel_iOSLevel;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = CLPRODUCT;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Visual_Novel_iOS/CL-Bridging-Header.h";
@ -550,6 +552,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_TEAM = 6GS5RC7C89;
@ -573,8 +576,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.personal.ChinaTravel;
PRODUCT_BUNDLE_IDENTIFIER = com.person.ChinaTravel;
PRODUCT_NAME = Visual_Novel_iOSLevel;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = CLAPPSTORE;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Visual_Novel_iOS/CL-Bridging-Header.h";
@ -607,6 +611,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_TEAM = 6GS5RC7C89;
@ -630,8 +635,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.personal.ChinaTravel;
PRODUCT_BUNDLE_IDENTIFIER = com.person.ChinaTravel;
PRODUCT_NAME = Visual_Novel_iOSLevel;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Visual_Novel_iOS/CL-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@ -645,6 +651,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
DEVELOPMENT_TEAM = 6GS5RC7C89;
@ -668,8 +675,9 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.personal.ChinaTravel;
PRODUCT_BUNDLE_IDENTIFIER = com.person.ChinaTravel;
PRODUCT_NAME = Visual_Novel_iOSLevel;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Visual_Novel_iOS/CL-Bridging-Header.h";
SWIFT_VERSION = 5.0;

View File

@ -22,7 +22,15 @@
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSExceptionDomains</key>
<dict/>
<dict>
<key>54.223.196.180</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
<key>UIAppFonts</key>
<array>

View File

@ -43,18 +43,18 @@ struct APIConfig {
static func apiHeaders() -> [String: String]? {
var updatHeaders = headers
//
// let platform = "IOS" // _\(Bundle.appVersion)
// updatHeaders?.updateValue(platform, forKey: "platform")
let platform = "IOS" // _\(Bundle.appVersion)
updatHeaders?.updateValue(platform, forKey: "platform")
// let tokenNow = UserCore.shared.token
// if tokenNow.count > 0 {
// updatHeaders?.updateValue(tokenNow, forKey: "AUTH_TK")
// }
let tokenNow = UserCore.shared.token
if tokenNow.count > 0 {
updatHeaders?.updateValue(tokenNow, forKey: "AUTH_TK")
}
// updatHeaders?.updateValue("\(versionNum)", forKey: "versionNum")
updatHeaders?.updateValue("\(versionNum)", forKey: "versionNum")
updatHeaders?.updateValue(UIDevice.UUID, forKey: "AUTH_DID")
// updatHeaders?.updateValue(UIDevice.UUID, forKey: "AUTH_DID")
/*
if let lan = Languages.preferedLans.first {
updatHeaders?.updateValue(lan.rawValue, forKey: "accept-language")
@ -106,4 +106,9 @@ struct APIConfig {
static var pigeon: String{
return "https://test-pigeon.crushlevel.ai"
}
static var role: String {
// URL
return "http://54.223.196.180:8091"
}
}

View File

@ -128,11 +128,14 @@ public enum ServiceErrorEnum: String, Codable {
// ResponseData API
struct ResponseData<T: Codable>: Codable {
/// OK or ERROR
let status: String?
let errorCode: ServiceErrorEnum?
let errorMsg: String?
let content: T?
let traceId : String?
// let status: String?
// let errorCode: ServiceErrorEnum?
// let errorMsg: String?
// let content: T?
// let traceId : String?
let code: Int?
let message: String?
let data: T?
}
class ResponseContentPageData<T: Codable>: Codable{
@ -213,58 +216,58 @@ extension MoyaProvider {
dlog("👉⭐️\(target.path)⭐️ response:\n\(jsonString)")
}
let status = data.status
let code = data.errorCode
let msg = data.errorMsg
// let status = data.status
// let code = data.errorCode
// let msg = data.errorMsg
if (status ?? "") == "OK" {
let model = data.content
if (data.code ?? 0) == 200 {
let model = data.data
completion(.success(model))
} else {
var toastMsg = autoShowErrMsg
if code == .tokenExpired || code == .tokenIllegal || code == .accountIsFrozen || code == .sign_usernotexist || code == .sign_usernotLoggedIn || code == .sign_userLoginclientNotExist || code == .sign_userNotAuthorizedClient {
//
UserCore.shared.logout()
if let Vc = UIWindow.getTopViewController(), (Vc is CLLoginMainController || Vc is PersonalInformationFillController) {
// do nothing.
} else {
// AppRouter.goBackRootController(jumpIndex: .home) {
// NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
// var toastMsg = autoShowErrMsg
//
// if code == .tokenExpired || code == .tokenIllegal || code == .accountIsFrozen || code == .sign_usernotexist || code == .sign_usernotLoggedIn || code == .sign_userLoginclientNotExist || code == .sign_userNotAuthorizedClient {
// //
// UserCore.shared.logout()
//
// if let Vc = UIWindow.getTopViewController(), (Vc is CLLoginMainController || Vc is PersonalInformationFillController) {
// // do nothing.
// } else {
//// AppRouter.goBackRootController(jumpIndex: .home) {
//// NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
//// }
// NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
// }
// } else if code == .newAccount {
// // ToastMsg
// toastMsg = false
// } else if code == .insufficentCoin {
// //
// // refresh wallet
// toastMsg = false
//
// var handled = false
// if let cow = target as? AICowAPI{
// switch cow{
// case .voiceCallOperate, .voiceAsr2, .voiceTts:
// IMAIViewModel.shared.showChatModelInsufficentCoinSheet()
// handled = true
// default:
// break
// }
NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
}
} else if code == .newAccount {
// ToastMsg
toastMsg = false
} else if code == .insufficentCoin {
//
// refresh wallet
toastMsg = false
var handled = false
if let cow = target as? AICowAPI{
switch cow{
case .voiceCallOperate, .voiceAsr2, .voiceTts:
IMAIViewModel.shared.showChatModelInsufficentCoinSheet()
handled = true
default:
break
}
}
if handled == false{
// Sheet
CLPurchase.shared.showIAPBuyCoinSheet()
}
}
if toastMsg, let msgUnpack = msg, msgUnpack.count > 0 {
UIWindow.getTopDisplayWindow()?.makeToast(msgUnpack)
}
dlog("error: code = \(code ?? .common), msg = \(data.errorMsg ?? "业务状态失败")")
completion(.failure(.serviceError(code: code, msg: msg)))
// }
// if handled == false{
// // Sheet
// CLPurchase.shared.showIAPBuyCoinSheet()
// }
// }
//
// if toastMsg, let msgUnpack = msg, msgUnpack.count > 0 {
// UIWindow.getTopDisplayWindow()?.makeToast(msgUnpack)
// }
//
// dlog("error: code = \(code ?? .common), msg = \(data.errorMsg ?? "")")
// completion(.failure(.serviceError(code: code, msg: msg)))
}
} catch {

View File

@ -0,0 +1,69 @@
//
// RoleApi.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/11/6.
//
import Moya
let RoleProvider = APIConfig.useMock && UserAPI.useMock
? MoyaProvider<RoleAPI>(endpointClosure: myEndpointClosure, stubClosure: { target in
let data = target.sampleData
if(data.count > 0){
return .delayed(seconds: 0.5)
}else{
return .never
}
})
: MoyaProvider<RoleAPI>(requestClosure: myRequestClosure)
enum RoleAPI {
static let useMock: Bool = false
//
case characterList(params: [String: Any])
}
extension RoleAPI: TargetType {
var method: Moya.Method {
return .post
}
var task: Task {
var mParams = [String: Any]()
switch self {
case .characterList(let params):
// mParams
mParams = params
}
return .requestParameters(parameters: mParams, encoding: JSONEncoding.default)
}
var headers: [String : String]? {
return APIConfig.apiHeaders()
}
var baseURL: URL {
// URL
guard let url = URL(string: APIConfig.role) else {
fatalError("Invalid baseURL: \(APIConfig.role)")
}
return url
}
var path: String {
switch self {
case .characterList:
return "/character/list"
}
}
var sampleData: Data {
switch self {
case .characterList:
return Data()
}
}
}

View File

@ -0,0 +1,64 @@
//
// ChatRoleViewModel.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/11/6.
//
import Foundation
import CodableWrappers
// request
struct RoleListRequest: Codable {
var index = 1
var limit = 20
var name: String = ""
var sourceId = 0
var tagId: Int?
}
// model
struct RoleListModel: Codable {
var total: Int = 0
var index: Int = -1
var rows: [RoleItem] = []
}
struct RoleItem: Codable {
var id: Int = 0
var name: String = ""
var coverImage: String = ""
var updateTime: String = ""
var sourceId: Int = 0
}
class ChatRoleViewModel {
func loadRoles(index: Int, limit: Int = 20, name: String = "", sourceId: Int = -1, tagId: Int? = nil, completion: ((_ datas: [RoleListModel]?) -> Void)?) {
var req = RoleListRequest()
req.index = index
req.limit = limit
req.name = name
req.sourceId = sourceId
req.tagId = tagId
let params = req.toNonNilDictionary()
// API RoleListModel
//
RoleProvider.request(.characterList(params: params), modelType: RoleListModel.self) { result in
switch result {
case .success(let model):
// RoleListModel
if let model = model {
completion?([model])
} else {
completion?(nil)
}
case .failure(let failure):
dlog("⛔️ 加载角色列表失败: \(failure)")
completion?(nil)
}
}
}
}

View File

@ -189,11 +189,6 @@ extension ChatSettingSwipeView {
extension ChatSettingSwipeView: UITableViewDelegate, UITableViewDataSource {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// tableView
// contentInset
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let imageRow = rows[indexPath.section][indexPath.row] as? ImageRow,
imageRow.showArrow else { return }

View File

@ -12,6 +12,8 @@ import Combine
class RolesRootPageController: CLTabRootController<RolesRootPageView> {
private var cancellables = Set<AnyCancellable>()
var page: Int = 1
var viewModel: ChatRoleViewModel = ChatRoleViewModel()
override func viewDidLoad() {
super.viewDidLoad()
@ -29,6 +31,11 @@ class RolesRootPageController: CLTabRootController<RolesRootPageView> {
setupEvent()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadData()
}
private func setupViews() {
navigationView.bgView.alpha = 0
navigationView.setupBgViewToStatusBarHeight()
@ -44,6 +51,18 @@ class RolesRootPageController: CLTabRootController<RolesRootPageView> {
.store(in: &cancellables)
}
func loadData() {
// if page == 1{
//// loadedAiIds.removeAll()
// }
viewModel.loadRoles(index: page) { datas in
print(datas)
print("11111")
}
}
//
private func handleJump(_ target: JumpTarget) {
switch target {