407 lines
9.4 KiB
Markdown
407 lines
9.4 KiB
Markdown
# 音视频通话测试指南
|
||
|
||
## 问题说明
|
||
|
||
当前错误的根本原因:
|
||
|
||
```
|
||
目标用户 patient_1 没有在腾讯云 TRTC 中登录/初始化
|
||
```
|
||
|
||
### 为什么会出现这个错误?
|
||
|
||
1. **医生端**(当前系统)已经初始化:`doctor_1`
|
||
2. **患者端**需要呼叫:`patient_1`
|
||
3. **问题**:`patient_1` 没有登录 TRTC,无法接听
|
||
|
||
这就像打电话:
|
||
- 你(医生)的手机已经开机 ✅
|
||
- 对方(患者)的手机没开机 ❌
|
||
- 所以无法接通
|
||
|
||
## 解决方案
|
||
|
||
### 方案 1: 双浏览器测试(推荐)
|
||
|
||
使用两个浏览器窗口模拟医生和患者:
|
||
|
||
#### 步骤 1: 创建测试页面
|
||
|
||
创建一个简单的患者端测试页面:
|
||
|
||
```html
|
||
<!-- public/patient-test.html -->
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>患者端测试</title>
|
||
<script src="https://web.sdk.qcloud.com/trtc/webrtc/v5/TUICallKit.iife.js"></script>
|
||
</head>
|
||
<body>
|
||
<h1>患者端 - 等待来电</h1>
|
||
<div id="status">初始化中...</div>
|
||
<div id="TUICallKit"></div>
|
||
|
||
<script>
|
||
// 配置信息(从后端获取)
|
||
const config = {
|
||
SDKAppID: 你的SDKAppID, // 替换为实际值
|
||
userID: 'patient_1',
|
||
userSig: '从后端获取的userSig' // 需要为 patient_1 生成
|
||
};
|
||
|
||
// 初始化
|
||
TUICallKitServer.init({
|
||
userID: config.userID,
|
||
userSig: config.userSig,
|
||
SDKAppID: config.SDKAppID
|
||
}).then(() => {
|
||
document.getElementById('status').textContent = '等待来电...';
|
||
console.log('患者端初始化成功,等待来电');
|
||
}).catch(error => {
|
||
document.getElementById('status').textContent = '初始化失败: ' + error.message;
|
||
console.error('初始化失败:', error);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
#### 步骤 2: 后端添加获取患者签名的接口
|
||
|
||
```php
|
||
// server/app/adminapi/controller/tcm/DiagnosisController.php
|
||
|
||
/**
|
||
* @notes 获取患者通话签名(用于测试)
|
||
* @return \think\response\Json
|
||
*/
|
||
public function getPatientSignature()
|
||
{
|
||
$params = $this->request->get();
|
||
|
||
if (empty($params['patient_id'])) {
|
||
return $this->fail('患者ID不能为空');
|
||
}
|
||
|
||
$result = DiagnosisLogic::getPatientSignature($params);
|
||
if ($result) {
|
||
return $this->data($result);
|
||
}
|
||
return $this->fail(DiagnosisLogic::getError());
|
||
}
|
||
```
|
||
|
||
```php
|
||
// server/app/adminapi/logic/tcm/DiagnosisLogic.php
|
||
|
||
/**
|
||
* @notes 获取患者通话签名
|
||
* @param array $params
|
||
* @return array|bool
|
||
*/
|
||
public static function getPatientSignature(array $params)
|
||
{
|
||
try {
|
||
$config = self::getTrtcConfig();
|
||
|
||
if (!$config) {
|
||
self::setError('请先配置腾讯云TRTC参数');
|
||
return false;
|
||
}
|
||
|
||
// 患者的 userId
|
||
$userId = 'patient_' . $params['patient_id'];
|
||
|
||
// 生成 UserSig
|
||
$userSig = self::generateUserSig($config['sdkAppId'], $config['secretKey'], $userId);
|
||
|
||
if (!$userSig) {
|
||
self::setError('生成签名失败');
|
||
return false;
|
||
}
|
||
|
||
return [
|
||
'sdkAppId' => $config['sdkAppId'],
|
||
'userId' => $userId,
|
||
'userSig' => $userSig,
|
||
'expireTime' => 86400
|
||
];
|
||
} catch (\Exception $e) {
|
||
self::setError($e->getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 步骤 3: 测试流程
|
||
|
||
1. **打开患者端**
|
||
- 浏览器 1:访问 `http://localhost/patient-test.html?patient_id=1`
|
||
- 获取签名并初始化
|
||
- 等待来电
|
||
|
||
2. **打开医生端**
|
||
- 浏览器 2:登录后台管理系统
|
||
- 进入诊断列表
|
||
- 点击"视频通话"
|
||
- 发起通话
|
||
|
||
3. **验证**
|
||
- 患者端应该收到来电提示
|
||
- 点击接听
|
||
- 双方可以进行视频通话
|
||
|
||
### 方案 2: 使用腾讯云 Demo(快速测试)
|
||
|
||
1. 访问腾讯云官方 Demo:
|
||
```
|
||
https://web.sdk.qcloud.com/trtc/webrtc/demo/latest/official-demo/index.html
|
||
```
|
||
|
||
2. 输入你的配置:
|
||
- SDKAppID
|
||
- SecretKey
|
||
- UserID: `patient_1`
|
||
|
||
3. 点击"进入房间"
|
||
|
||
4. 在你的系统中发起通话
|
||
|
||
### 方案 3: 自测试(单用户测试)
|
||
|
||
如果只是想测试初始化是否成功,可以呼叫自己:
|
||
|
||
```typescript
|
||
// 修改前端代码,呼叫自己
|
||
await TUICallKitServer.call({
|
||
userID: res.userId, // 呼叫自己
|
||
type: TUICallType.VIDEO_CALL
|
||
})
|
||
```
|
||
|
||
这样可以验证:
|
||
- ✅ 初始化是否成功
|
||
- ✅ 签名是否正确
|
||
- ✅ 配置是否正确
|
||
- ❌ 但无法测试真实的通话流程
|
||
|
||
## 完整的测试方案
|
||
|
||
### 创建患者端测试组件
|
||
|
||
```vue
|
||
<!-- admin/src/views/test/patient-call.vue -->
|
||
<template>
|
||
<div class="patient-test">
|
||
<el-card>
|
||
<h2>患者端测试 - 接听来电</h2>
|
||
|
||
<el-form :model="form" label-width="100px">
|
||
<el-form-item label="患者ID">
|
||
<el-input v-model="form.patientId" placeholder="输入患者ID,如:1" />
|
||
</el-form-item>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="initPatient" :loading="loading">
|
||
初始化患者端
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<div v-if="initialized" class="status">
|
||
<el-alert type="success" :closable="false">
|
||
患者端已初始化,等待来电...
|
||
<br>
|
||
患者ID: {{ currentUserId }}
|
||
</el-alert>
|
||
</div>
|
||
|
||
<div id="TUICallKit" class="call-container"></div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { TUICallKitServer, TUICallType } from '@tencentcloud/call-uikit-vue'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
const form = ref({
|
||
patientId: '1'
|
||
})
|
||
|
||
const loading = ref(false)
|
||
const initialized = ref(false)
|
||
const currentUserId = ref('')
|
||
|
||
const initPatient = async () => {
|
||
try {
|
||
loading.value = true
|
||
|
||
// 获取患者签名
|
||
const response = await fetch(`/adminapi/tcm.diagnosis/getPatientSignature?patient_id=${form.value.patientId}`, {
|
||
headers: {
|
||
'Authorization': 'Bearer ' + localStorage.getItem('token')
|
||
}
|
||
})
|
||
|
||
const result = await response.json()
|
||
|
||
if (result.code !== 1) {
|
||
throw new Error(result.msg || '获取签名失败')
|
||
}
|
||
|
||
const { sdkAppId, userId, userSig } = result.data
|
||
currentUserId.value = userId
|
||
|
||
// 初始化
|
||
await TUICallKitServer.init({
|
||
userID: userId,
|
||
userSig: userSig,
|
||
SDKAppID: sdkAppId
|
||
})
|
||
|
||
// 等待初始化完成
|
||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||
|
||
initialized.value = true
|
||
ElMessage.success('患者端初始化成功,等待来电...')
|
||
|
||
} catch (error: any) {
|
||
console.error('初始化失败:', error)
|
||
ElMessage.error(error.message || '初始化失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.patient-test {
|
||
padding: 20px;
|
||
}
|
||
|
||
.status {
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.call-container {
|
||
width: 100%;
|
||
height: 500px;
|
||
margin-top: 20px;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
### 添加路由
|
||
|
||
```typescript
|
||
// admin/src/router/index.ts
|
||
{
|
||
path: '/test/patient-call',
|
||
name: 'PatientCallTest',
|
||
component: () => import('@/views/test/patient-call.vue'),
|
||
meta: { title: '患者端测试' }
|
||
}
|
||
```
|
||
|
||
## 测试步骤
|
||
|
||
### 完整测试流程
|
||
|
||
1. **准备两个浏览器窗口**
|
||
- 窗口 1:Chrome(医生端)
|
||
- 窗口 2:Chrome 无痕模式(患者端)
|
||
|
||
2. **初始化患者端**
|
||
- 在窗口 2 中访问:`http://localhost:5173/#/test/patient-call`
|
||
- 输入患者ID:1
|
||
- 点击"初始化患者端"
|
||
- 等待提示"患者端初始化成功"
|
||
|
||
3. **发起通话**
|
||
- 在窗口 1 中进入诊断列表
|
||
- 找到患者ID为1的诊单
|
||
- 点击"视频通话"
|
||
- 点击"开始通话"
|
||
|
||
4. **接听通话**
|
||
- 窗口 2 应该收到来电提示
|
||
- 点击"接听"
|
||
- 开始视频通话
|
||
|
||
5. **验证功能**
|
||
- ✅ 视频画面正常
|
||
- ✅ 音频正常
|
||
- ✅ 可以挂断
|
||
- ✅ 通话记录保存
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 患者端没有收到来电
|
||
|
||
**可能原因**:
|
||
1. 患者端没有初始化
|
||
2. 患者ID不匹配
|
||
3. 网络问题
|
||
|
||
**解决方案**:
|
||
```javascript
|
||
// 在患者端控制台检查
|
||
console.log('当前用户ID:', TUICallKitServer.userID)
|
||
// 应该显示: patient_1
|
||
```
|
||
|
||
### Q2: 提示用户不存在
|
||
|
||
**原因**: UserSig 生成的 userId 和呼叫的 userId 不一致
|
||
|
||
**解决方案**: 确保:
|
||
```typescript
|
||
// 医生端
|
||
const doctorUserId = 'doctor_1' // 医生登录时使用
|
||
|
||
// 患者端
|
||
const patientUserId = 'patient_1' // 患者登录时使用
|
||
|
||
// 呼叫时
|
||
await TUICallKitServer.call({
|
||
userID: 'patient_1' // 必须和患者登录的 userId 一致
|
||
})
|
||
```
|
||
|
||
### Q3: 两个窗口都是同一个用户
|
||
|
||
**原因**: 使用了相同的浏览器和相同的 localStorage
|
||
|
||
**解决方案**: 使用无痕模式或不同的浏览器
|
||
|
||
## 生产环境部署
|
||
|
||
在生产环境中,需要:
|
||
|
||
1. **患者端应用**
|
||
- 开发患者端 H5/小程序/App
|
||
- 集成 TUICallKit
|
||
- 实现登录和来电监听
|
||
|
||
2. **推送通知**
|
||
- 当医生发起通话时,推送通知给患者
|
||
- 患者点击通知进入通话界面
|
||
|
||
3. **在线状态管理**
|
||
- 检查患者是否在线
|
||
- 如果不在线,提示医生
|
||
|
||
4. **通话记录**
|
||
- 保存通话记录
|
||
- 统计通话时长
|
||
- 生成通话报表
|
||
|
||
## 参考资料
|
||
|
||
- [TUICallKit 快速集成](https://cloud.tencent.com/document/product/647/78742)
|
||
- [多端互通](https://cloud.tencent.com/document/product/647/78769)
|
||
- [常见问题](https://cloud.tencent.com/document/product/647/78769#3a61f42b-e06f-49af-88bf-362d40025887)
|