当前位置:首页 > FF14

FF14 挖宝会计 - V4插件开发手册

FF14 挖宝会计 - 插件开发手册目录 插件是什么 插件必需声明 目录结构规范 插件生命周期 插件方法说明 插件可用的 API 数据库接口 主窗口公开 API WebSocket 服务

黑卡蒂admin

FF14 挖宝会计 - 插件开发手册

目录

  1. 插件是什么

  2. 插件必需声明

  3. 目录结构规范

  4. 插件生命周期

  5. 插件方法说明

  6. 插件可用的 API

  7. 数据库接口

  8. 主窗口公开 API

  9. WebSocket 服务器

  10. 创建自定义窗口

  11. 跨插件协作

  12. 打包与分发

  13. 性能与稳定性

  14. 注意事项

  15. 完整示例

  16. 依赖清单


一、插件是什么?

一个插件就是一个独立的 .py 文件或文件夹,放在 %APPDATA%\FF14TreasureHunter\plugin\plugins\ 目录下(没有则新建)。程序启动时会自动扫描并加载其中的所有插件。

每个插件必须定义一个类,继承自 src.core.tool_plugin.ToolPlugin,并实现或声明一些必要的属性和方法。

目录结构规范

方式一:单文件插件

text
plugin/plugins/
├── door_chooser.py          # 插件主文件
├── another_plugin.py        # 另一个插件

方式二:文件夹插件(推荐)

text
plugin/plugins/
├── door_chooser/            # 插件文件夹(与 plugin_id 同名)
│   ├── main.py              # 插件入口文件(必须)
│   ├── helper.pyd           # 私有依赖(可选)
│   ├── icon.png             # 资源文件(可选)
│   └── overlay.html         # 悬浮窗页面(可选)
├── summary_display/
│   └── main.py

配置文件目录

text
plugin/
├── plugins/                 # 插件代码目录
├── config/                  # 插件配置目录
│   ├── door_chooser/
│   │   └── settings.json    # 插件配置
│   └── summary_display/
│       └── settings.json
└── pluginlist.json          # 所有插件的元数据缓存

二、插件必需声明

在你的插件类中,必须直接声明以下类属性(不需要实例化),它们是插件的身份证:

属性 类型 说明
plugin_id str 全局唯一标识,建议使用英文下划线命名,如 "door_chooser"。后续配置和更新都依赖此 ID。
plugin_name str 显示在管理界面的名称,如 "选门工具"
plugin_description str 简要描述插件功能,会出现在管理界面和鼠标悬停提示中。
plugin_author str 作者名。
plugin_version str 版本号,如 "1.0.0"。用于更新检测。
update_url str 可选。更新信息 JSON 文件的 URL。若不需要更新功能,留空即可。

示例

python
from src.core.tool_plugin import ToolPlugin

class DoorChooser(ToolPlugin):
    plugin_id = "door_chooser"
    plugin_name = "选门工具"
    plugin_description = "发送指令随机选择左/中/右门"
    plugin_author = "陆行鸟"
    plugin_version = "1.0.0"
    update_url = ""  # 暂不提供更新

三、目录结构规范

插件文件夹结构

text
plugin/plugins/{plugin_id}/
├── main.py              # 插件主文件(必须)
├── icon.png             # 可选资源
├── helper.pyd           # 私有依赖库
└── overlay.html         # 悬浮窗页面

配置文件路径

插件配置自动存储在 plugin/config/{plugin_id}/settings.json,通过 self.load_config() 和 self.save_config() 操作。


四、插件生命周期

生命周期流程图

text
加载插件 → on_load() → 正常运行 → on_unload() → 卸载插件
                ↓
         on_permission_changed()  (权限变更时)

生命周期方法

方法 说明
on_load() 插件被加载/启用时调用。在此创建窗口、启动服务、初始化资源。
on_unload() 插件被卸载/禁用时调用。在此销毁窗口、释放资源、停止 WebSocket 服务器。
on_permission_changed(has_full_access: bool) 当用户在管理界面切换本插件的数据库权限时调用。

示例

python
def on_load(self):
    """插件加载时初始化"""
    config = self.load_config()
    self.debug = config.get('debug', False)
    self.start_ws_server(9765)      # 启动 WebSocket
    self.create_overlay()           # 创建 UI
    self.debug_log("插件已加载")

