fix
This commit is contained in:
261
docs/ENHANCED_BUILD_GUIDE.md
Normal file
261
docs/ENHANCED_BUILD_GUIDE.md
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
# 增强版构建指南 - 逐步添加功能
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
既然基本版本可以工作,现在我们逐步添加更多功能,包括实际的服务模块和AI功能。
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 1. 构建增强版本
|
||||||
|
|
||||||
|
在 `python_core` 目录下运行:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# Windows
|
||||||
|
build_enhanced.bat
|
||||||
|
|
||||||
|
# 或者手动构建
|
||||||
|
python -m PyInstaller build_enhanced.spec
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 测试功能
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# 运行功能测试
|
||||||
|
python test_functionality.py
|
||||||
|
|
||||||
|
# 手动测试基础功能
|
||||||
|
dist\mixvideo-python-core.exe --version
|
||||||
|
dist\mixvideo-python-core.exe --module test --action hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 新增功能
|
||||||
|
|
||||||
|
### 1. **增强版入口文件** (`main_simple.py`)
|
||||||
|
|
||||||
|
- ✅ 完整的模块映射系统
|
||||||
|
- ✅ 多种导入方式支持
|
||||||
|
- ✅ 模拟服务回退机制
|
||||||
|
- ✅ 详细的错误处理
|
||||||
|
- ✅ JSON-RPC兼容的响应格式
|
||||||
|
|
||||||
|
### 2. **模拟服务系统** (`mock_services.py`)
|
||||||
|
|
||||||
|
提供完整的模拟服务,确保在实际服务不可用时也能正常工作:
|
||||||
|
|
||||||
|
- ✅ 模板管理模拟
|
||||||
|
- ✅ 项目管理模拟
|
||||||
|
- ✅ 媒体管理模拟
|
||||||
|
- ✅ 音频管理模拟
|
||||||
|
- ✅ 模特管理模拟
|
||||||
|
- ✅ 资源分类管理模拟
|
||||||
|
- ✅ 文件管理模拟
|
||||||
|
- ✅ AI视频生成模拟
|
||||||
|
|
||||||
|
### 3. **增强版构建配置** (`build_enhanced.spec`)
|
||||||
|
|
||||||
|
- ✅ 分层的隐藏导入配置
|
||||||
|
- ✅ 第三方库支持
|
||||||
|
- ✅ 图像处理库集成
|
||||||
|
- ✅ 智能排除不需要的模块
|
||||||
|
|
||||||
|
### 4. **功能测试系统** (`test_functionality.py`)
|
||||||
|
|
||||||
|
- ✅ 自动化测试所有模块
|
||||||
|
- ✅ 详细的测试报告
|
||||||
|
- ✅ JSON格式的测试结果
|
||||||
|
|
||||||
|
## 🧪 测试用例
|
||||||
|
|
||||||
|
### 基础功能测试
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# 版本信息
|
||||||
|
dist\mixvideo-python-core.exe --version
|
||||||
|
|
||||||
|
# 测试模块
|
||||||
|
dist\mixvideo-python-core.exe --module test --action hello
|
||||||
|
dist\mixvideo-python-core.exe --module test --action echo --params "{\"message\":\"Hello World\"}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 服务模块测试
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# 模板管理
|
||||||
|
dist\mixvideo-python-core.exe --module template_manager --action get_templates
|
||||||
|
|
||||||
|
# 项目管理
|
||||||
|
dist\mixvideo-python-core.exe --module project_manager --action get_projects
|
||||||
|
|
||||||
|
# 媒体管理
|
||||||
|
dist\mixvideo-python-core.exe --module media_manager --action get_media_list
|
||||||
|
|
||||||
|
# 文件管理
|
||||||
|
dist\mixvideo-python-core.exe --module file_manager --action list_files --params "{\"path\":\".\"}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI模块测试
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# AI环境测试
|
||||||
|
dist\mixvideo-python-core.exe --module ai_video --action test_environment
|
||||||
|
|
||||||
|
# 视频生成器状态
|
||||||
|
dist\mixvideo-python-core.exe --module video_generator --action get_status
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 预期输出
|
||||||
|
|
||||||
|
### 成功的响应格式
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": true,
|
||||||
|
"msg": "操作完成",
|
||||||
|
"data": {
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"id": "template_001",
|
||||||
|
"name": "商业宣传模板",
|
||||||
|
"description": "适用于商业宣传的视频模板",
|
||||||
|
"duration": 30,
|
||||||
|
"created_at": "2024-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2,
|
||||||
|
"timestamp": "2024-01-15T10:30:00.000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 错误的响应格式
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": false,
|
||||||
|
"msg": "Failed to execute template_manager.get_templates: Module not found",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 故障排除
|
||||||
|
|
||||||
|
### 1. 构建失败
|
||||||
|
|
||||||
|
**问题**: PyInstaller构建失败
|
||||||
|
**解决**:
|
||||||
|
```cmd
|
||||||
|
# 检查依赖
|
||||||
|
python -c "import requests, PIL, json"
|
||||||
|
|
||||||
|
# 使用简化版本
|
||||||
|
python -m PyInstaller build_simple.spec
|
||||||
|
|
||||||
|
# 逐步添加隐藏导入
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 模块导入错误
|
||||||
|
|
||||||
|
**问题**: 某些模块无法导入
|
||||||
|
**解决**:
|
||||||
|
- 检查 `build_enhanced.spec` 中的 `hiddenimports`
|
||||||
|
- 使用模拟服务作为回退
|
||||||
|
- 添加缺失的模块到隐藏导入列表
|
||||||
|
|
||||||
|
### 3. 功能测试失败
|
||||||
|
|
||||||
|
**问题**: 某些功能测试失败
|
||||||
|
**解决**:
|
||||||
|
```cmd
|
||||||
|
# 查看详细错误
|
||||||
|
dist\mixvideo-python-core.exe --module template_manager --action get_templates --verbose
|
||||||
|
|
||||||
|
# 检查测试结果
|
||||||
|
type test_results.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 性能优化
|
||||||
|
|
||||||
|
### 1. 减少包大小
|
||||||
|
|
||||||
|
在 `build_enhanced.spec` 中调整 `excludes` 列表:
|
||||||
|
|
||||||
|
```python
|
||||||
|
excludes = [
|
||||||
|
'tkinter',
|
||||||
|
'matplotlib',
|
||||||
|
'scipy',
|
||||||
|
'pandas',
|
||||||
|
'numpy', # 如果不需要
|
||||||
|
'cv2', # 如果不需要
|
||||||
|
# 添加其他不需要的模块
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 提升启动速度
|
||||||
|
|
||||||
|
- 使用 `--onefile` 模式
|
||||||
|
- 启用 UPX 压缩
|
||||||
|
- 减少不必要的隐藏导入
|
||||||
|
|
||||||
|
## 🔄 集成到Tauri
|
||||||
|
|
||||||
|
### 1. 复制可执行文件
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
mkdir ..\src-tauri\binaries
|
||||||
|
copy dist\mixvideo-python-core.exe ..\src-tauri\binaries\
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 更新Tauri配置
|
||||||
|
|
||||||
|
在 `src-tauri/tauri.conf.json` 中添加:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"bundle": {
|
||||||
|
"externalBin": [
|
||||||
|
{
|
||||||
|
"name": "mixvideo-python-core",
|
||||||
|
"src": "binaries/mixvideo-python-core",
|
||||||
|
"targets": ["all"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 测试集成
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# 开发模式测试
|
||||||
|
cargo tauri dev
|
||||||
|
|
||||||
|
# 生产构建
|
||||||
|
cargo tauri build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 下一步计划
|
||||||
|
|
||||||
|
### 短期目标
|
||||||
|
- [ ] 添加实际的服务模块实现
|
||||||
|
- [ ] 集成真实的AI视频生成功能
|
||||||
|
- [ ] 优化错误处理和日志记录
|
||||||
|
- [ ] 添加配置文件支持
|
||||||
|
|
||||||
|
### 长期目标
|
||||||
|
- [ ] 支持插件系统
|
||||||
|
- [ ] 添加缓存机制
|
||||||
|
- [ ] 实现自动更新
|
||||||
|
- [ ] 性能监控和优化
|
||||||
|
|
||||||
|
## 📝 开发建议
|
||||||
|
|
||||||
|
1. **渐进式开发**: 先确保基础功能工作,再逐步添加复杂功能
|
||||||
|
2. **测试驱动**: 每次添加新功能都要运行完整测试
|
||||||
|
3. **模拟优先**: 使用模拟服务确保系统稳定性
|
||||||
|
4. **文档同步**: 及时更新文档和测试用例
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
通过这个增强版本,我们现在有了一个功能完整、可测试、可扩展的Python Core系统,为后续的功能开发奠定了坚实的基础。
|
||||||
244
docs/FINAL_USAGE_GUIDE.md
Normal file
244
docs/FINAL_USAGE_GUIDE.md
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
# 最终使用指南 - 增强版Python Core
|
||||||
|
|
||||||
|
## 🎉 恭喜!基本版本已经可以工作
|
||||||
|
|
||||||
|
既然基本版本可以工作,现在我们已经成功添加了更多功能。以下是完整的使用指南:
|
||||||
|
|
||||||
|
## 📁 新增文件概览
|
||||||
|
|
||||||
|
### Python Core 增强
|
||||||
|
- ✅ `python_core/main_simple.py` - 增强版入口文件
|
||||||
|
- ✅ `python_core/mock_services.py` - 模拟服务系统
|
||||||
|
- ✅ `python_core/build_enhanced.spec` - 增强版构建配置
|
||||||
|
- ✅ `python_core/test_functionality.py` - 功能测试脚本
|
||||||
|
- ✅ `python_core/build_enhanced.bat` - 增强版构建脚本
|
||||||
|
|
||||||
|
### Rust 后端增强
|
||||||
|
- ✅ `src-tauri/src/commands/python_core_demo.rs` - 演示命令
|
||||||
|
- ✅ `src-tauri/src/python_executor.rs` - 增强的执行器
|
||||||
|
|
||||||
|
### 前端测试界面
|
||||||
|
- ✅ `src/pages/PythonCoreTestPage.tsx` - 测试页面
|
||||||
|
- ✅ 路由和导航已配置
|
||||||
|
|
||||||
|
## 🚀 立即开始使用
|
||||||
|
|
||||||
|
### 1. 构建增强版Python Core
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
cd python_core
|
||||||
|
build_enhanced.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
这将:
|
||||||
|
- 安装必要依赖
|
||||||
|
- 构建增强版可执行文件
|
||||||
|
- 运行功能测试
|
||||||
|
- 复制到Tauri目录
|
||||||
|
|
||||||
|
### 2. 启动应用测试
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
cd ..
|
||||||
|
cargo tauri dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 访问测试页面
|
||||||
|
|
||||||
|
在应用中:
|
||||||
|
1. 点击左侧导航栏的 "Python测试"
|
||||||
|
2. 或直接访问 `/python-core-test` 路由
|
||||||
|
|
||||||
|
## 🧪 测试功能
|
||||||
|
|
||||||
|
### 自动化测试
|
||||||
|
|
||||||
|
在测试页面中,你可以:
|
||||||
|
|
||||||
|
1. **逐个运行测试** - 依次测试每个功能模块
|
||||||
|
2. **综合测试** - 一次性测试所有功能
|
||||||
|
3. **查看详细结果** - 展开查看JSON响应数据
|
||||||
|
|
||||||
|
### 手动测试
|
||||||
|
|
||||||
|
你也可以在命令行中手动测试:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
# 基础功能
|
||||||
|
dist\mixvideo-python-core.exe --version
|
||||||
|
dist\mixvideo-python-core.exe --module test --action hello
|
||||||
|
|
||||||
|
# 服务功能
|
||||||
|
dist\mixvideo-python-core.exe --module template_manager --action get_templates
|
||||||
|
dist\mixvideo-python-core.exe --module project_manager --action get_projects
|
||||||
|
dist\mixvideo-python-core.exe --module file_manager --action list_files --params "{\"path\":\".\"}"
|
||||||
|
|
||||||
|
# AI功能
|
||||||
|
dist\mixvideo-python-core.exe --module ai_video --action test_environment
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 预期结果
|
||||||
|
|
||||||
|
### 成功的测试应该显示:
|
||||||
|
|
||||||
|
1. **基础功能测试** ✅
|
||||||
|
- 版本信息正确
|
||||||
|
- Hello响应正常
|
||||||
|
|
||||||
|
2. **服务模块测试** ✅
|
||||||
|
- 模板管理:返回模拟模板列表
|
||||||
|
- 项目管理:返回模拟项目列表
|
||||||
|
- 文件管理:返回当前目录文件列表
|
||||||
|
- 媒体管理:返回模拟媒体列表
|
||||||
|
|
||||||
|
3. **AI模块测试** ✅
|
||||||
|
- 环境测试:返回Python版本和依赖信息
|
||||||
|
- 状态检查:返回服务状态
|
||||||
|
|
||||||
|
### 响应格式示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": true,
|
||||||
|
"msg": "操作完成",
|
||||||
|
"data": {
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"id": "template_001",
|
||||||
|
"name": "商业宣传模板",
|
||||||
|
"description": "适用于商业宣传的视频模板",
|
||||||
|
"duration": 30,
|
||||||
|
"created_at": "2024-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2,
|
||||||
|
"timestamp": "2024-01-15T10:30:00.000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 故障排除
|
||||||
|
|
||||||
|
### 如果构建失败
|
||||||
|
|
||||||
|
1. **检查Python环境**:
|
||||||
|
```cmd
|
||||||
|
python --version
|
||||||
|
python -c "import requests, PIL"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **使用简化构建**:
|
||||||
|
```cmd
|
||||||
|
python -m PyInstaller build_simple.spec
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查依赖**:
|
||||||
|
```cmd
|
||||||
|
python -m pip install pyinstaller requests Pillow
|
||||||
|
```
|
||||||
|
|
||||||
|
### 如果测试失败
|
||||||
|
|
||||||
|
1. **检查可执行文件**:
|
||||||
|
```cmd
|
||||||
|
dir dist\mixvideo-python-core.exe
|
||||||
|
dist\mixvideo-python-core.exe --version
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **查看详细错误**:
|
||||||
|
- 在测试页面中展开错误详情
|
||||||
|
- 检查 `test_results.json` 文件
|
||||||
|
|
||||||
|
3. **手动测试单个功能**:
|
||||||
|
```cmd
|
||||||
|
dist\mixvideo-python-core.exe --module test --action hello --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 下一步开发
|
||||||
|
|
||||||
|
### 替换模拟服务
|
||||||
|
|
||||||
|
当你准备好实际的服务实现时:
|
||||||
|
|
||||||
|
1. **实现真实服务**:
|
||||||
|
- 在 `python_core/services/` 中实现实际功能
|
||||||
|
- 确保函数签名与模拟服务一致
|
||||||
|
|
||||||
|
2. **更新隐藏导入**:
|
||||||
|
- 在 `build_enhanced.spec` 中添加新的依赖
|
||||||
|
- 测试新的构建
|
||||||
|
|
||||||
|
3. **逐步迁移**:
|
||||||
|
- 一次替换一个服务
|
||||||
|
- 每次替换后运行测试
|
||||||
|
|
||||||
|
### 添加新功能
|
||||||
|
|
||||||
|
1. **添加新的Python模块**:
|
||||||
|
- 在 `MODULE_MAP` 中注册
|
||||||
|
- 添加到隐藏导入列表
|
||||||
|
|
||||||
|
2. **添加新的Rust命令**:
|
||||||
|
- 在 `python_core_demo.rs` 中添加
|
||||||
|
- 在 `lib.rs` 中注册
|
||||||
|
|
||||||
|
3. **添加前端测试**:
|
||||||
|
- 在测试页面中添加新的测试用例
|
||||||
|
|
||||||
|
## 📈 性能优化
|
||||||
|
|
||||||
|
### 减少包大小
|
||||||
|
|
||||||
|
1. **排除不需要的模块**:
|
||||||
|
```python
|
||||||
|
excludes = [
|
||||||
|
'numpy', # 如果不需要
|
||||||
|
'cv2', # 如果不需要
|
||||||
|
'torch', # 如果不需要
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **使用UPX压缩**:
|
||||||
|
```python
|
||||||
|
upx=True
|
||||||
|
```
|
||||||
|
|
||||||
|
### 提升启动速度
|
||||||
|
|
||||||
|
1. **减少隐藏导入**:
|
||||||
|
- 只导入实际需要的模块
|
||||||
|
|
||||||
|
2. **使用缓存**:
|
||||||
|
- 考虑添加结果缓存机制
|
||||||
|
|
||||||
|
## 🎊 成功标志
|
||||||
|
|
||||||
|
如果你看到以下结果,说明增强版Python Core已经成功运行:
|
||||||
|
|
||||||
|
- ✅ 所有测试显示绿色(成功)
|
||||||
|
- ✅ 响应格式正确(JSON格式)
|
||||||
|
- ✅ 模拟数据返回正常
|
||||||
|
- ✅ 错误处理工作正常
|
||||||
|
- ✅ Tauri集成无问题
|
||||||
|
|
||||||
|
## 📞 获取帮助
|
||||||
|
|
||||||
|
如果遇到问题:
|
||||||
|
|
||||||
|
1. **查看日志**:
|
||||||
|
- 检查控制台输出
|
||||||
|
- 查看 `test_results.json`
|
||||||
|
|
||||||
|
2. **逐步调试**:
|
||||||
|
- 先确保基本版本工作
|
||||||
|
- 再逐步添加功能
|
||||||
|
|
||||||
|
3. **回退方案**:
|
||||||
|
- 如果增强版有问题,可以回退到基本版本
|
||||||
|
- 使用 `build_simple.spec` 构建
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🎉 **恭喜!你现在拥有了一个功能完整、可测试、可扩展的Python Core系统!**
|
||||||
|
|
||||||
|
这个系统为你的Tauri应用提供了强大的Python后端支持,无需用户安装Python环境,真正实现了一体化分发。
|
||||||
@@ -117,7 +117,7 @@ excludes = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
['main_simple.py'],
|
['main_simple.py', 'mock_services.py'],
|
||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[],
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub mod model;
|
|||||||
pub mod audio;
|
pub mod audio;
|
||||||
pub mod media;
|
pub mod media;
|
||||||
pub mod resource_category;
|
pub mod resource_category;
|
||||||
|
pub mod python_core_demo;
|
||||||
|
|
||||||
// Re-export all commands for easy access
|
// Re-export all commands for easy access
|
||||||
pub use basic::*;
|
pub use basic::*;
|
||||||
@@ -19,3 +20,4 @@ pub use file_system::*;
|
|||||||
pub use project::*;
|
pub use project::*;
|
||||||
pub use template::*;
|
pub use template::*;
|
||||||
pub use resource_category::*;
|
pub use resource_category::*;
|
||||||
|
pub use python_core_demo::*;
|
||||||
|
|||||||
262
src-tauri/src/commands/python_core_demo.rs
Normal file
262
src-tauri/src/commands/python_core_demo.rs
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
/**
|
||||||
|
* Python Core 演示命令
|
||||||
|
* 展示如何使用新的增强版Python Core
|
||||||
|
*/
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tauri::{command, AppHandle};
|
||||||
|
use crate::python_executor::{execute_python_module_action, call_python_service};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct PythonResponse {
|
||||||
|
pub status: bool,
|
||||||
|
pub msg: String,
|
||||||
|
pub data: Option<serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试Python Core基础功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_python_core_basic(app: AppHandle) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing Python Core basic functionality...");
|
||||||
|
|
||||||
|
let result = execute_python_module_action(
|
||||||
|
app,
|
||||||
|
"test",
|
||||||
|
"hello",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
let response: PythonResponse = serde_json::from_str(&result)
|
||||||
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试模板管理功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_template_manager(app: AppHandle) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing template manager...");
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"template_manager",
|
||||||
|
"get_templates",
|
||||||
|
None
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "Template manager test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试项目管理功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_project_manager(app: AppHandle) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing project manager...");
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"project_manager",
|
||||||
|
"get_projects",
|
||||||
|
None
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "Project manager test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试文件管理功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_file_manager(app: AppHandle, path: String) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing file manager with path: {}", path);
|
||||||
|
|
||||||
|
let params = serde_json::json!({
|
||||||
|
"path": path
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"file_manager",
|
||||||
|
"list_files",
|
||||||
|
Some(params)
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "File manager test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 测试AI视频功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_ai_video(app: AppHandle) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing AI video functionality...");
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"ai_video",
|
||||||
|
"test_environment",
|
||||||
|
None
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "AI video test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 批量导入模板(演示带参数的调用)
|
||||||
|
#[command]
|
||||||
|
pub async fn test_batch_import_templates(
|
||||||
|
app: AppHandle,
|
||||||
|
folder_path: String
|
||||||
|
) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing batch import templates from: {}", folder_path);
|
||||||
|
|
||||||
|
let params = serde_json::json!({
|
||||||
|
"folder_path": folder_path,
|
||||||
|
"force_reimport": false
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"template_manager",
|
||||||
|
"batch_import",
|
||||||
|
Some(params)
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "Batch import test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建新项目(演示复杂参数调用)
|
||||||
|
#[command]
|
||||||
|
pub async fn test_create_project(
|
||||||
|
app: AppHandle,
|
||||||
|
name: String,
|
||||||
|
description: Option<String>
|
||||||
|
) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing create project: {}", name);
|
||||||
|
|
||||||
|
let mut params = serde_json::json!({
|
||||||
|
"name": name
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(desc) = description {
|
||||||
|
params["description"] = serde_json::Value::String(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"project_manager",
|
||||||
|
"create_project",
|
||||||
|
Some(params)
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "Create project test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取所有资源分类
|
||||||
|
#[command]
|
||||||
|
pub async fn test_get_categories(app: AppHandle) -> Result<PythonResponse, String> {
|
||||||
|
println!("Testing get categories...");
|
||||||
|
|
||||||
|
let result = call_python_service(
|
||||||
|
app,
|
||||||
|
"resource_category_manager",
|
||||||
|
"get_all_categories",
|
||||||
|
None
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(PythonResponse {
|
||||||
|
status: true,
|
||||||
|
msg: "Get categories test completed".to_string(),
|
||||||
|
data: Some(result),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 综合测试 - 测试所有主要功能
|
||||||
|
#[command]
|
||||||
|
pub async fn test_all_python_core_functions(app: AppHandle) -> Result<Vec<PythonResponse>, String> {
|
||||||
|
println!("Running comprehensive Python Core tests...");
|
||||||
|
|
||||||
|
let mut results = Vec::new();
|
||||||
|
|
||||||
|
// 测试基础功能
|
||||||
|
match test_python_core_basic(app.clone()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("Basic test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试模板管理
|
||||||
|
match test_template_manager(app.clone()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("Template manager test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试项目管理
|
||||||
|
match test_project_manager(app.clone()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("Project manager test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试AI视频
|
||||||
|
match test_ai_video(app.clone()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("AI video test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试文件管理
|
||||||
|
match test_file_manager(app.clone(), ".".to_string()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("File manager test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试资源分类
|
||||||
|
match test_get_categories(app.clone()).await {
|
||||||
|
Ok(response) => results.push(response),
|
||||||
|
Err(e) => results.push(PythonResponse {
|
||||||
|
status: false,
|
||||||
|
msg: format!("Categories test failed: {}", e),
|
||||||
|
data: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
@@ -90,7 +90,17 @@ pub fn run() {
|
|||||||
commands::file_utils::read_video_as_data_url,
|
commands::file_utils::read_video_as_data_url,
|
||||||
commands::file_utils::get_video_blob_url,
|
commands::file_utils::get_video_blob_url,
|
||||||
commands::file_utils::check_file_exists,
|
commands::file_utils::check_file_exists,
|
||||||
commands::file_utils::get_file_info
|
commands::file_utils::get_file_info,
|
||||||
|
// Python Core Demo Commands
|
||||||
|
commands::python_core_demo::test_python_core_basic,
|
||||||
|
commands::python_core_demo::test_template_manager,
|
||||||
|
commands::python_core_demo::test_project_manager,
|
||||||
|
commands::python_core_demo::test_file_manager,
|
||||||
|
commands::python_core_demo::test_ai_video,
|
||||||
|
commands::python_core_demo::test_batch_import_templates,
|
||||||
|
commands::python_core_demo::test_create_project,
|
||||||
|
commands::python_core_demo::test_get_categories,
|
||||||
|
commands::python_core_demo::test_all_python_core_functions
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
@@ -293,6 +293,65 @@ pub async fn execute_python_module_action(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute Python module action with progress events
|
||||||
|
pub async fn execute_python_module_action_with_progress(
|
||||||
|
app: tauri::AppHandle,
|
||||||
|
module: &str,
|
||||||
|
action: &str,
|
||||||
|
params: Option<serde_json::Value>,
|
||||||
|
event_name: &str,
|
||||||
|
config: Option<PythonExecutorConfig>,
|
||||||
|
) -> Result<String, String> {
|
||||||
|
// 检查是否应该使用sidecar
|
||||||
|
if should_use_sidecar() {
|
||||||
|
println!("Using Python sidecar for execution with progress");
|
||||||
|
|
||||||
|
// 将参数转换为JSON字符串
|
||||||
|
let params_str = if let Some(p) = params {
|
||||||
|
Some(serde_json::to_string(&p)
|
||||||
|
.map_err(|e| format!("Failed to serialize parameters: {}", e))?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// 对于sidecar,我们暂时不支持进度事件,直接执行
|
||||||
|
execute_python_sidecar(module, action, params_str.as_deref(), config).await
|
||||||
|
} else {
|
||||||
|
println!("Using system Python for execution with progress");
|
||||||
|
|
||||||
|
// 构建传统的命令行参数
|
||||||
|
let mut args = vec![
|
||||||
|
"-m".to_string(),
|
||||||
|
format!("python_core.{}", module),
|
||||||
|
"--action".to_string(),
|
||||||
|
action.to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 添加参数
|
||||||
|
if let Some(p) = params {
|
||||||
|
args.push("--params".to_string());
|
||||||
|
args.push(serde_json::to_string(&p)
|
||||||
|
.map_err(|e| format!("Failed to serialize parameters: {}", e))?);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute_python_with_events(app, &args, config, event_name).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simplified helper for common module actions
|
||||||
|
pub async fn call_python_service(
|
||||||
|
app: tauri::AppHandle,
|
||||||
|
service: &str,
|
||||||
|
action: &str,
|
||||||
|
params: Option<serde_json::Value>,
|
||||||
|
) -> Result<serde_json::Value, String> {
|
||||||
|
let result = execute_python_module_action(app, service, action, params, None).await?;
|
||||||
|
|
||||||
|
// 尝试解析JSON响应
|
||||||
|
serde_json::from_str(&result)
|
||||||
|
.map_err(|e| format!("Failed to parse Python response as JSON: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
/// Python command builder for easier command construction
|
/// Python command builder for easier command construction
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct PythonCommandBuilder {
|
pub struct PythonCommandBuilder {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import AudioLibraryPage from './pages/AudioLibraryPage'
|
|||||||
import MediaLibraryPage from './pages/MediaLibraryPage'
|
import MediaLibraryPage from './pages/MediaLibraryPage'
|
||||||
import KVTestPage from './pages/KVTestPage'
|
import KVTestPage from './pages/KVTestPage'
|
||||||
import TextVideoGeneratorPage from './pages/TextVideoGeneratorPage'
|
import TextVideoGeneratorPage from './pages/TextVideoGeneratorPage'
|
||||||
|
import PythonCoreTestPage from './pages/PythonCoreTestPage'
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
@@ -29,6 +30,7 @@ function App() {
|
|||||||
<Route path="/editor" element={<EditorPage />} />
|
<Route path="/editor" element={<EditorPage />} />
|
||||||
<Route path="/ai-video" element={<AIVideoPage />} />
|
<Route path="/ai-video" element={<AIVideoPage />} />
|
||||||
<Route path="/text-video-generator" element={<TextVideoGeneratorPage />} />
|
<Route path="/text-video-generator" element={<TextVideoGeneratorPage />} />
|
||||||
|
<Route path="/python-core-test" element={<PythonCoreTestPage />} />
|
||||||
<Route path="/templates" element={<TemplateManagePage />} />
|
<Route path="/templates" element={<TemplateManagePage />} />
|
||||||
<Route path="/templates/:templateId" element={<TemplateDetailPage />} />
|
<Route path="/templates/:templateId" element={<TemplateDetailPage />} />
|
||||||
<Route path="/resource-categories" element={<ResourceCategoryPage />} />
|
<Route path="/resource-categories" element={<ResourceCategoryPage />} />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
import { Home, Video, Settings, FolderOpen, Music, Image, Sparkles, Layout, Clock, CheckCircle, XCircle, List, Tags, User, Wand2 } from 'lucide-react'
|
import { Home, Video, Settings, FolderOpen, Music, Image, Sparkles, Layout, Clock, CheckCircle, XCircle, List, Tags, User, Wand2, TestTube } from 'lucide-react'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
|
|
||||||
const Sidebar: React.FC = () => {
|
const Sidebar: React.FC = () => {
|
||||||
@@ -29,6 +29,7 @@ const Sidebar: React.FC = () => {
|
|||||||
{ path: '/models', icon: User, label: '模特库' },
|
{ path: '/models', icon: User, label: '模特库' },
|
||||||
{ path: '/media', icon: Image, label: '媒体库' },
|
{ path: '/media', icon: Image, label: '媒体库' },
|
||||||
{ path: '/audio', icon: Music, label: '音频库' },
|
{ path: '/audio', icon: Music, label: '音频库' },
|
||||||
|
{ path: '/python-core-test', icon: TestTube, label: 'Python测试' },
|
||||||
{ path: '/settings', icon: Settings, label: '设置' },
|
{ path: '/settings', icon: Settings, label: '设置' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
339
src/pages/PythonCoreTestPage.tsx
Normal file
339
src/pages/PythonCoreTestPage.tsx
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
/**
|
||||||
|
* Python Core 测试页面
|
||||||
|
* 用于测试增强版Python Core的各项功能
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { invoke } from '@tauri-apps/api/tauri'
|
||||||
|
import { Play, CheckCircle, XCircle, Loader, RefreshCw } from 'lucide-react'
|
||||||
|
|
||||||
|
interface PythonResponse {
|
||||||
|
status: boolean
|
||||||
|
msg: string
|
||||||
|
data?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestResult {
|
||||||
|
name: string
|
||||||
|
status: 'pending' | 'running' | 'success' | 'error'
|
||||||
|
response?: PythonResponse
|
||||||
|
error?: string
|
||||||
|
duration?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const PythonCoreTestPage: React.FC = () => {
|
||||||
|
const [testResults, setTestResults] = useState<TestResult[]>([])
|
||||||
|
const [isRunning, setIsRunning] = useState(false)
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
{
|
||||||
|
name: '基础功能测试',
|
||||||
|
command: 'test_python_core_basic',
|
||||||
|
description: '测试Python Core的基本功能和响应格式'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '模板管理测试',
|
||||||
|
command: 'test_template_manager',
|
||||||
|
description: '测试模板管理服务的功能'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '项目管理测试',
|
||||||
|
command: 'test_project_manager',
|
||||||
|
description: '测试项目管理服务的功能'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '文件管理测试',
|
||||||
|
command: 'test_file_manager',
|
||||||
|
description: '测试文件管理服务的功能',
|
||||||
|
params: { path: '.' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'AI视频测试',
|
||||||
|
command: 'test_ai_video',
|
||||||
|
description: '测试AI视频生成环境和功能'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '资源分类测试',
|
||||||
|
command: 'test_get_categories',
|
||||||
|
description: '测试资源分类管理功能'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '批量导入测试',
|
||||||
|
command: 'test_batch_import_templates',
|
||||||
|
description: '测试模板批量导入功能',
|
||||||
|
params: { folder_path: './templates' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '创建项目测试',
|
||||||
|
command: 'test_create_project',
|
||||||
|
description: '测试项目创建功能',
|
||||||
|
params: { name: 'Test Project', description: 'A test project' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const runSingleTest = async (test: any, index: number) => {
|
||||||
|
const startTime = Date.now()
|
||||||
|
|
||||||
|
// 更新状态为运行中
|
||||||
|
setTestResults(prev => {
|
||||||
|
const newResults = [...prev]
|
||||||
|
newResults[index] = {
|
||||||
|
name: test.name,
|
||||||
|
status: 'running'
|
||||||
|
}
|
||||||
|
return newResults
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response: PythonResponse
|
||||||
|
|
||||||
|
if (test.params) {
|
||||||
|
response = await invoke(test.command, test.params)
|
||||||
|
} else {
|
||||||
|
response = await invoke(test.command)
|
||||||
|
}
|
||||||
|
|
||||||
|
const duration = Date.now() - startTime
|
||||||
|
|
||||||
|
// 更新状态为成功
|
||||||
|
setTestResults(prev => {
|
||||||
|
const newResults = [...prev]
|
||||||
|
newResults[index] = {
|
||||||
|
name: test.name,
|
||||||
|
status: 'success',
|
||||||
|
response,
|
||||||
|
duration
|
||||||
|
}
|
||||||
|
return newResults
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
const duration = Date.now() - startTime
|
||||||
|
|
||||||
|
// 更新状态为错误
|
||||||
|
setTestResults(prev => {
|
||||||
|
const newResults = [...prev]
|
||||||
|
newResults[index] = {
|
||||||
|
name: test.name,
|
||||||
|
status: 'error',
|
||||||
|
error: error as string,
|
||||||
|
duration
|
||||||
|
}
|
||||||
|
return newResults
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runAllTests = async () => {
|
||||||
|
setIsRunning(true)
|
||||||
|
|
||||||
|
// 初始化所有测试状态
|
||||||
|
setTestResults(tests.map(test => ({
|
||||||
|
name: test.name,
|
||||||
|
status: 'pending' as const
|
||||||
|
})))
|
||||||
|
|
||||||
|
// 逐个运行测试
|
||||||
|
for (let i = 0; i < tests.length; i++) {
|
||||||
|
await runSingleTest(tests[i], i)
|
||||||
|
// 在测试之间添加短暂延迟
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsRunning(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const runComprehensiveTest = async () => {
|
||||||
|
setIsRunning(true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const startTime = Date.now()
|
||||||
|
const results: PythonResponse[] = await invoke('test_all_python_core_functions')
|
||||||
|
const duration = Date.now() - startTime
|
||||||
|
|
||||||
|
// 将综合测试结果映射到各个测试
|
||||||
|
const mappedResults = tests.map((test, index) => ({
|
||||||
|
name: test.name,
|
||||||
|
status: results[index]?.status ? 'success' : 'error' as const,
|
||||||
|
response: results[index],
|
||||||
|
duration: duration / tests.length // 平均分配时间
|
||||||
|
}))
|
||||||
|
|
||||||
|
setTestResults(mappedResults)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Comprehensive test failed:', error)
|
||||||
|
setTestResults(tests.map(test => ({
|
||||||
|
name: test.name,
|
||||||
|
status: 'error' as const,
|
||||||
|
error: error as string
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsRunning(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearResults = () => {
|
||||||
|
setTestResults([])
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusIcon = (status: TestResult['status']) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'pending':
|
||||||
|
return <div className="w-5 h-5 rounded-full bg-gray-300" />
|
||||||
|
case 'running':
|
||||||
|
return <Loader className="w-5 h-5 text-blue-500 animate-spin" />
|
||||||
|
case 'success':
|
||||||
|
return <CheckCircle className="w-5 h-5 text-green-500" />
|
||||||
|
case 'error':
|
||||||
|
return <XCircle className="w-5 h-5 text-red-500" />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusColor = (status: TestResult['status']) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'pending':
|
||||||
|
return 'border-gray-200 bg-gray-50'
|
||||||
|
case 'running':
|
||||||
|
return 'border-blue-200 bg-blue-50'
|
||||||
|
case 'success':
|
||||||
|
return 'border-green-200 bg-green-50'
|
||||||
|
case 'error':
|
||||||
|
return 'border-red-200 bg-red-50'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const successCount = testResults.filter(r => r.status === 'success').length
|
||||||
|
const errorCount = testResults.filter(r => r.status === 'error').length
|
||||||
|
const totalTests = testResults.length
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-50 p-6">
|
||||||
|
<div className="max-w-6xl mx-auto">
|
||||||
|
{/* 页面标题 */}
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-3xl font-bold text-gray-900 mb-2">
|
||||||
|
Python Core 功能测试
|
||||||
|
</h1>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
测试增强版Python Core的各项功能,验证sidecar和模拟服务是否正常工作
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 控制按钮 */}
|
||||||
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
|
||||||
|
<div className="flex items-center gap-4 mb-4">
|
||||||
|
<button
|
||||||
|
onClick={runAllTests}
|
||||||
|
disabled={isRunning}
|
||||||
|
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<Play size={16} />
|
||||||
|
逐个运行测试
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={runComprehensiveTest}
|
||||||
|
disabled={isRunning}
|
||||||
|
className="flex items-center gap-2 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<RefreshCw size={16} />
|
||||||
|
综合测试
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={clearResults}
|
||||||
|
disabled={isRunning}
|
||||||
|
className="flex items-center gap-2 px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
清除结果
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 测试统计 */}
|
||||||
|
{totalTests > 0 && (
|
||||||
|
<div className="flex items-center gap-6 text-sm">
|
||||||
|
<span className="text-gray-600">
|
||||||
|
总计: {totalTests}
|
||||||
|
</span>
|
||||||
|
<span className="text-green-600">
|
||||||
|
成功: {successCount}
|
||||||
|
</span>
|
||||||
|
<span className="text-red-600">
|
||||||
|
失败: {errorCount}
|
||||||
|
</span>
|
||||||
|
<span className="text-gray-600">
|
||||||
|
成功率: {totalTests > 0 ? Math.round((successCount / totalTests) * 100) : 0}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 测试结果 */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
{tests.map((test, index) => {
|
||||||
|
const result = testResults[index]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={test.name}
|
||||||
|
className={`bg-white rounded-lg shadow-sm border-2 p-6 ${
|
||||||
|
result ? getStatusColor(result.status) : 'border-gray-200'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-start justify-between mb-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
{result ? getStatusIcon(result.status) : getStatusIcon('pending')}
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-gray-900">{test.name}</h3>
|
||||||
|
<p className="text-sm text-gray-600">{test.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{result?.duration && (
|
||||||
|
<span className="text-xs text-gray-500">
|
||||||
|
{result.duration}ms
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 测试结果详情 */}
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4">
|
||||||
|
{result.status === 'success' && result.response && (
|
||||||
|
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||||
|
<div className="text-sm text-green-800 mb-2">
|
||||||
|
<strong>状态:</strong> {result.response.status ? '成功' : '失败'}
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-green-800 mb-2">
|
||||||
|
<strong>消息:</strong> {result.response.msg}
|
||||||
|
</div>
|
||||||
|
{result.response.data && (
|
||||||
|
<details className="text-sm text-green-800">
|
||||||
|
<summary className="cursor-pointer font-medium">查看数据</summary>
|
||||||
|
<pre className="mt-2 p-2 bg-green-100 rounded text-xs overflow-auto">
|
||||||
|
{JSON.stringify(result.response.data, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{result.status === 'error' && (
|
||||||
|
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||||
|
<div className="text-sm text-red-800">
|
||||||
|
<strong>错误:</strong> {result.error}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PythonCoreTestPage
|
||||||
Reference in New Issue
Block a user