6.8 KiB
6.8 KiB
修复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
根本原因
- 环境变量读取:
env()函数从.env文件读取的值默认是字符串 - 配置未转换:
config/project.php中没有将字符串转换为整数 - 前端未转换:前端组件直接使用后端返回的值
解决方案
采用多层防护策略,在多个位置确保类型正确:
1. 配置层转换(第一道防线)
文件:server/config/project.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 方法
// 修改前
return [
'sdkAppId' => $config['sdkAppId'], // ❌ 可能是字符串
// ...
];
// 修改后
return [
'sdkAppId' => (int)$config['sdkAppId'], // ✅ 确保返回整数
// ...
];
getPatientSignature 方法
// 从数据库读取时
return [
'sdkAppId' => (int)$patientTrtc->sdk_app_id, // ✅ 确保返回整数
// ...
];
// 新生成时
return [
'sdkAppId' => (int)$config['sdkAppId'], // ✅ 确保返回整数
// ...
];
3. 前端转换(第三道防线)
文件:admin/src/components/video-call/index.vue
// 修改前
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) // ✅ 强制转换为数字
})
修改的文件
server/config/project.php- 配置层转换server/app/adminapi/logic/tcm/DiagnosisLogic.php- Logic层转换(3处)admin/src/components/video-call/index.vue- 前端转换
为什么需要多层防护?
单层防护的风险
如果只在一个地方转换,可能会遇到:
- 配置缓存问题:配置文件修改后可能需要清除缓存
- 数据库存储问题:数据库中可能存储了字符串类型
- API传输问题:JSON传输可能改变数据类型
- 前端解析问题:JavaScript可能将数字解析为字符串
多层防护的优势
配置层 ✅ → Logic层 ✅ → 前端 ✅ → TUICallKit ✅
即使某一层失效,其他层仍能保证类型正确。
测试方法
1. 清除配置缓存
# 如果使用了配置缓存
cd server
php think clear
2. 测试医生通话
# 登录管理后台
# 进入诊单详情
# 点击"视频通话"按钮
# 查看浏览器控制台
预期输出:
签名获取成功: { userId: "doctor_1", sdkAppId: 1600127710 }
TUICallKit init 方法调用完成
等待完成,准备显示通话界面
初始化完成,准备发起通话...
不应该出现:
❌ Error: SDKAppID must be Number, current SDKAppID is string
3. 测试患者通话
# 打开患者测试页面
# 点击"初始化"按钮
# 查看浏览器控制台
应该能正常初始化,不报类型错误。
4. 验证数据类型
在浏览器控制台执行:
// 获取签名后
console.log(typeof res.sdkAppId) // 应该输出 "number"
// 传递给TUICallKit前
console.log(typeof Number(res.sdkAppId)) // 应该输出 "number"
技术细节
PHP类型转换
// 方式1:强制类型转换(推荐)
$intValue = (int)$stringValue;
// 方式2:intval函数
$intValue = intval($stringValue);
// 示例
$str = "1600127710";
$int = (int)$str; // 1600127710 (整数)
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
typeof 1600127710 // "number" ✅
typeof "1600127710" // "string" ❌
typeof Number("1600127710") // "number" ✅
// 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 - 管理员ID获取修复
- DOCTOR_IM_ACCOUNT.md - 医生账号导入功能
- QUICK_START.md - 快速开始指南
更新日志
2026-03-02
- ✅ 修复配置层:添加
(int)转换 - ✅ 修复Logic层:3处返回值添加
(int)转换 - ✅ 修复前端层:添加
Number()转换 - ✅ 采用多层防护策略,确保类型正确
现在SDKAppID类型正确,TUICallKit应该能正常初始化了! ✅