def on_unload(self):
    """插件卸载时清理资源"""
    self.stop_ws_server()           # 停止 WebSocket
    self.destroy_overlay()          # 销毁 UI
    self.debug_log("插件已卸载")

def on_permission_changed(self, has_full_access: bool):
    """数据库权限变更时调用"""
    self.debug_log(f"数据库权限已变更: {has_full_access}")

五、插件方法说明

1. 构造方法 __init__(self, manager, plugin_id)

插件实例化时调用,manager 是工具箱管理器,你可以通过它访问各种能力。通常在这里加载本插件的自定义配置。

python
def __init__(self, manager, plugin_id):
    super().__init__(manager, plugin_id)
    config = self.load_config()  # 读取 plugin/config/{plugin_id}/settings.json
    self.keyword = config.get('keyword', '!选门')

2. 日志匹配条件 get_match_conditions(self)

如果插件需要监听特定的日志事件,实现此方法,返回一个条件列表。每个条件是一个字典,可以包含 message_codetype_codekeyword(大小写不敏感子串匹配)。所有条件为"与"关系,列表内条件为"或"关系。

python
def get_match_conditions(self):
    # 匹配 00|0038 的默语消息,且内容包含 self.keyword
    return [{'message_code': '00', 'type_code': '0038', 'keyword': self.keyword}]

如果不需监听日志,可以返回空列表或直接删除该方法。
#更新支持列表 OR 语义:
        只要事件满足任意一个条件,就视为匹配。列表中的多个条件,只要满足其中一个,就会触发插件的 on_log_event
实例:

def get_match_conditions(self): # 监听11(队伍), 03/38/39(角色名), 21(挖掘动作), 00+0839(任务流程)
    return [
        {'message_code': '11'},
        {'message_code': '03'},
        {'message_code': '38'},
        {'message_code': '39'},
        {'message_code': '21'},
        {'message_code': '00', 'type_code': '0839'},
    ]

3. 事件处理 on_log_event(self, event)

当有日志匹配你的条件时,此方法被调用。event 是一个字典,包含以下字段:

  • timestamp:时间戳

  • message_code:消息代码

  • type_code:类型代码

  • event_type:事件类型

  • raw_log:原始日志行

python
def on_log_event(self, event):
    # 随机选门
    result = random.choice(["左", "中", "右"])
    self.send_message(f"/e {result}门 <se.6>")

4. 数据库权限声明 get_full_db_permission_state(self) -> bool

返回 True 表示你的插件需要完整数据库访问权限(可读写所有数据)。管理界面会根据此返回值决定是否允许用户勾选"开放"权限。若返回 False,则插件只拥有隔离权限(只能读写自己的记录)。

python
def get_full_db_permission_state(self):
    return False  # 选门工具无需数据库

5. 设置界面 get_settings_widget(self) -> QWidget or None

如果插件需要自定义设置界面,实现此方法,返回一个 QWidget。用户可在管理界面点击"打开设置"来弹出这个窗口。没有设置界面则返回 None

python
def get_settings_widget(self):
    from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton
    
    widget = QWidget()
    layout = QVBoxLayout(widget)
    layout.addWidget(QLabel("关键词:"))
    self.keyword_edit = QLineEdit(self.keyword)
    layout.addWidget(self.keyword_edit)
    
    save_btn = QPushButton("保存")
    save_btn.clicked.connect(self.save_settings)
    layout.addWidget(save_btn)
    
    return widget

def save_settings(self):
    self.keyword = self.keyword_edit.text()
    self.save_config({'keyword': self.keyword})

6. 依赖声明 get_dependencies(self)

如果插件依赖其他插件,实现此方法返回依赖的插件 ID 列表。

python
def get_dependencies(self):
    return ["data_provider", "overlay_manager"]

六、插件可用的 API

插件基类提供的便利方法(通过 self 调用)

方法 说明
self.send_message(text) 通过鲶鱼精邮差发送聊天消息。text 可以是 /e 消息 或 /p 消息 等格式。
self.get_config_dir() 返回本插件的配置目录路径(Path 对象)。
self.load_config() 加载插件配置(settings.json),返回字典。
self.save_config(data) 保存插件配置(字典)。
self.debug_log(msg) 输出调试日志到 plugin/DEBUG.log(需 self.debug = True)。
self.plugin_db 数据库访问代理。根据权限,可能是隔离的 PluginDB 或完整的 Database 实例。
self.main_window 访问主窗口实例(只读属性)。
self.ws_server 获取当前插件的 WebSocket 服务器实例(可能为 None)。
self.start_ws_server(port) 为当前插件启动 WebSocket 服务器。
self.stop_ws_server() 停止当前插件的 WebSocket 服务器。
self.get_plugin(plugin_id) 获取另一个已加载的插件实例。

