Browse Source

update ailiao

warrior 3 months ago
parent
commit
1f521c6904

+ 34 - 12
projects/live-app/src/moduls/live/link-page/link-page.component.html

@@ -29,17 +29,27 @@
     (click)="showTool = !showTool"
     [style.visibility]="showTool ? 'visible' : 'hidden'"
   >
+    <div class="row" style="justify-content: center;">
+      <div class="tips">剩余通话时长 <span>{{ liveService.countdown | secondsToTime }}</span></div>
+    </div>
+    @if (!liveService.isAnchor) {
     <div class="row">
-      <div class="row-li" (click)="onChangeLiveStatus($event, 'audio')">
-        <div [ngClass]="{ 'action-icon': liveService.tools['audio'], 'icon-box': true }">
-          <ion-icon class="icon" name="mic-off"></ion-icon>
+      <div class="row-li">
+        <div class="icon-box">
+          <ion-icon class="icon" name="gift"></ion-icon>
         </div>
-        <div class="label">麦克风{{ liveService.tools['audio'] ? "已关" : "已开" }}</div>
+        <div class="label">礼物</div>
       </div>
     </div>
+    }
     <div class="row">
       <div class="row-li" (click)="onChangeLiveStatus($event, 'camera')">
-        <div [ngClass]="{ 'action-icon': liveService.tools['camera'], 'icon-box': true }">
+        <div
+          [ngClass]="{
+            'action-icon': liveService.tools['camera'],
+            'icon-box': true
+          }"
+        >
           <ion-icon name="camera-reverse"></ion-icon>
         </div>
         <div class="label">旋转摄像头</div>
@@ -47,11 +57,16 @@
       <div class="row-li" (click)="onChangeLiveStatus($event, 'mute')">
         <div
           class="icon-box"
-          [ngClass]="{ 'action-icon': liveService.tools['mute'], 'icon-box': true }"
+          [ngClass]="{
+            'action-icon': liveService.tools['mute'],
+            'icon-box': true
+          }"
         >
           <ion-icon class="icon" name="notifications-off"></ion-icon>
         </div>
-        <div class="label">{{ liveService.tools['mute'] ? "已静音" : "静音" }}</div>
+        <div class="label">
+          {{ liveService.tools["mute"] ? "已静音" : "静音" }}
+        </div>
       </div>
     </div>
     <div class="row">
@@ -62,16 +77,23 @@
         <div class="label">聊天</div>
       </div>
       <div class="row-li" (click)="endCall($event)">
-        <div class="icon-box" style="background-color: rgba(0, 0, 0, 0.0);">
+        <div class="icon-box" style="background-color: rgba(0, 0, 0, 0)">
           <img class="icon" src="/img/挂断.png" alt="" class="icon-img" />
         </div>
         <div class="label">挂断</div>
       </div>
-      <div class="row-li">
-        <div class="icon-box">
-          <ion-icon class="icon" name="gift"></ion-icon>
+      <div class="row-li" (click)="onChangeLiveStatus($event, 'audio')">
+        <div
+          [ngClass]="{
+            'action-icon': liveService.tools['audio'],
+            'icon-box': true
+          }"
+        >
+          <ion-icon class="icon" name="mic-off"></ion-icon>
+        </div>
+        <div class="label">
+          麦克风{{ liveService.tools["audio"] ? "已关" : "已开" }}
         </div>
-        <div class="label">礼物</div>
       </div>
     </div>
   </div>

+ 11 - 1
projects/live-app/src/moduls/live/link-page/link-page.component.scss

@@ -67,7 +67,7 @@
     bottom: 0;
     left: 0;
     width: 100%;
-    height: 260px;
+    // height: 260px;
     padding: 10px;
     .row{
       display: flex;
@@ -116,6 +116,16 @@
           }
         }
       }
+      .tips{
+        background-color: rgba(0, 0, 0, 0.4);
+        border-radius: 20px;
+        color: white;
+        padding: 6px;
+        margin-bottom: 10px;
+        span{
+          color: #ffc409;
+        }
+      }
     }
   }
 }

+ 2 - 1
projects/live-app/src/moduls/live/link-page/link-page.component.ts

