RQExerciseQuestionItemViewModel.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //
  2. // RQExerciseQuestionItemViewModel.m
  3. // JSJP
  4. //
  5. // Created by 张嵘 on 2021/8/16.
  6. //
  7. #import "RQExerciseQuestionItemViewModel.h"
  8. @interface RQExerciseQuestionItemViewModel ()
  9. @property (nonatomic, readwrite, strong) RQExerciseModel *exerciseModel;
  10. @property (nonatomic, readwrite, strong) YYLabel *yyLabel;
  11. @property (nonatomic, readwrite, strong) NSString *typeString;
  12. @property (nonatomic, readwrite, strong) NSString *newString;
  13. @property (nonatomic, readwrite, strong) NSMutableAttributedString *qusetionString;
  14. @property (nonatomic, readwrite, assign) CGFloat labelHeight;
  15. @property (nonatomic, readwrite, assign) CGFloat imageHeight;
  16. @property (nonatomic, readwrite, strong) NSString *imageString;
  17. @property (nonatomic, readwrite, strong) NSString *videoString;
  18. @property (nonatomic, readwrite, strong) NSMutableAttributedString *spaceAttachment;
  19. @end
  20. @implementation RQExerciseQuestionItemViewModel
  21. - (instancetype)initWithRQExerciseModel:(RQExerciseModel *)exerciseModel {
  22. if (self = [super init]) {
  23. @weakify(self)
  24. self.exerciseModel = exerciseModel;
  25. dispatch_async(dispatch_get_main_queue(), ^{
  26. @strongify(self)
  27. self.qusetionString = [self dealQuestionStrWithRQExerciseModel:exerciseModel];
  28. self.labelHeight = [self getMessageHeightWithAttributedStr:self.qusetionString andLabel:self.yyLabel];
  29. });
  30. if (RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.media_url)) {
  31. if (RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.sinaimg)) {
  32. self.imageString = exerciseModel.ydtQuestionModel.media_url;
  33. self.videoString = @"";
  34. } else if (RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.video_url)) {
  35. self.imageString = @"";
  36. self.videoString = exerciseModel.ydtQuestionModel.media_url;
  37. } else {
  38. self.imageString = @"";
  39. self.videoString = @"";
  40. }
  41. } else {
  42. self.imageString = @"";
  43. self.videoString = @"";
  44. }
  45. if (RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.sinaimg) && RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.media_url)) {
  46. if (!RQObjectIsNil(exerciseModel.ydtQuestionModel.media_content)) {
  47. NSString *imageStr = [exerciseModel.ydtQuestionModel.media_content base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  48. UIImage *sinaImage = [UIImage sd_imageWithData:[NSData dataWithBase64EncodedString:imageStr] scale:1 firstFrameOnly:YES];
  49. exerciseModel.ydtQuestionModel.sinaImage = sinaImage;
  50. } else {
  51. NSString *media_name;
  52. if ([exerciseModel.ydtQuestionModel.media_url containsString:@"https://"]) {
  53. media_name = [exerciseModel.ydtQuestionModel.media_url componentsSeparatedByString:@"/"].lastObject;
  54. }
  55. NSData *mediaData = [RQ_YDTQuestion_Module getMediaDataWithMediaName:media_name];
  56. if (mediaData) {
  57. NSString *imageStr = [mediaData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  58. UIImage *sinaImage = [UIImage sd_imageWithData:[NSData dataWithBase64EncodedString:imageStr] scale:1 firstFrameOnly:YES];
  59. exerciseModel.ydtQuestionModel.sinaImage = sinaImage;
  60. }
  61. }
  62. } else if (RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.video_url) && RQStringIsNotEmpty(exerciseModel.ydtQuestionModel.media_url)) {
  63. NSString *media_name;
  64. if ([exerciseModel.ydtQuestionModel.video_url containsString:@"https://"]) {
  65. media_name = [exerciseModel.ydtQuestionModel.video_url componentsSeparatedByString:@"/"].lastObject;
  66. } else {
  67. media_name = exerciseModel.ydtQuestionModel.video_url;
  68. }
  69. NSURL *video_filePath_Url;
  70. if (!RQObjectIsNil(exerciseModel.ydtQuestionModel.media_content) && !RQ_COMMON_MANAGER.JSJP_Is_Online_Media_Video) {
  71. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  72. NSString *documentsDirectory = [paths objectAtIndex:0];
  73. NSString *path = [documentsDirectory stringByAppendingPathComponent:media_name];
  74. [[NSFileManager defaultManager] createFileAtPath:path contents:exerciseModel.ydtQuestionModel.media_content attributes:nil];
  75. video_filePath_Url = [NSURL fileURLWithPath:path];
  76. }
  77. exerciseModel.ydtQuestionModel.video_filePath_Url = video_filePath_Url;
  78. }
  79. if (RQStringIsNotEmpty(self.imageString)) {
  80. __block CGSize imageSize = CGSizeMake(RQ_SCREEN_WIDTH - 32.f, (RQ_SCREEN_WIDTH - 32.f) * (175.f / 345.f));
  81. if (exerciseModel.ydtQuestionModel.sinaImage) {
  82. imageSize = exerciseModel.ydtQuestionModel.sinaImage.size;
  83. } else {
  84. NSString *cacheKeyStr = [[YYWebImageManager sharedManager] cacheKeyForURL:[NSURL URLWithString:self.imageString]];
  85. UIImage *cacheImage = [[YYImageCache sharedCache] getImageForKey:cacheKeyStr];
  86. if (cacheImage) {
  87. imageSize = cacheImage.size;
  88. } else {
  89. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  90. @strongify(self)
  91. // 处理耗时操作的代码块...
  92. imageSize = [UIImage getImageSizeWithURL:self.imageString];
  93. //通知主线程刷新
  94. dispatch_async(dispatch_get_main_queue(), ^{
  95. @strongify(self)
  96. //回调或者说是通知主线程刷新,
  97. if (imageSize.width == 0 || imageSize.height == 0) {
  98. self.imageHeight = (RQ_SCREEN_WIDTH - 32.f) * (175.f / 345.f);
  99. } else {
  100. self.imageHeight = (RQ_SCREEN_WIDTH - 32.f) * (imageSize.height / imageSize.width);
  101. }
  102. });
  103. });
  104. }
  105. }
  106. if (imageSize.width == 0 || imageSize.height == 0) {
  107. self.imageHeight = (RQ_SCREEN_WIDTH - 32.f) * (175.f / 345.f);
  108. } else {
  109. self.imageHeight = (RQ_SCREEN_WIDTH - 32.f) * (imageSize.height / imageSize.width);
  110. }
  111. } else if (RQStringIsNotEmpty(self.videoString)) {
  112. self.imageHeight = (RQ_SCREEN_WIDTH - 32.f) * (175.f / 345.f);
  113. }
  114. self.rowHeight = 16.f + self.labelHeight + ((self.imageHeight == 0)? 0 : (16.f + self.imageHeight)) + 16.f;
  115. [[[RACObserve(RQ_Exercise_Module, exerciseFontSize) takeUntil:self.rac_willDeallocSignal] deliverOnMainThread] subscribeNext:^(id _Nullable x) {
  116. @strongify(self)
  117. self.qusetionString = [self dealQuestionStrWithRQExerciseModel:exerciseModel];
  118. self.labelHeight = [self getMessageHeightWithAttributedStr:self.qusetionString andLabel:self.yyLabel];
  119. }];
  120. RAC(self, rowHeight) = [[RACSignal combineLatest:@[[RACObserve(RQ_Exercise_Module, exerciseFontSize) takeUntil:self.rac_willDeallocSignal],[RACObserve(self, imageHeight) takeUntil:self.rac_willDeallocSignal],[RACObserve(self, labelHeight) takeUntil:self.rac_willDeallocSignal]] reduce:^(NSNumber *exerciseFontSize, NSNumber *imageHeight, NSNumber *labelHeight) {
  121. return @(16.f + labelHeight.floatValue + ((imageHeight.floatValue == 0)? 0 : (16.f + imageHeight.floatValue)) + 16.f);
  122. }] deliverOnMainThread] ;
  123. }
  124. return self;
  125. }
  126. - (NSString *)newString {
  127. return @"新规题";
  128. }
  129. - (NSMutableAttributedString *)dealQuestionStrWithRQExerciseModel:(RQExerciseModel *)exerciseModel {
  130. switch (exerciseModel.ydtQuestionModel.Type) {
  131. case 1:
  132. self.typeString = @"判断题";
  133. break;
  134. case 2:
  135. self.typeString = @"单选题";
  136. break;
  137. case 3:
  138. self.typeString = @"多选题";
  139. break;
  140. default:
  141. self.typeString = @"";
  142. break;
  143. }
  144. NSString *questionStr = [NSString stringWithFormat:@"%ld、%@",(long)exerciseModel.ydtQuestionModel.num + 1 ,exerciseModel.ydtQuestionModel.Question];
  145. NSMutableAttributedString *text = [NSMutableAttributedString new];
  146. NSMutableAttributedString *testText = [NSMutableAttributedString new];
  147. NSMutableAttributedString *typeAttachment = nil;
  148. QMUIButton *typeBtn = [QMUIButton buttonWithType:UIButtonTypeCustom];
  149. CGFloat btnHeight = (25.f / 17.f) * RQ_Exercise_Module.exerciseFontSize;
  150. CGFloat btnWeight = (60.f / 25.f) * btnHeight;
  151. CGFloat btnCornerRadius = btnHeight / 2.f;
  152. CGSize btnSize = CGSizeMake(btnWeight, btnHeight);
  153. typeBtn.size = btnSize;
  154. [typeBtn setTitle:self.typeString textColor:RQ_MAIN_TEXT_COLOR_WHITE Font:RQ_Exercise_Module.exerciseFontSize - 3 fotState:UIControlStateNormal];
  155. [typeBtn setBackgroundImage:[UIImage qmui_imageWithColor:RQ_MAIN_COLOR size:btnSize cornerRadiusArray:@[@(btnCornerRadius), @(btnCornerRadius), @0, @(btnCornerRadius)]] forState:UIControlStateNormal];
  156. typeAttachment = [NSMutableAttributedString yy_attachmentStringWithContent:typeBtn
  157. contentMode:UIViewContentModeCenter
  158. attachmentSize:btnSize
  159. alignToFont:[UIFont systemFontOfSize:RQ_Exercise_Module.exerciseFontSize]
  160. alignment:YYTextVerticalAlignmentCenter];
  161. [testText appendAttributedString:typeAttachment];
  162. [testText appendAttributedString:self.spaceAttachment];
  163. if ([RQ_YDTQuestion_Module isNewRuleQuestionWithQuestionId:exerciseModel.ydtQuestionModel.ID]) {
  164. NSMutableAttributedString *newAttachment = nil;
  165. QMUIButton *newBtn = [QMUIButton buttonWithType:UIButtonTypeCustom];
  166. newBtn.size = btnSize;
  167. [newBtn setTitle:@"新规题" textColor:RQ_MAIN_TEXT_COLOR_WHITE Font:RQ_Exercise_Module.exerciseFontSize - 3 fotState:UIControlStateNormal];
  168. [newBtn setBackgroundImage:[UIImage qmui_imageWithColor:RQColorFromHexString(@"#9C5FED") size:btnSize cornerRadiusArray:@[@(btnCornerRadius), @(btnCornerRadius), @(btnCornerRadius), @(btnCornerRadius)]] forState:UIControlStateNormal];
  169. newAttachment = [NSMutableAttributedString yy_attachmentStringWithContent:newBtn
  170. contentMode:UIViewContentModeCenter
  171. attachmentSize:btnSize
  172. alignToFont:[UIFont systemFontOfSize:RQ_Exercise_Module.exerciseFontSize]
  173. alignment:YYTextVerticalAlignmentCenter];
  174. [testText appendAttributedString:newAttachment];
  175. [testText appendAttributedString:self.spaceAttachment];
  176. }
  177. NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:questionStr];
  178. attrString.yy_font = [UIFont systemFontOfSize:RQ_Exercise_Module.exerciseFontSize];
  179. attrString.yy_color = RQ_MAIN_TEXT_COLOR_1;
  180. // if (RQStringIsNotEmpty(exerciseModel.titlekeyword) && exerciseModel.isShowSkillExplanation) {
  181. // [[[exerciseModel.titlekeyword componentsSeparatedByString:@"-"].rac_sequence.signal deliverOnMainThread] subscribeNext:^(NSString * _Nullable skillkeywordStr) {
  182. // NSRange range = [questionStr rangeOfString:skillkeywordStr];
  183. // [attrString yy_setColor:RQ_MAIN_TEXT_COLOR_RED range:range];
  184. // [attrString yy_setFont:[UIFont boldSystemFontOfSize:RQ_Exercise_Module.exerciseFontSize + 2] range:range];
  185. // }];
  186. // }
  187. // NSRange range = [string rangeOfString:@"《遵守实验室须知》"];
  188. // [attrString yy_setColor:[UIColor colorWithHexString:@"#19ADA9"] range:range];
  189. //
  190. // [attrString yy_setTextHighlightRange:range
  191. // color:[UIColor colorWithHexString:@"#19ADA9"]
  192. // backgroundColor:[UIColor blueColor]
  193. // tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
  194. // [_self showMessage:[NSString stringWithFormat:@"Tap: %@",[text.string substringWithRange:range]]];
  195. // }];
  196. [testText appendAttributedString: attrString];
  197. [text appendAttributedString:testText];
  198. // [text appendAttributedString:[self padding]];
  199. text.yy_lineSpacing = 8;
  200. return text;
  201. }
  202. /**
  203. * 获取lb的高度
  204. * @param mess lb.text
  205. * @param lb (YYLabel *)label
  206. * @return lb的高度
  207. */
  208. - (CGFloat)getMessageHeight:(NSString *)mess andLabel:(YYLabel *)lb {
  209. NSMutableAttributedString *introText = [[NSMutableAttributedString alloc] initWithString:mess];
  210. introText.yy_font = [UIFont boldSystemFontOfSize:RQ_Exercise_Module.exerciseFontSize];
  211. introText.yy_lineSpacing = 8;
  212. lb.attributedText = introText;
  213. CGSize introSize = CGSizeMake(RQ_SCREEN_WIDTH - (16 * 2), CGFLOAT_MAX);
  214. YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:introSize text:introText];
  215. lb.textLayout = layout;
  216. CGFloat introHeight = layout.textBoundingSize.height;
  217. return introHeight;
  218. }
  219. - (CGFloat)getMessageHeightWithAttributedStr:(NSMutableAttributedString *)attributedStr andLabel:(YYLabel *)lb {
  220. lb.attributedText = attributedStr;
  221. CGSize introSize = CGSizeMake(RQ_SCREEN_WIDTH - (16 * 2), CGFLOAT_MAX);
  222. YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:introSize text:attributedStr];
  223. lb.textLayout = layout;
  224. CGFloat introHeight = layout.textBoundingSize.height;
  225. return introHeight;
  226. }
  227. - (YYLabel *)yyLabel {
  228. if (!_yyLabel) {
  229. _yyLabel = [[YYLabel alloc] init];
  230. }
  231. return _yyLabel;
  232. }
  233. - (NSMutableAttributedString *)spaceAttachment {
  234. if (!_spaceAttachment) {
  235. UIView *spaceView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 4, 25)];
  236. _spaceAttachment = [NSMutableAttributedString yy_attachmentStringWithContent:spaceView contentMode:UIViewContentModeCenter attachmentSize:CGSizeMake(4, 25) alignToFont:[UIFont boldSystemFontOfSize:RQ_Exercise_Module.exerciseFontSize] alignment:YYTextVerticalAlignmentCenter];
  237. }
  238. return _spaceAttachment;
  239. }
  240. - (NSString *)itemClassName {
  241. return @"RQExerciseQuestionCell";
  242. }
  243. @end