@xubill/xx-cli 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -0
- package/bin/cli.js +89 -0
- package/lib/core/base-plugin.js +292 -0
- package/lib/core/index.js +550 -0
- package/lib/plugins/ai.js +295 -0
- package/lib/plugins/config-manager.js +165 -0
- package/lib/plugins/history.js +108 -0
- package/lib/plugins/plugin-manager.js +700 -0
- package/lib/utils/config-manager.js +185 -0
- package/lib/utils/history-manager.js +119 -0
- package/lib/utils/logger.js +28 -0
- package/lib/utils/plugin-config.js +158 -0
- package/lib/utils/plugins-helper.js +276 -0
- package/lib/utils/transformers/getInput.js +76 -0
- package/lib/utils/transformers/index.js +43 -0
- package/lib/utils/transformers/renderLists.js +94 -0
- package/lib/utils/transformers/sfcMaterial.js +113 -0
- package/lib/utils/transformers/transformFilter.js +95 -0
- package/lib/utils/transformers/transformList.js +120 -0
- package/lib/utils/transformers/transformMock.js +43 -0
- package/lib/utils/transformers/transformRoutes.js +36 -0
- package/lib/utils/transformers/transformTable.js +81 -0
- package/lib/utils/transformers/transformTemplate.js +129 -0
- package/lib/utils/validator.js +96 -0
- package/package.json +68 -0
- package/plugin-development-new.md +565 -0
- package/plugin-development-old.md +447 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# xx-cli
|
|
2
|
+
|
|
3
|
+
个人开发工具集,支持插件系统,提供常用开发工具功能。
|
|
4
|
+
|
|
5
|
+
## 安装与使用
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 全局安装 xx-cli
|
|
9
|
+
npm i @xubill/xx-cli -g
|
|
10
|
+
|
|
11
|
+
# 添加插件
|
|
12
|
+
xx p add xxxx.js
|
|
13
|
+
|
|
14
|
+
# 使用命令
|
|
15
|
+
xx <command> [options]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 版本记录
|
|
19
|
+
|
|
20
|
+
### v2.0.0
|
|
21
|
+
- 支持新格式命令注册,兼容旧格式插件
|
|
22
|
+
- 更新插件创建模板,采用配置对象格式并包含类结构实现
|
|
23
|
+
|
|
24
|
+
### v2.0.1
|
|
25
|
+
- 新增ai插件,解析自然语言为xx命令
|
|
26
|
+
|
|
27
|
+
## 框架自带命令
|
|
28
|
+
|
|
29
|
+
xx-cli 框架自带以下核心命令(位于 core 模块中):
|
|
30
|
+
|
|
31
|
+
### 基础命令
|
|
32
|
+
|
|
33
|
+
| 命令 | 别名 | 描述 |
|
|
34
|
+
|------|------|------|
|
|
35
|
+
| `help` | - | 显示帮助信息 |
|
|
36
|
+
| `version` | `v` | 显示版本信息 |
|
|
37
|
+
| `history` | `h` | 查看命令历史记录 |
|
|
38
|
+
| `ai` | - | AI 智能解释命令,将自然语言转换为 xx 命令 |
|
|
39
|
+
|
|
40
|
+
### AI 插件使用说明
|
|
41
|
+
|
|
42
|
+
**获取 API key**:访问 [白山智算](https://ai.baishan.com/auth/login?referralCode=9CbeQycJJP) 获取 API key
|
|
43
|
+
|
|
44
|
+
**使用方法**:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 快捷添加 API key
|
|
48
|
+
xx ai add <apiKey>
|
|
49
|
+
|
|
50
|
+
# 使用 AI 解释命令
|
|
51
|
+
xx ai <查询内容>
|
|
52
|
+
|
|
53
|
+
# 生成配置文件
|
|
54
|
+
xx ai config
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**示例**:
|
|
58
|
+
```bash
|
|
59
|
+
# 添加 API key
|
|
60
|
+
xx ai add sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
61
|
+
|
|
62
|
+
# 解释命令
|
|
63
|
+
xx ai 关闭占用3000端口的进程
|
|
64
|
+
|
|
65
|
+
# 命令兜底(输入不存在的命令时自动调用 AI)
|
|
66
|
+
xx npm
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 插件管理命令
|
|
70
|
+
|
|
71
|
+
| 命令 | 别名 | 描述 |
|
|
72
|
+
|------|------|------|
|
|
73
|
+
| `plugin list` | `p ls` | 列出所有插件 |
|
|
74
|
+
| `plugin enable <plugin>` | `p en <plugin>` | 启用插件 |
|
|
75
|
+
| `plugin disable <plugin>` | `p dis <plugin>` | 禁用插件 |
|
|
76
|
+
| `plugin add <url>` | `p add <url>` | 添加外部自定义插件 |
|
|
77
|
+
| `plugin remove <plugin>` | `p rm <plugin>` | 删除指定插件 |
|
|
78
|
+
| `plugin create <name>` | `p cr <name>` | 创建指定名称的插件模板 |
|
|
79
|
+
| `plugin config <plugin> [key] [value]` | `p c <plugin> [key] [value]` | 查看和设置插件配置 |
|
|
80
|
+
|
|
81
|
+
### 配置管理命令
|
|
82
|
+
|
|
83
|
+
| 命令 | 别名 | 描述 |
|
|
84
|
+
|------|------|------|
|
|
85
|
+
| `config-manager export [target]` | `conf export [target]` | 导出所有插件配置到指定目录 |
|
|
86
|
+
| `config-manager import [source]` | `conf import [source]` | 从指定目录导入配置并覆盖 |
|
|
87
|
+
| `config-manager list` | `conf list` | 列出所有插件的配置文件位置和状态 |
|
|
88
|
+
|
|
89
|
+
## 项目结构
|
|
90
|
+
|
|
91
|
+
xx-cli 项目采用模块化设计,主要包含以下核心目录:
|
|
92
|
+
|
|
93
|
+
### 核心模块目录 (`/Users/xub/xx-cli/lib/core`)
|
|
94
|
+
|
|
95
|
+
核心模块目录包含 xx-cli 的核心功能实现,负责初始化系统、注册命令、管理插件等。
|
|
96
|
+
|
|
97
|
+
#### 文件结构
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
lib/core/
|
|
101
|
+
├── index.js # 核心模块,负责初始化系统、注册命令、管理插件等
|
|
102
|
+
└── base-plugin.js # 插件基础类,提供标准化的插件接口和通用功能
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### 核心文件说明
|
|
106
|
+
|
|
107
|
+
- **index.js**:核心模块,负责初始化系统、注册命令、管理插件等。它包含了插件加载、命令注册、钩子管理等核心功能。
|
|
108
|
+
- **base-plugin.js**:插件基础类,提供标准化的插件接口和通用功能。所有插件应该继承此类以确保一致性,它提供了命令注册、配置管理、用户界面等通用功能。
|
|
109
|
+
|
|
110
|
+
### 插件目录 (`/Users/xub/xx-cli/lib/plugins`)
|
|
111
|
+
|
|
112
|
+
插件目录包含 xx-cli 的内置插件,这些插件提供了各种功能,如配置管理、历史记录管理、插件管理等。
|
|
113
|
+
|
|
114
|
+
#### 文件结构
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
lib/plugins/
|
|
118
|
+
├── config-manager.js # 配置管理插件,用于管理所有插件的配置文件
|
|
119
|
+
├── history.js # 历史记录插件,用于查看命令历史记录
|
|
120
|
+
└── plugin-manager.js # 插件管理插件,用于管理所有插件
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### 内置插件说明
|
|
124
|
+
|
|
125
|
+
- **config-manager.js**:配置管理插件,用于管理所有插件的配置文件。它提供了导出、导入、列出配置等功能。
|
|
126
|
+
- **history.js**:历史记录插件,用于查看命令历史记录。它提供了查看、清除、搜索历史记录等功能。
|
|
127
|
+
- **plugin-manager.js**:插件管理插件,用于管理所有插件。它提供了列出、启用、禁用、添加、删除、创建插件等功能。
|
|
128
|
+
- **ai.js**:AI 智能解释插件,用于解释 xx-cli 命令的含义,将自然语言转换为命令。它提供了智能解释、命令兜底等功能。
|
|
129
|
+
|
|
130
|
+
## 插件开发
|
|
131
|
+
|
|
132
|
+
本部分将详细介绍如何在 xx-cli 中创建、开发和部署插件。
|
|
133
|
+
|
|
134
|
+
### 插件格式
|
|
135
|
+
|
|
136
|
+
xx-cli 支持两种插件格式:
|
|
137
|
+
|
|
138
|
+
1. **新格式(配置对象格式)**:使用配置对象定义的插件实现(推荐)
|
|
139
|
+
2. **旧格式(类结构格式)**:继承自 `BasePlugin` 类的插件实现(仅用于向后兼容)
|
|
140
|
+
|
|
141
|
+
### 新格式插件开发(推荐)
|
|
142
|
+
|
|
143
|
+
新格式插件使用配置对象定义插件信息和命令,结合类结构实现核心功能,是推荐的插件开发方式。
|
|
144
|
+
|
|
145
|
+
#### 创建新格式插件
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# 创建新格式插件(默认)
|
|
149
|
+
xx plugin create <plugin-name>
|
|
150
|
+
|
|
151
|
+
# 或者使用别名
|
|
152
|
+
xx p create <plugin-name>
|
|
153
|
+
# 或者使用更短的别名
|
|
154
|
+
xx p cr <plugin-name>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### 新格式插件特点
|
|
158
|
+
|
|
159
|
+
- **配置对象格式**:使用配置对象定义插件的基本信息和命令
|
|
160
|
+
- **包含类结构实现**:核心功能通过类结构实现,提高代码模块化和可维护性
|
|
161
|
+
- **自动生成命令名称**:根据插件名称自动生成驼峰命名的命令名称
|
|
162
|
+
- **标准的用户提示**:使用标准化的用户提示和错误处理
|
|
163
|
+
|
|
164
|
+
#### 详细文档
|
|
165
|
+
|
|
166
|
+
完整的新格式插件开发指南请参考:[新格式插件开发教程](./plugin-development-new.md)
|
|
167
|
+
|
|
168
|
+
### 旧格式插件开发(仅用于向后兼容)
|
|
169
|
+
|
|
170
|
+
旧格式插件需要继承 `BasePlugin` 类,主要用于向后兼容已有的插件。
|
|
171
|
+
|
|
172
|
+
#### 创建旧格式插件
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# 创建旧格式插件
|
|
176
|
+
xx plugin create <plugin-name> --format old
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### 详细文档
|
|
180
|
+
|
|
181
|
+
完整的旧格式插件开发指南请参考:[旧格式插件开发教程](./plugin-development-old.md)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* xx CLI 工具入口文件
|
|
5
|
+
* 全局命令:xx
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
(async () => {
|
|
9
|
+
const { program } = require("commander");
|
|
10
|
+
// 直接导入原始核心模块
|
|
11
|
+
const core = require("../lib/core");
|
|
12
|
+
const figlet = require("figlet");
|
|
13
|
+
const chalk = require("chalk").default;
|
|
14
|
+
const updateNotifier = require("update-notifier");
|
|
15
|
+
const pkg = require("../package.json");
|
|
16
|
+
|
|
17
|
+
// // 检查版本更新
|
|
18
|
+
// const notifier = updateNotifier({
|
|
19
|
+
// pkg,
|
|
20
|
+
// updateCheckInterval: 1000 * 60 * 60 * 24 // 1天检查一次
|
|
21
|
+
// });
|
|
22
|
+
|
|
23
|
+
// // 显示更新通知
|
|
24
|
+
// notifier.notify();
|
|
25
|
+
|
|
26
|
+
// 初始化核心功能
|
|
27
|
+
await core.init();
|
|
28
|
+
|
|
29
|
+
// 定义 CLI 命令
|
|
30
|
+
program
|
|
31
|
+
.name("xx")
|
|
32
|
+
.version(pkg.version)
|
|
33
|
+
.description("个人开发工具集,支持插件系统");
|
|
34
|
+
|
|
35
|
+
// 监听 --help 指令,加上额外的提示
|
|
36
|
+
program.on("--help", async function () {
|
|
37
|
+
// 美化logo
|
|
38
|
+
console.log(
|
|
39
|
+
chalk.green("\r\n" +
|
|
40
|
+
figlet.textSync("xx", {
|
|
41
|
+
font: "3D-ASCII",
|
|
42
|
+
horizontalLayout: "default",
|
|
43
|
+
verticalLayout: "default",
|
|
44
|
+
whitespaceBreak: true,
|
|
45
|
+
})
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
// 前后两个空行调整格式,更舒适
|
|
49
|
+
console.log();
|
|
50
|
+
console.log("示例:");
|
|
51
|
+
console.log(" $ xx help");
|
|
52
|
+
console.log(" $ xx version");
|
|
53
|
+
console.log();
|
|
54
|
+
console.log();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 注册核心命令
|
|
58
|
+
core.registerCommands(program);
|
|
59
|
+
|
|
60
|
+
// 全局错误处理
|
|
61
|
+
process.on('uncaughtException', (error) => {
|
|
62
|
+
console.error(chalk.red('错误:'), error.message);
|
|
63
|
+
console.error(chalk.red('错误堆栈:'), error.stack);
|
|
64
|
+
console.error(chalk.yellow('提示:'), '请检查命令参数是否正确,或使用 --help 查看帮助信息');
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
process.on('unhandledRejection', (error) => {
|
|
69
|
+
console.error(chalk.red('错误:'), error.message);
|
|
70
|
+
console.error(chalk.red('错误堆栈:'), error.stack);
|
|
71
|
+
console.error(chalk.yellow('提示:'), '请检查命令参数是否正确,或使用 --help 查看帮助信息');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// 记录命令历史
|
|
76
|
+
const commandLine = process.argv.slice(2).join(' ');
|
|
77
|
+
if (commandLine) {
|
|
78
|
+
const historyManager = require('../lib/utils/history-manager');
|
|
79
|
+
historyManager.addHistory(commandLine);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 解析命令行参数
|
|
83
|
+
program.parse(process.argv);
|
|
84
|
+
|
|
85
|
+
// 注册自动补全
|
|
86
|
+
if (program.autocomplete) {
|
|
87
|
+
program.autocomplete();
|
|
88
|
+
}
|
|
89
|
+
})();
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 插件基础类
|
|
3
|
+
* 提供标准化的插件接口和通用功能
|
|
4
|
+
* 所有插件应该继承此类以确保一致性
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ConfigManager = require('../utils/config-manager');
|
|
8
|
+
const chalk = require('chalk').default;
|
|
9
|
+
const ora = require('ora').default;;
|
|
10
|
+
const clipboardy = require('clipboardy').default;
|
|
11
|
+
|
|
12
|
+
class BasePlugin {
|
|
13
|
+
/**
|
|
14
|
+
* 构造函数
|
|
15
|
+
* @param {Object} options - 插件选项
|
|
16
|
+
*/
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.pluginName = this.constructor.name.replace('Plugin', '').toLowerCase();
|
|
19
|
+
this.homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
20
|
+
this.configManager = new ConfigManager(this.pluginName, options);
|
|
21
|
+
this.spinner = null;
|
|
22
|
+
this.progressTotal = 0;
|
|
23
|
+
this.progressCurrent = 0;
|
|
24
|
+
this.hooks = {};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 注册命令
|
|
29
|
+
* @param {Object} program - Commander.js 实例
|
|
30
|
+
* @abstract
|
|
31
|
+
*/
|
|
32
|
+
registerCommands(program) {
|
|
33
|
+
throw new Error('子类必须实现 registerCommands 方法');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 初始化插件
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*/
|
|
40
|
+
async init() {
|
|
41
|
+
// 插件初始化逻辑,子类可以覆盖
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 获取插件信息
|
|
46
|
+
* @returns {Object} 插件信息对象
|
|
47
|
+
*/
|
|
48
|
+
getInfo() {
|
|
49
|
+
return {
|
|
50
|
+
name: this.pluginName,
|
|
51
|
+
version: '1.0.0',
|
|
52
|
+
description: '插件描述'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 显示加载状态
|
|
58
|
+
* @param {string} text - 加载文本
|
|
59
|
+
*/
|
|
60
|
+
startLoading(text) {
|
|
61
|
+
this.spinner = ora(text).start();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 停止加载状态
|
|
66
|
+
* @param {string} text - 成功文本
|
|
67
|
+
*/
|
|
68
|
+
stopLoading(text) {
|
|
69
|
+
if (this.spinner) {
|
|
70
|
+
this.spinner.succeed(text);
|
|
71
|
+
this.spinner = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 显示错误状态
|
|
77
|
+
* @param {string} text - 错误文本
|
|
78
|
+
*/
|
|
79
|
+
showError(text) {
|
|
80
|
+
if (this.spinner) {
|
|
81
|
+
this.spinner.fail(text);
|
|
82
|
+
this.spinner = null;
|
|
83
|
+
} else {
|
|
84
|
+
console.error(chalk.red(`❌ ${text}`));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 启动进度条
|
|
90
|
+
* @param {string} text - 进度条文本
|
|
91
|
+
* @param {number} total - 总进度值
|
|
92
|
+
*/
|
|
93
|
+
startProgressBar(text, total = 100) {
|
|
94
|
+
this.spinner = ora({
|
|
95
|
+
text,
|
|
96
|
+
spinner: 'arc',
|
|
97
|
+
color: 'cyan'
|
|
98
|
+
}).start();
|
|
99
|
+
this.progressTotal = total;
|
|
100
|
+
this.progressCurrent = 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 更新进度条
|
|
105
|
+
* @param {number} current - 当前进度值
|
|
106
|
+
* @param {string} text - 进度条文本
|
|
107
|
+
*/
|
|
108
|
+
updateProgressBar(current, text) {
|
|
109
|
+
if (this.spinner && this.progressTotal > 0) {
|
|
110
|
+
this.progressCurrent = current;
|
|
111
|
+
const percentage = Math.min(Math.round((current / this.progressTotal) * 100), 100);
|
|
112
|
+
this.spinner.text = `${text || ''} ${percentage}%`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 停止进度条
|
|
118
|
+
* @param {string} text - 完成文本
|
|
119
|
+
*/
|
|
120
|
+
stopProgressBar(text) {
|
|
121
|
+
if (this.spinner) {
|
|
122
|
+
this.spinner.succeed(text);
|
|
123
|
+
this.spinner = null;
|
|
124
|
+
this.progressTotal = 0;
|
|
125
|
+
this.progressCurrent = 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 显示成功信息
|
|
131
|
+
* @param {string} text - 成功文本
|
|
132
|
+
*/
|
|
133
|
+
showSuccess(text) {
|
|
134
|
+
console.log(chalk.green(`✅ ${text}`));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 显示警告信息
|
|
139
|
+
* @param {string} text - 警告文本
|
|
140
|
+
*/
|
|
141
|
+
showWarning(text) {
|
|
142
|
+
console.log(chalk.yellow(`⚠️ ${text}`));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 显示信息
|
|
147
|
+
* @param {string} text - 信息文本
|
|
148
|
+
*/
|
|
149
|
+
showInfo(text) {
|
|
150
|
+
console.log(chalk.blue(`${text}`));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 加载配置
|
|
155
|
+
* @param {string} configName - 配置名称
|
|
156
|
+
* @param {Object} cliOptions - 命令行选项
|
|
157
|
+
* @returns {Object} 合并后的配置对象
|
|
158
|
+
*/
|
|
159
|
+
loadConfig(configName = 'config', cliOptions = {}) {
|
|
160
|
+
return this.configManager.loadConfig(configName, cliOptions);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 保存配置
|
|
165
|
+
* @param {Object} config - 配置对象
|
|
166
|
+
* @param {string} configName - 配置名称
|
|
167
|
+
* @param {boolean} isGlobal - 是否保存到全局配置
|
|
168
|
+
*/
|
|
169
|
+
saveConfig(config, configName = 'config', isGlobal = true) {
|
|
170
|
+
this.configManager.saveConfig(config, configName, isGlobal);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 验证配置
|
|
175
|
+
* @param {Object} config - 配置对象
|
|
176
|
+
* @param {Object} schema - 配置 schema
|
|
177
|
+
* @returns {Object} 验证结果
|
|
178
|
+
*/
|
|
179
|
+
validateConfig(config, schema) {
|
|
180
|
+
return this.configManager.validateConfig(config, schema);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 错误处理
|
|
185
|
+
* @param {Error} error - 错误对象
|
|
186
|
+
* @param {string} message - 错误消息
|
|
187
|
+
*/
|
|
188
|
+
handleError(error, message = '操作失败') {
|
|
189
|
+
this.showError(`${message}: ${error.message}`);
|
|
190
|
+
// 可以添加错误日志记录等逻辑
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 执行异步操作
|
|
195
|
+
* @param {Function} fn - 异步函数
|
|
196
|
+
* @param {string} loadingText - 加载文本
|
|
197
|
+
* @param {string} successText - 成功文本
|
|
198
|
+
* @param {string} errorText - 错误文本
|
|
199
|
+
* @returns {Promise<any>}
|
|
200
|
+
*/
|
|
201
|
+
async executeAsync(fn, loadingText, successText, errorText) {
|
|
202
|
+
try {
|
|
203
|
+
this.startLoading(loadingText);
|
|
204
|
+
const result = await fn();
|
|
205
|
+
this.stopLoading(successText);
|
|
206
|
+
return result;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.handleError(error, errorText);
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 注册钩子
|
|
215
|
+
* @param {string} event - 事件名称
|
|
216
|
+
* @param {Function} callback - 回调函数
|
|
217
|
+
*/
|
|
218
|
+
registerHook(event, callback) {
|
|
219
|
+
if (!this.hooks) {
|
|
220
|
+
this.hooks = {};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!this.hooks[event]) {
|
|
224
|
+
this.hooks[event] = [];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.hooks[event].push(callback);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 触发钩子
|
|
232
|
+
* @param {string} event - 事件名称
|
|
233
|
+
* @param {*} data - 事件数据
|
|
234
|
+
* @returns {Promise<Array>} 钩子执行结果
|
|
235
|
+
*/
|
|
236
|
+
async triggerHook(event, data) {
|
|
237
|
+
if (!this.hooks || !this.hooks[event]) {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const results = [];
|
|
242
|
+
for (const callback of this.hooks[event]) {
|
|
243
|
+
try {
|
|
244
|
+
const result = await callback(data);
|
|
245
|
+
results.push(result);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
this.handleError(error, `执行钩子 ${event} 时出错`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return results;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 检查是否注册了指定钩子
|
|
256
|
+
* @param {string} event - 事件名称
|
|
257
|
+
* @returns {boolean} 是否注册了钩子
|
|
258
|
+
*/
|
|
259
|
+
hasHook(event) {
|
|
260
|
+
return this.hooks && this.hooks[event] && this.hooks[event].length > 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 复制文本到剪贴板
|
|
265
|
+
* @param {string} text - 要复制的文本
|
|
266
|
+
* @param {string} successMessage - 成功消息
|
|
267
|
+
* @returns {Promise<boolean>} 是否复制成功
|
|
268
|
+
*/
|
|
269
|
+
async copyToClipboard(text, successMessage) {
|
|
270
|
+
try {
|
|
271
|
+
// 尝试不同的 clipboardy API 调用方式
|
|
272
|
+
if (clipboardy.default && typeof clipboardy.default.write === 'function') {
|
|
273
|
+
await clipboardy.default.write(text);
|
|
274
|
+
} else if (typeof clipboardy.write === 'function') {
|
|
275
|
+
await clipboardy.write(text);
|
|
276
|
+
} else if (typeof clipboardy.writeSync === 'function') {
|
|
277
|
+
clipboardy.writeSync(text);
|
|
278
|
+
} else {
|
|
279
|
+
throw new Error('clipboardy API 不可用');
|
|
280
|
+
}
|
|
281
|
+
if (successMessage) {
|
|
282
|
+
this.showSuccess(successMessage);
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
this.showWarning(`复制到剪贴板失败: ${error.message}`);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
module.exports = BasePlugin;
|