@@ -12,12 +12,13 @@ import {
 import { ActivatedRoute } from '@angular/router';
 import { LiveComponent } from '../../../app/components/live/live.component';
 import { LiveService } from '../../../services/live.service';
+import { SharedModule } from '../../shared.module';
 @Component({
   selector: 'app-link-page',
   templateUrl: './link-page.component.html',
   styleUrls: ['./link-page.component.scss'],
   standalone: true,
-  imports: [IonicModule, FormsModule, LiveComponent, CommonModule],
+  imports: [IonicModule, FormsModule, LiveComponent, CommonModule,SharedModule],
 })
 export class LinkPageComponent implements OnInit {
   @ViewChild('live') live!: LiveComponent;

+ 3 - 2
projects/live-app/src/moduls/shared.module.ts

@@ -2,10 +2,11 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { ShowDatePipe } from '../pipes/show-date'
+import { SecondsToTimePipe } from '../pipes/secondsToTime';
 
 @NgModule({
   imports: [CommonModule],
-  declarations: [ShowDatePipe],
-  exports: [ShowDatePipe],
+  declarations: [ShowDatePipe,SecondsToTimePipe],
+  exports: [ShowDatePipe,SecondsToTimePipe],
 })
 export class SharedModule { }

+ 21 - 0
projects/live-app/src/pipes/secondsToTime.ts

@@ -0,0 +1,21 @@
+// seconds-to-time.pipe.ts
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'secondsToTime'
+})
+export class SecondsToTimePipe implements PipeTransform {
+
+  transform(seconds: number): string {
+    const hours = Math.floor(seconds / 3600);
+    seconds %= 3600;
+    const minutes = Math.floor(seconds / 60);
+    seconds %= 60;
+
+    return `${this.pad(hours)}:${this.pad(minutes)}:${this.pad(seconds)}`;
+  }
+
+  private pad(value: number): string {
+    return value < 10 ? `0${value}` : `${value}`;
+  }
+}

+ 10 - 4
projects/live-app/src/services/http.service.ts

@@ -19,10 +19,16 @@ export class HttpService {
     });
   }
 
