فهرست منبع

机构学生个人中心显示

Steven 2 ماه پیش
والد
کامیت
160556cce8
34فایلهای تغییر یافته به همراه1047 افزوده شده و 864 حذف شده
  1. 1 1
      KulexiuForStudent/KulexiuForStudent.xcodeproj/xcshareddata/xcschemes/KulexiuForStudent.xcscheme
  2. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineToolDetail.imageset/institution_mineToolDetail@2x.png
  3. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineToolDetail.imageset/institution_mineToolDetail@3x.png
  4. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/Contents.json
  5. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/institution_mineTool_expired@2x.png
  6. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/institution_mineTool_expired@3x.png
  7. 2 2
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/Contents.json
  8. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/institution_mineTool_open@2x.png
  9. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/institution_mineTool_open@3x.png
  10. 8 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  11. 12 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  12. 122 52
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.m
  13. 60 77
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.m
  14. 63 72
      KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.m
  15. 21 0
      KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/Controller/InsititutionMineViewController.m
  16. 2 0
      KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.h
  17. 71 17
      KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.m
  18. 33 21
      KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.xib
  19. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Controller/VipCouseDetailViewController.m
  20. 1 1
      KulexiuForStudent/Podfile.lock
  21. 1 0
      KulexiuForStudent/Pods/Headers/Private/KSCloudAccompanyLibrary/AudioProcessHandle.hpp
  22. 1 0
      KulexiuForStudent/Pods/Headers/Private/KSCloudAccompanyLibrary/EvaluateManager.h
  23. 1 0
      KulexiuForStudent/Pods/Headers/Public/KSCloudAccompanyLibrary/EvaluateManager.h
  24. 5 1
      KulexiuForStudent/Pods/Local Podspecs/KSCloudAccompanyLibrary.podspec.json
  25. 1 1
      KulexiuForStudent/Pods/Manifest.lock
  26. 610 609
      KulexiuForStudent/Pods/Pods.xcodeproj/project.pbxproj
  27. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.debug.xcconfig
  28. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.dev.xcconfig
  29. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.release.xcconfig
  30. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.test.xcconfig
  31. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.debug.xcconfig
  32. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.dev.xcconfig
  33. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.release.xcconfig
  34. 1 1
      KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.test.xcconfig

+ 1 - 1
KulexiuForStudent/KulexiuForStudent.xcodeproj/xcshareddata/xcschemes/KulexiuForStudent.xcscheme

@@ -92,7 +92,7 @@
       buildConfiguration = "Debug">
    </AnalyzeAction>
    <ArchiveAction
-      buildConfiguration = "Release"
+      buildConfiguration = "TEST"
       revealArchiveInOrganizer = "YES">
    </ArchiveAction>
 </Scheme>

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineToolDetail.imageset/institution_mineToolDetail@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineToolDetail.imageset/institution_mineToolDetail@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "institution_mineTool_expired@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "institution_mineTool_expired@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/institution_mineTool_expired@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_expired.imageset/institution_mineTool_expired@3x.png


+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineToolDetail.imageset/Contents.json → KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/Contents.json

@@ -5,12 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "institution_mineToolDetail@2x.png",
+      "filename" : "institution_mineTool_open@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "institution_mineToolDetail@3x.png",
+      "filename" : "institution_mineTool_open@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/institution_mineTool_open@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Institution/Mine/institution_mineTool_open.imageset/institution_mineTool_open@3x.png


+ 8 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h

@@ -923,6 +923,14 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)userBuyAlbumInfoDetailRequest:(NSString *)get tenantAlbumId:(NSString *)tenantAlbumId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
+// userTenantAlbumRecord/lastRecord
+
+///  查询专辑记录
+/// @param get get
+/// @param success 成功
+/// @param faliure 失败
++ (void)userTenantAlbumRecordRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 /// 查询配置客服电话和手机号
 /// @param post post
 /// @param success 成功

+ 12 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m

@@ -1786,6 +1786,18 @@
     [self request:get andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// userTenantAlbumRecord/lastRecord
+
+///  查询专辑记录
+/// @param get get
+/// @param success 成功
+/// @param faliure 失败
++ (void)userTenantAlbumRecordRequest:(NSString *)get success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-student/userTenantAlbumRecord/lastRecord"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [self request:get andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 /// 查询配置客服电话和手机号
 /// @param post post
 /// @param success 成功

+ 122 - 52
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSRealtimeAnalyzer.m

@@ -22,6 +22,13 @@
 
 @property (nonatomic, assign) BOOL isCanceled;
 
+@property (nonatomic, strong) NSArray<NSValue *> *bandIndexRanges;
+
+@property (nonatomic, assign) float *windowBuffer;
+@property (nonatomic, assign) float *amplitudesBuffer;
+
+@property (nonatomic, strong) dispatch_queue_t analyzeQueue;
+
 @end
 
 @implementation KSRealtimeAnalyzer
@@ -40,15 +47,29 @@
         _spectrumBuffer = [NSMutableArray array];
         [self setupBands];
         _cachedFrequencyWeights = [self createFrequencyWeights];
+
+        _windowBuffer = (float *)calloc(_fftSize, sizeof(float));
+        _amplitudesBuffer = (float *)calloc(_fftSize / 2, sizeof(float));
+
+        vDSP_hann_window(_windowBuffer, _fftSize, vDSP_HANN_NORM);
+
+        _analyzeQueue = dispatch_queue_create("com.kulexiu.audioanalyzer", DISPATCH_QUEUE_SERIAL);
     }
     return self;
 }
 
 - (void)dealloc {
     self.isCanceled = YES;
+    
+    dispatch_sync(self.analyzeQueue, ^{});
+    
+    self.analyzeQueue = nil;
+    
     vDSP_destroy_fftsetup(_fftSetup);
     free(_realp);
     free(_imagp);
+    free(_windowBuffer);
+    free(_amplitudesBuffer);
     NSLog(@"-------KSRealtimeAnalyzer dealloc");
 }
 
@@ -64,54 +85,94 @@
     }
     
     self.bands = [bands copy];
+    
+    // 预计算频段索引范围
+    NSMutableArray *indexRanges = [NSMutableArray arrayWithCapacity:self.frequencyBands];
+    float bandWidth = 44100.0 / self.fftSize; // 假设采样率为44100
+    
+    for (NSDictionary *band in self.bands) {
+        NSInteger startIndex = round([band[@"lowerFrequency"] floatValue] / bandWidth);
+        NSInteger endIndex = MIN(round([band[@"upperFrequency"] floatValue] / bandWidth), self.fftSize / 2 - 1);
+        [indexRanges addObject:[NSValue valueWithRange:NSMakeRange(startIndex, endIndex - startIndex + 1)]];
+    }
+    self.bandIndexRanges = indexRanges;
 }
 
