Initial commit: suixinkan_ios UIKit rewrite project.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 14:33:31 +08:00
commit 9edf993432
297 changed files with 47151 additions and 0 deletions

View File

@ -0,0 +1,336 @@
//
// ScenicPermissionModels.swift
// suixinkan
//
// Created by Codex on 2026/6/23.
//
import Foundation
///
struct ScenicAreaNode: Decodable, Equatable, Identifiable {
let id: String
let code: String
let name: String
let children: [ScenicAreaNode]
enum CodingKeys: String, CodingKey {
case id
case code
case name
case children
}
///
init(id: String, code: String = "", name: String, children: [ScenicAreaNode] = []) {
self.id = id
self.code = code
self.name = name
self.children = children
}
/// id/code
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
code = try container.decodeLossyString(forKey: .code)
let rawId = try container.decodeLossyString(forKey: .id).trimmingCharacters(in: .whitespacesAndNewlines)
id = rawId.isEmpty ? code : rawId
name = try container.decodeLossyString(forKey: .name)
children = try container.decodeIfPresent([ScenicAreaNode].self, forKey: .children) ?? []
}
}
///
struct ScenicApplicationPendingsResponse: Decodable, Equatable {
let items: [ScenicApplicationPendingResponse]
enum CodingKeys: String, CodingKey {
case items
case list
case data
}
///
init(items: [ScenicApplicationPendingResponse] = []) {
self.items = items
}
/// items/list/data
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
items = try container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .items)
?? container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .list)
?? container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .data)
?? []
}
}
///
struct ScenicApplicationPendingResponse: Decodable, Equatable, Identifiable {
let id: Int
let code: String
let scenicId: Int
let scenicName: String
let scenicImages: String
let scenicProvince: String
let scenicCity: String
let coopType: Int
let remark: String?
let status: Int
let rejectReason: String?
let auditedBy: String?
let auditedAt: String?
let auditNote: String?
let createdAt: String
enum CodingKeys: String, CodingKey {
case id
case code
case scenicId = "scenic_id"
case scenicName = "scenic_name"
case scenicImages = "scenic_images"
case scenicProvince = "scenic_province"
case scenicCity = "scenic_city"
case coopType = "coop_type"
case remark
case status
case rejectReason = "reject_reason"
case auditedBy = "audited_by"
case auditedAt = "audited_at"
case auditNote = "audit_note"
case createdAt = "created_at"
}
///
init(
id: Int,
code: String = "",
scenicId: Int = 0,
scenicName: String,
scenicImages: String = "",
scenicProvince: String = "",
scenicCity: String = "",
coopType: Int = 1,
remark: String? = nil,
status: Int = 1,
rejectReason: String? = nil,
auditedBy: String? = nil,
auditedAt: String? = nil,
auditNote: String? = nil,
createdAt: String = ""
) {
self.id = id
self.code = code
self.scenicId = scenicId
self.scenicName = scenicName
self.scenicImages = scenicImages
self.scenicProvince = scenicProvince
self.scenicCity = scenicCity
self.coopType = coopType
self.remark = remark
self.status = status
self.rejectReason = rejectReason
self.auditedBy = auditedBy
self.auditedAt = auditedAt
self.auditNote = auditNote
self.createdAt = createdAt
}
///
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
code = try container.decodeLossyString(forKey: .code)
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
scenicName = try container.decodeLossyString(forKey: .scenicName)
if let images = try? container.decode([String].self, forKey: .scenicImages) {
scenicImages = images.joined(separator: ",")
} else {
scenicImages = try container.decodeLossyString(forKey: .scenicImages)
}
scenicProvince = try container.decodeLossyString(forKey: .scenicProvince)
scenicCity = try container.decodeLossyString(forKey: .scenicCity)
coopType = try container.decodeLossyInt(forKey: .coopType) ?? 1
remark = try? container.decodeIfPresent(String.self, forKey: .remark)
status = try container.decodeLossyInt(forKey: .status) ?? 0
rejectReason = try? container.decodeIfPresent(String.self, forKey: .rejectReason)
auditedBy = try? container.decodeIfPresent(String.self, forKey: .auditedBy)
auditedAt = try? container.decodeIfPresent(String.self, forKey: .auditedAt)
auditNote = try? container.decodeIfPresent(String.self, forKey: .auditNote)
createdAt = try container.decodeLossyString(forKey: .createdAt)
}
}
///
struct ScenicApplicationSubmitRequest: Encodable, Equatable {
let scenicName: String?
let scenicImages: [String]?
let scenicProvince: String
let scenicCity: String
let coopType: Int
let remark: String
let scenicId: Int
enum CodingKeys: String, CodingKey {
case scenicName = "scenic_name"
case scenicImages = "scenic_images"
case scenicProvince = "scenic_province"
case scenicCity = "scenic_city"
case coopType = "coop_type"
case remark
case scenicId = "scenic_id"
}
}
/// /
struct RoleApplyPendingResponse: Decodable, Equatable, Hashable, Identifiable {
let id: Int
let code: String
let roleId: Int
let roleName: String
let scenicList: [RoleApplyScenicItem]
let status: Int
let statusLabel: String
let createdAt: String
let auditedBy: String?
let auditedAt: String?
let auditNote: String?
enum CodingKeys: String, CodingKey {
case id
case code
case roleId = "role_id"
case roleName = "role_name"
case scenicList = "scenic_list"
case status
case statusLabel = "status_label"
case createdAt = "created_at"
case auditedBy = "audited_by"
case auditedAt = "audited_at"
case auditNote = "audit_note"
}
///
init(
id: Int,
code: String = "",
roleId: Int,
roleName: String,
scenicList: [RoleApplyScenicItem] = [],
status: Int = 1,
statusLabel: String = "审核中",
createdAt: String = "",
auditedBy: String? = nil,
auditedAt: String? = nil,
auditNote: String? = nil
) {
self.id = id
self.code = code
self.roleId = roleId
self.roleName = roleName
self.scenicList = scenicList
self.status = status
self.statusLabel = statusLabel
self.createdAt = createdAt
self.auditedBy = auditedBy
self.auditedAt = auditedAt
self.auditNote = auditNote
}
///
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
code = try container.decodeLossyString(forKey: .code)
roleId = try container.decodeLossyInt(forKey: .roleId) ?? 0
roleName = try container.decodeLossyString(forKey: .roleName)
scenicList = try container.decodeIfPresent([RoleApplyScenicItem].self, forKey: .scenicList) ?? []
status = try container.decodeLossyInt(forKey: .status) ?? 0
statusLabel = try container.decodeLossyString(forKey: .statusLabel)
createdAt = try container.decodeLossyString(forKey: .createdAt)
auditedBy = try? container.decodeIfPresent(String.self, forKey: .auditedBy)
auditedAt = try? container.decodeIfPresent(String.self, forKey: .auditedAt)
auditNote = try? container.decodeIfPresent(String.self, forKey: .auditNote)
}
}
///
struct RoleApplyScenicItem: Decodable, Equatable, Hashable, Identifiable {
let id: Int
let name: String
enum CodingKeys: String, CodingKey {
case id
case name
}
///
init(id: Int, name: String) {
self.id = id
self.name = name
}
/// ID
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
name = try container.decodeLossyString(forKey: .name)
}
}
///
struct RoleApplySubmitRequest: Encodable, Equatable {
let scenicId: [Int]
let roleId: Int
enum CodingKeys: String, CodingKey {
case scenicId = "scenic_id"
case roleId = "role_id"
}
}
///
struct ScenicApplicationUploadPlaceholder: Encodable, Equatable {
let fileName: String
let fileType: String
let fileSize: Int64
enum CodingKeys: String, CodingKey {
case fileName = "file_name"
case fileType = "file_type"
case fileSize = "file_size"
}
}
private extension KeyedDecodingContainer {
///
func decodeLossyString(forKey key: Key) throws -> String {
if let value = try? decodeIfPresent(String.self, forKey: key) {
return value
}
if let value = try? decodeIfPresent(Int.self, forKey: key) {
return String(value)
}
if let value = try? decodeIfPresent(Double.self, forKey: key) {
return String(value)
}
if let value = try? decodeIfPresent(Bool.self, forKey: key) {
return value ? "1" : "0"
}
return ""
}
///
func decodeLossyInt(forKey key: Key) throws -> Int? {
if let value = try? decodeIfPresent(Int.self, forKey: key) {
return value
}
if let value = try? decodeIfPresent(Double.self, forKey: key) {
return Int(value)
}
if let value = try? decodeIfPresent(String.self, forKey: key) {
return Int(value.trimmingCharacters(in: .whitespacesAndNewlines))
}
return nil
}
}