89fc42819d
- 新增 AI 场景路由控制器和管理接口 - 新增 ASR 语音识别服务及前后端集成 - 同步 AI Runtime 客户端到 Web/小程序/Life-Script - 完善 AI 配置测试修复和管理后台路由配置 - 新增数据库迁移脚本 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
227 lines
7.0 KiB
Markdown
227 lines
7.0 KiB
Markdown
# AI 配置管理接口测试修复实施计划
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 删除废弃的旧 AI 配置页面,在新系统测试对话框中增加非流式测试功能
|
||
|
||
**Architecture:** 路由已正确指向新系统 `AiRoutingList.vue`,只需删除旧文件残留并增强测试对话框。后端接口 `testAiRuntime` 已存在,只需在 API 层和 UI 层连接。
|
||
|
||
**Tech Stack:** Vue 3, Element Plus, TypeScript
|
||
|
||
---
|
||
|
||
### 前置确认:检查生产数据库配置
|
||
|
||
- [ ] 在生产数据库上执行以下查询,确认 Dify provider 和 endpoint 状态
|
||
|
||
```sql
|
||
-- 检查 Dify provider
|
||
SELECT id, provider_code, provider_name, provider_type, base_url, is_enabled
|
||
FROM t_ai_provider WHERE provider_code = 'dify_default';
|
||
|
||
-- 检查 Dify endpoints
|
||
SELECT id, endpoint_code, endpoint_name, provider_id, api_path, support_stream, is_enabled
|
||
FROM t_ai_endpoint_config WHERE endpoint_code LIKE 'dify.%';
|
||
|
||
-- 检查场景绑定
|
||
SELECT id, scene_code, scene_name, endpoint_id, is_enabled, required_stream
|
||
FROM t_ai_scene_binding WHERE is_enabled = 1;
|
||
```
|
||
|
||
- [ ] 如果 Dify provider `is_enabled = 0`,执行:
|
||
```sql
|
||
UPDATE t_ai_provider SET is_enabled = 1 WHERE provider_code = 'dify_default';
|
||
```
|
||
|
||
- [ ] 如果 Dify endpoints `is_enabled = 0`,执行:
|
||
```sql
|
||
UPDATE t_ai_endpoint_config SET is_enabled = 1 WHERE endpoint_code LIKE 'dify.%';
|
||
```
|
||
|
||
### Task 1: 删除废弃的旧 AI 配置页面
|
||
|
||
**Files:**
|
||
- Delete: `web-admin/src/views/aiconfig/AiConfigList.vue`
|
||
|
||
- [ ] 删除旧页面文件
|
||
|
||
```bash
|
||
rm web-admin/src/views/aiconfig/AiConfigList.vue
|
||
```
|
||
|
||
### Task 2: 在 API 层导出非流式测试函数
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/api/aiconfig.ts`
|
||
|
||
- [ ] 确认 `testAiRuntime` 已存在(已确认在第 263 行)
|
||
|
||
```typescript
|
||
export function testAiRuntime(data: AiRuntimeRequest) {
|
||
return request({ url: '/ai/runtime/test', method: 'post', data })
|
||
}
|
||
```
|
||
|
||
已存在,无需修改。但需要确认 `AiRoutingList.vue` 中是否 import 了这个函数。
|
||
|
||
检查 `web-admin/src/views/aiconfig/AiRoutingList.vue` 的 import 语句(当前第 269-281 行):
|
||
- 当前 import 了 `streamAiRuntime`,**没有 import** `testAiRuntime`
|
||
- 需要在 import 列表中添加 `testAiRuntime`
|
||
|
||
### Task 3: 在测试对话框中增加非流式测试按钮
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/views/aiconfig/AiRoutingList.vue`
|
||
|
||
- [ ] 在 import 中添加 `testAiRuntime`
|
||
|
||
修改第 269-281 行的 import 语句:
|
||
|
||
```typescript
|
||
import {
|
||
deleteAiEndpoint,
|
||
deleteAiProvider,
|
||
deleteAiScene,
|
||
listAiCallLogs,
|
||
listAiEndpoints,
|
||
listAiProviders,
|
||
listAiScenes,
|
||
saveAiEndpoint,
|
||
saveAiProvider,
|
||
saveAiScene,
|
||
streamAiRuntime,
|
||
testAiRuntime // ← 新增
|
||
} from '@/api/aiconfig'
|
||
```
|
||
|
||
- [ ] 在测试对话框 footer 中增加「非流式测试」按钮
|
||
|
||
找到第 257-261 行的 `<template #footer>`,修改为:
|
||
|
||
```vue
|
||
<template #footer>
|
||
<el-button @click="testDialog = false">关闭</el-button>
|
||
<el-button :loading="testing" @click="submitNonStreamTest">非流式测试</el-button>
|
||
<el-button type="primary" :loading="testing" @click="submitRuntimeTest">流式测试</el-button>
|
||
</template>
|
||
```
|
||
|
||
- [ ] 添加 `nonStreamResult` 响应式变量
|
||
|
||
在 `testResult` 声明后面(第 296 行)添加:
|
||
|
||
```typescript
|
||
const nonStreamResult = ref<AiRuntimeTestResponse | null>(null)
|
||
```
|
||
|
||
- [ ] 实现 `submitNonStreamTest` 函数
|
||
|
||
在 `submitRuntimeTest` 函数(第 451 行)之前添加:
|
||
|
||
```typescript
|
||
async function submitNonStreamTest() {
|
||
let inputs: Record<string, any>
|
||
try {
|
||
inputs = JSON.parse(testInputsJson.value || '{}')
|
||
} catch (error) {
|
||
ElMessage.error('入参 JSON 格式不正确')
|
||
return
|
||
}
|
||
testing.value = true
|
||
try {
|
||
const res = await testAiRuntime({ sceneCode: testForm.sceneCode, inputs })
|
||
nonStreamResult.value = res.data as AiRuntimeTestResponse
|
||
if (nonStreamResult.value.status === 'success') {
|
||
ElMessage.success('非流式测试成功')
|
||
} else {
|
||
ElMessage.error(`测试失败: ${nonStreamResult.value.errorMessage || nonStreamResult.value.errorCode}`)
|
||
}
|
||
await loadAll()
|
||
} catch (error: any) {
|
||
nonStreamResult.value = {
|
||
sceneCode: testForm.sceneCode,
|
||
status: 'failed',
|
||
errorMessage: error?.message || '非流式测试失败'
|
||
} as AiRuntimeTestResponse
|
||
ElMessage.error(error?.message || '非流式测试失败')
|
||
} finally {
|
||
testing.value = false
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] 在测试对话框中展示非流式测试结果
|
||
|
||
在 `submitRuntimeTest` 相关的 `<el-alert>` 和 `<pre>` 展示块(第 250-256 行)之前,添加非流式测试结果的展示:
|
||
|
||
```vue
|
||
<el-alert
|
||
v-if="nonStreamResult"
|
||
:type="nonStreamResult.status === 'success' ? 'success' : 'error'"
|
||
:title="nonStreamResult.status === 'success' ? '非流式测试成功' : '非流式测试失败'"
|
||
show-icon
|
||
:closable="false"
|
||
style="margin-bottom: 12px;"
|
||
/>
|
||
<pre v-if="nonStreamResult" class="test-output">{{ nonStreamResult.output || nonStreamResult.errorMessage || '暂无输出' }}</pre>
|
||
|
||
<el-alert
|
||
v-if="testResult"
|
||
:type="testResult.status === 'success' ? 'success' : 'error'"
|
||
:title="testResult.status === 'success' ? '流式测试成功' : '流式测试失败'"
|
||
show-icon
|
||
/>
|
||
<pre v-if="testResult" class="test-output">{{ testResult.output || testResult.errorMessage || '暂无输出' }}</pre>
|
||
```
|
||
|
||
- [ ] 在打开测试对话框时清空非流式结果
|
||
|
||
在 `openRuntimeTest` 函数(第 400-404 行)中添加:
|
||
|
||
```typescript
|
||
function openRuntimeTest() {
|
||
testForm.sceneCode = scenes.value.find(item => item.isEnabled === 1 && item.endpointId)?.sceneCode || scenes.value[0]?.sceneCode || ''
|
||
testResult.value = null
|
||
nonStreamResult.value = null // ← 新增
|
||
testDialog.value = true
|
||
}
|
||
```
|
||
|
||
- [ ] 在 TypeScript 类型定义中确保 `AiRuntimeTestResponse` 包含所有必要字段
|
||
|
||
检查 `web-admin/src/types/aiconfig.ts` 中的 `AiRuntimeTestResponse` 定义,确保包含:
|
||
|
||
```typescript
|
||
export interface AiRuntimeTestResponse {
|
||
sceneCode: string
|
||
status: 'success' | 'failed'
|
||
output?: string
|
||
streamChunks?: number
|
||
durationMs?: number
|
||
errorCode?: string
|
||
errorMessage?: string
|
||
}
|
||
```
|
||
|
||
### Task 4: 浏览器验证
|
||
|
||
- [ ] 启动 web-admin 开发服务器
|
||
|
||
```bash
|
||
cd web-admin && npm run dev
|
||
```
|
||
|
||
- [ ] 在浏览器中访问管理后台 `http://localhost:5174/emotion-museum-admin/`
|
||
|
||
- [ ] 导航到「AI 配置管理」页面,确认旧页面已删除、新页面正常显示
|
||
|
||
- [ ] 在「场景绑定」Tab 中点击「流式测试」按钮,确认测试对话框正常打开
|
||
|
||
- [ ] 确认测试对话框中有两个按钮:「非流式测试」和「流式测试」
|
||
|
||
- [ ] 选择一个场景(如 `script_generate`),输入入参 `{ "prompt": "请用一句中文回复测试成功。" }`,点击「非流式测试」,确认返回成功结果
|
||
|
||
- [ ] 点击「流式测试」,确认流式输出正常
|
||
|
||
- [ ] 确认浏览器 Console 中没有任何错误
|