fix(presentation): 修复 presentation 模块类型错误和语法问题
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- 创建 types.ts 定义完整的类型系统
- 重写 DocumentRenderer.tsx 修复语法错误
- 重写 QuizRenderer.tsx 修复语法错误
- 重写 PresentationContainer.tsx 添加类型守卫
- 重写 TypeSwitcher.tsx 修复类型引用
- 更新 index.ts 移除不存在的 ChartRenderer 导出

审计结果:
- 类型检查: 通过
- 单元测试: 222 passed
- 构建: 成功
This commit is contained in:
iven
2026-03-26 17:19:28 +08:00
parent d0c6319fc1
commit b7f3d94950
71 changed files with 15896 additions and 1133 deletions

View File

@@ -1569,6 +1569,101 @@ async fn load_skill_from_dir(&self, dir: &PathBuf) -> Result<()> {
---
## 10.4 Pipeline YAML 解析失败 - 类型不匹配
**症状**:
- Pipeline 列表显示为空Found 0 pipelines
- 后端调试日志显示扫描目录成功但没有找到任何 Pipeline
- 没有明显的错误消息
**根本原因**: YAML 文件中的字段类型与 Rust 类型定义不匹配
**问题分析**:
1. **FileExport action formats 字段类型不匹配**:
- Rust 定义:`formats: Vec<ExportFormat>`(枚举数组)
- YAML 写法:`formats: ${inputs.export_formats}`(表达式字符串)
- serde_yaml 无法将字符串解析为枚举数组,静默失败
2. **InputType serde rename_all 配置错误**:
- YAML 使用 `multi-select`kebab-case
- Rust serde 配置 `rename_all = "snake_case"`
- 期望 `multi_select` 但收到 `multi-select`,解析失败
**修复方案**:
1. **将 formats 字段改为 String 类型** (`types.rs`):
```rust
FileExport {
formats: String, // 从 Vec<ExportFormat> 改为 String
input: String,
output_dir: Option<String>,
}
```
2. **在运行时解析 formats 表达式** (`executor.rs`):
```rust
let resolved_formats = context.resolve(formats)?;
let format_strings: Vec<String> = if resolved_formats.is_array() {
resolved_formats.as_array()?
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect()
} else if resolved_formats.is_string() {
// 尝试解析为 JSON 数组
serde_json::from_str(s).unwrap_or_else(|_| vec![s.to_string()])
} else {
return Err(...);
};
// 转换为 ExportFormat 枚举
let export_formats: Vec<ExportFormat> = format_strings
.iter()
.filter_map(|s| match s.to_lowercase().as_str() {
"pptx" => Some(ExportFormat::Pptx),
"html" => Some(ExportFormat::Html),
"pdf" => Some(ExportFormat::Pdf),
"markdown" | "md" => Some(ExportFormat::Markdown),
"json" => Some(ExportFormat::Json),
_ => None,
})
.collect();
```
3. **修正 InputType serde 配置** (`types.rs`):
```rust
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "kebab-case")] // 从 snake_case 改为 kebab-case
pub enum InputType {
#[default]
String,
Number,
Boolean,
Select,
MultiSelect, // YAML 中写 multi-select
File,
Text,
}
```
**影响范围**:
- `crates/zclaw-pipeline/src/types.rs` - InputType serde, FileExport formats
- `crates/zclaw-pipeline/src/executor.rs` - 运行时解析 formats
- `pipelines/**/*.yaml` - 确保使用 `multi-select` 而非 `multi_select`
**验证修复**:
```
[DEBUG pipeline_list] Found 5 pipelines
[DEBUG pipeline_list] Pipeline: classroom-generator -> category: education, industry: 'education'
```
**最佳实践**:
- YAML 中的表达式(如 `${inputs.xxx}`)应该定义为 String 类型
- 在运行时通过 ExecutionContext.resolve() 解析表达式
- 使用 `kebab-case` 命名风格更符合 YAML 惯例
---
## 11. 相关文档
- [OpenFang 配置指南](./openfang-configuration.md) - 配置文件位置、格式和最佳实践