Commit 4fa16fab authored by Alex朱枝文's avatar Alex朱枝文

资源相关

parent 051ce9c5
......@@ -12,7 +12,8 @@ import SnapKit
class YHResourceDetailViewController: YHBaseViewController {
// MARK: - Properties
var resourceModel: YHResourceListModel?
var companyId: Int = 0 // 只需要传入公司ID
var detailModel: YHResourceDetailModel? // 详情数据
var isMyCompany: Bool = false {
didSet {
......@@ -20,6 +21,10 @@ class YHResourceDetailViewController: YHBaseViewController {
}
}
private lazy var viewModel: YHResourceViewModel = {
return YHResourceViewModel()
}()
private lazy var messageHandler: YHIMMessageHandler = {
return YHIMMessageHandler(
viewController: self,
......@@ -29,7 +34,7 @@ class YHResourceDetailViewController: YHBaseViewController {
// MARK: - UI Components
// 背景图 - 改为在tableView后面
// 背景图
private lazy var bgIcon: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "resource_detail_bg")
......@@ -87,7 +92,6 @@ class YHResourceDetailViewController: YHBaseViewController {
gk_backImage = UIImage(named: "nav_black_24")
view.addSubview(bgIcon)
view.addSubview(tableView)
// 添加底部操作栏
view.addSubview(bottomActionView)
bottomActionView.addSubview(contactButton)
setupConstraints()
......@@ -96,21 +100,15 @@ class YHResourceDetailViewController: YHBaseViewController {
private func updateViewIsMine() {
gk_navTitle = isMyCompany ? "我的企业" : "企业详情"
if isMyCompany {
bottomActionView.isHidden = true
} else {
bottomActionView.isHidden = false
}
bottomActionView.isHidden = isMyCompany
updateRightBarButtonItem()
}
private func setupConstraints() {
// 背景图约束 - 参照YHMemberCenterViewController
bgIcon.snp.makeConstraints { make in
make.top.left.right.bottom.equalToSuperview()
}
// tableView约束
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(k_Height_NavigationtBarAndStatuBar)
......@@ -130,7 +128,6 @@ class YHResourceDetailViewController: YHBaseViewController {
make.height.equalTo(46)
}
// 不需要设置contentInset,让内容从导航栏下方开始
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: 0.01))
}
......@@ -154,29 +151,42 @@ class YHResourceDetailViewController: YHBaseViewController {
gk_navRightBarButtonItem = rightButtonItem
gk_navItemRightSpace = 16
}
}
// MARK: - Data
private func loadData() {
guard let _ = resourceModel else { return }
tableView.reloadData()
incrementViewCount()
guard companyId > 0 else {
YHHUD.flash(message: "公司ID无效")
return
}
private func incrementViewCount() {
resourceModel?.incrementViewCount()
// 直接调用详情接口
YHHUD.show(.progress(message: "加载中..."))
viewModel.getCompanyDetail(companyId: companyId) { [weak self] detail, error in
guard let self = self else { return }
DispatchQueue.main.async {
YHHUD.hide()
if let detail = detail {
self.detailModel = detail
self.tableView.reloadData()
} else if let error = error {
YHHUD.flash(message: error)
}
}
}
}
// MARK: - Actions
@objc private func shareButtonClicked() {
//
// 分享功能
}
@objc private func moreButtonClicked() {
//
// 更多操作
}
@objc private func contactButtonClicked() {
......@@ -184,9 +194,10 @@ class YHResourceDetailViewController: YHBaseViewController {
YHOneKeyLoginManager.shared.oneKeyLogin()
return
}
messageHandler.gotoChatVC(senderID: "")
if let detailModel = detailModel, !detailModel.yh_id.isEmpty {
messageHandler.gotoChatVC(senderID: detailModel.yh_id)
}
}
}
// MARK: - UITableViewDataSource & UITableViewDelegate
......@@ -202,12 +213,10 @@ extension YHResourceDetailViewController: UITableViewDataSource, UITableViewDele
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let model = resourceModel else {
guard let model = detailModel else {
return UITableViewCell()
}
let hasDocuments = !model.images.isEmpty
switch indexPath.section {
case 0:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell", for: indexPath) as? YHResourceDetailHeaderCell else {
......@@ -224,37 +233,23 @@ extension YHResourceDetailViewController: UITableViewDataSource, UITableViewDele
return cell
case 2:
if hasDocuments {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "DemandCell", for: indexPath) as? YHResourceDetailDemandCell else {
return UITableViewCell()
}
cell.configure(with: model)
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "DemandCell", for: indexPath) as? YHResourceDetailDemandCell else {
return UITableViewCell()
}
cell.configure(with: model)
return cell
}
case 3:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "DocumentsCell", for: indexPath) as? YHResourceDetailDocumentsCell else {
return UITableViewCell()
}
cell.configure(with: model.images)
let images = model.company_information.map { $0.url }
cell.configure(with: images)
cell.onImageTapped = { [weak self] index in
self?.showImageBrowser(at: index)
}
cell.onImageHeightChanged = { [weak self] in
guard let self = self else { return }
// NSObject.cancelPreviousPerformRequests(
// withTarget: self,
// selector: #selector(self.performBatchReload),
// object: nil
// )
// self.perform(#selector(self.performBatchReload), with: indexPath, afterDelay: 0.01)
// // 使用 performBatchUpdates 避免动画跳动
UIView.performWithoutAnimation {
self.tableView.reloadRows(at: [indexPath], with: .none)
}
......@@ -266,12 +261,6 @@ extension YHResourceDetailViewController: UITableViewDataSource, UITableViewDele
}
}
@objc private func performBatchReload(indexPath: IndexPath) {
UIView.performWithoutAnimation {
self.tableView.reloadRows(at: [indexPath], with: .none)
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
......@@ -292,10 +281,8 @@ extension YHResourceDetailViewController: UITableViewDataSource, UITableViewDele
return 0.01
}
// 关键改动:参照YHMemberCenterViewController的scrollViewDidScroll实现
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y > 0 {
// 向上滚动
var alpha = scrollView.contentOffset.y / k_Height_NavigationtBarAndStatuBar
if alpha > 1.0 {
alpha = 1.0
......@@ -311,7 +298,11 @@ extension YHResourceDetailViewController: UITableViewDataSource, UITableViewDele
}
private func showImageBrowser(at index: Int) {
guard let images = resourceModel?.images else { return }
print("显示图片浏览器,索引:\(index),共\(images.count)张")
guard let companyInformation = detailModel?.company_information else { return }
let images = companyInformation.map { $0.url }
if images.count > index, images.count > 0 {
printLog("显示图片浏览器,索引:\(index),共\(images.count)张")
YHPictureReviewManager.shared.showNetWorkPicturs(curIndex: index, arrPicturs: images)
}
}
}
......@@ -3,7 +3,7 @@
// galaxy
//
// Created by alexzzw on 2025/9/24.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
......@@ -33,6 +33,9 @@ class YHResourceViewController: YHBaseViewController {
// 筛选条件
var selectedCategories: [YHResourceCategory] = []
// 行业分类数据
var allCategories: [YHResourceCategory] = []
// MARK: - UI Components
// 自定义搜索视图
......@@ -121,7 +124,6 @@ class YHResourceViewController: YHBaseViewController {
}()
// 空状态视图
private lazy var noDataView: YHEmptyDataView = {
let view = YHEmptyDataView.createView("暂无内容", kEmptyOrderBgName)
view.frame = CGRect(x: 0, y: 0, width: KScreenWidth, height: 164)
......@@ -146,7 +148,8 @@ class YHResourceViewController: YHBaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
addDefaultData()
loadCategories() // 先加载分类数据
// addDefaultData()
getData()
}
......@@ -162,7 +165,8 @@ class YHResourceViewController: YHBaseViewController {
}
func handleTypeChangeNotification(_ userInfo: [AnyHashable: Any]) {
guard let selectTypeKey = userInfo[YHResourceViewController.selectTypeKey] as? String, let type = YHResourceFilterType(rawValue: selectTypeKey) else {
guard let selectTypeKey = userInfo[YHResourceViewController.selectTypeKey] as? String,
let type = YHResourceFilterType(rawValue: selectTypeKey) else {
return
}
setResourceType(type)
......@@ -186,7 +190,7 @@ private extension YHResourceViewController {
view.addSubview(noDataView)
view.addSubview(publishButton)
// 分类视图要最后添加确保在最上层
// 分类视图要最后添加,确保在最上层
view.addSubview(maskView)
view.addSubview(categoryView)
......@@ -206,6 +210,7 @@ private extension YHResourceViewController {
make.left.right.equalToSuperview()
make.height.equalTo(44)
}
serviceButton.setContentCompressionResistancePriority(.required, for: .horizontal)
demandButton.setContentCompressionResistancePriority(.required, for: .horizontal)
industryButton.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
......@@ -235,7 +240,6 @@ private extension YHResourceViewController {
categoryView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(filterContainerView.snp.bottom)
// 使用变量保存高度约束的引用
self.categoryViewHeightConstraint = make.height.equalTo(0).constraint
}
......@@ -303,6 +307,20 @@ private extension YHResourceViewController {
}
}
/// 加载行业分类数据
func loadCategories() {
viewModel.getResourceCategories { [weak self] categories, error in
guard let self = self else { return }
if let categories = categories {
self.allCategories = categories
self.categoryView.setCategories(categories)
} else if let error = error {
print("加载分类失败: \(error)")
}
}
}
func getData() {
loadFirstData()
}
......@@ -313,21 +331,22 @@ private extension YHResourceViewController {
YHHUD.show(.progress(message: "加载中..."))
}
DispatchQueue.global().async {
self.viewModel.getResourceList(firstFlag: true) { [weak self] success, message in
viewModel.getResourceList(firstFlag: true) { [weak self] success, message in
guard let self = self else { return }
DispatchQueue.main.async {
YHHUD.hide()
if success, let arrData = self.viewModel.arrResourceData, arrData.count > 0 {
let arrString = arrData.toJSONString()
UserDefaults.standard.set(arrString, forKey: "resourceFirstPageData")
UserDefaults.standard.synchronize()
} else if !success, let errorMessage = message {
// if success, let arrData = self.viewModel.arrResourceData, arrData.count > 0 {
// let arrString = arrData.toJSONString()
// UserDefaults.standard.set(arrString, forKey: "resourceFirstPageData")
// UserDefaults.standard.synchronize()
// } else if !success, let errorMessage = message {
// YHHUD.flash(message: errorMessage)
// }
if !success, let errorMessage = message {
YHHUD.flash(message: errorMessage)
}
self.resourceTableView.es.stopPullToRefresh()
if self.viewModel.hasMoreForResource == false {
......@@ -339,11 +358,9 @@ private extension YHResourceViewController {
}
}
}
}
func loadMoreData() {
DispatchQueue.global().async {
self.viewModel.getResourceList(firstFlag: false) { [weak self] _, _ in
viewModel.getResourceList(firstFlag: false) { [weak self] _, _ in
guard let self = self else { return }
DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35, execute: {
......@@ -357,7 +374,6 @@ private extension YHResourceViewController {
})
}
}
}
func updateUI() {
let hasData = viewModel.arrResourceData?.count ?? 0 > 0
......@@ -454,7 +470,6 @@ private extension YHResourceViewController {
industryButton.setImage(UIImage(named: "resource_filter_up"), for: .normal)
}
// 修改隐藏动画方法
@objc func hideCategoryView() {
// 高度约束动画
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
......@@ -510,10 +525,8 @@ extension YHResourceViewController: YHCustomSearchViewDelegate {
func searchView(_ searchView: YHCustomSearchView, didSearchWithText text: String?) {
viewModel.searchKeyword = text
if text?.isEmpty == true {
getData()
}
}
func searchViewDidBeginEditing(_ searchView: YHCustomSearchView) {
// 搜索开始编辑时的处理
......@@ -521,7 +534,6 @@ extension YHResourceViewController: YHCustomSearchViewDelegate {
func searchViewDidEndEditing(_ searchView: YHCustomSearchView) {
// 搜索结束编辑时的处理
getData()
}
}
......@@ -538,8 +550,9 @@ extension YHResourceViewController: UITableViewDelegate, UITableViewDataSource {
let cell = tableView.dequeueReusableCell(withIdentifier: YHResourceTableViewCell.cellReuseIdentifier, for: indexPath) as? YHResourceTableViewCell else {
return UITableViewCell()
}
cell.resourceModel = datas[indexPath.row]
let model = datas[indexPath.row]
model.isService = viewModel.currentType == .service
cell.resourceModel = model
return cell
}
......@@ -552,8 +565,10 @@ extension YHResourceViewController: UITableViewDelegate, UITableViewDataSource {
tableView.deselectRow(at: indexPath, animated: true)
guard let model = viewModel.arrResourceData?[indexPath.row] else { return }
// 跳转到详情页
let vc = YHResourceDetailViewController()
vc.resourceModel = model
vc.companyId = model.id
navigationController?.pushViewController(vc, animated: true)
}
}
......@@ -586,15 +601,14 @@ extension YHResourceViewController: YHResourceCategoryViewDelegate {
selectedCategories = categories
viewModel.selectedCategories = categories
updateIndustryButtonTitle()
if isSet {
// 隐藏分类视图
hideCategoryView()
}
// 重新加载数据
getData()
}
}
}
// MARK: - 枚举定义
......
......@@ -9,220 +9,190 @@
import UIKit
import SmartCodable
// MARK: - 资源列表模型
class YHResourceListModel: SmartCodable {
// MARK: - 公司列表响应模型
class YHResourceListResponse: SmartCodable {
required init() {}
var total: Int = 0
var list: [YHResourceListModel] = []
}
// MARK: - 公司头像模型
class YHCompanyAvatar: SmartCodable {
required init() {}
var needNewLine: Bool?
var name: String = ""
var url: String = ""
}
// MARK: - 基本信息
var id: String = ""
var title: String = ""
var content: String = ""
var company_name: String = ""
var company_logo: String = ""
var contact_name: String = ""
var contact_phone: String = ""
var contact_wechat: String = ""
var category_id: String = ""
var category_name: String = ""
var type: String = "" // service 或 demand
var status: Int = 0 // 0-待审核 1-已发布 2-已下架
var is_favorite: Bool = false
var favorite_count: Int = 0
var view_count: Int = 0
var created_time: String = ""
var updated_time: String = ""
var expires_time: String = ""
var images: [String] = []
var tags: [String] = []
var location: String = ""
var price: String = ""
var price_unit: String = ""
// MARK: - 扩展属性
var user_id: String = ""
var user_name: String = ""
var user_avatar: String = ""
var certification_status: Int = 0 // 0-未认证 1-已认证
var priority: Int = 0 // 优先级,用于排序
var click_count: Int = 0 // 点击量
var comment_count: Int = 0 // 评论数
var share_count: Int = 0 // 分享数
var service_area: String = "" // 服务区域
var min_price: String = "" // 最低价格
var max_price: String = "" // 最高价格
var service_duration: String = "" // 服务周期
var qualification: String = "" // 资质证明
var business_hours: String = "" // 营业时间
var website: String = "" // 公司网站
var email: String = "" // 邮箱
var address: String = "" // 详细地址
// MARK: - UI相关属性
var cell_width: CGFloat = 0
var cell_height: CGFloat = 0
// MARK: - 公司文档模型
class YHCompanyDocument: SmartCodable {
required init() {}
// MARK: - 计算属性
var name: String = ""
var url: String = ""
}
/// 显示时间(相对时间格式)
var displayTime: String {
return created_time.toDisplayTime()
}
// MARK: - 公司详情模型
class YHResourceDetailModel: SmartCodable {
required init() {}
/// 显示价格
var displayPrice: String {
if price.isEmpty {
if !min_price.isEmpty && !max_price.isEmpty {
return "\(min_price)-\(max_price)" + (price_unit.isEmpty ? "" : "/" + price_unit)
} else if !min_price.isEmpty {
return "¥\(min_price)起" + (price_unit.isEmpty ? "" : "/" + price_unit)
}
return "面议"
}
return "¥" + price + (price_unit.isEmpty ? "" : "/" + price_unit)
}
var contract_avatar: YHCompanyAvatar?
var id: Int = 0
var company_name: String = ""
var company_english_name: String = ""
var customer_id: Int = 0
var customer_name: String = ""
var last_processed_time: String = ""
var processor_id: Int = 0
var processor: String = ""
var settlement_status: Int = 0
var settlement_status_str: String = ""
var resource_provided: String = ""
var demand_published: String = ""
var settlement_time: String = ""
var industry_type: Int = 0
var industry_type_str: String = ""
var company_introduction: String = "" // 公司介绍
var company_business: String = "" // 主营业务
var company_information: [YHCompanyDocument] = [] // 公司资料图片
var created_at: String = ""
var updated_at: String = ""
var yh_id: String = ""
/// 类型显示名称
var typeDisplayName: String {
return type == "service" ? "企业服务" : "企业需求"
// 计算属性
var companyLogoUrl: String {
return contract_avatar?.url ?? ""
}
/// 状态显示名称
var statusDisplayName: String {
switch status {
case 0:
return "待审核"
case 1:
return "已发布"
case 2:
return "已下架"
default:
return "未知"
}
var displayName: String {
return company_name.isEmpty ? company_english_name : company_name
}
}
/// 认证状态显示
var certificationDisplayName: String {
return certification_status == 1 ? "已认证" : "未认证"
}
// MARK: - 资源列表模型(公司信息)
class YHResourceListModel: SmartCodable {
/// 是否已认证
var isCertified: Bool {
return certification_status == 1
}
required init() {}
var isService = true
/// 是否为服务类型
var isService: Bool {
return type == "service"
}
// MARK: - 基本信息(匹配列表API)
var id: Int = 0
var company_avatar: YHCompanyAvatar?
var company_name: String = ""
var company_english_name: String = ""
var resource_provided: String = "" // 提供的服务
var demand_published: String = "" // 发布的需求
var industry_type: Int = 0
var industry_type_str: String = ""
// MARK: - 详情字段(从详情接口获取后填充)
var company_introduction: String = "" // 公司介绍
var company_business: String = "" // 主营业务
var company_information: [YHCompanyDocument] = [] // 公司资料
var settlement_status: Int = 0
var settlement_status_str: String = ""
/// 是否为需求类型
var isDemand: Bool {
return type == "demand"
}
// MARK: - 计算属性
/// 是否已过期
var isExpired: Bool {
guard !expires_time.isEmpty else { return false }
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let expireDate = formatter.date(from: expires_time) else { return false }
return Date() > expireDate
/// 公司Logo URL
var companyLogoUrl: String {
return company_avatar?.url ?? ""
}
/// 剩余天数
var remainingDays: Int {
guard !expires_time.isEmpty else { return -1 }
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let expireDate = formatter.date(from: expires_time) else { return -1 }
let calendar = Calendar.current
let components = calendar.dateComponents([.day], from: Date(), to: expireDate)
return components.day ?? -1
/// 显示名称(优先显示中文名)
var displayName: String {
return company_name.isEmpty ? company_english_name : company_name
}
/// 热度值(综合点击、收藏、分享等)
var hotScore: Int {
return view_count + favorite_count * 2 + share_count * 3 + comment_count * 1
/// 是否有英文名
var hasEnglishName: Bool {
return !company_english_name.isEmpty
}
/// 第一张图片URL
var firstImageUrl: String {
return images.first ?? ""
/// 行业类型显示文本
var industryDisplayText: String {
return industry_type_str.isEmpty ? "其他" : industry_type_str
}
/// 是否有图片
var hasImages: Bool {
return !images.isEmpty
/// 是否提供服务
var hasResourceProvided: Bool {
return !resource_provided.isEmpty
}
/// 标签字符串(用逗号分隔)
var tagsString: String {
return tags.joined(separator: ", ")
/// 是否有需求
var hasDemandPublished: Bool {
return !demand_published.isEmpty
}
// MARK: - 计算Cell高度方法
func didFinishMapping() {
if needNewLine == nil {
needNewLine = calculateNeedNewLine()
/// 服务和需求显示文本
var serviceInfoText: String {
var texts: [String] = []
if hasResourceProvided {
texts.append("服务: \(resource_provided)")
}
if hasDemandPublished {
texts.append("需求: \(demand_published)")
}
return texts.joined(separator: " | ")
}
func calculateNeedNewLine() -> Bool {
let company = company_name.count > 0 ? company_name : "-"
let categoryName = category_name.count > 0 ? category_name : "-"
let companyWidth = YHResourceTableViewCell.getLabelWidth(company)
let categoryNameWidth = YHResourceTableViewCell.getLabelWidth(categoryName)
return companyWidth + categoryNameWidth >= KScreenWidth - YHResourceTableViewCell.logoWidth - YHResourceTableViewCell.logoToRight - YHResourceTableViewCell.arrowWidth - 2 * YHResourceTableViewCell.marginX - YHResourceTableViewCell.widthVLine - YHResourceTableViewCell.marginBetweenVLine * 2
/// ID字符串(用于兼容旧代码)
var idString: String {
return "\(id)"
}
// MARK: - 便利方法
// MARK: - 兼容旧字段的计算属性
/// 更新收藏状态
func updateFavoriteStatus(_ isFavorite: Bool) {
is_favorite = isFavorite
if isFavorite {
favorite_count += 1
} else {
favorite_count = max(0, favorite_count - 1)
/// 企业介绍(兼容旧字段 content)
var content: String {
return company_introduction.isEmpty ?
(resource_provided.isEmpty ? demand_published : resource_provided) :
company_introduction
}
/// 分类名称(兼容旧字段 category_name)
var category_name: String {
return industry_type_str
}
/// 增加浏览量
func incrementViewCount() {
view_count += 1
/// 服务周期(兼容旧字段 service_duration)
var service_duration: String {
return company_business
}
/// 增加分享数
func incrementShareCount() {
share_count += 1
/// 图片数组(兼容旧字段 images)
var images: [String] {
return company_information.map { $0.url }
}
// MARK: - 便利方法
/// 验证数据完整性
func isValid() -> Bool {
return !id.isEmpty &&
!title.isEmpty &&
!content.isEmpty &&
!company_name.isEmpty &&
!contact_name.isEmpty &&
!contact_phone.isEmpty &&
!category_id.isEmpty
return id > 0 && !displayName.isEmpty
}
/// 获取联系方式字符串
func getContactInfo() -> String {
var contactInfo = contact_name
if !contact_phone.isEmpty {
contactInfo += " \(contact_phone)"
/// 更新详情数据(从详情接口获取后调用)
func updateWithDetail(_ detail: YHResourceDetailModel) {
self.company_introduction = detail.company_introduction
self.company_business = detail.company_business
self.company_information = detail.company_information
self.settlement_status = detail.settlement_status
self.settlement_status_str = detail.settlement_status_str
// 如果需要,可以更新其他字段
if self.resource_provided.isEmpty {
self.resource_provided = detail.resource_provided
}
if self.demand_published.isEmpty {
self.demand_published = detail.demand_published
}
if !contact_wechat.isEmpty {
contactInfo += " 微信:\(contact_wechat)"
}
return contactInfo
/// 增加浏览量(兼容方法)
func incrementViewCount() {
// 如果需要调用接口增加浏览量,在这里实现
print("增加浏览量")
}
}
......@@ -251,6 +221,29 @@ class YHResourceCategory: SmartCodable {
}
}
// MARK: - 行业分类响应模型
class YHIndustryTypeResponse: SmartCodable {
required init() {}
var industry_type: [YHIndustryTypeModel] = []
}
// MARK: - 行业类型模型
class YHIndustryTypeModel: SmartCodable {
required init() {}
var id: String = ""
var name: String = ""
/// 转换为YHResourceCategory(用于兼容现有UI)
func toResourceCategory() -> YHResourceCategory {
let category = YHResourceCategory()
category.id = id
category.name = name
return category
}
}
// MARK: - String Extension
extension String {
func toDisplayTime() -> String {
......
......@@ -40,6 +40,11 @@ class YHResourceCategoryView: UIView {
private lazy var bottomButtonContainer: UIView = {
let view = UIView()
view.backgroundColor = .white
// 添加顶部阴影
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: -2)
view.layer.shadowOpacity = 0.05
view.layer.shadowRadius = 4
return view
}()
......@@ -81,13 +86,11 @@ class YHResourceCategoryView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
loadCategories()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupUI()
loadCategories()
}
// MARK: - Setup
......@@ -130,87 +133,17 @@ class YHResourceCategoryView: UIView {
}
}
private func loadCategories() {
// 模拟数据,实际使用时从接口获取
let allCategory = YHResourceCategory()
allCategory.id = "0"
allCategory.name = "全部行业"
let category1 = YHResourceCategory()
category1.id = "1"
category1.name = "金融会计"
let category2 = YHResourceCategory()
category2.id = "2"
category2.name = "资讯科技"
let category3 = YHResourceCategory()
category3.id = "3"
category3.name = "业务支持"
let category4 = YHResourceCategory()
category4.id = "4"
category4.name = "工业制造"
let category5 = YHResourceCategory()
category5.id = "5"
category5.name = "建筑工程"
let category6 = YHResourceCategory()
category6.id = "6"
category6.name = "地产开发"
let category7 = YHResourceCategory()
category7.id = "7"
category7.name = "法律服务"
let category8 = YHResourceCategory()
category8.id = "8"
category8.name = "商业贸易"
let category9 = YHResourceCategory()
category9.id = "9"
category9.name = "物流运输"
let category10 = YHResourceCategory()
category10.id = "10"
category10.name = "餐饮旅游"
let category11 = YHResourceCategory()
category11.id = "11"
category11.name = "广播娱乐"
let category12 = YHResourceCategory()
category12.id = "12"
category12.name = "艺术文化"
let category13 = YHResourceCategory()
category13.id = "13"
category13.name = "体育运动"
let category14 = YHResourceCategory()
category14.id = "14"
category14.name = "医疗健康"
let category15 = YHResourceCategory()
category15.id = "15"
category15.name = "学术教育"
let category16 = YHResourceCategory()
category16.id = "16"
category16.name = "其他"
categories = [
allCategory, category1, category2, category3, category4, category5,
category6, category7, category8, category9, category10, category11,
category12, category13, category14, category15, category16
]
// MARK: - Public Methods
/// 设置分类数据(从外部传入,通常来自API)
/// - Parameter categories: 分类数组
func setCategories(_ categories: [YHResourceCategory]) {
self.categories = categories
collectionView.reloadData()
}
// MARK: - Public Methods
/// 设置已选中的分类
/// - Parameter categories: 已选中的分类数组
func setSelectedCategories(_ categories: [YHResourceCategory]) {
selectedCategories = categories
collectionView.reloadData()
......@@ -219,7 +152,7 @@ class YHResourceCategoryView: UIView {
// MARK: - Actions
@objc private func resetButtonClicked() {
// 重置为"全部行业"
// 重置:清空所有选择
selectedCategories.removeAll()
collectionView.reloadData()
delegate?.categoryView(self, didSelectCategories: selectedCategories, isSet: false)
......@@ -238,7 +171,8 @@ extension YHResourceCategoryView: UICollectionViewDataSource, UICollectionViewDe
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard categories.count > indexPath.item, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YHResourceCategoryCell", for: indexPath) as? YHResourceCategoryCell else {
guard categories.count > indexPath.item,
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YHResourceCategoryCell", for: indexPath) as? YHResourceCategoryCell else {
return UICollectionViewCell()
}
......@@ -252,28 +186,20 @@ extension YHResourceCategoryView: UICollectionViewDataSource, UICollectionViewDe
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let category = categories[indexPath.item]
// 如果是"全部行业",清空其他选择
if category.id == "0" {
selectedCategories.removeAll()
selectedCategories.append(category)
} else {
// 移除"全部行业"选项
selectedCategories.removeAll { $0.id == "0" }
// 切换选中状态
// 切换选中状态(支持多选)
if let index = selectedCategories.firstIndex(where: { $0.id == category.id }) {
// 如果已选中,则取消选中
selectedCategories.remove(at: index)
} else {
// 如果未选中,则添加到选中列表
selectedCategories.append(category)
}
// // 如果没有选中任何分类,自动选中"全部行业"
// if selectedCategories.isEmpty {
// selectedCategories.append(categories.first!)
// }
}
// 刷新UI
collectionView.reloadData()
// 通知代理(不自动关闭,用户需要点击"筛选"按钮)
delegate?.categoryView(self, didSelectCategories: selectedCategories, isSet: false)
}
}
......@@ -295,9 +221,16 @@ extension YHResourceCategoryView: UICollectionViewDelegateFlowLayout {
// MARK: - YHResourceCategoryCell
class YHResourceCategoryCell: UICollectionViewCell {
private lazy var iconLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 18)
label.textAlignment = .center
return label
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = UIFont.PFSC_R(ofSize: 14)
label.font = UIFont.PFSC_R(ofSize: 13)
label.textAlignment = .center
label.textColor = .brandGrayColor8
label.numberOfLines = 1
......@@ -306,6 +239,15 @@ class YHResourceCategoryCell: UICollectionViewCell {
return label
}()
private lazy var containerStackView: UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.spacing = 4
stack.alignment = .center
stack.distribution = .fill
return stack
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
......@@ -318,26 +260,43 @@ class YHResourceCategoryCell: UICollectionViewCell {
private func setupUI() {
backgroundColor = UIColor.brandGrayColor2
layer.cornerRadius = 2// 调整圆角以适应新高度
layer.cornerRadius = 2
layer.borderWidth = 1
layer.borderColor = UIColor.clear.cgColor
contentView.addSubview(titleLabel)
contentView.addSubview(containerStackView)
containerStackView.addArrangedSubview(iconLabel)
containerStackView.addArrangedSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 12, left: 4, bottom: 12, right: 4))
containerStackView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.left.greaterThanOrEqualToSuperview().offset(8)
make.right.lessThanOrEqualToSuperview().offset(-8)
}
iconLabel.setContentHuggingPriority(.required, for: .horizontal)
titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
}
func configure(with category: YHResourceCategory, isSelected: Bool) {
// 设置图标(如果有)
if !category.icon.isEmpty {
iconLabel.text = category.icon
iconLabel.isHidden = false
} else {
iconLabel.isHidden = true
}
titleLabel.text = category.name
if isSelected {
layer.borderColor = UIColor.brandGrayColor8.cgColor
titleLabel.font = UIFont.PFSC_B(ofSize: 14)
titleLabel.font = UIFont.PFSC_B(ofSize: 13)
titleLabel.textColor = UIColor.brandGrayColor8
} else {
layer.borderColor = UIColor.clear.cgColor
titleLabel.font = UIFont.PFSC_R(ofSize: 14)
titleLabel.font = UIFont.PFSC_R(ofSize: 13)
titleLabel.textColor = UIColor.brandGrayColor7
}
}
}
......@@ -70,13 +70,19 @@ class YHResourceDetailBaseInfoCell: UITableViewCell {
}
}
func configure(with model: YHResourceListModel) {
func configure(with model: YHResourceDetailModel) {
stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
addInfoRow(title: "企业介绍", content: model.content.isEmpty ? "未填写" : model.content)
addInfoRow(title: "主营业务", content: model.category_name.isEmpty ? "未填写" : model.category_name)
addInfoRow(title: "提供服务", content: model.service_duration.isEmpty ? "未填写" : model.service_duration)
addInfoRow(title: "行业类型", content: model.category_name.isEmpty ? "未填写" : model.category_name)
// 使用详情接口的字段
addInfoRow(title: "企业介绍", content: model.company_introduction.isEmpty ? "未填写" : model.company_introduction)
addInfoRow(title: "主营业务", content: model.company_business.isEmpty ? "未填写" : model.company_business)
addInfoRow(title: "提供服务", content: model.resource_provided.isEmpty ? "未填写" : model.resource_provided)
addInfoRow(title: "发布需求", content: model.demand_published.isEmpty ? "未填写" : model.demand_published)
addInfoRow(title: "行业类型", content: model.industry_type_str.isEmpty ? "未填写" : model.industry_type_str)
if !model.settlement_status_str.isEmpty {
addInfoRow(title: "入驻状态", content: model.settlement_status_str)
}
}
private func addInfoRow(title: String, content: String) {
......@@ -98,7 +104,7 @@ class YHResourceDetailBaseInfoCell: UITableViewCell {
contentLabel.font = UIFont.PFSC_R(ofSize: 13)
contentLabel.textColor = UIColor.brandGrayColor8
contentLabel.text = content
contentLabel.numberOfLines = 4
contentLabel.numberOfLines = 0
contentLabel.textAlignment = .left
container.addSubview(titleLabel)
......@@ -110,7 +116,7 @@ class YHResourceDetailBaseInfoCell: UITableViewCell {
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview()
make.top.equalToSuperview()
make.bottom.lessThanOrEqualToSuperview()
make.width.equalTo(70)
}
contentLabel.snp.makeConstraints { make in
......
......@@ -36,7 +36,7 @@ class YHResourceDetailDemandCell: UITableViewCell {
let label = UILabel()
label.font = UIFont.PFSC_R(ofSize: 13)
label.textColor = UIColor.brandGrayColor8
label.numberOfLines = 4
label.numberOfLines = 0
return label
}()
......@@ -66,15 +66,15 @@ class YHResourceDetailDemandCell: UITableViewCell {
}
demandTitleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.left.equalToSuperview().offset(20)
make.top.equalTo(titleLabel.snp.bottom).offset(16)
make.width.equalTo(70)
}
demandContentLabel.snp.makeConstraints { make in
make.left.equalTo(demandTitleLabel.snp.right).offset(12)
make.right.equalToSuperview().offset(-20)
make.top.equalTo(demandTitleLabel)
}
dividerView.snp.makeConstraints { make in
......@@ -85,7 +85,8 @@ class YHResourceDetailDemandCell: UITableViewCell {
}
}
func configure(with model: YHResourceListModel) {
demandContentLabel.text = model.title.isEmpty ? "未填写" : model.title
func configure(with model: YHResourceDetailModel) {
// 使用详情接口的 demand_published 字段
demandContentLabel.text = model.demand_published.isEmpty ? "未填写" : model.demand_published
}
}
......@@ -133,7 +133,7 @@ class YHResourceDetailDocumentsCell: UITableViewCell {
}
let imageWidth = KScreenWidth - 20 * 2 // 左右各16的padding
let imageHeight = imageWidth * 1.4 // A4纸张比例
let imageHeight = imageWidth * 1.0 // A4纸张比例
for (index, imageUrl) in images.enumerated() {
let imageView = UIImageView()
......
......@@ -7,15 +7,18 @@
//
import UIKit
import Kingfisher
class YHResourceDetailHeaderCell: UITableViewCell {
private lazy var logoImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 4
imageView.backgroundColor = .white
imageView.layer.borderWidth = 1
imageView.layer.borderColor = UIColor.brandGrayColor3.cgColor
return imageView
}()
......@@ -72,11 +75,26 @@ class YHResourceDetailHeaderCell: UITableViewCell {
}
}
func configure(with model: YHResourceListModel) {
if let url = URL(string: model.company_logo) {
logoImageView.sd_setImage(with: url, placeholderImage: UIImage(named: "people_head_default"))
func configure(with model: YHResourceDetailModel) {
// 设置Logo
if !model.companyLogoUrl.isEmpty {
logoImageView.kf.setImage(
with: URL(string: model.companyLogoUrl),
placeholder: UIImage(named: "global_default_image")
)
} else {
logoImageView.image = UIImage(named: "global_default_image")
}
// 设置公司名称
companyNameLabel.text = model.displayName
// 设置英文名称
if !model.company_english_name.isEmpty {
companyEnglishNameLabel.text = model.company_english_name
companyEnglishNameLabel.isHidden = false
} else {
companyEnglishNameLabel.isHidden = true
}
companyNameLabel.text = model.company_name
companyEnglishNameLabel.text = "JUXIN CERTIFIED PUBLIC ACCOUNTANTS FIRM"
}
}
......@@ -191,83 +191,35 @@ extension YHResourceTableViewCell {
private func updateUI() {
guard let model = resourceModel else { return }
// 设置基本信息
let title = model.title.count > 0 ? model.title : "-"
let company = model.company_name.count > 0 ? model.company_name : "-"
let categoryName = model.category_name.count > 0 ? model.category_name : "-"
titleLabel.text = title
companyLabel.text = company
industryLabel.text = categoryName
var needNext = false
if let needNewLine = model.needNewLine {
needNext = needNewLine
} else {
let needNewLine = model.calculateNeedNewLine()
model.needNewLine = needNewLine
needNext = needNewLine
}
if !needNext {
companyLabel.snp.remakeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(4)
}
vSeparatorLine.snp.remakeConstraints { make in
make.left.equalTo(companyLabel.snp.right).offset(YHResourceTableViewCell.marginBetweenVLine)
make.centerY.equalTo(companyLabel)
make.width.equalTo(1)
make.height.equalTo(8)
}
// 行业标签约束
industryLabel.snp.remakeConstraints { make in
make.left.equalTo(vSeparatorLine.snp.right).offset(YHResourceTableViewCell.marginBetweenVLine)
make.right.lessThanOrEqualTo(rightArrow.snp.left)
make.top.equalTo(companyLabel)
make.bottom.equalToSuperview().offset(-32)
}
} else {
companyLabel.snp.remakeConstraints { make in
make.left.equalTo(titleLabel)
make.right.lessThanOrEqualTo(rightArrow.snp.left)
make.top.equalTo(titleLabel.snp.bottom).offset(4)
}
vSeparatorLine.snp.remakeConstraints { make in
make.left.equalTo(companyLabel.snp.left)
make.centerY.equalTo(industryLabel)
make.width.equalTo(1)
make.height.equalTo(8)
}
// 行业标签约束
industryLabel.snp.remakeConstraints { make in
make.left.equalTo(vSeparatorLine.snp.right).offset(YHResourceTableViewCell.marginBetweenVLine)
make.right.lessThanOrEqualTo(rightArrow.snp.left)
make.top.equalTo(companyLabel.snp.bottom).offset(4)
make.bottom.equalToSuperview().offset(-32)
}
}
// 设置基本信息 - 使用新的API字段
titleLabel.text = getServiceOrDemandText(model: model) // 显示服务或需求信息
companyLabel.text = model.displayName // 使用 company_name
industryLabel.text = model.industryDisplayText // 使用 industry_type_str
// 设置Logo
if !model.company_logo.isEmpty {
// 设置Logo - 使用新的API字段
if !model.companyLogoUrl.isEmpty {
logoImageView.kf.setImage(
with: URL(string: model.company_logo),
with: URL(string: model.companyLogoUrl),
placeholder: UIImage(named: "global_default_image")
)
} else {
logoImageView.image = UIImage(named: "global_default_image")
}
// 设置类型标签
if model.type == "service" {
// 设置类型标签 - 根据是服务还是需求
if model.isService {
typeTagIcon.image = UIImage(named: "resource_flag_service")
} else if model.type == "demand" {
typeTagIcon.image = UIImage(named: "resource_flag_demand")
} else {
typeTagIcon.image = nil
typeTagIcon.image = UIImage(named: "resource_flag_demand")
}
}
/// 获取服务或需求文本
private func getServiceOrDemandText(model: YHResourceListModel) -> String {
if model.isService {
return model.resource_provided.isEmpty ? "-" : model.resource_provided
} else {
return model.demand_published.isEmpty ? "-" : model.demand_published
}
}
}
......@@ -16,6 +16,7 @@ class YHResourceViewModel: NSObject {
var currentPage: Int = 1
var pageSize: Int = 20
var preloadItemIndex: Int = 10
var totalCount: Int = 0
// 筛选条件
var currentType: YHResourceFilterType = .service
......@@ -28,7 +29,7 @@ class YHResourceViewModel: NSObject {
// MARK: - 网络请求
/// 获取资源列表
/// 获取资源列表(公司列表)
/// - Parameters:
/// - firstFlag: 是否首次加载
/// - completion: 完成回调
......@@ -45,16 +46,17 @@ class YHResourceViewModel: NSObject {
}
}
// 构建请求参数
var params: [String: Any] = [
"page": currentPage,
"page_size": pageSize,
"type": currentType == .service ? "service" : "demand"
"type": currentType == .service ? 1 : 2 // 1-服务 2-需求
]
// 添加分类筛选(多选)
// 添加分类筛选(多选)- 转为Int数组
if !selectedCategories.isEmpty {
let categoryIds = selectedCategories.map { $0.id }
params["category_ids"] = categoryIds
let categoryIds = selectedCategories.compactMap { Int($0.id) }
params["industry_type"] = categoryIds
}
// 添加搜索关键词
......@@ -62,229 +64,110 @@ class YHResourceViewModel: NSObject {
params["keyword"] = keyword
}
// 模拟网络延迟
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
let mockData = self.generateMockResourceData(page: self.currentPage)
// 调用真实API
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.Resource.companyList
_ = YHNetRequest.postRequest(url: strUrl, params: params) { [weak self] json, _ in
guard let self = self else { return }
if json.code == 200 {
guard let dic = json.data?.peel as? [String: Any],
let result = YHResourceListResponse.deserialize(from: dic) else {
completion(false, "数据解析失败")
return
}
if firstFlag {
self.arrResourceData = mockData
self.totalCount = result.total
self.arrResourceData = result.list
} else {
self.arrResourceData?.append(contentsOf: mockData)
self.arrResourceData?.append(contentsOf: result.list)
}
self.currentPage += 1
self.hasMoreForResource = self.currentPage <= 5 // 模拟5页数据
completion(true, nil)
}
// 判断是否还有更多数据
if (self.arrResourceData?.count ?? 0) >= self.totalCount {
self.hasMoreForResource = false
} else {
self.hasMoreForResource = true
}
/// 切换收藏状态
/// - Parameters:
/// - resourceId: 资源ID
/// - completion: 完成回调
func toggleFavorite(resourceId: String, completion: @escaping (Bool, String?) -> Void) {
// 模拟网络延迟
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if let index = self.arrResourceData?.firstIndex(where: { $0.id == resourceId }) {
let item = self.arrResourceData![index]
item.updateFavoriteStatus(!item.is_favorite)
completion(true, nil)
} else {
completion(false, "资源不存在")
let errorMsg = json.msg.isEmpty ? "获取数据失败" : json.msg
completion(false, errorMsg)
}
} failBlock: { err in
let errorMsg = err.errorMsg
completion(false, errorMsg)
}
}
/// 获取资源分类
/// 获取资源分类(行业类型)
/// - Parameter completion: 完成回调
func getResourceCategories(completion: @escaping ([YHResourceCategory]?, String?) -> Void) {
// 模拟网络延迟
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let categories = self.generateMockCategories()
completion(categories, nil)
}
}
// MARK: - Mock数据生成
private func generateMockResourceData(page: Int) -> [YHResourceListModel] {
let serviceTitles = [
"专业财务咨询服务",
"企业IT系统开发",
"品牌营销策划方案",
"法律顾问服务",
"人力资源管理咨询",
"企业培训服务",
"网站建设与维护",
"财务审计服务"
]
let demandTitles = [
"寻找优质供应商",
"招聘高级技术人员",
"需要市场推广合作",
"寻求投资合作伙伴",
"需要办公场地租赁",
"寻找物流配送服务",
"需要设备采购咨询",
"寻求技术合作"
]
let companies = [
("北京科技有限公司哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈", "https://picsum.photos/60/60?random=1"),
("上海贸易集团", "https://picsum.photos/60/60?random=2"),
("深圳创新科技", "https://picsum.photos/60/60?random=3"),
("杭州电商公司", "https://picsum.photos/60/60?random=4"),
("成都软件开发", "https://picsum.photos/60/60?random=5"),
("广州制造企业", "https://picsum.photos/60/60?random=6"),
("武汉咨询公司", "https://picsum.photos/60/60?random=7"),
("西安技术公司", "https://picsum.photos/60/60?random=8")
]
let categories = [
("finance", "金融会计哈哈哈哈哈哈"),
("tech", "资讯科技"),
("business", "业务支援"),
("manufacturing", "工业制造"),
("legal", "法律服务"),
("trade", "商业贸易"),
("logistics", "物流运输"),
("other", "其他")
]
let contacts = [
("张经理", "138****1234", "zhang123"),
("李总监", "139****5678", "li_manager"),
("王助理", "136****9876", "wang_assistant"),
("赵主管", "137****4321", "zhao_supervisor"),
("孙经理", "135****8765", "sun_manager"),
("周总", "134****2468", "zhou_boss"),
("吴主任", "133****1357", "wu_director"),
("郑经理", "132****9753", "zheng_manager")
]
let locations = ["北京·朝阳区", "上海·浦东新区", "深圳·南山区", "杭州·西湖区", "成都·锦江区", "广州·天河区", "武汉·江汉区", "西安·雁塔区"]
let contents = [
"我们提供专业的财务咨询服务,帮助企业优化财务结构,降低运营成本,提高资金使用效率。团队拥有10年以上行业经验。",
"专业的IT系统开发团队,提供定制化解决方案,包括Web应用、移动应用、企业管理系统等。技术栈涵盖主流开发框架。",
"专注品牌营销策划,提供全方位的品牌推广方案。从品牌定位到执行落地,一站式服务,已服务500+企业客户。",
"资深律师团队提供专业法律顾问服务,涵盖合同审查、法律风险评估、争议解决等。保障企业合规经营。",
"人力资源管理专家,提供招聘、培训、绩效管理等全方位HR服务。帮助企业建立完善的人才管理体系。",
"企业培训专业机构,提供管理培训、技能培训、团队建设等服务。定制化课程设计,提升员工综合素质。",
"专业网站建设团队,提供网站设计、开发、运维一体化服务。响应式设计,SEO优化,提升企业网络形象。",
"注册会计师团队提供财务审计服务,确保财务报表真实可靠。严格按照审计准则执行,保障审计质量。"
]
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.Resource.categoryList
// 根据筛选条件过滤数据
var filteredData: [YHResourceListModel] = []
for i in 0..<8 {
let model = YHResourceListModel()
let baseId = (page - 1) * 8 + i
model.id = "resource_\(baseId)"
// 根据当前类型选择标题
let titles = currentType == .service ? serviceTitles : demandTitles
model.title = titles[i % titles.count]
model.content = contents[i % contents.count]
model.type = currentType == .service ? "service" : "demand"
// 公司信息
let company = companies[i % companies.count]
model.company_name = company.0
model.company_logo = company.1
// 分类信息
let category = categories[i % categories.count]
model.category_id = category.0
model.category_name = category.1
// 联系信息
let contact = contacts[i % contacts.count]
model.contact_name = contact.0
model.contact_phone = contact.1
model.contact_wechat = contact.2
// 其他信息
model.location = locations[i % locations.count]
model.price = i % 3 == 0 ? "" : "\(Int.random(in: 1000...9999))"
model.price_unit = i % 3 == 0 ? "" : ["小时", "天", "月", "项目"][i % 4]
model.view_count = Int.random(in: 10...999)
model.favorite_count = Int.random(in: 0...50)
model.is_favorite = Bool.random()
model.status = 1 // 已发布
model.certification_status = i % 2 // 随机认证状态
// 时间
let daysAgo = Int.random(in: 0...30)
let date = Calendar.current.date(byAdding: .day, value: -daysAgo, to: Date()) ?? Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
model.created_time = formatter.string(from: date)
// 图片(随机添加1-3张图片)
let imageCount = Int.random(in: 0...3)
model.images = (0..<imageCount).map { "https://picsum.photos/300/200?random=\(baseId)_\($0)" }
// 标签
let allTags = ["优质服务", "专业团队", "价格优惠", "经验丰富", "快速响应", "全程跟踪", "售后保障", "行业领先"]
let tagCount = Int.random(in: 0...3)
model.tags = Array(allTags.shuffled().prefix(tagCount))
// 应用筛选条件
var shouldInclude = true
// 分类筛选
if !selectedCategories.isEmpty {
let categoryIds = selectedCategories.map { $0.id }
shouldInclude = shouldInclude && categoryIds.contains(model.category_id)
_ = YHNetRequest.getRequest(url: strUrl, params: [:]) { json, _ in
if json.code == 200 {
guard let dic = json.data?.peel as? [String: Any],
let result = YHIndustryTypeResponse.deserialize(from: dic) else {
completion(nil, "数据解析失败")
return
}
// 搜索关键词筛选
if let keyword = searchKeyword, !keyword.isEmpty {
let searchText = "\(model.title) \(model.content) \(model.company_name)".lowercased()
shouldInclude = shouldInclude && searchText.contains(keyword.lowercased())
// 转换为YHResourceCategory数组
let categories = result.industry_type.map { $0.toResourceCategory() }
completion(categories, nil)
} else {
let errorMsg = json.msg.isEmpty ? "获取分类失败" : json.msg
completion(nil, errorMsg)
}
if shouldInclude {
filteredData.append(model)
} failBlock: { err in
let errorMsg = err.errorMsg
completion(nil, errorMsg)
}
}
return filteredData
/// 获取公司详情
/// - Parameters:
/// - companyId: 公司ID
/// - completion: 完成回调
func getCompanyDetail(companyId: Int, completion: @escaping (YHResourceDetailModel?, String?) -> Void) {
let params: [String: Any] = ["id": companyId]
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.Resource.companyDetail
_ = YHNetRequest.getRequest(url: strUrl, params: params) { json, _ in
if json.code == 200 {
guard let dic = json.data?.peel as? [String: Any],
let result = YHResourceDetailModel.deserialize(from: dic) else {
completion(nil, "数据解析失败")
return
}
private func generateMockCategories() -> [YHResourceCategory] {
let categoryData = [
("finance", "金融会计", "💰"),
("tech", "资讯科技", "💻"),
("business", "业务支援", "📊"),
("manufacturing", "工业制造", "🏭"),
("construction", "建筑工程", "🏗️"),
("real_estate", "地产开发", "🏢"),
("legal", "法律服务", "⚖️"),
("trade", "商业贸易", "🛒"),
("logistics", "物流运输", "🚚"),
("food", "餐饮旅游", "🍽️"),
("media", "广播娱乐", "📺"),
("culture", "艺术文化", "🎨"),
("sports", "体育运动", "⚽"),
("health", "医疗健康", "🏥"),
("education", "学术教育", "📚"),
("other", "其他", "📋")
]
completion(result, nil)
} else {
let errorMsg = json.msg.isEmpty ? "获取详情失败" : json.msg
completion(nil, errorMsg)
}
return categoryData.map { (id, name, icon) in
let category = YHResourceCategory()
category.id = id
category.name = name
category.icon = icon
category.resource_count = Int.random(in: 10...999)
category.is_hot = Int.random(in: 0...1) == 1
return category
} failBlock: { err in
let errorMsg = err.errorMsg
completion(nil, errorMsg)
}
}
/// 切换收藏状态(如果有收藏功能的话)
/// - Parameters:
/// - resourceId: 资源ID
/// - completion: 完成回调
func toggleFavorite(resourceId: String, completion: @escaping (Bool, String?) -> Void) {
// TODO: 如果后端提供收藏接口,在这里实现
// 目前暂时不支持收藏功能
completion(false, "暂不支持收藏功能")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment