# 数美文本风险拦截实施方案

## 一、需求概述

在聊天页面（ConversationActivity）实现基于数美API的文本风险拦截功能，根据风险等级显示不同级别的警告提示。

## 二、风险等级与提示对应关系

根据数美接口返回的 `riskLevel` 字段：

| riskLevel | 风险等级 | 提示内容 | 处理方式 |
|-----------|---------|---------|---------|
| PASS | 通过 | 无提示 | 正常发送消息 |
| REVIEW | 二级警告 | "聊天内容存在风险，请谨慎交流" | 显示警告，允许用户选择是否发送 |
| REJECT | 三级警告 | "当前聊天内容可能存在风险，请谨慎核实信息真实性" | 显示警告，建议用户修改内容 |

## 三、技术实现方案

### 3.1 架构设计

```
ConversationFragment (聊天界面)
    ↓
TextRiskInterceptor (风险拦截器)
    ↓
ShumeiApiClient (数美API客户端)
    ↓
数美API服务器
```

### 3.2 核心组件

#### 3.2.1 TextRiskInterceptor（风险拦截器）

**职责**：
- 在消息发送前拦截文本消息
- 调用数美API进行风险检测
- 根据风险等级决定是否允许发送或显示警告

**关键方法**：
```java
public interface TextRiskInterceptor {
    /**
     * 检测文本风险
     * @param text 待检测文本
     * @param callback 检测结果回调
     */
    void checkTextRisk(String text, RiskCheckCallback callback);
    
    /**
     * 风险检测回调
     */
    interface RiskCheckCallback {
        void onRiskCheckResult(RiskCheckResult result);
    }
}
```

#### 3.2.2 ShumeiApiClient（数美API客户端）

**职责**：
- 封装数美API调用逻辑
- 处理请求参数构建
- 解析响应结果

**关键参数**：
- accessKey: "4OLLd2djEWRoCDVAbRAV"
- appId: "default"
- eventId: "text"
- type: "TEXTRISK"
- data.text: 待检测文本
- data.tokenId: 用户token
- data.ip: 用户IP
- data.deviceId: 设备ID
- data.nickname: 用户昵称

#### 3.2.3 RiskWarningDialog（风险警告对话框）

**职责**：
- 显示二级/三级警告提示
- 提供用户操作选项（继续发送/取消/修改）

### 3.3 集成点

#### 3.3.1 消息发送拦截点

在 `ConversationFragment` 或 `ConversationInputPanel` 中，消息发送前进行拦截：

**位置**：`ConversationInputPanel.sendTextMessage()` 或类似方法

**拦截流程**：
1. 用户点击发送按钮
2. 获取输入框文本内容
3. 调用 `TextRiskInterceptor.checkTextRisk()` 进行风险检测
4. 根据检测结果：
   - PASS：直接发送消息
   - REVIEW：显示二级警告，用户确认后发送
   - REJECT：显示三级警告，建议用户修改

#### 3.3.2 警告提示显示位置

**方案一：对话框提示（推荐）**
- 在消息发送前弹出警告对话框
- 显示风险等级和提示内容
- 提供"继续发送"和"取消"按钮

**方案二：消息气泡提示**
- 在聊天界面中插入系统警告消息
- 显示在风险消息的上方或下方
- 使用灰色背景，区别于普通消息

**方案三：顶部横幅提示**
- 在聊天界面顶部显示警告横幅
- 持续显示一段时间后自动消失
- 可手动关闭

### 3.4 数据模型

#### 3.4.1 RiskCheckResult（风险检测结果）

```java
public class RiskCheckResult {
    private String riskLevel;        // PASS, REVIEW, REJECT
    private String riskDescription; // 风险描述
    private String riskLabel1;       // 一级标签
    private String riskLabel2;       // 二级标签
    private String riskLabel3;       // 三级标签
    private double probability;      // 风险概率
    private String filteredText;     // 过滤后的文本
    private List<RiskLabel> allLabels; // 所有风险标签
}
```

#### 3.4.2 响应解析

根据数美接口文档，关键字段：
- `code`: 1100 表示成功
- `riskLevel`: 风险等级（PASS/REVIEW/REJECT）
- `riskDescription`: 风险描述
- `allLabels`: 所有检测到的风险标签数组
- `filteredText`: 过滤后的文本（敏感词被替换为**）

## 四、实现步骤

### 步骤1：创建数美API客户端

**文件**：`app/src/main/java/com/xunpaisoft/social/im/risk/ShumeiApiClient.java`

