书砚 插件开发指南 适配 v1.0.0 · PySide2 返回首页
书砚 / 插件开发指南 / 实战示例

实战示例

下面三个示例由浅入深,覆盖菜单、侧边栏面板与 Hook 三种最常见的插件形态;最后介绍书砚内置的有声书扩展示例。

示例 1:给工具菜单加一个「字数统计」

"""字数统计扩展"""

def get_info():
    return {'name': 'word_counter',
            'display_name': '📊 字数统计',
            'version': '1.0.0',
            'author': 'me',
            'description': '在工具菜单里加一个"显示全书字数"按钮'}

def activate(api):
    def show_total():
        chapters = api.list_chapters()
        total = sum(ch.get('word_count', 0) for ch in chapters)
        api.toast(f"全书共 {total:,} 字,{len(chapters)} 章")

    api.add_menu('工具', '📊 显示全书字数', show_total, 'Ctrl+Shift+W')

示例 2:侧边栏面板——生成 Markdown 目录

"""Markdown 目录扩展"""

def get_info():
    return {'name': 'markdown_toc',
            'display_name': '📋 MD 目录',
            'version': '1.0.0',
            'description': '生成当前项目的 Markdown 目录'}

def activate(api):
    from PySide2.QtWidgets import QWidget, QVBoxLayout, QPlainTextEdit, QPushButton
    from PySide2.QtCore import Qt

    panel = QWidget()
    lay = QVBoxLayout(panel)
    edit = QPlainTextEdit()
    edit.setReadOnly(True)
    btn = QPushButton("🔄 生成目录")
    lay.addWidget(edit)
    lay.addWidget(btn)

    def gen():
        chapters = api.list_chapters()
        lines = ['# ' + (api.project.get('name','') or '') + ' 目录', '']
        for i, ch in enumerate(chapters, 1):
            lines.append(f"{i}. {ch['title']}  ({ch.get('word_count',0):,} 字)")
        edit.setPlainText('\n'.join(lines))
        api.toast(f"生成了 {len(chapters)} 章目录")

    btn.clicked.connect(gen)
    api.add_side_tab(panel, "📋 MD 目录")

示例 3:用 Hook 监听保存 + 写入自定义元数据

"""保存自动记录扩展"""

def get_info():
    return {'name': 'auto_log',
            'display_name': '📝 保存日志',
            'version': '1.0.0',
            'description': '每次保存自动记录到项目日志里'}

def activate(api):
    def on_saved(editor):
        ch = api.db.get_chapter(editor.chapter_id)
        words = ch.get('word_count', 0) if ch else 0
        key = f'save_log_{api.project_id}'
        import json
        logs = json.loads(api.get_config(key, '[]'))
        logs.append({'chapter': ch['title'] if ch else '?', 'words': words})
        api.set_config(key, json.dumps(logs, ensure_ascii=False))
        api.log(f"保存记录: {ch['title']} {words:,} 字")

    api.on_chapter_saved(on_saved)

内置扩展:有声书

书砚内置了一个示例扩展 plugins/audiobook_plugin.py,功能是给每章填写旁白音色和预计时长,一键导出有声书描述文件。可以直接打开看源码,是学习插件开发的最佳模板。

这个插件做的事:

  1. 往侧边栏加一个 🎧 有声书 tab(一个 QTableWidget 表格)
  2. 每章可填:旁白音色、预计时长、是否已录、备注
  3. 数据持久化到 DB config(key = audiobook_meta_{project_id})
  4. 一键导出 JSON / TXT 格式的有声书描述文件