001project_wildgrowth/backend/scripts/test-course-generation-flow.ts

383 lines
11 KiB
TypeScript
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 测试课程生成完整流程
* 使用方法ts-node backend/scripts/test-course-generation-flow.ts
*/
import axios from 'axios';
import * as dotenv from 'dotenv';
import path from 'path';
// 加载环境变量
dotenv.config({ path: path.join(__dirname, '../.env.test') });
const BASE_URL = process.env.API_BASE_URL || 'http://localhost:3000';
const TEST_USER_EMAIL = process.env.TEST_USER_EMAIL || 'test@example.com';
const TEST_USER_PASSWORD = process.env.TEST_USER_PASSWORD || 'test123456';
interface CreateCourseResponse {
success: boolean;
data: {
courseId: string;
taskId: string;
status: string;
generationStyle?: string;
message?: string;
};
}
interface CourseStatusResponse {
success: boolean;
data: {
courses: Array<{
id: string;
title: string;
generation_status: string | null;
generation_progress: number | null;
status: string;
progress: number;
error_message?: string | null;
}>;
};
}
interface TaskResponse {
success: boolean;
data: {
task: {
id: string;
status: string;
generationStyle: string | null;
outline: any;
suggestedTitle: string | null;
errorMessage: string | null;
};
};
}
interface PromptLogResponse {
success: boolean;
data: {
logs: Array<{
id: string;
promptType: string;
taskId: string | null;
status: string;
duration: number | null;
tokensUsed: number | null;
errorMessage: string | null;
createdAt: string;
}>;
total: number;
};
}
// 测试内容
const TEST_CONTENT = `
# 如何有效社交
社交是每个人都需要掌握的重要技能。在现代社会,良好的人际关系不仅能帮助我们获得更多机会,还能提升我们的生活质量。
## 第一章:理解社交的本质
社交不仅仅是简单的聊天和应酬,它更是一种建立信任、传递价值的过程。真正的社交应该是双向的,既要有给予,也要有收获。
### 1.1 社交的核心价值
社交的核心在于建立有意义的人际关系。这种关系应该基于:
- 相互尊重
- 价值交换
- 长期维护
### 1.2 常见的社交误区
很多人对社交存在误解:
- 认为社交就是应酬和喝酒
- 认为社交需要花费大量时间
- 认为社交是外向者的专利
## 第二章:提升社交能力的方法
### 2.1 培养倾听能力
倾听是社交的基础。一个好的倾听者应该:
- 专注对方的表达
- 理解对方的情绪
- 给予适当的反馈
### 2.2 学会表达自己
表达自己同样重要:
- 清晰表达观点
- 适当展示价值
- 保持真诚和自然
## 第三章:维护人际关系
### 3.1 定期联系
不要等到需要帮助时才联系朋友:
- 定期问候
- 分享有价值的信息
- 在对方需要时提供帮助
### 3.2 维护关系
关系的维护需要:
- 时间和精力
- 真诚的态度
- 持续的价值交换
`;
async function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
interface LoginResponse {
success: boolean;
data: {
token: string;
user: any;
};
}
async function login(): Promise<string> {
console.log('🔐 登录获取 Token...');
// 先尝试注册(如果用户不存在)
try {
console.log('📝 尝试注册测试用户...');
await axios.post(`${BASE_URL}/api/auth/register`, {
email: TEST_USER_EMAIL,
password: TEST_USER_PASSWORD,
username: '测试用户',
});
console.log('✅ 注册成功');
} catch (regError: any) {
if (regError.response?.status === 400 && regError.response?.data?.message?.includes('已存在')) {
console.log(' 用户已存在,直接登录');
} else {
console.log(`⚠️ 注册失败(可能用户已存在): ${regError.response?.data?.message || regError.message}`);
}
}
// 登录
try {
const response = await axios.post<LoginResponse>(`${BASE_URL}/api/auth/login`, {
email: TEST_USER_EMAIL,
password: TEST_USER_PASSWORD,
});
if (response.data.success && response.data.data.token) {
console.log('✅ 登录成功');
return response.data.data.token;
} else {
throw new Error('登录失败:未返回 Token');
}
} catch (error: any) {
const errorMsg = error.response?.data?.message || error.message;
throw new Error(`登录失败: ${errorMsg}`);
}
}
async function createCourse(token: string, style: 'full' | 'essence' | 'one-page' = 'essence'): Promise<CreateCourseResponse['data']> {
console.log(`\n📝 创建课程(风格: ${style}...`);
const response = await axios.post<CreateCourseResponse>(
`${BASE_URL}/api/ai/content/upload`,
{
content: TEST_CONTENT,
style: style,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (!response.data.success) {
throw new Error('创建课程失败');
}
console.log(`✅ 课程创建成功:`);
console.log(` - Course ID: ${response.data.data.courseId}`);
console.log(` - Task ID: ${response.data.data.taskId}`);
console.log(` - 状态: ${response.data.data.status}`);
return response.data.data;
}
async function checkCourseStatus(token: string, courseId: string, maxWait: number = 300000): Promise<void> {
console.log(`\n⏳ 等待课程生成完成(最多 ${maxWait / 1000} 秒)...`);
const startTime = Date.now();
let lastProgress = -1;
while (Date.now() - startTime < maxWait) {
try {
const response = await axios.get<CourseStatusResponse>(
`${BASE_URL}/api/my-courses`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const course = response.data.data.courses.find(c => c.id === courseId);
if (!course) {
console.log('⚠️ 课程未找到,继续等待...');
await sleep(3000);
continue;
}
const progress = course.generation_progress ? Math.round(course.generation_progress * 100) : 0;
if (progress !== lastProgress) {
console.log(`📊 生成进度: ${progress}% (状态: ${course.generation_status || course.status})`);
lastProgress = progress;
}
if (course.generation_status === 'completed' || course.status === 'completed') {
console.log(`\n✅ 课程生成完成!`);
console.log(` - 标题: ${course.title}`);
console.log(` - 最终状态: ${course.status}`);
return;
}
if (course.generation_status === 'failed' || course.status === 'failed') {
console.log(`\n❌ 课程生成失败!`);
console.log(` - 错误信息: ${course.error_message || '未知错误'}`);
throw new Error(`生成失败: ${course.error_message || '未知错误'}`);
}
await sleep(3000);
} catch (error: any) {
if (error.response?.status === 401) {
throw new Error('Token 已过期,请重新登录');
}
console.log(`⚠️ 查询状态失败: ${error.message},继续重试...`);
await sleep(3000);
}
}
throw new Error('生成超时');
}
async function checkTaskStatus(token: string, taskId: string): Promise<void> {
console.log(`\n📋 查询任务详情 (Task ID: ${taskId})...`);
try {
const response = await axios.get<TaskResponse>(
`${BASE_URL}/api/ai/content/tasks/${taskId}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const task = response.data.data.task;
console.log(`✅ 任务状态:`);
console.log(` - 状态: ${task.status}`);
console.log(` - 风格: ${task.generationStyle || '未设置'}`);
console.log(` - 标题: ${task.suggestedTitle || '未生成'}`);
console.log(` - 大纲: ${task.outline ? '已生成' : '未生成'}`);
if (task.errorMessage) {
console.log(` - 错误: ${task.errorMessage}`);
}
} catch (error: any) {
console.log(`⚠️ 查询任务失败: ${error.message}`);
}
}
async function checkPromptLogs(token: string, taskId: string): Promise<void> {
console.log(`\n📝 查询 AI 调用日志 (Task ID: ${taskId})...`);
try {
const response = await axios.get<PromptLogResponse>(
`${BASE_URL}/api/ai/prompts/logs?taskId=${taskId}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const logs = response.data.data.logs;
console.log(`✅ 找到 ${logs.length} 条日志记录:`);
logs.forEach((log, index) => {
console.log(`\n ${index + 1}. ${log.promptType} (${log.status})`);
console.log(` - 耗时: ${log.duration ? `${log.duration}ms` : 'N/A'}`);
console.log(` - Tokens: ${log.tokensUsed || 'N/A'}`);
console.log(` - 时间: ${new Date(log.createdAt).toLocaleString()}`);
if (log.errorMessage) {
console.log(` - 错误: ${log.errorMessage}`);
}
});
} catch (error: any) {
console.log(`⚠️ 查询日志失败: ${error.message}`);
}
}
async function main() {
console.log('🧪 开始测试课程生成完整流程\n');
console.log(`📍 API 地址: ${BASE_URL}`);
console.log(`👤 测试用户: ${TEST_USER_EMAIL}\n`);
try {
// 1. 登录
const token = await login();
// 2. 创建课程(测试三种风格)
const styles: Array<'full' | 'essence' | 'one-page'> = ['essence', 'full', 'one-page'];
for (const style of styles) {
console.log(`\n${'='.repeat(60)}`);
console.log(`测试风格: ${style}`);
console.log('='.repeat(60));
try {
// 创建课程
const { courseId, taskId } = await createCourse(token, style);
// 查询任务状态
await checkTaskStatus(token, taskId);
// 等待生成完成
await checkCourseStatus(token, courseId);
// 查询日志
await checkPromptLogs(token, taskId);
console.log(`\n✅ 风格 ${style} 测试完成!`);
// 等待一下再进行下一个测试
if (style !== styles[styles.length - 1]) {
console.log('\n⏸ 等待 5 秒后进行下一个测试...');
await sleep(5000);
}
} catch (error: any) {
console.error(`\n❌ 风格 ${style} 测试失败: ${error.message}`);
// 继续测试下一个风格
}
}
console.log(`\n${'='.repeat(60)}`);
console.log('🎉 所有测试完成!');
console.log('='.repeat(60));
} catch (error: any) {
console.error(`\n❌ 测试失败: ${error.message}`);
if (error.stack) {
console.error(error.stack);
}
process.exit(1);
}
}
// 运行测试
main().catch(console.error);