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
style: 格式化代码文件并修复样式问题 docs: 新增部署文档和系统要求文档 test: 更新测试截图和覆盖率报告 refactor: 重构SchedulerPanel加载状态逻辑 ci: 添加lint和format脚本到package.json build: 更新依赖项并添加开发工具 chore: 添加验证报告和上线审查计划
11 KiB
11 KiB
Pipeline 行业分类展示功能实现计划
问题描述
当前 Pipeline 列表仅支持功能分类筛选(教育、营销、法律、生产力、研究),用户期望能够按行业分类(互联网、金融、医疗等)筛选 Pipeline。
用户需求
- 保留现有功能分类筛选
- 添加行业分类维度
- 支持双维度筛选(功能 + 行业)
根因分析
当前架构
| 层级 | 文件 | 现状 |
|---|---|---|
| Pipeline YAML | pipelines/**/*.yaml |
metadata.category = 功能分类(education、marketing、legal 等) |
| 后端类型 | types.rs:29-44 | PipelineMetadata 只有 category 字段 |
| 后端命令 | pipeline_commands.rs:41-62 | PipelineInfo 只有 category 字段 |
| 前端类型 | pipeline-client.ts:26-36 | PipelineInfo 只有 category 字段 |
| 前端 UI | PipelinesPanel.tsx:34-44 | CATEGORY_CONFIG 定义 8 个功能分类 |
问题根因
Pipeline 元数据中缺少 industry(行业)字段,无法按行业分类筛选。
解决方案
整体架构
┌─────────────────────────────────────────────────────────────┐
│ PipelinesPanel │
├─────────────────────────────────────────────────────────────┤
│ [搜索框] │
│ 功能分类: [全部][教育][营销][法律][生产力][研究] │ ← 现有
│ 行业分类: [全部][互联网][金融][医疗][教育][制造业]... │ ← 新增
├─────────────────────────────────────────────────────────────┤
│ Pipeline 卡片 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 📚 互动课堂生成器 [教育] [互联网] │ │
│ │ 生成结构化大纲、互动场景... │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
实现步骤
步骤 1:后端类型定义
文件:crates/zclaw-pipeline/src/types.rs
在 PipelineMetadata 结构体中添加 industry 字段:
/// Pipeline metadata
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PipelineMetadata {
pub name: String,
pub display_name: Option<String>,
pub category: Option<String>,
/// Industry classification (e.g., "internet", "finance", "healthcare")
#[serde(default)]
pub industry: Option<String>, // ← 新增
pub description: Option<String>,
pub tags: Vec<String>,
pub icon: Option<String>,
pub author: Option<String>,
pub version: String,
}
步骤 2:后端命令更新
文件:desktop/src-tauri/src/pipeline_commands.rs
更新 PipelineInfo 结构体:
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PipelineInfo {
pub id: String,
pub display_name: String,
pub description: String,
pub category: String,
pub industry: String, // ← 新增
pub tags: Vec<String>,
pub icon: String,
pub version: String,
pub author: String,
pub inputs: Vec<PipelineInputInfo>,
}
更新 pipeline_to_info 函数:
fn pipeline_to_info(pipeline: &Pipeline) -> PipelineInfo {
PipelineInfo {
// ...
industry: pipeline.metadata.industry.clone().unwrap_or_default(),
// ...
}
}
更新 pipeline_list 命令支持行业筛选:
pub async fn pipeline_list(
state: State<'_, Arc<PipelineState>>,
category: Option<String>,
industry: Option<String>, // ← 新增
) -> Result<Vec<PipelineInfo>, String> {
// ...
}
步骤 3:前端类型定义
文件:desktop/src/lib/pipeline-client.ts
更新 PipelineInfo 接口:
export interface PipelineInfo {
id: string;
displayName: string;
description: string;
category: string;
industry: string; // ← 新增
tags: string[];
icon: string;
version: string;
author: string;
inputs: PipelineInputInfo[];
}
更新 listPipelines 方法:
static async listPipelines(options?: {
category?: string;
industry?: string; // ← 新增
}): Promise<PipelineInfo[]> {
const pipelines = await invoke<PipelineInfo[]>('pipeline_list', {
category: options?.category || null,
industry: options?.industry || null, // ← 新增
});
return pipelines;
}
步骤 4:前端行业配置
文件:desktop/src/components/PipelinesPanel.tsx
添加行业配置:
// 行业分类配置
const INDUSTRY_CONFIG: Record<string, { label: string; className: string }> = {
internet: { label: '互联网', className: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400' },
finance: { label: '金融', className: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' },
healthcare: { label: '医疗', className: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400' },
education: { label: '教育', className: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400' },
manufacturing: { label: '制造业', className: 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400' },
retail: { label: '零售', className: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400' },
realestate: { label: '房地产', className: 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400' },
energy: { label: '能源', className: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400' },
government: { label: '政府', className: 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-400' },
other: { label: '其他', className: 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400' },
};
添加行业筛选状态和 UI:
// 状态
const [selectedIndustry, setSelectedIndustry] = useState<string | null>(null);
// 获取唯一行业列表
const industries = Array.from(
new Set(pipelines.map((p) => p.industry).filter(Boolean))
);
// 行业筛选按钮组
<div className="flex items-center gap-2 flex-wrap">
<Building className="w-4 h-4 text-gray-400" />
<button onClick={() => setSelectedIndustry(null)} ...>全部</button>
{industries.map((ind) => (
<button key={ind} onClick={() => setSelectedIndustry(ind)} ...>
{INDUSTRY_CONFIG[ind]?.label || ind}
</button>
))}
</div>
更新 usePipelines hook 支持行业筛选:
const { pipelines, loading, error, refresh } = usePipelines({
category: selectedCategory ?? undefined,
industry: selectedIndustry ?? undefined, // ← 新增
});
步骤 5:更新 Pipeline YAML 文件
为每个 Pipeline 添加 industry 字段:
pipelines/education/classroom.yaml:
metadata:
name: classroom-generator
category: education
industry: education # ← 新增
pipelines/marketing/campaign.yaml:
metadata:
name: marketing-campaign
category: marketing
industry: internet # ← 新增(营销主要面向互联网)
pipelines/legal/contract-review.yaml:
metadata:
name: contract-review
category: legal
industry: other # ← 新增(合同审查适用于所有行业)
pipelines/research/literature-review.yaml:
metadata:
name: literature-review
category: research
industry: other # ← 新增(学术研究适用于所有领域)
pipelines/productivity/meeting-summary.yaml:
metadata:
name: meeting-summary
category: productivity
industry: other # ← 新增(会议纪要适用于所有行业)
文件修改清单
| 文件 | 修改类型 | 说明 |
|---|---|---|
crates/zclaw-pipeline/src/types.rs |
修改 | 添加 industry 字段 |
desktop/src-tauri/src/pipeline_commands.rs |
修改 | 更新 PipelineInfo 和筛选逻辑 |
desktop/src/lib/pipeline-client.ts |
修改 | 更新类型和 API 调用 |
desktop/src/components/PipelinesPanel.tsx |
修改 | 添加行业筛选 UI |
pipelines/education/classroom.yaml |
修改 | 添加 industry 字段 |
pipelines/marketing/campaign.yaml |
修改 | 添加 industry 字段 |
pipelines/legal/contract-review.yaml |
修改 | 添加 industry 字段 |
pipelines/research/literature-review.yaml |
修改 | 添加 industry 字段 |
pipelines/productivity/meeting-summary.yaml |
修改 | 添加 industry 字段 |
验证清单
- 后端编译通过:
cargo build - 前端类型检查通过:
pnpm tsc --noEmit - Pipeline 列表正确显示功能分类和行业分类
- 功能分类筛选正常工作
- 行业分类筛选正常工作
- 双维度筛选(功能 + 行业)正常工作
- Pipeline 卡片显示行业标签
验证命令
# 后端编译
cd desktop/src-tauri && cargo build
# 前端类型检查
cd desktop && pnpm tsc --noEmit
# 启动应用
pnpm start:dev
风险评估
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| 现有 Pipeline 无 industry 字段 | 显示为空 | 后端使用 unwrap_or_default() 提供默认值 |
| 行业列表不完整 | 用户找不到对应行业 | 添加"其他"作为兜底 |
| 前后端类型不一致 | 运行时错误 | 先修改后端,再修改前端 |
预定义行业列表
| ID | 中文标签 | 说明 |
|---|---|---|
internet |
互联网 | 互联网/科技公司 |
finance |
金融 | 银行、保险、证券 |
healthcare |
医疗 | 医疗、医药、健康 |
education |
教育 | 学校、培训、教育科技 |
manufacturing |
制造业 | 工厂、制造业 |
retail |
零售 | 电商、零售 |
realestate |
房地产 | 房地产、建筑 |
energy |
能源 | 能源、电力、环保 |
government |
政府 | 政府、公共服务 |
other |
其他 | 通用/跨行业 |