Commit 55ceadf2 authored by Alex朱枝文's avatar Alex朱枝文

我的资源

parent ebbf1004
......@@ -72,6 +72,10 @@
04307BB42D21623300ED8E8D /* YHRecommendedAppointmentLiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04307BB32D21623300ED8E8D /* YHRecommendedAppointmentLiveView.swift */; };
04307BB62D2180C300ED8E8D /* YHRecommendedOnLiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04307BB52D2180C300ED8E8D /* YHRecommendedOnLiveView.swift */; };
04307BBC2D22A21E00ED8E8D /* YHLiveStatusModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04307BBB2D22A21E00ED8E8D /* YHLiveStatusModel.swift */; };
04355C8D2E890DF10083BE91 /* YHResourceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04355C8C2E890DF10083BE91 /* YHResourceViewModel.swift */; };
04355C912E890E020083BE91 /* YHResourceCategoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04355C8F2E890E020083BE91 /* YHResourceCategoryView.swift */; };
04355C932E8912490083BE91 /* YHResourceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04355C922E8912490083BE91 /* YHResourceTableViewCell.swift */; };
04355C952E8912620083BE91 /* YHResourceListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04355C942E8912620083BE91 /* YHResourceListModel.swift */; };
0436713B2D643A7A00E8D9BA /* YHMemberCenterMyPrivilegeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0436713A2D643A7A00E8D9BA /* YHMemberCenterMyPrivilegeCell.swift */; };
0436713D2D6470A400E8D9BA /* YHMemberCenterActionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0436713C2D6470A400E8D9BA /* YHMemberCenterActionCell.swift */; };
0436713F2D64817500E8D9BA /* YHMemberCenterFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0436713E2D64817500E8D9BA /* YHMemberCenterFooterView.swift */; };
......@@ -1175,6 +1179,7 @@
047A968F2D16AA410033BB4E /* YHGCIncomeRecordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047A968A2D16AA410033BB4E /* YHGCIncomeRecordViewController.swift */; };
047A96902D16AA410033BB4E /* YHGCIncomeRecordWorkExperienceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047A968B2D16AA410033BB4E /* YHGCIncomeRecordWorkExperienceViewController.swift */; };
047A96932D16C0900033BB4E /* YHInfoQuestionSelectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047A96922D16C0900033BB4E /* YHInfoQuestionSelectionCell.swift */; };
0487C1C72E8940D000CE6472 /* YHCustomSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0487C1C62E8940D000CE6472 /* YHCustomSearchView.swift */; };
048D6ADB2D5E00DE00BC6F4C /* YHMemberCenterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048D6ADA2D5E00DE00BC6F4C /* YHMemberCenterViewController.swift */; };
048D6ADD2D5EF0A900BC6F4C /* YHMemberCenterHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048D6ADC2D5EF0A900BC6F4C /* YHMemberCenterHeaderView.swift */; };
048D6ADF2D5F0FBE00BC6F4C /* YHMemberCenterHeaderBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048D6ADE2D5F0FBE00BC6F4C /* YHMemberCenterHeaderBannerCell.swift */; };
......@@ -1433,6 +1438,10 @@
04307BB32D21623300ED8E8D /* YHRecommendedAppointmentLiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHRecommendedAppointmentLiveView.swift; sourceTree = "<group>"; };
04307BB52D2180C300ED8E8D /* YHRecommendedOnLiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHRecommendedOnLiveView.swift; sourceTree = "<group>"; };
04307BBB2D22A21E00ED8E8D /* YHLiveStatusModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHLiveStatusModel.swift; sourceTree = "<group>"; };
04355C8C2E890DF10083BE91 /* YHResourceViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHResourceViewModel.swift; sourceTree = "<group>"; };
04355C8F2E890E020083BE91 /* YHResourceCategoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHResourceCategoryView.swift; sourceTree = "<group>"; };
04355C922E8912490083BE91 /* YHResourceTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHResourceTableViewCell.swift; sourceTree = "<group>"; };
04355C942E8912620083BE91 /* YHResourceListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHResourceListModel.swift; sourceTree = "<group>"; };
0436713A2D643A7A00E8D9BA /* YHMemberCenterMyPrivilegeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterMyPrivilegeCell.swift; sourceTree = "<group>"; };
0436713C2D6470A400E8D9BA /* YHMemberCenterActionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterActionCell.swift; sourceTree = "<group>"; };
0436713E2D64817500E8D9BA /* YHMemberCenterFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterFooterView.swift; sourceTree = "<group>"; };
......@@ -2540,6 +2549,7 @@
047A968A2D16AA410033BB4E /* YHGCIncomeRecordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCIncomeRecordViewController.swift; sourceTree = "<group>"; };
047A968B2D16AA410033BB4E /* YHGCIncomeRecordWorkExperienceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCIncomeRecordWorkExperienceViewController.swift; sourceTree = "<group>"; };
047A96922D16C0900033BB4E /* YHInfoQuestionSelectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHInfoQuestionSelectionCell.swift; sourceTree = "<group>"; };
0487C1C62E8940D000CE6472 /* YHCustomSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCustomSearchView.swift; sourceTree = "<group>"; };
048D6ADA2D5E00DE00BC6F4C /* YHMemberCenterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterViewController.swift; sourceTree = "<group>"; };
048D6ADC2D5EF0A900BC6F4C /* YHMemberCenterHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterHeaderView.swift; sourceTree = "<group>"; };
048D6ADE2D5F0FBE00BC6F4C /* YHMemberCenterHeaderBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMemberCenterHeaderBannerCell.swift; sourceTree = "<group>"; };
......@@ -7031,6 +7041,7 @@
04D4EC2D2E839B4200B0329B /* M */ = {
isa = PBXGroup;
children = (
04355C942E8912620083BE91 /* YHResourceListModel.swift */,
);
path = M;
sourceTree = "<group>";
......@@ -7038,6 +7049,9 @@
04D4EC2E2E839B4200B0329B /* V */ = {
isa = PBXGroup;
children = (
0487C1C62E8940D000CE6472 /* YHCustomSearchView.swift */,
04355C922E8912490083BE91 /* YHResourceTableViewCell.swift */,
04355C8F2E890E020083BE91 /* YHResourceCategoryView.swift */,
);
path = V;
sourceTree = "<group>";
......@@ -7045,6 +7059,7 @@
04D4EC2F2E839B4200B0329B /* VM */ = {
isa = PBXGroup;
children = (
04355C8C2E890DF10083BE91 /* YHResourceViewModel.swift */,
);
path = VM;
sourceTree = "<group>";
......@@ -7702,6 +7717,7 @@
045C101A2D12CA5F00BD2DC0 /* YHActivityDetailCell1.swift in Sources */,
045C101B2D12CA5F00BD2DC0 /* YHLoginOneLeadView.swift in Sources */,
0411CEE22D14014000644D35 /* YHGCMainInformationCardTableViewCell.swift in Sources */,
04355C8D2E890DF10083BE91 /* YHResourceViewModel.swift in Sources */,
045C101C2D12CA5F00BD2DC0 /* YHCollectionViewLeftAlignedFlowLayout.swift in Sources */,
0411CF082D1A896800644D35 /* YHGCMySignatureListModel.swift in Sources */,
045C101D2D12CA5F00BD2DC0 /* YHHUDProgressView.swift in Sources */,
......@@ -7984,6 +8000,7 @@
045C11072D12CA5F00BD2DC0 /* YHIncomeItemOccupyingCell.swift in Sources */,
045C11082D12CA5F00BD2DC0 /* YHServerCenterHoldViewController.swift in Sources */,
045C11092D12CA5F00BD2DC0 /* YHResignCertificateListViewModel.swift in Sources */,
0487C1C72E8940D000CE6472 /* YHCustomSearchView.swift in Sources */,
045C110A2D12CA5F00BD2DC0 /* YHResignDocumentListModel.swift in Sources */,
04307BB62D2180C300ED8E8D /* YHRecommendedOnLiveView.swift in Sources */,
0436713F2D64817500E8D9BA /* YHMemberCenterFooterView.swift in Sources */,
......@@ -8042,6 +8059,7 @@
045C11372D12CA5F00BD2DC0 /* YHButlerServiceManager.swift in Sources */,
045C11382D12CA5F00BD2DC0 /* YHHomeModel.swift in Sources */,
045C11392D12CA5F00BD2DC0 /* YHSchemeHeadScoreItemView.swift in Sources */,
04355C912E890E020083BE91 /* YHResourceCategoryView.swift in Sources */,
045C113A2D12CA5F00BD2DC0 /* YHAIViewModel.swift in Sources */,
045C113B2D12CA5F00BD2DC0 /* YHButlerServiceMessageHandler.swift in Sources */,
045C113C2D12CA5F00BD2DC0 /* YHResignScheduleLineCollectCell.swift in Sources */,
......@@ -8443,6 +8461,7 @@
045C12732D12CA5F00BD2DC0 /* YHActivityDetailItemView.swift in Sources */,
045C12742D12CA5F00BD2DC0 /* YHWorkExperienceListViewController.swift in Sources */,
045C12752D12CA5F00BD2DC0 /* YHEducationInfo.swift in Sources */,
04355C952E8912620083BE91 /* YHResourceListModel.swift in Sources */,
045C12762D12CA5F00BD2DC0 /* UIFont+Extension.swift in Sources */,
045C12772D12CA5F00BD2DC0 /* YHTabBarViewController.swift in Sources */,
045C12782D12CA5F00BD2DC0 /* YHHKRecordsPersonnelSelectCell.swift in Sources */,
......@@ -8558,6 +8577,7 @@
045647572D7976880001D831 /* YHHKVisaRenewalApplicationVC.swift in Sources */,
045C12D92D12CA5F00BD2DC0 /* YHPayMemberSectionItem.swift in Sources */,
045C12DA2D12CA5F00BD2DC0 /* YHPickTimeHoldView.swift in Sources */,
04355C932E8912490083BE91 /* YHResourceTableViewCell.swift in Sources */,
04307B9F2D1D4B3600ED8E8D /* YHGCIncomeTypeSelectViewController.swift in Sources */,
045C12DB2D12CA5F00BD2DC0 /* YHServiceOrderInIncubationView.swift in Sources */,
045C12DC2D12CA5F00BD2DC0 /* YHUatHelperViewModel.swift in Sources */,
......
......@@ -41,9 +41,9 @@ class YHTencentDeskManager: NSObject {
/// 需要隐藏已读未读
TUIConfig.default().needHideReadReceipt = true
/// 需要隐藏聊天页点击用户头像显示用户信息
TUIChatConfig.default().needHideShowUserInfoPage = true
TUIChatConfig.default().needHideShowUserInfoPage = false
/// 需要隐藏显示聊天页rightBarButton按钮
TUIChatConfig.default().needHideNaviMore = true
TUIChatConfig.default().needHideNaviMore = false
}
func loginSDK() {
......
//
// YHCircleViewModel.swift
// galaxy
//
// Created by alexzzw on 2025/9/24.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHCircleViewModel: NSObject {
}
//
// YHResourceListModel.swift
// galaxy
//
// Created by alexzzw on 2025/9/24.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import SmartCodable
// MARK: - 资源列表模型
class YHResourceListModel: SmartCodable {
required init() {}
// 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: - 计算属性
/// 显示时间(相对时间格式)
var displayTime: String {
return created_time.toDisplayTime()
}
/// 显示价格
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 typeDisplayName: String {
return type == "service" ? "企业服务" : "企业需求"
}
/// 状态显示名称
var statusDisplayName: String {
switch status {
case 0:
return "待审核"
case 1:
return "已发布"
case 2:
return "已下架"
default:
return "未知"
}
}
/// 认证状态显示
var certificationDisplayName: String {
return certification_status == 1 ? "已认证" : "未认证"
}
/// 是否已认证
var isCertified: Bool {
return certification_status == 1
}
/// 是否为服务类型
var isService: Bool {
return type == "service"
}
/// 是否为需求类型
var isDemand: Bool {
return type == "demand"
}
/// 是否已过期
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
}
/// 剩余天数
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 hotScore: Int {
return view_count + favorite_count * 2 + share_count * 3 + comment_count * 1
}
/// 第一张图片URL
var firstImageUrl: String {
return images.first ?? ""
}
/// 是否有图片
var hasImages: Bool {
return !images.isEmpty
}
/// 标签字符串(用逗号分隔)
var tagsString: String {
return tags.joined(separator: ", ")
}
// MARK: - 计算Cell高度方法
func calHeightParam() {
let screenWidth = KScreenWidth
let cellWidth = (screenWidth - 47) / 2
var totalHeight: CGFloat = 60 + 20 + 44 // 基础高度
// 标题高度
if !title.isEmpty {
let titleFont = UIFont.PFSC_M(ofSize: 16) ?? UIFont.systemFont(ofSize: 16)
let maxSize = CGSize(width: cellWidth - 24, height: CGFloat.greatestFiniteMagnitude)
let titleRect = title.boundingRect(
with: maxSize,
options: [.usesLineFragmentOrigin, .usesFontLeading],
attributes: [.font: titleFont],
context: nil
)
totalHeight += ceil(titleRect.height) + 8
}
// 内容高度
if !content.isEmpty {
let contentFont = UIFont.PFSC_R(ofSize: 13) ?? UIFont.systemFont(ofSize: 13)
let maxSize = CGSize(width: cellWidth - 24, height: CGFloat.greatestFiniteMagnitude)
let textRect = content.boundingRect(
with: maxSize,
options: [.usesLineFragmentOrigin, .usesFontLeading],
attributes: [.font: contentFont],
context: nil
)
totalHeight += min(ceil(textRect.height), 40) + 8 // 限制最大高度为2行
}
// 图片高度
if !images.isEmpty {
let imageHeight: CGFloat = 100
totalHeight += imageHeight + 8
}
// 标签高度
if !tags.isEmpty {
totalHeight += 20 + 8
}
// 底部信息高度
totalHeight += 30
self.cell_width = cellWidth
self.cell_height = max(totalHeight, 160) // 最小高度160
}
// MARK: - 便利方法
/// 更新收藏状态
func updateFavoriteStatus(_ isFavorite: Bool) {
is_favorite = isFavorite
if isFavorite {
favorite_count += 1
} else {
favorite_count = max(0, favorite_count - 1)
}
}
/// 增加浏览量
func incrementViewCount() {
view_count += 1
}
/// 增加分享数
func incrementShareCount() {
share_count += 1
}
/// 验证数据完整性
func isValid() -> Bool {
return !id.isEmpty &&
!title.isEmpty &&
!content.isEmpty &&
!company_name.isEmpty &&
!contact_name.isEmpty &&
!contact_phone.isEmpty &&
!category_id.isEmpty
}
/// 获取联系方式字符串
func getContactInfo() -> String {
var contactInfo = contact_name
if !contact_phone.isEmpty {
contactInfo += " \(contact_phone)"
}
if !contact_wechat.isEmpty {
contactInfo += " 微信:\(contact_wechat)"
}
return contactInfo
}
}
// MARK: - 资源分类模型
class YHResourceCategory: SmartCodable {
required init() {}
var id: String = ""
var name: String = ""
var icon: String = ""
var sort: Int = 0
var parent_id: String = ""
var children: [YHResourceCategory] = []
var description_text: String = ""
var is_hot: Bool = false
var resource_count: Int = 0
// 计算属性
var hasChildren: Bool {
return !children.isEmpty
}
var isTopLevel: Bool {
return parent_id.isEmpty
}
}
// MARK: - String Extension
extension String {
func toDisplayTime() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let date = formatter.date(from: self) else {
return self
}
let now = Date()
let interval = now.timeIntervalSince(date)
if interval < 60 {
return "刚刚"
} else if interval < 3600 {
return "\(Int(interval / 60))分钟前"
} else if interval < 86400 {
return "\(Int(interval / 3600))小时前"
} else if interval < 2592000 {
return "\(Int(interval / 86400))天前"
} else {
formatter.dateFormat = "MM-dd"
return formatter.string(from: date)
}
}
}
//
// YHCustomSearchView.swift
// galaxy
//
// Created by alexzzw on 2025/9/24.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
protocol YHCustomSearchViewDelegate: AnyObject {
func searchView(_ searchView: YHCustomSearchView, didSearchWithText text: String?)
func searchViewDidBeginEditing(_ searchView: YHCustomSearchView)
func searchViewDidEndEditing(_ searchView: YHCustomSearchView)
}
class YHCustomSearchView: UIView {
weak var delegate: YHCustomSearchViewDelegate?
// MARK: - UI Components
private lazy var containerView: UIView = {
let view = UIView()
view.backgroundColor = .brandGrayColor1
return view
}()
private lazy var searchIconImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "resource_search")
imageView.contentMode = .scaleAspectFit
return imageView
}()
private lazy var searchTextField: UITextField = {
let textField = UITextField()
textField.font = UIFont.PFSC_M(ofSize: 14)
textField.textColor = UIColor.brandGrayColor8
textField.borderStyle = .none
textField.delegate = self
textField.addTarget(self, action: #selector(textFieldEditingChanged(_:)), for: .editingChanged)
textField.addTarget(self, action: #selector(textFieldEditingDidBegin(_:)), for: .editingDidBegin)
textField.addTarget(self, action: #selector(textFieldEditingDidEnd(_:)), for: .editingDidEnd)
textField.returnKeyType = .search
textField.attributedPlaceholder = NSAttributedString.init(string: "搜索企业名称、企业供需", attributes: [.foregroundColor: UIColor.brandGrayColor6, .font: UIFont.PFSC_R(ofSize: 14)])
return textField
}()
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupUI()
}
// MARK: - Setup
private func setupUI() {
backgroundColor = .white
addSubview(containerView)
containerView.addSubview(searchIconImageView)
containerView.addSubview(searchTextField)
setupConstraints()
}
private func setupConstraints() {
containerView.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20)
make.centerY.equalToSuperview()
make.height.equalTo(36)
}
searchIconImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.centerY.equalToSuperview()
make.width.height.equalTo(24)
}
searchTextField.snp.makeConstraints { make in
make.left.equalTo(searchIconImageView.snp.right).offset(6)
make.right.equalToSuperview().offset(-12)
make.top.bottom.equalToSuperview()
}
}
// MARK: - Public Methods
var text: String? {
get {
return searchTextField.text
}
set {
searchTextField.text = newValue
}
}
var placeholder: String? {
get {
return searchTextField.placeholder
}
set {
searchTextField.placeholder = newValue
}
}
@discardableResult
override func becomeFirstResponder() -> Bool {
return searchTextField.becomeFirstResponder()
}
@discardableResult
override func resignFirstResponder() -> Bool {
return searchTextField.resignFirstResponder()
}
func clearText() {
searchTextField.text = ""
delegate?.searchView(self, didSearchWithText: "")
}
// MARK: - Actions
@objc private func textFieldEditingChanged(_ textField: UITextField) {
delegate?.searchView(self, didSearchWithText: textField.text)
}
@objc private func textFieldEditingDidBegin(_ textField: UITextField) {
delegate?.searchViewDidBeginEditing(self)
}
@objc private func textFieldEditingDidEnd(_ textField: UITextField) {
delegate?.searchViewDidEndEditing(self)
}
}
// MARK: - UITextFieldDelegate
extension YHCustomSearchView: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
delegate?.searchView(self, didSearchWithText: textField.text)
return true
}
}
//
// YHResourceTableViewCell.swift
// galaxy
//
// Created by alexzzw on 2025/9/24.
// Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Kingfisher
class YHResourceTableViewCell: UITableViewCell {
static let labelFont = UIFont.PFSC_R(ofSize: 14)
static let labelHeight: CGFloat = 20.0
private let marginX: CGFloat = 20.0
private let logoWidth: CGFloat = 60.0
private let logoToRight: CGFloat = 10.0
private let marginBetweenVLine: CGFloat = 6.0
private let widthVLine: CGFloat = 1
private let arrowWidth: CGFloat = 24
private let arrowToLeft: CGFloat = 24
static let cellReuseIdentifier = "YHResourceTableViewCell"
// MARK: - 属性
var resourceModel: YHResourceListModel? {
didSet {
updateUI()
}
}
// MARK: - UI Components
// 分割线
lazy var separatorLine: UIView = {
let view = UIView()
view.backgroundColor = UIColor.brandGrayColor3
return view
}()
lazy var vSeparatorLine: UIView = {
let view = UIView()
view.backgroundColor = UIColor.brandGrayColor3
return view
}()
// 左侧LOGO
lazy var logoImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 4
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.brandGrayColor3.cgColor
imageView.layer.borderWidth = 1
imageView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
return imageView
}()
lazy var typeTagIcon: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
return imageView
}()
lazy var rightArrow: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "resource_feed_arrow"))
imageView.contentMode = .scaleAspectFit
return imageView
}()
// 主标题
lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = UIFont.PFSC_M(ofSize: 15)
label.textColor = UIColor.brandGrayColor8
label.numberOfLines = 2
return label
}()
// 公司名称
lazy var companyLabel: UILabel = {
let label = UILabel()
label.font = UIFont.PFSC_R(ofSize: 14)
label.textColor = UIColor.gray
label.numberOfLines = 1
return label
}()
// 行业标签
lazy var industryLabel: UILabel = {
let label = UILabel()
label.font = UIFont.PFSC_R(ofSize: 14)
label.textColor = UIColor.gray
label.numberOfLines = 1
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// MARK: - 私有方法
private extension YHResourceTableViewCell {
func setupUI() {
backgroundColor = .white
selectionStyle = .none
contentView.addSubview(logoImageView)
contentView.addSubview(rightArrow)
contentView.addSubview(typeTagIcon)
contentView.addSubview(titleLabel)
contentView.addSubview(companyLabel)
contentView.addSubview(industryLabel)
contentView.addSubview(separatorLine)
contentView.addSubview(vSeparatorLine)
setupConstraints()
}
func setupConstraints() {
// LOGO约束
logoImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(marginX)
make.top.equalToSuperview().offset(24)
make.width.height.equalTo(logoWidth)
}
// 右上角标签约束
typeTagIcon.snp.makeConstraints { make in
make.left.equalTo(logoImageView.snp.right).offset(logoToRight)
make.top.equalTo(logoImageView)
make.height.equalTo(16)
make.width.equalTo(52)
}
// 主标题约束
titleLabel.snp.makeConstraints { make in
make.left.equalTo(logoImageView.snp.right).offset(logoToRight)
make.right.equalTo(rightArrow.snp.left)
make.top.equalTo(typeTagIcon.snp.bottom).offset(4)
}
rightArrow.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-marginX)
make.width.height.equalTo(arrowWidth)
make.top.equalTo(titleLabel)
}
// 公司名称约束
companyLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(4)
}
vSeparatorLine.snp.makeConstraints { make in
make.left.equalTo(companyLabel.snp.right).offset(marginBetweenVLine)
make.centerY.equalTo(companyLabel)
make.width.equalTo(1)
make.height.equalTo(8)
}
// 行业标签约束
industryLabel.snp.makeConstraints { make in
make.left.equalTo(vSeparatorLine.snp.right).offset(marginBetweenVLine)
make.right.lessThanOrEqualTo(rightArrow.snp.left)
make.top.equalTo(companyLabel)
make.bottom.equalToSuperview().offset(-32)
}
// 分割线约束
separatorLine.snp.makeConstraints { make in
make.bottom.equalToSuperview()
make.left.right.equalToSuperview().inset(20)
make.height.equalTo(0.5)
}
}
private func getLabelWidth(_ text: String) -> CGFloat {
let attrString = NSAttributedString(string: text, attributes: [.font: YHResourceTableViewCell.labelFont])
let width = attrString.yh_width(containerHeight: YHResourceTableViewCell.labelHeight)
return width
}
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
let companyWidth = getLabelWidth(company)
let categoryNameWidth = getLabelWidth(categoryName)
if companyWidth + categoryNameWidth < KScreenWidth - logoWidth - logoToRight - arrowWidth - 2 * marginX - widthVLine - marginBetweenVLine * 2 {
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(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(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(marginBetweenVLine)
make.right.lessThanOrEqualTo(rightArrow.snp.left)
make.top.equalTo(companyLabel.snp.bottom).offset(4)
make.bottom.equalToSuperview().offset(-32)
}
}
// 设置Logo
if !model.company_logo.isEmpty {
logoImageView.kf.setImage(
with: URL(string: model.company_logo),
placeholder: UIImage(named: "global_default_image")
)
} else {
logoImageView.image = UIImage(named: "global_default_image")
}
// 设置类型标签
if model.type == "service" {
typeTagIcon.image = UIImage(named: "resource_flag_service")
} else if model.type == "demand" {
typeTagIcon.image = UIImage(named: "resource_flag_demand")
} else {
typeTagIcon.image = nil
}
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_feed_arrow@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_feed_arrow@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_filter_down@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_filter_down@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_filter_reset@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_filter_reset@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_filter_up@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_filter_up@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_flag_demand@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_flag_demand@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_flag_service@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_flag_service@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "resource_search@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "resource_search@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
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