# 小程序端与 Web 端 API 差异说明

## 重要提示 ⚠️

小程序端的 TUICallKit API 与 Web 端有显著差异，不能直接使用 Web 端的事件监听方式。

## 核心差异

### 1. 事件监听方式

#### ❌ Web 端方式（小程序端不支持）
```javascript
// Web 端可以这样使用
TUICallKitServer.setCallback({
  statusChanged: handleStatusChange,
  afterCalling: handleAfterCalling
});

// 或者
TUICallKitAPI.on('onCallReceived', (data) => {
  console.log('收到来电', data);
});
```

#### ✅ 小程序端正确方式
```javascript
// 小程序端不需要手动监听事件
// TUICallKit 组件会自动处理来电显示

// 只需要：
// 1. 初始化 TUICallKit
await TUICallKitAPI.init({
  sdkAppID: Number(sdkAppId),
  userID: userId,
  userSig: userSig,
});

// 2. 挂载 TUICallKit 组件
<TUICallKit v-if="isLogin"></TUICallKit>

// 组件会自动：
// - 监听来电
// - 显示来电界面
// - 处理接听/拒绝
// - 显示通话界面
```

### 2. 状态管理

#### Web 端
使用回调函数处理状态变化：
```javascript
const handleStatusChange = ({ oldStatus, newStatus }) => {
  if (newStatus === STATUS.CALLING_C2C_VIDEO) {
    console.log('通话已接通');
  }
};
```

#### 小程序端
使用 TUIStore 监听状态（如果需要）：
```javascript
import { TUIStore, StoreName, NAME } from '../src/index';

// 监听通话状态
TUIStore.watch(StoreName.CALL, {
  [NAME.CALL_STATUS]: (newValue) => {
    console.log('通话状态变化:', newValue);
  }
});
```

### 3. 发起通话

#### Web 端
```javascript
await TUICallKitServer.call({
  userID: 'patient_2',
  type: TUICallType.VIDEO_CALL
});
```

#### 小程序端
```javascript
await TUICallKitAPI.calls({
  userIDList: ['doctor_1'],
  type: 2,  // 2 表示视频通话
});
```

注意差异：
- Web 端：`call()` 方法，单数
- 小程序端：`calls()` 方法，复数
- Web 端：`userID` 参数，单个用户
- 小程序端：`userIDList` 参数，用户数组

## 小程序端正确的使用流程

### 步骤 1：初始化

```javascript
const loginHandler = async () => {
  // 1. 获取签名
  const signatureData = await getSignatureFromServer(patientId.value);
  const { sdkAppId, userId, userSig } = signatureData;
  
  // 2. 初始化 TUICallKit
  await TUICallKitAPI.init({
    sdkAppID: Number(sdkAppId),
    userID: userId,
    userSig: userSig,
  });
  
  console.log('TUICallKit 初始化成功');
  
  // 3. 设置登录状态（触发组件挂载）
  isLogin.value = true;
  
  // 完成！不需要手动设置事件监听
};
```

### 步骤 2：挂载组件

```vue
<template>
  <view>
    <!-- 登录后才挂载组件 -->
    <TUICallKit v-if="isLogin"></TUICallKit>
    
    <!-- 登录界面 -->
    <view class="loginBox">
      <!-- ... -->
    </view>
  </view>
</template>
```

### 步骤 3：自动处理来电

当有来电时，TUICallKit 组件会自动：
1. 检测到来电信号
2. 显示来电界面
3. 播放铃声
4. 显示接听/拒绝按钮
5. 处理用户操作

**你不需要做任何额外的事情！**

### 步骤 4：发起通话（可选）

```javascript
const callHandler = async () => {
  let targetUserId = patientId.value;
  
  // 如果是纯数字，添加前缀
  if (/^\d+$/.test(patientId.value)) {
    targetUserId = `doctor_${patientId.value}`;
  }
  
  // 发起通话
  await TUICallKitAPI.calls({
    userIDList: [targetUserId],
    type: 2,  // 2 = 视频通话
  });
};
```

## 常见错误

### 错误 1：使用 .on() 方法

```javascript
// ❌ 错误：小程序端不支持
TUICallKitAPI.on('onCallReceived', (data) => {
  console.log('收到来电', data);
});

// 错误信息：
// TUICallKitAPI.on is not a function
```

**解决：** 删除所有 `.on()` 调用，让组件自动处理。

### 错误 2：使用 setCallback

```javascript
// ❌ 错误：小程序端不支持
TUICallKitAPI.setCallback({
  statusChanged: handleStatusChange
});

// 错误信息：
// TUICallKitAPI.setCallback is not a function
```

**解决：** 删除 `setCallback` 调用，使用 TUIStore 监听（如果需要）。

### 错误 3：使用 call() 而不是 calls()