+// 在 analyseWithBuffer 中添加同步锁
 - (NSArray<NSArray<NSNumber *> *> *)analyseWithBuffer:(AVAudioPCMBuffer *)buffer {
     if (self.isCanceled) {
         return [NSArray array];
     }
-    self.isAnalise = YES;
-    NSArray<NSArray<NSNumber *> *> *channelsAmplitudes = [self fftWithBuffer:buffer];
-    NSArray<NSNumber *> *aWeights = self.cachedFrequencyWeights;
-    if (self.spectrumBuffer.count == 0) {
-        for (NSInteger i = 0; i < channelsAmplitudes.count; i++) {
-            [self.spectrumBuffer addObject:[self emptyArrayOfCount:self.bands.count]];
-        }
-    }
     
-    NSMutableArray<NSArray<NSNumber *> *> *result = [NSMutableArray arrayWithArray:self.spectrumBuffer];
-    // 放大倍数
-    CGFloat amplificationFactor = 40.0; // 调整为所需的放大倍数
-    dispatch_apply(channelsAmplitudes.count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
-        NSArray<NSNumber *> *amplitudes = channelsAmplitudes[index];
-        NSMutableArray<NSNumber *> *weightedAmplitudes = [NSMutableArray arrayWithCapacity:amplitudes.count];
-        
-        for (NSInteger i = 0; i < amplitudes.count; i++) {
-            weightedAmplitudes[i] = @(amplitudes[i].floatValue * aWeights[i].floatValue);
-        }
-        
-        NSMutableArray<NSNumber *> *spectrum = [NSMutableArray arrayWithCapacity:self.bands.count];
-        
-        for (NSDictionary *band in self.bands) {
-            float bandWidth = (float)buffer.format.sampleRate / self.fftSize;
-            [spectrum addObject:@([self findMaxAmplitudeForBand:band inAmplitudes:weightedAmplitudes withBandWidth:bandWidth] * amplificationFactor)];
-        }
-        
-        spectrum = [self highlightWaveform:spectrum];
-        
-        NSMutableArray<NSNumber *> *previousSpectrum = [self.spectrumBuffer[index] mutableCopy];
-        NSMutableArray<NSNumber *> *newSpectrum = [NSMutableArray arrayWithCapacity:spectrum.count];
-        
-        for (NSInteger i = 0; i < spectrum.count; i++) {
-            float smoothedValue = ([previousSpectrum[i] floatValue] * self.spectrumSmooth) + (spectrum[i].floatValue * (1 - self.spectrumSmooth));
-            newSpectrum[i] = @(smoothedValue);
+    @synchronized (self) {
+        self.isAnalise = YES;
+        @autoreleasepool {
+            NSArray<NSArray<NSNumber *> *> *channelsAmplitudes = [self fftWithBuffer:buffer];
+            NSArray<NSNumber *> *aWeights = self.cachedFrequencyWeights;
+            
+            if (self.spectrumBuffer.count == 0) {
+                for (NSInteger i = 0; i < channelsAmplitudes.count; i++) {
+                    [self.spectrumBuffer addObject:[self emptyArrayOfCount:self.bands.count]];
+                }
+            }
+            
+            NSMutableArray<NSArray<NSNumber *> *> *result = [NSMutableArray arrayWithArray:self.spectrumBuffer];
+            CGFloat amplificationFactor = 40.0;
+            
+            for (size_t index = 0; index < channelsAmplitudes.count; index++) {
+                dispatch_async(self.analyzeQueue, ^{
+                    NSArray<NSNumber *> *amplitudes = channelsAmplitudes[index];
+                    NSMutableArray<NSNumber *> *weightedAmplitudes = [NSMutableArray arrayWithCapacity:amplitudes.count];
+                    
+                    float *amplitudesBuffer = (float *)malloc(amplitudes.count * sizeof(float));
+                    float *weightsBuffer = (float *)malloc(amplitudes.count * sizeof(float));
+                    float *resultBuffer = (float *)malloc(amplitudes.count * sizeof(float));
+                    
+                    for (NSInteger i = 0; i < amplitudes.count; i++) {
+                        amplitudesBuffer[i] = amplitudes[i].floatValue;
+                        weightsBuffer[i] = aWeights[i].floatValue;
+                    }
+                    
+                    vDSP_vmul(amplitudesBuffer, 1, weightsBuffer, 1, resultBuffer, 1, (vDSP_Length)amplitudes.count);
+                    
+                    for (NSInteger i = 0; i < amplitudes.count; i++) {
+                        weightedAmplitudes[i] = @(resultBuffer[i]);
+                    }
+                    
+                    free(amplitudesBuffer);
+                    free(weightsBuffer);
+                    free(resultBuffer);
+                    
+                    NSMutableArray<NSNumber *> *spectrum = [NSMutableArray arrayWithCapacity:self.bands.count];
+                    
+                    for (NSDictionary *band in self.bands) {
+                        float bandWidth = (float)buffer.format.sampleRate / self.fftSize;
+                        [spectrum addObject:@([self findMaxAmplitudeForBand:band inAmplitudes:weightedAmplitudes withBandWidth:bandWidth] * amplificationFactor)];
+                    }
+                    
+                    spectrum = [self highlightWaveform:spectrum];
+                    
+                    NSMutableArray<NSNumber *> *previousSpectrum = [self.spectrumBuffer[index] mutableCopy];
+                    NSMutableArray<NSNumber *> *newSpectrum = [NSMutableArray arrayWithCapacity:spectrum.count];
+                    
+                    for (NSInteger i = 0; i < spectrum.count; i++) {
+                        float smoothedValue = ([previousSpectrum[i] floatValue] * self.spectrumSmooth) + (spectrum[i].floatValue * (1 - self.spectrumSmooth));
+                        newSpectrum[i] = @(smoothedValue);
+                    }
+                    
+                    dispatch_async(dispatch_get_main_queue(), ^{
+                        result[index] = [newSpectrum copy];
+                        self.spectrumBuffer[index] = [newSpectrum copy];
+                    });
+                });
+            }
+            
+            dispatch_sync(self.analyzeQueue, ^{});
+            
+            self.isAnalise = NO;
+            return [result copy];
         }
-        
-        result[index] = [newSpectrum copy];
-        self.spectrumBuffer[index] = [newSpectrum copy];
-    });
-    self.isAnalise = NO;
-    return [result copy];
+    }
 }
 
 
