warrior 3 months ago
parent
commit
c65a7b5f24

+ 3 - 3
projects/live-app/src/app/components/live/live.component.html

@@ -1,4 +1,4 @@
-<div class="video_box" id="video-box">
+<div class="video_box" id="video-box" (click)="onTouch()">
   <div class="camera_box">
     <!-- 主屏 -->
     <div
@@ -6,7 +6,7 @@
       id="video"
       width="100%"
       height="100%"
-      (click)="onChangeScreen('big')"
+      (click)="onChangeScreen('big',$event)"
     >
       等待连接
     </div>
@@ -16,7 +16,7 @@
       id="vice-video"
       width="100%"
       height="100%"
-      (click)="onChangeScreen('small')"
+      (click)="onChangeScreen('small',$event)"
     >
       网络不佳
     </div>

+ 32 - 138
projects/live-app/src/app/components/live/live.component.ts

@@ -1,7 +1,8 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, EventEmitter, OnInit, Output, output } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 import * as Parse from 'parse';
 import {
+  AlertController,
   IonicModule,
   LoadingController,
   ToastController,
@@ -9,8 +10,7 @@ import {
 import { ActivatedRoute } from '@angular/router';
 import { AiChatService } from '../../../services/aichart.service';
 import { HttpService } from '../../../services/http.service';
-declare const AgoraRTC: any;
-
+import { LiveService } from '../../../services/live.service';
 @Component({
   selector: 'app-live',
   templateUrl: './live.component.html',
@@ -19,38 +19,23 @@ declare const AgoraRTC: any;
   imports: [IonicModule, FormsModule],
 })
 export class LiveComponent implements OnInit {
+  @Output() touch = new EventEmitter();
   profile?: Parse.Object;
   rid?: string;
   room?: Parse.Object;
-  client: any; //客户端
-  options: {
-    appid: string;
-    channel: string;
-    uid: string | undefined;
-    token: string;
-  } = {
-    appid: '',
-    channel: '',
-    uid: '',
-    token: '',
-  };
-  localTracks: any = {
-    audioTrack: null,
-    videoTrack: null,
-  };
   changeScreen: boolean = false; //大小屏切换
   constructor(
     public toastController: ToastController,
     private loadingCtrl: LoadingController,
     private activateRoute: ActivatedRoute,
-    private aiSer: AiChatService,
-    private http: HttpService
+    private alertController: AlertController,
+    private http: HttpService,
+    private liveService: LiveService
   ) {}
 
   ngOnInit() {
-    this.client = AgoraRTC.createClient({ mode: 'rtc', codec: 'h264' });
-    AgoraRTC.enableLogUpload();
-    this.getDevices();
+    this.liveService.initAgora();
+    this.liveService.getDevices();
     this.activateRoute.paramMap.subscribe(async (params) => {
       let rid: any = params.get('rid');
       this.rid = rid;
@@ -60,136 +45,45 @@ export class LiveComponent implements OnInit {
       this.getRoom();
     });
   }
-  // 获取所有音视频设备
-  getDevices() {
-    AgoraRTC.getDevices()
-      .then((devices: any) => {
-        const audioDevices = devices.filter(function (device: any) {
-          return device.kind === 'audioinput';
-        });
-        const videoDevices = devices.filter(function (device: any) {
-          return device.kind === 'videoinput';
-        });
-        let selectedMicrophoneId = audioDevices[0].deviceId;
-        let selectedCameraId = videoDevices[0].deviceId;
-        return Promise.all([
-          AgoraRTC.createCameraVideoTrack({ cameraId: selectedCameraId }),
-          AgoraRTC.createMicrophoneAudioTrack({
-            microphoneId: selectedMicrophoneId,
-          }),
-        ]);
-      })
-      .then((tracks: any) => {
-        console.log('createCameraVideoTrack', tracks);
-      })
-      .catch((err: any) => {
-        console.log(err);
-      });
-  }
+
   async getRoom() {
     let query = new Parse.Query('Room');
     query.equalTo('objectId', this.rid);
     query.notEqualTo('isDeleted', true);
-    query.include('user');
+    query.include('user', 'profile');
     this.room = await query.first();
-    let queryProfile = new Parse.Query('Profile');
-    queryProfile.equalTo('user', this.room?.get('user').id);
-    queryProfile.notEqualTo('isDeleted', true);
-    this.profile = await queryProfile.first();
-    this.getToken();
-  }
-  async getToken() {
-    let baseurl = 'https://server.fmode.cn/api/webrtc/build_token';
-    let reqBody = {
-      company: '9aMy8gAuey', // this.aiSer.company,
-      profile: this.profile?.id,
-      channelName: this.profile?.id,
-      // department: localStorage.getItem('department'),
-      // exam: localStorage.getItem('exam'),
-    };
-    let data: any = await this.http.httpRequst(baseurl, reqBody, 'POST');
-    console.log(data);
-    if (data.code == 200) {
-      (this.options.token = data.data.token),
-        (this.options.appid = data.data.appid),
-        (this.options.channel = this.profile?.id ?? ''),
-        (this.options.uid = this.profile?.id);
-      // await this.join();
-    }
-  }
-  // 进入频道
-  async join() {
-    let data = await Promise.all([
-      this.client.join(
-        this.options.appid,
-        this.options.channel,
-        this.options.token,
-        111111
-      ),
-      /* 创建音频和视频轨道 */
-      AgoraRTC.createMicrophoneAudioTrack(),
-      AgoraRTC.createCameraVideoTrack(),
-    ]);
-    // await this.client.setClientRole('host');
-    this.localTracks.audioTrack = data[1];
-    this.localTracks.videoTrack = data[2];
-    let remoteEle = document.getElementById('vice-video');
-    if (remoteEle) {
-      remoteEle.textContent = '';
+    // let queryProfile = new Parse.Query('Profile');
+    // queryProfile.equalTo('user', this.room?.get('user').id);
+    // queryProfile.notEqualTo('isDeleted', true);
+    // this.profile = await queryProfile.first();
+    if (this.room?.id) {
+      await this.liveService.getToken(this.room);
+      this.liveService.join();
+    } else {
+      const alert = await this.alertController.create({
+        header: '提示',
+        message: '房间号不存在',
+        buttons: ['Action'],
+      });
+      await alert.present();
     }
-    this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
-    let publish = await this.client.publish(Object.values(this.localTracks));
-    this.joinReady();
-  }
-  /* 订阅远程视频 */
-  async joinReady() {
-    console.log(this.client.remoteUsers);
-    let wxRemoteUsers = this.client.remoteUsers.find((item: any) => {
-      if (item.uid && item._video_added_) {
-        return item;
-      }
-    });
-    console.log(wxRemoteUsers);
-    this.client.on('user-joined', (user: any) => {
-      console.log(user, `${user.uid} 加入频道`);
-    });
-    this.client.on('user-published', async (user: any, mediaType: any) => {
-      console.log('用户推流成功');
-      // if (user.uid == 333333) {
-      await this.client.subscribe(user, mediaType);
-      // }
-      let remoteEle = document.getElementById('video');
-      if (remoteEle) {
-        remoteEle.textContent = '';
-      }
-      if (mediaType === 'video') {
-        user.videoTrack.play(`video`);
-      }
-      if (mediaType === 'audio') {
-        user.audioTrack.play();
-      }
-    });
-    this.client.on('user-unpublished', (user: any) => {
-      let remoteEle = document.getElementById('video');
-      if (remoteEle) {
-        remoteEle.textContent = '对方离开直播间';
-      }
-      // if (user.uid == 333333) {
-      console.log('用户取消推流');
-      // }
-    });
   }
   /* 监听屏幕切换 */
-  onChangeScreen(type: string) {
+  onChangeScreen(type: string, e: any) {
     if (type == 'big' && this.changeScreen) {
+      e.cancelBubble = true;
       this.changeScreen = !this.changeScreen;
     } else if (type == 'small' && !this.changeScreen) {
+      e.cancelBubble = true;
       this.changeScreen = !this.changeScreen;
     }
   }
+  onTouch() {
+    this.touch.emit();
+  }
   ngOnDestroy(): void {
     /* 离开房间 */
-    this.client.leave();
+    this.liveService.client.leave();
     console.log(111);
   }
 }

+ 24 - 17
projects/live-app/src/moduls/live/link-page/link-page.component.html

@@ -19,32 +19,39 @@
     <div class="report">
       <ion-icon name="warning-outline"></ion-icon>
     </div>
-    <div class="exit" (click)="onExit()">
+    <div class="exit" (click)="endCall($event)">
       <ion-icon name="enter-outline"></ion-icon>
     </div>
   </div>
-  <app-live></app-live>
-  <div class="tools">
+  <app-live (touch)="showTool = !showTool"></app-live>
+  <div
+    class="tools"
+    (click)="showTool = !showTool"
+    [style.visibility]="showTool ? 'visible' : 'hidden'"
+  >
     <div class="row">
-      <div class="row-li">
-        <div class="icon-box">
-          <ion-icon class="icon" name="mic-circle"></ion-icon>
+      <div class="row-li" (click)="onChangeLiveStatus($event, 'audio')">
+        <div [ngClass]="{ 'action-icon': audio, 'icon-box': true }">
+          <ion-icon class="icon" name="mic-off"></ion-icon>
         </div>
-        <div class="label">麦克风已关</div>
+        <div class="label">麦克风{{ audio ? "已关" : "已开" }}</div>
       </div>
     </div>
     <div class="row">
-      <div class="row-li">
-        <div class="icon-box">
-          <ion-icon class="icon" name="notifications"></ion-icon>
+      <div class="row-li" (click)="onChangeLiveStatus($event, 'camera')">
+        <div [ngClass]="{ 'action-icon': camera, 'icon-box': true }">
+          <ion-icon name="camera-reverse"></ion-icon>
         </div>
-        <div class="label">麦克风已关</div>
+        <div class="label">旋转摄像头</div>
       </div>
-      <div class="row-li">
-        <div class="icon-box">
+      <div class="row-li" (click)="onChangeLiveStatus($event, 'mute')">
+        <div
+          class="icon-box"
+          [ngClass]="{ 'action-icon': mute, 'icon-box': true }"
+        >
           <ion-icon class="icon" name="notifications-off"></ion-icon>
         </div>
-        <div class="label">麦克风已关</div>
+        <div class="label">{{ mute ? "已静音" : "静音" }}</div>
       </div>
     </div>
     <div class="row">
@@ -54,8 +61,8 @@
         </div>
         <div class="label">聊天</div>
       </div>
-      <div class="row-li">
-        <div class="icon-box">
+      <div class="row-li" (click)="endCall($event)">
+        <div class="icon-box" style="background-color: rgba(0, 0, 0, 0.0);">
           <img class="icon" src="/img/挂断.png" alt="" class="icon-img" />
         </div>
         <div class="label">挂断</div>
@@ -64,7 +71,7 @@
         <div class="icon-box">
           <ion-icon class="icon" name="gift"></ion-icon>
         </div>
-        <div class="label">麦克风已关</div>
+        <div class="label">礼物</div>
       </div>
     </div>
   </div>

+ 10 - 0
projects/live-app/src/moduls/live/link-page/link-page.component.scss

@@ -97,11 +97,21 @@
             color: white;
             font-size: 30px;
           }
+          .icon-tool{
+            width: 30px;
+            height: 30px;
+          }
           img{
             width: 50px;
             height: 50px;
           }
         }
+        .action-icon{
+          background-color: #ffffff;
+          ion-icon{
+            color: black !important;
+          }
+        }
       }
     }
   }

