mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 18:42:54 +00:00
feat:添加会议分享功能 - 100%
This commit is contained in:
parent
3a2c40a43e
commit
0c4abb5db3
@ -613,7 +613,10 @@ class UsersController extends AbstractController
|
||||
*/
|
||||
public function basic()
|
||||
{
|
||||
User::auth();
|
||||
$sharekey = Request::header('Sharekey');
|
||||
if(empty($sharekey) || !Meeting::getShareInfo($sharekey)){
|
||||
User::auth();
|
||||
}
|
||||
//
|
||||
$userid = Request::input('userid');
|
||||
$array = Base::json2array($userid);
|
||||
@ -1120,7 +1123,7 @@ class UsersController extends AbstractController
|
||||
* - join: 加入会议,有效参数:meetingid (必填)
|
||||
* @apiParam {String} [meetingid] 频道ID(不是数字)
|
||||
* @apiParam {String} [name] 会话ID
|
||||
* @apiParam {String} [meetingsign] 签名
|
||||
* @apiParam {String} [sharekey] 分享的key
|
||||
* @apiParam {String} [username] 用户名称
|
||||
* @apiParam {Array} [userids] 邀请成员
|
||||
*
|
||||
@ -1134,11 +1137,17 @@ class UsersController extends AbstractController
|
||||
$meetingid = trim(Request::input('meetingid'));
|
||||
$name = trim(Request::input('name'));
|
||||
$userids = Request::input('userids');
|
||||
$meetingsign = trim(Request::input('meetingsign'));
|
||||
$sharekey = trim(Request::input('sharekey'));
|
||||
$username = trim(Request::input('username'));
|
||||
$user = empty($meetingsign) ? User::auth() : null;
|
||||
$user = null;
|
||||
if(!empty($sharekey) && $type === 'join'){
|
||||
if(!Meeting::getShareInfo($sharekey)){
|
||||
return Base::retError('分享链接已过期');
|
||||
}
|
||||
}else{
|
||||
$user = User::auth();
|
||||
}
|
||||
$isCreate = false;
|
||||
|
||||
// 创建、加入
|
||||
if ($type === 'join') {
|
||||
$meeting = Meeting::whereMeetingid($meetingid)->first();
|
||||
@ -1169,7 +1178,10 @@ 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(Base::generatePassword(4,1), 9, 8, STR_PAD_LEFT));
|
||||
if($user){
|
||||
$uid = intval(str_pad(Request::header('fd'), 5, 9, STR_PAD_LEFT).$user->userid);
|
||||
}
|
||||
try {
|
||||
$service = new AgoraTokenGenerator($meetingSetting['appid'], $meetingSetting['app_certificate'], $meeting->channel, $uid);
|
||||
} catch (\Exception $e) {
|
||||
@ -1198,13 +1210,40 @@ class UsersController extends AbstractController
|
||||
//
|
||||
$data['appid'] = $meetingSetting['appid'];
|
||||
$data['uid'] = $uid;
|
||||
$data['userimg'] = $meetingsign ? 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png' : $user?->userimg;
|
||||
$data['nickname'] = $meetingsign ? $username : $user?->nickname;
|
||||
$data['userimg'] = $sharekey ? Base::fillUrl('avatar/'.$username.'.png') : $user?->userimg;
|
||||
$data['nickname'] = $sharekey ? $username : $user?->nickname;
|
||||
$data['token'] = $token;
|
||||
$data['msgs'] = $msgs;
|
||||
$data['sharelink'] = $meeting->getShareLink();
|
||||
//
|
||||
Meeting::setTouristInfo($data);
|
||||
//
|
||||
return Base::retSuccess('success', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/meeting/tourist 16. 【会议】游客信息
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup users
|
||||
* @apiName meeting__tourist
|
||||
*
|
||||
* @apiParam {String} tourist_id 游客ID
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function meeting__tourist()
|
||||
{
|
||||
$touristId = trim(Request::input('tourist_id'));
|
||||
if ($touristInfo = Meeting::getTouristInfo($touristId)) {
|
||||
return Base::retSuccess('success', $touristInfo);
|
||||
}
|
||||
return Base::retError('Id不存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/meeting/invitation 17. 【会议】发送邀请
|
||||
*
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Cache;
|
||||
use App\Module\Base;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* App\Models\Meeting
|
||||
*
|
||||
@ -30,5 +34,58 @@ namespace App\Models;
|
||||
*/
|
||||
class Meeting extends AbstractModel
|
||||
{
|
||||
const CACHE_KEY = 'meeting_share_link_code';
|
||||
const CACHE_EXPIRED_TIME = 6; // 小时
|
||||
|
||||
/**
|
||||
* 获取分享链接
|
||||
* @return mixed
|
||||
*/
|
||||
public function getShareLink()
|
||||
{
|
||||
$code = base64_encode("{$this->meetingid}" . Base::generatePassword());
|
||||
Cache::put(self::CACHE_KEY.'_'.$code, [
|
||||
'id' => $this->id,
|
||||
'meetingid' => $this->meetingid,
|
||||
'channel' => $this->channel,
|
||||
], Carbon::now()->addHours(self::CACHE_EXPIRED_TIME));
|
||||
return Base::fillUrl("meeting/{$this->meetingid}/".$code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分享信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getShareInfo($code)
|
||||
{
|
||||
if(Cache::has(self::CACHE_KEY.'_'.$code)){
|
||||
return Cache::get(self::CACHE_KEY.'_'.$code);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存访客信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function setTouristInfo($data)
|
||||
{
|
||||
Cache::put(Meeting::CACHE_KEY.'_'.$data['uid'], [
|
||||
'uid' => $data['uid'],
|
||||
'userimg' => $data['userimg'],
|
||||
'nickname' => $data['nickname'],
|
||||
], Carbon::now()->addHours(self::CACHE_EXPIRED_TIME));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取访客信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getTouristInfo($touristId)
|
||||
{
|
||||
if(Cache::has(Meeting::CACHE_KEY.'_'.$touristId)){
|
||||
return Base::retSuccess('success', Cache::get(Meeting::CACHE_KEY.'_'.$touristId) );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@ export default {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/basic',
|
||||
data: {
|
||||
userid: [ (uuid+"").substring(6) ]
|
||||
userid: [ (uuid+"").substring(5) ]
|
||||
}
|
||||
}).then(({data}) => {
|
||||
$A.eeuiAppSendMessage({
|
||||
|
||||
@ -5,14 +5,14 @@
|
||||
v-model="addShow"
|
||||
:title="$L(addData.type === 'join' ? '加入会议' : '新会议')"
|
||||
:mask-closable="false"
|
||||
:closable="!addData.meetingsign">
|
||||
:closable="!addData.sharekey">
|
||||
<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('你的姓名')">
|
||||
<FormItem v-if="addData.sharekey" prop="username" :label="$L('你的姓名')">
|
||||
<Input v-model="addData.username" :placeholder="$L('请输入你的姓名')"/>
|
||||
</FormItem>
|
||||
<FormItem prop="meetingid" :label="$L('会议频道ID')">
|
||||
@ -40,7 +40,7 @@
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="addShow=false" v-if="!addData.meetingsign">{{$L('取消')}}</Button>
|
||||
<Button type="default" @click="addShow=false" v-if="!addData.sharekey">{{$L('取消')}}</Button>
|
||||
<Button type="primary" :loading="loadIng > 0" @click="onSubmit">{{$L(addData.type === 'join' ? '加入会议' : '开始会议')}}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -76,17 +76,17 @@
|
||||
<Button type="primary" @click="onInvitation('open')">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
<Button type="primary" v-if="!addData.meetingsign" @click="meetingMini = true">
|
||||
<Button type="primary" v-if="!addData.sharekey" @click="meetingMini = true">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
<Button type="warning" v-if="!addData.meetingsign" :loading="loadIng > 0" @click="onClose">
|
||||
<Button type="warning" :loading="loadIng > 0" @click="onClose">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Button type="primary" @click="onInvitation('open')">{{$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>
|
||||
<Button type="primary" v-if="!addData.sharekey" @click="meetingMini = true">{{$L('最小化')}}</Button>
|
||||
<Button type="warning" :loading="loadIng > 0" @click="onClose">{{$L('离开会议')}}</Button>
|
||||
</template>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -113,7 +113,7 @@
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="invitationShow=false">{{$L('取消')}}</Button>
|
||||
<Button type="default" @click="linkCopy">{{$L('复制链接')}}</Button>
|
||||
<Button type="primary" :loading="invitationLoad" @click="onInvitation('submit')">{{$L('发送邀请')}}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -193,7 +193,6 @@ export default {
|
||||
},
|
||||
meetingWindow: {
|
||||
handler(val) {
|
||||
console.log(val)
|
||||
switch (val.type) {
|
||||
case 'add':
|
||||
this.addShow = val.show;
|
||||
@ -203,10 +202,10 @@ export default {
|
||||
this.addShow = val.show;
|
||||
this.loadIng = 0;
|
||||
this.addData.type = 'join';
|
||||
if(val.meetingsign){
|
||||
if(val.meetingSharekey){
|
||||
this.addData.sharekey = val.meetingSharekey;
|
||||
this.addData.meetingid = val.meetingid || '';
|
||||
this.addData.meetingdisabled = val.meetingsign ? true : false;
|
||||
this.addData.meetingsign = val.meetingsign;
|
||||
this.addData.meetingdisabled = val.meetingSharekey ? true : false;
|
||||
}
|
||||
break;
|
||||
case 'invitation':
|
||||
@ -275,6 +274,9 @@ export default {
|
||||
}).then(({data}) => {
|
||||
this.$set(this.addData, 'name', data.name);
|
||||
this.$set(this.addData, 'meetingid', data.meetingid);
|
||||
this.$set(this.addData, 'sharelink', data.sharelink);
|
||||
this.$set(this.localUser, 'nickname', data.nickname);
|
||||
this.$set(this.localUser, 'userimg', data.userimg);
|
||||
this.$store.dispatch("saveDialogMsg", data.msgs);
|
||||
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
||||
delete data.name;
|
||||
@ -294,6 +296,7 @@ export default {
|
||||
video: this.addData.tracks.includes("video"),
|
||||
audio: this.addData.tracks.includes("audio"),
|
||||
meetingid: data.meetingid,
|
||||
sharelink: data.sharelink,
|
||||
alert: {
|
||||
title: this.$L('温馨提示'),
|
||||
message: this.$L('确定要离开会议吗?'),
|
||||
@ -338,6 +341,10 @@ export default {
|
||||
|
||||
onInvitation(type) {
|
||||
if (type === 'open') {
|
||||
if(this.addData.sharekey){
|
||||
this.linkCopy();
|
||||
return;
|
||||
}
|
||||
this.invitationData = {
|
||||
userids: [],
|
||||
meetingid: this.addData.meetingid
|
||||
@ -369,6 +376,10 @@ export default {
|
||||
okText: '退出',
|
||||
onOk: async _ => {
|
||||
await this.leave()
|
||||
if(this.addData.sharekey){
|
||||
this.addShow = true;
|
||||
this.loadIng = 0;
|
||||
}
|
||||
resolve()
|
||||
}
|
||||
});
|
||||
@ -376,7 +387,6 @@ export default {
|
||||
},
|
||||
|
||||
async join(options) {
|
||||
console.log(options)
|
||||
this.loadIng++;
|
||||
// 音频采集设备状态变化回调
|
||||
AgoraRTC.onMicrophoneChanged = async (changedDevice) => {
|
||||
@ -521,7 +531,16 @@ export default {
|
||||
if (item) {
|
||||
await this.agoraClient.unsubscribe(user, mediaType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
linkCopy() {
|
||||
this.$copyText(this.addData.sharelink).then(_ => {
|
||||
$A.messageSuccess('已复制会议邀请链接');
|
||||
}).catch(_ => {
|
||||
$A.messageError('复制失败');
|
||||
});
|
||||
this.invitationShow = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div class="meeting-player">
|
||||
<div :id="id" class="player" :style="playerStyle"></div>
|
||||
<UserAvatar :userid="userid" :size="36" :borderWitdh="2"/>
|
||||
<UserAvatar v-if="userid" :userid="userid" :size="36" :borderWitdh="2"/>
|
||||
<div v-else-if="tourist.userimg" class="common-avatar avatar-wrapper">
|
||||
<div class="avatar-box online">
|
||||
<em style="transform: scale(1.0625);"></em>
|
||||
<EAvatar :size="36" style="border: 2px solid #FFFFFF;" :src="tourist.userimg"></EAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-state">
|
||||
<i v-if="!audio" class="taskfont"></i>
|
||||
<i v-if="!video" class="taskfont"></i>
|
||||
@ -32,7 +38,12 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timer: null
|
||||
timer: null,
|
||||
tourist: {
|
||||
uid: '',
|
||||
nickname: '',
|
||||
userimg: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -52,8 +63,11 @@ export default {
|
||||
...mapState(['cacheUserBasic']),
|
||||
userid() {
|
||||
if (this.player.uid) {
|
||||
console.log(parseInt( (this.player.uid+"").substring(6) ));
|
||||
return parseInt( (this.player.uid+"").substring(6) )
|
||||
if( (this.player.uid + '').indexOf('88888') !== -1 ){
|
||||
this.getTouristInfo();
|
||||
return 0;
|
||||
}
|
||||
return parseInt( (this.player.uid+"").substring(5) ) || 0
|
||||
}
|
||||
return 0
|
||||
},
|
||||
@ -63,11 +77,12 @@ export default {
|
||||
return {
|
||||
backgroundImage: `url("${user.userimg}")`
|
||||
}
|
||||
}else{
|
||||
}else if(this.tourist.userimg){
|
||||
return {
|
||||
backgroundColor: '#000000'
|
||||
backgroundImage: `url("${this.tourist.userimg}")`
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
audio() {
|
||||
return !!this.player.audioTrack
|
||||
@ -103,6 +118,18 @@ export default {
|
||||
console.log("Meeting Player Error", e);
|
||||
}
|
||||
})
|
||||
},
|
||||
getTouristInfo() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/meeting/tourist',
|
||||
data: {
|
||||
tourist_id: this.player.uid
|
||||
}
|
||||
}).then(({data}) => {
|
||||
this.tourist = data.data;
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ export default {
|
||||
mounted() {
|
||||
this.$store.dispatch("showMeetingWindow",{
|
||||
type: "join",
|
||||
meetingsign: 'sign',
|
||||
meetingid: 10812486455,
|
||||
meetingid: this.$route.params.meetingId,
|
||||
meetingSharekey: this.$route.params.sharekey,
|
||||
meetingdisabled: true,
|
||||
})
|
||||
},
|
||||
|
||||
2
resources/assets/js/routes.js
vendored
2
resources/assets/js/routes.js
vendored
@ -11,7 +11,7 @@ export default [
|
||||
},
|
||||
{
|
||||
name: 'meeting',
|
||||
path: '/meeting',
|
||||
path: '/meeting/:meetingId?/:sharekey?',
|
||||
component: () => import('./pages/meeting.vue'),
|
||||
},
|
||||
{
|
||||
|
||||
7
resources/assets/js/store/actions.js
vendored
7
resources/assets/js/store/actions.js
vendored
@ -112,6 +112,9 @@ export default {
|
||||
'version': window.systemInfo.version || "0.0.1",
|
||||
'platform': $A.Platform,
|
||||
}
|
||||
if(!state.userToken && state.meetingWindow?.meetingSharekey){
|
||||
header.sharekey = state.meetingWindow.meetingSharekey;
|
||||
}
|
||||
if ($A.isJson(params.header)) {
|
||||
params.header = Object.assign(header, params.header)
|
||||
} else {
|
||||
@ -3608,13 +3611,13 @@ export default {
|
||||
* @param type
|
||||
* @param meetingid
|
||||
*/
|
||||
showMeetingWindow({state}, {type, meetingid, meetingdisabled, meetingsign}) {
|
||||
showMeetingWindow({state}, {type, meetingid, meetingdisabled, meetingSharekey}) {
|
||||
state.meetingWindow = {
|
||||
show: true,
|
||||
type: type,
|
||||
meetingid: meetingid,
|
||||
meetingdisabled: meetingdisabled,
|
||||
meetingsign: meetingsign
|
||||
meetingSharekey: meetingSharekey
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
2
resources/assets/js/store/state.js
vendored
2
resources/assets/js/store/state.js
vendored
@ -199,7 +199,7 @@ export default {
|
||||
// 审批待办未读数量
|
||||
approveUnreadNumber: 0,
|
||||
|
||||
// 会议窗口
|
||||
// 会议
|
||||
meetingWindow: {
|
||||
show: false,
|
||||
type: "",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user