@@ -145,10 +206,7 @@
     
     for (NSInteger i = 0; i < channelCount; i++) {
         float *channel = floatChannelData[i];
-        NSMutableData *windowData = [NSMutableData dataWithLength:self.fftSize * sizeof(float)];
-        float *window = windowData.mutableBytes;
-        vDSP_hann_window(window, self.fftSize, vDSP_HANN_NORM);
-        vDSP_vmul(channel, 1, window, 1, channel, 1, self.fftSize);
+        vDSP_vmul(channel, 1, self.windowBuffer, 1, channel, 1, self.fftSize);
         
         DSPSplitComplex fftInOut;
         fftInOut.realp = self.realp;
@@ -162,19 +220,15 @@
         vDSP_vsmul(fftInOut.realp, 1, &fftNormFactor, fftInOut.realp, 1, self.fftSize / 2);
         vDSP_vsmul(fftInOut.imagp, 1, &fftNormFactor, fftInOut.imagp, 1, self.fftSize / 2);
         
-        NSMutableArray<NSNumber *> *channelAmplitudes = [NSMutableArray arrayWithCapacity:self.fftSize / 2];
-        float *amplitudesArray = (float *)calloc(self.fftSize / 2, sizeof(float));
-        vDSP_zvabs(&fftInOut, 1, amplitudesArray, 1, self.fftSize / 2);
-        amplitudesArray[0] /= 2;
+        vDSP_zvabs(&fftInOut, 1, self.amplitudesBuffer, 1, self.fftSize / 2);
+        self.amplitudesBuffer[0] /= 2;
         
+        NSMutableArray<NSNumber *> *channelAmplitudes = [NSMutableArray arrayWithCapacity:self.fftSize / 2];
         for (NSInteger j = 0; j < self.fftSize / 2; j++) {
-            channelAmplitudes[j] = @(amplitudesArray[j]);
+            channelAmplitudes[j] = @(self.amplitudesBuffer[j]);
         }
         
         [amplitudes addObject:[channelAmplitudes copy]];
-//        free(fftInOut.realp);
-//        free(fftInOut.imagp);
-        free(amplitudesArray);
     }
     
     if (isInterleaved) {
@@ -259,4 +313,20 @@
     return array;
 }
 
+- (float)findMaxAmplitudeForBand:(NSInteger)bandIndex inAmplitudes:(NSArray<NSNumber *> *)amplitudes {
+    NSRange range = [self.bandIndexRanges[bandIndex] rangeValue];
+    float maxAmplitude = -FLT_MAX;
+    
+    for (NSInteger i = range.location; i < NSMaxRange(range); i++) {
+        float amplitude = [amplitudes[i] floatValue];
+        maxAmplitude = MAX(maxAmplitude, amplitude);
+    }
+    return maxAmplitude;
+}
+
+- (void)shutdown {
+    self.isCanceled = YES;
+    dispatch_sync(self.analyzeQueue, ^{});
+}
+
 @end

+ 60 - 77
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergeAudioAnimation/KSSpectrumView.m

@@ -10,8 +10,8 @@
 @interface KSSpectrumView ()
 
 @property (nonatomic, strong) CAGradientLayer *combinedGradientLayer;
-@property (nonatomic, strong) dispatch_queue_t spectrumQueue;
-@property (atomic, assign) BOOL isCalculating;
+
+@property (nonatomic, assign) NSUInteger currentTaskId;
 
 @end
 
@@ -37,13 +37,11 @@
 - (void)setupView {
     self.barWidth = 3.0;
     self.space = 1.0;
-    
-    self.spectrumQueue = dispatch_queue_create("com.kulexiu.spectrumQueue", DISPATCH_QUEUE_SERIAL);
-    
+
     self.combinedGradientLayer = [CAGradientLayer layer];
     self.combinedGradientLayer.colors = @[
-        (__bridge id)HexRGBAlpha(0xFFFFFF, 1.0f).CGColor,
-        (__bridge id)HexRGBAlpha(0xFFFFFF, 1.0f).CGColor
+        (__bridge id)HexRGBAlpha(0xffffff, 1.0f).CGColor,
+        (__bridge id)HexRGBAlpha(0xffffff, 1.0f).CGColor
     ];
     self.combinedGradientLayer.locations = @[@0.6, @1.0];
     [self.layer addSublayer:self.combinedGradientLayer];
@@ -54,88 +52,73 @@
 }
 
 - (void)setSpectra:(NSArray<NSArray<NSNumber *> *> *)spectra {
-    if (!spectra || self.isCalculating) return;
-    
-    _spectra = [spectra copy];
-    
-    CGFloat viewHeight = self.bounds.size.height;
-    CGFloat viewWidth = self.bounds.size.width;
-    
-    @weakObj(self);
-    dispatch_async(self.spectrumQueue, ^{
-        @strongObj(self);
-        if (!self) return;
-        
-        self.isCalculating = YES;
-        self.isModify = YES;
-        
-        NSUInteger spectraCount = [spectra[0] count];
-        NSMutableArray<NSNumber *> *combinedSpectrum = [[NSMutableArray alloc] initWithCapacity:spectraCount];
-        UIBezierPath *combinedPath = [UIBezierPath bezierPath];
-        
-        CGFloat middleY = viewHeight / 2.0;
-        CGFloat barHeight = viewHeight / 2.0;
-        CGFloat cornerRadius = self.barWidth / 2.0f;
-        CGFloat xIncrement = self.barWidth + self.space;
-        
-        [self combineSpectraChannels:spectra intoArray:combinedSpectrum];
-        
-        [self createSpectrumPath:combinedPath
-                  withSpectrum:combinedSpectrum
-                     middleY:middleY
-                   barHeight:barHeight
-               cornerRadius:cornerRadius
-                xIncrement:xIncrement];
-        
-        dispatch_async(dispatch_get_main_queue(), ^{
-            if (!self.isModify) return;
+    _spectra = spectra;
+    if (spectra) {
+        // 生成唯一标识,用于取消旧任务
+        NSUInteger taskId = arc4random();
+        _currentTaskId = taskId;
+
+        CGFloat viewHeight = self.bounds.size.height;
+        CGFloat viewWidth = self.bounds.size.width;
+        @weakObj(self);
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            @strongObj(self);
+            if (!self || self.currentTaskId != taskId) {
+                return;
+            }
+            self.isModify = YES;
+            NSUInteger spectraCount = [spectra[0] count];
+            NSMutableArray<NSNumber *> *combinedSpectrum = [NSMutableArray arrayWithCapacity:spectraCount];
+            // 取两个声道数据中的最大值
+            for (NSUInteger i = 0; i < spectraCount; i++) {
+                NSNumber *leftAmplitude = spectra[0][i];
+                NSNumber *rightAmplitude = spectra.count > 1 ? spectra[1][i] : @0;
+                CGFloat maxAmplitude = MAX(leftAmplitude.floatValue, rightAmplitude.floatValue);
+                [combinedSpectrum addObject:@(maxAmplitude)];
+            }
             
-            CAShapeLayer *combinedMaskLayer = [CAShapeLayer layer];
-            combinedMaskLayer.path = combinedPath.CGPath;
-            self.combinedGradientLayer.frame = CGRectMake(0, 0, viewWidth, viewHeight);
-            self.combinedGradientLayer.mask = combinedMaskLayer;
+            CGFloat middleY = viewHeight / 2.0;
+            CGFloat barHeight = (viewHeight) / 2.0;
+            CGFloat cornerRadius = viewWidth / 2.0f;
+            CGFloat xIncrement = self.barWidth + self.space;
+            UIBezierPath *combinedPath = [UIBezierPath bezierPath];
             
-            self.isModify = NO;
-            self.isCalculating = NO;
+            // Left channel
+            for (NSUInteger i = 0; i < spectraCount; i++) {
+                CGFloat x = i * xIncrement + self.space;
+                CGFloat amplitudeValue = combinedSpectrum[i].floatValue;
+                CGFloat height = amplitudeValue * barHeight;
+                CGFloat y = middleY - height/2.0; // Centered vertically
+                
+                CGRect rect = CGRectMake(x, y, self.barWidth, height);
+                UIBezierPath *barPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
+                [combinedPath appendPath:barPath];
+            }
+            
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if (self.currentTaskId != taskId) {
+                    return;
+                }
+                CAShapeLayer *combinedMaskLayer = [CAShapeLayer layer];
+                combinedMaskLayer.path = combinedPath.CGPath;
+                self.combinedGradientLayer.frame = CGRectMake(0, 0, viewWidth, viewHeight);
+                self.combinedGradientLayer.mask = combinedMaskLayer;
+                self.isModify = NO;
+            });
         });
-    });
-}
-
-- (void)combineSpectraChannels:(NSArray<NSArray<NSNumber *> *> *)spectra
-                   intoArray:(NSMutableArray<NSNumber *> *)combinedSpectrum {
-    NSUInteger spectraCount = [spectra[0] count];
-    for (NSUInteger i = 0; i < spectraCount; i++) {
-        NSNumber *leftAmplitude = spectra[0][i];
-        NSNumber *rightAmplitude = spectra.count > 1 ? spectra[1][i] : @0;
-        CGFloat maxAmplitude = MAX(leftAmplitude.floatValue, rightAmplitude.floatValue);
-        [combinedSpectrum addObject:@(maxAmplitude)];
     }
 }
 
