新增功能
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
# 修复SDKAppID类型错误
|
||||
|
||||
## 问题描述
|
||||
|
||||
在启动视频通话时,TUICallKit报错:
|
||||
|
||||
```
|
||||
Error: 【CallService】API<init>: SDKAppID must be Number, current SDKAppID is string.
|
||||
```
|
||||
|
||||
## 问题原因
|
||||
|
||||
TUICallKit的 `init()` 方法要求 `SDKAppID` 参数必须是 **Number(数字)类型**,但系统传递的是 **String(字符串)类型**。
|
||||
|
||||
### 问题链路
|
||||
|
||||
```
|
||||
.env 文件
|
||||
↓ (env() 函数读取,返回字符串)
|
||||
config/project.php
|
||||
↓ (配置读取)
|
||||
DiagnosisLogic.php
|
||||
↓ (API返回)
|
||||
前端 video-call 组件
|
||||
↓ (传递给TUICallKit)
|
||||
❌ 类型错误:期望Number,实际String
|
||||
```
|
||||
|
||||
### 根本原因
|
||||
|
||||
1. **环境变量读取**:`env()` 函数从 `.env` 文件读取的值默认是字符串
|
||||
2. **配置未转换**:`config/project.php` 中没有将字符串转换为整数
|
||||
3. **前端未转换**:前端组件直接使用后端返回的值
|
||||
|
||||
## 解决方案
|
||||
|
||||
采用**多层防护**策略,在多个位置确保类型正确:
|
||||
|
||||
### 1. 配置层转换(第一道防线)
|
||||
|
||||
**文件**:`server/config/project.php`
|
||||
|
||||
```php
|
||||
// 修改前
|
||||
'trtc' => [
|
||||
'sdkAppId' => env('trtc.sdk_app_id', 1600127710), // ❌ 可能返回字符串
|
||||
// ...
|
||||
]
|
||||
|
||||
// 修改后
|
||||
'trtc' => [
|
||||
'sdkAppId' => (int)env('trtc.sdk_app_id', 1600127710), // ✅ 强制转换为整数
|
||||
// ...
|
||||
]
|
||||
```
|
||||
|
||||
### 2. Logic层转换(第二道防线)
|
||||
|
||||
**文件**:`server/app/adminapi/logic/tcm/DiagnosisLogic.php`
|
||||
|
||||
#### getCallSignature 方法
|
||||
|
||||
```php
|
||||
// 修改前
|
||||
return [
|
||||
'sdkAppId' => $config['sdkAppId'], // ❌ 可能是字符串
|
||||
// ...
|
||||
];
|
||||
|
||||
// 修改后
|
||||
return [
|
||||
'sdkAppId' => (int)$config['sdkAppId'], // ✅ 确保返回整数
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
#### getPatientSignature 方法
|
||||
|
||||
```php
|
||||
// 从数据库读取时
|
||||
return [
|
||||
'sdkAppId' => (int)$patientTrtc->sdk_app_id, // ✅ 确保返回整数
|
||||
// ...
|
||||
];
|
||||
|
||||
// 新生成时
|
||||
return [
|
||||
'sdkAppId' => (int)$config['sdkAppId'], // ✅ 确保返回整数
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
### 3. 前端转换(第三道防线)
|
||||
|
||||
**文件**:`admin/src/components/video-call/index.vue`
|
||||
|
||||
```typescript
|
||||
// 修改前
|
||||
await TUICallKitServer.init({
|
||||
userID: res.userId,
|
||||
userSig: res.userSig,
|
||||
SDKAppID: res.sdkAppId // ❌ 可能是字符串
|
||||
})
|
||||
|
||||
// 修改后
|
||||
await TUICallKitServer.init({
|
||||
userID: res.userId,
|
||||
userSig: res.userSig,
|
||||
SDKAppID: Number(res.sdkAppId) // ✅ 强制转换为数字
|
||||
})
|
||||
```
|
||||
|
||||
## 修改的文件
|
||||
|
||||
1. `server/config/project.php` - 配置层转换
|
||||
2. `server/app/adminapi/logic/tcm/DiagnosisLogic.php` - Logic层转换(3处)
|
||||
3. `admin/src/components/video-call/index.vue` - 前端转换
|
||||
|
||||
## 为什么需要多层防护?
|
||||
|
||||
### 单层防护的风险
|
||||
|
||||
如果只在一个地方转换,可能会遇到:
|
||||
|
||||
1. **配置缓存问题**:配置文件修改后可能需要清除缓存
|
||||
2. **数据库存储问题**:数据库中可能存储了字符串类型
|
||||
3. **API传输问题**:JSON传输可能改变数据类型
|
||||
4. **前端解析问题**:JavaScript可能将数字解析为字符串
|
||||
|
||||
### 多层防护的优势
|
||||
|
||||
```
|
||||
配置层 ✅ → Logic层 ✅ → 前端 ✅ → TUICallKit ✅
|
||||
```
|
||||
|
||||
即使某一层失效,其他层仍能保证类型正确。
|
||||
|
||||
## 测试方法
|
||||
|
||||
### 1. 清除配置缓存
|
||||
|
||||
```bash
|
||||
# 如果使用了配置缓存
|
||||
cd server
|
||||
php think clear
|
||||
```
|
||||
|
||||
### 2. 测试医生通话
|
||||
|
||||
```bash
|
||||
# 登录管理后台
|
||||
# 进入诊单详情
|
||||
# 点击"视频通话"按钮
|
||||
# 查看浏览器控制台
|
||||
```
|
||||
|
||||
**预期输出**:
|
||||
```
|
||||
签名获取成功: { userId: "doctor_1", sdkAppId: 1600127710 }
|
||||
TUICallKit init 方法调用完成
|
||||
等待完成,准备显示通话界面
|
||||
初始化完成,准备发起通话...
|
||||
```
|
||||
|
||||
**不应该出现**:
|
||||
```
|
||||
❌ Error: SDKAppID must be Number, current SDKAppID is string
|
||||
```
|
||||
|
||||
### 3. 测试患者通话
|
||||
|
||||
```bash
|
||||
# 打开患者测试页面
|
||||
# 点击"初始化"按钮
|
||||
# 查看浏览器控制台
|
||||
```
|
||||
|
||||
应该能正常初始化,不报类型错误。
|
||||
|
||||
### 4. 验证数据类型
|
||||
|
||||
在浏览器控制台执行:
|
||||
|
||||
```javascript
|
||||
// 获取签名后
|
||||
console.log(typeof res.sdkAppId) // 应该输出 "number"
|
||||
|
||||
// 传递给TUICallKit前
|
||||
console.log(typeof Number(res.sdkAppId)) // 应该输出 "number"
|
||||
```
|
||||
|
||||
## 技术细节
|
||||
|
||||
### PHP类型转换
|
||||
|
||||
```php
|
||||
// 方式1:强制类型转换(推荐)
|
||||
$intValue = (int)$stringValue;
|
||||
|
||||
// 方式2:intval函数
|
||||
$intValue = intval($stringValue);
|
||||
|
||||
// 示例
|
||||
$str = "1600127710";
|
||||
$int = (int)$str; // 1600127710 (整数)
|
||||
```
|
||||
|
||||
### JavaScript类型转换
|
||||
|
||||
```javascript
|
||||
// 方式1:Number构造函数(推荐)
|
||||
const numValue = Number(strValue)
|
||||
|
||||
// 方式2:parseInt函数
|
||||
const numValue = parseInt(strValue, 10)
|
||||
|
||||
// 方式3:一元加号运算符
|
||||
const numValue = +strValue
|
||||
|
||||
// 示例
|
||||
const str = "1600127710"
|
||||
const num = Number(str) // 1600127710 (数字)
|
||||
```
|
||||
|
||||
### 类型检查
|
||||
|
||||
```javascript
|
||||
// JavaScript
|
||||
typeof 1600127710 // "number" ✅
|
||||
typeof "1600127710" // "string" ❌
|
||||
typeof Number("1600127710") // "number" ✅
|
||||
```
|
||||
|
||||
```php
|
||||
// PHP
|
||||
is_int(1600127710) // true ✅
|
||||
is_int("1600127710") // false ❌
|
||||
is_int((int)"1600127710") // true ✅
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 为什么env()返回字符串?
|
||||
|
||||
**答**:`.env` 文件是纯文本文件,所有值都是字符串。PHP的 `env()` 函数不会自动转换类型。
|
||||
|
||||
### Q2: 配置文件修改后需要重启吗?
|
||||
|
||||
**答**:
|
||||
- 开发环境:不需要,每次请求都会重新读取
|
||||
- 生产环境:如果使用了配置缓存,需要清除缓存
|
||||
|
||||
### Q3: 数据库中的sdk_app_id是什么类型?
|
||||
|
||||
**答**:
|
||||
- 如果字段类型是 `int`,存储的是整数
|
||||
- 如果字段类型是 `varchar`,存储的是字符串
|
||||
- 读取时需要转换:`(int)$model->sdk_app_id`
|
||||
|
||||
### Q4: JSON传输会改变类型吗?
|
||||
|
||||
**答**:
|
||||
- PHP的 `json_encode()` 会保持整数类型
|
||||
- JavaScript的 `JSON.parse()` 也会保持整数类型
|
||||
- 但如果PHP端是字符串,传到前端也是字符串
|
||||
|
||||
### Q5: 为什么前端还要转换?
|
||||
|
||||
**答**:
|
||||
- 防御性编程,确保类型正确
|
||||
- 即使后端返回字符串,前端也能处理
|
||||
- 提高代码健壮性
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 配置文件已添加 `(int)` 转换
|
||||
- [ ] Logic层所有返回都添加了 `(int)` 转换
|
||||
- [ ] 前端组件添加了 `Number()` 转换
|
||||
- [ ] 清除了配置缓存(如果有)
|
||||
- [ ] 测试医生通话,不报类型错误
|
||||
- [ ] 测试患者通话,不报类型错误
|
||||
- [ ] 浏览器控制台验证类型为 "number"
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [FIX_ADMIN_ID.md](./FIX_ADMIN_ID.md) - 管理员ID获取修复
|
||||
- [DOCTOR_IM_ACCOUNT.md](./DOCTOR_IM_ACCOUNT.md) - 医生账号导入功能
|
||||
- [QUICK_START.md](./QUICK_START.md) - 快速开始指南
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2026-03-02
|
||||
- ✅ 修复配置层:添加 `(int)` 转换
|
||||
- ✅ 修复Logic层:3处返回值添加 `(int)` 转换
|
||||
- ✅ 修复前端层:添加 `Number()` 转换
|
||||
- ✅ 采用多层防护策略,确保类型正确
|
||||
|
||||
---
|
||||
|
||||
**现在SDKAppID类型正确,TUICallKit应该能正常初始化了!** ✅
|
||||
Reference in New Issue
Block a user