**功能**：
- 封装数美API调用
- 构建请求参数
- 解析响应结果
- 错误处理

**关键代码**：
```java
public class ShumeiApiClient {
    private static final String API_URL = "http://api-text-bj.fengkongcloud.com/text/v4";
    private static final String ACCESS_KEY = "4OLLd2djEWRoCDVAbRAV";
    private static final String APP_ID = "default";
    private static final String EVENT_ID = "text";
    private static final String TYPE = "TEXTRISK";
    
    public void checkTextRisk(String text, String tokenId, String ip, 
                             String deviceId, String nickname, 
                             Map<String, String> extra, 
                             RiskCheckCallback callback) {
        // 构建请求参数
        // 发送POST请求
        // 解析响应
        // 回调结果
    }
}
```

### 步骤2：创建风险拦截器

**文件**：`app/src/main/java/com/xunpaisoft/social/im/risk/TextRiskInterceptor.java`

**功能**：
- 在消息发送前拦截
- 调用数美API检测
- 根据风险等级处理

**关键代码**：
```java
public class TextRiskInterceptor {
    private ShumeiApiClient apiClient;
    
    public void interceptBeforeSend(String text, InterceptCallback callback) {
        // 获取用户信息（tokenId, ip, deviceId, nickname等）
        // 调用数美API检测
        // 根据riskLevel处理
    }
}
```

### 步骤3：创建警告对话框

**文件**：`app/src/main/java/com/xunpaisoft/social/im/risk/RiskWarningDialog.java`

**功能**：
- 显示二级/三级警告
- 提供用户操作选项

**关键代码**：
```java
public class RiskWarningDialog {
    public static void showReviewWarning(Context context, String message, 
                                        OnConfirmListener listener) {
        // 显示二级警告："聊天内容存在风险，请谨慎交流"
    }
    
    public static void showRejectWarning(Context context, String message, 
                                       OnConfirmListener listener) {
        // 显示三级警告："当前聊天内容可能存在风险，请谨慎核实信息真实性"
    }
}
```

### 步骤4：集成到ConversationFragment

**修改文件**：`uikit/src/main/java/cn/wildfire/chat/kit/conversation/ConversationFragment.java`

**集成点**：消息发送方法

**关键代码**：
```java
// 在发送文本消息前拦截
private void sendTextMessage(String text) {
    // 先进行风险检测
    textRiskInterceptor.interceptBeforeSend(text, new InterceptCallback() {
        @Override
        public void onInterceptResult(RiskCheckResult result) {
            if (result.getRiskLevel().equals("PASS")) {
                // 风险等级为PASS，直接发送
                doSendMessage(text);
            } else if (result.getRiskLevel().equals("REVIEW")) {
                // 二级警告
                RiskWarningDialog.showReviewWarning(
                    getContext(), 
                    "聊天内容存在风险，请谨慎交流",
                    new OnConfirmListener() {
                        @Override
                        public void onConfirm() {
                            doSendMessage(text);
                        }
                        @Override
                        public void onCancel() {
                            // 取消发送
                        }
                    }
                );
            } else if (result.getRiskLevel().equals("REJECT")) {
                // 三级警告
                RiskWarningDialog.showRejectWarning(
                    getContext(),
                    "当前聊天内容可能存在风险，请谨慎核实信息真实性",
                    new OnConfirmListener() {
                        @Override
                        public void onConfirm() {
                            // 仍然允许发送，但建议用户修改
                            doSendMessage(text);
                        }
                        @Override
                        public void onCancel() {
                            // 取消发送，建议用户修改内容
                        }
                    }
                );
            }
        }
        
        @Override
        public void onError(String error) {
            // 检测失败，可以选择直接发送或提示错误
            // 建议：检测失败时允许发送，避免影响用户体验
            doSendMessage(text);
        }
    });
}
```

## 五、性能优化

### 5.1 异步处理
- 风险检测在后台线程进行
- 不阻塞UI线程
- 显示加载提示

### 5.2 缓存机制
- 相同文本内容可以缓存检测结果
- 减少重复API调用
- 提高响应速度

### 5.3 超时处理
- 设置API调用超时时间（建议1-2秒）
- 超时后允许发送，避免影响用户体验
- 记录超时日志

### 5.4 频率限制
- 避免频繁调用API
- 可以设置检测间隔（如500ms内不重复检测）
- 减少服务器压力

## 六、用户体验设计

### 6.1 加载提示
- 检测过程中显示"正在检测..."提示
- 使用ProgressDialog或Toast
- 避免用户等待焦虑

