文章目录[隐藏]
手把手教学:集成在线视频会议与屏幕共享工具到WordPress网站
引言:为什么网站需要集成视频会议功能?
在当今数字化时代,线上沟通已成为商业运营、教育、医疗咨询和社交互动的重要组成部分。随着远程工作和在线协作的普及,网站不再仅仅是信息展示的平台,更是连接用户、提供实时服务的门户。集成视频会议与屏幕共享功能到您的WordPress网站,可以显著提升用户体验,增加用户粘性,并为您的业务创造新的价值。
传统的视频会议解决方案通常要求用户离开网站,跳转到第三方平台,这种体验割裂且不够专业。通过将视频会议功能直接集成到您的WordPress网站中,您可以:
- 提供无缝的用户体验
- 增强品牌一致性
- 降低用户使用门槛
- 收集有价值的用户互动数据
- 创造新的收入机会(如付费咨询、在线课程等)
本文将详细介绍如何通过代码二次开发,在WordPress网站中集成在线视频会议与屏幕共享功能,让您的网站从静态展示平台转变为动态互动空间。
第一部分:准备工作与环境搭建
1.1 选择合适的视频会议API
在开始集成之前,您需要选择一个合适的视频会议API。市场上有多种选择,每种都有其优缺点:
主流视频会议API对比:
| API提供商 | 免费额度 | 最大参与者 | 屏幕共享 | 录制功能 | 集成难度 |
|---|---|---|---|---|---|
| Zoom API | 40分钟/会议 | 100人 | 支持 | 额外付费 | 中等 |
| Jitsi Meet | 完全开源免费 | 无限制 | 支持 | 支持 | 较简单 |
| Daily.co | 每月2000分钟免费 | 无限制 | 支持 | 支持 | 简单 |
| Agora.io | 每月10000分钟免费 | 无限制 | 支持 | 支持 | 中等 |
| Twilio Video | 免费试用额度 | 50人 | 支持 | 支持 | 中等 |
推荐选择:
对于大多数WordPress网站,我们推荐使用Jitsi Meet或Daily.co,原因如下:
- 免费或提供慷慨的免费额度
- 无需用户注册即可加入会议
- 提供完善的文档和社区支持
- 支持屏幕共享和录制功能
1.2 开发环境准备
在开始编码之前,请确保您的开发环境满足以下要求:
- WordPress环境:WordPress 5.0+,PHP 7.2+,MySQL 5.6+
- 代码编辑器:VS Code、Sublime Text或PHPStorm
- 本地开发环境:XAMPP、MAMP或Local by Flywheel
- 版本控制:Git(可选但推荐)
- 浏览器开发者工具:熟悉Chrome或Firefox的开发者工具
1.3 创建WordPress插件框架
我们将创建一个独立的WordPress插件来实现视频会议功能,这样可以确保代码的可维护性和可移植性。
创建插件基本结构:
wp-content/plugins/video-meeting-integration/
├── video-meeting-integration.php # 主插件文件
├── includes/
│ ├── class-api-handler.php # API处理类
│ ├── class-shortcodes.php # 短代码类
│ └── class-admin-settings.php # 管理设置类
├── assets/
│ ├── css/
│ │ └── style.css # 前端样式
│ └── js/
│ └── script.js # 前端脚本
├── templates/
│ └── meeting-room.php # 会议室模板
└── uninstall.php # 卸载脚本
主插件文件基础代码:
<?php
/**
* Plugin Name: 视频会议与屏幕共享集成
* Plugin URI: https://yourwebsite.com/
* Description: 在WordPress网站中集成在线视频会议与屏幕共享功能
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: video-meeting-integration
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('VMI_VERSION', '1.0.0');
define('VMI_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('VMI_PLUGIN_URL', plugin_dir_url(__FILE__));
// 自动加载类文件
spl_autoload_register(function ($class) {
$prefix = 'VMI_';
$base_dir = VMI_PLUGIN_DIR . 'includes/';
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
return;
}
$relative_class = substr($class, $len);
$file = $base_dir . 'class-' . strtolower(str_replace('_', '-', $relative_class)) . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化插件
function vmi_init() {
// 检查依赖
if (!function_exists('curl_init')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>视频会议插件需要cURL扩展支持,请联系主机提供商启用cURL。</p></div>';
});
return;
}
// 初始化各个组件
VMI_API_Handler::init();
VMI_Shortcodes::init();
VMI_Admin_Settings::init();
}
add_action('plugins_loaded', 'vmi_init');
// 激活插件时的操作
register_activation_hook(__FILE__, function() {
// 创建必要的数据库表
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'vmi_meetings';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
meeting_id varchar(100) NOT NULL,
meeting_name varchar(255) NOT NULL,
host_id bigint(20) NOT NULL,
start_time datetime DEFAULT CURRENT_TIMESTAMP,
end_time datetime,
max_participants int(11) DEFAULT 10,
recording_enabled tinyint(1) DEFAULT 0,
status varchar(20) DEFAULT 'scheduled',
PRIMARY KEY (id),
UNIQUE KEY meeting_id (meeting_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 添加默认选项
add_option('vmi_api_provider', 'jitsi');
add_option('vmi_default_max_participants', 10);
add_option('vmi_enable_recording', 0);
});
第二部分:集成Jitsi Meet视频会议
2.1 Jitsi Meet API基础集成
Jitsi Meet是一个开源的视频会议解决方案,可以自托管或使用其云服务。我们将使用Jitsi Meet API在WordPress中创建视频会议房间。
创建API处理类:
<?php
// includes/class-api-handler.php
class VMI_API_Handler {
private static $instance = null;
private $api_provider;
private $api_settings;
public static function init() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->api_provider = get_option('vmi_api_provider', 'jitsi');
$this->api_settings = get_option('vmi_api_settings', array());
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
}
// 加载前端资源
public function enqueue_scripts() {
if (is_singular() && has_shortcode(get_post()->post_content, 'video_meeting')) {
// Jitsi Meet API脚本
wp_enqueue_script(
'jitsi-external-api',
'https://meet.jit.si/external_api.js',
array(),
null,
true
);
// 自定义脚本
wp_enqueue_script(
'vmi-frontend',
VMI_PLUGIN_URL . 'assets/js/script.js',
array('jquery', 'jitsi-external-api'),
VMI_VERSION,
true
);
// 样式
wp_enqueue_style(
'vmi-frontend-style',
VMI_PLUGIN_URL . 'assets/css/style.css',
array(),
VMI_VERSION
);
// 本地化脚本
wp_localize_script('vmi-frontend', 'vmi_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('vmi_nonce')
));
}
}
// 创建会议房间
public function create_meeting($meeting_name, $options = array()) {
$defaults = array(
'room_name' => sanitize_title($meeting_name) . '-' . uniqid(),
'user_display_name' => '主持人',
'max_participants' => get_option('vmi_default_max_participants', 10),
'enable_recording' => get_option('vmi_enable_recording', 0),
'start_with_audio_muted' => true,
'start_with_video_muted' => false
);
$options = wp_parse_args($options, $defaults);
// 生成会议ID
$meeting_id = $this->generate_meeting_id($options['room_name']);
// 保存到数据库
$this->save_meeting_to_db($meeting_id, $meeting_name, $options);
return array(
'meeting_id' => $meeting_id,
'room_name' => $options['room_name'],
'join_url' => $this->get_join_url($options['room_name'], $options)
);
}
// 生成会议ID
private function generate_meeting_id($room_name) {
return md5($room_name . time() . wp_rand(1000, 9999));
}
// 保存会议到数据库
private function save_meeting_to_db($meeting_id, $meeting_name, $options) {
global $wpdb;
$table_name = $wpdb->prefix . 'vmi_meetings';
$data = array(
'meeting_id' => $meeting_id,
'meeting_name' => $meeting_name,
'host_id' => get_current_user_id(),
'max_participants' => $options['max_participants'],
'recording_enabled' => $options['enable_recording'] ? 1 : 0,
'status' => 'scheduled'
);
$wpdb->insert($table_name, $data);
}
// 获取加入URL
private function get_join_url($room_name, $options) {
$base_url = 'https://meet.jit.si/';
$params = array(
'config.startWithAudioMuted' => $options['start_with_audio_muted'] ? 'true' : 'false',
'config.startWithVideoMuted' => $options['start_with_video_muted'] ? 'true' : 'false',
'config.prejoinPageEnabled' => 'false',
'userInfo.displayName' => urlencode($options['user_display_name'])
);
if ($options['enable_recording']) {
$params['config.recordingService'] = 'enabled';
}
$query_string = http_build_query($params);
return $base_url . $room_name . '?' . $query_string;
}
// 获取会议信息
public function get_meeting_info($meeting_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'vmi_meetings';
return $wpdb->get_row(
$wpdb->prepare("SELECT * FROM $table_name WHERE meeting_id = %s", $meeting_id)
);
}
}
2.2 创建视频会议短代码
短代码是WordPress中集成功能的最简单方式,允许用户通过简单的标签将视频会议嵌入到任何页面或文章中。
<?php
// includes/class-shortcodes.php
class VMI_Shortcodes {
private static $instance = null;
public static function init() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// 注册短代码
add_shortcode('video_meeting', array($this, 'video_meeting_shortcode'));
add_shortcode('create_meeting', array($this, 'create_meeting_shortcode'));
add_shortcode('meeting_list', array($this, 'meeting_list_shortcode'));
// AJAX处理
add_action('wp_ajax_vmi_create_meeting', array($this, 'ajax_create_meeting'));
add_action('wp_ajax_nopriv_vmi_create_meeting', array($this, 'ajax_create_meeting'));
add_action('wp_ajax_vmi_join_meeting', array($this, 'ajax_join_meeting'));
add_action('wp_ajax_nopriv_vmi_join_meeting', array($this, 'ajax_join_meeting'));
}
// 视频会议短代码
public function video_meeting_shortcode($atts) {
$atts = shortcode_atts(array(
'id' => '',
'width' => '100%',
'height' => '600px',
'prejoin' => 'true'
), $atts, 'video_meeting');
if (empty($atts['id'])) {
return '<div class="vmi-error">请提供会议ID</div>';
}
// 获取会议信息
$api_handler = VMI_API_Handler::init();
$meeting_info = $api_handler->get_meeting_info($atts['id']);
if (!$meeting_info) {
return '<div class="vmi-error">会议不存在或已结束</div>';
}
// 检查用户权限
$can_join = $this->check_meeting_access($meeting_info);
if (!$can_join) {
return '<div class="vmi-error">您没有权限加入此会议</div>';
}
// 输出会议容器
ob_start();
?>
<div class="vmeeting-container">
<div id="vmeeting-<?php echo esc_attr($atts['id']); ?>"
class="vmeeting-room"
data-meeting-id="<?php echo esc_attr($atts['id']); ?>"
data-room-name="<?php echo esc_attr($meeting_info->meeting_name); ?>"
style="width: <?php echo esc_attr($atts['width']); ?>; height: <?php echo esc_attr($atts['height']); ?>;">
<?php if ($atts['prejoin'] === 'true') : ?>
<div class="vmeeting-prejoin">
<h3><?php echo esc_html($meeting_info->meeting_name); ?></h3>
<div class="prejoin-form">
<div class="form-group">
<label for="display-name">您的显示名称</label>
<input type="text" id="display-name" class="form-control"
value="<?php echo esc_attr(wp_get_current_user()->display_name); ?>">
</div>
<div class="form-group">
<label for="audio-option">
<input type="checkbox" id="audio-option" checked> 加入时静音
</label>
</div>
<div class="form-group">
<label for="video-option">
<input type="checkbox" id="video-option"> 开启摄像头
</label>
</div>
<button class="btn btn-primary btn-join-meeting">加入会议</button>
</div>
</div>
<?php endif; ?>
<div class="vmeeting-interface" style="display: none;">
<div id="meeting-container"></div>
<div class="meeting-controls">
<button class="btn-control btn-toggle-audio" title="静音/取消静音">
<i class="dashicons dashicons-microphone"></i>
</button>
<button class="btn-control btn-toggle-video" title="开启/关闭视频">
<i class="dashicons dashicons-video-alt3"></i>
</button>
<button class="btn-control btn-screen-share" title="共享屏幕">
<i class="dashicons dashicons-desktop"></i>
</button>
<button class="btn-control btn-toggle-chat" title="聊天">
<i class="dashicons dashicons-format-chat"></i>
</button>
<button class="btn-control btn-leave-meeting btn-danger" title="离开会议">
<i class="dashicons dashicons-no"></i>
</button>
</div>
</div>
</div>
</div>
<?php
return ob_get_clean();
}
// 创建会议短代码
public function create_meeting_shortcode($atts) {
// 仅限登录用户
if (!is_user_logged_in()) {
return '<div class="vmi-login-required">请先登录以创建会议</div>';
}
ob_start();
?>
<div class="vmi-create-meeting-form">
<h3>创建新会议</h3>
<form id="vmi-meeting-form">
<div class="form-group">
<label for="meeting-name">会议名称 *</label>
meeting-name" name="meeting_name" required class="form-control">
</div>
<div class="form-group">
<label for="max-participants">最大参与人数</label>
<input type="number" id="max-participants" name="max_participants"
min="2" max="100" value="10" class="form-control">
</div>
<div class="form-group">
<label for="enable-recording">
<input type="checkbox" id="enable-recording" name="enable_recording"> 启用录制
</label>
</div>
<div class="form-group">
<label for="meeting-password">会议密码(可选)</label>
<input type="password" id="meeting-password" name="meeting_password" class="form-control">
</div>
<div class="form-group">
<label for="meeting-duration">会议时长(分钟)</label>
<select id="meeting-duration" name="meeting_duration" class="form-control">
<option value="30">30分钟</option>
<option value="60" selected>60分钟</option>
<option value="120">2小时</option>
<option value="240">4小时</option>
<option value="0">无限制</option>
</select>
</div>
<input type="hidden" name="action" value="vmi_create_meeting">
<?php wp_nonce_field('vmi_create_meeting_nonce', 'vmi_nonce'); ?>
<button type="submit" class="btn btn-primary">创建会议</button>
</form>
<div id="vmi-meeting-result" style="display: none; margin-top: 20px;">
<h4>会议创建成功!</h4>
<p>会议ID: <span id="result-meeting-id" class="meeting-info"></span></p>
<p>会议链接: <a id="result-meeting-link" href="#" target="_blank"></a></p>
<p>邀请链接: <input type="text" id="result-invite-link" readonly class="form-control"></p>
<button class="btn btn-secondary" onclick="copyInviteLink()">复制邀请链接</button>
</div>
</div>
<script>
function copyInviteLink() {
var copyText = document.getElementById("result-invite-link");
copyText.select();
copyText.setSelectionRange(0, 99999);
document.execCommand("copy");
alert("邀请链接已复制到剪贴板");
}
</script>
<?php
return ob_get_clean();
}
// 会议列表短代码
public function meeting_list_shortcode($atts) {
global $wpdb;
$table_name = $wpdb->prefix . 'vmi_meetings';
$atts = shortcode_atts(array(
'limit' => 10,
'status' => 'scheduled',
'show_past' => false
), $atts, 'meeting_list');
$user_id = get_current_user_id();
$where_clause = "WHERE host_id = %d";
$where_args = array($user_id);
if ($atts['status'] !== 'all') {
$where_clause .= " AND status = %s";
$where_args[] = $atts['status'];
}
if (!$atts['show_past']) {
$where_clause .= " AND (end_time IS NULL OR end_time > NOW())";
}
$meetings = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM $table_name $where_clause ORDER BY start_time DESC LIMIT %d",
array_merge($where_args, array($atts['limit']))
)
);
if (empty($meetings)) {
return '<div class="vmi-no-meetings">没有找到会议</div>';
}
ob_start();
?>
<div class="vmi-meeting-list">
<h3>我的会议</h3>
<table class="vmi-meetings-table">
<thead>
<tr>
<th>会议名称</th>
<th>会议ID</th>
<th>开始时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($meetings as $meeting): ?>
<tr>
<td><?php echo esc_html($meeting->meeting_name); ?></td>
<td><code><?php echo esc_html($meeting->meeting_id); ?></code></td>
<td><?php echo date('Y-m-d H:i', strtotime($meeting->start_time)); ?></td>
<td>
<span class="meeting-status status-<?php echo esc_attr($meeting->status); ?>">
<?php echo $this->get_status_label($meeting->status); ?>
</span>
</td>
<td>
<?php if ($meeting->status === 'scheduled' || $meeting->status === 'active'): ?>
<a href="<?php echo $this->get_meeting_join_url($meeting->meeting_id); ?>"
class="btn btn-small btn-primary" target="_blank">加入会议</a>
<?php endif; ?>
<?php if ($meeting->status === 'ended' && $meeting->recording_enabled): ?>
<button class="btn btn-small btn-secondary"
onclick="vmiViewRecording('<?php echo esc_js($meeting->meeting_id); ?>')">
查看录制
</button>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
return ob_get_clean();
}
// AJAX创建会议
public function ajax_create_meeting() {
// 验证nonce
if (!wp_verify_nonce($_POST['vmi_nonce'], 'vmi_create_meeting_nonce')) {
wp_die('安全验证失败');
}
// 验证用户权限
if (!is_user_logged_in()) {
wp_send_json_error('请先登录');
}
// 获取表单数据
$meeting_name = sanitize_text_field($_POST['meeting_name']);
$max_participants = intval($_POST['max_participants']);
$enable_recording = isset($_POST['enable_recording']) ? 1 : 0;
$meeting_password = sanitize_text_field($_POST['meeting_password']);
$meeting_duration = intval($_POST['meeting_duration']);
if (empty($meeting_name)) {
wp_send_json_error('会议名称不能为空');
}
// 创建会议
$api_handler = VMI_API_Handler::init();
$options = array(
'max_participants' => $max_participants,
'enable_recording' => $enable_recording,
'meeting_password' => $meeting_password,
'meeting_duration' => $meeting_duration
);
$result = $api_handler->create_meeting($meeting_name, $options);
// 生成邀请链接
$invite_link = add_query_arg(
array('meeting_id' => $result['meeting_id']),
get_permalink()
);
wp_send_json_success(array(
'meeting_id' => $result['meeting_id'],
'meeting_link' => $result['join_url'],
'invite_link' => $invite_link,
'message' => '会议创建成功'
));
}
// 辅助方法:检查会议访问权限
private function check_meeting_access($meeting_info) {
// 如果是公开会议
if (get_option('vmi_meeting_access', 'public') === 'public') {
return true;
}
// 如果是私有会议,检查用户权限
$user_id = get_current_user_id();
// 主持人可以访问自己的会议
if ($user_id == $meeting_info->host_id) {
return true;
}
// 检查用户是否被邀请
global $wpdb;
$invites_table = $wpdb->prefix . 'vmi_meeting_invites';
$invited = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $invites_table WHERE meeting_id = %s AND user_id = %d",
$meeting_info->meeting_id,
$user_id
)
);
return $invited > 0;
}
// 辅助方法:获取状态标签
private function get_status_label($status) {
$labels = array(
'scheduled' => '已安排',
'active' => '进行中',
'ended' => '已结束',
'cancelled' => '已取消'
);
return isset($labels[$status]) ? $labels[$status] : $status;
}
// 辅助方法:获取会议加入URL
private function get_meeting_join_url($meeting_id) {
return add_query_arg(
array('meeting_id' => $meeting_id, 'action' => 'join'),
get_permalink()
);
}
}
## 第三部分:实现屏幕共享功能
### 3.1 屏幕共享API集成
屏幕共享是现代视频会议的核心功能之一。我们将扩展Jitsi Meet的集成,添加屏幕共享功能。
**扩展前端JavaScript:**
// assets/js/script.js
(function($) {
'use strict';
var VMI_Meeting = {
api: null,
isAudioMuted: true,
isVideoMuted: false,
isScreenSharing: false,
currentMeetingId: null,
init: function() {
this.bindEvents();
// 如果有会议ID参数,自动加入会议
var urlParams = new URLSearchParams(window.location.search);
var meetingId = urlParams.get('meeting_id');
var action = urlParams.get('action');
if (meetingId && action === 'join') {
this.joinMeetingById(meetingId);
}
},
bindEvents: function() {
// 加入会议按钮
$(document).on('click', '.btn-join-meeting', function(e) {
e.preventDefault();
VMI_Meeting.joinMeeting($(this).closest('.vmeeting-room'));
});
// 会议控制按钮
$(document).on('click', '.btn-toggle-audio', function() {
VMI_Meeting.toggleAudio();
});
$(document).on('click', '.btn-toggle-video', function() {
VMI_Meeting.toggleVideo();
});
$(document).on('click', '.btn-screen-share', function() {
VMI_Meeting.toggleScreenShare();
});
$(document).on('click', '.btn-leave-meeting', function() {
VMI_Meeting.leaveMeeting();
});
// 创建会议表单
$(document).on('submit', '#vmi-meeting-form', function(e) {
e.preventDefault();
VMI_Meeting.createMeeting($(this));
});
},
joinMeeting: function($container) {
var meetingId = $container.data('meeting-id');
var roomName = $container.data('room-name');
var displayName = $container.find('#display-name').val();
var startAudioMuted = $container.find('#audio-option').is(':checked');
var startVideoMuted = !$container.find('#video-option').is(':checked');
this.currentMeetingId = meetingId;
// 隐藏预加入界面
$container.find('.vmeeting-prejoin').hide();
$container.find('.vmeeting-interface').show();
// 初始化Jitsi Meet API
const domain = 'meet.jit.si';
const options = {
roomName: roomName,
width: '100%',
height: '100%',
parentNode: $container.find('#meeting-container')[0],
configOverwrite: {
startWithAudioMuted: startAudioMuted,
startWithVideoMuted: startVideoMuted,
enableWelcomePage: false,
prejoinPageEnabled: false,
disableSimulcast: false
},
interfaceConfigOverwrite: {
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone',
'security'
],
SETTINGS_SECTIONS: ['devices', 'language', 'moderator', 'profile', 'calendar'],
SHOW_CHROME_EXTENSION_BANNER: false
},
userInfo: {
displayName: displayName
}
};
this.api = new JitsiMeetExternalAPI(domain, options);
// 添加事件监听器
this.api.addEventListeners({
readyToClose: this.onMeetingEnd.bind(this),
participantJoined: this.onParticipantJoined.bind(this),
participantLeft: this.onParticipantLeft.bind(this),
videoConferenceJoined: this.onConferenceJoined.bind(this),
videoConferenceLeft: this.onConferenceLeft.bind(this),
screenSharingStatusChanged: this.onScreenSharingChanged.bind(this)
});
// 更新会议状态为活跃
this.updateMeetingStatus(meetingId, 'active');
},
joinMeetingById: function(meetingId) {
$.ajax({
url: vmi_ajax.ajax_url,
type: 'POST',
data: {
action: 'vmi_join_meeting',
meeting_id: meetingId,
nonce: vmi_ajax.nonce
},
success: function(response) {
if (response.success) {
// 重定向到会议页面
window.location.href = response.data.join_url;
} else {
alert('加入会议失败: ' + response.data);
}
}
});
},
createMeeting: function($form) {
var formData = $form.serialize();
$.ajax({
url: vmi_ajax.ajax_url,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
$('#vmi-meeting-result').show();
$('#result-meeting-id').text(response.data.meeting_id);
$('#result-meeting-link').attr('href', response.data.meeting_link)
.text(response.data.meeting_link);
$('#result-invite-link').val(response.data.invite_link);
$form.hide();
} else {
alert('创建会议失败: ' + response.data);
}
}
});
},
toggleAudio: function() {
if (this.api) {
this.api.executeCommand('toggleAudio');
this.isAudioMuted = !this.isAudioMuted;
$('.btn-toggle-audio').toggleClass('muted', this.isAudioMuted);
}
},
toggleVideo: function() {
if (this.api) {
this.api.executeCommand('toggleVideo');
this.isVideoMuted = !this.isVideoMuted;
$('.btn-toggle-video').toggleClass('muted', this.isVideoMuted);
}
},
toggleScreenShare: function() {
if (this.api) {
if (this.isScreenSharing) {
this.api.executeCommand('toggleShareScreen');
} else {
// 检查浏览器是否支持屏幕共享
if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
alert('您的浏览器不支持屏幕共享功能。请使用最新版本的Chrome、Firefox或Edge浏览器。');
return;
}
// 请求屏幕共享权限
navigator.mediaDevices.getDisplayMedia({ video: true })
.then(() => {
this.api.executeCommand('toggleShareScreen');
})
.catch(err => {
console.error('屏幕共享失败:', err);
if (err.name !== 'NotAllowedError') {
alert('屏幕共享失败: ' + err.message);
}
});
}
this.isScreenSharing = !this.isScreenSharing;
$('.btn-screen-share').toggleClass('active', this.isScreenSharing);
}
},
leaveMeeting: function() {
if (this.api) {
this.api.executeCommand('hangup');
this.api.dispose();
// 显示离开消息
$('#meeting-container').html(
'<div class="meeting-ended">' +
'<h3>会议已结束</h3>' +
'<p>您已离开会议。</p>' +
'<button class="btn btn-primary" onclick="window.location.reload()">返回</button>' +
'</div>'
);
// 更新会议状态
if (this.currentMeetingId) {
this.updateMeetingStatus(this.currentMeetingId, 'ended');
}
}
},
// 事件处理函数
onMeetingEnd: function() {
console.log('会议结束');
},
onParticipantJoined: function(data) {
console.log('参与者加入:', data);
this.updateParticipantCount();
},
onParticipantLeft: function(data) {
console.log('参与者离开:', data);
this.updateParticipantCount();
},
onConferenceJoined: function(data) {
console.log('已加入会议:', data);
// 发送加入通知到服务器
this.sendJoinNotification();
},
onConferenceLeft: function(data) {
console.log('已离开