-- (void)createSpectrumPath:(UIBezierPath *)path
-             withSpectrum:(NSArray<NSNumber *> *)spectrum
-                 middleY:(CGFloat)middleY
-               barHeight:(CGFloat)barHeight
-            cornerRadius:(CGFloat)cornerRadius
-             xIncrement:(CGFloat)xIncrement {
-    [spectrum enumerateObjectsUsingBlock:^(NSNumber *amplitude, NSUInteger i, BOOL *stop) {
-        CGFloat x = i * xIncrement + self.space;
-        CGFloat height = amplitude.floatValue * barHeight;
-        CGFloat y = middleY - height/2.0;
-        
-        CGRect rect = CGRectMake(x, y, self.barWidth, height);
-        UIBezierPath *barPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
-        [path appendPath:barPath];
-    }];
-}
-
 - (CGFloat)translateAmplitudeToYPosition:(float)amplitude {
     CGFloat barHeight = amplitude * self.bounds.size.height;
     return self.bounds.size.height - barHeight;
 }
 
 - (void)dealloc {
-    self.spectrumQueue = nil;
+    _currentTaskId = 0;
+    // 移除图层
+    [self.combinedGradientLayer removeFromSuperlayer];
+    self.combinedGradientLayer = nil;
     NSLog(@"---- KSSpectrumView dealloc");
 }
 /*

+ 63 - 72
KulexiuForStudent/KulexiuForStudent/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.m

@@ -72,7 +72,9 @@
 
 - (void)configEngine {
     [self setupAudioSession];
-    
+    if (self.audioEngine) {
+        [self releaseAudioResources];
+    }
     self.audioEngine = [[AVAudioEngine alloc] init];
     self.nodePlayer = [[AVAudioPlayerNode alloc] init];
     
@@ -160,6 +162,7 @@
         self.sampleRate = self.audioFile.fileFormat.sampleRate;
         [self configEngine];
         
+        
         AVAudioFormat *outputFormat = [self.audioEngine.mainMixerNode outputFormatForBus:0];
         [self.audioEngine connect:self.nodePlayer to:self.audioEngine.mainMixerNode format:outputFormat];
         if (self.needAnalyzer) {
@@ -404,8 +407,15 @@
           startPosition:(AVAudioFramePosition)startPosition
                mixStart:(AVAudioFramePosition)mixStartPosition {
     
-    // 使用异步队列处理混音
+    // 添加取消检查
+    if (self.isCanceled) return;
+    
+    // 使用 weak 引用避免循环
+    @weakObj(self);
     dispatch_async(self.mixerQueue, ^{
+        @strongObj(self);
+        if (!self || self.isCanceled) return; // 关键检查
+        
         float *bgLeftChannel = bgBuffer.floatChannelData[0];
         float *bgRightChannel = bgBuffer.floatChannelData[bgBuffer.format.channelCount > 1 ? 1 : 0];
         float *recordLeftChannel = recordBuffer.floatChannelData[0];
@@ -470,8 +480,9 @@
     else if (type == AVAudioSessionInterruptionTypeEnded) {
         AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
         if (options == AVAudioSessionInterruptionOptionShouldResume) {
-            //Handle Resume
+            // 正确的顺序:1.恢复会话 → 2.重建引擎
             [self resumeAudioSession];
+            [self retryInitEngine];
             NSLog(@"---- 播放恢复");
         }
     }
@@ -479,10 +490,16 @@
 
 - (void)resumeAudioSession {
     NSError *error = nil;
-    [[AVAudioSession sharedInstance] setActive:YES error:&error];
-    if (error) {
-        NSLog(@"------ error desc %@", error.description);
+    // 先设置为非活动状态确保配置生效
+    [[AVAudioSession sharedInstance] setActive:NO error:nil];
+    
+    // 重新激活会话
+    if (![[AVAudioSession sharedInstance] setActive:YES error:&error]) {
+        NSLog(@"会话激活失败: %@", error.localizedDescription);
     }
+    
+    // 添加延迟保证会话生效
+    [NSThread sleepForTimeInterval:0.05]; // 50ms延迟
 }
 
 - (void)handleRouteChange:(NSNotification *)notification {
@@ -596,8 +613,9 @@
 }
 
 - (void)stopTimer {
-    
-    [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器
+    if (_timer) {
+        [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器
+    }
 }
 
 #pragma mark ---- lazying
@@ -637,6 +655,7 @@
 
 - (void)timeFunction {
     if (self.isCanceled) {
+        [self stopTimer];
         return;
     }
     self.totalDuration = [self getTotalTime];
@@ -711,78 +730,50 @@
 }
 
 - (void)releaseAudioResources {
-    // 使用 sync 而不是 async 确保资源释放完成
+    
     dispatch_sync(self.sourceQueue, ^{
-        @try {
-            // 1. 首先停止所有活动
-            if (self.nodePlayer.isPlaying) {
-                [self.nodePlayer stop];
-            }
-            
-            if (self.audioEngine.isRunning) {
-                [self removeTap];
-                [self.audioEngine stop];
-                [self.audioEngine reset];
-            }
-            
-            // 2. 移除节点连接
-            if (self.nodePlayer && self.audioEngine) {
-                @try {
-                    [self.audioEngine detachNode:self.nodePlayer];
-                } @catch (NSException *exception) {
-                    NSLog(@"Detach node exception: %@", exception);
-                }
-            }
-            
-            // 3. 使用临时变量持有引用
-            AVAudioEngine *tempEngine = self.audioEngine;
-            AVAudioPlayerNode *tempPlayer = self.nodePlayer;
-            AVAudioFile *tempAudioFile = self.audioFile;
-            AVAudioFile *tempBgAudioFile = self.bgAudioFile;
-            AVAudioPCMBuffer *tempMixBuffer = self.mixBuffer;
-            
-            // 4. 先清空属性引用
-            self.audioEngine = nil;
-            self.nodePlayer = nil;
-            self.analyzer = nil;
-            self.audioFile = nil;
-            self.audioFormat = nil;
-            self.bgAudioFile = nil;
-            self.bgAudioFormat = nil;
-            self.mixBuffer = nil;
-            
-            // 5. 在临时变量作用域内释放资源
-            @autoreleasepool {
-                tempEngine = nil;
-                tempPlayer = nil;
-                tempAudioFile = nil;
-                tempBgAudioFile = nil;
-                tempMixBuffer = nil;
-            }
-            
-            // 6. 重置状态
-            self.isReady = NO;
-            self.currentFrame = 0;
-            self.startPosition = 0;
-            self.timeCount = 0;
-            
-        } @catch (NSException *exception) {
-            NSLog(@"Release resources exception: %@", exception);
-        } @finally {
-            NSLog(@"Audio resources release completed");
+        if (!self) return;
+
+        if (self.nodePlayer.isPlaying) {
+            [self.nodePlayer stop];
         }
+        if (self.audioEngine.isRunning) {
+            [self.audioEngine stop];
+            [self.audioEngine reset];
+        }
+        if (self.audioEngine && self.nodePlayer) {
+            [self.audioEngine disconnectNodeInput:self.nodePlayer];
+            [self.audioEngine detachNode:self.nodePlayer];
+        }
+       
     });
+    self.audioFile = nil;
+    self.bgAudioFile = nil;
+    self.mixBuffer = nil;
 }
 
 - (void)dealloc {
-    NSLog(@"---- KSMergeEnginePlayer dealloc");
+    // 1. 取消所有异步操作
+    self.isCanceled = YES;
+    // 2. 执行资源释放
     [self releaseAudioResources];
-    // 停止并清理定时器
-    if (_timer) {
-        [_timer invalidate];
-        _timer = nil;
-    }
+    // 3. 安全释放定时器
+    dispatch_main_sync_safe(^{
+        [self stopTimer];
+        if (self->_timer) {
+            [self->_timer invalidate];
+            self->_timer = nil;
+        }
+    });
+    
+    dispatch_sync(self.sourceQueue, ^{});
+
+    // 4. 移除通知监听
     [[NSNotificationCenter defaultCenter] removeObserver:self];
+    
+    
+    
+    NSLog(@"---- KSMergeEnginePlayer dealloc");
 }
 
 @end

+ 21 - 0
KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/Controller/InsititutionMineViewController.m

@@ -77,6 +77,7 @@
     if ([self checkIsLoginToLoginView:YES]) {
         [self requsetUserMessage];
         [self requestUnreadCount];
+        [self requestAlbumRecord];
     }
 }
 
@@ -130,6 +131,26 @@
     }];
 }
 
+- (void)requestAlbumRecord {
+    [KSNetworkingManager userTenantAlbumRecordRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
+        NSString *tenantAlbumName = nil;
+        NSString *endTime = nil;
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSDictionary *result = [dic ks_dictionaryValueForKey:@"data"];
+            tenantAlbumName = [result ks_stringValueForKey:@"tenantAlbumName"];
+            endTime = [result ks_stringValueForKey:@"endTime"];
+        }
+        [self refreshAlbumInfo:tenantAlbumName endTime:endTime];
+    } faliure:^(NSError * _Nonnull error) {
+        
+        [self refreshAlbumInfo:nil endTime:nil];
+    }];
+}
+
+- (void)refreshAlbumInfo:(NSString *)tenantAlbumName endTime:(NSString *)endTime {
+    [self.bodyView configWithAlbumInfo:tenantAlbumName endTime:endTime];
+}
+
 - (void)refreshView {
     self.bodyView.hasCustomService = self.mineInfo.customerServiceNum > 0 ? YES : NO;
     CGFloat contentMinHeight = [_bodyView getViewHeight];

+ 2 - 0
KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.h

@@ -37,6 +37,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (void)configWithSource:(UserInfo *)sourceModel;
 
+- (void)configWithAlbumInfo:(NSString *)tenantAlbumName endTime:(NSString *)endTime;
+
 - (void)operationCallback:(INSMineViewCallback)callback;
 
 - (CGFloat)getViewHeight;

+ 71 - 17
KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.m

@@ -9,6 +9,8 @@
 #import <UIImageView+DisplayImage.h>
 #import "TYPageControl.h"
 #import "TenantMineFunctionView.h"
+#import "CBAutoScrollLabel.h"
+#import "NSDate+Extension.h"
 
 #define MAX_FUNCROWCOUNT (IS_IPAD ? 6 : 4)
 
@@ -31,7 +33,11 @@
 @property (weak, nonatomic) IBOutlet UIView *subjectView;
 @property (weak, nonatomic) IBOutlet UILabel *subjectLabel;
 
+@property (weak, nonatomic) IBOutlet UIView *toolNameContainer;
+@property (nonatomic, strong) CBAutoScrollLabel *toolNameLabel;
+
 @property (weak, nonatomic) IBOutlet UILabel *toolDesc;
+@property (weak, nonatomic) IBOutlet UIImageView *descImage;
 
 @property (nonatomic, copy) INSMineViewCallback callback;
 
@@ -81,6 +87,14 @@
     self.bgImageHeight.constant = height;
     
     [self createToolViewLayer];
+    [self configToolName];
+}
+
+- (void)configToolName {
+    [self.toolNameContainer addSubview:self.toolNameLabel];
+    [self.toolNameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.toolNameContainer);
+    }];
 }
 
 - (void)createToolViewLayer {
@@ -142,23 +156,6 @@
         self.subjectView.hidden = NO;
     }
     
-    // 时间
-//    NSString *tagImg = sourceModel.isVip == 0 ? @"institution_mineMember_tag_no" : @"institution_mineMember_tag";
-//    [self.memberImg setImage:[UIImage imageNamed:tagImg]];
-//    self.memberImg.hidden = NO;
-    
-//    if ([sourceModel.tenantAlbumFlag integerValue] > 0) {
-//        self.toolDesc.text = [NSString stringWithFormat:@"至%@",[[sourceModel.tenantAlbumEndTime componentsSeparatedByString:@" "] firstObject]];
-//    }
-//    else {
-//        if (![NSString isEmptyString:sourceModel.tenantAlbumEndTime]) {
-//            self.toolDesc.text = @"训练工具已过期";
-//        }
-//        else {
-//            self.toolDesc.text = @"暂未开通";
-//        }
-//    }
-    
     // 小组名称
     if ([NSString isEmptyString:sourceModel.tenantGroupName]) {
         self.userNameTop.constant = 21.0f;
@@ -172,6 +169,50 @@
     
 }
 
+- (void)configWithAlbumInfo:(NSString *)tenantAlbumName endTime:(NSString *)endTime {
+    NSString *descImg = @"";
+    NSString *descTitle = @"";
+    NSMutableAttributedString *descAttr;
+    if ([NSString isEmptyString:endTime]) {
+        descImg = @"institution_mineTool_open";
+        descAttr = [[NSMutableAttributedString alloc] initWithString:@"您暂未开通训练教程" attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.5f)}];
+        descTitle = @"训练教程";
+    }
+    else {
+        descTitle = [NSString isEmptyString:tenantAlbumName] ? @"训练教程" : tenantAlbumName;
+        descImg = @"institution_mineTool_expired";
+        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+        [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+        NSDate *endDate = [formatter dateFromString:endTime];
+        [formatter setDateFormat:@"yyyy-MM-dd"];
+        
+        
+        // 如果没有过期
+        if ([endDate timeIntervalSinceNow] > 0) {
+            descAttr = [[NSMutableAttributedString alloc] initWithString:@"有效期至 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.5f)}];
+            [descAttr appendAttributedString:[[NSAttributedString alloc] initWithString:[formatter stringFromDate:endDate] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGB(0xFE2451)}]];
+        }
+        // 如果超过7天
+        else if ([[NSDate date] timeIntervalSinceDate:endDate] > 7 * 24 * 60 * 60) {
+            descImg = @"institution_mineTool_open";
+            descTitle = @"训练教程";
+            descAttr = [[NSMutableAttributedString alloc] initWithString:@"您暂未开通训练教程" attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.5f)}];
+        }
+        else {
+            
+            descAttr = [[NSMutableAttributedString alloc] initWithString:@"已过期 " attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGBAlpha(0x000000, 0.5f)}];
+            // 计算过期天数
+            NSInteger days = [endDate daysAgo];
+            NSString *exipreDay = [NSString stringWithFormat:@"%ld天",days];
+            [descAttr appendAttributedString:[[NSAttributedString alloc] initWithString:exipreDay attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGB(0xFE2451)}]];
+        }
+    }
+    
+    [self.descImage setImage:[UIImage imageNamed:descImg]];
+    self.toolNameLabel.text = descTitle;
+    self.toolDesc.attributedText = descAttr;
+}
+
 - (IBAction)clickAction:(UITapGestureRecognizer *)sender {
     NSInteger index = sender.view.tag;
     
@@ -281,4 +322,17 @@
     }
     return _functionScrollView;
 }
+
+- (CBAutoScrollLabel *)toolNameLabel {
+    if (!_toolNameLabel) {
+        _toolNameLabel = [[CBAutoScrollLabel alloc] init];
+        _toolNameLabel.font = [UIFont systemFontOfSize:14.0f weight:UIFontWeightSemibold];
+        _toolNameLabel.textColor = HexRGB(0x131414);
+        _toolNameLabel.pauseInterval = 1.5;
+        _toolNameLabel.scrollDirection = CBAutoScrollDirectionLeft;
+        _toolNameLabel.fadeLength = 1;
+        [_toolNameLabel observeApplicationNotifications];
+    }
+    return _toolNameLabel;
+}
 @end

+ 33 - 21
KulexiuForStudent/KulexiuForStudent/InstitutionModule/Mine/View/InstitutionMineBodyView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina6_12" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -139,11 +139,8 @@
                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="institution_ToolImage" translatesAutoresizingMaskIntoConstraints="NO" id="LC0-SH-j3j">
                                     <rect key="frame" x="4" y="0.0" width="47" height="49"/>
                                 </imageView>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="institution_ToolTitle" translatesAutoresizingMaskIntoConstraints="NO" id="3mi-f7-wdo">
-                                    <rect key="frame" x="61" y="11" width="60" height="15"/>
-                                </imageView>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="曲目训练教程" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mvV-Sr-oNN">
-                                    <rect key="frame" x="61.000000000000007" y="30" width="73.666666666666686" height="17"/>
+                                    <rect key="frame" x="61.000000000000007" y="30" width="71.666666666666686" height="17"/>
                                     <constraints>
                                         <constraint firstAttribute="height" constant="17" id="xic-Zn-hSL"/>
                                     </constraints>
@@ -154,22 +151,35 @@
                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="institution_mineToolBg" translatesAutoresizingMaskIntoConstraints="NO" id="U3x-hC-8CJ">
                                     <rect key="frame" x="139" y="0.0" width="237" height="57"/>
                                 </imageView>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="institution_mineToolDetail" translatesAutoresizingMaskIntoConstraints="NO" id="Q15-wp-WHa">
-                                    <rect key="frame" x="282" y="13" width="81" height="31"/>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="institution_mineTool_open" translatesAutoresizingMaskIntoConstraints="NO" id="Q15-wp-WHa">
+                                    <rect key="frame" x="305" y="15" width="59" height="27"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="27" id="EcQ-0b-J7q"/>
+                                        <constraint firstAttribute="width" constant="59" id="RDn-AN-vAL"/>
+                                    </constraints>
                                 </imageView>
+                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wJ9-AM-hhh">
+                                    <rect key="frame" x="61" y="9" width="235" height="20"/>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="20" id="Of5-xj-7mw"/>
+                                    </constraints>
+                                </view>
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <constraints>
-                                <constraint firstItem="3mi-f7-wdo" firstAttribute="leading" secondItem="mvV-Sr-oNN" secondAttribute="leading" id="2vK-eb-bjK"/>
+                                <constraint firstItem="wJ9-AM-hhh" firstAttribute="top" secondItem="ps4-up-G2N" secondAttribute="top" constant="9" id="AZ3-Bz-Sqj"/>
+                                <constraint firstItem="mvV-Sr-oNN" firstAttribute="leading" secondItem="wJ9-AM-hhh" secondAttribute="leading" id="BaZ-tm-bRb"/>
                                 <constraint firstAttribute="trailing" secondItem="U3x-hC-8CJ" secondAttribute="trailing" id="Cy3-z6-X5r"/>
                                 <constraint firstItem="U3x-hC-8CJ" firstAttribute="top" secondItem="ps4-up-G2N" secondAttribute="top" id="EBZ-Dq-UTy"/>
+                                <constraint firstItem="mvV-Sr-oNN" firstAttribute="top" secondItem="wJ9-AM-hhh" secondAttribute="bottom" constant="1" id="GVA-ny-zCD"/>
                                 <constraint firstItem="LC0-SH-j3j" firstAttribute="leading" secondItem="ps4-up-G2N" secondAttribute="leading" constant="4" id="L23-Ux-Bow"/>
                                 <constraint firstItem="LC0-SH-j3j" firstAttribute="top" secondItem="ps4-up-G2N" secondAttribute="top" id="Vao-c4-Sp5"/>
+                                <constraint firstItem="Q15-wp-WHa" firstAttribute="leading" secondItem="wJ9-AM-hhh" secondAttribute="trailing" constant="9" id="Xo4-Tf-czN"/>
                                 <constraint firstAttribute="bottom" secondItem="U3x-hC-8CJ" secondAttribute="bottom" id="ZCv-TO-fQ4"/>
                                 <constraint firstAttribute="bottom" secondItem="mvV-Sr-oNN" secondAttribute="bottom" constant="10" id="cgK-6A-Li4"/>
-                                <constraint firstItem="mvV-Sr-oNN" firstAttribute="top" secondItem="3mi-f7-wdo" secondAttribute="bottom" constant="4" id="gzD-zS-bh4"/>
-                                <constraint firstAttribute="trailing" secondItem="Q15-wp-WHa" secondAttribute="trailing" constant="13" id="nzX-vo-NAA"/>
-                                <constraint firstAttribute="bottom" secondItem="Q15-wp-WHa" secondAttribute="bottom" constant="13" id="s1n-KP-Qcb"/>
+                                <constraint firstAttribute="trailing" secondItem="Q15-wp-WHa" secondAttribute="trailing" constant="12" id="nzX-vo-NAA"/>
+                                <constraint firstAttribute="bottom" secondItem="Q15-wp-WHa" secondAttribute="bottom" constant="15" id="s1n-KP-Qcb"/>
                                 <constraint firstItem="mvV-Sr-oNN" firstAttribute="leading" secondItem="LC0-SH-j3j" secondAttribute="trailing" constant="10" id="sro-fQ-SuB"/>
                             </constraints>
                         </view>
@@ -212,7 +222,7 @@
                             <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         </view>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="常用功能" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QIe-vg-wc9">
-                            <rect key="frame" x="15.000000000000004" y="15" width="61.333333333333343" height="21"/>
+                            <rect key="frame" x="14.999999999999996" y="15" width="59.666666666666657" height="21"/>
                             <constraints>
                                 <constraint firstAttribute="height" constant="21" id="Sxy-2a-YhZ"/>
                             </constraints>
@@ -244,7 +254,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="帮助中心" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fWv-5K-YGR">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333314" width="65.333333333333314" height="19.333333333333329"/>
+                                    <rect key="frame" x="52" y="19.333333333333314" width="63.666666666666657" height="19.333333333333329"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -285,7 +295,7 @@
                             <rect key="frame" x="0.0" y="58" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="意见反馈" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dnv-60-hyW">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333314" width="65.333333333333314" height="19"/>
+                                    <rect key="frame" x="52" y="19.333333333333314" width="63.666666666666657" height="19"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -326,7 +336,7 @@
                             <rect key="frame" x="0.0" y="115.99999999999994" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="用户协议" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8mD-vY-M3T">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333371" width="65.333333333333314" height="19"/>
+                                    <rect key="frame" x="52" y="19.333333333333371" width="63.666666666666657" height="19"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -367,7 +377,7 @@
                             <rect key="frame" x="0.0" y="173.99999999999994" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="隐私协议" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8We-Tk-Xu4">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333371" width="65.333333333333314" height="19"/>
+                                    <rect key="frame" x="52" y="19.333333333333371" width="63.666666666666657" height="19"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -408,7 +418,7 @@
                             <rect key="frame" x="0.0" y="231.99999999999994" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="关于我们" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ojF-qm-wBA">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333371" width="65.333333333333314" height="19"/>
+                                    <rect key="frame" x="52" y="19.333333333333371" width="63.666666666666657" height="19"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -449,7 +459,7 @@
                             <rect key="frame" x="0.0" y="289.99999999999994" width="388" height="58"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="在线客服" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Uzi-OH-vgU">
-                                    <rect key="frame" x="51.999999999999993" y="19.333333333333371" width="65.333333333333314" height="19"/>
+                                    <rect key="frame" x="52" y="19.333333333333371" width="63.666666666666657" height="19"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                     <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
@@ -538,12 +548,15 @@
                 <outlet property="bottomLine" destination="dSf-QJ-hbD" id="Xjs-T3-Sgq"/>
                 <outlet property="customServiceHeight" destination="lJB-vz-5Ci" id="9Jk-mI-ORQ"/>
                 <outlet property="customServiceView" destination="d2M-k7-crG" id="lye-nL-GbD"/>
+                <outlet property="descImage" destination="Q15-wp-WHa" id="rA2-dS-48o"/>
                 <outlet property="functionView" destination="Akl-gJ-5NJ" id="aPS-KN-edW"/>
                 <outlet property="memberImg" destination="j1E-FX-DSh" id="Qcd-Se-bsQ"/>
                 <outlet property="subjectLabel" destination="k3g-g1-liB" id="4om-GC-86Z"/>
                 <outlet property="subjectView" destination="aWj-xg-N6w" id="LbY-EU-yem"/>
                 <outlet property="tenantName" destination="v4r-I2-0Uz" id="WSa-2L-Hzv"/>
                 <outlet property="toolBgView" destination="Mxr-u3-Zhb" id="CXc-sO-fed"/>
+                <outlet property="toolDesc" destination="mvV-Sr-oNN" id="vLY-eE-W7z"/>
+                <outlet property="toolNameContainer" destination="wJ9-AM-hhh" id="Wok-II-qEs"/>
                 <outlet property="userAvatar" destination="X3c-Yi-Xkh" id="cOQ-qB-Uel"/>
                 <outlet property="userName" destination="Nlb-bG-jKG" id="gQI-V1-EYx"/>
                 <outlet property="userNameTop" destination="2Do-ed-2h8" id="scI-hM-fzo"/>
@@ -628,10 +641,9 @@
         <image name="insititution_privacy" width="22" height="22"/>
         <image name="insititution_userAgreement" width="22" height="22"/>
         <image name="institution_ToolImage" width="47" height="49"/>
-        <image name="institution_ToolTitle" width="60" height="15"/>
         <image name="institution_mineMember_tag" width="44" height="17"/>
         <image name="institution_mineToolBg" width="237" height="58"/>
-        <image name="institution_mineToolDetail" width="81" height="31"/>
+        <image name="institution_mineTool_open" width="59" height="27"/>
         <image name="mine_next" width="8" height="15"/>
         <image name="tenant_defalut_avatar" width="150" height="150"/>
         <systemColor name="systemBackgroundColor">

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Course/VipCourse/Controller/VipCouseDetailViewController.m

@@ -95,8 +95,8 @@
     [KSNetworkingManager selectRoomConfigRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSDictionary *result = [dic ks_dictionaryValueForKey:@"data"];
-            self.joinRoomBeforeTime = [result ks_integerValueForKey:@"practiceStartTime"];
-            self.quitRomeEndTime = [result ks_integerValueForKey:@"practiceEndTime"];
+            self.joinRoomBeforeTime = [result ks_integerValueForKey:@"vipStartTime"];
+            self.quitRomeEndTime = [result ks_integerValueForKey:@"vipEndTime"];
         }
         else {
             [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];

+ 1 - 1
KulexiuForStudent/Podfile.lock

@@ -357,7 +357,7 @@ SPEC CHECKSUMS:
   JPush: 88d6361fbec4be7c8b55b20b7fe1c292228f6bc2
   JXCategoryView: 262d503acea0b1278c79a1c25b7332ffaef4d518
   JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e
-  KSCloudAccompanyLibrary: e9edc50bba0b63b7b270389afbb31d6655255961
+  KSCloudAccompanyLibrary: a85e75727985fe95b2454585b2288e3430a0d43c
   KSToolsLibrary: c1630ddfedd31f005ed2d7dbe0162fc0eb546a99
   lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31
   Masonry: 678fab65091a9290e40e2832a55e7ab731aad201

+ 1 - 0
KulexiuForStudent/Pods/Headers/Private/KSCloudAccompanyLibrary/AudioProcessHandle.hpp

@@ -0,0 +1 @@
+../../../../../../../WorkSpace/TargetModule/my-local-repo/KSCloudAccompanyLibrary/KSCloudAccompanyLibrary/Evaluate/AudioProcessHandle.hpp

+ 1 - 0
KulexiuForStudent/Pods/Headers/Private/KSCloudAccompanyLibrary/EvaluateManager.h

@@ -0,0 +1 @@
+../../../../../../../WorkSpace/TargetModule/my-local-repo/KSCloudAccompanyLibrary/KSCloudAccompanyLibrary/Classes/Base/EvaluateManager.h

+ 1 - 0
KulexiuForStudent/Pods/Headers/Public/KSCloudAccompanyLibrary/EvaluateManager.h

@@ -0,0 +1 @@
+../../../../../../../WorkSpace/TargetModule/my-local-repo/KSCloudAccompanyLibrary/KSCloudAccompanyLibrary/Classes/Base/EvaluateManager.h

+ 5 - 1
KulexiuForStudent/Pods/Local Podspecs/KSCloudAccompanyLibrary.podspec.json

@@ -18,7 +18,10 @@
   "platforms": {
     "ios": "12.0"
   },
-  "source_files": "KSCloudAccompanyLibrary/Classes/**/*",
+  "source_files": [
+    "KSCloudAccompanyLibrary/Classes/**/*",
+    "KSCloudAccompanyLibrary/Evaluate/AudioProcessHandle.hpp"
+  ],
   "swift_versions": "5.0",
   "pod_target_xcconfig": {
     "VALID_ARCHS": "arm64"
@@ -28,6 +31,7 @@
   "vendored_frameworks": [
     "KSTunerLibrary.framework"
   ],
+  "vendored_libraries": "KSCloudAccompanyLibrary/Evaluate/libEvaluateLibrary.a",
   "dependencies": {
     "KSToolsLibrary": [
 

+ 1 - 1
KulexiuForStudent/Pods/Manifest.lock

@@ -357,7 +357,7 @@ SPEC CHECKSUMS:
   JPush: 88d6361fbec4be7c8b55b20b7fe1c292228f6bc2
   JXCategoryView: 262d503acea0b1278c79a1c25b7332ffaef4d518
   JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e
-  KSCloudAccompanyLibrary: e9edc50bba0b63b7b270389afbb31d6655255961
+  KSCloudAccompanyLibrary: a85e75727985fe95b2454585b2288e3430a0d43c
   KSToolsLibrary: c1630ddfedd31f005ed2d7dbe0162fc0eb546a99
   lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31
   Masonry: 678fab65091a9290e40e2832a55e7ab731aad201

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 610 - 609
KulexiuForStudent/Pods/Pods.xcodeproj/project.pbxproj


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.debug.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.dev.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.release.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent-KulexiuForStudentUITests/Pods-KulexiuForStudent-KulexiuForStudentUITests.test.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.debug.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.dev.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.release.xcconfig


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
KulexiuForStudent/Pods/Target Support Files/Pods-KulexiuForStudent/Pods-KulexiuForStudent.test.xcconfig


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است