调试日志使用

python
def on_load(self):
    config = self.load_config()
    self.debug = config.get('debug', False)  # 从配置读取是否启用调试
    self.debug_log("插件加载完成")

七、数据库接口

插件通过 self.plugin_db 访问数据库。根据用户在管理界面设置的权限,该对象可能是:

  • 受限模式PluginDB 实例(默认)

  • 完全模式:原始 Database 实例

1. 受限模式 (PluginDB)

受限模式下,插件可读取全部数据,但写入操作自动附加 plugin_id,且只能修改/删除自己创建的记录。

写入方法(仅操作自己的记录)

方法 说明
log_event(timestamp, event_type, raw_log=None, extra=None, run_label='') 写入一条事件,自动附加当前 plugin_id。返回 event_id
add_loot(event_id, item_name, quantity=1, map_name=None, vault_segment_id=None) 记录一件物品(与指定事件关联)。
add_custom_record(event_id, record_name, value, vault_segment_id=None) 添加一条自定义记录。
update_my_record(record_id, new_value) 修改自己创建的自定义记录的值。
delete_my_record(record_id) 删除自己创建的自定义记录。

读取方法(全部数据可读)

方法 说明
get_my_custom_records(since=None, run_label=None) 获取本插件创建的所有自定义记录。
get_total_maps(run_label=None) 总地图数。
get_total_magic_seals(run_label=None) 总魔纹数。
get_loot_summary(run_label=None) 物品汇总。
get_layer_summary(run_label=None) 层级汇总。
get_custom_record_summary(run_label=None) 所有自定义记录汇总。
get_run_summary(run_label) 当前运行标签的盈亏汇总。

示例:记录自定义数据

python
def on_log_event(self, event):
    # 创建一个事件
    eid = self.plugin_db.log_event(
        timestamp=event['timestamp'],
        event_type='custom',
        raw_log=event.get('raw_log'),
        run_label=self.get_current_run_label()
    )
    
    # 添加自定义记录
    self.plugin_db.add_custom_record(eid, "选门次数", 1)
    
    # 读取自己插件的所有记录
    records = self.plugin_db.get_my_custom_records()
    for r in records:
        print(r['record_name'], r['value'])

2. 完全模式 (Database)

当用户授予"开放"权限后,插件直接获得完整的 Database 实例,拥有与主程序相同的读写权限,无任何限制。请谨慎使用,避免破坏用户数据。

可用方法包括 log_event(不带自动 plugin_id)、直接调用 execute 执行自定义 SQL 等,但需自行保证数据安全。

3. 如何申请完整权限

在插件类中重写 get_full_db_permission_state 方法并返回 True

python
def get_full_db_permission_state(self) -> bool:
    return True

用户在管理界面即可将"数据权限"切换为"开放"。


八、主窗口公开 API

插件可通过 self.main_window 直接获取主程序的所有实时数据与状态,无需数据库查询。

方法 返回类型 说明
get_summary_data() dict 当前全部汇总数据(地图数、魔纹数、系统金、总成本、总收入、盈亏、物品列表、层级列表)
get_current_segment_data() dict 当前分段(增量)数据
get_segment_snapshots() list 所有历史分段快照
get_game_status() str 游戏状态:"启动" 或 "等待游戏数据..."
get_postnamazu_status() bool 鲶鱼精邮差是否已连接
is_advanced_output_enabled() bool 高级功能输出是否启用
is_prediction_enabled() bool 预测功能是否启用
is_detail_output_enabled() bool 详细信息通知是否启用
is_global_actions_enabled() bool 全局高级功能是否启用
is_map_actions_enabled() bool 地图高级功能是否启用
is_single_loot_enabled() bool 单人物品获取模式是否启用
get_current_run_label() str 当前运行标签(日期)
get_item_map_short_name(item_name) str 获取物品所属地图的简称(如 "G18")
get_layer_map_short_name(layer_name) str 获取层级所属地图的简称

示例

python
# 获取汇总数据
summary = self.main_window.get_summary_data()
print(f"地图数: {summary['total_maps']}, 盈亏: {summary['profit']}")

