This commit is contained in:
anlicheng 2025-02-25 12:03:51 +08:00
parent cd34006635
commit 1ef90a8972
4 changed files with 86 additions and 74 deletions

View File

@ -61,13 +61,13 @@ struct API {
} }
static func getDateIndex<T: Codable>(as: T.Type) async -> APIResponse<T> { static func getDateIndex<T: Codable>(as: T.Type) async -> APIResponse<T> {
let request = URLRequest(url: URL(string: url + "date_index")!) let request = URLRequest(url: URL(string: baseUrl + "date_index")!)
return await doRequest(request: request, as: T.self) return await doRequest(request: request, as: T.self)
} }
static func getDramaDetail<T: Codable>(as: T.Type) async -> APIResponse<T> { static func getDramaDetail<T: Codable>(userId: Int, id: Int, as: T.Type) async -> APIResponse<T> {
let request = URLRequest(url: URL(string: url + "detail")!) let request = URLRequest(url: URL(string: baseUrl + "/api/detail?user_id=\(userId)&id=\(id)")!)
return await doRequest(request: request, as: T.self) return await doRequest(request: request, as: T.self)
} }

View File

@ -10,22 +10,15 @@ import Observation
@Observable @Observable
final class DetailModel { final class DetailModel {
struct VoiceActor: Codable { struct Episode: Codable, Identifiable {
let actor_id: Int let id = UUID().uuidString
let name: String
}
struct Episode: Codable {
let id: Int32
let name: String let name: String
let num_name: String
let thumb: String let thumb: String
let numName: String let play: String
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case id = "id" case name, num_name, thumb, play
case name = "name"
case thumb = "thumb"
case numName = "num_name"
} }
} }
@ -37,14 +30,51 @@ final class DetailModel {
struct DramaDetailResponse: Codable { struct DramaDetailResponse: Codable {
let name: String let name: String
let voice_actors: [VoiceActor] let summary: String
let status: Int let thumb: String
let status: [String]
let channels: [Channel] let channels: [Channel]
} }
//
struct DramaStatus {
struct DisplayConfig {
let name: String
let bgColor: Color
let fontColor: Color
}
let status: String
let config: DisplayConfig
init?(_ rawValue: String) {
switch rawValue {
case "first_row":
self.status = rawValue
self.config = DisplayConfig(name: "前排占位", bgColor: .black, fontColor: .white)
case "following":
self.status = rawValue
self.config = DisplayConfig(name: "追番", bgColor: .white, fontColor: Color(hex: "#333333"))
case "catching_up":
self.status = rawValue
self.config = DisplayConfig(name: "补番", bgColor: .black, fontColor: .white)
case "dropping":
self.status = rawValue
self.config = DisplayConfig(name: "弃番", bgColor: .black, fontColor: .white)
case "finished":
self.status = rawValue
self.config = DisplayConfig(name: "补完", bgColor: .black, fontColor: .white)
default:
return nil
}
}
}
var name: String = "" var name: String = ""
var voiceActors: [VoiceActor] = [] var summary: String = ""
var status: Int = 0 var thumb: String = ""
var statuses: [DramaStatus] = []
var channels: [Channel] = [] var channels: [Channel] = []
// channel // channel
@ -52,16 +82,21 @@ final class DetailModel {
var selectedEpisodes: [Episode] = [] var selectedEpisodes: [Episode] = []
@MainActor @MainActor
func loadData(dramaId: Int) async { func loadData(userId: Int, id: Int) async {
let response = await API.getDramaDetail(as: DramaDetailResponse.self) let response = await API.getDramaDetail(userId: userId, id: id, as: DramaDetailResponse.self)
switch response { switch response {
case .error(let code, let message): case .error(let code, let message):
print(code) print(code)
print(message) print(message)
case .result(let detail): case .result(let detail):
self.name = detail.name self.name = detail.name
self.voiceActors = detail.voice_actors self.statuses = detail.status.flatMap({ s in
self.status = detail.status if let status = DramaStatus(s) {
return [status]
} else {
return []
}
})
self.channels = detail.channels self.channels = detail.channels
self.selectedChannelIdx = 0 self.selectedChannelIdx = 0
@ -78,6 +113,7 @@ final class DetailModel {
struct DetailView: View { struct DetailView: View {
@State var detailModel = DetailModel() @State var detailModel = DetailModel()
let id: Int32
var body: some View { var body: some View {
VStack(alignment: .center) { VStack(alignment: .center) {
@ -88,6 +124,7 @@ struct DetailView: View {
.fontWeight(.bold) .fontWeight(.bold)
.foregroundColor(Color(hex: "#333333")) .foregroundColor(Color(hex: "#333333"))
/*
HStack(alignment: .center, spacing: 0) { HStack(alignment: .center, spacing: 0) {
ForEach(Array(detailModel.voiceActors.enumerated()), id: \.offset) { index, actor in ForEach(Array(detailModel.voiceActors.enumerated()), id: \.offset) { index, actor in
if index > 0 { if index > 0 {
@ -105,33 +142,16 @@ struct DetailView: View {
Spacer() Spacer()
} }
*/
} }
.padding([.top, .leading], 10) .padding([.top, .leading], 10)
.background(Color(hex: "#F2F2F2"), ignoresSafeAreaEdges: [.bottom]) .background(Color(hex: "#F2F2F2"), ignoresSafeAreaEdges: [.bottom])
HStack { HStack(alignment: .center, spacing: 10) {
Spacer() Spacer()
ForEach(detailModel.statuses, id: \.status) { status in
switch detailModel.status { FollowButtonView(title: status.config.name, bgColor: status.config.bgColor, fontColor: status.config.fontColor) {
case 0: print("call me follow button clicked")
FollowButtonView(title: "补完", bgColor: .black, fontColor: .white) {
}
case 1:
FollowButtonView(title: "追番", bgColor: .black, fontColor: .white) {
}
case 2:
FollowButtonView(title: "前排站位", bgColor: .black, fontColor: .white) {
}
case 3:
FollowButtonView(title: "弃番", bgColor: .black, fontColor: .white) {
}
default:
FollowButtonView(title: "追番", bgColor: .white, fontColor: Color(hex: "#333333")) {
} }
} }
} }
@ -206,8 +226,7 @@ struct DetailView: View {
} }
.frame(width: 370, alignment: .center) .frame(width: 370, alignment: .center)
.task { .task {
await detailModel.loadData(dramaId: 124) await detailModel.loadData(userId: 1, id: self.id)
print(UIScreen.main.bounds.width)
} }
} }
@ -244,5 +263,5 @@ extension DetailView {
} }
#Preview { #Preview {
DetailView() DetailView(id: 19625)
} }

View File

@ -338,7 +338,7 @@ extension IndexView {
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
NavigationLink(destination: DetailView()) { NavigationLink(destination: DetailView(id: dramaItem.id)) {
Text(dramaItem.title) Text(dramaItem.title)
.font(.system(size: 20)) .font(.system(size: 20))
.foregroundColor(Color(hex: "#333333")) .foregroundColor(Color(hex: "#333333"))

View File

@ -10,22 +10,15 @@ import Observation
@Observable @Observable
final class ListModel { final class ListModel {
struct VoiceActor: Codable { struct Episode: Codable, Identifiable {
let actor_id: Int let id = UUID().uuidString
let name: String
}
struct Episode: Codable {
let id: Int32
let name: String let name: String
let num_name: String
let thumb: String let thumb: String
let numName: String let play: String
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case id = "id" case name, num_name, thumb, play
case name = "name"
case thumb = "thumb"
case numName = "num_name"
} }
} }
@ -37,14 +30,15 @@ final class ListModel {
struct DramaDetailResponse: Codable { struct DramaDetailResponse: Codable {
let name: String let name: String
let voice_actors: [VoiceActor] let summary: String
let status: Int let thumb: String
let status: [String]
let channels: [Channel] let channels: [Channel]
} }
var name: String = "" var name: String = ""
var voiceActors: [VoiceActor] = [] var summary: String = ""
var status: Int = 0 var thumb: String = ""
var channels: [Channel] = [] var channels: [Channel] = []
// channel // channel
@ -52,16 +46,14 @@ final class ListModel {
var selectedEpisodes: [Episode] = [] var selectedEpisodes: [Episode] = []
@MainActor @MainActor
func loadData(dramaId: Int) async { func loadData(userId: Int, id: Int) async {
let response = await API.getDramaDetail(as: DramaDetailResponse.self) let response = await API.getDramaDetail(userId: userId, id: id, as: DramaDetailResponse.self)
switch response { switch response {
case .error(let code, let message): case .error(let code, let message):
print(code) print(code)
print(message) print(message)
case .result(let detail): case .result(let detail):
self.name = detail.name self.name = detail.name
self.voiceActors = detail.voice_actors
self.status = detail.status
self.channels = detail.channels self.channels = detail.channels
self.selectedChannelIdx = 0 self.selectedChannelIdx = 0
@ -78,7 +70,8 @@ final class ListModel {
struct ListView: View { struct ListView: View {
@Environment(\.presentationMode) var presentationMode @Environment(\.presentationMode) var presentationMode
@State var detailModel = DetailModel() @State var detailModel = ListModel()
let id: Int
var body: some View { var body: some View {
VStack(alignment: .center, spacing: 20) { VStack(alignment: .center, spacing: 20) {
@ -117,7 +110,7 @@ struct ListView: View {
// //
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .center, spacing: 15) { VStack(alignment: .center, spacing: 15) {
ForEach(detailModel.selectedEpisodes, id: \.id) { episode in ForEach(detailModel.selectedEpisodes) { episode in
HStack(alignment: .center) { HStack(alignment: .center) {
AsyncImage(url: URL(string: episode.thumb)) { image in AsyncImage(url: URL(string: episode.thumb)) { image in
image.resizable() image.resizable()
@ -127,7 +120,7 @@ struct ListView: View {
.frame(width: 90, height: 60) .frame(width: 90, height: 60)
VStack(alignment: .leading, spacing: 20) { VStack(alignment: .leading, spacing: 20) {
Text(episode.numName) Text(episode.num_name)
.font(.system(size: 12)) .font(.system(size: 12))
.foregroundColor(Color(hex: "#333333")) .foregroundColor(Color(hex: "#333333"))
@ -165,12 +158,12 @@ struct ListView: View {
} }
.frame(width: 370, alignment: .center) .frame(width: 370, alignment: .center)
.task { .task {
await detailModel.loadData(dramaId: 124) await detailModel.loadData(userId: 1, id: self.id)
} }
} }
} }
#Preview { #Preview {
ListView() ListView(id: 19625)
} }