feat:会议可分享 - 60%

This commit is contained in:
weifashi 2023-08-29 17:09:32 +08:00
parent 288e265aaa
commit 3a2c40a43e
7 changed files with 95 additions and 20 deletions

View File

@ -1120,6 +1120,8 @@ class UsersController extends AbstractController
* - join: 加入会议有效参数meetingid (必填)
* @apiParam {String} [meetingid] 频道ID不是数字
* @apiParam {String} [name] 会话ID
* @apiParam {String} [meetingsign] 签名
* @apiParam {String} [username] 用户名称
* @apiParam {Array} [userids] 邀请成员
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
@ -1128,13 +1130,15 @@ class UsersController extends AbstractController
*/
public function meeting__open()
{
$user = User::auth();
//
$type = trim(Request::input('type'));
$meetingid = trim(Request::input('meetingid'));
$name = trim(Request::input('name'));
$userids = Request::input('userids');
$meetingsign = trim(Request::input('meetingsign'));
$username = trim(Request::input('username'));
$user = empty($meetingsign) ? User::auth() : null;
$isCreate = false;
// 创建、加入
if ($type === 'join') {
$meeting = Meeting::whereMeetingid($meetingid)->first();
@ -1143,13 +1147,13 @@ class UsersController extends AbstractController
}
} elseif ($type === 'create') {
$meetingid = strtoupper(Base::generatePassword(11, 1));
$name = $name ?: "{$user->nickname} 发起的会议";
$name = $name ?: "{$user?->nickname} 发起的会议";
$channel = "DooTask:" . substr(md5($meetingid . env("APP_KEY")), 16);
$meeting = Meeting::createInstance([
'meetingid' => $meetingid,
'name' => $name,
'channel' => $channel,
'userid' => $user->userid
'userid' => $user?->userid
]);
$meeting->save();
$isCreate = true;
@ -1165,7 +1169,7 @@ class UsersController extends AbstractController
if (empty($meetingSetting['appid']) || empty($meetingSetting['app_certificate'])) {
return Base::retError('会议功能配置错误,请联系管理员');
}
$uid = intval(str_pad( Request::header('fd'), 6, 9, STR_PAD_LEFT) . $user->userid);
$uid = intval(str_pad( Request::header('fd'), 6, 9, STR_PAD_LEFT) . $user?->userid);
try {
$service = new AgoraTokenGenerator($meetingSetting['appid'], $meetingSetting['app_certificate'], $meeting->channel, $uid);
} catch (\Exception $e) {
@ -1194,8 +1198,8 @@ class UsersController extends AbstractController
//
$data['appid'] = $meetingSetting['appid'];
$data['uid'] = $uid;
$data['userimg'] = $user->userimg;
$data['nickname'] = $user->nickname;
$data['userimg'] = $meetingsign ? 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png' : $user?->userimg;
$data['nickname'] = $meetingsign ? $username : $user?->nickname;
$data['token'] = $token;
$data['msgs'] = $msgs;
return Base::retSuccess('success', $data);

View File

@ -438,4 +438,16 @@ class IndexController extends InvokeController
}
return implode("\n", array_values($array));
}
/**
* 提取所有中文
* @return array|string
*/
public function meeting__share()
{
return response()->view('meeting.share', [
'version' => Base::getVersion(),
])->header('Link', "<" . url('manifest.txt') . ">; rel=\"prefetch\"");
}
}

View File