-  // 定义get请求方法
-  getMsg(url: string, params: any) {
-    return this.http.get(url, {
-      params,
+  // 定义请求方法
+  httpPostRquest(url: string, params: any) : Promise<any> {
+    return new Promise((resolve, reason) => {
+      this.http
+        .post(url, {
+          params,
+        })
+        .subscribe((data) => {
+          resolve(data);
+        });
     });
   }
 

+ 104 - 59
projects/live-app/src/services/live.service.ts

@@ -9,6 +9,7 @@ declare const AgoraRTC: any;
   providedIn: 'root',
 })
 export class LiveService {
+  isAnchor: boolean = false; //是否是主播
   options: {
     appid: string;
     channel: string;
@@ -51,6 +52,8 @@ export class LiveService {
   room?: Parse.Object; //直播间
   connection_state?: string; //连接状态
   surplusNumber: number = 0; //剩余可通话时长(单位:秒s)
+  countdown: number = 0; // 新增倒计时变量
+  timer_countdown: any;
   liveLog?: Parse.Object; //直播记录
   constructor(
     private http: HttpService,
@@ -74,6 +77,7 @@ export class LiveService {
   /* 初始化Agora */
   initAgora() {
     this.timer && clearTimeout(this.timer);
+    this.timer_countdown && clearInterval(this.timer_countdown);
     this.options['token'] = '';
     this.options['channel'] = '';
     this.client?.leave();
@@ -99,10 +103,10 @@ export class LiveService {
           audioDevice: this.media_devices.audioDevices[0].deviceId,
           videoDevice: this.media_devices.videoDevices[0].deviceId,
         };
-        return Promise.all([
-          AgoraRTC.createCameraVideoTrack(),
-          AgoraRTC.createMicrophoneAudioTrack(),
-        ]);
+        // return Promise.all([
+        //   AgoraRTC.createCameraVideoTrack(),
+        //   AgoraRTC.createMicrophoneAudioTrack(),
+        // ]);
       })
       .then((tracks: any) => {
         console.log(tracks);
@@ -115,11 +119,12 @@ export class LiveService {
   /* 获取token */
   async getToken(room: Parse.Object) {
     this.room = room;
+    this.isAnchor = room?.get('user')?.id === Parse.User.current()?.id;
     this.timer && clearTimeout(this.timer);
     let remoteEle = document.getElementById('vice-video');
     (remoteEle as any).style.display = 'none';
     //获取频道token记录
-    if (room?.get('user')?.id === Parse.User.current()?.id) {
+    if (this.isAnchor) {
       this.UID = 111111;
       let uid = Parse.User.current()?.id;
       if (!uid) {
@@ -185,11 +190,13 @@ export class LiveService {
         // await this.client.setClientRole('host');
         console.log('进入频道当前uid:', uid);
         this.connection_state = this.client.connectionState;
-        if (this.room?.get('user')?.id !== Parse.User.current()?.id) {
+        if (!this.isAnchor) {
           // 观众进入直播间,创建直播记录
           await this.createLiveLog(uid);
+        } else {
+          //主播进入直播间直接发送自己推流
+          await this.publishSelf();
         }
-        await this.publishSelf();
         await this.joinReady();
         this.afterJoin();
       })
@@ -199,26 +206,31 @@ export class LiveService {
   }
   /* 发布本地视频 */
   async publishSelf() {
-    let data = await Promise.all([
-      /* 创建音频和视频轨道 */
-      AgoraRTC.createMicrophoneAudioTrack(this.currentUsedDevice.audioDevice),
-      AgoraRTC.createCameraVideoTrack(this.currentUsedDevice.videoDevice),
-    ]);
-    this.localTracks.audioTrack = data[0];
-    this.localTracks.videoTrack = data[1];
-    // console.log(this.localTracks);
-    let remoteEle = document.getElementById('vice-video');
-    if (remoteEle) {
-      remoteEle.textContent = '';
-      remoteEle.style.display = 'block';
-    }
-    this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
-    if (this.tools['audio']) {
-      this.localTracks.audioTrack.setEnabled(false);
-    } else {
-      this.localTracks.audioTrack.setEnabled(true);
+    try {
+      let data = await Promise.all([
+        /* 创建音频和视频轨道 */
+        AgoraRTC.createMicrophoneAudioTrack(this.currentUsedDevice.audioDevice),
+        AgoraRTC.createCameraVideoTrack(this.currentUsedDevice.videoDevice),
+      ]);
+      this.localTracks.audioTrack = data[0];
+      this.localTracks.videoTrack = data[1];
+      // console.log(this.localTracks);
+      let remoteEle = document.getElementById('vice-video');
+      if (remoteEle) {
+        remoteEle.textContent = '';
+        remoteEle.style.display = 'block';
+      }
+      this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
+      if (this.tools['audio']) {
+        this.localTracks.audioTrack.setEnabled(false);
+      } else {
+        this.localTracks.audioTrack.setEnabled(true);
+      }
+      await this.client.publish(Object.values(this.localTracks));
+    } catch (err) {
+      console.log('发布本地视频失败:', err);
+      this.alertTips('发布本地视频失败:');
     }
-    await this.client.publish(Object.values(this.localTracks));
   }
   /* 订阅远程视频 */
   async joinReady() {
@@ -268,8 +280,8 @@ export class LiveService {
           remoteEle.textContent = '对方离开直播间';
         }
         //主播离开,停止计时计费
-        if(this.room?.get('user').id !== Parse.User.current()?.id){
-          this.client.leave()
+        if (!this.isAnchor) {
+          this.client.leave();
         }
         this.alertTips('对方已离开直播间');
       }
@@ -278,10 +290,15 @@ export class LiveService {
       'connection-state-change',
       (curState: any, prevState: any) => {
         this.connection_state = curState;
-        if(curState == 'RECONNECTING' || curState == 'DISCONNECTED' || curState == 'DISCONNECTING'){
-          this.timer && clearInterval(this.timer);
+        if (
+          curState == 'RECONNECTING' ||
+          curState == 'DISCONNECTED' ||
+          curState == 'DISCONNECTING'
+        ) {
+          this.timer && clearTimeout(this.timer);
+          this.timer_countdown && clearInterval(this.timer_countdown);
         }
-        console.log(this.connection_state);
+        console.log('状态变更:', this.connection_state);
         console.log(prevState);
       }
     );
@@ -318,14 +335,29 @@ export class LiveService {
   /* 连线成功立即创建直播记录,同步获取剩余可通话时长,并且开始计时 */
   async afterJoin() {
     this.timer && clearTimeout(this.timer);
+    this.timer_countdown && clearInterval(this.timer_countdown);
     if (this.client.remoteUsers.length > 0) {
-      if (this.room?.get('user')?.id === Parse.User.current()?.id) {
+      if (this.isAnchor) {
         //如果是主播,进入获取remoteUsers.user获取livelog再获取对方剩余通话时长
-        this.getLiveLog()
+        this.getLiveLog();
       } else {
-        //首次进入至少计时2分钟,不足2分钟按2分钟计算扣时
-        await this.get_duration();
-        this.computeDuration(60000 * 2);
+        let query = new Parse.Query('LiveLog');
+        query.equalTo('objectId', this.liveLog?.id);
+        query.equalTo('isLive', true);
+        query.select('objectId');
+        const resultData = await query.first();
+        if (resultData?.id) {
+          //首次进入至少计时2分钟,不足2分钟按2分钟计算扣时
+          await this.publishSelf();
+          await this.get_duration();
+          this.countdown = this.surplusNumber; // 初始化倒计时
+          this.startCountdown();
+          this.computeDuration(60000 * 2);
+        } else {
+          this.timer = setTimeout(() => {
+            this.afterJoin();
+          }, 1000);
+        }
       }
     } else {
       this.timer = setTimeout(() => {
@@ -333,48 +365,62 @@ export class LiveService {
       }, 1000);
     }
   }
-  async getLiveLog(){
-    let uid = this.client.remoteUsers[0].uid
-    this.timer && clearInterval(this.timer);
-    let query = new Parse.Query('LiveLog')
-    query.equalTo('uid',String(uid))
-    query.equalTo('room',this.room?.id)
-    query.notEqualTo('isDeleted',true)
-    query.notEqualTo('isLive',true)
-    query.descending('createdAt')
-    this.liveLog = await query.first()
-    if(this.liveLog?.id){
-      this.liveLog?.set('isLive',true)
-      await this.liveLog?.save()
-      this.get_duration()
-      return
+  async getLiveLog() {
+    let uid = this.client.remoteUsers[0].uid;
+    this.timer && clearTimeout(this.timer);
+    let query = new Parse.Query('LiveLog');
+    query.equalTo('uid', String(uid));
+    query.equalTo('room', this.room?.id);
+    query.notEqualTo('isDeleted', true);
+    query.notEqualTo('isLive', true);
+    query.descending('createdAt');
+    this.liveLog = await query.first();
+    if (this.liveLog?.id) {
+      this.liveLog?.set('isLive', true);
+      await this.liveLog?.save();
+      this.get_duration();
+      return;
     }
     this.timer = setTimeout(() => {
       this.getLiveLog();
     }, 1000);
   }
   async get_duration() {
-    let url = 'http://localhost:7337/api/ailiao/remain_second';
+    let url = 'https://server.fmode.cn/api/ailiao/remain_second';
     let params = {
       rid: this.room?.id,
       uid: this.liveLog?.get('user')?.id || this.liveLog?.get('user')?.objectId,
     };
     let data = await this.http.httpRequst(url, params, 'POST');
     console.log(data);
-    this.surplusNumber = data.data.secoud ?? 0;
+    this.surplusNumber = data.data ?? 0;
+  }
+  startCountdown() {
+    this.timer_countdown = setInterval(() => {
+      if (this.countdown > 0) {
+        this.countdown--;
+        console.log(this.countdown);
+      } else {
+        clearInterval(this.timer_countdown);
+        this.alertTips('通话时间结束');
+        this.client.leave(); // 结束通话
+      }
+    }, 1000);
   }
-
   /* 开始计时 */
   async computeDuration(num?: number) {
     //每10秒保存一次数据
-    this.timer && clearInterval(this.timer);
-    let url = 'http://localhost:7337/api/ailiao/count/duration';
+    this.timer && clearTimeout(this.timer);
+    let p = JSON.parse(this.profile);
+    console.log(p);
+    let url = 'https://server.fmode.cn/api/ailiao/count/duration';
     let params = {
       company: this.company,
-      profile: this.profile?.id,
+      profile: p?.objectId,
       rid: this.room?.id,
       uid: Parse.User.current()?.id,
-      duration: num ? num/1000 : 10,
+      duration: num ? num / 1000 : 10,
+      logid: this.liveLog?.id,
     };
     let data = await this.http.httpRequst(url, params, 'POST');
     console.log(data);
@@ -478,7 +524,6 @@ export class LiveService {
         {
           text: '确认',
           handler: () => {
-            console.log('Confirm Cancel: blah');
             callBack && callBack();
           },
         },