# 获取游戏状态
game_status = self.main_window.get_game_status()

# 获取物品所属地图
short_name = self.main_window.get_item_map_short_name("羊角笛")

# 获取当前运行标签
run_label = self.main_window.get_current_run_label()

九、WebSocket 服务器

启动 WebSocket 服务器

插件可以创建独立的 WebSocket 服务器,用于与本地网页前端通信。

python
def on_load(self):
    # 启动 WebSocket 服务器,监听指定端口
    self.start_ws_server(9765)
    self.debug_log(f"WebSocket 服务器已启动,端口: 9765")

广播消息

python
def refresh_data(self):
    summary = self.main_window.get_summary_data()
    segment = self.main_window.get_current_segment_data()
    
    if self.ws_server:
        self.ws_server.broadcast({
            "type": "dual_update",
            "summary": summary,
            "segment": segment,
            "timestamp": datetime.now().isoformat()
        })

停止 WebSocket 服务器

重要:卸载时必须停止 WebSocket 服务器以释放端口。

python
def on_unload(self):
    self.stop_ws_server()
    self.debug_log("WebSocket 服务器已停止")

工具箱管理器 WebSocket 方法(通过 self.manager

方法 说明
create_ws_server(plugin_id, port) 为插件创建独立端口的 WebSocket 服务器(自动停止旧服务)
stop_ws_server(plugin_id) 停止插件的 WebSocket 服务器并释放端口

十、创建自定义窗口

插件可以在事件触发时创建并显示独立的 QWidget 窗口。为确保主窗口不受影响,请遵循以下规则:

  1. 使用 show() 而非 exec_() 显示窗口。

  2. 在窗口的 __init__ 中只构建 UI,不执行耗时操作。

  3. 如需加载数据,使用 QTimer.singleShot(0, self.load_data) 延迟执行。

示例:非模态工具窗口

python
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt, QTimer

class MyToolWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("我的工具")
        self.setWindowFlags(Qt.Window)  # 独立窗口
        
        layout = QVBoxLayout(self)
        layout.addWidget(QLabel("工具内容"))
        
        # 延迟加载数据
        QTimer.singleShot(0, self.load_data)
        self.show()
    
    def load_data(self):
        # 执行耗时操作
        pass

# 在插件事件中调用
def on_log_event(self, event):
    self.window = MyToolWindow()

使用 Overlay Manager 创建悬浮窗

程序内置了 overlay_manager 插件,可用于创建可拖拽、半透明的悬浮窗。

python
def init_overlay(self):
    import time
    from pathlib import Path
    
    # 等待 overlay_manager 就绪(最多3秒)
    for _ in range(30):
        mgr = self.get_plugin("overlay_manager")
        if mgr and getattr(mgr, 'enabled', False):
            self.overlay_manager = mgr
            break
        time.sleep(0.1)
    else:
        self.debug_log("overlay_manager 插件未找到或未启用")
        return
    # 检查窗口是否已被注册
    existing_windows = self.overlay_manager._windows_config.get('windows', [])
    if any(w['window_id'] == self.overlay_window_id for w in existing_windows):
        self.debug_log("悬浮窗已存在,跳过注册")
        return

    plugin_dir = Path(__file__).resolve().parent
    html_path = plugin_dir / "overlay.html"
    
    if not html_path.exists():
        self.debug_log(f"缺少 overlay.html: {html_path}")
        return
    
    self.overlay_manager.register_overlay(
        window_id=self.overlay_window_id,
        url=html_path.as_uri(),
        width=800, height=600,
        x=100, y=100,
        draggable=True,
        click_through=False,
        auto_resize=True,
        scrollable=True
    )
    self.debug_log(f"已请求创建悬浮窗: {self.overlay_window_id}")


如果希望保留“持续更新窗口属性”的能力

如果你以后需要通过插件更新窗口属性(比如修改默认大小),可以改为只更新 url,而不动已有的位置和大小:

python
    # 更新已有窗口,但只修改 URL,保留位置和大小
    for w in existing_windows:
        if w['window_id'] == self.overlay_window_id:
            w['url'] = html_path.as_uri()
            self.overlay_manager.save_windows_config()
            # 如果需要实时更新窗口,可调用宿主指令(但谨慎)
            return

十一、跨插件协作

获取其他插件实例

通过 self.get_plugin(plugin_id) 获取另一个已加载的插件实例。

python
def on_load(self):
    # 获取数据提供者插件
    data_provider = self.get_plugin("data_provider")
    if data_provider:
        self.data = data_provider.get_data()

声明依赖

在插件类中实现 get_dependencies() 方法,确保依赖插件先加载。

python
def get_dependencies(self):
    return ["data_provider", "overlay_manager"]

工具箱管理器方法(通过 self.manager

方法 说明
get_plugin(plugin_id) 获取另一个已加载的插件实例
save_plugin_state() 将插件元数据(启用状态、权限)保存到 pluginlist.json
delete_plugin(plugin_id) 永久删除插件及其所有数据(文件、配置、记录)
install_from_zip(zip_path) 从 ZIP 文件导入插件包
download_file(url, dest) 下载文件到指定路径

十二、打包与分发

ZIP 包格式

若要通过 ZIP 分发,ZIP 内必须包含 manifest.json,结构如下:

json
{
    "plugins": [
        {
            "plugin_id": "door_chooser",
            "version": "1.0.1",
            "entry_file": "main.py",
            "dependencies": []
        }
    ]
}

ZIP 内其他文件将全部被解压到插件文件夹。

ZIP 包目录结构示例

text
door_chooser_v1.0.1.zip
├── manifest.json
├── main.py
├── icon.png
└── overlay.html

十三、性能与稳定性

执行限制

您的插件在主线程中执行,但为了避免阻塞 UI 和核心功能,插件事件处理被推迟到 Qt 事件队列的下一轮。这意味着即使您的 on_log_event 执行了耗时操作,主界面也不会立即卡死,但极长时间(>数秒)的阻塞仍会导致界面失去响应

注意:任何执行超过 3 秒的插件都会被自动禁用。

最佳实践

  1. 耗时操作使用后台线程

python
import threading

def on_log_event(self, event):
    thread = threading.Thread(target=self.do_heavy_work)
    thread.daemon = True
    thread.start()

def do_heavy_work(self):
    # 执行网络请求、文件 I/O 等耗时操作
    result = self.fetch_data()
    # 通过信号或 invokeMethod 更新 UI
  1. 避免在 on_log_event 中使用无限循环

  2. 使用 self.debug_log() 记录关键信息,结合 plugin/DEBUG.log 快速定位问题

调试建议

python
def on_load(self):
    config = self.load_config()
    self.debug = config.get('debug', False)
    self.debug_log("插件加载完成,调试模式: {}".format(self.debug))
    
def on_log_event(self, event):
    self.debug_log(f"收到事件: {event.get('raw_log', '')}")
    # 插件逻辑...

十四、注意事项

  1. 唯一 ID 不可变plugin_id 确定后不要随意更改,否则用户的配置和数据库记录会丢失关联。

  2. 谨慎申请完整数据库权限:如非必要,请使用隔离模式,确保用户数据安全。

  3. 设置文件格式:建议使用 JSON,通过 self.load_config() 和 self.save_config() 操作。

  4. 卸载时务必释放资源

    • 调用 self.stop_ws_server() 停止 WebSocket

    • 关闭所有自定义窗口

    • 保存配置

  5. 隔离模式下,所有写入操作会自动附上 plugin_id,不会影响主程序或其他插件的数据。

  6. 读取操作不受限,但请勿缓存敏感用户信息。

  7. 如需执行复杂查询,可在完全权限下使用 self.plugin_db.execute("SELECT ...")(受限模式未暴露)。

  8. 数据库字段增删请在主程序更新时留意兼容性。


十五、完整示例

示例:选门工具

完整代码可在 plugin/plugins/door_chooser.py 找到。

python
import random
from src.core.tool_plugin import ToolPlugin
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton

class DoorChooser(ToolPlugin):
    plugin_id = "door_chooser"
    plugin_name = "选门工具"
    plugin_description = "发送指令(默认 !选门),随机选择左/中/右门"
    plugin_author = "陆行鸟"
    plugin_version = "1.0.0"
    update_url = ""
    
    def __init__(self, manager, plugin_id):
        super().__init__(manager, plugin_id)
        config = self.load_config()
        self.keyword = config.get('keyword', '!选门')
        self.debug = config.get('debug', False)
    
    def get_match_conditions(self):
        return [{'message_code': '00', 'type_code': '0038', 'keyword': self.keyword}]
    
    def on_log_event(self, event):
        result = random.choice(["左", "中", "右"])
        self.send_message(f"/e {result}门 <se.6>")
        self.debug_log(f"选门结果: {result}")
    
    def get_full_db_permission_state(self):
        return False
    
    def get_settings_widget(self):
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.addWidget(QLabel("触发关键词:"))
        self.keyword_edit = QLineEdit(self.keyword)
        layout.addWidget(self.keyword_edit)
        
        save_btn = QPushButton("保存")
        save_btn.clicked.connect(self.save_settings)
        layout.addWidget(save_btn)
        return widget
    
    def save_settings(self):
        self.keyword = self.keyword_edit.text()
        self.save_config({'keyword': self.keyword, 'debug': self.debug})
    
    def on_load(self):
        self.debug_log("选门工具已加载")
    
    def on_unload(self):
        self.debug_log("选门工具已卸载")

示例:数据展示插件(使用 WebSocket)

python
import json
from datetime import datetime
from src.core.tool_plugin import ToolPlugin
from PyQt5.QtCore import QTimer

class SummaryDisplay(ToolPlugin):
    plugin_id = "summary_display"
    plugin_name = "数据展示"
    plugin_description = "通过 WebSocket 推送挖宝数据到前端"
    plugin_author = "陆行鸟"
    plugin_version = "1.0.0"
    update_url = ""
    
    def on_load(self):
        config = self.load_config()
        self.refresh_interval = config.get('refresh_interval', 5)
        self.start_ws_server(9765)
        
        # 定时推送数据
        self.timer = QTimer()
        self.timer.timeout.connect(self.push_data)
        self.timer.start(self.refresh_interval * 1000)
        self.debug_log("数据展示插件已加载")
    
    def on_unload(self):
        if self.timer:
            self.timer.stop()
        self.stop_ws_server()
        self.debug_log("数据展示插件已卸载")
    
    def push_data(self):
        if not self.ws_server:
            return
        
        summary = self.main_window.get_summary_data()
        segment = self.main_window.get_current_segment_data()
        
        self.ws_server.broadcast({
            "type": "data_update",
            "summary": summary,
            "segment": segment,
            "timestamp": datetime.now().isoformat()
        })
    
    def get_full_db_permission_state(self):
        return False  # 只读数据,不需要完整权限

十六、依赖清单

以下是程序打包时已包含的全部第三方依赖库,插件开发者可放心使用这些库而无需用户额外安装。若插件需要使用清单外的库,请务必在插件文档中明确说明,并提供安装指导。

核心依赖

库名 版本 (参考) 用途
PyQt5 5.15.x 图形用户界面框架
requests 2.x HTTP 网络请求(API 调用、版本检查、市场数据)
beautifulsoup4 4.x HTML/XML 解析
winotify 1.x Windows 原生 Toast 通知
sqlite3 (内置) 本地数据库
win32file - 网络管道(Deucalion 预测)

Qt 子系统(由 PyQt5 附带)

模块 说明
PyQt5.QtWidgets 窗口、控件、布局
PyQt5.QtCore 信号槽、定时器、事件循环
PyQt5.QtGui 字体、图标、颜色
PyQt5.QtNetwork 网络功能

Python 标准库(无需额外安装)

库名 用途
json 配置文件读写、数据序列化
threading 日志监控后台线程
queue 事件队列
hashlib 日志行去重
re 正则表达式匹配
time / datetime 时间处理
pathlib 文件路径操作
sqlite3 数据库操作
importlib 插件动态加载
zipfile 插件 ZIP 包导入
tempfile 临时文件
shutil 文件复制、目录删除
os 系统操作
sys 系统参数
ctypes Windows API 调用
collections 数据结构(deque、defaultdict)
urllib.parse URL 编码
typing 类型注解

插件开发注意事项

  1. 优先使用清单内库:避免引入额外依赖,保证用户开箱即用。

  2. 如需特殊库:在插件文档中明确列出,并提供 .pyd 文件或安装说明。

  3. 打包时不会自动包含新库:如果您为插件引入了 numpy 等大型库,需要用户自行安装 Python 环境或由您提供预编译文件。


版本历史

版本 日期 说明
1.0 - 初始版本
2.0 - 新增主窗口 API、WebSocket、生命周期方法
2.1 - 新增 Overlay Manager 悬浮窗支持
3.0 2026-01-15 完整整合所有文档,重组织结构


返回顶部