```javascript
// ❌ 错误：小程序端使用 calls()
await TUICallKitAPI.call({
  userID: 'doctor_1',
  type: 2
});

// 错误信息：
// TUICallKitAPI.call is not a function
```

**解决：** 使用 `calls()` 方法，参数为 `userIDList` 数组。

## 如何监听状态（高级用法）

如果你确实需要监听通话状态，使用 TUIStore：

```javascript
import { TUIStore, StoreName, NAME, CallStatus } from '../src/index';

// 在 setup 中
onMounted(() => {
  // 监听通话状态
  TUIStore.watch(StoreName.CALL, {
    [NAME.CALL_STATUS]: (newStatus) => {
      console.log('通话状态变化:', newStatus);
      
      switch (newStatus) {
        case CallStatus.IDLE:
          console.log('空闲状态');
          break;
        case CallStatus.WAITING:
          console.log('等待接听');
          break;
        case CallStatus.CONNECTED:
          console.log('通话中');
          break;
      }
    },
    
    [NAME.IS_GROUP]: (isGroup) => {
      console.log('是否群组通话:', isGroup);
    },
    
    [NAME.CALL_ROLE]: (role) => {
      console.log('通话角色:', role);
    }
  });
});

// 在 onUnmounted 中取消监听
onUnmounted(() => {
  TUIStore.unwatch(StoreName.CALL, {
    [NAME.CALL_STATUS]: () => {},
    [NAME.IS_GROUP]: () => {},
    [NAME.CALL_ROLE]: () => {}
  });
});
```

## 可用的 TUIStore 监听项

```javascript
// 通话状态
NAME.CALL_STATUS        // 通话状态（IDLE, WAITING, CONNECTED）
NAME.CALL_ROLE          // 通话角色（CALLER, CALLEE）
NAME.CALL_MEDIA_TYPE    // 通话类型（VIDEO, AUDIO）
NAME.IS_GROUP           // 是否群组通话

// 用户信息
NAME.LOCAL_USER_INFO    // 本地用户信息
NAME.REMOTE_USER_INFO_LIST  // 远程用户列表

// 设备状态
NAME.IS_MUTED           // 是否静音
NAME.IS_CAMERA_ON       // 摄像头是否开启
NAME.IS_EAR_PHONE       // 是否使用听筒

// 其他
NAME.CALL_DURATION      // 通话时长
NAME.CALLER_USER_INFO   // 主叫用户信息
```

## 完整示例

```vue
<template>
  <view>
    <TUICallKit v-if="isLogin"></TUICallKit>
    <view class="loginBox">
      <input v-model="patientId" placeholder="请输入患者ID" />
      <button @click="loginHandler">登录</button>
      <button v-if="isLogin" @click="callHandler">呼叫</button>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { TUICallKitAPI, TUIStore, StoreName, NAME, CallStatus } from "../src/index";
import TUICallKit from "../src/Components/TUICallKit";

const patientId = ref("2");
const isLogin = ref(false);

// 登录
const loginHandler = async () => {
  try {
    // 获取签名
    const signatureData = await getSignatureFromServer(patientId.value);
    const { sdkAppId, userId, userSig } = signatureData;
    
    // 初始化
    await TUICallKitAPI.init({
      sdkAppID: Number(sdkAppId),
      userID: userId,
      userSig: userSig,
    });
    
    console.log('初始化成功');
    isLogin.value = true;
    
  } catch (error) {
    console.error('登录失败:', error);
  }
};

// 发起通话
const callHandler = async () => {
  try {
    await TUICallKitAPI.calls({
      userIDList: ['doctor_1'],
      type: 2,
    });
  } catch (error) {
    console.error('发起通话失败:', error);
  }
};

// 监听状态（可选）
onMounted(() => {
  TUIStore.watch(StoreName.CALL, {
    [NAME.CALL_STATUS]: (newStatus) => {
      console.log('通话状态:', newStatus);
    }
  });
});

onUnmounted(() => {
  TUIStore.unwatch(StoreName.CALL, {
    [NAME.CALL_STATUS]: () => {}
  });
});
</script>
```

## 总结

### ✅ 小程序端应该做的

1. 初始化 TUICallKit
2. 挂载 TUICallKit 组件
3. 让组件自动处理来电

### ❌ 小程序端不应该做的

1. 使用 `.on()` 方法监听事件
2. 使用 `setCallback()` 设置回调
3. 使用 `call()` 而不是 `calls()`
4. 手动显示来电界面

### 🎯 关键点

- **TUICallKit 组件会自动处理一切**
- **你只需要初始化和挂载组件**
- **如果需要监听状态，使用 TUIStore**
- **不要尝试使用 Web 端的 API**

---

**最后更新：** 2024-03-04
**版本：** 1.0
