Commit c0dc9ab4 authored by Steven杜宇's avatar Steven杜宇

Merge branch 'swiftLint-develop' into 'duyu'

垃圾杜宇

See merge request !4
parents 0ee59eb8 341c630a

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
## Build generated ## Build generated
build/ build/
buglybin/
DerivedData/ DerivedData/
Podfile.lock Podfile.lock
...@@ -37,6 +38,7 @@ xcuserdata/ ...@@ -37,6 +38,7 @@ xcuserdata/
*.ipa *.ipa
*.dSYM.zip *.dSYM.zip
*.dSYM *.dSYM
*.zip
## Playgrounds ## Playgrounds
timeline.xctimeline timeline.xctimeline
......
# 执行 linting 时包含的路径。
included:
- galaxy
# 执行 linting 时忽略的路径。 优先级比 `included` 更高。
excluded:
- Pods
# 执行时排除掉的规则
disabled_rules:
# 每一个空行不能有空格,会与Xcode换行后自动对齐生成的空格冲突,建议排除掉
- trailing_whitespace
# 解禁非驼峰
- identifier_name
# 单行代码长度,默认error 120
line_length: 300
# 文件长度
file_length:
warning: 800
error: 2000
# 函数体长度
function_body_length:
warning: 100
error: 300
# 函数参数个数
function_parameter_count:
warning: 10
error: 20
# 函数体复杂度
cyclomatic_complexity:
warning: 50
error: 100
# 类型体长度
type_body_length:
warning: 500
error: 1000
# 参数名称长度,默认3-40
identifier_name:
# 过滤不需要处理的字段
excluded:
- id
- i
- j
- k
- x
- y
- z
- mj_header
- mj_footer
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods"
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
base64
nkf
rexml
activesupport (7.1.3.2)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
aws-partitions (1.919.0)
aws-sdk-core (3.192.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.79.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.147.0)
aws-sdk-core (~> 3, >= 3.192.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
bigdecimal (3.1.7)
claide (1.1.0)
cocoapods (1.15.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.15.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.15.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (2.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
cocoapods-trunk (1.6.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
declarative (0.0.20)
digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
drb (2.2.1)
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
excon (0.110.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.3.1)
fastlane (2.220.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-plugin-pgyer (0.2.9)
fastlane-plugin-upload_to_bugly (0.1.2)
fastlane-plugin-versioning (0.7.1)
ffi (1.16.3)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.7.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.4.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.14.4)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.7.2)
jwt (2.8.1)
base64
mini_magick (4.12.0)
mini_mime (1.1.5)
minitest (5.22.3)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.4.0)
mutex_m (0.2.0)
nanaimo (0.3.0)
nap (1.1.0)
naturally (2.2.1)
netrc (0.11.0)
nkf (0.2.0)
optparse (0.5.0)
os (1.1.4)
plist (3.7.1)
public_suffix (4.0.7)
rake (13.2.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.6)
rouge (2.0.7)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unicode-display_width (2.5.0)
word_wrap (1.0.0)
xcodeproj (1.24.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
x86_64-darwin-23
DEPENDENCIES
cocoapods
fastlane
fastlane-plugin-pgyer
fastlane-plugin-upload_to_bugly
fastlane-plugin-versioning
BUNDLED WITH
2.5.9
# Uncomment the next line to define a global platform for your project # Uncomment the next line to define a global platform for your project
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/aliyun-sls/Specs.git'
platform :ios, '13.0' platform :ios, '13.0'
target 'galaxy' do target 'galaxy' do
use_frameworks! use_frameworks!
#声网SDK播放器等(先弄完整的,后续剪裁)
pod 'AgoraRtcEngine_iOS', '4.4.0' #, :subspecs => ['RtcBasic']
#环信IM 聊天室
pod 'HyphenateChat','4.10.2'
#鸿蒙AGC 短链处理相关
pod 'AGConnectCore','1.9.0.302'
pod 'AGConnectAppLinking','1.9.0.302'
#日历 多时间选择
pod 'FSCalendar',"2.8.4"
#图片预览
pod 'JXPhotoBrowser','3.1.4'
pod 'SDWebImage','5.18.10'
#与H5进行交互
pod "dsBridge",'3.0.6'
#网络检查 #网络检查
pod 'ReachabilitySwift','5.0.0' pod 'ReachabilitySwift','5.0.0'
#键盘处理 #键盘处理
pod 'IQKeyboardManagerSwift','7.0.1' pod 'IQKeyboardManagerSwift','8.0.0'
#网络请求 #网络请求
pod 'Alamofire','5.8.1' pod 'Alamofire','5.8.1'
#图片加载 #图片加载
pod 'Kingfisher','7.10.1' pod 'Kingfisher','7.10.1'
#支持avif格式
pod 'libavif','0.11.1'
#异步编程框架 #异步编程框架
# pod 'RxSwift','6.6.0' # pod 'RxSwift','6.6.0'
# pod 'RxCocoa','6.6.0' # pod 'RxCocoa','6.6.0'
# pod 'RxAlamofire','6.1.1' # pod 'RxAlamofire','6.1.1'
#数据存储 # #数据存储
pod 'SwiftyUserDefaults','5.3.0' # pod 'SwiftyUserDefaults','5.3.0'
#数据加、解密 #数据加、解密
pod 'CryptoSwift','1.8.0' pod 'CryptoSwift','1.8.0'
#手动布局 #手动布局
pod 'SnapKit','5.6.0' pod 'SnapKit','5.0.0'
#底部tabbar布局 #底部tabbar布局
pod 'ESTabBarController-swift' , '2.8.0' pod 'ESTabBarController-swift' , '2.8.0'
#扩展集合 #扩展集合
pod 'SwifterSwift','6.0.0' pod 'SwifterSwift','6.0.0'
#下拉刷新、上拉更多 #下拉刷新、上拉更多
pod 'ESPullToRefresh',"2.9.3" pod 'ESPullToRefresh',"2.9.3"
#Toast # #Toast
pod 'Toast-Swift', '5.0.1' # pod 'Toast-Swift', '5.0.1'
#富文本 UILabel # #富文本 UILabel
pod 'Nantes','0.1.2' # pod 'Nantes','0.1.2'
#提示框 #提示框
pod 'PKHUD','5.3.0' pod 'PKHUD','5.3.0'
#日志 调试 #日志 调试
# pod 'CocoaDebug', '1.7.7' # pod 'CocoaDebug', '1.7.7'
#date分类 # #date分类
pod 'SwiftDate','7.0.0' # pod 'SwiftDate','7.0.0'
#定时器 # #定时器
pod 'SwiftyTimer','2.1.0' # pod 'SwiftyTimer','2.1.0'
#UIColor 的扩展 #UIColor 的扩展
# pod 'Hue','5.0.0' # pod 'Hue','5.0.0'
#内存泄漏 # #内存泄漏
pod 'LifetimeTracker','1.8.1' # pod 'LifetimeTracker','1.8.1'
#控制台转换成中文 # #控制台转换成中文
pod 'ByebyeUnicode','1.1.0' pod 'ByebyeUnicode','1.1.0'
#轮播图 #轮播图
pod 'FSPagerView','0.8.3' pod 'FSPagerView','0.8.3'
#字典、模型互转
pod 'SmartCodable','2.2.2'
#设备框架 #设备框架
pod 'DeviceKit', '5.1.0' pod 'DeviceKit', '5.2.1'
#骨架图 # #骨架图
pod 'SkeletonView','1.30.4' # pod 'SkeletonView','1.30.4'
#导航栏、手势 #导航栏、手势
pod 'GKNavigationBarSwift','1.6.5' pod 'GKNavigationBarSwift','1.6.5'
#crash统计 #crash统计
pod 'Bugly','2.5.93' pod 'Bugly','2.6.1'
#神策数据分析 #神策数据分析
pod 'SensorsAnalyticsSDK','4.6.0' pod 'SensorsAnalyticsSDK','4.8.3'
#主流APP分类切换滚动视图 #主流APP分类切换滚动视图
pod 'JXSegmentedView','1.3.0' pod 'JXSegmentedView','1.3.0'
#UI调试组件 #UI调试组件
pod 'LookinServer','1.2.6',:subspecs => ['Swift'], :configurations => ['Debug'] pod 'LookinServer','1.2.6',:subspecs => ['Swift'], :configurations => ['Debug']
#阿里云OOS #阿里云OOS
pod 'AliyunOSSiOS','2.10.18' pod 'AliyunOSSiOS','2.10.18'
#极光推送
############# 网易云信 IM相关 start ############# pod 'JPush', '5.2.0'
#A 基础Kit库 pod 'JCore', '4.6.0-noidfa'
pod 'NECoreKit', '9.6.5'
pod 'NECoreIMKit', '9.6.5'
pod 'NEChatKit', '9.6.5'
pod 'NECommonKit', '9.6.4'
pod 'NECommonUIKit', '9.6.5'
pod 'NIMSDK_LITE', '9.14.0'
#B UI组件,依次为通讯录组件、会话列表组件、会话(聊天)组件、群相关设置组件
pod 'NEContactUIKit', '9.6.5'
pod 'NEConversationUIKit', '9.6.5'
pod 'NEChatUIKit', '9.6.5'
pod 'NETeamUIKit', '9.6.5'
############# 网易云信 IM相关 end #############
#富文本库 #富文本库
pod 'AttributedString','3.3.5' pod 'AttributedString','3.4.2'
#json转模型 #Json字典、模型互转
pod 'HandyJSON', '5.0.2' pod 'SmartCodable','3.4.0'
end
#微信SDK
pod 'WechatOpenSDK', '2.0.4'
#视频播放器
pod 'BMPlayer', '1.3.0'
#高斯模糊
pod 'VisualEffectView', '4.1.5'
#动画框架
pod 'lottie-ios', '4.4.0'
#GIF图播放
pod 'YYImage', '1.0.4'
#滑动卡片
pod 'DragCardContainer', '1.2.0'
#列表截图
pod 'TYSnapshotScroll', '0.4.0'
#七鱼SDK
pod 'QY_iOS_SDK', '9.9.2'
#阿里云日志
pod 'AliyunLogProducer', '4.3.3'
#加密
pod 'xxtea', '1.0.2'
#代码规范
pod 'SwiftLint', :configurations => ['Debug']
end
post_install do |installer| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
......
# app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app
# apple_id("[[APPLE_ID]]") # Your Apple Developer Portal username
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile
default_platform(:ios)
platform :ios do
desc "Description of what the lane does"
# 打包时候用的名称 例如 fastlane app
bundle_id = "com.intelligence.galaxy"
adhoc_profile_name = "com.adhoc.profile"
release_profile_name = "dis.intelligence.com"
adhoc_pgyer_api_key = "ba79f62a052072f2486ad29632fefd46"
release_pgyer_api_key = "80288e92bc9ff83c45df5d0ee778853b"
# bugly app_id
adhoc_bugly_app_id = "3b10faa43e"
release_bugly_app_id = "5dc2acc53e"
# bugly app_key
adhoc_bugly_app_key = "e4bd292e-596d-4942-afda-dd841808218e"
release_bugly_app_key = "ce23936f-3625-4452-92d9-31551858ae02"
# 上传符号表相对路径
adhoc_symbol_path = "./App/ad-hoc/galaxy.app.dSYM"
release_symbol_path = "./App/Release/galaxy.app.dSYM"
#可以用来打包的分支
develop_branch = "develop"
main_branch = "main"
davidhuang_branch = "davidhuang"
alex_branch = "main-bugfix-alex"
xmas_1130_branch = "qmas-1130"
yinhe_live_1212 = "yinhe-live-1212"
sc_105_branch = "sc-1.0.5"
main_fix = "main-fix"
jiaofei = "jiaofei"
lint = "swiftLint-develop"
#打包正使用的分支
myPack_branch = lint
# 打adhoc包 执行命令 fastlane galaxyTest
lane :galaxyTest do
# add actions here: https://docs.fastlane.tools/actions
sh "git checkout #{myPack_branch}"
# 拉取最新代码
sh "git pull origin #{myPack_branch}"
# 显示git当前分支最新submit id
sh "git rev-parse HEAD"
# 更新pod第三方库
#cocoapods(use_bundle_exec: true)
# 先清空打包路径下的文件
sh "pwd"
sh "rm -rf ../App/ad-hoc/*"
gym(
workspace: 'galaxy.xcworkspace',
# 每次打包之前clean一下
clean: true,
# 打包出 ipa 文件的路径,我放到了桌面文件夹,你自行更改文件夹
output_directory: './App/ad-hoc',
# 打包的名称,可任意取
output_name: 'galaxy.ipa',
# 项目的 scheme,自己项目名 .xcworkspace 前面的项目名就是
scheme: "galaxyForTestArchive",
# 默认 Release,Release or Debug
configuration: 'TestEnv',
# 是否包含 bitcode
include_bitcode: false,
# 是否包含 symbols
include_symbols: true,
# 打包导出方式,包含 app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application
export_method: 'ad-hoc',
# 这个设置是为了设置 xcode 自动配置证书和配置文件,当然也可以手动配置,可以参考文档
# export_xcargs: '-allowProvisioningUpdates',
#手动配置证书和配置文件
export_options: {
signingStyle: "manual",
provisioningProfiles: {
"#{bundle_id}" => "#{adhoc_profile_name}",
}
}
)
# mac上的通知弹窗,通知打包完毕
notification(app_icon: "", title: "manager", subtitle: "打包成功,已导出安装包", message: "准备发布到蒲公英中……")
#配置上传蒲公英账号 蒲公英的 api_key
pgyer(
# 蒲公英 API Key
api_key: "#{adhoc_pgyer_api_key}"
)
# mac上的通知弹窗,通知上传pgy完毕
notification(app_icon: "", title: "manager", subtitle: "安装包上传到蒲公英成功", message: "准备上传符号表到bugly")
#上传符号表
#1、通过 bugly 官网下载 buglyqq-upload-symbol.jar,可直接点击该链接下载
#2、下载后放在 ~/bin/ 文件夹下,文件夹不存在时手动创建
adhoc_version = get_version_number_from_xcodeproj(scheme: "galaxyForTestArchive", xcodeproj: "./galaxy.xcodeproj")
adhoc_build_number = get_build_number_from_xcodeproj(scheme: "galaxyForTestArchive", xcodeproj: "./galaxy.xcodeproj")
adhoc_version_key = "#{adhoc_version}.#{adhoc_build_number}"
# 解压.dSYM.zip
sh "unzip -o ../App/ad-hoc/galaxy.app.dSYM.zip -d ../App/ad-hoc"
upload_to_bugly(
appid: adhoc_bugly_app_id,
appkey: adhoc_bugly_app_key,
bundleid: bundle_id,
version: adhoc_version_key,
inputSymbol: adhoc_symbol_path)
# mac上的通知弹窗,通知上传符号表完毕
notification(app_icon: "", title: "manager", subtitle: "符号表上传到bugly成功", message: "")
end
# 打realease包 执行命令 fastlane galaxyRelease
lane :galaxyRelease do
# add actions here: https://docs.fastlane.tools/actions
sh "git checkout #{myPack_branch}"
# 拉取最新代码
sh "git pull origin #{myPack_branch}"
# 显示git当前分支最新submit id
sh "git rev-parse HEAD"
# 更新pod第三方库
#cocoapods(use_bundle_exec: true)
# 先清空打包路径下的文件
sh "pwd"
sh "rm -rf ../App/Release/*"
gym(
workspace: 'galaxy.xcworkspace',
# 每次打包之前clean一下
clean: true,
# 打包出 ipa 文件的路径,我放到了桌面文件夹,你自行更改文件夹
output_directory: './App/Release',
# 打包的名称,可任意取
output_name: 'galaxy.ipa',
# 项目的 scheme,自己项目名 .xcworkspace 前面的项目名就是
scheme: "galaxy",
# 默认 Release,Release or Debug
configuration: 'Release',
# 是否包含 bitcode
include_bitcode: false,
# 是否包含 symbols
include_symbols: true,
# 打包导出方式,包含 app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application
export_method: 'ad-hoc',
# 这个设置是为了设置 xcode 自动配置证书和配置文件,当然也可以手动配置,可以参考文档
# export_xcargs: '-allowProvisioningUpdates',
#手动配置证书和配置文件
export_options: {
signingStyle: "manual",
provisioningProfiles: {
"#{bundle_id}" => "#{adhoc_profile_name}",
}
}
)
# mac上的通知弹窗,通知打包完毕
notification(app_icon: "", title: "manager", subtitle: "打包成功,已导出安装包", message: "准备发布到蒲公英中……")
#配置上传蒲公英账号 蒲公英的 api_key和 user_key 用自己蒲公英账号的,别用我的!!!如果没有可删除
pgyer(
# 蒲公英 API Key
api_key: "#{release_pgyer_api_key}"
)
# mac上的通知弹窗,通知上传pgy完毕
notification(app_icon: "", title: "manager", subtitle: "安装包上传到蒲公英成功", message: "准备上传符号表到bugly")
release_version = get_version_number_from_xcodeproj(scheme: "galaxy", xcodeproj: "./galaxy.xcodeproj")
release_build_number = get_build_number_from_xcodeproj(scheme: "galaxy", xcodeproj: "./galaxy.xcodeproj")
release_version_key = "#{release_version}.#{release_build_number}"
# 解压.dSYM.zip
sh "unzip -o ../App/Release/galaxy.app.dSYM.zip -d ../App/Release"
upload_to_bugly(
appid: release_bugly_app_id,
appkey: release_bugly_app_key,
bundleid: bundle_id,
version: release_version_key,
inputSymbol: release_symbol_path)
# mac上的通知弹窗,通知上传符号表完毕
notification(app_icon: "", title: "manager", subtitle: "符号表上传到bugly成功", message: "")
end
# 打uat包 执行命令 fastlane galaxyUat
lane :galaxyUat do
# add actions here: https://docs.fastlane.tools/actions
sh "git checkout #{myPack_branch}"
# 拉取最新代码
sh "git pull origin #{myPack_branch}"
# 显示git当前分支最新submit id
# sh "git rev-parse HEAD"
# 更新pod第三方库
# cocoapods(use_bundle_exec: true)
gym(
workspace: 'galaxy.xcworkspace',
# 每次打包之前clean一下
clean: true,
# 打包出 ipa 文件的路径,我放到了桌面文件夹,你自行更改文件夹
output_directory: './App/uat',
# 打包的名称,可任意取
output_name: 'galaxy-uat.ipa',
# 项目的 scheme,自己项目名 .xcworkspace 前面的项目名就是
scheme: "galaxyForUat",
# 默认 Release,Release or Debug
configuration: 'UatEnv',
# 是否包含 bitcode
include_bitcode: false,
# 是否包含 symbols
include_symbols: true,
# 打包导出方式,包含 app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application
export_method: 'ad-hoc',
# 这个设置是为了设置 xcode 自动配置证书和配置文件,当然也可以手动配置,可以参考文档
# export_xcargs: '-allowProvisioningUpdates',
#手动配置证书和配置文件
export_options: {
signingStyle: "manual",
provisioningProfiles: {
"#{bundle_id}" => "#{adhoc_profile_name}",
}
}
)
# # mac上的通知弹窗,通知打包完毕
# notification(app_icon: "./fastlane/icon.png", title: "manager", subtitle: "打包成功,已导出安装包", message: "准备发布到蒲公英中……")
# #配置上传蒲公英账号 蒲公英的 api_key和 user_key 用自己蒲公英账号的,别用我的!!!如果没有可删除
# pgyer(
# # 蒲公英 API Key
# api_key: "#{adhoc_pgyer_api_key}"
# )
end
end
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
gem 'fastlane-plugin-pgyer'
gem 'fastlane-plugin-upload_to_bugly'
gem 'fastlane-plugin-versioning'
fastlane documentation
----
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```sh
xcode-select --install
```
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
# Available Actions
## iOS
### ios galaxyTest
```sh
[bundle exec] fastlane ios galaxyTest
```
Description of what the lane does
### ios galaxyRelease
```sh
[bundle exec] fastlane ios galaxyRelease
```
### ios galaxyUat
```sh
[bundle exec] fastlane ios galaxyUat
```
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
1. 安装环境
1.1 安装 Homebrew
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
1.2 安装 fastlane
brew install fastlane
2. fastlane 配置
2.1 进入到工程目录 .xcworkspace 下面
2.2 初始化 fastlane
执行终端命令 fastlane init
会显示4个选项 输入4并按下enter 表示手动配置你的项目
完成后项目文件夹下会多几个文件Gemfile, Gemfile.lock 和文件夹
2.3 加入蒲公英插件
执行终端命令 fastlane add_plugin pgyer 或者 bundle exec fastlane add_plugin pgyer
3. fastlane 自动打包上传
3.1
Fastlane文件夹下的Fastlane文件已写好,只需修改output_directory的值为你本地文件夹路径即可
3.2
执行终端命令 fastlane galaxy 或者 bundle exec fastlane galaxy
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1520"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573EE32B317C0100D98EC0"
BuildableName = "galaxyTests.xctest"
BlueprintName = "galaxyTests"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573EED2B317C0100D98EC0"
BuildableName = "galaxyUITests.xctest"
BlueprintName = "galaxyUITests"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1520"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "TestEnv"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1520"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5573ECD2B317BFF00D98EC0"
BuildableName = "galaxy.app"
BlueprintName = "galaxy"
ReferencedContainer = "container:galaxy.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "UatRelease"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
This diff is collapsed.
//
// Applegate(JPush).swift
// galaxy
//
// Created by edy on 2024/3/27.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import AuthenticationServices
extension AppDelegate: JPUSHRegisterDelegate {
// 注册JPush服务
func registerJPushService(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
let entity: JPUSHRegisterEntity = JPUSHRegisterEntity()
entity.types = Int(JPAuthorizationOptions.alert.rawValue |
JPAuthorizationOptions.badge.rawValue |
JPAuthorizationOptions.sound.rawValue |
JPAuthorizationOptions.providesAppNotificationSettings.rawValue)
JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
// Required
// init Push
// notice: 2.1.5 版本的 SDK 新增的注册方法,改成可上报 IDFA,如果没有使用 IDFA 直接传 nil
// 初始化极光推送服务,调用了本 API 后,开启 JPush 推送服务,将会开始收集上报 SDK 业务功能所必要的用户个人信息
// [JPUSHService setupWithOption:launchOptions appKey:appKey
// channel:channel
// apsForProduction:isProduction
// advertisingIdentifier:advertisingId];
#if DEBUG
let isProduction = false
#elseif TESTENV
let isProduction = true
#else
let isProduction = true
#endif
JPUSHService.setup(withOption: launchOptions,
appKey: YhConstant.Jpush.appKey,
channel: "appStore",
apsForProduction: isProduction)
}
// 系统获取Token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenStr = deviceToken.map {String(format: "%02.2hhx", arguments: [$0]) }.joined()
print("deviceToken:\(deviceTokenStr)")
JPUSHService.registerDeviceToken(deviceToken)
YHLoginManager.shared.deviceTokenModel.deviceToken = deviceTokenStr
YHButlerServiceManager.shared.updateApnsToken(token: deviceToken)
}
// 获取token 失败
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { // 可选
print("did Fail To Register For Remote Notifications With Error: \(error)")
#if DEBUG
YHHUD.flash(message: error.localizedDescription)
#elseif TESTENV
YHHUD.flash(message: error.localizedDescription)
#else
#endif
}
// 点推送进来执行这个方法
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
JPUSHService.handleRemoteNotification(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
// 转换到消息tab
YHLoginManager.shared.needJumpToMsgTabFlag = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
goToMessagePage()
})
}
// 后台进前台
func applicationWillEnterForeground(_ application: UIApplication) {
DispatchQueue.main.async {
// 请求消息页面通知权限通知
NotificationCenter.default.post(name: YhConstant.YhNotification.didReqeustNotifyPermissionNotification, object: nil)
}
clearAllUnreadBadge()
YHOSSManager.share.getOSSID()
}
func jpushNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: ((Int) -> Void)) {
let userInfo = notification.request.content.userInfo
if notification.request.trigger is UNPushNotificationTrigger {
JPUSHService.handleRemoteNotification(userInfo)
}
// 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以选择设置
completionHandler(Int(UNNotificationPresentationOptions.alert.rawValue))
// 显示通知时需要刷新消息列表和消息未读总数
DispatchQueue.main.async {
// 请求消息未读总数通知
NotificationCenter.default.post(name: YhConstant.YhNotification.didRequestUnreadMsgTotalCountNotification, object: nil)
// 请求消息列表通知
NotificationCenter.default.post(name: YhConstant.YhNotification.didRequestUnreadMsgListNotification, object: nil)
// 更新首页消息
NotificationCenter.default.post(name: YhConstant.YhNotification.didRevMsgNotifiction, object: nil)
}
}
func jpushNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: (() -> Void)) {
let userInfo = response.notification.request.content.userInfo
if response.notification.request.trigger is UNPushNotificationTrigger {
JPUSHService.handleRemoteNotification(userInfo)
}
// 系统要求执行这个方法
completionHandler()
// 转换到消息tab
YHLoginManager.shared.needJumpToMsgTabFlag = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
goToMessagePage()
})
}
func jpushNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification) {
}
func jpushNotificationAuthorization(_ status: JPAuthorizationStatus, withInfo info: [AnyHashable: Any]?) {
}
}
extension AppDelegate {
func handleAppleLoginUser() {
if #available(iOS 13.0, *) {
// 注意 存储用户标识信息需要使用钥匙串来存储 这里使用NSUserDefaults 做的简单示例
let userIdentifier = UserDefaults.standard.value(forKey: "appleID") as? String
if let userIdentifier = userIdentifier {
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: userIdentifier) {
credentialState, _ in
switch credentialState {
case .authorized:
// 授权状态有效
break
case .revoked:
// 苹果账号登录的凭据已被移除,需解除绑定并重新引导用户使用苹果登录
break
case .notFound:
// 未登录授权,直接弹出登录页面,引导用户登录
break
case .transferred:
// 授权AppleID提供者凭据转移
break
default:
break
}
}
}
}
}
private func clearAllUnreadBadge() {
DispatchQueue.main.async {
if #available(iOS 16.0, *) {
UNUserNotificationCenter.current().setBadgeCount(0)
} else {
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
}
}
...@@ -14,19 +14,24 @@ class YHBaseViewController: UIViewController { ...@@ -14,19 +14,24 @@ class YHBaseViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
//背景色 // 背景色
view.backgroundColor = UIColor.pageBkgColor view.backgroundColor = UIColor.pageBkgColor
//vc中导航栏默认透明,需要使用到的 在各自的vc中定制 // vc中导航栏默认透明,需要使用到的 在各自的vc中定制
gk_navBackgroundColor = .clear gk_navBackgroundColor = .clear
gk_navLineHidden = true gk_navLineHidden = true
gk_navBarAlpha = 0 gk_navBarAlpha = 0
gk_backImage = UIImage(named: "back_icon")
#if DEBUG #if DEBUG
IQKeyboardManager.shared.enable = true IQKeyboardManager.shared.isEnabled = true
#endif #endif
// navigationController?.interactivePopGestureRecognizer?.delegate = self
if let key = getKeys(), !key.isEmpty {
YHAnalytics.track(key)
}
} }
override var prefersStatusBarHidden: Bool { override var prefersStatusBarHidden: Bool {
...@@ -42,4 +47,77 @@ class YHBaseViewController: UIViewController { ...@@ -42,4 +47,77 @@ class YHBaseViewController: UIViewController {
printLog(#function) printLog(#function)
#endif #endif
} }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let key = getKeys(), !key.isEmpty {
YHAnalytics.timeStrat(key)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let key = getKeys(), !key.isEmpty {
YHAnalytics.timeEnd(key)
}
}
func getKeys() -> String? {
let key = String(describing: type(of: self))
if YHAnalyticsUnit.events.keys.contains(key) {
guard let event = YHAnalyticsUnit.events[key] else { return nil}
if key == "YHHomeInfoDetailContainerViewController" || key == "YHH5WebViewVC" || key == "YHAIRobotChatViewController" {
let subevent = self.title ?? ""
let events = event as? [String: String] ?? [:]
if events.keys.contains(subevent) {
guard let subEvent = events[subevent] else { return nil}
return subEvent
}
}
if let value = event as? String {
return value
}
}
return nil
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}
func popGestureClose() {
if let ges = self.navigationController?.interactivePopGestureRecognizer?.view?.gestureRecognizers {
for item in ges {
item.isEnabled = false
}
}
}
func popGestureOpen() {
if let ges = self.navigationController?.interactivePopGestureRecognizer?.view?.gestureRecognizers {
for item in ges {
item.isEnabled = false
}
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if children.count == 1 {
return false
} else {
return true
}
}
} }
// extension YHBaseViewController: UIGestureRecognizerDelegate {
//// 这个方法是在手势将要激活前调用
//// 返回YES允许右滑手势的激活,返回NO不允许右滑手势的激活
// func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// return true
// }
// }
...@@ -8,9 +8,6 @@ ...@@ -8,9 +8,6 @@
import UIKit import UIKit
class YHNavigationController: UINavigationController { class YHNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) { override func pushViewController(_ viewController: UIViewController, animated: Bool) {
// 隐藏要push的控制器的tabbar // 隐藏要push的控制器的tabbar
...@@ -20,3 +17,23 @@ class YHNavigationController: UINavigationController { ...@@ -20,3 +17,23 @@ class YHNavigationController: UINavigationController {
super.pushViewController(viewController, animated: animated) super.pushViewController(viewController, animated: animated)
} }
} }
// extension YHNavigationController: UIGestureRecognizerDelegate {
// func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// if self.viewControllers.count <= 1 {
// return false
// }
// return true
// }
//
// func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
// if touch.view == gestureRecognizer.view {
// return true
// }
// return false
// }
//
// func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// return false
// }
// }
...@@ -8,52 +8,194 @@ ...@@ -8,52 +8,194 @@
import UIKit import UIKit
import ESTabBarController_swift import ESTabBarController_swift
class YHTabBarViewController: ESTabBarController { class YHTabBarViewController: ESTabBarController {
lazy var viewModel = {
let model = YHMsgViewModel()
return model
}()
let msgViewModel = YHMsgViewModel()
lazy var shareView: YHShareViewOnTablebarView = {
let view = YHShareViewOnTablebarView()
view.isHidden = true
return view
}()
private var shareModel: TabBarShareModel?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
shareView.frame = self.tabBar.frame
view.bringSubviewToFront(shareView)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
handleTabBarLine() handleTabBarLine()
addObservers()
if YHLoginManager.shared.isLogin() {
reportDeviceInfo()
}
shareView.frame = self.tabBar.frame
view.addSubview(shareView)
shareView.block = { tag in
if let model = self.shareModel {
if tag == 0 {
// 分享
let title = !model.shareTitle.isEmpty ? model.shareTitle : "请查看"
YHShareManager.shared.shareToMiniProgram(path: model.shareUrl, shareTitle: title)
} else {
// 预约咨询
let codeUrl = model.codeUrl
let downloadUrl = model.downloadUrl
YHConsultantQRCodeView.codeView(codeUrl, downloadUrl: downloadUrl).show()
}
}
}
getTotalUnreadMsgCount()
}
func addObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(loginSuccess), name: YhConstant.YhNotification.didLoginSuccessNotifiction, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(logoutSuccess), name: YhConstant.YhNotification.didLogoutSuccessNotifiction, object: nil)
// self.tabBar.shadowImage = UIImage() NotificationCenter.default.addObserver(self, selector: #selector(changeShareViewStatus(_ :)), name: YhConstant.YhNotification.changeShareViewStatusOnTabBarNotifiction, object: nil)
// self.tabBar.backgroundImage = UIImage()
NotificationCenter.default.addObserver(self, selector: #selector(getTotalUnreadMsgCount), name: YhConstant.YhNotification.didRequestUnreadMsgTotalCountNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(getTotalUnreadMsgCount), name: YhConstant.YhNotification.didQiYuUnReadMsgCountChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(clearFriendTabBadge), name: YhConstant.YhNotification.didMarkAllMessagesReadedNotifiction, object: nil)
}
@objc func getTotalUnreadMsgCount() {
if !YHLoginManager.shared.isLogin() {
return
}
// NotificationCenter.default.addObserver(self, selector: #selector(hideTabBar), name: BsConstant.BsNotification.tabBarHideNotification, object: nil) self.msgViewModel.requestTotalUnreadMsgCount {
// [weak self] _, _ in
// NotificationCenter.default.addObserver(self, selector: #selector(showTabBar), name: BsConstant.BsNotification.tabBarShowNotification, object: nil) guard let self = self else { return }
DispatchQueue.main.async {
var unreadCount = self.msgViewModel.unreadTotalCount
if YHButlerServiceManager.shared.isUatAllowed() {
unreadCount = self.msgViewModel.unreadTotalCount + YHButlerServiceManager.shared.unreadCount
}
// 朋友tab小红点显示逻辑
self.showFriendTabRedBadgeNumber(unreadCount)
}
}
}
@objc func clearFriendTabBadge() {
showFriendTabRedBadgeNumber(0)
}
func showFriendTabRedBadgeNumber(_ num: Int) {
if let vcs = self.viewControllers, vcs.count > 3 {
let friendVC = vcs[3]
if let tabBarItem = friendVC.tabBarItem as? ESTabBarItem {
// badgeValue 空字符串会显示小红点 nil则隐藏
var badge: String?
if num > 99 {
badge = "99+"
} else if 0 < num, num <= 99 {
badge = "\(num)"
}
tabBarItem.badgeColor = UIColor.init(hex: 0xF81D22)
tabBarItem.contentView?.badgeView.badgeLabel.font = UIFont.PFSC_M(ofSize: 10)
tabBarItem.badgeValue = badge
}
}
} }
} }
extension YHTabBarViewController { extension YHTabBarViewController {
@objc func hideTabBar() -> Void { @objc func hideTabBar() {
self.tabBar.isHidden = true self.tabBar.isHidden = true
} }
@objc func showTabBar() -> Void { @objc func showTabBar() {
self.tabBar.isHidden = false self.tabBar.isHidden = false
} }
@objc func loginSuccess() {
printLog("登录成功,进行相应的 UI刷新操作")
getTotalUnreadMsgCount()
}
@objc func logoutSuccess() {
printLog("登出成功")
clearFriendTabBadge()
}
@objc func changeShareViewStatus(_ notification: Notification) {
if let model = notification.object as? TabBarShareModel {
shareModel = model
if model.showFlag {
if self.shareView.isHidden {
self.shareView.isHidden = false
self.shareView.layer.opacity = 0.0
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) {
self.shareView.layer.opacity = 1.0
} completion: { _ in }
}
} else {
if self.shareView.isHidden == false {
shareView.layer.opacity = 1.0
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseOut]) {
self.shareView.layer.opacity = 0.0
} completion: { _ in
self.shareView.isHidden = true
}
}
}
}
}
func reportDeviceInfo() {
if !YHLoginManager.shared.isLogin() {
return
}
JPUSHService.registrationIDCompletionHandler {
_, registrationID in
if let deviceId = registrationID, !deviceId.isEmpty {
printLog("deviceId:\(deviceId)")
YHLoginManager.shared.deviceTokenModel.registerId = deviceId
self.viewModel.requestReportDeviceInfo(deviceId: deviceId) {
_, error in
if let error = error, !error.errorMsg.isEmpty {
printLog("error:\(error.errorMsg)")
}
}
}
}
}
} }
extension YHTabBarViewController { extension YHTabBarViewController {
//展示tabbar上的横线 // 展示tabbar上的横线
func handleTabBarLine() -> Void { func handleTabBarLine() {
let rect = CGRect.init(x:0,y:0,width:KScreenWidth,height:0.5) let rect = CGRect.init(x: 0, y: 0, width: KScreenWidth, height: 0.5)
let fillColor = UIColor(hex:0x888888) let fillColor = UIColor.mainTextColor5
let img = UIImage.from(color: fillColor, rect: rect) let img = UIImage.from(color: fillColor, rect: rect)
UIView.transition(with:self.tabBar, duration:0.5, options: .transitionCrossDissolve) { UIView.transition(with: self.tabBar, duration: 0.5, options: .transitionCrossDissolve) {
if #available(iOS 13.0, *) { let appearance = self.tabBar.standardAppearance.copy()
let appearance = self.tabBar.standardAppearance.copy() appearance.backgroundImage = UIImage()
appearance.backgroundImage = UIImage() appearance.shadowImage = img
appearance.shadowImage = img self.tabBar.standardAppearance = appearance
self.tabBar.standardAppearance = appearance } completion: { _ in
}
else{
self.tabBar.backgroundImage = UIImage()
self.tabBar.shadowImage = img
}
} completion: { Bool in
} }
} }
} }
// //
// YHBaseModel.swift // SmartCodable.swift
// galaxy // galaxy
// //
// Created by EDY on 2024/2/28. // Created by EDY on 2024/2/28.
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
// //
import UIKit import UIKit
import HandyJSON import SmartCodable
class YHBaseModel: HandyJSON { // class SmartCodable: SmartCodable {
required init() { // required init() {
// }
} // }
}
//
// YHAITabBarItem.swift
// galaxy
//
// Created by Dufet on 2024/11/26.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import ESTabBarController_swift
import Lottie
class YHAITabBarItemContentView: ESTabBarItemContentView {
var timer: Timer?
lazy var tipsView: UIView = {
let v = UIView()
let grayView = UIView()
grayView.backgroundColor = UIColor(hex: 0x000000, alpha: 0.6)
grayView.layer.cornerRadius = 6.0
grayView.clipsToBounds = true
v.addSubview(grayView)
let label = UILabel()
label.textColor = UIColor.white
label.textAlignment = .center
label.font = UIFont.PFSC_R(ofSize: 12)
label.text = "Hi 我是港小宝,有什么需要帮助的,来找我吧~"
grayView.addSubview(label)
let arrowImgV = UIImageView(image: UIImage(named: "ai_tab_down_arrow"))
v.addSubview(arrowImgV)
arrowImgV.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.width.equalTo(24)
make.height.equalTo(6)
make.bottom.equalTo(-4)
}
label.snp.makeConstraints { make in
make.left.equalTo(15)
make.right.equalTo(-15)
make.height.equalTo(34)
make.top.bottom.equalToSuperview()
}
grayView.snp.makeConstraints { make in
make.left.equalTo(0)
make.right.equalTo(0)
make.top.equalToSuperview()
make.bottom.equalTo(arrowImgV.snp.top)
}
return v
}()
lazy var bottomTitleLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.mainTextColor
label.textAlignment = .center
label.font = UIFont.PFSC_R(ofSize: 10)
label.text = "港小宝"
return label
}()
lazy var iconImgView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "tab_ai")
lottieView.loopMode = .loop
lottieView.contentMode = .scaleAspectFit
lottieView.play()
return lottieView
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createUI() {
self.removeSubviews()
self.addSubview(iconImgView)
self.addSubview(bottomTitleLabel)
self.addSubview(tipsView)
bottomTitleLabel.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(14)
}
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(48.0)
make.bottom.equalTo(bottomTitleLabel.snp.top)
make.centerX.equalToSuperview()
}
tipsView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.bottom.equalTo(iconImgView.snp.top)
}
startTimer()
}
func startTimer() {
// 每隔 1 秒调用 timerFired 方法
timer = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(timerFired),
userInfo: nil,
repeats: false)
}
@objc func timerFired() {
stopTimer()
tipsView.isHidden = true
}
// 停止定时器
func stopTimer() {
timer?.invalidate()
timer = nil
}
deinit {
// 确保在视图控制器被销毁时停止定时器
stopTimer()
}
}
//
// YHAutoTextView.swift
// galaxy
//
// Created by Dufet on 2024/11/20.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAutoTextView: UITextView, UITextViewDelegate {
private var calculateHeight: CGFloat = 0.0
var isShowKeyboard: Bool = false {
didSet {
if !isShowKeyboard {
self.snp.updateConstraints { make in
make.top.equalTo(5)
make.height.equalTo(36)
make.bottom.equalTo(-5)
}
} else {
var realHeight = self.calculateHeight
if self.calculateHeight > maxHeight {
realHeight = maxHeight
self.snp.updateConstraints { make in
make.top.equalTo(11)
make.height.equalTo(realHeight)
make.bottom.equalTo(-11)
}
} else {
self.snp.updateConstraints { make in
make.top.equalTo(11-Self.verticalGap)
make.height.equalTo(realHeight)
make.bottom.equalTo(-(11-Self.verticalGap))
}
}
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var textChange: ((String) -> Void)?
override open var text: String! {
didSet {
textViewDidChange(self)
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
let maxHeight = 80.0
static let verticalGap = 5.0
var placeHolder: String = "" {
didSet {
placeholderLabel.text = placeHolder
}
}
lazy var placeholderLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.init(hex: 0xB3C8E9)
label.font = UIFont.PFSC_R(ofSize: 14)
return label
}()
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
self.font = .PFSC_R(ofSize: 14)
delegate = self
isScrollEnabled = false // 禁止滚动
self.addSubview(placeholderLabel)
placeholderLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
make.left.equalTo(5)
make.right.equalTo(-5)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// UITextViewDelegate 方法
func textViewDidChange(_ textView: UITextView) {
// 更新自身的高度
invalidateIntrinsicContentSize()
placeholderLabel.isHidden = !textView.text.isEmpty
textChange?(textView.text)
}
override var intrinsicContentSize: CGSize {
// 计算内容的尺寸
// var height = self.getHeight(text: self.text, font: self.font!, width: frame.width)
// if height < 20.0 {
// height = 20.0
// }
// // 加上textView周边的缝隙
// height += 15.0
let size = sizeThatFits(CGSize(width: frame.width, height: .greatestFiniteMagnitude))
var height = size.height
self.calculateHeight = height
isScrollEnabled = height > maxHeight
if height > maxHeight {
height = maxHeight
self.snp.updateConstraints { make in
make.top.equalTo(11)
make.height.equalTo(height)
make.bottom.equalTo(-11)
}
} else {
self.snp.updateConstraints { make in
make.top.equalTo(11-Self.verticalGap)
make.height.equalTo(height)
make.bottom.equalTo(-(11-Self.verticalGap))
}
}
return CGSize(width: size.width, height: height)
}
func getHeight(text: String, font: UIFont, width: CGFloat) -> CGFloat {
let size = CGSize.init(width: width, height: CGFloat(MAXFLOAT))
let dic = [NSAttributedString.Key.font: font]
let strSize = text.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: dic, context: nil).size
return CGSize(width: strSize.width, height: ceil(strSize.height)).height
}
}
//
// YHBaseCornerRadiusBorderView.swift
// galaxy
//
// Created by alexzzw on 2024/9/20.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHBaseCornerRadiusBorderView: UIView {
private var radius: CGFloat = 2
private var corner: UIRectCorner = .allCorners
var lineWidth: CGFloat? {
didSet {
if lineWidth != oldValue {
boarderLayers?.forEach {
$0.removeFromSuperlayer()
}
boarderLayers = nil
boarderLayers = createRoundedCornersAndBorder(corners: corner, radii: CGSize(width: radius, height: radius), lineWidth: lineWidth, lineColor: lineColor)
}
}
}
var lineColor: CGColor? {
didSet {
if lineColor != oldValue {
boarderLayers?.forEach {
$0.removeFromSuperlayer()
}
boarderLayers = nil
boarderLayers = createRoundedCornersAndBorder(corners: corner, radii: CGSize(width: radius, height: radius), lineWidth: lineWidth, lineColor: lineColor)
}
}
}
public init(cornerRadius: CGFloat, corner: UIRectCorner, lineWidth: CGFloat?, lineColor: CGColor?) {
self.corner = corner
self.radius = cornerRadius
self.lineWidth = lineWidth
self.lineColor = lineColor
super.init(frame: CGRect.zero)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private var boarderLayers: [CAShapeLayer]?
private var viewBounds = CGRect.zero {
didSet {
boarderLayers?.forEach {
$0.removeFromSuperlayer()
}
boarderLayers = nil
boarderLayers = createRoundedCornersAndBorder(corners: corner, radii: CGSize(width: radius, height: radius), lineWidth: lineWidth, lineColor: lineColor)
}
}
override public func layoutSubviews() {
super.layoutSubviews()
viewBounds = bounds
}
}
//
// YHBaseDynamicCornerRadiusView.swift
// galaxy
//
// Created by alexzzw on 2024/9/11.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHBaseDynamicCornerRadiusView: UIView {
public var radius: CGFloat = 8
public var corner: UIRectCorner? {
didSet {
if corner != oldValue {
layoutSubviews()
}
}
}
public init(cornerRadius: CGFloat, corner: UIRectCorner? = nil) {
self.corner = corner
self.radius = cornerRadius
super.init(frame: CGRect.zero)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private var boarderLayer: CAShapeLayer?
private var viewBounds = CGRect.zero {
didSet {
boarderLayer?.removeFromSuperlayer()
boarderLayer = nil
if let corner = corner {
boarderLayer = createCorner(CGSize(width: radius, height: radius), corner)
}
}
}
override public func layoutSubviews() {
super.layoutSubviews()
viewBounds = bounds
}
}
...@@ -8,22 +8,197 @@ ...@@ -8,22 +8,197 @@
import UIKit import UIKit
import ESTabBarController_swift import ESTabBarController_swift
import Lottie
class YHBasicContentView: ESTabBarItemContentView { class YHBasicContentView: ESTabBarItemContentView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
textColor = UIColor.init(white: 175.0 / 255.0, alpha: 1.0)
highlightTextColor = .brandMainColor // 此渲染模式会影响图片颜色哦
iconColor = UIColor.init(white: 175.0 / 255.0, alpha: 1.0) renderingMode = .alwaysOriginal
highlightIconColor = .brandMainColor
titleLabel.font = UIFont.PFSC_R(ofSize: 10) textColor = UIColor.mainTextColor
highlightTextColor = UIColor.mainTextColor
titleLabel.font = UIFont.PFSC_R(ofSize: 14)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class YHHomeLottieAnimateContentView: YHBasicContentView {
let lottieView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "home")
lottieView.loopMode = .playOnce
lottieView.contentMode = .scaleAspectFit
lottieView.isHidden = true
return lottieView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(lottieView)
} }
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func updateLayout() {
super.updateLayout()
lottieView.snp.makeConstraints { make in
make.height.width.equalTo(25)
make.center.equalTo(self.imageView.snp.center)
}
}
override func selectAnimation(animated: Bool, completion: (() -> Void)?) {
super.selectAnimation(animated: animated, completion: nil)
lottieView.isHidden = false
imageView.isHidden = true
lottieView.play { _ in
self.imageView.isHidden = false
}
}
override func deselectAnimation(animated: Bool, completion: (() -> Void)?) {
super.deselectAnimation(animated: animated, completion: nil)
lottieView.isHidden = true
imageView.isHidden = false
}
}
class YHServiceLottieAnimateContentView: YHBasicContentView {
let lottieView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "service")
lottieView.loopMode = .playOnce
lottieView.contentMode = .scaleAspectFit
lottieView.isHidden = true
return lottieView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(lottieView)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateLayout() {
super.updateLayout()
lottieView.snp.makeConstraints { make in
make.height.width.equalTo(25)
make.center.equalTo(self.imageView.snp.center)
}
}
override func selectAnimation(animated: Bool, completion: (() -> Void)?) {
super.selectAnimation(animated: animated, completion: nil)
lottieView.isHidden = false
imageView.isHidden = true
lottieView.play { _ in
self.imageView.isHidden = false
}
}
override func deselectAnimation(animated: Bool, completion: (() -> Void)?) {
super.deselectAnimation(animated: animated, completion: nil)
lottieView.isHidden = true
imageView.isHidden = false
}
}
class YHCommunityLottieAnimateContentView: YHBasicContentView {
let lottieView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "community")
lottieView.loopMode = .playOnce
lottieView.contentMode = .scaleAspectFit
lottieView.isHidden = true
return lottieView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(lottieView)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateLayout() {
super.updateLayout()
lottieView.snp.makeConstraints { make in
make.height.width.equalTo(25)
make.center.equalTo(self.imageView.snp.center)
}
}
override func selectAnimation(animated: Bool, completion: (() -> Void)?) {
super.selectAnimation(animated: animated, completion: nil)
lottieView.isHidden = false
imageView.isHidden = true
lottieView.play { _ in
self.imageView.isHidden = false
}
}
override func deselectAnimation(animated: Bool, completion: (() -> Void)?) {
super.deselectAnimation(animated: animated, completion: nil)
lottieView.isHidden = true
imageView.isHidden = false
}
}
class YHMyLottieAnimateContentView: YHBasicContentView {
let lottieView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "my")
lottieView.loopMode = .playOnce
lottieView.contentMode = .scaleAspectFit
lottieView.isHidden = true
return lottieView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(lottieView)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateLayout() {
super.updateLayout()
lottieView.snp.makeConstraints { make in
make.height.width.equalTo(25)
make.center.equalTo(self.imageView.snp.center)
}
}
override func selectAnimation(animated: Bool, completion: (() -> Void)?) {
super.selectAnimation(animated: animated, completion: nil)
lottieView.isHidden = false
imageView.isHidden = true
lottieView.play { _ in
self.imageView.isHidden = false
}
}
override func deselectAnimation(animated: Bool, completion: (() -> Void)?) {
super.deselectAnimation(animated: animated, completion: nil)
lottieView.isHidden = true
imageView.isHidden = false
}
} }
...@@ -20,19 +20,19 @@ class YHBouncesContentView: YHBasicContentView { ...@@ -20,19 +20,19 @@ class YHBouncesContentView: YHBasicContentView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func selectAnimation(animated: Bool, completion: (() -> ())?) { override func selectAnimation(animated: Bool, completion: (() -> Void)?) {
self.bounceAnimation() self.bounceAnimation()
completion?() completion?()
} }
override func reselectAnimation(animated: Bool, completion: (() -> ())?) { override func reselectAnimation(animated: Bool, completion: (() -> Void)?) {
self.bounceAnimation() self.bounceAnimation()
completion?() completion?()
} }
func bounceAnimation() { func bounceAnimation() {
let impliesAnimation = CAKeyframeAnimation(keyPath: "transform.scale") let impliesAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
impliesAnimation.values = [1.0 ,1.4, 0.9, 1.15, 0.95, 1.02, 1.0] impliesAnimation.values = [1.0, 1.4, 0.9, 1.15, 0.95, 1.02, 1.0]
impliesAnimation.duration = duration * 2 impliesAnimation.duration = duration * 2
impliesAnimation.calculationMode = CAAnimationCalculationMode.cubic impliesAnimation.calculationMode = CAAnimationCalculationMode.cubic
imageView.layer.add(impliesAnimation, forKey: nil) imageView.layer.add(impliesAnimation, forKey: nil)
......
//
// YHEmptyDataView.swift
// galaxy
//
// Created by edy on 2024/5/16.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
// 通用空视图
let kEmptyCommonBgName = "no_data_bg_common"
// 搜索空视图
let kEmptySearchBgName = "no_data_bg_search"
// 消息空视图
let kEmptyMessageBgName = "no_data_bg_msg"
// 订单空视图
let kEmptyOrderBgName = "no_data_bg_order"
// 无网络空视图
let kNotNetWorkBgName = "no_network_bg"
// 人脉无好友空视图
let kNoFriendsBgName = "people_no_friend_bg"
class YHEmptyDataView: UIView {
// 组件视图总高度
static let fixHeight = imgHeight + tipsHeight + gap
static let imgHeight = 128.0
static let tipsHeight = 20.0
static let gap = 16.0
var bgName: String = kEmptyCommonBgName {
didSet {
emptyBgImgV.image = UIImage(named: bgName)
}
}
var tips: String = "暂无内容" {
didSet {
tipsLabel.text = tips
}
}
var topMargin: Double = 0.0 {
didSet {
emptyBgImgV.snp.updateConstraints { make in
make.top.equalToSuperview().offset(topMargin)
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var emptyBgImgV: UIImageView = {
let imgView = UIImageView(image: UIImage(named: kEmptyCommonBgName))
return imgView
}()
var tipsLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.mainTextColor50
label.font = UIFont.PFSC_R(ofSize: 14)
label.textAlignment = .center
label.text = "暂无内容".local
return label
}()
static func createView(_ tips: String = "暂无内容", _ bgName: String = kEmptyCommonBgName) -> YHEmptyDataView {
let view = YHEmptyDataView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: self.fixHeight))
view.bgName = bgName
view.tips = tips
return view
}
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createUI() {
self.addSubview(emptyBgImgV)
self.addSubview(tipsLabel)
emptyBgImgV.snp.makeConstraints { make in
make.top.equalToSuperview().offset(0)
make.width.height.equalTo(Self.imgHeight)
make.centerX.equalTo(self)
}
tipsLabel.snp.makeConstraints { make in
make.top.equalTo(emptyBgImgV.snp.bottom).offset(Self.gap)
make.height.equalTo(Self.tipsHeight)
make.centerX.equalTo(self)
}
}
}
//
// YHNoDataTipView.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/25.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
class YHNoDataTipView: UIView {
public var reloadBlock: (()->())?
private var imageStr: String = "no-order-bkg-icon"
private var title: String = "暂无数据"
private lazy var imageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "no-order-bkg-icon"))
return imageView
}()
private lazy var titleLabel: UILabel = {
let label = UILabel(text: "暂无数据", font: UIFont.PFSC_R(ofSize: 14), color: UIColor.labelTextColor2)
return label
}()
private lazy var descLabel: UILabel = {
let label = UILabel(text: "", font: UIFont.PFSC_R(ofSize: 12), color: UIColor.labelTextColor2)
return label
}()
private lazy var reloadBtn: UIButton = {
let btn = UIButton.bs_button(title: "重新加载", font: UIFont.PFSC_M(ofSize: 12), normalColor: UIColor.brandMainColor)
btn.layer.cornerRadius = 6
btn.layer.masksToBounds = true
btn.layer.borderWidth = 1
btn.layer.borderColor = UIColor.labelTextColor2.cgColor
btn.addTarget(self, action: #selector(onReloadData), for: .touchUpInside)
return btn
}()
override init(frame: CGRect) {
super.init(frame: frame)
initView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func setup(image: String? = nil, title: String) {
if let image = image {
imageView.image = UIImage(named: image)
self.imageStr = image
}
titleLabel.text = title
self.title = title
}
override var isHidden: Bool {
didSet {
if isHidden == false {
if YHNetworkStatusManager.shared.isNetWorkOK == true {
imageView.image = UIImage(named: self.imageStr)
titleLabel.text = title
descLabel.isHidden = true
reloadBtn.isHidden = true
} else {
imageView.image = UIImage(named: "no_data_network_icon")
titleLabel.text = "网络好像断开了哦"
descLabel.isHidden = false
reloadBtn.isHidden = false
}
}
}
}
}
// MARK: - 提供快速创建的类方法
extension YHNoDataTipView {
private func initView() {
self.addSubview(imageView)
self.addSubview(titleLabel)
self.addSubview(descLabel)
self.addSubview(reloadBtn)
let imageViewTop = 132 / (UIDevice.kScreenW - UIDevice.bs_navigationFullHeight())
imageView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(imageViewTop)
make.centerX.equalToSuperview()
make.width.height.equalTo(165)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(imageView.snp.bottom)
make.centerX.equalToSuperview()
}
descLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(4)
make.centerX.equalToSuperview()
}
reloadBtn.snp.makeConstraints { make in
make.top.equalTo(descLabel.snp.bottom).offset(16)
make.centerX.equalToSuperview()
make.width.equalTo(80)
make.height.equalTo(28)
}
descLabel.isHidden = true
reloadBtn.isHidden = true
}
// class func noDataTipView() -> YHNoDataTipView {
// return YHNoDataTipView()
// //return Bundle.main.loadNibNamed("YHNoDataTipView", owner: nil, options: nil)?.first as! YHNoDataTipView
// }
override func layoutSubviews() {
super.layoutSubviews()
let imageViewTop = (132 + UIDevice.bs_navigationFullHeight()) / UIDevice.kScreenH * self.frame.size.height
imageView.snp.updateConstraints { make in
make.top.equalToSuperview().offset(imageViewTop)
}
}
@objc private func onReloadData() {
reloadBlock?()
}
}
//
// YHPaddedLabel.swift
// galaxy
//
// Created by alexzzw on 2024/9/13.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHPaddedLabel: UILabel {
var padding: UIEdgeInsets
init(padding: UIEdgeInsets) {
self.padding = padding
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
self.padding = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4)
super.init(coder: coder)
}
override func drawText(in rect: CGRect) {
let insetRect = rect.inset(by: padding)
super.drawText(in: insetRect)
}
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(width: size.width + padding.left + padding.right,
height: size.height + padding.top + padding.bottom)
}
}
//
// YHPageControl.swift
// galaxy
//
// Created by Dufet on 2024/12/13.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHPageControl: UIView {
// MARK: - Properties
private var dots: [UIView] = []
var dotSize: CGSize = CGSize(width: 40, height: 8) // 普通点的大小
var selectedDotSize: CGSize = CGSize(width: 60, height: 8) // 选中点的大小
var spacing: CGFloat = 8 // 点之间的间距
// 当前页码
var currentPage: Int = 0 {
didSet {
guard oldValue != currentPage else { return }
updateDots(animated: true)
}
}
// 总页数
var numberOfPages: Int = 0 {
didSet {
guard oldValue != numberOfPages else { return }
setupDots()
}
}
// 自定义颜色
var dotColor: UIColor = UIColor.lightGray {
didSet {
dots.forEach { $0.backgroundColor = dotColor }
dots[safe: currentPage]?.backgroundColor = selectedDotColor
}
}
var selectedDotColor: UIColor = UIColor.systemBlue {
didSet {
dots[safe: currentPage]?.backgroundColor = selectedDotColor
}
}
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
// MARK: - Setup
private func setupView() {
backgroundColor = .clear
}
private func setupDots() {
// 移除现有的点
dots.forEach { $0.removeFromSuperview() }
dots.removeAll()
// 创建新的点
for _ in 0..<numberOfPages {
let dot = UIView()
dot.backgroundColor = dotColor
dot.layer.shadowOffset = .zero
addSubview(dot)
dots.append(dot)
}
// 更新布局
setNeedsLayout()
updateDots(animated: false)
}
// MARK: - Layout
override func layoutSubviews() {
super.layoutSubviews()
let totalWidth = CGFloat(numberOfPages - 1) * (dotSize.width + spacing) + selectedDotSize.width
var xOffset = (bounds.width - totalWidth) / 2
for (index, dot) in dots.enumerated() {
let isSelected = index == currentPage
let width = isSelected ? selectedDotSize.width : dotSize.width
dot.frame = CGRect(x: xOffset,
y: (bounds.height - dotSize.height) / 2,
width: width,
height: dotSize.height)
dot.layer.cornerRadius = self.dotSize.height / 2
dot.clipsToBounds = true
xOffset += width + spacing
}
}
// MARK: - Updates
private func updateDots(animated: Bool) {
guard !dots.isEmpty else { return }
let update = {
self.dots.enumerated().forEach { index, dot in
let isSelected = index == self.currentPage
dot.backgroundColor = isSelected ? self.selectedDotColor : self.dotColor
let width = isSelected ? self.selectedDotSize.width : self.dotSize.width
var frame = dot.frame
frame.size.width = width
dot.layer.cornerRadius = self.dotSize.height / 2
dot.clipsToBounds = true
dot.frame = frame
}
self.layoutSubviews()
}
if animated {
UIView.animate(withDuration: 0.3,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: [.curveEaseInOut],
animations: update)
} else {
update()
}
}
}
// MARK: - Safe Array Access
private extension Array {
subscript(safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
//
// YHShareViewOnTablebarView.swift
// galaxy
//
// Created by davidhuangA on 2024/7/20.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
/*
导航栏上的 分享、咨询 按钮
*/
// tabbar上view 的参数对象
struct TabBarShareModel {
var showFlag: Bool = false // 是否展示tabbar上的分享view
var shareTitle: String = "" // 分享到小程序的标题
var shareUrl: String = "" // 分享到小程序上的url
var codeUrl: String = "" // 用于展示的二维码图片
var downloadUrl: String = ""// 用于下载的二维码图片
}
class YHShareViewOnTablebarView: UIView {
static let viewH: CGFloat = 98.0
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: YHBasicInfoFillBottomView.viewH))
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
typealias Block = (Int) -> Void // 0-快速测评 1-资讯顾问 2-分享有礼
var block: Block?
lazy var topLine: UIView = {
let line = UIView()
line.backgroundColor = UIColor.separatorColor
return line
}()
// 分享按钮
lazy var shareBtn: UIButton = {
let button = UIButton(type: .custom)
button.titleLabel?.font = UIFont.PFSC_R(ofSize: 11)
// button.contentHorizontalAlignment = .center
button.setTitle("分享", for: .normal)
button.setTitle("分享", for: .highlighted)
button.setTitleColor(UIColor.mainTextColor, for: .normal)
button.setTitleColor(UIColor.mainTextColor, for: .highlighted)
button.setImage(UIImage(named: "share_item"), for: .normal)
button.setImage(UIImage(named: "share_item"), for: .highlighted)
button.addTarget(self, action: #selector(clickShareBtn), for: .touchUpInside)
return button
}()
// 预约咨询
lazy var consultantBtn: UIButton = {
let button = UIButton(type: .custom)
button.titleLabel?.font = UIFont.PFSC_M(ofSize: 15)
button.contentHorizontalAlignment = .center
button.setTitle("预约咨询", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.layer.cornerRadius = kCornerRadius3
button.clipsToBounds = true
button.addTarget(self, action: #selector(clickConsultantBtn), for: .touchUpInside)
button.backgroundColor = UIColor.brandMainColor
return button
}()
override func layoutSubviews() {
super.layoutSubviews()
// if YHLoginManager.shared.isLogin() {
// quickEvaluationBtn.isHidden = true
// consultantBtn.isHidden = true
// rewardBtn.isHidden = false
// } else {
// quickEvaluationBtn.isHidden = false
// consultantBtn.isHidden = false
// rewardBtn.isHidden = true
// }
shareBtn.iconInTop(spacing: 0)
}
}
private extension YHShareViewOnTablebarView {
func setupUI() {
backgroundColor = .white
addSubview(topLine)
addSubview(shareBtn)
addSubview(consultantBtn)
topLine.snp.makeConstraints { make in
make.left.right.top.equalToSuperview()
make.height.equalTo(0.5)
}
shareBtn.snp.makeConstraints { make in
make.centerY.equalTo(consultantBtn).offset(4.0)
make.left.equalTo(14)
make.right.equalTo(consultantBtn.snp.left).offset(-14)
make.height.equalTo(40)
make.width.equalTo(60)
}
consultantBtn.snp.makeConstraints { make in
make.top.equalToSuperview().offset(8)
make.left.equalTo(shareBtn.snp.right).offset(14)
make.right.equalTo(-20)
make.height.equalTo(44)
}
}
@objc func clickShareBtn() {
block?(0)
}
@objc func clickConsultantBtn() {
block?(1)
}
}
...@@ -10,17 +10,18 @@ import UIKit ...@@ -10,17 +10,18 @@ import UIKit
class YHTwoOptionAlertView: UIView { class YHTwoOptionAlertView: UIView {
typealias Block = (Bool) -> () typealias Block = (Bool) -> Void
var block: Block? var block: Block?
var centerView: UIView! var centerView: UIView!
var messageLabel: UILabel! var messageLabel: UILabel!
var rightButton: UIButton! var rightButton: UIButton!
var leftButton: UIButton! var leftButton: UIButton!
static func showAlertView(message:String?,leftBtnTitle:String? = "取消".local, rightBtnTitle:String? = "确认".local, callBack: @escaping Block) { static func showAlertView(message: String?, leftBtnTitle: String? = "取消".local, rightBtnTitle: String? = "确认".local, aligentment: NSTextAlignment = .center, callBack: @escaping Block) {
let view = YHTwoOptionAlertView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: KScreenHeight)) let view = YHTwoOptionAlertView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: KScreenHeight))
view.messageLabel.text = message view.messageLabel.text = message
view.messageLabel.textAlignment = aligentment
view.leftButton.setTitle(leftBtnTitle, for: .normal) view.leftButton.setTitle(leftBtnTitle, for: .normal)
view.rightButton.setTitle(rightBtnTitle, for: .normal) view.rightButton.setTitle(rightBtnTitle, for: .normal)
view.block = callBack view.block = callBack
...@@ -64,14 +65,14 @@ class YHTwoOptionAlertView: UIView { ...@@ -64,14 +65,14 @@ class YHTwoOptionAlertView: UIView {
leftButton = { leftButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.backgroundColor = UIColor(hex:0xffffff) button.backgroundColor = UIColor(hex: 0xffffff)
button.titleLabel?.font = UIFont.PFSC_M(ofSize: 14) button.titleLabel?.font = UIFont.PFSC_M(ofSize: 14)
button.contentHorizontalAlignment = .center button.contentHorizontalAlignment = .center
button.setTitle("取消".local, for: .normal) button.setTitle("取消".local, for: .normal)
button.setTitleColor( UIColor(hex:0x3c86f8), for: .normal) button.setTitleColor( UIColor.brandMainColor, for: .normal)
button.layer.cornerRadius = kCornerRadius6 button.layer.cornerRadius = kCornerRadius3
button.layer.borderWidth = 1 button.layer.borderWidth = 1
button.layer.borderColor = UIColor(hex: 0x3c86f8).cgColor button.layer.borderColor = UIColor.brandMainColor.cgColor
button.addTarget(self, action: #selector(disagree), for: .touchUpInside) button.addTarget(self, action: #selector(disagree), for: .touchUpInside)
return button return button
}() }()
...@@ -79,12 +80,12 @@ class YHTwoOptionAlertView: UIView { ...@@ -79,12 +80,12 @@ class YHTwoOptionAlertView: UIView {
rightButton = { rightButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.backgroundColor = UIColor(hex:0x3c86f8) button.backgroundColor = UIColor.brandMainColor
button.titleLabel?.font = UIFont.PFSC_M(ofSize: 14) button.titleLabel?.font = UIFont.PFSC_M(ofSize: 14)
button.contentHorizontalAlignment = .center button.contentHorizontalAlignment = .center
button.setTitle("确认".local, for: .normal) button.setTitle("确认".local, for: .normal)
button.setTitleColor( UIColor(hex:0xffffff), for: .normal) button.setTitleColor( UIColor(hex: 0xffffff), for: .normal)
button.layer.cornerRadius = kCornerRadius6 button.layer.cornerRadius = kCornerRadius3
button.addTarget(self, action: #selector(agree), for: .touchUpInside) button.addTarget(self, action: #selector(agree), for: .touchUpInside)
return button return button
}() }()
...@@ -100,8 +101,9 @@ class YHTwoOptionAlertView: UIView { ...@@ -100,8 +101,9 @@ class YHTwoOptionAlertView: UIView {
make.left.equalTo(22) make.left.equalTo(22)
make.right.equalTo(-22) make.right.equalTo(-22)
} }
leftButton.snp.makeConstraints { make in leftButton.snp.makeConstraints { make in
make.top.equalTo(messageLabel.snp.bottom).offset(40) make.top.equalTo(messageLabel.snp.bottom).offset(20)
make.left.equalTo(16) make.left.equalTo(16)
make.bottom.equalToSuperview().offset(-16) make.bottom.equalToSuperview().offset(-16)
make.size.equalTo(CGSize(width: 128, height: 45)) make.size.equalTo(CGSize(width: 128, height: 45))
...@@ -120,7 +122,6 @@ class YHTwoOptionAlertView: UIView { ...@@ -120,7 +122,6 @@ class YHTwoOptionAlertView: UIView {
} }
@objc private func handleTap(_ sender: AnyObject?) { @objc private func handleTap(_ sender: AnyObject?) {
print("处理点击手势")
dismiss() dismiss()
} }
...@@ -135,11 +136,10 @@ class YHTwoOptionAlertView: UIView { ...@@ -135,11 +136,10 @@ class YHTwoOptionAlertView: UIView {
} }
extension YHTwoOptionAlertView: UIGestureRecognizerDelegate { extension YHTwoOptionAlertView: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer:UIGestureRecognizer, shouldReceive touch:UITouch) -> Bool { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view == self { if touch.view == self {
return true return true
} }
return false return false
} }
} }
//
// YHAIChatUIConfiguration.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIChatConfiguration {
var disableHandleMessage: Bool = false
func registerMessageGroupCells(_ tableView: UITableView) {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
tableView.register(YHAITextMessageCell.self, forCellReuseIdentifier: YHAITextMessageCell.cellReuseIdentifier)
tableView.register(YHAIThinkingMessageCell.self, forCellReuseIdentifier: YHAIThinkingMessageCell.cellReuseIdentifier)
tableView.register(YHProductListMessageCell.self, forCellReuseIdentifier: YHProductListMessageCell.cellReuseIdentifier)
tableView.register(YHFixProductListMessageCell.self, forCellReuseIdentifier: YHFixProductListMessageCell.cellReuseIdentifier)
tableView.register(YHCardMessageCell.self, forCellReuseIdentifier: YHCardMessageCell.cellReuseIdentifier)
tableView.register(YHAIPictureMessageCell.self, forCellReuseIdentifier: YHAIPictureMessageCell.cellReuseIdentifier)
tableView.register(YHRecommendTextMessageCell.self, forCellReuseIdentifier: YHRecommendTextMessageCell.cellReuseIdentifier)
}
func handleReceiveMessage(_ res: YHAIChatMessage?, _ done: Bool, _ messages: inout [YHAIChatMessage]) {
// 去除loading消息
removeThinkingMessageFromChatList(&messages)
if disableHandleMessage {
for msg in messages {
msg.isDone = true
}
return
}
if let res = res {
var find = false
for msg in messages {
if msg.messageId == res.messageId {
if msg.isNeedSpiceMessage(), res.isNeedSpiceMessage() {
// 多个文字需要拼接
find = true
if res.isTextCompleted() {
msg.isDone = true
} else {
msg.body.contentText += res.body.contentText
}
msg.updateBodyToData()
}
}
}
if !find {
messages.append(res)
}
}
if done { // 思考完成
for msg in messages {
msg.isDone = true
}
}
}
func removeThinkingMessageFromChatList( _ messages: inout [YHAIChatMessage]) {
var findIndex = -1
for (index, msg) in messages.enumerated() {
if msg.getType() == .thinking {
findIndex = index
}
}
if findIndex != -1 {
messages.remove(at: findIndex)
}
}
func createRobotResponseTextMessage(_ text: String) -> YHAIChatMessage {
let message = YHAIChatMessage()
message.messageId = UUID().uuidString + NSDate().timeIntervalSince1970.description
message.isSelf = false
let body = YHAIMessageBody()
body.contentType = YHAIMessageType.text.rawValue
body.contentText = text
message.setDone()
message.body = body
message.updateBodyToData()
return message
}
func createRobotResponseLocalPictureMessage(_ imgName: String, previewUrl: String) -> YHAIChatMessage {
let message = YHAIChatMessage()
message.messageId = UUID().uuidString + NSDate().timeIntervalSince1970.description
message.isSelf = false
let body = YHAIMessageBody()
body.contentType = YHAIMessageType.picture.rawValue
let imgInfo = YHAIImageInfo()
imgInfo.imageType = YHAIImageType.local.rawValue
imgInfo.localImageName = imgName
imgInfo.imageUrl = previewUrl
body.imageInfo = imgInfo
message.setDone()
message.body = body
message.updateBodyToData()
return message
}
}
//
// YHAIServiceListViewController.swift
// galaxy
//
// Created by Dufet on 2024/11/26.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import JXSegmentedView
import IQKeyboardManagerSwift
let isNeedShowAutoPictureMsg = "isNeedShowAutoPictureMsg"
let isNeedShowAIChatKeyBoard = "isNeedShowAIChatKeyBoard"
class YHAIServiceListViewController: YHBaseViewController {
var serviceArr: [YHEntranceconfigModel] = []
let viewModel = YHAIViewModel()
let manager = YHAIRequestManager()
lazy var collectionView: UICollectionView = {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumInteritemSpacing = 10.0
flowLayout.minimumLineSpacing = 28.0
flowLayout.scrollDirection = .vertical
let collectView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
collectView.backgroundColor = .clear
collectView.delegate = self
collectView.dataSource = self
collectView.register(YHAIProductCell.self, forCellWithReuseIdentifier: YHAIProductCell.cellReuseIdentifier)
collectView.register(YHAIGreetCollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: YHAIGreetCollectionReusableView.reuseIdentifier)
collectView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "UICollectionReusableView")
collectView.contentInset = .zero
collectView.showsVerticalScrollIndicator = false
return collectView
}()
lazy var bottomInputView: YHAITextInputView = {
let v = YHAITextInputView(frame: .zero)
v.backgroundColor = .clear
v.disable = true
let btn = UIButton()
btn.addTarget(self, action: #selector(didInputButtonClicked), for: .touchUpInside)
v.addSubview(btn)
btn.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
return v
}()
@objc func didInputButtonClicked() {
let dict: [String: Any] = [isNeedShowAutoPictureMsg: false,
isNeedShowAIChatKeyBoard: true]
NotificationCenter.default.post(name: YhConstant.YhNotification.didSwitchToAIChatNotification, object: dict)
}
override func viewDidLoad() {
super.viewDidLoad()
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
IQKeyboardManager.shared.isEnabled = false
view.backgroundColor = .clear
view.addSubview(collectionView)
view.addSubview(bottomInputView)
collectionView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalToSuperview()
}
bottomInputView.snp.makeConstraints { make in
make.top.equalTo(collectionView.snp.bottom).offset(8)
make.left.right.bottom.equalToSuperview()
}
}
}
extension YHAIServiceListViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
// 返回单元格数量
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return serviceArr.count
}
// 返回每个单元格的大小
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = floor((KScreenWidth-16.0*2.0-10.0)/2.0)
let height = width * (200.0/166.0)
return CGSize(width: width, height: height)
}
// 返回自定义单元格
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: YHAIProductCell.cellReuseIdentifier, for: indexPath) as? YHAIProductCell else {
return UICollectionViewCell()
}
if 0 <= indexPath.item && indexPath.item < serviceArr.count {
let model = serviceArr[indexPath.item]
cell.model = model
// 根据索引设置旋转
cell.rotateToRight(indexPath.item % 2 == 0)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if 0 <= indexPath.item && indexPath.item < serviceArr.count {
let model = serviceArr[indexPath.item]
if model.redirectMode == 1 { // web页面
if !model.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.url = model.redirectPath
UIViewController.current?.navigationController?.pushViewController(vc, animated: true)
}
} else if model.redirectMode == 2 {
// customerVoice -> APP客户心声 productList -> APP-首页银河甄选 AppServiceTab -> 服务页
if model.redirectPath == YHAIJumpPageType.customerHeart.rawValue {
// 客户心声
let vc = YHOtherServiceViewController()
vc.classID = 5
UIViewController.current?.navigationController?.pushViewController(vc)
} else if model.redirectPath == YHAIJumpPageType.galaxySelect.rawValue {
YHAnalytics.track("APP_ChanPinZhenXuan")
// 银河甄选
let vc = YHSelectViewController()
vc.hideFlag = false
UIViewController.current?.navigationController?.pushViewController(vc, animated: true)
} else if model.redirectPath == YHAIJumpPageType.appServiceTab.rawValue {
YHAnalytics.track("APP_FuWuJinDu")
// 服务页
UIViewController.current?.navigationController?.popToRootViewController(animated: false)
goTabBarBy(tabType: .service)
}
} else if model.redirectMode == 3 { // agent
if model.businessType == YHAIRobotType.main.rawValue {
// 切到主Robot
let dict: [String: Any] = [isNeedShowAutoPictureMsg: true,
isNeedShowAIChatKeyBoard: false]
NotificationCenter.default.post(name: YhConstant.YhNotification.didSwitchToAIChatNotification, object: dict)
} else {
if model.businessType == YHAIRobotType.education.rawValue {
YHAnalytics.track("APP_JiaoYuBao")
} else if model.businessType == YHAIRobotType.sale.rawValue {
YHAnalytics.track("APP_GuiHuaShi")
} else if model.businessType == YHAIRobotType.business.rawValue {
// YHAnalytics.track("APP_Gangxiaobao_Galaxy_Business_Planner")
}
self.manager.getSubRobotChatConversationId(listItemId: "\(model.id)") {
sesseionId in
let vc = YHAIRobotChatViewController()
vc.isNeedShowBannerHeader = model.isNeedShowBannerHeader()
vc.myTitle = model.title
vc.robotId = model.redirectPath
vc.listItemId = model.id
vc.conversationId = sesseionId
vc.robotType = model.businessType
vc.title = model.titleName
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
guard let headerView: YHAIGreetCollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: YHAIGreetCollectionReusableView.reuseIdentifier, for: indexPath) as? YHAIGreetCollectionReusableView else {
return UICollectionReusableView()
}
headerView.updateGreetingText()
return headerView
}
let footerView: UICollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "UICollectionReusableView", for: indexPath)
return footerView
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection: Int) -> CGSize {
return CGSize(width: KScreenWidth, height: 177)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection: Int) -> CGSize {
return CGSize(width: KScreenWidth, height: 42.0)
}
}
extension YHAIServiceListViewController: JXSegmentedListContainerViewListDelegate {
func listView() -> UIView {
return view
}
}
//
// YHAIHistoryMessage.swift
// galaxy
//
// Created by Dufet on 2024/12/3.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import SmartCodable
class YHAIHistoryMessage: SmartCodable {
var botId: String = ""
var chatId: String = ""
var contentText: String = ""
var contentType: Int = 0
var messageId: String = ""
var role: String = ""
var type: String = ""
var cardsInfo: YHAIListInfoModel?
var imageInfo: YHAIImageInfo?
required init() {
}
func convertToChatMessage() -> YHAIChatMessage {
let msg = YHAIChatMessage()
msg.messageId = self.messageId
msg.isSelf = self.role == "user"
msg.isDone = true
let body = YHAIMessageBody()
body.contentType = self.contentType
body.contentText = self.contentText
body.botId = self.botId
body.chatId = self.chatId
body.type = self.type
body.cardsInfo = self.cardsInfo
body.imageInfo = self.imageInfo
msg.body = body
msg.setDone()
msg.updateBodyToData()
return msg
}
}
//
// YHAIListModel.swift
// galaxy
//
// Created by Dufet on 2024/11/27.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import SmartCodable
class YHAIListModel: SmartCodable {
var mainBotId: String = ""
var entranceConfig: [YHEntranceconfigModel] = []
required init() {
}
}
enum YHAIRobotType: String {
case main = "mainBot"
case education = "educationBot"
case sale = "saleBot"
case image = "entryPrecautionsImage"
case business = "businessBot"
}
class YHEntranceconfigModel: SmartCodable {
var id: Int = 0
var title: String = ""
var icon: String = ""
var cover: String = ""
var description: String = ""
var btnText: String = ""
var redirectMode: Int = 0
var businessType: String = ""
var redirectPath: String = ""
var titleName: String {
if businessType == "businessBot" {
return "银河商务规划师"
} else {
return ""
}
}
func isNeedShowBannerHeader() -> Bool {
if businessType == YHAIRobotType.education.rawValue || businessType == YHAIRobotType.sale.rawValue || businessType == YHAIRobotType.business.rawValue {
return true
}
return false
}
required init() {
}
}
class YHAIBoardInfo: SmartCodable {
var prologue: String = ""
var suggestedQuestions: [String] = []
required init() {
}
}
class YHAIBotConfigInfo: SmartCodable {
var description: String = ""
var onboardingInfo: YHAIBoardInfo = YHAIBoardInfo()
required init() {
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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