新增功能

This commit is contained in:
Your Name
2026-03-04 15:32:30 +08:00
parent a07e844c47
commit ab77f5488d
2266 changed files with 177942 additions and 3444 deletions
+300
View File
@@ -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;
// 方式2intval函数
$intValue = intval($stringValue);
// 示例
$str = "1600127710";
$int = (int)$str; // 1600127710 (整数)
```
### JavaScript类型转换
```javascript
// 方式1:Number构造函数(推荐)
const numValue = Number(strValue)
// 方式2parseInt函数
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应该能正常初始化了!**