### 6.2 警告对话框设计

**二级警告（REVIEW）**：
- 标题："风险提示"
- 内容："聊天内容存在风险，请谨慎交流"
- 按钮："继续发送" / "取消"
- 样式：黄色警告图标

**三级警告（REJECT）**：
- 标题："高风险提示"
- 内容："当前聊天内容可能存在风险，请谨慎核实信息真实性"
- 按钮："仍然发送" / "取消并修改"
- 样式：红色警告图标

### 6.3 错误处理
- API调用失败时，记录日志但不阻止发送
- 网络异常时，提示用户但允许发送
- 避免因检测失败影响正常聊天

## 七、数据获取

### 7.1 用户信息获取
- `tokenId`: 从用户登录信息获取
- `ip`: 从网络请求中获取或使用设备IP
- `deviceId`: 从设备信息获取（Android ID或设备唯一标识）
- `nickname`: 从当前用户信息获取

### 7.2 额外信息（extra）
- `topic`: 会话ID或话题ID
- `atId`: 发送者用户ID
- `room`: 群聊ID（如果是群聊）
- `receiveTokenId`: 接收者用户ID

## 八、测试方案

### 8.1 测试用例

**测试用例1：正常文本**
- 输入："你好"
- 预期：riskLevel = PASS，直接发送

**测试用例2：二级风险文本**
- 输入：包含敏感词但风险较低
- 预期：riskLevel = REVIEW，显示二级警告

**测试用例3：三级风险文本**
- 输入："加个好友吧 qq12345"
- 预期：riskLevel = REJECT，显示三级警告

**测试用例4：API调用失败**
- 模拟网络异常
- 预期：允许发送，记录错误日志

**测试用例5：API超时**
- 模拟超时情况
- 预期：允许发送，记录超时日志

### 8.2 性能测试
- API响应时间测试
- 并发检测测试
- 内存占用测试

## 九、注意事项

### 9.1 隐私保护
- 用户聊天内容需要加密传输
- 遵守数据保护法规
- 不存储敏感内容

### 9.2 用户体验
- 检测速度要快，避免用户等待
- 检测失败不应阻止正常聊天
- 警告提示要清晰但不影响使用

### 9.3 成本控制
- 数美API可能有调用费用
- 考虑是否需要限制检测频率
- 可以只检测文本消息，不检测图片/视频

### 9.4 兼容性
- 确保不影响现有聊天功能
- 向后兼容，不影响旧版本
- 考虑不同Android版本的兼容性

## 十、实施优先级

### 第一阶段（核心功能）
1. 实现数美API客户端
2. 实现风险拦截器
3. 集成到消息发送流程
4. 实现二级/三级警告对话框

### 第二阶段（优化）
1. 添加缓存机制
2. 优化性能
3. 完善错误处理
4. 添加日志记录

### 第三阶段（增强）
1. 支持更多消息类型检测
2. 添加统计功能
3. 优化用户体验
4. 添加配置管理

## 十一、代码示例

### 11.1 数美API调用示例

```java
// 构建请求参数
Map<String, Object> requestParams = new HashMap<>();
requestParams.put("accessKey", "4OLLd2djEWRoCDVAbRAV");
requestParams.put("appId", "default");
requestParams.put("eventId", "text");
requestParams.put("type", "TEXTRISK");

Map<String, Object> data = new HashMap<>();
data.put("text", text);
data.put("tokenId", getUserTokenId());
data.put("ip", getUserIp());
data.put("deviceId", getDeviceId());
data.put("nickname", getCurrentUserNickname());

Map<String, String> extra = new HashMap<>();
extra.put("topic", conversationId);
extra.put("atId", getCurrentUserId());
extra.put("room", getGroupId()); // 如果是群聊
extra.put("receiveTokenId", getTargetUserId());

data.put("extra", extra);
requestParams.put("data", data);

// 发送POST请求
// 解析响应，获取riskLevel
```

### 11.2 风险等级判断

```java
String riskLevel = result.getRiskLevel();
if ("PASS".equals(riskLevel)) {
    // 通过，直接发送
} else if ("REVIEW".equals(riskLevel)) {
    // 二级警告
} else if ("REJECT".equals(riskLevel)) {
    // 三级警告
}
```

## 十二、总结

本方案提供了完整的数美文本风险拦截实现思路，包括：
- 架构设计
- 核心组件
- 集成方案
- 性能优化
- 用户体验
- 测试方案

实施时建议分阶段进行，先实现核心功能，再逐步优化和完善。
