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

Merge branch 'AI-1212' into yinhe-live-1212

# Conflicts:
#	galaxy/Podfile
#	galaxy/galaxy.xcodeproj/project.pbxproj
#	galaxy/galaxy/Classes/Modules/Login(登录)/Server/YHLoginManager.swift
#	galaxy/galaxy/Classes/Tools/Helper/YhConstant.swift
#	galaxy/galaxy/Classes/Tools/NetWork/YHAllApiName.swift
parents 22485f1c b67ba8f7
...@@ -115,7 +115,10 @@ target 'galaxy' do ...@@ -115,7 +115,10 @@ target 'galaxy' do
pod 'AliyunLogProducer', '4.3.3' pod 'AliyunLogProducer', '4.3.3'
#加密 #加密
pod 'xxtea', '1.0.2' pod 'xxtea', '1.0.2'
end #Realm
pod 'RealmSwift', '20.0.0'
pod 'Realm', '20.0.0'
end
post_install do |installer| post_install do |installer|
......
...@@ -502,6 +502,13 @@ ...@@ -502,6 +502,13 @@
045EEF232B9F171A0022A143 /* YHItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE762B9F171A0022A143 /* YHItemView.swift */; }; 045EEF232B9F171A0022A143 /* YHItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE762B9F171A0022A143 /* YHItemView.swift */; };
045EEF242B9F171A0022A143 /* YHStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE772B9F171A0022A143 /* YHStepView.swift */; }; 045EEF242B9F171A0022A143 /* YHStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE772B9F171A0022A143 /* YHStepView.swift */; };
045EEF252B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE782B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift */; }; 045EEF252B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EEE782B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift */; };
045F28402CF5ED3400520F19 /* YHAITabBarItemContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F283F2CF5ED3400520F19 /* YHAITabBarItemContentView.swift */; };
045F28422CF6028A00520F19 /* YHAITabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F28412CF6028A00520F19 /* YHAITabViewController.swift */; };
045F28442CF608C100520F19 /* YHAIServiceListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F28432CF608C100520F19 /* YHAIServiceListViewController.swift */; };
045F28462CF6C47800520F19 /* YHAIProductCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F28452CF6C47800520F19 /* YHAIProductCell.swift */; };
045F28482CF6EF9800520F19 /* YHAIGreetCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F28472CF6EF9800520F19 /* YHAIGreetCollectionReusableView.swift */; };
045F284A2CF6F5B100520F19 /* YHAIViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F28492CF6F5B100520F19 /* YHAIViewModel.swift */; };
045F284C2CF6F65200520F19 /* YHAIListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045F284B2CF6F65200520F19 /* YHAIListModel.swift */; };
0468D4222B493A5E00CFB916 /* YHPhoneMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4212B493A5E00CFB916 /* YHPhoneMessageView.swift */; }; 0468D4222B493A5E00CFB916 /* YHPhoneMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4212B493A5E00CFB916 /* YHPhoneMessageView.swift */; };
0468D4262B495A5400CFB916 /* YHPickPhoneAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4252B495A5400CFB916 /* YHPickPhoneAddressViewController.swift */; }; 0468D4262B495A5400CFB916 /* YHPickPhoneAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4252B495A5400CFB916 /* YHPickPhoneAddressViewController.swift */; };
0468D4282B50D4AF00CFB916 /* YHPrivacyAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4272B50D4AF00CFB916 /* YHPrivacyAlertView.swift */; }; 0468D4282B50D4AF00CFB916 /* YHPrivacyAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0468D4272B50D4AF00CFB916 /* YHPrivacyAlertView.swift */; };
...@@ -605,7 +612,10 @@ ...@@ -605,7 +612,10 @@
0493B3DC2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0493B3DB2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift */; }; 0493B3DC2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0493B3DB2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift */; };
0493B3DE2BA80C2300AF9393 /* YHCertificateFilterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0493B3DD2BA80C2300AF9393 /* YHCertificateFilterButton.swift */; }; 0493B3DE2BA80C2300AF9393 /* YHCertificateFilterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0493B3DD2BA80C2300AF9393 /* YHCertificateFilterButton.swift */; };
04943BE82CF0A0B500BF2255 /* submit_page_scroll.gif in Resources */ = {isa = PBXBuildFile; fileRef = 04943BE72CF0A0B500BF2255 /* submit_page_scroll.gif */; }; 04943BE82CF0A0B500BF2255 /* submit_page_scroll.gif in Resources */ = {isa = PBXBuildFile; fileRef = 04943BE72CF0A0B500BF2255 /* submit_page_scroll.gif */; };
04943BEA2CF1B44100BF2255 /* YHAIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943BE92CF1B44100BF2255 /* YHAIViewController.swift */; }; 04943BEA2CF1B44100BF2255 /* YHAIMainChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943BE92CF1B44100BF2255 /* YHAIMainChatViewController.swift */; };
04943BED2CF46B6600BF2255 /* YHAIRequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943BEC2CF46B6600BF2255 /* YHAIRequestManager.swift */; };
04943BF42CF4954800BF2255 /* YHAITextMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943BF32CF4954800BF2255 /* YHAITextMessageCell.swift */; };
04943BF62CF49E3E00BF2255 /* YHAITextInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943BF52CF49E3E00BF2255 /* YHAITextInputView.swift */; };
049537852BA9B28500AF7E59 /* YHCertificateTemplateCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049537842BA9B28500AF7E59 /* YHCertificateTemplateCell.swift */; }; 049537852BA9B28500AF7E59 /* YHCertificateTemplateCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049537842BA9B28500AF7E59 /* YHCertificateTemplateCell.swift */; };
049663BA2BF6105C003C8295 /* YHRefreshHeaderAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049663B92BF6105C003C8295 /* YHRefreshHeaderAnimator.swift */; }; 049663BA2BF6105C003C8295 /* YHRefreshHeaderAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049663B92BF6105C003C8295 /* YHRefreshHeaderAnimator.swift */; };
049663C02BF729F6003C8295 /* galaxy_refresher.gif in Resources */ = {isa = PBXBuildFile; fileRef = 049663BF2BF729F5003C8295 /* galaxy_refresher.gif */; }; 049663C02BF729F6003C8295 /* galaxy_refresher.gif in Resources */ = {isa = PBXBuildFile; fileRef = 049663BF2BF729F5003C8295 /* galaxy_refresher.gif */; };
...@@ -694,6 +704,30 @@ ...@@ -694,6 +704,30 @@
04B9EE5A2C06CC3100A4018D /* YHCodeSueecssViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B9EE582C06CC3100A4018D /* YHCodeSueecssViewController.swift */; }; 04B9EE5A2C06CC3100A4018D /* YHCodeSueecssViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B9EE582C06CC3100A4018D /* YHCodeSueecssViewController.swift */; };
04B9EE5B2C06CC3100A4018D /* YHOtherLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B9EE592C06CC3100A4018D /* YHOtherLoginViewController.swift */; }; 04B9EE5B2C06CC3100A4018D /* YHOtherLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B9EE592C06CC3100A4018D /* YHOtherLoginViewController.swift */; };
04BD83452CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 04BD83442CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf */; }; 04BD83452CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 04BD83442CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf */; };
04BE39282CF848F300BD31DB /* YHAIMessageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39272CF848F300BD31DB /* YHAIMessageModel.swift */; };
04BE392A2CF85F8900BD31DB /* YHAITabIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39292CF85F8900BD31DB /* YHAITabIndicatorView.swift */; };
04BE392C2CF8917100BD31DB /* YHAIThinkingMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE392B2CF8917100BD31DB /* YHAIThinkingMessageCell.swift */; };
04BE392E2CF964A200BD31DB /* YHProductListMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE392D2CF964A200BD31DB /* YHProductListMessageCell.swift */; };
04BE39302CF964F800BD31DB /* YHProductItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE392F2CF964F800BD31DB /* YHProductItemView.swift */; };
04BE39322CF9AB0900BD31DB /* YHCardMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39312CF9AB0900BD31DB /* YHCardMessageCell.swift */; };
04BE39342CF9AFAE00BD31DB /* YHFixProductMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39332CF9AFAE00BD31DB /* YHFixProductMessageCell.swift */; };
04BE39362CF9AFF200BD31DB /* YHFixProductItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39352CF9AFF200BD31DB /* YHFixProductItemView.swift */; };
04BE393C2CF9B67000BD31DB /* ai_chat_loading.json in Resources */ = {isa = PBXBuildFile; fileRef = 04BE393B2CF9B67000BD31DB /* ai_chat_loading.json */; };
04BE393E2CF9B67700BD31DB /* ai_chat_input_pause.json in Resources */ = {isa = PBXBuildFile; fileRef = 04BE393D2CF9B67700BD31DB /* ai_chat_input_pause.json */; };
04BE39402CF9B95800BD31DB /* YHAIRobotChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE393F2CF9B95800BD31DB /* YHAIRobotChatViewController.swift */; };
04BE39422CF9B99200BD31DB /* YHAIChatConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39412CF9B99200BD31DB /* YHAIChatConfiguration.swift */; };
04BE39442CFAB46100BD31DB /* YHAIChatBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39432CFAB46100BD31DB /* YHAIChatBannerView.swift */; };
04BE39462CFAB5F200BD31DB /* YHAIChatBannerItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39452CFAB5F100BD31DB /* YHAIChatBannerItemCell.swift */; };
04BE39482CFABB7F00BD31DB /* YHAIChatBannerCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39472CFABB7F00BD31DB /* YHAIChatBannerCollectionCell.swift */; };
04BE394A2CFABC5E00BD31DB /* YHAIChatShadowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39492CFABC5E00BD31DB /* YHAIChatShadowView.swift */; };
04BE394C2CFAC16600BD31DB /* YHAIChatCustomFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE394B2CFAC16600BD31DB /* YHAIChatCustomFlowLayout.swift */; };
04BE394E2CFD92C100BD31DB /* YHAIChatInputShadowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE394D2CFD92C100BD31DB /* YHAIChatInputShadowView.swift */; };
04BE39502CFD9B5900BD31DB /* YHAIChatDataBaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE394F2CFD9B5800BD31DB /* YHAIChatDataBaseManager.swift */; };
04BE39522CFDA19000BD31DB /* YHAIChatDataBaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39512CFDA19000BD31DB /* YHAIChatDataBaseModel.swift */; };
04BE39542CFEA62000BD31DB /* YHAICardItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39532CFEA62000BD31DB /* YHAICardItemView.swift */; };
04BE39582CFED3F700BD31DB /* YHAIHistoryMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39572CFED3F700BD31DB /* YHAIHistoryMessage.swift */; };
04BE395A2CFEECFA00BD31DB /* YHAIEvaluationAlertWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE39592CFEECFA00BD31DB /* YHAIEvaluationAlertWebView.swift */; };
04BE395C2CFF058200BD31DB /* YHAIPictureMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BE395B2CFF058200BD31DB /* YHAIPictureMessageCell.swift */; };
04C693622B723AB8004C1758 /* YHMySettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C693612B723AB8004C1758 /* YHMySettingViewController.swift */; }; 04C693622B723AB8004C1758 /* YHMySettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C693612B723AB8004C1758 /* YHMySettingViewController.swift */; };
04C693642B723B56004C1758 /* YHMySettingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C693632B723B56004C1758 /* YHMySettingCell.swift */; }; 04C693642B723B56004C1758 /* YHMySettingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C693632B723B56004C1758 /* YHMySettingCell.swift */; };
04C85DDF2C364FE9008B20D6 /* YHAboutUsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C85DDE2C364FE9008B20D6 /* YHAboutUsCell.swift */; }; 04C85DDF2C364FE9008B20D6 /* YHAboutUsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C85DDE2C364FE9008B20D6 /* YHAboutUsCell.swift */; };
...@@ -1576,6 +1610,13 @@ ...@@ -1576,6 +1610,13 @@
045EEE762B9F171A0022A143 /* YHItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHItemView.swift; sourceTree = "<group>"; }; 045EEE762B9F171A0022A143 /* YHItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHItemView.swift; sourceTree = "<group>"; };
045EEE772B9F171A0022A143 /* YHStepView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHStepView.swift; sourceTree = "<group>"; }; 045EEE772B9F171A0022A143 /* YHStepView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHStepView.swift; sourceTree = "<group>"; };
045EEE782B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHMainInformationCardTableViewCell.swift; sourceTree = "<group>"; }; 045EEE782B9F171A0022A143 /* YHMainInformationCardTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHMainInformationCardTableViewCell.swift; sourceTree = "<group>"; };
045F283F2CF5ED3400520F19 /* YHAITabBarItemContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAITabBarItemContentView.swift; sourceTree = "<group>"; };
045F28412CF6028A00520F19 /* YHAITabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAITabViewController.swift; sourceTree = "<group>"; };
045F28432CF608C100520F19 /* YHAIServiceListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIServiceListViewController.swift; sourceTree = "<group>"; };
045F28452CF6C47800520F19 /* YHAIProductCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIProductCell.swift; sourceTree = "<group>"; };
045F28472CF6EF9800520F19 /* YHAIGreetCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIGreetCollectionReusableView.swift; sourceTree = "<group>"; };
045F28492CF6F5B100520F19 /* YHAIViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIViewModel.swift; sourceTree = "<group>"; };
045F284B2CF6F65200520F19 /* YHAIListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIListModel.swift; sourceTree = "<group>"; };
0468D4212B493A5E00CFB916 /* YHPhoneMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPhoneMessageView.swift; sourceTree = "<group>"; }; 0468D4212B493A5E00CFB916 /* YHPhoneMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPhoneMessageView.swift; sourceTree = "<group>"; };
0468D4252B495A5400CFB916 /* YHPickPhoneAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPickPhoneAddressViewController.swift; sourceTree = "<group>"; }; 0468D4252B495A5400CFB916 /* YHPickPhoneAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPickPhoneAddressViewController.swift; sourceTree = "<group>"; };
0468D4272B50D4AF00CFB916 /* YHPrivacyAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPrivacyAlertView.swift; sourceTree = "<group>"; }; 0468D4272B50D4AF00CFB916 /* YHPrivacyAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHPrivacyAlertView.swift; sourceTree = "<group>"; };
...@@ -1682,7 +1723,10 @@ ...@@ -1682,7 +1723,10 @@
0493B3DB2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateSearchViewController.swift; sourceTree = "<group>"; }; 0493B3DB2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateSearchViewController.swift; sourceTree = "<group>"; };
0493B3DD2BA80C2300AF9393 /* YHCertificateFilterButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateFilterButton.swift; sourceTree = "<group>"; }; 0493B3DD2BA80C2300AF9393 /* YHCertificateFilterButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateFilterButton.swift; sourceTree = "<group>"; };
04943BE72CF0A0B500BF2255 /* submit_page_scroll.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = submit_page_scroll.gif; sourceTree = "<group>"; }; 04943BE72CF0A0B500BF2255 /* submit_page_scroll.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = submit_page_scroll.gif; sourceTree = "<group>"; };
04943BE92CF1B44100BF2255 /* YHAIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIViewController.swift; sourceTree = "<group>"; }; 04943BE92CF1B44100BF2255 /* YHAIMainChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIMainChatViewController.swift; sourceTree = "<group>"; };
04943BEC2CF46B6600BF2255 /* YHAIRequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIRequestManager.swift; sourceTree = "<group>"; };
04943BF32CF4954800BF2255 /* YHAITextMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAITextMessageCell.swift; sourceTree = "<group>"; };
04943BF52CF49E3E00BF2255 /* YHAITextInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAITextInputView.swift; sourceTree = "<group>"; };
049537842BA9B28500AF7E59 /* YHCertificateTemplateCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateTemplateCell.swift; sourceTree = "<group>"; }; 049537842BA9B28500AF7E59 /* YHCertificateTemplateCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCertificateTemplateCell.swift; sourceTree = "<group>"; };
049663B92BF6105C003C8295 /* YHRefreshHeaderAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHRefreshHeaderAnimator.swift; sourceTree = "<group>"; }; 049663B92BF6105C003C8295 /* YHRefreshHeaderAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHRefreshHeaderAnimator.swift; sourceTree = "<group>"; };
049663BF2BF729F5003C8295 /* galaxy_refresher.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = galaxy_refresher.gif; sourceTree = "<group>"; }; 049663BF2BF729F5003C8295 /* galaxy_refresher.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = galaxy_refresher.gif; sourceTree = "<group>"; };
...@@ -1771,6 +1815,30 @@ ...@@ -1771,6 +1815,30 @@
04B9EE582C06CC3100A4018D /* YHCodeSueecssViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHCodeSueecssViewController.swift; sourceTree = "<group>"; }; 04B9EE582C06CC3100A4018D /* YHCodeSueecssViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHCodeSueecssViewController.swift; sourceTree = "<group>"; };
04B9EE592C06CC3100A4018D /* YHOtherLoginViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHOtherLoginViewController.swift; sourceTree = "<group>"; }; 04B9EE592C06CC3100A4018D /* YHOtherLoginViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHOtherLoginViewController.swift; sourceTree = "<group>"; };
04BD83442CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "AlimamaShuHeiTi-Bold.ttf"; sourceTree = "<group>"; }; 04BD83442CCA2009003A88DF /* AlimamaShuHeiTi-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "AlimamaShuHeiTi-Bold.ttf"; sourceTree = "<group>"; };
04BE39272CF848F300BD31DB /* YHAIMessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIMessageModel.swift; sourceTree = "<group>"; };
04BE39292CF85F8900BD31DB /* YHAITabIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAITabIndicatorView.swift; sourceTree = "<group>"; };
04BE392B2CF8917100BD31DB /* YHAIThinkingMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIThinkingMessageCell.swift; sourceTree = "<group>"; };
04BE392D2CF964A200BD31DB /* YHProductListMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHProductListMessageCell.swift; sourceTree = "<group>"; };
04BE392F2CF964F800BD31DB /* YHProductItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHProductItemView.swift; sourceTree = "<group>"; };
04BE39312CF9AB0900BD31DB /* YHCardMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCardMessageCell.swift; sourceTree = "<group>"; };
04BE39332CF9AFAE00BD31DB /* YHFixProductMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHFixProductMessageCell.swift; sourceTree = "<group>"; };
04BE39352CF9AFF200BD31DB /* YHFixProductItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHFixProductItemView.swift; sourceTree = "<group>"; };
04BE393B2CF9B67000BD31DB /* ai_chat_loading.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ai_chat_loading.json; sourceTree = "<group>"; };
04BE393D2CF9B67700BD31DB /* ai_chat_input_pause.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ai_chat_input_pause.json; sourceTree = "<group>"; };
04BE393F2CF9B95800BD31DB /* YHAIRobotChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIRobotChatViewController.swift; sourceTree = "<group>"; };
04BE39412CF9B99200BD31DB /* YHAIChatConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatConfiguration.swift; sourceTree = "<group>"; };
04BE39432CFAB46100BD31DB /* YHAIChatBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatBannerView.swift; sourceTree = "<group>"; };
04BE39452CFAB5F100BD31DB /* YHAIChatBannerItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatBannerItemCell.swift; sourceTree = "<group>"; };
04BE39472CFABB7F00BD31DB /* YHAIChatBannerCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatBannerCollectionCell.swift; sourceTree = "<group>"; };
04BE39492CFABC5E00BD31DB /* YHAIChatShadowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatShadowView.swift; sourceTree = "<group>"; };
04BE394B2CFAC16600BD31DB /* YHAIChatCustomFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatCustomFlowLayout.swift; sourceTree = "<group>"; };
04BE394D2CFD92C100BD31DB /* YHAIChatInputShadowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatInputShadowView.swift; sourceTree = "<group>"; };
04BE394F2CFD9B5800BD31DB /* YHAIChatDataBaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatDataBaseManager.swift; sourceTree = "<group>"; };
04BE39512CFDA19000BD31DB /* YHAIChatDataBaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIChatDataBaseModel.swift; sourceTree = "<group>"; };
04BE39532CFEA62000BD31DB /* YHAICardItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAICardItemView.swift; sourceTree = "<group>"; };
04BE39572CFED3F700BD31DB /* YHAIHistoryMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIHistoryMessage.swift; sourceTree = "<group>"; };
04BE39592CFEECFA00BD31DB /* YHAIEvaluationAlertWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIEvaluationAlertWebView.swift; sourceTree = "<group>"; };
04BE395B2CFF058200BD31DB /* YHAIPictureMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAIPictureMessageCell.swift; sourceTree = "<group>"; };
04C693612B723AB8004C1758 /* YHMySettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMySettingViewController.swift; sourceTree = "<group>"; }; 04C693612B723AB8004C1758 /* YHMySettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMySettingViewController.swift; sourceTree = "<group>"; };
04C693632B723B56004C1758 /* YHMySettingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMySettingCell.swift; sourceTree = "<group>"; }; 04C693632B723B56004C1758 /* YHMySettingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMySettingCell.swift; sourceTree = "<group>"; };
04C85DDE2C364FE9008B20D6 /* YHAboutUsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAboutUsCell.swift; sourceTree = "<group>"; }; 04C85DDE2C364FE9008B20D6 /* YHAboutUsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAboutUsCell.swift; sourceTree = "<group>"; };
...@@ -4107,6 +4175,77 @@ ...@@ -4107,6 +4175,77 @@
path = VM; path = VM;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
04943BEE2CF4945800BF2255 /* AI */ = {
isa = PBXGroup;
children = (
04943BEF2CF4946200BF2255 /* AI-Dialogue(AI对话) */,
);
path = AI;
sourceTree = "<group>";
};
04943BEF2CF4946200BF2255 /* AI-Dialogue(AI对话) */ = {
isa = PBXGroup;
children = (
04943BF22CF4948400BF2255 /* C */,
04943BF12CF4947F00BF2255 /* V */,
04943BF02CF4947A00BF2255 /* M */,
);
path = "AI-Dialogue(AI对话)";
sourceTree = "<group>";
};
04943BF02CF4947A00BF2255 /* M */ = {
isa = PBXGroup;
children = (
045F28492CF6F5B100520F19 /* YHAIViewModel.swift */,
045F284B2CF6F65200520F19 /* YHAIListModel.swift */,
04BE39272CF848F300BD31DB /* YHAIMessageModel.swift */,
04BE39572CFED3F700BD31DB /* YHAIHistoryMessage.swift */,
04BE39512CFDA19000BD31DB /* YHAIChatDataBaseModel.swift */,
04BE394F2CFD9B5800BD31DB /* YHAIChatDataBaseManager.swift */,
);
path = M;
sourceTree = "<group>";
};
04943BF12CF4947F00BF2255 /* V */ = {
isa = PBXGroup;
children = (
04943BF32CF4954800BF2255 /* YHAITextMessageCell.swift */,
04BE392B2CF8917100BD31DB /* YHAIThinkingMessageCell.swift */,
04BE392D2CF964A200BD31DB /* YHProductListMessageCell.swift */,
04BE395B2CFF058200BD31DB /* YHAIPictureMessageCell.swift */,
04BE39332CF9AFAE00BD31DB /* YHFixProductMessageCell.swift */,
04BE39312CF9AB0900BD31DB /* YHCardMessageCell.swift */,
045F28452CF6C47800520F19 /* YHAIProductCell.swift */,
04943BF52CF49E3E00BF2255 /* YHAITextInputView.swift */,
045F28472CF6EF9800520F19 /* YHAIGreetCollectionReusableView.swift */,
04BE39292CF85F8900BD31DB /* YHAITabIndicatorView.swift */,
04BE392F2CF964F800BD31DB /* YHProductItemView.swift */,
04BE39532CFEA62000BD31DB /* YHAICardItemView.swift */,
04BE39352CF9AFF200BD31DB /* YHFixProductItemView.swift */,
04BE39432CFAB46100BD31DB /* YHAIChatBannerView.swift */,
04BE39452CFAB5F100BD31DB /* YHAIChatBannerItemCell.swift */,
04BE39472CFABB7F00BD31DB /* YHAIChatBannerCollectionCell.swift */,
04BE39492CFABC5E00BD31DB /* YHAIChatShadowView.swift */,
04BE394D2CFD92C100BD31DB /* YHAIChatInputShadowView.swift */,
04BE394B2CFAC16600BD31DB /* YHAIChatCustomFlowLayout.swift */,
04BE39592CFEECFA00BD31DB /* YHAIEvaluationAlertWebView.swift */,
);
path = V;
sourceTree = "<group>";
};
04943BF22CF4948400BF2255 /* C */ = {
isa = PBXGroup;
children = (
045F28412CF6028A00520F19 /* YHAITabViewController.swift */,
04943BE92CF1B44100BF2255 /* YHAIMainChatViewController.swift */,
045F28432CF608C100520F19 /* YHAIServiceListViewController.swift */,
04BE393F2CF9B95800BD31DB /* YHAIRobotChatViewController.swift */,
04943BEC2CF46B6600BF2255 /* YHAIRequestManager.swift */,
04BE39412CF9B99200BD31DB /* YHAIChatConfiguration.swift */,
);
path = C;
sourceTree = "<group>";
};
049663B62BF60BB7003C8295 /* CustomRefreshHeader */ = { 049663B62BF60BB7003C8295 /* CustomRefreshHeader */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -4348,6 +4487,22 @@ ...@@ -4348,6 +4487,22 @@
path = C; path = C;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
04BE39372CF9B5B100BD31DB /* ai_chat_loading */ = {
isa = PBXGroup;
children = (
04BE393B2CF9B67000BD31DB /* ai_chat_loading.json */,
);
path = ai_chat_loading;
sourceTree = "<group>";
};
04BE393A2CF9B61100BD31DB /* ai_chat_input_pause */ = {
isa = PBXGroup;
children = (
04BE393D2CF9B67700BD31DB /* ai_chat_input_pause.json */,
);
path = ai_chat_input_pause;
sourceTree = "<group>";
};
04CA2BE22CB7693500F36DE7 /* UploadTravelCrad(上传旅行证件) */ = { 04CA2BE22CB7693500F36DE7 /* UploadTravelCrad(上传旅行证件) */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -5386,6 +5541,7 @@ ...@@ -5386,6 +5541,7 @@
A5ACE91B2B4564F7002C94D2 /* Modules */ = { A5ACE91B2B4564F7002C94D2 /* Modules */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
04943BEE2CF4945800BF2255 /* AI */,
04129E842CD0C8000072F87B /* AliYunLog(阿里云日志) */, 04129E842CD0C8000072F87B /* AliYunLog(阿里云日志) */,
041470892C885EC900B7B688 /* ButlerServiceManager(银河管家) */, 041470892C885EC900B7B688 /* ButlerServiceManager(银河管家) */,
A596CADD2C6B9AF200F85797 /* HomeAlertViewManager(首页弹窗管理) */, A596CADD2C6B9AF200F85797 /* HomeAlertViewManager(首页弹窗管理) */,
...@@ -5423,7 +5579,6 @@ ...@@ -5423,7 +5579,6 @@
A5ACE9212B4564F7002C94D2 /* YHNavigationController.swift */, A5ACE9212B4564F7002C94D2 /* YHNavigationController.swift */,
A5ACE9222B4564F7002C94D2 /* YHTabBarViewController.swift */, A5ACE9222B4564F7002C94D2 /* YHTabBarViewController.swift */,
A5551FFD2B4C26CE00510980 /* YHBaseViewModel.swift */, A5551FFD2B4C26CE00510980 /* YHBaseViewModel.swift */,
04943BE92CF1B44100BF2255 /* YHAIViewController.swift */,
); );
path = C; path = C;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -5440,6 +5595,7 @@ ...@@ -5440,6 +5595,7 @@
04F243622C9D4C9700DF2C74 /* YHBaseCornerRadiusBorderView.swift */, 04F243622C9D4C9700DF2C74 /* YHBaseCornerRadiusBorderView.swift */,
04F2432E2C94704200DF2C74 /* YHPaddedLabel.swift */, 04F2432E2C94704200DF2C74 /* YHPaddedLabel.swift */,
04395F892CEDB26500D3005C /* YHAutoTextView.swift */, 04395F892CEDB26500D3005C /* YHAutoTextView.swift */,
045F283F2CF5ED3400520F19 /* YHAITabBarItemContentView.swift */,
); );
path = V; path = V;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -5534,6 +5690,8 @@ ...@@ -5534,6 +5690,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
04013E3D2CF87F3A001A8E40 /* zhibo.json */, 04013E3D2CF87F3A001A8E40 /* zhibo.json */,
04BE393A2CF9B61100BD31DB /* ai_chat_input_pause */,
04BE39372CF9B5B100BD31DB /* ai_chat_loading */,
A5F9EA022C647D32005BCA73 /* tabbar */, A5F9EA022C647D32005BCA73 /* tabbar */,
043BA8822C24360C006EF02D /* people_rotate */, 043BA8822C24360C006EF02D /* people_rotate */,
043BA87C2C2435D4006EF02D /* people_launch */, 043BA87C2C2435D4006EF02D /* people_launch */,
...@@ -5759,6 +5917,7 @@ ...@@ -5759,6 +5917,7 @@
049663C02BF729F6003C8295 /* galaxy_refresher.gif in Resources */, 049663C02BF729F6003C8295 /* galaxy_refresher.gif in Resources */,
045EEED42B9F171A0022A143 /* scoreOptionData.plist in Resources */, 045EEED42B9F171A0022A143 /* scoreOptionData.plist in Resources */,
A5EE42032C216C78005BBA5D /* data.json in Resources */, A5EE42032C216C78005BBA5D /* data.json in Resources */,
04BE393C2CF9B67000BD31DB /* ai_chat_loading.json in Resources */,
045EEED62B9F171A0022A143 /* YHQuestionList.plist in Resources */, 045EEED62B9F171A0022A143 /* YHQuestionList.plist in Resources */,
04EA2E722BF74FA200AE80B0 /* zixun.json in Resources */, 04EA2E722BF74FA200AE80B0 /* zixun.json in Resources */,
A5C5B2EE2B4F9B8800A7C5D1 /* Localizable.xcstrings in Resources */, A5C5B2EE2B4F9B8800A7C5D1 /* Localizable.xcstrings in Resources */,
...@@ -5775,6 +5934,7 @@ ...@@ -5775,6 +5934,7 @@
04013E402CF99505001A8E40 /* live.json in Resources */, 04013E402CF99505001A8E40 /* live.json in Resources */,
048FA0332BFDDFF400AD3BA9 /* submit_head_animation.gif in Resources */, 048FA0332BFDDFF400AD3BA9 /* submit_head_animation.gif in Resources */,
A5E69D512BA304D400411932 /* DIN Alternate Bold.ttf in Resources */, A5E69D512BA304D400411932 /* DIN Alternate Bold.ttf in Resources */,
04BE393E2CF9B67700BD31DB /* ai_chat_input_pause.json in Resources */,
A5EE42022C216C78005BBA5D /* img_2.jpg in Resources */, A5EE42022C216C78005BBA5D /* img_2.jpg in Resources */,
04EA2E702BF74FA200AE80B0 /* shipin.json in Resources */, 04EA2E702BF74FA200AE80B0 /* shipin.json in Resources */,
044378A42BFC848C001F95AE /* loginBkg.mov in Resources */, 044378A42BFC848C001F95AE /* loginBkg.mov in Resources */,
...@@ -5987,6 +6147,7 @@ ...@@ -5987,6 +6147,7 @@
04F2434B2C9BB70300DF2C74 /* YHHKRecordsSummaryItemCell.swift in Sources */, 04F2434B2C9BB70300DF2C74 /* YHHKRecordsSummaryItemCell.swift in Sources */,
046A95312C6EFB980059326A /* YHFamilyMemberRiskWarningAlertView.swift in Sources */, 046A95312C6EFB980059326A /* YHFamilyMemberRiskWarningAlertView.swift in Sources */,
A5ACE9292B4564F7002C94D2 /* YHSmsCodeInputView.swift in Sources */, A5ACE9292B4564F7002C94D2 /* YHSmsCodeInputView.swift in Sources */,
04BE39582CFED3F700BD31DB /* YHAIHistoryMessage.swift in Sources */,
A5ACE9452B4564F7002C94D2 /* YHHUDContainerView.swift in Sources */, A5ACE9452B4564F7002C94D2 /* YHHUDContainerView.swift in Sources */,
04912F642CB6885D00CC3105 /* YHResignFamilyMemberInfoCell.swift in Sources */, 04912F642CB6885D00CC3105 /* YHResignFamilyMemberInfoCell.swift in Sources */,
045EEEFD2B9F171A0022A143 /* YHSheetPickerViewType.swift in Sources */, 045EEEFD2B9F171A0022A143 /* YHSheetPickerViewType.swift in Sources */,
...@@ -6037,6 +6198,7 @@ ...@@ -6037,6 +6198,7 @@
045EEEBF2B9F171A0022A143 /* YHWorkFileItemView.swift in Sources */, 045EEEBF2B9F171A0022A143 /* YHWorkFileItemView.swift in Sources */,
04AF58C42B4FC51C0066011A /* YHLocalizable.swift in Sources */, 04AF58C42B4FC51C0066011A /* YHLocalizable.swift in Sources */,
0457921F2CBF62F300EBD99B /* YHResignUploadDetailModel.swift in Sources */, 0457921F2CBF62F300EBD99B /* YHResignUploadDetailModel.swift in Sources */,
04BE39282CF848F300BD31DB /* YHAIMessageModel.swift in Sources */,
04F4A5282CB8D4270026D469 /* YHResignAppointScheduleListViewController.swift in Sources */, 04F4A5282CB8D4270026D469 /* YHResignAppointScheduleListViewController.swift in Sources */,
A598E9E22C7CB32D00F84739 /* YHTravelDocsPreparationListModel.swift in Sources */, A598E9E22C7CB32D00F84739 /* YHTravelDocsPreparationListModel.swift in Sources */,
A598E9D72C7C9EF300F84739 /* YHTravelDocsPreparationListViewController.swift in Sources */, A598E9D72C7C9EF300F84739 /* YHTravelDocsPreparationListViewController.swift in Sources */,
...@@ -6071,12 +6233,14 @@ ...@@ -6071,12 +6233,14 @@
04256DF42C73626900A37BA4 /* YHServiceSelectAlertView.swift in Sources */, 04256DF42C73626900A37BA4 /* YHServiceSelectAlertView.swift in Sources */,
04F5F8702C1AC4C2004A463C /* YHHKEventWebViewController.swift in Sources */, 04F5F8702C1AC4C2004A463C /* YHHKEventWebViewController.swift in Sources */,
045EEE892B9F171A0022A143 /* YHPreviewBaseViewController.swift in Sources */, 045EEE892B9F171A0022A143 /* YHPreviewBaseViewController.swift in Sources */,
04BE39342CF9AFAE00BD31DB /* YHFixProductMessageCell.swift in Sources */,
045EEEA42B9F171A0022A143 /* YHImageResultViewController.swift in Sources */, 045EEEA42B9F171A0022A143 /* YHImageResultViewController.swift in Sources */,
045EEE812B9F171A0022A143 /* YHPreviewQuestionAndAnswerModel.swift in Sources */, 045EEE812B9F171A0022A143 /* YHPreviewQuestionAndAnswerModel.swift in Sources */,
049D62C02C6F1E6700E811A1 /* YHFamilyInfoWarmTipsView.swift in Sources */, 049D62C02C6F1E6700E811A1 /* YHFamilyInfoWarmTipsView.swift in Sources */,
04943BEA2CF1B44100BF2255 /* YHAIViewController.swift in Sources */, 04943BEA2CF1B44100BF2255 /* YHAIMainChatViewController.swift in Sources */,
04C85DDF2C364FE9008B20D6 /* YHAboutUsCell.swift in Sources */, 04C85DDF2C364FE9008B20D6 /* YHAboutUsCell.swift in Sources */,
045EEEB02B9F171A0022A143 /* YHWorkItemView.swift in Sources */, 045EEEB02B9F171A0022A143 /* YHWorkItemView.swift in Sources */,
04BE395A2CFEECFA00BD31DB /* YHAIEvaluationAlertWebView.swift in Sources */,
0468D4222B493A5E00CFB916 /* YHPhoneMessageView.swift in Sources */, 0468D4222B493A5E00CFB916 /* YHPhoneMessageView.swift in Sources */,
049D62C72C6F2F4F00E811A1 /* YHApproverInfoVerifyCell.swift in Sources */, 049D62C72C6F2F4F00E811A1 /* YHApproverInfoVerifyCell.swift in Sources */,
048787D12BCE61B20036E221 /* YHServiceNoOrderView.swift in Sources */, 048787D12BCE61B20036E221 /* YHServiceNoOrderView.swift in Sources */,
...@@ -6089,6 +6253,7 @@ ...@@ -6089,6 +6253,7 @@
04912F7E2CB7B2BA00CC3105 /* YHResignAppointOptionResultCell.swift in Sources */, 04912F7E2CB7B2BA00CC3105 /* YHResignAppointOptionResultCell.swift in Sources */,
A567E5972BD7643D00D5D5A0 /* YHHomeModel.swift in Sources */, A567E5972BD7643D00D5D5A0 /* YHHomeModel.swift in Sources */,
04AF82D82C291E960028CE2A /* YHMatchUserViewModel.swift in Sources */, 04AF82D82C291E960028CE2A /* YHMatchUserViewModel.swift in Sources */,
04BE39402CF9B95800BD31DB /* YHAIRobotChatViewController.swift in Sources */,
0468D4362B57752F00CFB916 /* YHUserModel.swift in Sources */, 0468D4362B57752F00CFB916 /* YHUserModel.swift in Sources */,
040450CF2CC8A0F400D1CFE5 /* YHResignDocumentMultiLineTipsCell.swift in Sources */, 040450CF2CC8A0F400D1CFE5 /* YHResignDocumentMultiLineTipsCell.swift in Sources */,
A567E5982BD7643D00D5D5A0 /* YHHKEventModel.swift in Sources */, A567E5982BD7643D00D5D5A0 /* YHHKEventModel.swift in Sources */,
...@@ -6168,6 +6333,7 @@ ...@@ -6168,6 +6333,7 @@
044EE23C2C92BFDC00A2FE3A /* YHResignCertificateModel.swift in Sources */, 044EE23C2C92BFDC00A2FE3A /* YHResignCertificateModel.swift in Sources */,
049D62C22C6F258700E811A1 /* YHFamilyInfoConfirmViewController.swift in Sources */, 049D62C22C6F258700E811A1 /* YHFamilyInfoConfirmViewController.swift in Sources */,
0430E64C2C732821000511E2 /* YHNoAdopterAlertView.swift in Sources */, 0430E64C2C732821000511E2 /* YHNoAdopterAlertView.swift in Sources */,
04BE39482CFABB7F00BD31DB /* YHAIChatBannerCollectionCell.swift in Sources */,
04CE1ADE2C2AD91F001CB80A /* YHActivityTravelCell.swift in Sources */, 04CE1ADE2C2AD91F001CB80A /* YHActivityTravelCell.swift in Sources */,
045EEF072B9F171A0022A143 /* YHBasicInfoFillViewModel.swift in Sources */, 045EEF072B9F171A0022A143 /* YHBasicInfoFillViewModel.swift in Sources */,
045EEF212B9F171A0022A143 /* YHMainInformationTableViewCell.swift in Sources */, 045EEF212B9F171A0022A143 /* YHMainInformationTableViewCell.swift in Sources */,
...@@ -6177,6 +6343,7 @@ ...@@ -6177,6 +6343,7 @@
042B20D42CEAE5E900655093 /* YHImproveTargetListCell.swift in Sources */, 042B20D42CEAE5E900655093 /* YHImproveTargetListCell.swift in Sources */,
04D144762C0452E200EE3758 /* YHOneKeyLoginManager.swift in Sources */, 04D144762C0452E200EE3758 /* YHOneKeyLoginManager.swift in Sources */,
A5551FFE2B4C26CE00510980 /* YHBaseViewModel.swift in Sources */, A5551FFE2B4C26CE00510980 /* YHBaseViewModel.swift in Sources */,
04BE394E2CFD92C100BD31DB /* YHAIChatInputShadowView.swift in Sources */,
04B360F72C646B4F001EB053 /* YHPrincipleEnvelopeModel.swift in Sources */, 04B360F72C646B4F001EB053 /* YHPrincipleEnvelopeModel.swift in Sources */,
048B2A4A2BC7D9DC00A93BF0 /* YHMyLikeViewController.swift in Sources */, 048B2A4A2BC7D9DC00A93BF0 /* YHMyLikeViewController.swift in Sources */,
A567E5AE2BD7643D00D5D5A0 /* YHHomeKingKongBlockItem.swift in Sources */, A567E5AE2BD7643D00D5D5A0 /* YHHomeKingKongBlockItem.swift in Sources */,
...@@ -6189,6 +6356,7 @@ ...@@ -6189,6 +6356,7 @@
04FB01D02C23FA420040115D /* YHMatchUserInfo.swift in Sources */, 04FB01D02C23FA420040115D /* YHMatchUserInfo.swift in Sources */,
045EEEE92B9F171A0022A143 /* YHFamilyRequestViewModel.swift in Sources */, 045EEEE92B9F171A0022A143 /* YHFamilyRequestViewModel.swift in Sources */,
04B360E72C60CD37001EB053 /* YHPrincipleUploadFileCell.swift in Sources */, 04B360E72C60CD37001EB053 /* YHPrincipleUploadFileCell.swift in Sources */,
04BE394C2CFAC16600BD31DB /* YHAIChatCustomFlowLayout.swift in Sources */,
04F957472C203033003C631C /* YHMyGoodFriendsVC.swift in Sources */, 04F957472C203033003C631C /* YHMyGoodFriendsVC.swift in Sources */,
044867B42BA1953B00DFAD4A /* YHCertificateFilterView.swift in Sources */, 044867B42BA1953B00DFAD4A /* YHCertificateFilterView.swift in Sources */,
045EEEDF2B9F171A0022A143 /* YHCollegeSearchBar.swift in Sources */, 045EEEDF2B9F171A0022A143 /* YHCollegeSearchBar.swift in Sources */,
...@@ -6212,6 +6380,7 @@ ...@@ -6212,6 +6380,7 @@
0472E25E2C534723008EAB6E /* YHLifeDetailViewController.swift in Sources */, 0472E25E2C534723008EAB6E /* YHLifeDetailViewController.swift in Sources */,
0457920D2CBCE8A800EBD99B /* YHResignUploadTravelCardListModel.swift in Sources */, 0457920D2CBCE8A800EBD99B /* YHResignUploadTravelCardListModel.swift in Sources */,
A5ACE92E2B4564F7002C94D2 /* YHValidateCodeInputView.swift in Sources */, A5ACE92E2B4564F7002C94D2 /* YHValidateCodeInputView.swift in Sources */,
04BE392C2CF8917100BD31DB /* YHAIThinkingMessageCell.swift in Sources */,
045EEED82B9F171A0022A143 /* YHQuestionInfo.swift in Sources */, 045EEED82B9F171A0022A143 /* YHQuestionInfo.swift in Sources */,
A567E5B82BD7643D00D5D5A0 /* YHSearchItemLayout.swift in Sources */, A567E5B82BD7643D00D5D5A0 /* YHSearchItemLayout.swift in Sources */,
A567E5A02BD7643D00D5D5A0 /* YHHomeWebViewController.swift in Sources */, A567E5A02BD7643D00D5D5A0 /* YHHomeWebViewController.swift in Sources */,
...@@ -6223,6 +6392,7 @@ ...@@ -6223,6 +6392,7 @@
04CE1AD82C2AD91F001CB80A /* YHActivityListViewController.swift in Sources */, 04CE1AD82C2AD91F001CB80A /* YHActivityListViewController.swift in Sources */,
A5ACE94E2B4564F7002C94D2 /* AlignedCollectionViewFlowLayout.swift in Sources */, A5ACE94E2B4564F7002C94D2 /* AlignedCollectionViewFlowLayout.swift in Sources */,
A567E5B32BD7643D00D5D5A0 /* YHServiceOrderAlertView.swift in Sources */, A567E5B32BD7643D00D5D5A0 /* YHServiceOrderAlertView.swift in Sources */,
04943BF42CF4954800BF2255 /* YHAITextMessageCell.swift in Sources */,
A592FE932BA6CFFC0062FACA /* YHCertificateEntryBottomView.swift in Sources */, A592FE932BA6CFFC0062FACA /* YHCertificateEntryBottomView.swift in Sources */,
A5ACE93B2B4564F7002C94D2 /* UIFont+Extension.swift in Sources */, A5ACE93B2B4564F7002C94D2 /* UIFont+Extension.swift in Sources */,
047F3DD92CE601D1001B2A6D /* YHEducationCertificateConfirmCell.swift in Sources */, 047F3DD92CE601D1001B2A6D /* YHEducationCertificateConfirmCell.swift in Sources */,
...@@ -6312,7 +6482,9 @@ ...@@ -6312,7 +6482,9 @@
04F243662C9D5CB200DF2C74 /* YHResignDocumentViewModel.swift in Sources */, 04F243662C9D5CB200DF2C74 /* YHResignDocumentViewModel.swift in Sources */,
A567E5B22BD7643D00D5D5A0 /* YHHomeBannerCollectionViewCell.swift in Sources */, A567E5B22BD7643D00D5D5A0 /* YHHomeBannerCollectionViewCell.swift in Sources */,
0430E68A2C77415D000511E2 /* YHAdopterAddModel.swift in Sources */, 0430E68A2C77415D000511E2 /* YHAdopterAddModel.swift in Sources */,
04BE39442CFAB46100BD31DB /* YHAIChatBannerView.swift in Sources */,
045EEF082B9F171A0022A143 /* YHBasicInfoCellModel.swift in Sources */, 045EEF082B9F171A0022A143 /* YHBasicInfoCellModel.swift in Sources */,
045F284A2CF6F5B100520F19 /* YHAIViewModel.swift in Sources */,
A59B43C92C491FB100B28379 /* YHH5WebViewVC.swift in Sources */, A59B43C92C491FB100B28379 /* YHH5WebViewVC.swift in Sources */,
0488518F2BF5FD1500C4E32D /* YHOSSManager.swift in Sources */, 0488518F2BF5FD1500C4E32D /* YHOSSManager.swift in Sources */,
A592FE952BA6D23C0062FACA /* YHCertificateEntryCell.swift in Sources */, A592FE952BA6D23C0062FACA /* YHCertificateEntryCell.swift in Sources */,
...@@ -6342,6 +6514,7 @@ ...@@ -6342,6 +6514,7 @@
A5ACE9312B4564F7002C94D2 /* YHPersonalCenterCell.swift in Sources */, A5ACE9312B4564F7002C94D2 /* YHPersonalCenterCell.swift in Sources */,
0430E6562C7342AB000511E2 /* YHAdopterIncomeFileCountTableViewCell.swift in Sources */, 0430E6562C7342AB000511E2 /* YHAdopterIncomeFileCountTableViewCell.swift in Sources */,
0449EEEB2C8EF2B700A397FD /* YHResignMaterialListVC.swift in Sources */, 0449EEEB2C8EF2B700A397FD /* YHResignMaterialListVC.swift in Sources */,
04943BED2CF46B6600BF2255 /* YHAIRequestManager.swift in Sources */,
044D0C1C2C22C30B00C5CF5E /* YHEditSchoolViewController.swift in Sources */, 044D0C1C2C22C30B00C5CF5E /* YHEditSchoolViewController.swift in Sources */,
044E31C92CBD2AA400500F8E /* YHResignInfoConfirmIViewModel.swift in Sources */, 044E31C92CBD2AA400500F8E /* YHResignInfoConfirmIViewModel.swift in Sources */,
A5CA3F562C74850200EB22F5 /* YHUploadCertificateDetailVC.swift in Sources */, A5CA3F562C74850200EB22F5 /* YHUploadCertificateDetailVC.swift in Sources */,
...@@ -6366,6 +6539,8 @@ ...@@ -6366,6 +6539,8 @@
0414708B2C88627B00B7B688 /* YHButlerServiceManager.swift in Sources */, 0414708B2C88627B00B7B688 /* YHButlerServiceManager.swift in Sources */,
0430E66A2C7493A5000511E2 /* YHAdopterExampleTableViewCell.swift in Sources */, 0430E66A2C7493A5000511E2 /* YHAdopterExampleTableViewCell.swift in Sources */,
04912F962CB924DA00CC3105 /* YHResignAppointTimeModifyViewController.swift in Sources */, 04912F962CB924DA00CC3105 /* YHResignAppointTimeModifyViewController.swift in Sources */,
04BE395C2CFF058200BD31DB /* YHAIPictureMessageCell.swift in Sources */,
045F28482CF6EF9800520F19 /* YHAIGreetCollectionReusableView.swift in Sources */,
045EEF102B9F171A0022A143 /* YHMainApplicantInformationViewModel.swift in Sources */, 045EEF102B9F171A0022A143 /* YHMainApplicantInformationViewModel.swift in Sources */,
0493B3DC2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift in Sources */, 0493B3DC2BA7EFE600AF9393 /* YHCertificateSearchViewController.swift in Sources */,
A5DF9C632C78733200CE48E6 /* YHHKLegaldaysModel.swift in Sources */, A5DF9C632C78733200CE48E6 /* YHHKLegaldaysModel.swift in Sources */,
...@@ -6374,6 +6549,7 @@ ...@@ -6374,6 +6549,7 @@
04256E1D2C75C74200A37BA4 /* YHAppointHKResultModel.swift in Sources */, 04256E1D2C75C74200A37BA4 /* YHAppointHKResultModel.swift in Sources */,
04564D592CF470B2004456E4 /* YHIncomeRecordCompanyTipsCell.swift in Sources */, 04564D592CF470B2004456E4 /* YHIncomeRecordCompanyTipsCell.swift in Sources */,
04564D7C2CF8CF6D004456E4 /* YHPlayer.swift in Sources */, 04564D7C2CF8CF6D004456E4 /* YHPlayer.swift in Sources */,
04BE394A2CFABC5E00BD31DB /* YHAIChatShadowView.swift in Sources */,
047F3DE62CE83A0F001B2A6D /* YHHKRequiredItemView.swift in Sources */, 047F3DE62CE83A0F001B2A6D /* YHHKRequiredItemView.swift in Sources */,
04CE1ADB2C2AD91F001CB80A /* YHActivityTitleItemView.swift in Sources */, 04CE1ADB2C2AD91F001CB80A /* YHActivityTitleItemView.swift in Sources */,
042B20E32CEC92C400655093 /* YHMajorNameCell.swift in Sources */, 042B20E32CEC92C400655093 /* YHMajorNameCell.swift in Sources */,
...@@ -6446,10 +6622,12 @@ ...@@ -6446,10 +6622,12 @@
045EEEC12B9F171A0022A143 /* YHOtherInfoFillModel.swift in Sources */, 045EEEC12B9F171A0022A143 /* YHOtherInfoFillModel.swift in Sources */,
047A3DF52C295AFF0048937B /* YHFriendListModel.swift in Sources */, 047A3DF52C295AFF0048937B /* YHFriendListModel.swift in Sources */,
04912F722CB7714300CC3105 /* YHResignAppointTimeSingleCell.swift in Sources */, 04912F722CB7714300CC3105 /* YHResignAppointTimeSingleCell.swift in Sources */,
04BE39302CF964F800BD31DB /* YHProductItemView.swift in Sources */,
0468D43A2B579EAC00CFB916 /* YHLoginViewModel.swift in Sources */, 0468D43A2B579EAC00CFB916 /* YHLoginViewModel.swift in Sources */,
04CE1AD72C2AD91F001CB80A /* YHActivityDetailViewController.swift in Sources */, 04CE1AD72C2AD91F001CB80A /* YHActivityDetailViewController.swift in Sources */,
045EEE9E2B9F171A0022A143 /* YHWorkExampleModel.swift in Sources */, 045EEE9E2B9F171A0022A143 /* YHWorkExampleModel.swift in Sources */,
045EEE8A2B9F171A0022A143 /* YHPreviewOtherInformationViewController.swift in Sources */, 045EEE8A2B9F171A0022A143 /* YHPreviewOtherInformationViewController.swift in Sources */,
04BE39542CFEA62000BD31DB /* YHAICardItemView.swift in Sources */,
04F2433B2C9ACED700DF2C74 /* YHHKRecordsSummaryVC.swift in Sources */, 04F2433B2C9ACED700DF2C74 /* YHHKRecordsSummaryVC.swift in Sources */,
044F39402CB7CB6B007CA277 /* YHVisaRenewalTroubleshootingGuideVC.swift in Sources */, 044F39402CB7CB6B007CA277 /* YHVisaRenewalTroubleshootingGuideVC.swift in Sources */,
043D2C8A2C0EEF3F00172438 /* YHOrderSearchViewController.swift in Sources */, 043D2C8A2C0EEF3F00172438 /* YHOrderSearchViewController.swift in Sources */,
...@@ -6504,6 +6682,7 @@ ...@@ -6504,6 +6682,7 @@
045EEF0F2B9F171A0022A143 /* YHSelectCountryViewModel.swift in Sources */, 045EEF0F2B9F171A0022A143 /* YHSelectCountryViewModel.swift in Sources */,
04F2432B2C942B5100DF2C74 /* YHResignDocumentTipsCell.swift in Sources */, 04F2432B2C942B5100DF2C74 /* YHResignDocumentTipsCell.swift in Sources */,
A567E59F2BD7643D00D5D5A0 /* YHStartPageViewController.swift in Sources */, A567E59F2BD7643D00D5D5A0 /* YHStartPageViewController.swift in Sources */,
04BE392E2CF964A200BD31DB /* YHProductListMessageCell.swift in Sources */,
045EEF202B9F171A0022A143 /* YHCardExampleView.swift in Sources */, 045EEF202B9F171A0022A143 /* YHCardExampleView.swift in Sources */,
A567E5A72BD7643D00D5D5A0 /* YHHomeKingKongBlockView.swift in Sources */, A567E5A72BD7643D00D5D5A0 /* YHHomeKingKongBlockView.swift in Sources */,
04912F8C2CB907F200CC3105 /* YHResignAppointTimeMultipleCell.swift in Sources */, 04912F8C2CB907F200CC3105 /* YHResignAppointTimeMultipleCell.swift in Sources */,
...@@ -6565,6 +6744,7 @@ ...@@ -6565,6 +6744,7 @@
04256E182C75BD2700A37BA4 /* YHVisaPayTypeCell.swift in Sources */, 04256E182C75BD2700A37BA4 /* YHVisaPayTypeCell.swift in Sources */,
0430E6642C7482DD000511E2 /* YHYHAdopterTravelViewModel.swift in Sources */, 0430E6642C7482DD000511E2 /* YHYHAdopterTravelViewModel.swift in Sources */,
A5CA3F502C7447FB00EB22F5 /* YHUploadCertificateVC.swift in Sources */, A5CA3F502C7447FB00EB22F5 /* YHUploadCertificateVC.swift in Sources */,
045F28462CF6C47800520F19 /* YHAIProductCell.swift in Sources */,
04A7BD192BA441D400BD35A2 /* YHMyDocumentsUrlModel.swift in Sources */, 04A7BD192BA441D400BD35A2 /* YHMyDocumentsUrlModel.swift in Sources */,
04DF69BB2CBA1CC5005AA41E /* YHResignSelectApplicantCollectCell.swift in Sources */, 04DF69BB2CBA1CC5005AA41E /* YHResignSelectApplicantCollectCell.swift in Sources */,
04A91E742CC6220900E5A079 /* YHCommonAlertView+AttributedMessage.swift in Sources */, 04A91E742CC6220900E5A079 /* YHCommonAlertView+AttributedMessage.swift in Sources */,
...@@ -6583,7 +6763,9 @@ ...@@ -6583,7 +6763,9 @@
04CA2C012CB7CEDC00F36DE7 /* YHResignUploadDocDetailViewController.swift in Sources */, 04CA2C012CB7CEDC00F36DE7 /* YHResignUploadDocDetailViewController.swift in Sources */,
04A671622BA058DE00C1FB91 /* YHCertificateEditSheetView.swift in Sources */, 04A671622BA058DE00C1FB91 /* YHCertificateEditSheetView.swift in Sources */,
04F4A52C2CB8F8190026D469 /* YHResignAppointedScheduleRiskTipsView.swift in Sources */, 04F4A52C2CB8F8190026D469 /* YHResignAppointedScheduleRiskTipsView.swift in Sources */,
04BE39322CF9AB0900BD31DB /* YHCardMessageCell.swift in Sources */,
04AD317D2C295AE800DF5655 /* YHUserInfoSettingViewModel.swift in Sources */, 04AD317D2C295AE800DF5655 /* YHUserInfoSettingViewModel.swift in Sources */,
04943BF62CF49E3E00BF2255 /* YHAITextInputView.swift in Sources */,
045A08C22C37EB8B00BCBABA /* YHMyFileListNoneCell.swift in Sources */, 045A08C22C37EB8B00BCBABA /* YHMyFileListNoneCell.swift in Sources */,
04F2435F2C9D1C0600DF2C74 /* YHHKRecordsStayingPersonnelCell.swift in Sources */, 04F2435F2C9D1C0600DF2C74 /* YHHKRecordsStayingPersonnelCell.swift in Sources */,
A5EB6C732C69FB9A0081FB6C /* YHOffivialApprovalSuccessCheckView.swift in Sources */, A5EB6C732C69FB9A0081FB6C /* YHOffivialApprovalSuccessCheckView.swift in Sources */,
...@@ -6670,6 +6852,7 @@ ...@@ -6670,6 +6852,7 @@
048097712BA18D66000B9DCA /* YHCertificateSearchBar.swift in Sources */, 048097712BA18D66000B9DCA /* YHCertificateSearchBar.swift in Sources */,
04F243432C9BB3F800DF2C74 /* YHHKRecordsHeaderCell.swift in Sources */, 04F243432C9BB3F800DF2C74 /* YHHKRecordsHeaderCell.swift in Sources */,
04256E172C75BD2700A37BA4 /* YHVisaPaymentTipsCell.swift in Sources */, 04256E172C75BD2700A37BA4 /* YHVisaPaymentTipsCell.swift in Sources */,
04BE39422CF9B99200BD31DB /* YHAIChatConfiguration.swift in Sources */,
045EEEAA2B9F171A0022A143 /* YHWorkExampleViewController.swift in Sources */, 045EEEAA2B9F171A0022A143 /* YHWorkExampleViewController.swift in Sources */,
04256E1F2C7618A800A37BA4 /* YHAppointWarmTipsCell.swift in Sources */, 04256E1F2C7618A800A37BA4 /* YHAppointWarmTipsCell.swift in Sources */,
0413A9B12CFFDB9A00304BC6 /* YHCategoryDropdownView.swift in Sources */, 0413A9B12CFFDB9A00304BC6 /* YHCategoryDropdownView.swift in Sources */,
...@@ -6701,11 +6884,13 @@ ...@@ -6701,11 +6884,13 @@
04B401D92CE6E6C8005C61A9 /* YHIncomeItemOccupyingCell.swift in Sources */, 04B401D92CE6E6C8005C61A9 /* YHIncomeItemOccupyingCell.swift in Sources */,
04B401DA2CE6E6C8005C61A9 /* YHTotalIncomeCell.swift in Sources */, 04B401DA2CE6E6C8005C61A9 /* YHTotalIncomeCell.swift in Sources */,
04EA230E2BB538E9009DA928 /* YHDocumentUploadTableViewCell.swift in Sources */, 04EA230E2BB538E9009DA928 /* YHDocumentUploadTableViewCell.swift in Sources */,
045F284C2CF6F65200520F19 /* YHAIListModel.swift in Sources */,
04256DEA2C73263A00A37BA4 /* YHInfoItemSelectSheetView.swift in Sources */, 04256DEA2C73263A00A37BA4 /* YHInfoItemSelectSheetView.swift in Sources */,
0430E6822C75E068000511E2 /* YHAdopterCardOtherGuideView.swift in Sources */, 0430E6822C75E068000511E2 /* YHAdopterCardOtherGuideView.swift in Sources */,
04174D742BCD5B74000BA46D /* IMAppKey.swift in Sources */, 04174D742BCD5B74000BA46D /* IMAppKey.swift in Sources */,
A567E5B62BD7643D00D5D5A0 /* YHHomeBannerIndicatorView.swift in Sources */, A567E5B62BD7643D00D5D5A0 /* YHHomeBannerIndicatorView.swift in Sources */,
04CA2BFB2CB7BAC600F36DE7 /* YHResignUploadDocListViewController.swift in Sources */, 04CA2BFB2CB7BAC600F36DE7 /* YHResignUploadDocListViewController.swift in Sources */,
04BE392A2CF85F8900BD31DB /* YHAITabIndicatorView.swift in Sources */,
045EEEAD2B9F171A0022A143 /* YHWorkExperienceListTableViewCell.swift in Sources */, 045EEEAD2B9F171A0022A143 /* YHWorkExperienceListTableViewCell.swift in Sources */,
049A48A82B49417300D0C641 /* YHAboutUsViewController.swift in Sources */, 049A48A82B49417300D0C641 /* YHAboutUsViewController.swift in Sources */,
047619E92BA9867100F45358 /* YHCountryHotView.swift in Sources */, 047619E92BA9867100F45358 /* YHCountryHotView.swift in Sources */,
...@@ -6716,6 +6901,7 @@ ...@@ -6716,6 +6901,7 @@
A598E9E62C7EF39D00F84739 /* YHTravelDocsPreparationDetailVC.swift in Sources */, A598E9E62C7EF39D00F84739 /* YHTravelDocsPreparationDetailVC.swift in Sources */,
045EEEF82B9F171A0022A143 /* YHFormItemOnlyDoubleChoiceCell.swift in Sources */, 045EEEF82B9F171A0022A143 /* YHFormItemOnlyDoubleChoiceCell.swift in Sources */,
A598E9DF2C7CB2C400F84739 /* YHTravelDocsPreparationViewModel.swift in Sources */, A598E9DF2C7CB2C400F84739 /* YHTravelDocsPreparationViewModel.swift in Sources */,
04BE39502CFD9B5900BD31DB /* YHAIChatDataBaseManager.swift in Sources */,
04CA2BE82CB769CD00F36DE7 /* YHResignUploadTravelCardListViewController.swift in Sources */, 04CA2BE82CB769CD00F36DE7 /* YHResignUploadTravelCardListViewController.swift in Sources */,
0480976D2BA158A1000B9DCA /* YHCertificateListVC.swift in Sources */, 0480976D2BA158A1000B9DCA /* YHCertificateListVC.swift in Sources */,
04CCEDFF2CA161910026EA70 /* YHHKRecordsFamilyMembers.swift in Sources */, 04CCEDFF2CA161910026EA70 /* YHHKRecordsFamilyMembers.swift in Sources */,
...@@ -6736,6 +6922,7 @@ ...@@ -6736,6 +6922,7 @@
04A271252BAC33BB00652B1B /* YHFilePreviewTool.swift in Sources */, 04A271252BAC33BB00652B1B /* YHFilePreviewTool.swift in Sources */,
044F39322CB64CC0007CA277 /* YHBottomPresentationController.swift in Sources */, 044F39322CB64CC0007CA277 /* YHBottomPresentationController.swift in Sources */,
045EEEC32B9F171A0022A143 /* YHOtherResidenceFillView.swift in Sources */, 045EEEC32B9F171A0022A143 /* YHOtherResidenceFillView.swift in Sources */,
04BE39522CFDA19000BD31DB /* YHAIChatDataBaseModel.swift in Sources */,
045EEE792B9F171A0022A143 /* YHPreviewViewModel.swift in Sources */, 045EEE792B9F171A0022A143 /* YHPreviewViewModel.swift in Sources */,
A54A07C92C7F478200F749AB /* YHTravelHKDLGuideSheetView.swift in Sources */, A54A07C92C7F478200F749AB /* YHTravelHKDLGuideSheetView.swift in Sources */,
04174D782BCD5B74000BA46D /* YHMessageListVC.swift in Sources */, 04174D782BCD5B74000BA46D /* YHMessageListVC.swift in Sources */,
...@@ -6765,6 +6952,7 @@ ...@@ -6765,6 +6952,7 @@
A5F886B62C61F76200B63CF5 /* YHLongtapPictureSheetView.swift in Sources */, A5F886B62C61F76200B63CF5 /* YHLongtapPictureSheetView.swift in Sources */,
045EEF1C2B9F171A0022A143 /* YHAddressPresentAnimated.swift in Sources */, 045EEF1C2B9F171A0022A143 /* YHAddressPresentAnimated.swift in Sources */,
04B401E82CE83FBD005C61A9 /* YHIncomeDocumentationConfirmationCell.swift in Sources */, 04B401E82CE83FBD005C61A9 /* YHIncomeDocumentationConfirmationCell.swift in Sources */,
045F28422CF6028A00520F19 /* YHAITabViewController.swift in Sources */,
04E86E0D2B70D51D00A35F4B /* YHWebViewViewController.swift in Sources */, 04E86E0D2B70D51D00A35F4B /* YHWebViewViewController.swift in Sources */,
048058332C7DC0CF00502CAA /* YHTravelCertificateTipsCell.swift in Sources */, 048058332C7DC0CF00502CAA /* YHTravelCertificateTipsCell.swift in Sources */,
04256E252C76E26100A37BA4 /* YHNoNeedAppointMembersCell.swift in Sources */, 04256E252C76E26100A37BA4 /* YHNoNeedAppointMembersCell.swift in Sources */,
...@@ -6804,6 +6992,7 @@ ...@@ -6804,6 +6992,7 @@
047AA3E42C4A6ADC009C4554 /* YHLifeHeadView.swift in Sources */, 047AA3E42C4A6ADC009C4554 /* YHLifeHeadView.swift in Sources */,
A58A8C942BA6C7C600632765 /* YHCertificateEntryModel.swift in Sources */, A58A8C942BA6C7C600632765 /* YHCertificateEntryModel.swift in Sources */,
044F39242CB50FB4007CA277 /* YHResignDocumentUploadActionCell.swift in Sources */, 044F39242CB50FB4007CA277 /* YHResignDocumentUploadActionCell.swift in Sources */,
045F28402CF5ED3400520F19 /* YHAITabBarItemContentView.swift in Sources */,
045EEEB82B9F171A0022A143 /* YHWorkExampleMessageView.swift in Sources */, 045EEEB82B9F171A0022A143 /* YHWorkExampleMessageView.swift in Sources */,
04256E142C75BD2700A37BA4 /* YHPayMemberItemsView.swift in Sources */, 04256E142C75BD2700A37BA4 /* YHPayMemberItemsView.swift in Sources */,
04F4B76B2BAA7E1E00D13284 /* YHCertificateTemplateSheetView.swift in Sources */, 04F4B76B2BAA7E1E00D13284 /* YHCertificateTemplateSheetView.swift in Sources */,
...@@ -6842,11 +7031,14 @@ ...@@ -6842,11 +7031,14 @@
045EEF1F2B9F171A0022A143 /* YHDatePickView.swift in Sources */, 045EEF1F2B9F171A0022A143 /* YHDatePickView.swift in Sources */,
04B401E42CE76B10005C61A9 /* YHIncomeInputMoneyCell.swift in Sources */, 04B401E42CE76B10005C61A9 /* YHIncomeInputMoneyCell.swift in Sources */,
04174D7A2BCD5B74000BA46D /* YHDetailMessageCell.swift in Sources */, 04174D7A2BCD5B74000BA46D /* YHDetailMessageCell.swift in Sources */,
04BE39462CFAB5F200BD31DB /* YHAIChatBannerItemCell.swift in Sources */,
04BE39362CF9AFF200BD31DB /* YHFixProductItemView.swift in Sources */,
04912F942CB921C300CC3105 /* YHResignAppointContainerViewController.swift in Sources */, 04912F942CB921C300CC3105 /* YHResignAppointContainerViewController.swift in Sources */,
045EEE972B9F171A0022A143 /* YHPreviewInfoWorkExpView.swift in Sources */, 045EEE972B9F171A0022A143 /* YHPreviewInfoWorkExpView.swift in Sources */,
04B401EC2CE84CBD005C61A9 /* YHIncomeTypePopViewSelectCell.swift in Sources */, 04B401EC2CE84CBD005C61A9 /* YHIncomeTypePopViewSelectCell.swift in Sources */,
04B401F42CEB1C51005C61A9 /* YHIncomeCompanyDetailModel.swift in Sources */, 04B401F42CEB1C51005C61A9 /* YHIncomeCompanyDetailModel.swift in Sources */,
04564D7E2CF8D03D004456E4 /* YHFloatingWindow.swift in Sources */, 04564D7E2CF8D03D004456E4 /* YHFloatingWindow.swift in Sources */,
045F28442CF608C100520F19 /* YHAIServiceListViewController.swift in Sources */,
044BACC72BCFA58E00184C64 /* YHNoDataTipsView.swift in Sources */, 044BACC72BCFA58E00184C64 /* YHNoDataTipsView.swift in Sources */,
04013E442CFD7F66001A8E40 /* YHLiveStateViewController.swift in Sources */, 04013E442CFD7F66001A8E40 /* YHLiveStateViewController.swift in Sources */,
04D5C5662B8ED92600190021 /* YHBaseModel.swift in Sources */, 04D5C5662B8ED92600190021 /* YHBaseModel.swift in Sources */,
......
...@@ -26,7 +26,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate { ...@@ -26,7 +26,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
Thread.sleep(forTimeInterval: 0.5) // 应产品同学Nick要求 启动页时间展示长点 Thread.sleep(forTimeInterval: 0.5) // 应产品同学Nick要求 启动页时间展示长点
setupAudionConfig() setupAudionConfig()
//初始化 神策sdk //初始化 神策sdk
...@@ -217,27 +216,9 @@ extension AppDelegate { ...@@ -217,27 +216,9 @@ extension AppDelegate {
//1.设置HomePageView为主窗口 //1.设置HomePageView为主窗口
func setupRootVCWithTabBar() { func setupRootVCWithTabBar() {
let tabBarController = YHTabBarViewController()
let homeVC = YHHomeHoldViewPageViewController()
tabBarController.delegate = homeVC
let v0 = YHNavigationController(rootVC:homeVC)
let v1 = YHNavigationController(rootVC:YHServiceCenterViewController())
let v2 = YHNavigationController(rootVC:YHCommunityViewController())
let v3 = YHNavigationController(rootVC:YHMyViewController())
v0.tabBarItem = ESTabBarItem.init(YHHomeLottieAnimateContentView(),title: "首页", image: UIImage(named: "home"), selectedImage: UIImage(named: "home_1"))
v1.tabBarItem = ESTabBarItem.init(YHServiceLottieAnimateContentView(),title: "服务", image: UIImage(named: "service"), selectedImage: UIImage(named: "service_1"))
v2.tabBarItem = ESTabBarItem.init(YHCommunityLottieAnimateContentView(),title: "朋友", image: UIImage(named: "msg"), selectedImage: UIImage(named: "msg_1"))
v3.tabBarItem = ESTabBarItem.init(YHMyLottieAnimateContentView(),title: "我的", image: UIImage(named: "me"), selectedImage: UIImage(named: "me_1"))
tabBarController.viewControllers = [v0,v1,v2,v3]
tabBarController.tabBar.backgroundColor = .white
window = UIWindow(frame: UIScreen.main.bounds) window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = tabBarController window?.rootViewController = configTabBarController()
window?.makeKeyAndVisible() window?.makeKeyAndVisible()
if YHLoginManager.shared.needJumpToMsgTabFlag { if YHLoginManager.shared.needJumpToMsgTabFlag {
......
//
// YHAIViewController.swift
// galaxy
//
// Created by Dufet on 2024/11/23.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Alamofire
class YHAIViewController: YHBaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func requestData() {
// AF.request("http://192.168.52.250:9898/stream")
// .responseStream { response in
// switch response.result {
// case .success(let stream):
// for line in stream {
// print("Received line: \(line)")
// }
// case .failure(let error):
// print("Error: \(error)")
// }
// }
}
}
...@@ -76,6 +76,7 @@ class YHTabBarViewController: ESTabBarController { ...@@ -76,6 +76,7 @@ class YHTabBarViewController: ESTabBarController {
NotificationCenter.default.addObserver(self, selector: #selector(clearFriendTabBadge), name: YhConstant.YhNotification.didMarkAllMessagesReadedNotifiction, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(clearFriendTabBadge), name: YhConstant.YhNotification.didMarkAllMessagesReadedNotifiction, object: nil)
} }
@objc func getTotalUnreadMsgCount() { @objc func getTotalUnreadMsgCount() {
...@@ -102,8 +103,8 @@ class YHTabBarViewController: ESTabBarController { ...@@ -102,8 +103,8 @@ class YHTabBarViewController: ESTabBarController {
} }
func showFriendTabRedBadgeNumber(_ num: Int) { func showFriendTabRedBadgeNumber(_ num: Int) {
if let vcs = self.viewControllers, vcs.count > 2 { if let vcs = self.viewControllers, vcs.count > 3 {
let friendVC = vcs[2] let friendVC = vcs[3]
if let tabBarItem = friendVC.tabBarItem as? ESTabBarItem { if let tabBarItem = friendVC.tabBarItem as? ESTabBarItem {
// badgeValue 空字符串会显示小红点 nil则隐藏 // badgeValue 空字符串会显示小红点 nil则隐藏
var badge: String? = nil var badge: String? = nil
......
//
// YHAITabBarItem.swift
// galaxy
//
// Created by Dufet on 2024/11/26.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import ESTabBarController_swift
class YHAITabBarItemContentView: ESTabBarItemContentView {
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: UIImageView = {
let v = UIImageView(image: UIImage(named: "tab_AI"))
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.removeSubviews()
self.addSubview(iconImgView)
self.addSubview(bottomTitleLabel)
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()
}
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateLayout() {
super.updateLayout()
}
}
...@@ -10,13 +10,18 @@ import UIKit ...@@ -10,13 +10,18 @@ import UIKit
class YHAutoTextView: UITextView, UITextViewDelegate { class YHAutoTextView: UITextView, UITextViewDelegate {
var textChange:((String)->())?
override open var text: String! { override open var text: String! {
didSet { didSet {
textViewDidChange(self)
self.setNeedsLayout() self.setNeedsLayout()
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
let maxHeight = 60.0
static let verticalGap = 5.0
var placeHolder: String = "" { var placeHolder: String = "" {
didSet { didSet {
placeholderLabel.text = placeHolder placeholderLabel.text = placeHolder
...@@ -26,21 +31,19 @@ class YHAutoTextView: UITextView, UITextViewDelegate { ...@@ -26,21 +31,19 @@ class YHAutoTextView: UITextView, UITextViewDelegate {
let placeholderLabel: UILabel = { let placeholderLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.lightGray label.textColor = UIColor.init(hex: 0xB3C8E9)
label.font = UIFont.PFSC_R(ofSize: 15) label.font = UIFont.PFSC_R(ofSize: 14)
return label return label
}() }()
override init(frame: CGRect, textContainer: NSTextContainer?) { override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer) super.init(frame: frame, textContainer: textContainer)
self.font = .PFSC_R(ofSize: 14)
delegate = self delegate = self
isScrollEnabled = false // 禁止滚动 isScrollEnabled = false // 禁止滚动
translatesAutoresizingMaskIntoConstraints = false
clearsOnInsertion = true
self.addSubview(placeholderLabel) self.addSubview(placeholderLabel)
placeholderLabel.snp.makeConstraints { make in placeholderLabel.snp.makeConstraints { make in
make.top.equalTo(5) make.center.equalToSuperview()
make.left.equalTo(5) make.left.equalTo(5)
make.right.equalTo(-5) make.right.equalTo(-5)
} }
...@@ -55,11 +58,41 @@ class YHAutoTextView: UITextView, UITextViewDelegate { ...@@ -55,11 +58,41 @@ class YHAutoTextView: UITextView, UITextViewDelegate {
// 更新自身的高度 // 更新自身的高度
invalidateIntrinsicContentSize() invalidateIntrinsicContentSize()
placeholderLabel.isHidden = !textView.text.isEmpty placeholderLabel.isHidden = !textView.text.isEmpty
textChange?(textView.text)
} }
override var intrinsicContentSize: CGSize { 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)) let size = sizeThatFits(CGSize(width: frame.width, height: .greatestFiniteMagnitude))
return CGSize(width: size.width, height: size.height) var height = size.height
isScrollEnabled = height > maxHeight
if height > maxHeight {
height = maxHeight
self.snp.updateConstraints { make in
make.top.equalTo(11)
make.bottom.equalTo(-11)
}
} else {
self.snp.updateConstraints { make in
make.top.equalTo(11-Self.verticalGap)
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 CGSizeMake(strSize.width, ceil(strSize.height)).height
} }
} }
//
// YHAIChatUIConfiguration.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIChatConfiguration {
static let defaultConfig = 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)
}
func handleReceiveMessage(_ res: YHAIChatMessage?, _ done: Bool, _ messages: inout [YHAIChatMessage]) {
if disableHandleMessage {
for msg in messages {
msg.isDone = true
}
return
}
// 去除loading消息
removeThinkingMessageFromChatList(&messages)
if let res = res {
var find = false
for msg in messages {
if msg.uuid == res.uuid {
if msg.isNeedSpiceMessage(), res.isNeedSpiceMessage() {
// 多个文字需要拼接
find = true
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)
}
}
}
//
// YHAIViewController.swift
// galaxy
//
// Created by Dufet on 2024/11/23.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Alamofire
import IQKeyboardManagerSwift
import JXSegmentedView
class YHAIMainChatViewController: YHBaseViewController {
var robotId: String = ""
var conversationId: String = ""
var historyLastMessageId: String = ""
var messages:[YHAIChatMessage] = []
let manager = YHAIRequestManager()
let viewModel = YHAIViewModel()
lazy var tableView: UITableView = {
let tableView = UITableView(frame:.zero, style:.grouped)
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
}
tableView.showsVerticalScrollIndicator = false
tableView.estimatedSectionHeaderHeight = 1.0
tableView.estimatedSectionFooterHeight = 1.0
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
YHAIChatConfiguration.defaultConfig.registerMessageGroupCells(tableView)
tableView.es.addYHPullToRefresh {
self.getHistoryMessages(false)
}
return tableView
}()
lazy var bottomInputView: YHAITextInputView = {
let v = YHAITextInputView(frame: .zero)
v.sendBlock = {
[weak self] text in
guard let self = self else { return }
self.sendMessage(text)
}
v.stopSendBlock = {
[weak self] in
guard let self = self else { return }
self.manager.stopChat(chatId: self.manager.chatId, conversationId: self.conversationId) { success, error in
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
if success {
YHAIChatConfiguration.defaultConfig.disableHandleMessage = true
YHAIChatConfiguration.defaultConfig.removeThinkingMessageFromChatList(&self.messages)
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
self.tableView.reloadData()
}
}
}
v.keyBoardChangeBlock = {
[weak self] isKeyBoardShow in
guard let self = self else { return }
self.scrollToBottom()
}
return v
}()
lazy var thinkingMessage: YHAIChatMessage = {
let msg = YHAIChatMessage.createThinkingMesssage()
return msg
}()
override func viewDidLoad() {
super.viewDidLoad()
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
view.backgroundColor = .clear
IQKeyboardManager.shared.enable = false
let historyMsgs = YHAIChatDataBaseManager.shared.readHistoryUIMessages()
messages.append(contentsOf: historyMsgs)
gk_navTitle = "AI对话"
self.view.addSubview(self.tableView)
self.view.addSubview(self.bottomInputView)
tableView.snp.makeConstraints { make in
make.left.right.equalTo(0)
make.top.equalTo(0)
make.bottom.equalTo(bottomInputView.snp.top).offset(-10)
}
bottomInputView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
}
YHHUD.show(.progress(message: "加载中..."))
self.manager.getMainChatConversationId {
sesseionId in
YHHUD.hide()
self.conversationId = sesseionId
self.getHistoryMessages(false)
}
}
func scrollToBottom() {
self.tableView.reloadData {
if self.messages.count > 0 {
let indexPath = IndexPath(row: self.messages.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
}
func sendMessage(_ text: String) {
self.manager.getMainChatConversationId {
sesseionId in
self.conversationId = sesseionId
YHAIChatConfiguration.defaultConfig.removeThinkingMessageFromChatList(&self.messages)
let question = YHAIChatMessage.createQuestionMessage(text)
self.messages.append(question)
self.messages.append(self.thinkingMessage)
self.scrollToBottom()
self.bottomInputView.status = .loading
YHAIChatConfiguration.defaultConfig.disableHandleMessage = false
self.manager.requestAI(botId: self.robotId, conversationId: self.conversationId, question:text) {
[weak self] res, done in
guard let self = self else { return }
YHAIChatConfiguration.defaultConfig.handleReceiveMessage(res, done, &messages)
if done {
print("RESPONSE-DONE")
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
}
self.scrollToBottom()
}
}
}
func getHistoryMessages(_ isLoading: Bool) {
if isLoading {
YHHUD.show(.progress(message: "加载中..."))
}
viewModel.getHistoryChatMessages(botId: robotId, conversationId: conversationId, messageId: historyLastMessageId) {
[weak self] success, error in
YHHUD.hide()
guard let self = self else { return }
self.historyLastMessageId = self.viewModel.lastHistroyMsgId
self.tableView.es.stopPullToRefresh()
let results = self.viewModel.historyMessages.map {
return $0.convertToChatMessage()
}
messages.append(contentsOf: results)
self.tableView.reloadData()
}
}
func uploadEvaluationMessage(_ msg: YHAIChatMessage, callback:((Bool)->())? = nil) {
viewModel.createMessage(conversationId: conversationId, role: "assistant", msg: msg) {
[weak self] success, error in
guard let self = self else { return }
callback?(success)
}
}
}
extension YHAIMainChatViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if 0 <= indexPath.row, indexPath.row < messages.count {
let msg = messages[indexPath.row]
let msgType = msg.getType()
if msg.isTextMessage() {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAITextMessageCell.cellReuseIdentifier, for: indexPath) as! YHAITextMessageCell
cell.message = msg
cell.messageClick = {
[weak self] text in
guard let self = self else { return }
self.sendMessage(text)
}
return cell
} else if msgType == .thinking {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAIThinkingMessageCell.cellReuseIdentifier, for: indexPath) as! YHAIThinkingMessageCell
return cell
} else if msgType == .productList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHProductListMessageCell.cellReuseIdentifier, for: indexPath) as! YHProductListMessageCell
if let listModel = msg.body.cardsInfo {
cell.listModel = listModel
}
return cell
} else if msgType == .fixProductList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHFixProductListMessageCell.cellReuseIdentifier, for: indexPath) as! YHFixProductListMessageCell
if let listModel = msg.body.cardsInfo {
cell.listModel = listModel
}
return cell
} else if msgType == .cardList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHCardMessageCell.cellReuseIdentifier, for: indexPath) as! YHCardMessageCell
if let listModel = msg.body.cardsInfo {
cell.cardListModel = listModel
cell.evaluationResultCallback = {
[weak self] dict in
guard let self = self else { return }
// 生成测评结果文字 和测评结果图片 两种消息
var arr = [YHAIChatMessage]()
if let satisfy_count = dict["meet_number"] as? Int {
let text = "测评成功!优才新政策要求满足12项评核准则中的任意6项即可申请(即12分制满足6分),您当前满足\(satisfy_count)项,联系专属顾问咨询详细方案!"
let textMsg = YHAIChatMessage.createTextMesssage(text: text)
arr.append(textMsg)
self.uploadEvaluationMessage(textMsg)
}
if let img1 = dict["consultant_qr_code_with_text"] as? String {
let picMsg = YHAIChatMessage.createPictureMessage(url: img1, imgType: 1)
arr.append(picMsg)
self.uploadEvaluationMessage(picMsg)
}
if arr.count > 0 {
messages.append(contentsOf: arr)
tableView.reloadData()
}
}
}
return cell
} else if msgType == .picture {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAIPictureMessageCell.cellReuseIdentifier, for: indexPath) as! YHAIPictureMessageCell
if let imgInfo = msg.body.imageInfo {
cell.imgInfo = imgInfo
}
return cell
}
}
let defaultCell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
return defaultCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 1.0
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let view = UIView()
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 1.0
}
}
extension YHAIMainChatViewController: JXSegmentedListContainerViewListDelegate {
func listView() -> UIView {
return view
}
}
//
// YHAIRequestManager.swift
// galaxy
//
// Created by Dufet on 2024/11/25.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Alamofire
import SmartCodable
class YHAIRequestManager: NSObject {
static let sessionKey = "YINHE_SESSION_KEY"
var sessionId: String = ""
let prefix_id = "id:"
let prefix_event = "event:"
let prefix_data = "data:"
let viewModel = YHAIViewModel()
var uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
var chatId = UUID().uuidString + NSDate().timeIntervalSince1970.description
func getCommonHeaders() -> HTTPHeaders {
var requestHeader = HTTPHeaders()
requestHeader.add(name: "Accept", value: "text/event-stream")
requestHeader.add(name:"appid",value:"1")
let dateStr = String(Date().timeIntervalSince1970)
requestHeader.add(name:"timestamp",value:dateStr)
requestHeader.add(name:"app_platform",value:"iOS")
requestHeader.add(name:"app_os",value:"iOS")
let version = UIDevice.appVersion()
requestHeader.add(name:"app_version",value:version)
requestHeader.add(name:"app_channel",value:"appStore")
requestHeader.add(name:"app_phoneModel",value:UIDevice.iPhoneModelName())
requestHeader.add(name:"os_version_name",value:UIDevice.iPhoneVersion())
requestHeader.add(name:"pass",value:"")
let appkey = "958364f87222c200a72414f492bf0e26"
let signOrgiString = "appid=" + "1" + "&" + "timestamp=" + dateStr + "&" + "appkey=" + appkey
let sign = signOrgiString.md5()
print("sign = \(sign)")
requestHeader.add(name:"sign",value:sign)
requestHeader.add(name: "token", value: YHLoginManager.shared.userModel?.token ?? "-")
if !YHLoginManager.shared.deviceTokenModel.registerId.isEmpty {
requestHeader.add(name: "device-id", value: YHLoginManager.shared.deviceTokenModel.registerId)
}
return requestHeader
}
func requestAI(botId: String, conversationId: String, question: String = "", callback: ((_ msg: YHAIChatMessage?, _ done: Bool) -> Void)?) {
let url = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.agentChat
self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
// body 请求体参数
let parameters = ["botId" : botId,
"conversationId" : conversationId,
"question" : question] as! [String: Any]
print("AI QUESTION PARAM: \(parameters)")
let headers = self.getCommonHeaders()
// 发送 POST 请求
AF.streamRequest(url,
method: .post,
headers: headers,
automaticallyCancelOnStreamError: false,
requestModifier: { request in
if let httpBodyStream = self.dictionaryToHttpBodyStream(parameters) {
request.httpBodyStream = httpBodyStream
}
}).responseStreamString {
[weak self] stream in
guard let self = self else { return }
switch stream.event {
case let .stream(result):
switch result {
case let .success(string):
print(string)
self.handle(dataString: string) {
response, done in
callback?(response, done)
}
case let .failure(error):
print("\(error)")
callback?(nil, true)
}
case let .complete(completion):
print("COMPLETE")
callback?(nil, true)
if let af_error = completion.error {
if let error = af_error.underlyingError {
print("\(error)")
} else {
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
}
} else if let res = completion.response {
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
print("\(res)")
} else {
print("response done")
}
}
}
}
func stopChat(chatId: String, conversationId: String, callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
let url = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.cancelAIChat
let param = ["chatId" : chatId,
"conversationId" : conversationId] as! [String: Any]
let _ = YHNetRequest.postRequest(url: url, params: param) { [weak self] json, code in
//1. json字符串 转 对象
guard let self = self else { return }
printLog("model 是 ==> \(json)")
if json.code == 200 {
callBackBlock(true,nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callBackBlock(false,err)
}
} failBlock: { err in
callBackBlock(false,err)
}
}
func dictionaryToHttpBodyStream(_ dic: [String: Any]) -> InputStream? {
do {
// 将字典序列化为 JSON 数据
let jsonData = try JSONSerialization.data(withJSONObject: dic, options: [])
// 创建一个 InputStream
let stream = InputStream(data: jsonData)
return stream
} catch {
print("Error serializing dictionary to JSON: \(error)")
return nil
}
}
// 处理data字符串
func handle(dataString: String, completion:((_ : YHAIChatMessage, _ done: Bool) ->())?) {
let arr = dataString.components(separatedBy: "\n\n")
if arr.count <= 0 {
return
}
for text in arr {
if text.isEmpty {
continue
}
let lines = text.components(separatedBy: "\n")
if lines.count > 0 {
let receiveMessage = YHAIChatMessage()
receiveMessage.uuid = uuid
for line in lines {
if line.starts(with: prefix_id) {
if let idRange = line.range(of: prefix_id) {
let id = String(line[idRange.upperBound...])
receiveMessage.id = id
}
} else if line.starts(with: prefix_event) {
if let eventRange = line.range(of: prefix_event) {
let eventString = String(line[eventRange.upperBound...])
receiveMessage.event = eventString
}
} else if line.starts(with: prefix_data) {
if let dataRange = line.range(of: prefix_data) {
let jsonString = String(line[dataRange.upperBound...])
receiveMessage.data = jsonString
do {
if let jsonData = jsonString.data(using: .utf8) {
let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any]
let dic = (jsonDict ?? [:])
receiveMessage.dataDict = dic
if let body = YHAIMessageBody.deserialize(from: dic) {
receiveMessage.body = body
}
}
} catch {
}
}
}
if receiveMessage.body.isStart() {
chatId = receiveMessage.body.chatId
}
}
print("MESSAGE_RECEIVE:\n \(receiveMessage)")
let sessionDone = receiveMessage.body.isDone()
if sessionDone {
print("SESSION DONE")
}
if !receiveMessage.body.isStart() {
completion?(receiveMessage, sessionDone)
}
if receiveMessage.isFinishd() {
// 一段话结束需要重新生成uuid 来
self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
}
}
} // arr 结束
}
}
extension YHAIRequestManager {
func getMainChatConversationId(completion:((String)->())?) {
let sessionId = getLocalGlobalConverastionId()
if !sessionId.isEmpty {
completion?(sessionId)
return
}
self.viewModel.requestConversationId { success, error in
let sessionId = self.viewModel.sessionId
self.saveGlobalConverastionId(sessionId)
completion?(self.viewModel.sessionId)
}
}
func saveGlobalConverastionId(_ conversationId: String) {
UserDefaults.standard.set(conversationId, forKey: YHAIRequestManager.sessionKey)
UserDefaults.standard.synchronize()
}
func clearGlobalConversationId() {
UserDefaults.standard.set(nil, forKey: YHAIRequestManager.sessionKey)
UserDefaults.standard.synchronize()
}
func getLocalGlobalConverastionId() -> String {
if let sessionId = UserDefaults.standard.value(forKey: YHAIRequestManager.sessionKey) as? String, !sessionId.isEmpty {
return sessionId
}
return ""
}
}
//
// YHAIRobotChatViewController.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Alamofire
import IQKeyboardManagerSwift
import JXSegmentedView
class YHAIRobotChatViewController: YHBaseViewController {
var robotId: String = ""
var conversationId: String = ""
var messages:[YHAIChatMessage] = []
var historyLastMessageId: String = ""
let manager = YHAIRequestManager()
let viewModel = YHAIViewModel()
lazy var tableView: UITableView = {
let tableView = UITableView(frame:.zero, style:.grouped)
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
}
tableView.showsVerticalScrollIndicator = false
tableView.estimatedSectionHeaderHeight = 1.0
tableView.estimatedSectionFooterHeight = 1.0
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
YHAIChatConfiguration.defaultConfig.registerMessageGroupCells(tableView)
tableView.es.addYHPullToRefresh {
self.getHistoryMessages(false)
}
return tableView
}()
lazy var bgImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "ai_chat_bg"))
return v
}()
lazy var bottomInputView: YHAITextInputView = {
let v = YHAITextInputView(frame: .zero)
v.sendBlock = {
[weak self] text in
guard let self = self else { return }
self.sendMessage(text)
}
v.stopSendBlock = {
[weak self] in
guard let self = self else { return }
self.manager.stopChat(chatId: self.manager.chatId, conversationId: self.conversationId) { success, error in
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
if success {
YHAIChatConfiguration.defaultConfig.disableHandleMessage = true
YHAIChatConfiguration.defaultConfig.removeThinkingMessageFromChatList(&self.messages)
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
self.tableView.reloadData()
}
}
}
v.keyBoardChangeBlock = {
[weak self] isKeyBoardShow in
guard let self = self else { return }
self.scrollToBottom()
}
return v
}()
lazy var cleanBtn: UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "msg_clean"), for: .normal)
btn.YH_clickEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
btn.addTarget(self, action: #selector(didCleanButtonClicked), for: .touchUpInside)
return btn
}()
lazy var thinkingMessage: YHAIChatMessage = {
let msg = YHAIChatMessage.createThinkingMesssage()
return msg
}()
override func viewDidLoad() {
super.viewDidLoad()
gk_navBarAlpha = 0
IQKeyboardManager.shared.enable = false
view.backgroundColor = .clear
view.addSubview(bgImgView)
gk_navTitle = "新港生活规划师"
gk_navTitleColor = .mainTextColor
gk_navigationBar.addSubview(cleanBtn)
self.view.addSubview(self.tableView)
self.view.addSubview(self.bottomInputView)
self.view.addSubview(self.bgImgView)
self.view.insertSubview(bgImgView, belowSubview: gk_navigationBar)
cleanBtn.snp.makeConstraints { make in
make.width.height.equalTo(24)
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-20)
}
bgImgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
tableView.snp.makeConstraints { make in
make.left.right.equalTo(0)
make.top.equalTo(k_Height_NavigationtBarAndStatuBar)
make.bottom.equalTo(bottomInputView.snp.top).offset(-10)
}
bottomInputView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
}
getHistoryMessages(true)
}
func scrollToBottom() {
self.tableView.reloadData {
if self.messages.count > 0 {
let indexPath = IndexPath(row: self.messages.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
}
func sendMessage(_ text: String) {
YHAIChatConfiguration.defaultConfig.removeThinkingMessageFromChatList(&messages)
let question = YHAIChatMessage.createQuestionMessage(text)
messages.append(question)
messages.append(thinkingMessage)
self.scrollToBottom()
self.bottomInputView.status = .loading
YHAIChatConfiguration.defaultConfig.disableHandleMessage = false
self.manager.requestAI(botId: self.robotId, conversationId: self.conversationId, question:text) {
[weak self] res, done in
guard let self = self else { return }
YHAIChatConfiguration.defaultConfig.handleReceiveMessage(res, done, &messages)
if done {
print("RESPONSE-DONE")
self.bottomInputView.status = self.bottomInputView.textView.text.isEmpty ? .disableSend : .enableSend
}
self.scrollToBottom()
}
}
func getHistoryMessages(_ isLoading: Bool) {
if isLoading {
YHHUD.show(.progress(message: "加载中..."))
}
viewModel.getHistoryChatMessages(botId: robotId, conversationId: conversationId, messageId: historyLastMessageId) {
[weak self] success, error in
YHHUD.hide()
guard let self = self else { return }
self.historyLastMessageId = self.viewModel.lastHistroyMsgId
self.tableView.es.stopPullToRefresh()
let results = self.viewModel.historyMessages.map {
return $0.convertToChatMessage()
}
messages.append(contentsOf: results)
self.tableView.reloadData()
}
}
func uploadEvaluationMessage(_ msg: YHAIChatMessage, callback:((Bool)->())? = nil) {
viewModel.createMessage(conversationId: conversationId, role: "assistant", msg: msg) {
[weak self] success, error in
guard let self = self else { return }
callback?(success)
}
}
@objc func didCleanButtonClicked() {
self.viewModel.requestConversationId { success, error in
if success {
let sessionId = self.viewModel.sessionId
self.conversationId = sessionId
self.manager.saveGlobalConverastionId(sessionId)
self.messages.removeAll()
self.tableView.reloadData()
YHHUD.flash(message: "清除成功")
}
}
}
}
extension YHAIRobotChatViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if 0 <= indexPath.row, indexPath.row < messages.count {
let msg = messages[indexPath.row]
let msgType = msg.getType()
if msg.isTextMessage() {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAITextMessageCell.cellReuseIdentifier, for: indexPath) as! YHAITextMessageCell
cell.message = msg
cell.messageClick = {
[weak self] text in
guard let self = self else { return }
self.sendMessage(text)
}
return cell
} else if msgType == .thinking {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAIThinkingMessageCell.cellReuseIdentifier, for: indexPath) as! YHAIThinkingMessageCell
return cell
} else if msgType == .productList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHProductListMessageCell.cellReuseIdentifier, for: indexPath) as! YHProductListMessageCell
if let listModel = msg.body.cardsInfo {
cell.listModel = listModel
}
return cell
} else if msgType == .fixProductList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHFixProductListMessageCell.cellReuseIdentifier, for: indexPath) as! YHFixProductListMessageCell
if let listModel = msg.body.cardsInfo {
cell.listModel = listModel
}
return cell
} else if msgType == .cardList {
let cell = tableView.dequeueReusableCell(withIdentifier: YHCardMessageCell.cellReuseIdentifier, for: indexPath) as! YHCardMessageCell
if let listModel = msg.body.cardsInfo {
cell.cardListModel = listModel
cell.evaluationResultCallback = {
[weak self] dict in
guard let self = self else { return }
// 生成测评结果文字 和测评结果图片 两种消息
var arr = [YHAIChatMessage]()
if let satisfy_count = dict["meet_number"] as? Int {
let text = "测评成功!优才新政策要求满足12项评核准则中的任意6项即可申请(即12分制满足6分),您当前满足\(satisfy_count)项,联系专属顾问咨询详细方案!"
let textMsg = YHAIChatMessage.createTextMesssage(text: text)
arr.append(textMsg)
self.uploadEvaluationMessage(textMsg)
}
if let img1 = dict["consultant_qr_code_with_text"] as? String {
let picMsg = YHAIChatMessage.createPictureMessage(url: img1, imgType: 1)
arr.append(picMsg)
self.uploadEvaluationMessage(picMsg)
}
if arr.count > 0 {
messages.append(contentsOf: arr)
tableView.reloadData()
}
}
}
return cell
} else if msgType == .picture {
let cell = tableView.dequeueReusableCell(withIdentifier: YHAIPictureMessageCell.cellReuseIdentifier, for: indexPath) as! YHAIPictureMessageCell
if let imgInfo = msg.body.imageInfo {
cell.imgInfo = imgInfo
}
return cell
}
}
let defaultCell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
return defaultCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = YHAIChatBannerView()
let arr:[YHBannerModel] = [YHBannerModel(), YHBannerModel(), YHBannerModel()]
view.dataArr = arr
view.items = ["阿萨法吉林师范", "阿萨法阿基德拉屎就发了阿基德拉屎就发了阿基德拉屎就发了阿基德拉屎就发了阿基德拉屎就发了阿基德拉屎就发了阿基德拉屎就发了", "啊设计立卡", "啊积", "阿基德拉屎就发了", "asfasf", "阿萨法", "啊设计立卡", "啊积", "阿基德拉屎就发了"]
return view
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let view = UIView()
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 360.0
}
}
extension YHAIRobotChatViewController: JXSegmentedListContainerViewListDelegate {
func listView() -> UIView {
return view
}
}
//
// 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
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.contentInset = .zero
return collectView
}()
lazy var bottomInputView: UIView = {
let v = UIView()
let whiteView = UIView()
whiteView.backgroundColor = .white
whiteView.layer.cornerRadius = 12.0
v.addSubview(whiteView)
let label = UILabel()
label.font = .PFSC_R(ofSize: 14)
label.text = "有什么问题尽管问我"
label.textColor = .init(hex: 0xB3C8E9)
whiteView.addSubview(label)
let sendImgV = UIImageView(image: UIImage(named: "ai_chat_send_gray"))
whiteView.addSubview(sendImgV)
let btn = UIButton()
btn.addTarget(self, action: #selector(didInputButtonClicked), for: .touchUpInside)
whiteView.addSubview(btn)
whiteView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
label.snp.makeConstraints { make in
make.left.equalTo(16)
make.height.equalTo(20)
make.centerY.equalToSuperview()
}
sendImgV.snp.makeConstraints { make in
make.right.equalTo(-16)
make.width.height.equalTo(24)
make.centerY.equalToSuperview()
}
btn.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
return v
}()
@objc func didInputButtonClicked() {
NotificationCenter.default.post(name: YhConstant.YhNotification.didSwitchToAIChatNotification, object: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
IQKeyboardManager.shared.enable = 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()
make.bottom.equalTo(bottomInputView.snp.top).offset(-8)
}
bottomInputView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.height.equalTo(46)
make.bottom.equalTo(-10-k_Height_safeAreaInsetsBottom())
}
}
}
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 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: YHAIProductCell.cellReuseIdentifier, for: indexPath) as! YHAIProductCell
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]
YHHUD.show(.progress(message: "加载中..."))
self.manager.getMainChatConversationId {
sesseionId in
YHHUD.hide()
let vc = YHAIRobotChatViewController()
vc.robotId = model.botId
vc.conversationId = sesseionId
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let headerView: YHAIGreetCollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: YHAIGreetCollectionReusableView.reuseIdentifier, for: indexPath) as! YHAIGreetCollectionReusableView
headerView.updateGreetingText()
return headerView
}
return UICollectionReusableView()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection:Int) -> CGSize {
return CGSize(width: KScreenWidth, height: 177)
}
}
extension YHAIServiceListViewController: JXSegmentedListContainerViewListDelegate {
func listView() -> UIView {
return view
}
}
//
// YHAITabViewController.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
class YHAITabViewController: YHBaseViewController {
var defaltIndex: Int = 0
let viewModel = YHAIViewModel()
let arrItemTitles = ["港小宝", "对话"]
var arrItemVCs : [YHBaseViewController] = []
lazy var headerImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "ai_product_list_head"))
return v
}()
lazy var bgImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "ai_chat_bg"))
v.isHidden = true
return v
}()
lazy var segmentedView : JXSegmentedView = {
let view = JXSegmentedView(frame: CGRect(x: 0, y: k_Height_safeAreaInsetsTop(), width: KScreenWidth, height: 48))
view.backgroundColor = .clear
return view
}()
lazy var segmentedDataSource: JXSegmentedTitleDataSource = {
let dataSource = JXSegmentedTitleDataSource()
dataSource.isTitleColorGradientEnabled = true
dataSource.titles = arrItemTitles
dataSource.titleNormalFont = UIFont.PFSC_M(ofSize: 16)
dataSource.titleNormalColor = UIColor.init(hex:0x778FB4)
dataSource.titleSelectedFont = UIFont(name: "AlimamaShuHeiTi-Bold", size: 18)
dataSource.titleSelectedColor = .mainTextColor
dataSource.isItemSpacingAverageEnabled = false
dataSource.itemWidth = JXSegmentedViewAutomaticDimension
dataSource.itemSpacing = 28.0
return dataSource
}()
//分类title 所对应的VC
lazy var listContainerView: JXSegmentedListContainerView! = {
let view = JXSegmentedListContainerView(dataSource: self, type: .scrollView)
view.scrollView.isScrollEnabled = false
view.backgroundColor = .clear
return view
}()
lazy var backBtn: UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "back_icon"), for: .normal)
btn.YH_clickEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
btn.addTarget(self, action: #selector(didBackBtnClicked), for: .touchUpInside)
return btn
}()
lazy var listVC: YHAIServiceListViewController = {
let vc = YHAIServiceListViewController()
return vc
}()
lazy var mainChatVC: YHAIMainChatViewController = {
let vc = YHAIMainChatViewController()
return vc
}()
@objc func didBackBtnClicked() {
self.navigationController?.popViewController(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .init(hex:0xDEECFE)
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
createUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
requestList()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func createUI() {
IQKeyboardManager.shared.enable = false
NotificationCenter.default.addObserver(self, selector: #selector(didJumoToAIChat), name: YhConstant.YhNotification.didSwitchToAIChatNotification, object: nil)
view.addSubview(bgImgView)
view.addSubview(headerImgView)
arrItemVCs.removeAll()
for i in 0..<arrItemTitles.count {
if i == 0 { // 银河AI
arrItemVCs.append(listVC)
} else if i == 1 { // 对话
arrItemVCs.append(mainChatVC)
}
}
//segmentedViewDataSource一定要通过属性强持有!!!!!!!!!
segmentedView.dataSource = segmentedDataSource
view.addSubview(segmentedView)
segmentedView.listContainer = listContainerView
view.addSubview(listContainerView)
//分类Title
segmentedView.dataSource = segmentedDataSource
segmentedView.delegate = self
//配置指示器
let indicator = YHAITabIndicatorView()
indicator.indicatorWidth = 34
indicator.indicatorHeight = 14
indicator.indicatorCornerRadius = 0.0
indicator.verticalOffset = 5
segmentedView.indicators = [indicator]
segmentedView.defaultSelectedIndex = defaltIndex
view.addSubview(backBtn)
backBtn.snp.makeConstraints { make in
make.left.equalTo(16)
make.width.height.equalTo(21)
make.centerY.equalTo(segmentedView)
}
bgImgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
headerImgView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.height.equalTo(269)
}
let segmentHeight = 48.0
segmentedView.snp.makeConstraints { make in
make.left.equalTo(61-25)
make.right.equalToSuperview()
make.top.equalTo(k_Height_safeAreaInsetsTop())
make.height.equalTo(segmentHeight)
}
listContainerView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(k_Height_safeAreaInsetsTop() + segmentHeight)
make.bottom.equalTo(0)
}
}
func requestList() {
YHHUD.show(.progress(message: "加载中..."))
viewModel.getAIEntranceList {
[weak self] success, error in
YHHUD.hide()
guard let self = self else { return }
self.mainChatVC.robotId = self.viewModel.listModel.mainBotId
self.listVC.serviceArr.removeAll()
self.listVC.serviceArr.append(contentsOf: self.viewModel.listModel.entranceConfig)
self.listVC.collectionView.reloadData()
}
}
func jumpToItemIndex(itemIndex : Int) {
self.segmentedView.selectItemAt(index: itemIndex)
}
@objc func didJumoToAIChat() {
jumpToItemIndex(itemIndex: 1)
mainChatVC.bottomInputView.showKeyBoard()
}
}
extension YHAITabViewController: JXSegmentedViewDelegate {
func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
if segmentedView.selectedIndex == 1 { // AI对话
bgImgView.isHidden = false
headerImgView.isHidden = true
} else { // 港小宝
bgImgView.isHidden = true
headerImgView.isHidden = false
}
}
}
extension YHAITabViewController: JXSegmentedListContainerViewDataSource {
func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int {
if let titleDataSource = segmentedView.dataSource as? JXSegmentedBaseDataSource {
return titleDataSource.dataSource.count
}
return 0
}
func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate {
return arrItemVCs[index] as! JXSegmentedListContainerViewListDelegate
}
}
//
// YHAIChatDataBaseManager.swift
// galaxy
//
// Created by Dufet on 2024/12/2.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Realm
import RealmSwift
class YHAIChatDataBaseManager {
static let shared = YHAIChatDataBaseManager()
let dbName = "AI_CHAT_DB.realm"
// 如果要存储的数据模型属性发生变化,需要配置当前版本号比之前大
let dbVersion: UInt64 = 1
init() {
configDataBase()
}
private func configDataBase() {
let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
let dbPath = docPath.appending("/\(dbName)")
let config = Realm.Configuration(fileURL: URL.init(string: dbPath), inMemoryIdentifier: nil, encryptionKey: nil, readOnly: false, schemaVersion: dbVersion, migrationBlock: { (migration, oldSchemaVersion) in
}, deleteRealmIfMigrationNeeded: false, shouldCompactOnLaunch: nil, objectTypes: nil)
Realm.Configuration.defaultConfiguration = config
Realm.asyncOpen { result in
switch result {
case let .success(succeed):
print("Realm 服务器配置成功!")
break
case let .failure(error):
print("Realm 数据库配置失败:\(error.localizedDescription)")
break
}
}
}
private func getDB() -> Realm {
let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
let dbPath = docPath.appending("/\(dbName)")
/// 传入路径会自动创建数据库
let defaultRealm = try! Realm(fileURL: URL.init(string: dbPath)!)
return defaultRealm
}
func addDBMessages(_ messages: [YHAIChatDBMessage]) {
// 获取 Realm 实例
let defaultRealm = self.getDB()
// 开始写入事务
for message in messages {
let students = getDBMessageBy(uuid: message.uuid)
try! defaultRealm.write {
// 将新对象添加到 Realm 数据库
defaultRealm.add(message, update: students.count > 0 ? .modified : .all)
}
}
}
func addDBMessage(_ message: YHAIChatDBMessage) -> Void {
let defaultRealm = self.getDB()
try! defaultRealm.write {
defaultRealm.add(message)
}
print(defaultRealm.configuration.fileURL ?? "")
}
/// 获取 所保存的消息
func getDBMessages() -> Results<YHAIChatDBMessage> {
let defaultRealm = self.getDB()
return defaultRealm.objects(YHAIChatDBMessage.self)
}
func getDBMessageBy(uuid: String) -> Results<YHAIChatDBMessage> {
return self.readDBMessages("uuid = '\(uuid)'")
}
func readDBMessages(_ predicate: String) -> Results<YHAIChatDBMessage> {
let defaultRealm = self.getDB()
print(defaultRealm.configuration.fileURL ?? "")
let predicate = NSPredicate(format: predicate)
let results = defaultRealm.objects(YHAIChatDBMessage.self)
return results.filter(predicate)
}
func readHistoryUIMessages() -> [YHAIChatMessage] {
let result = YHAIChatDataBaseManager.shared.getDBMessages()
var arr = [YHAIChatMessage]()
for msg in result {
let model = msg.getMessage()
arr.append(model)
}
return arr
}
}
//
// YHAIChatDataBaseModel.swift
// galaxy
//
// Created by Dufet on 2024/12/2.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Realm
import RealmSwift
class YHAIChatDataBaseModel: NSObject {
}
class YHAIChatDBMessage: Object {
@objc var uuid: String = ""
@objc dynamic var id: String = ""
@objc dynamic var event: String = ""
@objc dynamic var data: String = ""
@objc dynamic var is_self: Bool = false
@objc dynamic var is_done: Bool = false
//重写 Object.primaryKey() 可以设置模型的主键。
//声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。
//一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。
override static func primaryKey() -> String? {
return "uuid"
}
//重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性
override static func ignoredProperties() -> [String] {
// return ["tempID"]
return []
}
//重写 Object.indexedProperties() 方法可以为数据模型中需要添加索引的属性建立索引,Realm 支持为字符串、整型、布尔值以及 Date 属性建立索引。
override static func indexedProperties() -> [String] {
// return ["name"]
return []
}
static func createMessage(_ message: YHAIChatMessage) -> YHAIChatDBMessage {
let msg = YHAIChatDBMessage()
msg.uuid = message.uuid
msg.id = message.id
msg.event = message.event
msg.data = message.data
msg.is_self = message.isSelf
msg.is_done = message.isDone
print("DB WRITE-- \(message)")
return msg
}
func getMessage() -> YHAIChatMessage {
let msg = YHAIChatMessage()
msg.uuid = self.uuid
msg.id = self.id
msg.event = self.event
msg.data = self.data
msg.isSelf = self.is_self
msg.isDone = self.is_done
print("DB READ-- \(msg)")
if let jsonData = self.data.data(using: .utf8) {
do {
let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any]
let dic = (jsonDict ?? [:])
msg.dataDict = dic
if let body = YHAIMessageBody.deserialize(from: dic) {
msg.body = body
}
} catch {
}
}
return msg
}
}
//
// 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?
required init() {
}
func convertToChatMessage() -> YHAIChatMessage {
let msg = YHAIChatMessage()
msg.uuid = 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
msg.body = body
msg.setFinished()
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() {
}
}
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 botId: String = ""
var redirectPath: String = ""
required init() {
}
}
//
// YHAIMessageModel.swift
// galaxy
//
// Created by Dufet on 2024/11/28.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import SmartCodable
class YHAIMessageModel: NSObject {
}
enum YHAIMessageType: Int {
case unknown = 0
case text = 1 // 文字消息
case cardList = 2 // 卡片列表消息
case productList = 3 // 商品列表消息
case picture = 4 // 图片消息
case fixProductList = 5 // 文章列表消息
// 自定义case
case thinking = 9527 // 思考消息
case recommendText = -9527 // 推荐文字消息
}
class YHAIChatMessage: CustomStringConvertible {
var id: String = ""
var event: String = ""
var data: String = ""
var dataDict: [String : Any] = [:]
var uuid: String = ""
var isSelf: Bool = false
var isDone: Bool = false
var body = YHAIMessageBody()
func isFinishd() -> Bool {
if event.isEmpty {
return true
}
if event == "conversation.message.completed" {
return true
}
return false
}
func setFinished() {
event = "conversation.message.completed"
}
func isTextMessage() -> Bool {
let type = self.getType()
return type == .text || type == .recommendText
}
func isNeedSpiceMessage() -> Bool {
let type = self.getType()
return type == .text
}
static func createQuestionMessage(_ text: String) -> YHAIChatMessage {
let question = YHAIChatMessage()
question.isSelf = true
let body = YHAIMessageBody()
body.contentType = 1
body.contentText = text
question.setFinished()
question.body = body
question.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
question.updateBodyToData()
return question
}
static func createThinkingMesssage() -> YHAIChatMessage {
let message = YHAIChatMessage()
message.isSelf = false
let body = YHAIMessageBody()
body.contentType = YHAIMessageType.thinking.rawValue
message.setFinished()
message.body = body
message.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
message.updateBodyToData()
return message
}
static func createTextMesssage(text: String) -> YHAIChatMessage {
let message = YHAIChatMessage()
message.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
message.isSelf = false
let body = YHAIMessageBody()
body.contentType = YHAIMessageType.text.rawValue
body.contentText = text
message.setFinished()
message.body = body
message.updateBodyToData()
return message
}
static func createPictureMessage(url: String, imgType: Int) -> YHAIChatMessage {
let message = YHAIChatMessage()
message.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
message.isSelf = false
let body = YHAIMessageBody()
message.setFinished()
body.contentType = YHAIMessageType.picture.rawValue
let imgInfo = YHAIImageInfo()
imgInfo.imageUrl = url
imgInfo.imageType = imgType
body.imageInfo = imgInfo
message.body = body
message.updateBodyToData()
return message
}
func updateBodyToData() {
dataDict = body.toDictionary() ?? [:]
data = self.dicToJSONString(dict: dataDict)
}
func updateDataToBody() {
}
func dicToJSONString(dict: [String: Any]) -> String {
if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) {
return String(data: jsonData, encoding: .utf8) ?? ""
}
return ""
}
// 获取消息类型
func getType() -> YHAIMessageType {
if let contentType = dataDict["contentType"] as? Int {
if contentType == YHAIMessageType.thinking.rawValue {
return .thinking
}
if contentType == YHAIMessageType.text.rawValue {
if let type = dataDict["type"] as? String {
if type == "follow_up" {
return .recommendText
}
}
return .text
}
if contentType == YHAIMessageType.cardList.rawValue {
return .cardList
}
if contentType == YHAIMessageType.fixProductList.rawValue {
return .fixProductList
}
if contentType == YHAIMessageType.picture.rawValue {
return .picture
}
if contentType == YHAIMessageType.productList.rawValue {
return .productList
}
}
return .unknown
}
// 获取文字消息的文字
func getText() -> String {
let msgType = getType()
if msgType == .text || msgType == .recommendText {
if let text = dataDict["contentText"] as? String, !text.isEmpty {
return text
}
}
return ""
}
var description: String {
return "uudi:\(uuid)\n id: \(id)\n event: \(event)\n data:\(data)\n \n"
}
}
class YHAIMessageBody: SmartCodable {
var contentType: Int = 0
var contentText: String = ""
var chatId: String = ""
var botId: String = ""
var status: String = ""
var type: String = ""
var cardsInfo: YHAIListinfoModel?
var imageInfo: YHAIImageInfo?
func isStart() -> Bool {
if status == "start" {
return true
}
return false
}
func isDone() -> Bool {
if status == "done" {
return true
}
return false
}
required init() {
}
// var description: String {
// return "contentType:\(contentType)\n contentText: \(contentText)\n type: \(type)\n status: \(status))\n"
// }
}
class YHAIListinfoModel: SmartCodable {
var title: String = ""
var icon: String = ""
var description: String = ""
var btnText: String = ""
var list: [YHAIListItemModel] = []
var redirectMode: Int = 0
var redirectPath: String = ""
var businessType: String = ""
// 是否是测评
func isEvaluation() -> Bool {
return businessType == "evaluation"
}
required init() {
}
}
class YHAIListItemModel: SmartCodable {
var title: String = ""
var cover: String = ""
var description: String = ""
var redirectMode: Int = 0
var redirectPath: String = ""
var tags: [YHProductTag] = []
var original_price: Int = 0
var discount_price: Int = 0
required init() {
}
}
class YHProductTag: SmartCodable {
var text: String = ""
var color: String = ""
required init() {
}
}
class YHAIImageInfo: SmartCodable {
var imageType: Int = 0
var imageUrl: String = ""
required init() {
}
}
//
// YHAIViewModel.swift
// galaxy
//
// Created by Dufet on 2024/11/27.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIViewModel: NSObject {
var listModel: YHAIListModel = YHAIListModel()
var sessionId: String = ""
var historyMessages: [YHAIHistoryMessage] = []
var lastHistroyMsgId: String = ""
func getAIEntranceList(callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.aiProductList
let _ = YHNetRequest.getRequest(url: strUrl) { [weak self] json, code in
//1. json字符串 转 对象
guard let self = self else { return }
printLog("model 是 ==> \(json)")
if json.code == 200 {
guard let dic = json.data?.peel as? [String : Any], let resultModel = YHAIListModel.deserialize(from: dic) else {
let err = YHErrorModel(errorCode: YHErrorCode.dictParseError.rawValue, errorMsg: YHErrorCode.dictParseError.description())
callBackBlock(false,err)
return
}
self.listModel = resultModel
callBackBlock(true,nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callBackBlock(false,err)
}
} failBlock: { err in
callBackBlock(false,err)
}
}
func requestConversationId(callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.getAIChatSessionId
let _ = YHNetRequest.getRequest(url: strUrl) { [weak self] json, code in
//1. json字符串 转 对象
guard let self = self else { return }
printLog("model 是 ==> \(json)")
if json.code == 200 {
guard let dic = json.data?.peel as? [String : Any], let sessionId = dic["conversationId"] as? String else {
let err = YHErrorModel(errorCode: YHErrorCode.dictParseError.rawValue, errorMsg: YHErrorCode.dictParseError.description())
callBackBlock(false, err)
return
}
self.sessionId = sessionId
callBackBlock(true,nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callBackBlock(false,err)
}
} failBlock: { err in
callBackBlock(false,err)
}
}
func getHistoryChatMessages(botId: String, conversationId: String, messageId: String, callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.chatHistory
let params:[String : Any] = [
"botId" : botId,
"conversationId" : conversationId,
"messageId" : messageId
]
let _ = YHNetRequest.getRequest(url: strUrl, params:params) { [weak self] json, code in
//1. json字符串 转 对象
guard let self = self else { return }
printLog("model 是 ==> \(json)")
if json.code == 200 {
guard let dic = json.data?.peel as? [Any], let arr = [YHAIHistoryMessage].deserialize(from: dic) else {
let err = YHErrorModel(errorCode: YHErrorCode.dictParseError.rawValue, errorMsg: YHErrorCode.dictParseError.description())
callBackBlock(false, err)
return
}
self.historyMessages = arr.reversed()
if let lastMsg = arr.last {
self.lastHistroyMsgId = lastMsg.messageId
}
callBackBlock(true,nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callBackBlock(false,err)
}
} failBlock: { err in
callBackBlock(false,err)
}
}
func createMessage(conversationId: String, role: String, msg: YHAIChatMessage, callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
guard let msgDict = msg.body.toDictionary() else {
return
}
let content = self.dicToJSONString(dict: msgDict)
let params:[String : Any] = ["conversationId" : conversationId,
"contentType" : "\(msg.body.contentType)",
"role" : role,
"content" : content]
printLog("CREATE_MSG:\n \(params)")
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.createMessage
let _ = YHNetRequest.postRequest(url: strUrl, params: params) {
[weak self] json, code in
//1. json字符串 转 对象
guard let self = self else { return }
printLog("model 是 ==> \(json)")
if json.code == 200 {
callBackBlock(true,nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callBackBlock(false,err)
}
} failBlock: { err in
callBackBlock(false,err)
}
}
func dicToJSONString(dict: [String: Any]) -> String {
if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) {
return String(data: jsonData, encoding: .utf8) ?? ""
}
return ""
}
}
//
// YHAICardItemView.swift
// galaxy
//
// Created by Dufet on 2024/12/3.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAICardItemView: UIView {
var cardModel = YHAIListItemModel() {
didSet {
cardImgView.sd_setImage(with: URL(string: cardModel.cover), placeholderImage: UIImage(named: "global_default_image"))
cardTitleLabel.text = cardModel.title
describeLabel.text = cardModel.description
}
}
lazy var lineView: UIView = {
let v = UIView()
v.backgroundColor = .init(hex: 0xE9ECF0)
return v
}()
lazy var cardImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "global_default_image"))
return v
}()
lazy var cardTitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_B(ofSize:16)
lable.numberOfLines = 0
lable.text = "卡片标题"
return lable
}()
lazy var describeLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex: 0x8993A2)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:12)
lable.numberOfLines = 0
lable.text = "卡片描述文字"
return lable
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createUI() {
self.addSubview(lineView)
self.addSubview(cardImgView)
self.addSubview(cardTitleLabel)
self.addSubview(describeLabel)
lineView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(0)
make.height.equalTo(0.5)
}
cardImgView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(lineView.snp.bottom).offset(16)
make.height.equalTo(303)
}
cardTitleLabel.snp.makeConstraints { make in
make.top.equalTo(cardImgView.snp.bottom).offset(10)
make.left.equalTo(16)
make.right.equalTo(-16)
}
describeLabel.snp.makeConstraints { make in
make.top.equalTo(cardTitleLabel.snp.bottom).offset(4)
make.left.equalTo(16)
make.right.equalTo(-16)
make.bottom.equalTo(-16)
}
}
}
//
// YHAIChatBannerCollectionCell.swift
// galaxy
//
// Created by Dufet on 2024/11/30.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIChatBannerCollectionCell: UICollectionViewCell {
static let cellReuseIdentifier = "YHAIChatBannerCollectionCell"
lazy var titleLabel: UILabel = {
var label = UILabel()
label.font = .PFSC_R(ofSize: 12)
label.textAlignment = .left
label.textColor = UIColor.mainTextColor
return label
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
private func setupUI() {
contentView.backgroundColor = .white
contentView.layer.cornerRadius = 6.0
contentView.addSubview(shadowView)
contentView.addSubview(titleLabel)
shadowView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.top.bottom.equalToSuperview()
make.left.equalToSuperview().offset(10.0)
make.right.equalToSuperview().offset(-10.0)
}
}
}
//
// YHAIChatBannerItemCell.swift
// galaxy
//
// Created by Dufet on 2024/11/30.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import FSPagerView
import VisualEffectView
class YHAIChatBannerItemCell: FSPagerViewCell {
static let cellReuseIdentifier = "YHAIChatBannerItemCell"
lazy var effectView:VisualEffectView = {
let visualEffectView = VisualEffectView()
visualEffectView.colorTint = UIColor(hex: 0xAFAFAF).withAlphaComponent(0.15)
visualEffectView.blurRadius = 16
visualEffectView.scale = 1
return visualEffectView
}()
lazy var bannerImagV: UIImageView = {
let imagV : UIImageView = UIImageView()
imagV.contentMode = .scaleAspectFill
imagV.clipsToBounds = true
imagV.image = UIImage(named: "global_default_image")
return imagV
}()
lazy var titleLabel: UILabel = {
let lable = UILabel()
lable.font = UIFont.PFSC_B(ofSize: 14)
lable.textColor = UIColor.brandMainColor
lable.text = "银河明星产品"
return lable
}()
lazy var subtitleLabel: UILabel = {
let lable = UILabel()
lable.font = UIFont.PFSC_R(ofSize: 13)
lable.textColor = UIColor.mainTextColor
lable.text = "这里是副标题"
return lable
}()
override init(frame: CGRect) {
super.init(frame: frame)
initView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func initView() {
contentView.layer.shadowColor = UIColor.clear.cgColor
contentView.layer.shadowRadius = 0
contentView.layer.shadowOpacity = 0
contentView.layer.shadowOffset = .zero
contentView.addSubview(bannerImagV)
bannerImagV.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
contentView.addSubview(effectView)
effectView.snp.makeConstraints { make in
make.bottom.left.right.equalToSuperview()
make.height.equalTo(95)
}
contentView.addSubview(subtitleLabel)
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.height.equalTo(20)
make.bottom.equalTo(-35)
}
contentView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.height.equalTo(24)
make.bottom.equalTo(subtitleLabel.snp.top)
}
}
}
//
// YHAIChatBannerView.swift
// galaxy
//
// Created by Dufet on 2024/11/30.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import FSPagerView
class YHAIChatBannerView: UIView {
static let bannerHeight = 242.0
let cellHeight: CGFloat = 33.0 // 单元格的固定高度
var items:[String] = [] {
didSet {
layout.dataSource = items
collectionView.reloadData()
}
}
var dataArr: [YHBannerModel] = [] {
didSet {
// 设置为0是先停掉自动滑动定时器
bannerView.automaticSlidingInterval = 0
self.indicatorView.indicatorItems = self.dataArr.count
bannerView.reloadData()
// 指定指示器为第一个
self.indicatorView.curIndicatorIndex = 0
// 指定显示图片为第一个
bannerView.selectItem(at: 0, animated: false)
// 开启定时器开始滚动
bannerView.automaticSlidingInterval = bannerSildingInterval
bannerView.removesInfiniteLoopForSingleItem = true
bannerView.alwaysBounceHorizontal = true
}
}
private lazy var bannerView: FSPagerView = {
let view = FSPagerView()
view.delegate = self
view.dataSource = self
view.bounces = false
view.isInfinite = true
view.automaticSlidingInterval = bannerSildingInterval
view.register(YHAIChatBannerItemCell.self, forCellWithReuseIdentifier: YHAIChatBannerItemCell.cellReuseIdentifier)
view.itemSize = CGSizeMake(KScreenWidth-40.0, YHAIChatBannerView.bannerHeight)//FSPagerView.automaticSize
return view
}()
lazy var indicatorView : YHHomeBannerIndicatorView = {
let view = YHHomeBannerIndicatorView()
return view
}()
lazy var layout: YHAIChatCustomFlowLayout = {
let layout = YHAIChatCustomFlowLayout()
layout.scrollDirection = .horizontal
layout.dataSource = []
return layout
}()
lazy var collectionView: UICollectionView = {
let collectView = UICollectionView(frame:.zero, collectionViewLayout: layout)
collectView.delegate = self
collectView.dataSource = self
collectView.backgroundColor = .clear
collectView.showsHorizontalScrollIndicator = false
collectView.showsVerticalScrollIndicator = false
// 注册自定义单元格
collectView.register(YHAIChatBannerCollectionCell.self, forCellWithReuseIdentifier: YHAIChatBannerCollectionCell.cellReuseIdentifier)
return collectView
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func createUI() {
addSubview(bannerView)
bannerView.snp.makeConstraints { make in
make.top.equalTo(10)
make.left.equalTo(20)
make.right.equalTo(-20)
make.height.equalTo(YHAIChatBannerView.bannerHeight)
}
bannerView.addSubview(indicatorView)
indicatorView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(2)
make.bottom.equalTo(-14)
}
bannerView.reloadData()
addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.height.equalTo(33.0*2+10.0 + 10.0*2.0)
make.top.equalTo(bannerView.snp.bottom).offset(6)
make.bottom.equalTo(-6)
}
}
// 计算文字宽度大小
func getwith(font: UIFont, height: CGFloat, string: String) -> CGSize {
let size = CGSize.init(width: CGFloat(MAXFLOAT), height: height)
let dic = [NSAttributedString.Key.font: font] // swift 4.2
let strSize = string.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: dic, context:nil).size
return CGSizeMake(ceil(strSize.width), strSize.height)
}
}
extension YHAIChatBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
public func numberOfItems(in pagerView: FSPagerView) -> Int {
return self.dataArr.count
}
public func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
let cell = pagerView.dequeueReusableCell(withReuseIdentifier: YHAIChatBannerItemCell.cellReuseIdentifier, at: index) as! YHAIChatBannerItemCell
if index < dataArr.count {
}
return cell
}
// MARK: - FSPagerView Delegate
func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int) {
pagerView.deselectItem(at: index, animated: true)
pagerView.scrollToItem(at: index, animated: true)
if index >= dataArr.count {
return
}
}
func pagerViewWillEndDragging(_ pagerView: FSPagerView, targetIndex: Int) {
self.indicatorView.curIndicatorIndex = targetIndex
}
func pagerViewDidEndScrollAnimation(_ pagerView: FSPagerView) {
self.indicatorView.curIndicatorIndex = pagerView.currentIndex
}
}
extension YHAIChatBannerView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
// 返回单元格数量
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
// 返回每个单元格的大小
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return layout.getSize(index: indexPath.item)
}
// 返回自定义单元格
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: YHAIChatBannerCollectionCell.cellReuseIdentifier, for: indexPath) as! YHAIChatBannerCollectionCell
if 0 <= indexPath.item && indexPath.item < items.count {
cell.titleLabel.text = items[indexPath.item]
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if 0 <= indexPath.item && indexPath.item < items.count {
let text = items[indexPath.item]
}
}
}
//
// YHAIChatCustomFlowLayout.swift
// galaxy
//
// Created by Dufet on 2024/11/30.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIChatCustomFlowLayout: UICollectionViewFlowLayout {
let cellHeight = 33.0
let verticalGap = 10.0
let horizonalGap = 10.0
var firstLineX = 0.0
var secondLineX = 0.0
let firstLineY = 10.0
let secondLineY = 10.0 + 33.0 + 10.0
var attributes: [UICollectionViewLayoutAttributes] = []
// var dataSource:[String] = [] {
// didSet {
// attributes.removeAll()
// firstLineX = 0.0
// secondLineX = 0.0
// for (index, text) in dataSource.enumerated() {
// let attribute = UICollectionViewLayoutAttributes(forCellWith: IndexPath(row: index, section: 0))
// if index % 2 == 0 { // 第一行的数据
// let size = self.getSize(index: index)
// attribute.frame = CGRectMake(firstLineX, verticalGap, size.width, size.height)
// firstLineX = firstLineX + attribute.frame.width + horizonalGap
//
// } else { // 第二行的数据
// let size = self.getSize(index: index)
// attribute.frame = CGRectMake(secondLineX, verticalGap+cellHeight+verticalGap, size.width, size.height)
// secondLineX = secondLineX + attribute.frame.width + horizonalGap
// }
// attributes.append(attribute)
// }
// collectionView?.reloadData()
// }
// }
var dataSource:[String] = [] {
didSet {
attributes.removeAll()
firstLineX = 0.0
secondLineX = 0.0
for (index, text) in dataSource.enumerated() {
let attribute = UICollectionViewLayoutAttributes(forCellWith: IndexPath(row: index, section: 0))
let size = self.getSize(index: index)
if firstLineX <= secondLineX {
attribute.frame = CGRectMake(firstLineX, firstLineY, size.width, size.height)
firstLineX = firstLineX + attribute.frame.width + horizonalGap
} else {
attribute.frame = CGRectMake(secondLineX, secondLineY, size.width, size.height)
secondLineX = secondLineX + attribute.frame.width + horizonalGap
}
attributes.append(attribute)
}
collectionView?.reloadData()
}
}
override func prepare() {
super.prepare()
}
override func invalidateLayout() {
super.invalidateLayout()
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
if 0 <= indexPath.item, indexPath.item < attributes.count {
return attributes[indexPath.item]
}
return nil
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributes
}
override var collectionViewContentSize: CGSize {
guard let _ = collectionView else { return .zero }
let width = max(firstLineX, secondLineX)
let size = CGSize(width: width, height: cellHeight*2.0 + verticalGap)
return size
}
func getSize(index:Int) -> CGSize {
if 0 <= index, index < dataSource.count {
let size = self.getwith(font: UIFont.PFSC_R(ofSize: 12), height: cellHeight, string: dataSource[index])
let gap = 10.0
let width = size.width + gap*2.0
return CGSize(width: width, height: cellHeight)
}
return .zero
}
// 计算文字宽度大小
func getwith(font: UIFont, height: CGFloat, string: String) -> CGSize {
let size = CGSize.init(width: CGFloat(MAXFLOAT), height: height)
let dic = [NSAttributedString.Key.font: font] // swift 4.2
let strSize = string.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: dic, context:nil).size
return CGSizeMake(ceil(strSize.width), strSize.height)
}
}
//
// YHAIChatInputShadowView.swift
// galaxy
//
// Created by Dufet on 2024/12/2.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import UIKit
class YHAIChatInputShadowView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupShadow()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupShadow()
}
private func setupShadow() {
let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 12)
layer.shadowPath = shadowPath.cgPath
layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.12).cgColor
layer.shadowOpacity = 1
layer.shadowRadius = 6
layer.shadowOffset = CGSize(width: 0, height: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
// 确保在布局更新时更新阴影路径
setupShadow()
}
}
//
// YHAIChatShadowView.swift
// galaxy
//
// Created by Dufet on 2024/11/30.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIChatShadowView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupShadow()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupShadow()
}
private func setupShadow() {
// 创建阴影路径
let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 6)
// 设置阴影属性
layer.shadowPath = shadowPath.cgPath
layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.06).cgColor
layer.shadowOpacity = 1
layer.shadowRadius = 20
layer.shadowOffset = CGSize(width: 0, height: 4)
}
override func layoutSubviews() {
super.layoutSubviews()
// 确保在布局更新时更新阴影路径
setupShadow()
}
}
//
// YHAIEvaluationAlertWebView.swift
// galaxy
//
// Created by Dufet on 2024/12/3.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIEvaluationAlertWebView: UIView {
var url: String = ""
static func alertView(url: String) -> YHAIEvaluationAlertWebView {
let v = YHAIEvaluationAlertWebView()
return v
}
lazy var blackMaskView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hex: 0x0F1214, alpha: 0.5)
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss))
view.addGestureRecognizer(tap)
return view
}()
lazy var bottomView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.addSubview(leftBtn)
view.addSubview(rightBtn)
leftBtn.snp.makeConstraints { make in
make.top.equalTo(8)
make.left.equalTo(16)
make.width.equalTo(rightBtn)
make.right.equalTo(rightBtn.snp.left).offset(-10)
make.height.equalTo(46)
}
rightBtn.snp.makeConstraints { make in
make.top.equalTo(8)
make.right.equalTo(-16)
make.height.equalTo(46)
}
return view
}()
lazy var rightBtn: UIButton = {
let btn = UIButton()
btn.backgroundColor = .brandMainColor
btn.setTitle("重新选择提升目标", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = UIFont.PFSC_M(ofSize: 16)
btn.addTarget(self, action: #selector(didRightBtnClicked), for: .touchUpInside)
btn.layer.cornerRadius = kCornerRadius3
return btn
}()
lazy var leftBtn: UIButton = {
let btn = UIButton()
btn.backgroundColor = .init(hex: 0xF5F6F8)
btn.setTitle("返回", for: .normal)
btn.setTitleColor(.mainTextColor, for: .normal)
btn.titleLabel?.font = UIFont.PFSC_M(ofSize: 16)
btn.addTarget(self, action: #selector(didLeftBtnClicked), for: .touchUpInside)
btn.layer.cornerRadius = kCornerRadius3
return btn
}()
lazy var webVC: YHH5WebViewVC = {
let vc = YHH5WebViewVC()
vc.url = ""
vc.isNeedRefreshDataFlag = true
vc.isFullScreenFlag = false
return vc
}()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
static func alertView() -> YHAppVersionForceUpdateView {
let alertView = YHAppVersionForceUpdateView(frame:UIScreen.main.bounds)
return alertView
}
func createUI() {
self.addSubview(blackMaskView)
self.addSubview(bottomView)
webVC.url = self.url
webVC.view.frame = CGRectMake(0, 100, KScreenWidth, KScreenHeight-100-98)
self.addSubview(webVC.view)
blackMaskView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
bottomView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(98)
}
webVC.view.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(100)
}
}
@objc func show() {
UIApplication.shared.yhKeyWindow()?.addSubview(self)
}
@objc func dismiss() {
DispatchQueue.main.async {
self.removeFromSuperview()
}
}
@objc func didLeftBtnClicked() {
dismiss()
}
@objc func didRightBtnClicked() {
dismiss()
YHMyNewSchemeViewController.shared.goToSchemePage()
}
}
//
// YHAIGreetCollectionReusableView.swift
// galaxy
//
// Created by Dufet on 2024/11/27.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIGreetCollectionReusableView: UICollectionReusableView {
static let reuseIdentifier: String = "YHAIGreetCollectionReusableView"
let horizonalGap = 16.0
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "ai_gangXiaoBao_logo"))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont(name: "AlimamaShuHeiTi-Bold", size: 30)
lable.text = "Hi, 早上好!"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex:0x6D788A)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.numberOfLines = 0
lable.text = "我是银河AI助手港小宝,可以为您提供申请进度查询和赴港攻略,有什么问题尽管问我哟~"
return lable
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateGreetingText() {
titleLabel.text = greetingBasedOnTime()
}
func createUI() {
self.addSubview(iconImgView)
self.addSubview(titleLabel)
self.addSubview(subtitleLabel)
iconImgView.snp.makeConstraints { make in
make.right.equalTo(-20+horizonalGap)
make.top.equalTo(4)
make.width.equalTo(120)
make.height.equalTo(94)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(24-horizonalGap)
make.bottom.equalTo(iconImgView.snp.bottom).offset(-15)
make.height.equalTo(42)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(24-horizonalGap)
make.right.equalTo(-24+horizonalGap)
make.top.equalTo(titleLabel.snp.bottom).offset(8)
}
}
func greetingBasedOnTime() -> String {
let currentDate = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: currentDate)
let minute = calendar.component(.minute, from: currentDate)
var result = "Hi,"
switch (hour, minute) {
case (5..<8, _):
result += "早上好"
case (8, 0..<30):
result += "早上好"
case (8, 30..<60):
result += "上午好"
case (8..<11, _):
result += "上午好"
case (11..<14, _):
result += "中午好"
case (14..<18, _):
result += "下午好"
case (18..<24, _):
result += "晚上好"
case (0..<5, _):
result += "晚上好"
default:
result += "晚上好" // 默认情况
}
result += "!"
return result
}
}
//
// YHAIPictureMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/12/3.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIPictureMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHAIPictureMessageCell"
var imgInfo = YHAIImageInfo() {
didSet {
imgView.sd_setImage(with: URL(string: imgInfo.imageUrl), placeholderImage: UIImage(named: "global_default_image"), options: [], completed: { (image, error, cacheType, url) in
let size = self.getShowSize(image: image!)
self.imgView.snp.updateConstraints { make in
make.width.equalTo(size.width)
make.height.equalTo(size.height)
}
self.setNeedsLayout()
})
}
}
func getShowSize(image: UIImage) -> CGSize {
var imgW = 220.0
var imgH = 220.0
var ratio = 1.0
if image.size.width > 0, image.size.height > 0 {
ratio = image.size.width/image.size.height
}
imgH = imgW/ratio
// if imgH > 476 {
// imgH = 476
// imgW = imgH*ratio
//
// } else {
// imgW = 220
// imgH = imgW/ratio
// }
return CGSizeMake(imgW, imgH)
}
lazy var imgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "global_default_image"))
return v
}()
lazy var whiteContentView: UIView = {
let v = UIView()
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
let tap = UITapGestureRecognizer(target: self, action: #selector(didMessageClicked))
v.addGestureRecognizer(tap)
return v
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
lazy var rightAngleView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.isHidden = true
return v
}()
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(rightAngleView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(imgView)
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.top.equalTo(20)
make.bottom.equalTo(0)
}
imgView.snp.makeConstraints { make in
make.width.equalTo(220)
make.height.equalTo(220)
make.edges.equalToSuperview()
}
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
rightAngleView.snp.makeConstraints { make in
make.top.left.equalTo(whiteContentView)
make.width.height.equalTo(15)
}
}
@objc func didMessageClicked() {
self.endEditing(true)
YHPictureReviewManager.shared.showNetWorkPicturs(curIndex: 0, arrPicturs: [imgInfo.imageUrl])
}
}
//
// YHAIProductCell.swift
// galaxy
//
// Created by Dufet on 2024/11/27.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAIProductCell: UICollectionViewCell {
static let cellReuseIdentifier = "YHAIProductCell"
var model = YHEntranceconfigModel() {
didSet {
titleLabel.text = model.title
if !model.btnText.isEmpty {
subtitleLabel.text = model.description
} else {
subtitleLabel.text = "详细了解银河产品"
}
if !model.btnText.isEmpty {
blackButton.setTitle(model.btnText, for: .normal)
} else {
blackButton.setTitle("去了解", for: .normal)
}
bgImgView.sd_setImage(with: URL(string: model.cover))
}
}
lazy var bgImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_B(ofSize:14)
lable.text = "产品智能体"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex:0x8993A2)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:12)
lable.text = "银河在售商品介绍"
return lable
}()
lazy var blackButton: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("去了解", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .PFSC_M(ofSize: 11)
btn.backgroundColor = .black
btn.addTarget(self, action: #selector(didSendButtonClicked), for: .touchUpInside)
btn.YH_clickEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
btn.layer.cornerRadius = 13.0
btn.clipsToBounds = true
return btn
}()
@objc func didSendButtonClicked() {
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
func setupUI() {
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(bgImgView)
bgImgView.addSubview(titleLabel)
bgImgView.addSubview(subtitleLabel)
bgImgView.addSubview(blackButton)
bgImgView.snp.makeConstraints { make in
make.left.equalTo(0)
make.right.equalTo(0)
make.bottom.equalTo(0)
make.top.equalTo(0)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(22)
make.right.equalTo(-22)
make.bottom.equalTo(subtitleLabel.snp.top).offset(-3)
make.height.equalTo(20)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(22)
make.right.equalTo(-22)
make.bottom.equalTo(blackButton.snp.top).offset(-12)
}
blackButton.snp.makeConstraints { make in
make.left.equalTo(22)
make.bottom.equalTo(-24)
make.height.equalTo(26)
make.width.equalTo(54)
}
}
func rotateToRight(_ isRotateRight: Bool) {
let degree = isRotateRight ? 2.0 : -2.0
let transform = CGAffineTransform(rotationAngle: CGFloat(degree * CGFloat.pi / 180)) // 2 度转换为弧度
titleLabel.transform = transform
subtitleLabel.transform = transform
blackButton.transform = transform
if model.cover.isEmpty {
bgImgView.image = UIImage(named: isRotateRight ? "ai_product_left" : "ai_product_right")
}
}
}
//
// YHAITabIndicatorView.swift
// galaxy
//
// Created by Dufet on 2024/11/28.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import JXSegmentedView
class YHAITabIndicatorView: JXSegmentedIndicatorBaseView {
lazy var bgImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: "ai_tab_indicator"))
return v
}()
open var lineStyle: JXSegmentedIndicatorLineStyle = .normal
/// lineStyle为lengthenOffset时使用,滚动时x的偏移量
open var lineScrollOffsetX: CGFloat = 10
open override func commonInit() {
super.commonInit()
self.backgroundColor = .clear
self.addSubview(bgImgView)
bgImgView.snp.makeConstraints { make in
make.width.equalTo(34)
make.height.equalTo(14)
make.centerX.equalToSuperview()
make.top.equalTo(0)
}
}
open override func refreshIndicatorState(model: JXSegmentedIndicatorSelectedParams) {
super.refreshIndicatorState(model: model)
backgroundColor = .clear
layer.cornerRadius = getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame)
let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth)
let height = getIndicatorHeight(itemFrame: model.currentSelectedItemFrame)
let x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2
var y: CGFloat = 0
switch indicatorPosition {
case .top:
y = verticalOffset
case .bottom:
y = model.currentSelectedItemFrame.size.height - height - verticalOffset
case .center:
y = (model.currentSelectedItemFrame.size.height - height)/2 + verticalOffset
}
frame = CGRect(x: x, y: y, width: width, height: height)
}
open override func contentScrollViewDidScroll(model: JXSegmentedIndicatorTransitionParams) {
super.contentScrollViewDidScroll(model: model)
guard canHandleTransition(model: model) else {
return
}
let rightItemFrame = model.rightItemFrame
let leftItemFrame = model.leftItemFrame
let percent = model.percent
var targetX: CGFloat = leftItemFrame.origin.x
var targetWidth = getIndicatorWidth(itemFrame: leftItemFrame, itemContentWidth: model.leftItemContentWidth)
let leftWidth = targetWidth
let rightWidth = getIndicatorWidth(itemFrame: rightItemFrame, itemContentWidth: model.rightItemContentWidth)
let leftX = leftItemFrame.origin.x + (leftItemFrame.size.width - leftWidth)/2
let rightX = rightItemFrame.origin.x + (rightItemFrame.size.width - rightWidth)/2
switch lineStyle {
case .normal:
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat(percent))
if indicatorWidth == JXSegmentedViewAutomaticDimension {
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: rightWidth, percent: CGFloat(percent))
}
case .lengthen:
//前50%,只增加width;后50%,移动x并减小width
let maxWidth = rightX - leftX + rightWidth
if percent <= 0.5 {
targetX = leftX
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: maxWidth, percent: CGFloat(percent*2))
}else {
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat((percent - 0.5)*2))
targetWidth = JXSegmentedViewTool.interpolate(from: maxWidth, to: rightWidth, percent: CGFloat((percent - 0.5)*2))
}
case .lengthenOffset:
//前50%,增加width,并少量移动x;后50%,少量移动x并减小width
let maxWidth = rightX - leftX + rightWidth - lineScrollOffsetX*2
if percent <= 0.5 {
targetX = JXSegmentedViewTool.interpolate(from: leftX, to: leftX + lineScrollOffsetX, percent: CGFloat(percent*2))
targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: maxWidth, percent: CGFloat(percent*2))
}else {
targetX = JXSegmentedViewTool.interpolate(from:leftX + lineScrollOffsetX, to: rightX, percent: CGFloat((percent - 0.5)*2))
targetWidth = JXSegmentedViewTool.interpolate(from: maxWidth, to: rightWidth, percent: CGFloat((percent - 0.5)*2))
}
}
self.frame.origin.x = targetX
self.frame.size.width = targetWidth
}
open override func selectItem(model: JXSegmentedIndicatorSelectedParams) {
super.selectItem(model: model)
let targetWidth = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth)
var toFrame = self.frame
toFrame.origin.x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - targetWidth)/2
toFrame.size.width = targetWidth
if canSelectedWithAnimation(model: model) {
UIView.animate(withDuration: scrollAnimationDuration, delay: 0, options: .curveEaseOut, animations: {
self.frame = toFrame
}) { (_) in
}
}else {
frame = toFrame
}
}
}
//
// YHAITextInputView.swift
// galaxy
//
// Created by Dufet on 2024/11/25.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Lottie
import IQKeyboardManagerSwift
enum YHAITextInputStatus: Int {
case enableSend = 0
case disableSend = 1
case loading = 2
}
class YHAITextInputView: UIView {
var sendBlock: ((String)->())?
var stopSendBlock: (()->())?
var keyBoardChangeBlock: ((_ isShow: Bool)->())?
var status: YHAITextInputStatus = .enableSend {
didSet {
if status == .enableSend {
sendBtn.alpha = 1.0
sendBtn.isEnabled = true
sendBtn.isHidden = false
loadingImgView.isHidden = true
} else if status == .disableSend {
sendBtn.alpha = 0.3
sendBtn.isEnabled = false
sendBtn.isHidden = false
loadingImgView.isHidden = true
} else if status == .loading {
sendBtn.isHidden = true
loadingImgView.isHidden = false
}
}
}
lazy var contentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
return v
}()
lazy var whiteView: UIView = {
let v = UIView()
return v
}()
lazy var sendBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "ai_chat_send"), for: .normal)
btn.addTarget(self, action: #selector(didSendButtonClicked), for: .touchUpInside)
btn.YH_clickEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
return btn
}()
lazy var loadingImgView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "ai_chat_input_pause")
lottieView.loopMode = .loop
lottieView.contentMode = .scaleAspectFit
lottieView.play()
lottieView.isHidden = true
let btn = UIButton(type: .custom)
btn.YH_clickEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
btn.addTarget(self, action: #selector(didStopSendBtnClicked), for: .touchUpInside)
lottieView.addSubview(btn)
btn.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
return lottieView
}()
lazy var shadowView: YHAIChatInputShadowView = {
let v = YHAIChatInputShadowView()
return v
}()
@objc func didSendButtonClicked() {
sendBlock?(textView.text)
status = .loading
textView.text = ""
textView.isScrollEnabled = false
self.endEditing(true)
}
@objc func didStopSendBtnClicked() {
stopSendBlock?()
}
lazy var textView: YHAutoTextView = {
let v = YHAutoTextView()
v.backgroundColor = .clear
v.font = .PFSC_R(ofSize: 14)
v.placeHolder = "有什么问题尽管问我"
v.textChange = {
[weak self] text in
guard let self = self else { return }
if status != .loading {
status = text.count > 0 ? .enableSend : .disableSend
}
}
return v
}()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
deinit {
self.removeNotify()
}
func addKeyBoardNotify() {
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
func removeNotify() {
NotificationCenter.default.removeObserver(self)
}
func showKeyBoard() {
self.textView.becomeFirstResponder()
}
func createUI() {
self.addSubview(whiteView)
whiteView.addSubview(shadowView)
whiteView.addSubview(contentView)
contentView.addSubview(sendBtn)
contentView.addSubview(loadingImgView)
contentView.addSubview(textView)
status = .disableSend
whiteView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
contentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.top.equalTo(10)
make.bottom.equalTo(-10-k_Height_safeAreaInsetsBottom())
make.right.equalTo(-20)
}
shadowView.snp.makeConstraints { make in
make.edges.equalTo(contentView)
}
sendBtn.snp.makeConstraints { make in
make.width.equalTo(24)
make.height.equalTo(24)
make.right.equalTo(-16)
make.bottom.equalTo(-10)
}
loadingImgView.snp.makeConstraints { make in
make.edges.equalTo(sendBtn)
}
textView.snp.makeConstraints { make in
make.left.equalTo(5)
make.top.equalTo(11-YHAutoTextView.verticalGap)
make.bottom.equalTo(-(11-YHAutoTextView.verticalGap))
make.right.equalTo(sendBtn.snp.left).offset(-5)
}
addKeyBoardNotify()
}
@objc func handleKeyboardNotification(_ notification: Notification) {
if notification.userInfo != nil {
guard let keyboardFrame = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue else {return }
let isKeyboardShow = notification.name == UIResponder.keyboardWillShowNotification
let bottomMargin = (isKeyboardShow ? -keyboardFrame.height : 0)
contentView.snp.updateConstraints { make in
make.bottom.equalTo(-10-(isKeyboardShow ? 0.0 : k_Height_safeAreaInsetsBottom()))
}
self.snp.updateConstraints { make in
make.bottom.equalTo(bottomMargin)
}
self.setNeedsLayout()
self.layoutIfNeeded()
keyBoardChangeBlock?(isKeyboardShow)
}
}
}
//
// YHAIMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/11/25.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHAITextMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHAITextMessageCell"
var messageClick:((String)->())?
var message: YHAIChatMessage = YHAIChatMessage() {
didSet {
messageLabel.text = message.body.contentText
rightAngleView.backgroundColor = message.isSelf ? .brandMainColor : .white
rightAngleView.isHidden = message.getType() != .text
if message.isSelf {
whiteContentView.backgroundColor = .brandMainColor
messageLabel.textColor = .white
whiteContentView.snp.remakeConstraints { make in
make.left.greaterThanOrEqualTo(20)
make.right.equalTo(-20)
make.top.equalTo(20)
make.bottom.equalTo(0)
}
rightAngleView.snp.remakeConstraints { make in
make.top.right.equalTo(whiteContentView)
make.width.height.equalTo(15)
}
isNeedShowCopyView = false
} else {
messageLabel.text = message.body.contentText
whiteContentView.backgroundColor = .white
messageLabel.textColor = .mainTextColor
whiteContentView.snp.remakeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.top.equalTo(20)
make.bottom.equalTo(0)
}
rightAngleView.snp.remakeConstraints { make in
make.top.left.equalTo(whiteContentView)
make.width.height.equalTo(15)
}
if message.getType() == .recommendText {
isNeedShowCopyView = false
} else {
isNeedShowCopyView = message.isDone
}
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var isNeedShowCopyView: Bool = false {
didSet {
copyContentView.isHidden = !isNeedShowCopyView
copyContentView.snp.remakeConstraints { make in
make.left.equalTo(0)
make.right.equalTo(0)
make.top.equalTo(messageLabel.snp.bottom).offset(16)
make.height.equalTo(isNeedShowCopyView ? 37.0 : 0.0)
make.bottom.equalTo(0)
}
}
}
lazy var whiteContentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
let tap = UITapGestureRecognizer(target: self, action: #selector(didMessageClicked))
v.addGestureRecognizer(tap)
return v
}()
var rightAngleView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.isHidden = true
return v
}()
lazy var messageLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.numberOfLines = 0
return lable
}()
lazy var copyContentView: UIView = {
let v = UIView()
v.clipsToBounds = true
v.isHidden = true
let bgImgV = UIImageView(image: UIImage(named: "ai_chat_copy_bg"))
v.addSubview(bgImgV)
bgImgV.snp.makeConstraints { make in
make.left.top.bottom.equalToSuperview()
make.width.equalTo(KScreenWidth-40)
}
let label = UILabel()
label.textColor = UIColor.init(hex: 0x8993A2)
label.textAlignment = .left
label.font = UIFont.PFSC_R(ofSize:12)
label.text = "以上内容由银河AI生成"
v.addSubview(label)
label.snp.makeConstraints { make in
make.left.equalTo(16)
make.centerY.equalToSuperview()
make.height.equalTo(17)
}
let copyBtn = UIButton()
copyBtn.setTitle("复制", for: .normal)
copyBtn.titleLabel?.font = .PFSC_R(ofSize: 12)
copyBtn.setTitleColor(.mainTextColor, for: .normal)
copyBtn.setImage(UIImage(named: "ai_chat_msg_copy"), for: .normal)
copyBtn.YH_clickEdgeInsets = UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15)
copyBtn.addTarget(self, action: #selector(didCopyTextButtonClicked), for: .touchUpInside)
v.addSubview(copyBtn)
copyBtn.snp.makeConstraints { make in
make.right.equalTo(0)
make.centerY.equalToSuperview()
make.height.equalTo(37)
make.width.equalTo(82)
}
copyBtn.iconInLeft(spacing: 0.0)
return v
}()
@objc func didCopyTextButtonClicked() {
let text = message.body.contentText
let pasteBoard = UIPasteboard.general
pasteBoard.string = text
YHHUD.flash(message: "复制成功")
}
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(rightAngleView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(messageLabel)
whiteContentView.addSubview(copyContentView)
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
rightAngleView.snp.makeConstraints { make in
make.top.left.equalTo(whiteContentView)
make.width.height.equalTo(15)
}
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.top.equalTo(20)
make.bottom.equalTo(0)
}
messageLabel.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(16)
}
copyContentView.snp.makeConstraints { make in
make.left.equalTo(0)
make.top.equalTo(messageLabel.snp.bottom).offset(16)
make.height.equalTo(0)
make.bottom.equalTo(0)
}
}
@objc func didMessageClicked() {
self.endEditing(true)
if message.getType() == .recommendText {
let text = message.getText()
messageClick?(text)
}
}
}
//
// YHAIThinkingMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/11/28.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import Lottie
class YHAIThinkingMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHAIThinkingMessageCell"
var whiteContentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
return v
}()
lazy var messageLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.text = "港小宝正在思考…"
return lable
}()
let loadingImgView: LottieAnimationView! = {
let lottieView = LottieAnimationView(name: "ai_chat_loading")
lottieView.loopMode = .loop
lottieView.contentMode = .scaleAspectFit
lottieView.play()
return lottieView
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
var rightAngleView: UIView = {
let v = UIView()
v.backgroundColor = .white
return v
}()
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(rightAngleView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(messageLabel)
whiteContentView.addSubview(loadingImgView)
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
rightAngleView.snp.makeConstraints { make in
make.top.left.equalTo(whiteContentView)
make.width.height.equalTo(15)
}
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.lessThanOrEqualTo(-20)
make.top.equalTo(20)
make.bottom.equalTo(-20)
}
messageLabel.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(16)
}
loadingImgView.snp.makeConstraints { make in
make.left.equalTo(messageLabel)
make.width.equalTo(26)
make.height.equalTo(18)
make.top.equalTo(messageLabel.snp.bottom).offset(6)
make.bottom.equalTo(-16)
}
}
}
//
// YHCardMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHCardMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHCardMessageCell"
var evaluationResultCallback: ((Dictionary<String, Any>)->()) = { dic in }
var cardListModel = YHAIListinfoModel() {
didSet {
iconImgView.sd_setImage(with: URL(string: cardListModel.icon))
titleLabel.text = cardListModel.title
subtitleLabel.text = cardListModel.description
bottomBtn.setTitle(cardListModel.title, for: .normal)
listView.removeSubviews()
var lastItemView:YHAICardItemView? = nil
for (index, item) in cardListModel.list.enumerated() {
let productView = YHAICardItemView()
productView.cardModel = item
listView.addSubview(productView)
productView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
if let lastItemView = lastItemView {
make.top.equalTo(lastItemView.snp.bottom)
} else {
make.top.equalTo(0)
}
if index == cardListModel.list.count-1 {
make.bottom.equalTo(0)
}
}
lastItemView = productView
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var whiteContentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
return v
}()
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_B(ofSize:16)
lable.text = "港小宝"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex: 0x8993A2)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:12)
lable.text = "为您推荐以下优才产品"
return lable
}()
lazy var listView: UIView = {
let v = UIView()
return v
}()
lazy var bottomBtn: UIButton = {
let btn = UIButton()
btn.setTitle("", for: .normal)
btn.setTitleColor(UIColor.white, for: .normal)
btn.backgroundColor = .brandMainColor
btn.titleLabel?.font = .PFSC_M(ofSize: 14)
btn.layer.cornerRadius = 6.0
btn.addTarget(self, action: #selector(didBottomButtonClicked), for: .touchUpInside)
return btn
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
@objc func didBottomButtonClicked() {
if !cardListModel.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.isFullScreenFlag = true
vc.isHideNavigationBar = true
vc.url = cardListModel.redirectPath
vc.evaluationResultCallback = {
[weak self] dict in
guard let self = self else { return }
self.evaluationResultCallback(dict)
}
UIViewController.current?.present(vc, animated: true)
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(iconImgView)
whiteContentView.addSubview(titleLabel)
whiteContentView.addSubview(subtitleLabel)
whiteContentView.addSubview(listView)
whiteContentView.addSubview(bottomBtn)
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.top.equalTo(16)
make.bottom.equalTo(0)
}
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(36)
make.top.equalTo(20)
make.left.equalTo(16)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(iconImgView)
make.left.equalTo(iconImgView.snp.right).offset(8)
make.height.equalTo(24)
make.right.equalTo(-16)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(0)
make.height.equalTo(20)
make.right.equalTo(-16)
}
listView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(subtitleLabel.snp.bottom).offset(10)
}
bottomBtn.snp.makeConstraints { make in
make.top.equalTo(listView.snp.bottom).offset(0)
make.left.equalTo(16)
make.right.equalTo(-16)
make.bottom.equalTo(-16)
make.height.equalTo(44)
}
}
}
//
// YHFixProductItemView.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import AttributedString
class YHFixProductItemView: UIView {
var productModel = YHAIListItemModel() {
didSet {
iconImgView.sd_setImage(with: URL(string: productModel.cover), placeholderImage: UIImage(named: ""))
titleLabel.text = productModel.title
subtitleLabel.text = productModel.description
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
lazy var bottomLineView: UIView = {
let v = UIView()
v.backgroundColor = .init(hex: 0xE9ECF0)
return v
}()
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.text = "高才A香港企明星(7)"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.text = "高才A香港企明星(7)"
return lable
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didClickProductItem() {
if !productModel.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.isFullScreenFlag = false
vc.url = productModel.redirectPath
UIViewController.current?.navigationController?.pushViewController(vc)
}
}
func createUI() {
let tap = UITapGestureRecognizer(target: self, action: #selector(didClickProductItem))
self.addGestureRecognizer(tap)
self.addSubview(iconImgView)
self.addSubview(titleLabel)
self.addSubview(subtitleLabel)
self.addSubview(bottomLineView)
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(70)
make.left.equalTo(16)
make.top.equalTo(20)
make.bottom.equalTo(-16)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(iconImgView.snp.right).offset(12)
make.right.equalTo(-16)
make.top.equalTo(iconImgView)
make.height.equalTo(42)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.right.equalTo(-16)
make.bottom.equalTo(iconImgView)
make.height.equalTo(17)
}
bottomLineView.snp.makeConstraints { make in
make.left.equalTo(iconImgView)
make.right.equalTo(-16)
make.height.equalTo(0.5)
make.bottom.equalTo(0)
}
}
}
//
// YHFixProductMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHFixProductListMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHFixProductMessageCell"
var listModel = YHAIListinfoModel() {
didSet {
iconImgView.sd_setImage(with: URL(string: listModel.icon))
titleLabel.text = listModel.title
subtitleLabel.text = listModel.description
listView.removeSubviews()
var lastItemView:YHFixProductItemView? = nil
for (_, item) in listModel.list.enumerated() {
let productView = YHFixProductItemView()
productView.productModel = item
listView.addSubview(productView)
productView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
if let lastItemView = lastItemView {
make.top.equalTo(lastItemView.snp.bottom)
} else {
make.top.equalTo(0)
}
}
lastItemView = productView
}
if listModel.list.count > 0 {
if let lastItemView = lastItemView {
listView.addSubview(moreBtn)
moreBtn.snp.remakeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(lastItemView.snp.bottom)
make.height.equalTo(40)
}
moreBtn.iconInRight(with: 0)
}
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var whiteContentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
return v
}()
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_B(ofSize:16)
lable.text = "港小宝"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex: 0x8993A2)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:12)
lable.text = "为您推荐以下优才产品"
return lable
}()
lazy var lineView: UIView = {
let v = UIView()
v.backgroundColor = .init(hex: 0xE9ECF0)
return v
}()
lazy var listView: UIView = {
let v = UIView()
return v
}()
lazy var moreBtn: UIButton = {
let btn = UIButton()
btn.setTitle("查看更多", for: .normal)
btn.setTitleColor(UIColor.init(hex: 0xB9C1CC), for: .normal)
btn.setImage(UIImage(named: "my_doc_right_arrow"), for: .normal)
btn.titleLabel?.font = .PFSC_R(ofSize: 12)
btn.addTarget(self, action: #selector(didMoreButtonClicked), for: .touchUpInside)
return btn
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
@objc func didMoreButtonClicked() {
if !listModel.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.isFullScreenFlag = false
vc.url = listModel.redirectPath
UIViewController.current?.navigationController?.pushViewController(vc)
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(iconImgView)
whiteContentView.addSubview(titleLabel)
whiteContentView.addSubview(subtitleLabel)
whiteContentView.addSubview(lineView)
whiteContentView.addSubview(listView)
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.top.equalTo(16)
make.bottom.equalTo(0)
}
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(36)
make.top.equalTo(20)
make.left.equalTo(16)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(iconImgView)
make.left.equalTo(iconImgView.snp.right).offset(8)
make.height.equalTo(24)
make.right.equalTo(-16)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(0)
make.height.equalTo(20)
make.right.equalTo(-16)
}
lineView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(subtitleLabel.snp.bottom).offset(10)
make.height.equalTo(0.5)
}
listView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(lineView.snp.bottom).offset(0)
make.bottom.equalTo(0)
}
}
}
//
// YHProductItemView.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
import AttributedString
class YHProductItemView: UIView {
var productModel = YHAIListItemModel() {
didSet {
iconImgView.sd_setImage(with: URL(string: productModel.cover), placeholderImage: UIImage(named: "global_default_image"))
titleLabel.text = productModel.title
let aa: ASAttributedString = .init("¥", .font(UIFont(name: "DINAlternate-Bold", size: 14)!),.foreground(UIColor.mainTextColor))
let bb: ASAttributedString = .init("\(productModel.discount_price)", .font(UIFont(name: "DINAlternate-Bold", size: 20)!),.foreground(UIColor.mainTextColor))
let cc: ASAttributedString = .init(" ", .font(UIFont(name: "DINAlternate-Bold", size: 14)!),.foreground(UIColor.init(hex: 0xB9C1CC)))
let dd: ASAttributedString = .init("¥\(productModel.original_price)", .font(UIFont(name: "DINAlternate-Bold", size: 14)!),.foreground(UIColor.init(hex: 0xB9C1CC)), .strikethrough(.single))
priceLabel.attributed.text = aa+bb+cc+dd
tagContentView.removeSubviews()
var lastTagView:YHProductTagView? = nil
for tagModel in productModel.tags {
let v = YHProductTagView()
v.tagModel = tagModel
tagContentView.addSubview(v)
v.snp.makeConstraints { make in
make.top.bottom.equalTo(0)
if let lastTagView = lastTagView {
make.left.equalTo(lastTagView.snp.right).offset(4)
} else {
make.left.equalTo(0)
}
}
lastTagView = v
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
lazy var bottomLineView: UIView = {
let v = UIView()
v.backgroundColor = .init(hex: 0xE9ECF0)
return v
}()
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:14)
lable.text = "高才A香港企明星(7)"
return lable
}()
lazy var tagContentView: UIView = {
let v = UIView()
return v
}()
lazy var priceLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0
let aa: ASAttributedString = .init("¥", .font(UIFont(name: "DINAlternate-Bold", size: 14)!),.foreground(UIColor.mainTextColor))
let bb: ASAttributedString = .init("0", .font(UIFont(name: "DINAlternate-Bold", size: 20)!),.foreground(UIColor.mainTextColor))
let cc: ASAttributedString = .init(" ¥0", .font(UIFont(name: "DINAlternate-Bold", size: 14)!),.foreground(UIColor.init(hex: 0xB9C1CC)), .strikethrough(.single))
label.attributed.text = aa+bb+cc
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didClickProductItem() {
if !productModel.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.isFullScreenFlag = false
vc.url = productModel.redirectPath
UIViewController.current?.navigationController?.pushViewController(vc)
}
}
func createUI() {
let tap = UITapGestureRecognizer(target: self, action: #selector(didClickProductItem))
self.addGestureRecognizer(tap)
self.addSubview(iconImgView)
self.addSubview(titleLabel)
self.addSubview(tagContentView)
self.addSubview(priceLabel)
self.addSubview(bottomLineView)
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(80)
make.left.equalTo(16)
make.top.equalTo(20)
make.bottom.equalTo(-20)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(iconImgView.snp.right).offset(12)
make.right.equalTo(-12)
make.top.equalTo(iconImgView)
make.height.equalTo(22)
}
tagContentView.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.right.equalTo(-12)
make.height.equalTo(16)
make.top.equalTo(titleLabel.snp.bottom).offset(4)
}
priceLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.right.equalTo(-12)
make.bottom.equalTo(iconImgView)
make.height.equalTo(20)
}
bottomLineView.snp.makeConstraints { make in
make.left.equalTo(iconImgView)
make.right.equalTo(-12)
make.height.equalTo(0.5)
make.bottom.equalTo(0)
}
}
}
class YHProductTagView: UIView {
var tagModel: YHProductTag = YHProductTag() {
didSet {
tagLabel.text = tagModel.text
if !tagModel.color.isEmpty {
self.layer.borderColor = UIColor(hexString: tagModel.color, transparency: 0.3)?.cgColor
tagLabel.textColor = UIColor(hexString: tagModel.color)
} else {
self.layer.borderColor = UIColor.mainTextColor(alpha: 0.3).cgColor
tagLabel.textColor = UIColor.mainTextColor
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
lazy var tagLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .center
lable.font = UIFont.PFSC_R(ofSize:10)
return lable
}()
override init(frame: CGRect) {
super.init(frame: frame)
createUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func createUI() {
self.layer.borderColor = UIColor.mainTextColor.cgColor
self.layer.borderWidth = 0.5
self.clipsToBounds = true
self.addSubview(tagLabel)
tagLabel.snp.makeConstraints { make in
make.top.bottom.equalToSuperview()
make.left.equalTo(5)
make.right.equalTo(-5)
}
}
}
//
// YHProductListMessageCell.swift
// galaxy
//
// Created by Dufet on 2024/11/29.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHProductListMessageCell: UITableViewCell {
static let cellReuseIdentifier = "YHProductListMessageCell"
var listModel = YHAIListinfoModel() {
didSet {
iconImgView.sd_setImage(with: URL(string: listModel.icon))
titleLabel.text = listModel.title
subtitleLabel.text = listModel.description
listView.removeSubviews()
var lastItemView:YHProductItemView? = nil
for (_, item) in listModel.list.enumerated() {
let productView = YHProductItemView()
productView.productModel = item
listView.addSubview(productView)
productView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
if let lastItemView = lastItemView {
make.top.equalTo(lastItemView.snp.bottom)
} else {
make.top.equalTo(0)
}
}
lastItemView = productView
}
if listModel.list.count > 0 {
if let lastItemView = lastItemView {
listView.addSubview(moreBtn)
moreBtn.snp.remakeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(lastItemView.snp.bottom)
make.height.equalTo(40)
}
moreBtn.iconInRight(with: 0)
}
}
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
var whiteContentView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 12.0
v.clipsToBounds = true
return v
}()
lazy var iconImgView: UIImageView = {
let v = UIImageView(image: UIImage(named: ""))
return v
}()
lazy var titleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.mainTextColor
lable.textAlignment = .left
lable.font = UIFont.PFSC_B(ofSize:16)
lable.text = "港小宝"
return lable
}()
lazy var subtitleLabel:UILabel = {
let lable = UILabel()
lable.textColor = UIColor.init(hex: 0x8993A2)
lable.textAlignment = .left
lable.font = UIFont.PFSC_R(ofSize:12)
lable.text = "为您推荐以下优才产品"
return lable
}()
lazy var lineView: UIView = {
let v = UIView()
v.backgroundColor = .init(hex: 0xE9ECF0)
return v
}()
lazy var listView: UIView = {
let v = UIView()
return v
}()
lazy var moreBtn: UIButton = {
let btn = UIButton()
btn.setTitle("查看更多", for: .normal)
btn.setTitleColor(UIColor.init(hex: 0xB9C1CC), for: .normal)
btn.setImage(UIImage(named: "my_doc_right_arrow"), for: .normal)
btn.titleLabel?.font = .PFSC_R(ofSize: 12)
btn.addTarget(self, action: #selector(didMoreButtonClicked), for: .touchUpInside)
return btn
}()
lazy var shadowView: YHAIChatShadowView = {
let v = YHAIChatShadowView()
return v
}()
@objc func didMoreButtonClicked() {
if !listModel.redirectPath.isEmpty {
let vc = YHH5WebViewVC()
vc.isFullScreenFlag = false
vc.url = listModel.redirectPath
UIViewController.current?.navigationController?.pushViewController(vc)
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
func setupUI() {
selectionStyle = .none
contentView.backgroundColor = .clear
backgroundColor = .clear
contentView.addSubview(shadowView)
contentView.addSubview(whiteContentView)
whiteContentView.addSubview(iconImgView)
whiteContentView.addSubview(titleLabel)
whiteContentView.addSubview(subtitleLabel)
whiteContentView.addSubview(lineView)
whiteContentView.addSubview(listView)
shadowView.snp.makeConstraints { make in
make.edges.equalTo(whiteContentView)
}
whiteContentView.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.top.equalTo(16)
make.bottom.equalTo(0)
}
iconImgView.snp.makeConstraints { make in
make.width.height.equalTo(36)
make.top.equalTo(20)
make.left.equalTo(16)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(iconImgView)
make.left.equalTo(iconImgView.snp.right).offset(8)
make.height.equalTo(24)
make.right.equalTo(-16)
}
subtitleLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(0)
make.height.equalTo(20)
make.right.equalTo(-16)
}
lineView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(subtitleLabel.snp.bottom).offset(10)
make.height.equalTo(0.5)
}
listView.snp.makeConstraints { make in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(lineView.snp.bottom).offset(0)
make.bottom.equalTo(0)
}
}
}
...@@ -177,29 +177,11 @@ private extension YHStartPageViewController { ...@@ -177,29 +177,11 @@ private extension YHStartPageViewController {
//1.设置主窗口 //1.设置主窗口
func setupRootVC() { func setupRootVC() {
gk_navigationBar.isHidden = false
let tabBarController = YHTabBarViewController()
// let homeVC = YHHomePageViewController()
let homeVC = YHHomeHoldViewPageViewController()
tabBarController.delegate = homeVC
let v0 = YHNavigationController(rootVC:homeVC)
let v1 = YHNavigationController(rootVC:YHServiceCenterViewController())
let v2 = YHNavigationController(rootVC:YHCommunityViewController())
let v3 = YHNavigationController(rootVC:YHMyViewController())
v0.tabBarItem = ESTabBarItem.init(YHHomeLottieAnimateContentView(),title: "首页", image: UIImage(named: "home"), selectedImage: UIImage(named: "home_1"))
v1.tabBarItem = ESTabBarItem.init(YHServiceLottieAnimateContentView(),title: "服务", image: UIImage(named: "service"), selectedImage: UIImage(named: "service_1"))
v2.tabBarItem = ESTabBarItem.init(YHCommunityLottieAnimateContentView(),title: "朋友", image: UIImage(named: "msg"), selectedImage: UIImage(named: "msg_1")) gk_navigationBar.isHidden = false
v3.tabBarItem = ESTabBarItem.init(YHMyLottieAnimateContentView(),title: "我的", image: UIImage(named: "me"), selectedImage: UIImage(named: "me_1"))
tabBarController.viewControllers = [v0,v1,v2,v3]
tabBarController.tabBar.backgroundColor = .white
let window = UIApplication.shared.yhKeyWindow() let window = UIApplication.shared.yhKeyWindow()
window?.rootViewController = tabBarController window?.rootViewController = configTabBarController()
window?.makeKeyAndVisible() window?.makeKeyAndVisible()
if YHLoginManager.shared.needJumpToMsgTabFlag { if YHLoginManager.shared.needJumpToMsgTabFlag {
......
...@@ -15,6 +15,11 @@ import Photos ...@@ -15,6 +15,11 @@ import Photos
快速测评 及 其他与H5交互的界面 快速测评 及 其他与H5交互的界面
*/ */
class YHH5WebViewVC: YHBaseViewController, WKUIDelegate, WKNavigationDelegate { class YHH5WebViewVC: YHBaseViewController, WKUIDelegate, WKNavigationDelegate {
// 测评结果回调
var evaluationResultCallback:((Dictionary<String, Any>)->())?
lazy var webview : DWKWebView = { lazy var webview : DWKWebView = {
let config = WKWebViewConfiguration() let config = WKWebViewConfiguration()
config.applicationNameForUserAgent = "YinHeApp" config.applicationNameForUserAgent = "YinHeApp"
...@@ -504,6 +509,23 @@ extension YHH5WebViewVC { ...@@ -504,6 +509,23 @@ extension YHH5WebViewVC {
// MARK: - h5实现的接口 // MARK: - h5实现的接口
extension YHH5WebViewVC { extension YHH5WebViewVC {
//25 关闭AI聊天的测评弹窗并获取测评结果
// type 1 直接关闭。 2 测评出结果关闭
// result 测评结果json 待定
func closeEvaluationGetResult(type: Int, dic:[String:Any]) {
if type == 2 {
printLog("web evaluation:\n")
printLog("\(dic)")
self.evaluationResultCallback?(dic)
self.dismiss(animated: true)
} else {
self.dismiss(animated: true)
}
}
//22、禁用全局手势返回 //22、禁用全局手势返回
func disableFullScreenGestureSyn(_ tag : String) { func disableFullScreenGestureSyn(_ tag : String) {
if tag.contains("0") { if tag.contains("0") {
......
...@@ -35,6 +35,34 @@ extension YHJsApi { ...@@ -35,6 +35,34 @@ extension YHJsApi {
} }
} }
@objc func closeEvaluationGetResult(_ dicData: String) {
DispatchQueue.main.async {
if let data = dicData.data(using: .utf8) {
do {
if let result_dict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
var myType = 1
var results:[String:Any] = [:]
if let type = result_dict["type"] as? Int {
myType = type
}
if let result = result_dict["result"] as? [String:Any] {
results = result
}
if let delegate = self.delegate as? YHH5WebViewVC {
delegate.closeEvaluationGetResult(type: myType, dic: results)
}
} else {
printLog("JSON字符串不是有效的字典格式")
}
} catch {
printLog("JSON解析错误: \(error)")
}
}
}
}
//21、使用safari WebView打开Url //21、使用safari WebView打开Url
@objc func openUrlWithSafariSyn(_ payUrl: String) { @objc func openUrlWithSafariSyn(_ payUrl: String) {
......
...@@ -66,6 +66,7 @@ extension YHLoginManager { ...@@ -66,6 +66,7 @@ extension YHLoginManager {
UserDefaults.standard.set(nil, forKey: YhConstant.KLoginedInfoKey) UserDefaults.standard.set(nil, forKey: YhConstant.KLoginedInfoKey)
UserDefaults.standard.synchronize() UserDefaults.standard.synchronize()
YHAnalytics.loginout() YHAnalytics.loginout()
YHAIRequestManager().clearGlobalConversationId()
} }
func loadLocalUserInfoData() { func loadLocalUserInfoData() {
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
// //
import UIKit import UIKit
import ESTabBarController_swift
// MARK: - 统一上传图片的最大值 // MARK: - 统一上传图片的最大值
let picMaxSize : Int = 2 * 1024 * 1024 let picMaxSize : Int = 2 * 1024 * 1024
...@@ -162,6 +164,48 @@ func goToMessagePage() { ...@@ -162,6 +164,48 @@ func goToMessagePage() {
NotificationCenter.default.post(name: YhConstant.YhNotification.goMessageVCNotifiction, object: nil) NotificationCenter.default.post(name: YhConstant.YhNotification.goMessageVCNotifiction, object: nil)
} }
func configTabBarController() -> YHTabBarViewController {
let tabBarController = YHTabBarViewController()
let homeVC = YHHomeHoldViewPageViewController()
tabBarController.delegate = homeVC
let v0 = YHNavigationController(rootVC:homeVC)
let v1 = YHNavigationController(rootVC:YHServiceCenterViewController())
let v2 = YHNavigationController(rootVC: YHAITabViewController())
let v3 = YHNavigationController(rootVC:YHCommunityViewController())
let v4 = YHNavigationController(rootVC:YHMyViewController())
// 截获AI tabbarItem 点击事件
tabBarController.shouldHijackHandler = {
tabBarController, viewController, index in
if index == 2 {
return true
}
return false
}
tabBarController.didHijackHandler = {
tabBarController, viewController, index in
if index == 2 {
let vc = YHAITabViewController()
UIViewController.current?.navigationController?.pushViewController(vc)
}
}
v0.tabBarItem = ESTabBarItem.init(YHHomeLottieAnimateContentView(),title: "首页", image: UIImage(named: "home"), selectedImage: UIImage(named: "home_1"))
v1.tabBarItem = ESTabBarItem.init(YHServiceLottieAnimateContentView(),title: "服务", image: UIImage(named: "service"), selectedImage: UIImage(named: "service_1"))
v2.tabBarItem = ESTabBarItem.init(YHAITabBarItemContentView(),title: "港小宝", image: UIImage(named: "service"), selectedImage: UIImage(named: "service_1"))
v3.tabBarItem = ESTabBarItem.init(YHCommunityLottieAnimateContentView(),title: "朋友", image: UIImage(named: "msg"), selectedImage: UIImage(named: "msg_1"))
v4.tabBarItem = ESTabBarItem.init(YHMyLottieAnimateContentView(),title: "我的", image: UIImage(named: "me"), selectedImage: UIImage(named: "me_1"))
tabBarController.viewControllers = [v0,v1,v2,v3,v4]
tabBarController.tabBar.backgroundColor = .white
return tabBarController
}
// MARK: - 常量定义 // MARK: - 常量定义
class YhConstant { class YhConstant {
...@@ -319,8 +363,8 @@ extension YhConstant { ...@@ -319,8 +363,8 @@ extension YhConstant {
public static let didMyCertificateWeChatFileUploadCallBackNotification = Notification.Name(rawValue: "com.yinhe.myCertificate.wechat.fileUpload") public static let didMyCertificateWeChatFileUploadCallBackNotification = Notification.Name(rawValue: "com.yinhe.myCertificate.wechat.fileUpload")
// 已经展示银河管家 // 已经展示银河管家
public static let didLoadYhManagerNotification = Notification.Name(rawValue: "com.yinhe.didLoadYhManager") public static let didLoadYhManagerNotification = Notification.Name(rawValue: "com.yinhe.didLoadYhManager")
public static let backToHomeNotification = Notification.Name(rawValue: "com.yinhe.backToHomeNotification") public static let backToHomeNotification = Notification.Name(rawValue: "com.yinhe.backToHomeNotification")
// 切换到AI对话tab
public static let didSwitchToAIChatNotification = Notification.Name(rawValue: "com.yinhe.switchToAIChat")
} }
} }
...@@ -681,4 +681,14 @@ class YHAllApiName { ...@@ -681,4 +681,14 @@ class YHAllApiName {
// 进入直播间--需求登录 // 进入直播间--需求登录
static let joinLiveRoom = "super-app/live/app-live-join" static let joinLiveRoom = "super-app/live/app-live-join"
} }
struct AIChat {
static let aiProductList = "super-app/ai/agent/entrance"
static let agentChat = "super-app/ai/agent/chat"
static let getAIChatSessionId = "super-app/ai/agent/conversation"
static let cancelAIChat = "super-app/ai/agent/chat-cancel"
static let chatHistory = "super-app/ai/agent/chat-details"
static let createMessage = "super-app/ai/agent/chat-create-message"
}
} }
...@@ -83,7 +83,10 @@ class YHNetRequest: NSObject { ...@@ -83,7 +83,10 @@ class YHNetRequest: NSObject {
override init() { override init() {
super.init() super.init()
headers = YHNetRequest.getCommonHeaders()
}
static func getCommonHeaders() -> HTTPHeaders {
var requestHeader = HTTPHeaders() var requestHeader = HTTPHeaders()
requestHeader.add(name:"Conatent-Type",value:"application/json") requestHeader.add(name:"Conatent-Type",value:"application/json")
...@@ -114,7 +117,7 @@ class YHNetRequest: NSObject { ...@@ -114,7 +117,7 @@ class YHNetRequest: NSObject {
if !YHLoginManager.shared.deviceTokenModel.registerId.isEmpty { if !YHLoginManager.shared.deviceTokenModel.registerId.isEmpty {
requestHeader.add(name: "device-id", value: YHLoginManager.shared.deviceTokenModel.registerId) requestHeader.add(name: "device-id", value: YHLoginManager.shared.deviceTokenModel.registerId)
} }
headers = requestHeader return requestHeader
} }
func businessCode(_ code: String) -> Self { func businessCode(_ code: String) -> Self {
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Mask group.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "背景图.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame 2033196089.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame 2033196089-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "港小宝IP(5).png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "港小宝IP(4).png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "背景图样例1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "头部背景图.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "背景图样例2.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "装饰线.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "装饰线-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "柔和渐变+拟人.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "柔和渐变+拟人@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{"v":"5.6.10","fr":60,"ip":0,"op":90,"w":72,"h":72,"nm":"对话框loading","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"front","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.274509817362,0.705882370472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"front","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":67,"s":[1]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":22,"s":[100]},{"t":90,"s":[1]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":90,"s":[-360]}],"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"back","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.921568632126,0.941176474094,0.976470589638,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"back","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"BG","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":3,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.274509817362,0.705882370472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"BG","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
{"v":"5.6.10","fr":60,"ip":0,"op":90,"w":78,"h":54,"nm":"loading","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ellipse 1879","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[9,27,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0.921568632126,0.941176474094,0.976470589638,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":30,"s":[0,0.274509817362,0.705882370472,1]},{"t":60,"s":[0.921568632126,0.941176474094,0.976470589638,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Ellipse 1879","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Ellipse 1878","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39,27,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[0.921568632126,0.941176474094,0.976470589638,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":45,"s":[0,0.274509817362,0.705882370472,1]},{"t":75,"s":[0.921568632126,0.941176474094,0.976470589638,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Ellipse 1878","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse 1877","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[69,27,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0.921568632126,0.941176474094,0.976470589638,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[0,0.274509817362,0.705882370472,1]},{"t":90,"s":[0.921568632126,0.941176474094,0.976470589638,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Ellipse 1877","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
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