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(
|
||||
['main_simple.py'],
|
||||
['main_simple.py', 'mock_services.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod model;
|
||||
pub mod audio;
|
||||
pub mod media;
|
||||
pub mod resource_category;
|
||||
pub mod python_core_demo;
|
||||
|
||||
// Re-export all commands for easy access
|
||||
pub use basic::*;
|
||||
@@ -19,3 +20,4 @@ pub use file_system::*;
|
||||
pub use project::*;
|
||||
pub use template::*;
|
||||
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::get_video_blob_url,
|
||||
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!())
|
||||
.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
|
||||
#[allow(dead_code)]
|
||||
pub struct PythonCommandBuilder {
|
||||
|
||||
@@ -15,6 +15,7 @@ import AudioLibraryPage from './pages/AudioLibraryPage'
|
||||
import MediaLibraryPage from './pages/MediaLibraryPage'
|
||||
import KVTestPage from './pages/KVTestPage'
|
||||
import TextVideoGeneratorPage from './pages/TextVideoGeneratorPage'
|
||||
import PythonCoreTestPage from './pages/PythonCoreTestPage'
|
||||
function App() {
|
||||
return (
|
||||
<Routes>
|
||||
@@ -29,6 +30,7 @@ function App() {
|
||||
<Route path="/editor" element={<EditorPage />} />
|
||||
<Route path="/ai-video" element={<AIVideoPage />} />
|
||||
<Route path="/text-video-generator" element={<TextVideoGeneratorPage />} />
|
||||
<Route path="/python-core-test" element={<PythonCoreTestPage />} />
|
||||
<Route path="/templates" element={<TemplateManagePage />} />
|
||||
<Route path="/templates/:templateId" element={<TemplateDetailPage />} />
|
||||
<Route path="/resource-categories" element={<ResourceCategoryPage />} />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react'
|
||||
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'
|
||||
|
||||
const Sidebar: React.FC = () => {
|
||||
@@ -29,6 +29,7 @@ const Sidebar: React.FC = () => {
|
||||
{ path: '/models', icon: User, label: '模特库' },
|
||||
{ path: '/media', icon: Image, label: '媒体库' },
|
||||
{ path: '/audio', icon: Music, label: '音频库' },
|
||||
{ path: '/python-core-test', icon: TestTube, label: 'Python测试' },
|
||||
{ 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