@ -4,13 +4,17 @@
<Modal
v-model="addShow"
:title="$L(addData.type === 'join' ? '加入会议' : '新会议')"
:mask-closable="false">
:mask-closable="false"
:closable="!addData.meetingsign">
<Form ref="addForm" :model="addData" label-width="auto" @submit.native.prevent>
<template v-if="addData.type === 'join'">
<!-- 加入会议 -->
<FormItem v-if="addData.name" prop="userids" :label="$L('会议主题')">
<Input v-model="addData.name" disabled/>
</FormItem>
<FormItem v-if="addData.meetingsign" prop="username" :label="$L('你的姓名')">
<Input v-model="addData.username" :placeholder="$L('请输入你的姓名')"/>
</FormItem>
<FormItem prop="meetingid" :label="$L('会议频道ID')">
<Input v-model="addData.meetingid" :disabled="addData.meetingdisabled === true" :placeholder="$L('请输入会议频道ID')"/>
</FormItem>
@ -36,7 +40,7 @@
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="addShow=false">{{$L('取消')}}</Button>
<Button type="default" @click="addShow=false" v-if="!addData.meetingsign">{{$L('取消')}}</Button>
<Button type="primary" :loading="loadIng > 0" @click="onSubmit">{{$L(addData.type === 'join' ? '加入会议' : '开始会议')}}</Button>
</div>
</Modal>
@ -56,7 +60,8 @@
<ul>
<li v-if="localUser.uid">
<MeetingPlayer :player="localUser" isLocal/>
</li><li v-for="user in remoteUsers">
</li>
<li v-for="user in remoteUsers">
<MeetingPlayer :player="user"/>
</li>
</ul>
@ -68,20 +73,20 @@
<i class="taskfont" v-html="localUser.videoTrack ? '&#xe7c1;' : '&#xe7c8;'"></i>
</Button>
<template v-if="windowPortrait">
<Button type="primary" @click="onInvitation('open')">
<Button type="primary" @click="onInvitation('open')">
<i class="taskfont">&#xe646;</i>
</Button>
<Button type="primary" @click="meetingMini = true">
<Button type="primary" v-if="!addData.meetingsign" @click="meetingMini = true">
<i class="taskfont">&#xe656;</i>
</Button>
<Button type="warning" :loading="loadIng > 0" @click="onClose">
<Button type="warning" v-if="!addData.meetingsign" :loading="loadIng > 0" @click="onClose">
<i class="taskfont">&#xe612;</i>
</Button>
</template>
<template v-else>
<Button type="primary" @click="onInvitation('open')">{{$L('邀请')}}</Button>
<Button type="primary" @click="meetingMini = true">{{$L('最小化')}}</Button>
<Button type="warning" :loading="loadIng > 0" @click="onClose">{{$L('离开会议')}}</Button>
<Button type="primary" v-if="!addData.meetingsign" @click="meetingMini = true">{{$L('最小化')}}</Button>
<Button type="warning" v-if="!addData.meetingsign" :loading="loadIng > 0" @click="onClose">{{$L('离开会议')}}</Button>
</template>
</div>
</Modal>
@ -118,13 +123,21 @@
<script>
import {Store} from "le5le-store";
import {mapState} from 'vuex'
import MeetingPlayer from "./MeetingPlayer";
import MeetingPlayer from "./MeetingPlayer.vue";
import DragBallComponent from "../../../components/DragBallComponent";
import UserSelect from "../../../components/UserSelect.vue";
export default {
name: "MeetingManager",
components: {UserSelect, DragBallComponent, MeetingPlayer},
props: {
id: {
type: String,
default: () => {
return "meeting-player-" + Math.round(Math.random() * 10000);
}
}
},
data() {
return {
loadIng: 0,
@ -180,11 +193,22 @@ export default {
},
meetingWindow: {
handler(val) {
console.log(val)
switch (val.type) {
case 'add':
this.addShow = val.show;
this.loadIng = 0;
break;
case 'join':
this.addShow = val.show;
this.loadIng = 0;
this.addData.type = 'join';
if(val.meetingsign){
this.addData.meetingid = val.meetingid || '';
this.addData.meetingdisabled = val.meetingsign ? true : false;
this.addData.meetingsign = val.meetingsign;
}
break;
case 'invitation':
this.invitationShow = val.show;
this.invitationLoad = false;
@ -352,6 +376,7 @@ export default {
},
async join(options) {
console.log(options)
this.loadIng++;
//
AgoraRTC.onMicrophoneChanged = async (changedDevice) => {

View File

@ -1,5 +1,5 @@
<template>
<div v-if="userid" class="meeting-player">
<div class="meeting-player">
<div :id="id" class="player" :style="playerStyle"></div>
<UserAvatar :userid="userid" :size="36" :borderWitdh="2"/>
<div class="player-state">
@ -52,6 +52,7 @@ export default {
...mapState(['cacheUserBasic']),
userid() {
if (this.player.uid) {
console.log(parseInt( (this.player.uid+"").substring(6) ));
return parseInt( (this.player.uid+"").substring(6) )
}
return 0
@ -62,8 +63,11 @@ export default {
return {
backgroundImage: `url("${user.userimg}")`
}
}else{
return {
backgroundColor: '#000000'
}
}
return null;
},
audio() {
return !!this.player.audioTrack

View File

@ -0,0 +1,23 @@
<template>
<div>
<MeetingManager/>
</div>
</template>
<script>
import MeetingManager from "./manage/components/MeetingManager.vue";
export default {
components: {
MeetingManager,
},
mounted() {
this.$store.dispatch("showMeetingWindow",{
type: "join",
meetingsign: 'sign',
meetingid: 10812486455,
meetingdisabled: true,
})
},
}
</script>

View File

@ -9,6 +9,11 @@ export default [
path: '/pro',
component: () => import('./pages/pro.vue'),
},
{
name: 'meeting',
path: '/meeting',
component: () => import('./pages/meeting.vue'),
},
{
name: 'manage',
path: '/manage',

View File

@ -3608,11 +3608,13 @@ export default {
* @param type
* @param meetingid
*/
showMeetingWindow({state}, {type, meetingid}) {
showMeetingWindow({state}, {type, meetingid, meetingdisabled, meetingsign}) {
state.meetingWindow = {
show: true,
type: type,
meetingid: meetingid
meetingid: meetingid,
meetingdisabled: meetingdisabled,
meetingsign: meetingsign
};
},