角色list数据展示
This commit is contained in:
parent
8f61a1e969
commit
5b52194cc3
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// RoleVoiceActorListApi.swift
|
||||||
|
// Visual_Novel_iOS
|
||||||
|
//
|
||||||
|
// Created by mh on 2025/11/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Moya
|
||||||
|
|
||||||
|
let RoleActorProvider = APIConfig.useMock && UserAPI.useMock
|
||||||
|
? MoyaProvider<RoleActorApi>(endpointClosure: myEndpointClosure, stubClosure: { target in
|
||||||
|
let data = target.sampleData
|
||||||
|
if(data.count > 0){
|
||||||
|
return .delayed(seconds: 0.5)
|
||||||
|
}else{
|
||||||
|
return .never
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: MoyaProvider<RoleActorApi>(requestClosure: myRequestClosure)
|
||||||
|
|
||||||
|
enum RoleActorApi {
|
||||||
|
static let useMock: Bool = false
|
||||||
|
|
||||||
|
case roleActor(params: [String: Any])
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RoleActorApi: TargetType {
|
||||||
|
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 .roleActor:
|
||||||
|
return "/tts/config/list"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var method: Moya.Method {
|
||||||
|
return .post
|
||||||
|
}
|
||||||
|
|
||||||
|
var task: Task {
|
||||||
|
var mParams = [String: Any]()
|
||||||
|
switch self {
|
||||||
|
case .roleActor(let params):
|
||||||
|
// 将传入的参数赋值给 mParams
|
||||||
|
mParams = params
|
||||||
|
}
|
||||||
|
return .requestParameters(parameters: mParams, encoding: JSONEncoding.default)
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers: [String : String]? {
|
||||||
|
return APIConfig.apiHeaders()
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleData: Data {
|
||||||
|
switch self {
|
||||||
|
case .roleActor:
|
||||||
|
return Data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -398,6 +398,11 @@ extension SessionController {
|
||||||
// let vc = ChatSettingListController()
|
// let vc = ChatSettingListController()
|
||||||
// vc.aiId = aiId
|
// vc.aiId = aiId
|
||||||
// navigationController?.pushViewController(vc, animated: true)
|
// navigationController?.pushViewController(vc, animated: true)
|
||||||
|
|
||||||
|
roleActorViewModel.loadRoleActor(language: "en") { model in
|
||||||
|
print(model)
|
||||||
|
}
|
||||||
|
|
||||||
UIView.animate(withDuration: 0.25) {
|
UIView.animate(withDuration: 0.25) {
|
||||||
self.swipeBgView.alpha = 1.0
|
self.swipeBgView.alpha = 1.0
|
||||||
self.swipeView.snp.updateConstraints { make in
|
self.swipeView.snp.updateConstraints { make in
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,11 @@ class SessionController: CLBaseViewController {
|
||||||
var swipeView: ChatSettingSwipeView!
|
var swipeView: ChatSettingSwipeView!
|
||||||
var swipeBgView: UIView!
|
var swipeBgView: UIView!
|
||||||
|
|
||||||
|
lazy var roleActorViewModel: RoleActorViewModel = {
|
||||||
|
let model = RoleActorViewModel()
|
||||||
|
return model
|
||||||
|
}()
|
||||||
|
|
||||||
// MARK: BottomViews
|
// MARK: BottomViews
|
||||||
var bottomViewsStackV : InputStackView!
|
var bottomViewsStackV : InputStackView!
|
||||||
var toolView: UIView!
|
var toolView: UIView!
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// RoleActorViewModel.swift
|
||||||
|
// Visual_Novel_iOS
|
||||||
|
//
|
||||||
|
// Created by mh on 2025/11/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct RoleActorRequest: Codable {
|
||||||
|
var language: String = ""
|
||||||
|
// 1:男性 2:女性 不传查所有
|
||||||
|
var gender: Int?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct RoleActorModel: Codable {
|
||||||
|
var total: Int = 0
|
||||||
|
var rows: [RoleActorItem] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoleActorItem: Codable {
|
||||||
|
var ttsId: Int?
|
||||||
|
var language: Int?
|
||||||
|
var desLanguage: String?
|
||||||
|
var gender: Int?
|
||||||
|
// 解锁方式 (付费、vip、公开)
|
||||||
|
var rules: Int?
|
||||||
|
var nameLanguage: String?
|
||||||
|
var headPortrait: String?
|
||||||
|
var displayAudio: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class RoleActorViewModel {
|
||||||
|
|
||||||
|
func loadRoleActor(language: String, gender: Int? = nil, completion: ((_ datas: RoleActorModel?) -> Void)?) {
|
||||||
|
var req = RoleActorRequest()
|
||||||
|
req.language = language
|
||||||
|
req.gender = gender
|
||||||
|
|
||||||
|
let params = req.toNonNilDictionary()
|
||||||
|
|
||||||
|
RoleActorProvider.request(.roleActor(params: params), modelType: RoleActorModel.self) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let model):
|
||||||
|
// 如果返回的是单个 RoleActorModel,将其包装成数组
|
||||||
|
if let model = model {
|
||||||
|
completion?(model)
|
||||||
|
} else {
|
||||||
|
completion?(nil)
|
||||||
|
}
|
||||||
|
case .failure(let failure):
|
||||||
|
dlog("⛔️ 加载声优列表失败: \(failure)")
|
||||||
|
completion?(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -217,7 +217,7 @@ extension ChatSettingSwipeView: UITableViewDelegate, UITableViewDataSource {
|
||||||
|
|
||||||
tableView.performBatchUpdates({
|
tableView.performBatchUpdates({
|
||||||
tableView.insertRows(at: [insertIndexPath], with: .fade)
|
tableView.insertRows(at: [insertIndexPath], with: .fade)
|
||||||
tableView.reloadRows(at: [indexPath], with: .none)
|
// tableView.reloadRows(at: [indexPath], with: .none)
|
||||||
}, completion: { [weak self] _ in
|
}, completion: { [weak self] _ in
|
||||||
// 在 cell 完全布局后,设置筛选器状态
|
// 在 cell 完全布局后,设置筛选器状态
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
@ -245,7 +245,7 @@ extension ChatSettingSwipeView: UITableViewDelegate, UITableViewDataSource {
|
||||||
|
|
||||||
tableView.performBatchUpdates({
|
tableView.performBatchUpdates({
|
||||||
tableView.deleteRows(at: [deleteIndexPath], with: .fade)
|
tableView.deleteRows(at: [deleteIndexPath], with: .fade)
|
||||||
tableView.reloadRows(at: [indexPath], with: .none)
|
// tableView.reloadRows(at: [indexPath], with: .none)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ class CLRoleCollectionCell: UICollectionViewCell {
|
||||||
bookImgView.sd_setImage(with: URL(string: item.sourceCoverImage ?? ""), placeholderImage: nil)
|
bookImgView.sd_setImage(with: URL(string: item.sourceCoverImage ?? ""), placeholderImage: nil)
|
||||||
tagLab.text = item.tags.compactMap { "#\($0.name)" }.joined(separator: "/")
|
tagLab.text = item.tags.compactMap { "#\($0.name)" }.joined(separator: "/")
|
||||||
sourceLab.text = item.score?.truncateString(places: 1)
|
sourceLab.text = item.score?.truncateString(places: 1)
|
||||||
self.bookBgImgView.isHidden = item.sourceType != .novel
|
self.readImgView.isHidden = item.sourceType != .novel
|
||||||
self.playImgView.isHidden = item.sourceType != .video
|
self.playImgView.isHidden = item.sourceType != .video
|
||||||
self.remindLab.text = item.sourceName
|
self.remindLab.text = item.sourceName
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ class RolesRootPageView: CLContainer {
|
||||||
var onRefresh: (() -> Void)?
|
var onRefresh: (() -> Void)?
|
||||||
var onLoadMore: (() -> Void)?
|
var onLoadMore: (() -> Void)?
|
||||||
|
|
||||||
var data: [RoleItem] = []
|
var data: [RoleItem] = [
|
||||||
|
// RoleItem(id: "1", name: "哈哈哈", coverImage: nil, sourceCoverImage: nil, sourceName: "社会", headPortrait: nil, score: 1, description: "sdhfdshfjsdfjdsfh", updateTime: nil, sourceId: nil, sourceType: .novel, commonCount: 1, tags: [])
|
||||||
|
]
|
||||||
var hasMoreData: Bool = true // 是否还有更多数据
|
var hasMoreData: Bool = true // 是否还有更多数据
|
||||||
|
|
||||||
// lazy var topView: CLTopHeaderView = {
|
// lazy var topView: CLTopHeaderView = {
|
||||||
|
|
@ -177,7 +179,7 @@ extension RolesRootPageView: UICollectionViewDelegate, UICollectionViewDataSourc
|
||||||
let maxHeight = lineHeight * CGFloat(maxLines)
|
let maxHeight = lineHeight * CGFloat(maxLines)
|
||||||
|
|
||||||
// 真实文本高度(不会超过 maxHeight)
|
// 真实文本高度(不会超过 maxHeight)
|
||||||
let textSize = (model.name ?? "").boundingRect(
|
let textSize = (model.description ?? "").boundingRect(
|
||||||
with: CGSize(width: itemWidth - 20, height: maxHeight), // 高度封顶
|
with: CGSize(width: itemWidth - 20, height: maxHeight), // 高度封顶
|
||||||
options: [.usesLineFragmentOrigin, .usesFontLeading],
|
options: [.usesLineFragmentOrigin, .usesFontLeading],
|
||||||
attributes: [.font: font],
|
attributes: [.font: font],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue