crabatool 1.0.857 → 1.0.860
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/ev-recording-implementation.md +129 -1
- package/lib/utils.js +4 -1
- package/package.json +1 -1
- package/tool/checkjs.js +4 -0
- package/tool/javaEnum.js +141 -0
- package/tool/ngpSkinUtils.js +1 -1
|
@@ -162,4 +162,132 @@ crabatool -runEv -evSavePath "ev保存音频的路径,如c:\\Users\\grasp\\ev
|
|
|
162
162
|
|
|
163
163
|
- 所有日志都包含时间戳
|
|
164
164
|
- 详细记录文件监控、大小变化等信息
|
|
165
|
-
- 错误信息清晰明了
|
|
165
|
+
- 错误信息清晰明了
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
## 方案二:windows【命令版ev服务工具】使用步骤
|
|
170
|
+
|
|
171
|
+
1. **Node.js 环境**【仅首次安装】
|
|
172
|
+
|
|
173
|
+
若电脑尚未安装 Node.js,请先下载并安装:[Node.js 下载地址](https://nodejs.cn/download/)
|
|
174
|
+
|
|
175
|
+
2. [下载工具包](setup/evtool.zip) 然后解压到本地
|
|
176
|
+
|
|
177
|
+
3. 双击安装软件.bat【仅首次安装】
|
|
178
|
+
|
|
179
|
+
后期通知软件有更新的情况,就需要双击更新软件.bat,平时不用【仅有更新的时候】
|
|
180
|
+
|
|
181
|
+
4. 右键启动软件.bat---编辑---根据你当前的情况修改ev的存储路径【仅首次】
|
|
182
|
+
|
|
183
|
+
如果不清楚怎么修改ev存储路径,继续看下面的介绍
|
|
184
|
+
|
|
185
|
+
5. 双击启动软件.bat【**每次**】
|
|
186
|
+
|
|
187
|
+
平时需要采集音视频的时候
|
|
188
|
+
|
|
189
|
+
-----如果只是使用步骤,到此结束即可------
|
|
190
|
+
|
|
191
|
+
还需更多了解,可以继续往下看
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# crabatool + EV录屏 集成服务介绍
|
|
196
|
+
|
|
197
|
+
## 功能说明
|
|
198
|
+
|
|
199
|
+
`crabatool` 提供 EV 录屏自动化集成功能。启动服务后,工具将自动监听 EV 录屏生成的文件(视频/音频),检测录制完成并自动上传至七牛云存储,最终将生成的 URL 回填至教学录制页面中,实现教学音视频的自动化采集与上传。
|
|
200
|
+
|
|
201
|
+
## 适用场景
|
|
202
|
+
|
|
203
|
+
- 录制教学视频或音频,自动上传至七牛云
|
|
204
|
+
- 无需手动操作,自动获取录制文件的访问链接
|
|
205
|
+
- 支持 EV 录屏路径自动检测,简化配置流程
|
|
206
|
+
|
|
207
|
+
## 依赖环境
|
|
208
|
+
|
|
209
|
+
1. **Node.js 环境**(仅首次安装)
|
|
210
|
+
若电脑尚未安装 Node.js,请先下载并安装:[Node.js 下载地址](https://nodejs.cn/download/)
|
|
211
|
+
|
|
212
|
+
2. **全局安装 crabatool**(仅首次安装)
|
|
213
|
+
打开命令行工具,执行以下命令:
|
|
214
|
+
```bash
|
|
215
|
+
npm install crabatool -g
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 启动服务
|
|
219
|
+
|
|
220
|
+
### 命令格式
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
crabatool -runEv -evSavePath "<EV录屏保存路径>"
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 参数说明
|
|
227
|
+
|
|
228
|
+
| 参数 | 说明 |
|
|
229
|
+
|------|------|
|
|
230
|
+
| `-runEv` | 启动 EV 录屏集成服务 |
|
|
231
|
+
| `-evSavePath` | EV 录屏保存视频和音频的目录路径,需与 EV 录屏软件中的“保存路径”设置一致 |
|
|
232
|
+
|
|
233
|
+
> 💡 **如何查看或修改 EV 录屏的保存路径?**
|
|
234
|
+
> 参考官方帮助文档:[EV录屏 - 如何查看/修改保存路径](https://www.ieway.cn/help/desc-evcapture-pc-2141.html)
|
|
235
|
+
|
|
236
|
+
### 示例
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
crabatool -runEv -evSavePath "C:\Users\用户名\Documents\EV录屏"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 快捷启动(推荐)
|
|
243
|
+
|
|
244
|
+
建议将启动命令保存为 **批处理文件(.bat)**,便于后续快速启动服务,无需重复输入命令。
|
|
245
|
+
|
|
246
|
+
**创建方法:**
|
|
247
|
+
1. 新建文本文件,输入上述命令
|
|
248
|
+
2. 将文件扩展名改为 `.bat`
|
|
249
|
+
3. 双击即可启动服务
|
|
250
|
+
|
|
251
|
+
## 详细操作流程
|
|
252
|
+
|
|
253
|
+
1. **启动集成服务**
|
|
254
|
+
执行启动命令(或双击已保存的 `.bat` 文件),服务开始监听 EV 录屏的保存目录。
|
|
255
|
+
|
|
256
|
+
2. **触发录制**
|
|
257
|
+
在教学录制页面中,点击 **“采集这一步的音/视频”** 图标。
|
|
258
|
+
|
|
259
|
+
3. **启动 EV 录屏**
|
|
260
|
+
系统将自动打开 EV 录屏工具,请手动点击 EV 录屏的 **“开始录制”** 按钮或使用预设的快捷键开始录制。
|
|
261
|
+
|
|
262
|
+
4. **自动上传与回填**
|
|
263
|
+
录制完成后,文件将自动上传至七牛云,上传成功后生成的音频/视频 URL 将自动填入当前教学步骤,图标变为红色,表示处理完成。
|
|
264
|
+
|
|
265
|
+
## 注意事项
|
|
266
|
+
|
|
267
|
+
- 请确保 EV 录屏的保存路径与 `-evSavePath` 参数填写路径**完全一致**
|
|
268
|
+
- 录制过程中请勿手动删除或移动正在写入的文件,否则可能导致上传失败
|
|
269
|
+
- 若录制完成后长时间未触发上传,请检查网络连接及七牛云配置是否正常
|
|
270
|
+
- 服务启动后请保持命令行窗口运行状态,关闭窗口将停止监听
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
## 使用 crabatool 与原生 EV 录屏的对比
|
|
274
|
+
|
|
275
|
+
| 对比项 | 原生 EV 录屏 | crabatool 集成方案 |
|
|
276
|
+
|--------|--------------|--------------------|
|
|
277
|
+
| **启动方式** | 手动打开 EV 录屏,点击录制 | 双击 `.bat` 文件启动服务,教学页面一键触发录制 |
|
|
278
|
+
| **录制触发** | 手动点击 EV 录屏界面按钮 | 在教学页面点击“采集音/视频”,工具自动唤起 EV 录屏并开始监听 |
|
|
279
|
+
| **文件处理** | 录制完成后,需手动找到文件、重命名、上传至云存储 | 工具自动检测录制结束,自动上传至七牛云 |
|
|
280
|
+
| **URL 回填** | 手动复制云存储链接,粘贴到教学步骤中 | 上传成功后 URL 自动回填,图标状态自动更新 |
|
|
281
|
+
| **多步骤支持** | 需手动记录每次录制的文件对应关系 | 自动关联当前步骤,无需人工核对 |
|
|
282
|
+
| **出错处理** | 依赖人工检查是否遗漏 | 工具实时监控,有错误日志可追溯 |
|
|
283
|
+
| **适用场景** | 适合临时、少量录制 | 适合批量、流程化的教学音视频采集 |
|
|
284
|
+
|
|
285
|
+
通过集成 `crabatool`,可将原本需要 5~8 步的手动操作简化为 **一键触发 → 自动完成**,大幅提升录制上传效率,避免人工失误。
|
|
286
|
+
|
|
287
|
+
## 常见问题
|
|
288
|
+
|
|
289
|
+
**Q:为什么服务启动后没有反应?**
|
|
290
|
+
A:请检查 EV 录屏保存路径是否正确,以及该目录是否存在。
|
|
291
|
+
|
|
292
|
+
**Q:录制完成后未自动上传?**
|
|
293
|
+
A:可检查网络连接,或查看命令行窗口是否有错误日志输出。
|
package/lib/utils.js
CHANGED
|
@@ -9,6 +9,7 @@ var compressing = require('compressing');
|
|
|
9
9
|
var axios = require('axios');
|
|
10
10
|
var os = require('os');
|
|
11
11
|
const { execSync } = require('child_process');
|
|
12
|
+
const { execFileSync } = require('child_process');
|
|
12
13
|
/*
|
|
13
14
|
const util = require('util');
|
|
14
15
|
const execPromise = util.promisify(execSync);
|
|
@@ -984,7 +985,9 @@ class Utils {
|
|
|
984
985
|
execSync('git add --all', { cwd: webPath }); // 暂存
|
|
985
986
|
|
|
986
987
|
console.log('git commit -m "' + msg + '"'); // 提交日志
|
|
987
|
-
execSync('git commit -m "' + msg + '"', { cwd: webPath }); // 提交日志
|
|
988
|
+
//execSync('git commit -m "' + msg + '"', { cwd: webPath }); // 提交日志
|
|
989
|
+
execFileSync('git', ['commit', '-m', msg]);
|
|
990
|
+
|
|
988
991
|
|
|
989
992
|
//console.log('git pull --rebase origin ' + branchName); // 拉取分支
|
|
990
993
|
//execSync('git pull --rebase origin ' + branchName, { cwd: webPath }); // 拉取分支
|
package/package.json
CHANGED
package/tool/checkjs.js
CHANGED
|
@@ -10,6 +10,7 @@ var gspx = require('./checkgspx.js');
|
|
|
10
10
|
var iconfont = require('./checkiconfont.js');
|
|
11
11
|
var eslint = require('eslint');
|
|
12
12
|
const upgrade = require('./upgrade.js');
|
|
13
|
+
const javaEnum = require('./javaEnum.js');
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
// js超过多少kb给与提示
|
|
@@ -46,6 +47,9 @@ module.exports.start = async function() {
|
|
|
46
47
|
|
|
47
48
|
iconfont.start(); // 检查收集各项目组iconfont使用情况
|
|
48
49
|
|
|
50
|
+
//javaEnum.start(); // 执行代码检测时,搜集当前webPath路径下面所有java枚举类(1. 普通枚举,2. 含@EnumDbMapping注解的枚举)
|
|
51
|
+
|
|
52
|
+
|
|
49
53
|
//utils.copyFile(jsonPath, path.join(process.cwd(), '.eslintrc.json'));
|
|
50
54
|
var jsFiles = utils.getFiles({ source: config.webPath, exts: '.js', ignores: config.ignoreCheck });
|
|
51
55
|
|
package/tool/javaEnum.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var utils = require('../lib/utils.js');
|
|
4
|
+
var config = require('../lib/config.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function processJavaFile(filePath, enumInfos) {
|
|
8
|
+
try {
|
|
9
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
10
|
+
|
|
11
|
+
const hasEnumDbMapping = content.includes('@EnumDbMapping');
|
|
12
|
+
const isEnum = content.includes('public enum');
|
|
13
|
+
|
|
14
|
+
if (!hasEnumDbMapping || !isEnum) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const packageMatch = content.match(/package\s+([\w\.]+);/);
|
|
19
|
+
const packageName = packageMatch ? packageMatch[1] : '';
|
|
20
|
+
|
|
21
|
+
const classNameMatch = content.match(/public\s+(?:enum|class)\s+(\w+)\s+(?:implements|extends)/);
|
|
22
|
+
let className = '';
|
|
23
|
+
if (!classNameMatch) {
|
|
24
|
+
const enumNameMatch = content.match(/public\s+enum\s+(\w+)/);
|
|
25
|
+
if (!enumNameMatch) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
className = enumNameMatch[1];
|
|
29
|
+
} else {
|
|
30
|
+
className = classNameMatch[1];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let dbMap = '';
|
|
34
|
+
if (hasEnumDbMapping) {
|
|
35
|
+
let annotationMatch = content.match(/@EnumDbMapping\s*\(\s*"([^"]+)"\s*\)/);
|
|
36
|
+
if (!annotationMatch) {
|
|
37
|
+
annotationMatch = content.match(/@EnumDbMapping\s*\(\s*value\s*=\s*"([^"]+)"\s*\)/);
|
|
38
|
+
}
|
|
39
|
+
if (!annotationMatch) {
|
|
40
|
+
annotationMatch = content.match(/@EnumDbMapping\s*\(\s*value\s*=\s*\{\s*"([^"]+)"/);
|
|
41
|
+
}
|
|
42
|
+
if (!annotationMatch) {
|
|
43
|
+
annotationMatch = content.match(/@EnumDbMapping\s*\(\s*\{\s*"([^"]+)"/);
|
|
44
|
+
}
|
|
45
|
+
if (annotationMatch) {
|
|
46
|
+
dbMap = annotationMatch[1];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const values = [];
|
|
51
|
+
|
|
52
|
+
// 提取枚举体内容(在enum声明和第一个private字段之间)
|
|
53
|
+
// 支持有implements和没有implements两种情况
|
|
54
|
+
let enumBodyMatch = content.match(/public\s+enum\s+\w+\s+implements[^{]*\{([\s\S]*?)\n\s+private/);
|
|
55
|
+
if (!enumBodyMatch) {
|
|
56
|
+
enumBodyMatch = content.match(/public\s+enum\s+\w+\s*\{([\s\S]*?)\n\s+private/);
|
|
57
|
+
}
|
|
58
|
+
if (enumBodyMatch) {
|
|
59
|
+
const enumBody = enumBodyMatch[1];
|
|
60
|
+
// 使用更宽松的正则匹配枚举值:枚举名(参数1, 参数2, ...)
|
|
61
|
+
const valuePattern = /([A-Za-z_]\w*)\(([^)]+)\)/g;
|
|
62
|
+
let match;
|
|
63
|
+
while ((match = valuePattern.exec(enumBody)) !== null) {
|
|
64
|
+
const valueStr = match[2];
|
|
65
|
+
// 分割参数
|
|
66
|
+
const parts = valueStr.split(',');
|
|
67
|
+
if (parts.length >= 2) {
|
|
68
|
+
let part1 = parts[0].trim();
|
|
69
|
+
let part2 = parts[1].trim();
|
|
70
|
+
// 去除引号
|
|
71
|
+
part1 = part1.replace(/^"|"$/g, '');
|
|
72
|
+
part2 = part2.replace(/^"|"$/g, '');
|
|
73
|
+
|
|
74
|
+
// 判断哪个是code,哪个是name
|
|
75
|
+
// 如果第一个是数字,第二个是中文 -> (数字, "中文名")
|
|
76
|
+
// 如果第一个是中文,第二个是数字 -> ("中文名", 数字)
|
|
77
|
+
let code, name;
|
|
78
|
+
if (/^\d+$/.test(part1)) {
|
|
79
|
+
code = part1;
|
|
80
|
+
name = part2;
|
|
81
|
+
} else if (/^\d+$/.test(part2)) {
|
|
82
|
+
code = part2;
|
|
83
|
+
name = part1;
|
|
84
|
+
} else {
|
|
85
|
+
// 无法判断,使用第一个作为name,第二个作为code
|
|
86
|
+
name = part1;
|
|
87
|
+
code = part2;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (code && name) {
|
|
91
|
+
values.push(code + '=' + name);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const valueStr = values.join(',');
|
|
98
|
+
|
|
99
|
+
const enumInfo = {
|
|
100
|
+
name: packageName + "." + className,
|
|
101
|
+
dbMap: dbMap,
|
|
102
|
+
value: valueStr
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
enumInfos.push(enumInfo);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error(`Error processing file ${filePath}:`, error.message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function generateEnumsJson(enumInfos) {
|
|
112
|
+
try {
|
|
113
|
+
var jsonContent = JSON.stringify(enumInfos, null, 2);
|
|
114
|
+
fs.writeFileSync(path.join(__dirname, '../enums.json'), jsonContent, 'utf8');
|
|
115
|
+
console.log('Successfully generated enums.json with ' + enumInfos.length + ' entries');
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error('Error generating enums.json:', error.message);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports.start = function() {
|
|
122
|
+
var enumInfos = [];
|
|
123
|
+
|
|
124
|
+
console.log('Scanning Java files...');
|
|
125
|
+
var webPath = config.webPath;
|
|
126
|
+
if (!webPath) {
|
|
127
|
+
console.error('config.webPath is not defined');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
var javaFiles = utils.getFiles({ source: webPath, exts: '.java', ignores: config.ignoreCheck });
|
|
132
|
+
console.log('Found ' + javaFiles.length + ' Java files');
|
|
133
|
+
|
|
134
|
+
console.log('Processing files...');
|
|
135
|
+
for (var i = 0; i < javaFiles.length; i++) {
|
|
136
|
+
processJavaFile(javaFiles[i], enumInfos);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log('Generating enums.json...');
|
|
140
|
+
generateEnumsJson(enumInfos);
|
|
141
|
+
};
|