CertFlow 扩展开发指南

本文档面向开发者,介绍如何扩展 CertFlow 的功能。


扩展点总览

扩展点

方式

难度

说明

新增报告类型

继承 ReportGenerator

⭐⭐

自定义报告PDF

新增编号规则

数据库配置

配置驱动

新增数据模型

继承 Base

⭐⭐⭐

新表定义

新增处理器

添加到 handlers/

⭐⭐

基础功能

UI主题定制

修改 ui.yaml

配置驱动

新增视图

添加到 views/

⭐⭐⭐

UI组件

新增控制器

添加到 controllers/

⭐⭐⭐

业务协调

新增服务

添加到 services/

⭐⭐⭐

业务逻辑

新增CLI命令

添加到 cli/commands/

⭐⭐

命令行


示例1:新增CLI命令

步骤1:创建命令文件

# src/certflow/cli/commands/export_custom.py
from ..base_command import BaseCommand

class ExportCustomCommand(BaseCommand):
    name = "export_custom"
    help = "导出自定义格式数据"

    def add_arguments(self, parser):
        parser.add_argument("-o", "--output", required=True, help="输出文件路径")
        parser.add_argument("-f", "--format", choices=["json", "xml"], default="json")
        parser.add_argument("--ids", nargs="+", type=int, help="指定记录ID")

    def execute(self, args):
        # 实现导出逻辑
        print(f"导出到: {args.output}")
        print(f"格式: {args.format}")
        return 0

步骤2:注册命令

# src/certflow/cli/__init__.py
from .commands.export_custom import ExportCustomCommand

# 在命令注册表中添加
COMMANDS = {
    "export_custom": ExportCustomCommand,
    # ... 其他命令
}

示例2:新增报告类型

步骤1:继承 ReportGenerator

# src/certflow/handlers/report_generator.py
class CustomReportGenerator(ReportGenerator):
    """自定义报告生成器"""

    def __init__(self, template_path: str = None):
        super().__init__(template_path)
        self.report_type = "custom"

    def generate(self, data: dict, output_path: str) -> str:
        """生成自定义报告"""
        from reportlab.pdfgen import canvas
        from reportlab.lib.pagesizes import A4

        c = canvas.Canvas(output_path, pagesize=A4)
        width, height = A4

        # 标题
        c.setFont("Helvetica-Bold", 16)
        c.drawString(100, height - 100, "自定义报告")

        # 内容
        c.setFont("Helvetica", 12)
        y = height - 150
        for key, value in data.items():
            c.drawString(100, y, f"{key}: {value}")
            y -= 25

        c.save()
        return output_path

步骤2:注册报告类型

# 在服务中注册
REPORT_TYPES = {
    "custom": CustomReportGenerator,
    # ... 其他类型
}

示例3:新增数据模型

步骤1:定义模型

# src/certflow/models/custom_table.py
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from .base import Base

class CustomTable(Base):
    __tablename__ = "custom_tables"

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    description = Column(String(500))
    sale_plan_id = Column(Integer, ForeignKey("sale_plans.id"))
    created_at = Column(DateTime, default=datetime.now)

步骤2:更新模型导出

# src/certflow/models/__init__.py
from .custom_table import CustomTable

步骤3:创建迁移

# 自动创建表(开发模式)
python -c "from certflow.utils.database import DatabaseManager; db = DatabaseManager.get_instance(); db.initialize(); from certflow.models import Base; Base.metadata.create_all(db._engine)"

示例4:新增主题

步骤1:修改 ui.yaml

# config/ui.yaml
themes:
  dark:
    background: "#2b2b2b"
    foreground: "#ffffff"
    accent: "#007acc"

  light:
    background: "#f5f5f5"
    foreground: "#000000"
    accent: "#0066cc"

  # 自定义主题
  ocean:
    background: "#1a2a3a"
    foreground: "#8fcbff"
    accent: "#00b4d8"
    button_bg: "#0d1b2a"
    button_hover: "#1b2d45"

步骤2:重新加载配置

# 自动生效,或调用
from certflow.config.ui_config import reload_ui_config
reload_ui_config()

开发规范

命名规范

类型

规范

示例

类名

PascalCase

CustomReportGenerator

函数/方法

snake_case

generate_custom_report

变量

snake_case

custom_data

常量

UPPER_SNAKE

MAX_RETRY_COUNT

文档规范

所有扩展代码需要包含 docstring:

def custom_function(param1: str, param2: int) -> bool:
    """
    简短描述功能。

    Args:
        param1: 参数1的说明
        param2: 参数2的说明

    Returns:
        bool: 返回值的说明

    Raises:
        ValueError: 当参数无效时抛出
    """
    pass

测试扩展

# tests/test_custom_extension.py
import pytest
from src.certflow.handlers.report_generator import CustomReportGenerator

class TestCustomReportGenerator:
    def test_generate(self, tmp_path):
        generator = CustomReportGenerator()
        output = tmp_path / "report.pdf"

        data = {"title": "Test", "content": "Hello"}
        result = generator.generate(data, str(output))

        assert output.exists()
        assert result == str(output)

发布扩展

  1. 将扩展代码放在对应的模块中

  2. 更新相关文档

  3. 添加测试用例

  4. 提交 Pull Request