+ 48 - 6
projects/live-app/src/moduls/live/link-page/link-page.component.ts

@@ -1,7 +1,9 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import * as Parse from 'parse';
 import {
+  AlertController,
   IonicModule,
   LoadingController,
   ModalController,
@@ -9,23 +11,30 @@ import {
 } from '@ionic/angular';
 import { ActivatedRoute } from '@angular/router';
 import { LiveComponent } from '../../../app/components/live/live.component';
+import { LiveService } from '../../../services/live.service';
 @Component({
   selector: 'app-link-page',
   templateUrl: './link-page.component.html',
   styleUrls: ['./link-page.component.scss'],
   standalone: true,
-  imports: [IonicModule, FormsModule,LiveComponent],
+  imports: [IonicModule, FormsModule, LiveComponent, CommonModule],
 })
 export class LinkPageComponent implements OnInit {
+  @ViewChild('live') live!: LiveComponent;
   currentUser?: Parse.Object = Parse.User.current(); //当前登录用户
   rid?: string;
   room?: Parse.Object;
   isFollow: boolean = false;
-
+  showTool: boolean = true; // 是否显示工具栏
+  audio: boolean = false; //是否关闭音频
+  camera: boolean = false; //是否切换摄像头
+  mute: boolean = false; //是否静音
   constructor(
     public toastController: ToastController,
     private loadingCtrl: LoadingController,
-    private activateRoute: ActivatedRoute
+    private alertController: AlertController,
+    private activateRoute: ActivatedRoute,
+    private liveService: LiveService
   ) {}
 
   ngOnInit() {
@@ -93,7 +102,40 @@ export class LinkPageComponent implements OnInit {
     await profileRadar?.save();
     this.isFollow = !this.isFollow;
   }
-  onExit(){
-    history.back()
+  /* 直播状态 */
+  onChangeLiveStatus(e: any, type: string) {
+    e.cancelBubble = true;
+    if (type == 'audio' || type == 'camera' || type == 'mute') {
+      this[type] = !this[type];
+    }
+  }
+  /* 结束直播 */
+  async endCall(e: any){
+    e.cancelBubble = true;
+    const alert = await this.alertController.create({
+      cssClass: 'my-custom-class',
+      header: '退出提示',
+      message: '你确定退出登录吗?',
+      buttons: [
+        {
+          text: '确定',
+          role: 'cancel',
+          cssClass: 'secondary',
+          handler: (blah) => {
+            console.log('Confirm Cancel: blah');
+            this.onExit()
+          },
+        },
+        {
+          text: '取消',
+          handler: () => {},
+        },
+      ],
+    });
+    await alert.present();
+  }
+  onExit() {
+    this.liveService.client.leave();
+    history.back();
   }
 }

+ 2 - 2
projects/live-app/src/moduls/tabs/home/home.component.html

@@ -43,14 +43,14 @@
     @for (item of roomList; track $index) {
     <div
       class="list-row"
-      (click)="toUrl('live/link-room/' + item.id)"
+      (click)="toUrl('user/profile/' + item.get('user').id)"
       [style.background-image]="'url(' + item?.get('cover') + ')'"
     >
       <div class="title-tag">在线聊天</div>
       <div class="live-tag">
         <!-- <span></span>  -->
         <img src="/img/live.gif" alt="" />
-        直播中
+        在线
       </div>
       <div class="room-footer">
         <div class="user">

+ 1 - 1
projects/live-app/src/moduls/tabs/home/home.component.scss

@@ -136,7 +136,7 @@
           align-items: center;
           .row-li {
             display: flex;
-            align-content: center;
+            align-items: center;
             img {
               width: 12px;
               height: 12px;

+ 0 - 1
projects/live-app/src/moduls/tabs/home/home.component.ts

@@ -1,6 +1,5 @@
 import {
   Component,
-  CUSTOM_ELEMENTS_SCHEMA,
   OnInit,
   ViewChild,
 } from '@angular/core';

+ 13 - 7
projects/live-app/src/moduls/tabs/tabs/tabs.component.ts

@@ -18,12 +18,16 @@ import { AlertController } from '@ionic/angular';
 })
 export class TabsComponent implements OnInit {
   @Input('tabsOption') tabsOption: any = {};
+  company: any = window.localStorage.getItem('company');
   // @ViewChild('tabs',{static:true}) tabs;
   constructor(
     private router: Router,
-    private CDR: ChangeDetectorRef,
-    public alertController: AlertController
-  ) {}
+    private alertController: AlertController
+  ) {
+    console.log(11);
+    this.active = Number(localStorage.getItem('active')) || 0
+    this.presentAlert();
+  }
 
   option: any = [
     {
@@ -58,10 +62,10 @@ export class TabsComponent implements OnInit {
     },
   ];
   show: any;
-  active: number = Number(localStorage.getItem('active')) || 0;
+  active: number = 0;
+
+  ngOnInit() {
 
-  public ngOnInit() {
-    this.presentAlert();
   }
 
   async presentAlert() {
@@ -69,10 +73,12 @@ export class TabsComponent implements OnInit {
     if (profile) {
       return;
     }
-    let uid = Parse.User.current() && Parse.User.current()?.id;
+    let uid = Parse.User.current()?.id;
     let query = new Parse.Query('Profile');
     query.equalTo('user', uid);
     query.equalTo('isCross', true);
+    query.equalTo('company', this.company);
+    query.notEqualTo('isDeleted', true);
     let res = await query.first();
     if (res && res.id) {
       localStorage.setItem('profile', res.id);

+ 3 - 3
projects/live-app/src/moduls/user/certification/certification.component.html

@@ -1,4 +1,4 @@
-<nav title="实名认证"></nav>
+<nav title="主播认证"></nav>
 <ion-content class="content">
   <div class="hred">
     <div class="hred-left">
@@ -13,7 +13,7 @@
   <div class="tips">
     <img
       class="tips-img"
-      src="https://cloud.file.futurestack.cn/game-auth.png"
+      src="http://cloud.file.futurestack.cn/game-auth.png"
       alt=""
     />
     <div class="text">您已完成认证</div>
@@ -48,7 +48,6 @@
     />
   </div>
   <div class="footer" (click)="check()">提交</div>
-  }
   <div class="agreement">
     <ion-checkbox color="primary" [(ngModel)]="agreement"></ion-checkbox>
     <div class="content">
@@ -57,4 +56,5 @@
       >
     </div>
   </div>
+  }
 </ion-content>

+ 1 - 1
projects/live-app/src/moduls/user/certification/certification.component.scss

@@ -44,7 +44,7 @@
     font-size: 4.2667vw;
     font-family: Source Han Sans CN;
     font-weight: 500;
-    color: #ffffff;
+    // color: #ffffff;
     justify-content: center;
     align-items: center;
     flex-direction: column;

+ 105 - 85
projects/live-app/src/moduls/user/certification/certification.component.ts

@@ -1,8 +1,13 @@
 import { Component, OnInit } from '@angular/core';
 import { FormsModule } from '@angular/forms';
-import { IonicModule, LoadingController, ModalController, ToastController } from '@ionic/angular';
+import {
+  IonicModule,
+  LoadingController,
+  ModalController,
+  ToastController,
+} from '@ionic/angular';
 import { HttpService } from '../../../services/http.service';
-import * as utils from '../../../services/utils'
+import * as utils from '../../../services/utils';
 import { AgreementComponent } from '../../login/agreement/agreement.component';
 import * as Parse from 'parse';
 import { NavComponent } from '../../../app/components/nav/nav.component';
@@ -12,32 +17,32 @@ import { NavComponent } from '../../../app/components/nav/nav.component';
   templateUrl: './certification.component.html',
   styleUrls: ['./certification.component.scss'],
   standalone: true,
-  imports: [IonicModule,FormsModule,NavComponent],
+  imports: [IonicModule, FormsModule, NavComponent],
 })
 export class CertificationComponent implements OnInit {
-
-  name: string = ''
-  idCard: string = ''
-  title: string = '根据相关法律法规要求,用户需先进行实名认证,方可使用本平台。请尽快完成下方实名认证,本平台将对您的信息严格保密。'
-  company:any = window.localStorage.getItem("company")
-  isReal: boolean = false
-  loading: any
-  time: any //节流
-  secretName: any
-  secretIdCard:any
+  name: string = '';
+  idCard: string = '';
+  title: string =
+    '根据相关法律法规要求,用户需先进行实名认证,方可使用本平台。请尽快完成下方实名认证,本平台将对您的信息严格保密。';
+  company: any = window.localStorage.getItem('company');
+  isReal: boolean = false;
+  loading: any;
+  time: any; //节流
+  secretName: any;
+  secretIdCard: any;
   agreement: boolean = false;
   registerAgreement: any;
-
+  profile?: Parse.Object;
   constructor(
     private service: HttpService,
     public loadCtrl: LoadingController,
     private modalController: ModalController,
-    public toastController: ToastController,
-  ) { }
+    public toastController: ToastController
+  ) {}
 
   ngOnInit() {
-    this.getAgreement()
-    this.getProfile()
+    this.getAgreement();
+    this.getProfile();
   }
   getAgreement() {
     let Agreement = new Parse.Query('ContractAgreement');
@@ -49,15 +54,15 @@ export class CertificationComponent implements OnInit {
     });
   }
   async getProfile() {
-    let uid = Parse.User.current()?.id
-    let query = new Parse.Query("Profile")
-    query.equalTo("user", uid)
-    query.equalTo("isCross", true)
-    let res = await query.first()
-    if (res && res.id) {
-      this.isReal = true
-      this.secretIdCard = res.get('idcard').slice(0,6)
-      this.secretName = res.get('name').slice(0,1)
+    let uid = Parse.User.current()?.id;
+    let query = new Parse.Query('Profile');
+    query.equalTo('user', uid);
+    query.notEqualTo('isDeleted', true);
+    this.profile = await query.first();
+    if (this.profile?.id) {
+      this.isReal = this.profile.get('isCross');
+      this.secretIdCard = this.profile.get('idcard').slice(0, 6);
+      this.secretName = this.profile.get('name').slice(0, 1);
     }
   }
   async showAgreement() {
@@ -71,93 +76,108 @@ export class CertificationComponent implements OnInit {
     return await modal.present();
   }
 
-  async presentToast(title:string, time:number, color:string) {
+  async presentToast(title: string, time: number, color: string) {
     const toast = await this.toastController.create({
       message: title,
       duration: time,
-      color: color
+      color: color,
     });
     toast.present();
   }
 
   async check() {
-    this.loading = await this.loadCtrl.create()
-    this.loading.present()
-
-    this.time && clearTimeout(this.time)
-
+    this.loading = await this.loadCtrl.create();
+    this.loading.present();
+    this.time && clearTimeout(this.time);
     this.time = setTimeout(async () => {
       console.log(this.name, this.idCard);
       if (!this.idCard || this.idCard.length != 18 || !this.name) {
-        this.loading.dismiss()
-        await this.presentToast('格式错误', 1500, 'danger')
-        return
+        this.loading.dismiss();
+        await this.presentToast('格式错误', 1500, 'danger');
+        return;
       }
-      let pass = utils.fun.IdentityCodeValid(this.idCard)
+      let pass = utils.fun.IdentityCodeValid(this.idCard);
       console.log(pass);
       if (!pass) {
-        this.loading.dismiss()
-        await this.presentToast('认证失败,请填写真实的身份信息', 1500, 'danger')
-        return
+        this.loading.dismiss();
+        await this.presentToast(
+          '认证失败,请填写真实的身份信息',
+          1500,
+          'danger'
+        );
+        return;
       }
 
-      let res: any = await this.service.postAuth(this.company, this.idCard, this.name)
+      let res: any = await this.service.postAuth(
+        this.company,
+        this.idCard,
+        this.name
+      );
       if (res.code == 1) {
-        let { isok } = res.data.result
+        let { isok } = res.data.result;
         console.log(isok);
         if (isok) {
-          let { sex } = res.data.result.IdCardInfor
-          this.anthProfile(sex)
-          return
+          let { sex } = res.data.result.IdCardInfor;
+          this.anthProfile(sex);
+          return;
         }
-        this.loading.dismiss()
-        await this.presentToast('认证失败,请填写真实的身份信息', 1500, 'danger')
+        this.loading.dismiss();
+        await this.presentToast(
+          '认证失败,请填写真实的身份信息',
+          1500,
+          'danger'
+        );
       } else {
-        this.loading.dismiss()
-        await this.presentToast('认证失败', 1500, 'danger')
+        this.loading.dismiss();
+        await this.presentToast('认证失败', 1500, 'danger');
       }
     }, 500);
   }
 
   async anthProfile(sex: string) {
-    let uid = Parse.User.current()?.id
-    let query = new Parse.Query("Profile")
-    query.equalTo("idcard", this.idCard)
-    query.equalTo("company", this.company)
-    let res = await query.first()
+    let user = Parse.User.current();
+    let query = new Parse.Query('Profile');
+    query.equalTo('idcard', this.idCard);
+    query.equalTo('company', this.company);
+    query.notEqualTo('isDeleted', true);
+    let res = await query.first();
     if (res && res.id) {
-      this.loading.dismiss()
-      await this.presentToast('认证失败,该身份已被认证', 1500, 'danger')
-      return
+      this.loading.dismiss();
+      await this.presentToast('认证失败,该身份已被认证', 1500, 'danger');
+      return;
     }
-
-    let obj = Parse.Object.extend("Profile")
-    let profile = new obj()
-    profile.set("company", {
-      __type: "Pointer",
-      className: "Company",
-      objectId: this.company,
-    })
-    profile.set("user", {
-      __type: "Pointer",
-      className: "_User",
-      objectId: uid,
-    })
-    profile.set("idcard", this.idCard)
-    profile.set("name", this.name)
-    profile.set("isCross", true)
-    profile.set("sex", sex)
-    let r = await profile.save()
-    if (r && r.id) {
-      console.log(r.id);
-      localStorage.setItem("profile", r.id)
-      this.loading.dismiss()
-      this.isReal = true
-      await this.presentToast('认证成功', 1500, 'primary')
+    user?.set('sex', sex);
+    user?.set('idcard', this.idCard);
+    user?.set('name', this.name);
+    await user?.save();
+    if (!this.profile?.id) {
+      let obj = Parse.Object.extend('Profile');
+      this.profile = new obj();
+      this.profile?.set('company', {
+        __type: 'Pointer',
+        className: 'Company',
+        objectId: this.company,
+      });
+      this.profile?.set('user', {
+        __type: 'Pointer',
+        className: '_User',
+        objectId: user?.id,
+      });
+      this.profile?.set('mobile', Parse.User.current()?.get('mobile'));
+    }
+    this.profile?.set('idcard', this.idCard);
+    this.profile?.set('name', this.name);
+    this.profile?.set('sex', sex);
+    this.profile?.set('isCross', true);
+    await this.profile?.save();
+    if (this.profile?.id) {
+      localStorage.setItem('profile', this.profile.id);
+      this.loading.dismiss();
+      this.isReal = true;
+      await this.presentToast('认证成功', 1500, 'primary');
       setTimeout(() => {
-        history.back()
-      }, 1800);
+        history.back();
+      }, 1500);
     }
   }
-
 }

+ 9 - 9
projects/live-app/src/moduls/user/setting/setting.component.ts

@@ -104,16 +104,16 @@ export class SettingComponent implements OnInit {
     if (!this.profile?.id) {
       let obj = Parse.Object.extend('Profile');
       this.profile = new obj();
-      this.profile?.set('mobile', Parse.User.current()?.get('mobile'));
-      this.profile?.set('sex', this.formData.sex);
-      this.profile?.set('birthdate', this.formData.age);
+      this.profile?.set('user', Parse.User.current()?.toPointer());
+      this.profile?.set('company', {
+        __type: 'Pointer',
+        className: 'Company',
+        objectId: this.authServ.company,
+      });
     }
-    this.profile?.set('user', Parse.User.current()?.toPointer());
-    this.profile?.set('company', {
-      __type: 'Pointer',
-      className: 'Company',
-      objectId: this.authServ.company,
-    });
+    this.profile?.set('mobile', Parse.User.current()?.get('mobile'));
+    this.profile?.set('sex', this.formData.sex);
+    this.profile?.set('birthdate', this.formData.age);
     this.profile?.set('remark', this.formData.remark);
     await this.profile?.save();
     this.loading.dismiss();

+ 2 - 2
projects/live-app/src/services/auth.service.ts

@@ -25,12 +25,12 @@ export class AuthService {
         nickname: nickname,
       })
         .then((authData) => {
-          console.log(authData);
+          // console.log(authData);
           if (authData) {
             // let sessionToken = authData.get('sessionToken');
             Parse.User.become(authData)
               .then(async (data) => {
-                console.log(data);
+                // console.log(data);
                 this.redirectUrl = this.redirectUrl ? this.redirectUrl : 'tabs';
                 this.router.navigate([this.redirectUrl])
                 resolve(data);

+ 171 - 0
projects/live-app/src/services/live.service.ts

@@ -0,0 +1,171 @@
+import { Injectable } from '@angular/core';
+import * as Parse from 'parse';
+import { AiChatService } from './aichart.service';
+import { HttpService } from './http.service';
+declare const AgoraRTC: any;
+
+@Injectable({
+  providedIn: 'root',
+})
+export class LiveService {
+  options: {
+    appid: string;
+    channel: string;
+    token: string;
+  } = {
+    appid: '71d3357d920d4352b39ec8b8d26a7cb9',
+    channel: '',
+    token: '',
+  };
+  localTracks: any = {
+    audioTrack: null,
+    videoTrack: null,
+  };
+  rid?: string; //房间id(channel)
+  profile?: Parse.Object;
+  client: any; //客户端
+  company: string = '';
+  UID:any
+  constructor(private http: HttpService, private aiServ: AiChatService) {
+    this.company = this.aiServ.company;
+    this.getProfile();
+  }
+  async getProfile() {
+    let queryProfile = new Parse.Query('Profile');
+    queryProfile.equalTo('user', Parse.User.current()?.id);
+    queryProfile.notEqualTo('isDeleted', true);
+    queryProfile.equalTo('isCross', true);
+    this.profile = await queryProfile.first();
+  }
+  /* 初始化Agora */
+  initAgora() {
+    this.client = AgoraRTC.createClient({ mode: 'rtc', codec: 'h264' });
+    AgoraRTC.enableLogUpload();
+  }
+  // 获取所有音视频设备
+  getDevices() {
+    AgoraRTC.getDevices()
+      .then((devices: any) => {
+        const audioDevices = devices.filter(function (device: any) {
+          return device.kind === 'audioinput';
+        });
+        const videoDevices = devices.filter(function (device: any) {
+          return device.kind === 'videoinput';
+        });
+        let selectedMicrophoneId = audioDevices[0].deviceId;
+        let selectedCameraId = videoDevices[0].deviceId;
+        return Promise.all([
+          AgoraRTC.createCameraVideoTrack({ cameraId: selectedCameraId }),
+          AgoraRTC.createMicrophoneAudioTrack({
+            microphoneId: selectedMicrophoneId,
+          }),
+        ]);
+      })
+      .then((tracks: any) => {
+        console.log('createCameraVideoTrack', tracks);
+      })
+      .catch((err: any) => {
+        console.log(err);
+      });
+  }
+  async getToken(room: Parse.Object) {
+    //获取频道token记录
+    if (room?.get('profile').id == this.profile?.id) {
+      this.UID = 111111
+      let uid = Parse.User.current()?.id;
+      if (!uid) {
+        return;
+      }
+      let baseurl = 'https://server.fmode.cn/api/webrtc/build_token';
+      let reqBody = {
+        company: this.company, // this.aiSer.company,
+        profile: this.profile?.id,
+        channelName: this.profile?.id,
+      };
+      let data: any = await this.http.httpRequst(baseurl, reqBody, 'POST');
+      console.log(data);
+      if (data.code == 200) {
+        this.options.token = data.data.token;
+        this.options.appid = data.data.appid;
+        this.options.channel = room?.get('profile').id
+      }
+    } else {
+      let data = await this.updateToken(room?.get('profile').id);
+      this.options.token = data.token;
+      this.options.channel = data.channel;
+      console.log(data);
+    }
+  }
+  /* 获取token */
+  async updateToken(pid: string) {
+    let sql = `select  "rtc"."objectId" as "rid","rtc"."channel", "rtc"."token",  "rtc"."expiraTime" from "RtcToken" as "rtc" where "rtc"."profile" = '${pid}' and "rtc"."expiraTime" >= now() order by "createdAt" desc limit 1`;
+    let tokenData: any = await this.http.customSQL(sql);
+    if (
+      tokenData &&
+      tokenData.code == 200 &&
+      tokenData.data &&
+      tokenData.data.length > 0
+    ) {
+      return tokenData.data[0];
+    } else {
+      return null;
+    }
+  }
+  // 进入频道
+  async join() {
+    let data = await Promise.all([
+      this.client.join(this.options.appid, this.options.channel, this.options.token, this.UID),
+      /* 创建音频和视频轨道 */
+      AgoraRTC.createMicrophoneAudioTrack(),
+      AgoraRTC.createCameraVideoTrack(),
+    ]);
+    // await this.client.setClientRole('host');
+    this.localTracks.audioTrack = data[1];
+    this.localTracks.videoTrack = data[2];
+    let remoteEle = document.getElementById('vice-video');
+    if (remoteEle) {
+      remoteEle.textContent = '';
+    }
+    this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
+    let publish = await this.client.publish(Object.values(this.localTracks));
+    this.joinReady();
+  }
+  /* 订阅远程视频 */
+  async joinReady() {
+    console.log(this.client.remoteUsers);
+    let wxRemoteUsers = this.client.remoteUsers.find((item: any) => {
+      if (item.uid && item._video_added_) {
+        return item;
+      }
+    });
+    console.log(wxRemoteUsers);
+    this.client.on('user-joined', (user: any) => {
+      console.log(user, `${user.uid} 加入频道`);
+    });
+    this.client.on('user-published', async (user: any, mediaType: any) => {
+      console.log('用户推流成功');
+      // if (user.uid == 333333) {
+      await this.client.subscribe(user, mediaType);
+      // }
+      let remoteEle = document.getElementById('video');
+      if (remoteEle) {
+        remoteEle.textContent = '';
+      }
+      if (mediaType === 'video') {
+        user.videoTrack.play(`video`);
+      }
+      if (mediaType === 'audio') {
+        user.audioTrack.play();
+      }
+    });
+    this.client.on('user-unpublished', (user: any) => {
+      let remoteEle = document.getElementById('video');
+      if (remoteEle) {
+        remoteEle.textContent = '对方离开直播间';
+      }
+      // if (user.uid == 333333) {
+      console.log('用户取消推流');
+      // }
+    });
+  }
+}