crabatool 1.0.444 → 1.0.445

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/lib/server.js CHANGED
@@ -156,12 +156,6 @@ function createServer(app, options) {
156
156
  utils.log('文件监听功能已禁用');
157
157
  }
158
158
 
159
- // 统一拦截login.html
160
- if (config.modName && !config.localLogin) {
161
- app.use(utils.rewriteLoginHTML);
162
- }
163
-
164
-
165
159
  app.webPath = webPath; // handler.js里面动态获取当前app的网站路径(多个server实例的时候需要)
166
160
 
167
161
  app.use(express.static(webPath, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crabatool",
3
- "version": "1.0.444",
3
+ "version": "1.0.445",
4
4
  "description": "crabatool",
5
5
  "main": "index.js",
6
6
  "bin": {
package/res/client.js CHANGED
@@ -146,6 +146,11 @@
146
146
  existingOverlay.remove();
147
147
  }
148
148
 
149
+ // 兼容旧版本数据格式(单文件错误)
150
+ var allErrorFiles = errorData.allErrorFiles || [errorData];
151
+ var currentFile = errorData.currentFile || errorData;
152
+ var totalErrorFiles = errorData.totalErrorFiles || 1;
153
+
149
154
  // 创建错误覆盖层
150
155
  var overlay = document.createElement('div');
151
156
  overlay.id = 'syntax-error-overlay';
@@ -164,19 +169,56 @@
164
169
  var container = document.createElement('div');
165
170
  container.style.cssText = `
166
171
  background: #fff;
167
- margin: 50px auto;
168
- padding: 30px;
169
- max-width: 900px;
170
- max-height: 80vh;
171
- overflow-y: auto;
172
+ margin: 30px auto;
173
+ padding: 0;
174
+ max-width: 1000px;
175
+ max-height: 85vh;
172
176
  border-radius: 8px;
173
177
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
178
+ display: flex;
179
+ overflow: hidden;
174
180
  `;
175
181
 
176
- // 构建错误信息HTML
182
+ // 构建文件列表HTML(如果有多个文件)
183
+ var fileListHtml = '';
184
+ if (totalErrorFiles > 1) {
185
+ fileListHtml = `
186
+ <div style="width: 300px; background: #f8f9fa; border-right: 1px solid #dee2e6; overflow-y: auto;">
187
+ <div style="padding: 20px; border-bottom: 1px solid #dee2e6; background: #e9ecef;">
188
+ <h3 style="margin: 0; color: #495057; font-size: 16px;">错误文件列表 (${totalErrorFiles})</h3>
189
+ </div>
190
+ <div style="padding: 10px;">
191
+ ${allErrorFiles.map(function(file, index) {
192
+ var isActive = file.filePath === currentFile.filePath;
193
+ var fileId = 'error-file-' + index;
194
+ return `
195
+ <div id="${fileId}" onclick="switchErrorFile('${file.filePath}')"
196
+ class="${isActive ? 'active-file' : 'inactive-file'}"
197
+ data-filepath="${file.filePath}"
198
+ style="
199
+ padding: 12px;
200
+ margin-bottom: 8px;
201
+ border-radius: 4px;
202
+ cursor: pointer;
203
+ background: ${isActive ? '#007bff !important' : '#fff'};
204
+ color: ${isActive ? '#fff' : '#333'};
205
+ border: 1px solid ${isActive ? '#007bff' : '#dee2e6'};
206
+ transition: all 0.2s;
207
+ " onmouseover="handleFileHover(this, true)" onmouseout="handleFileHover(this, false)">
208
+ <div style="font-weight: bold; font-size: 12px; margin-bottom: 4px;">${file.filePath.split('/').pop()}</div>
209
+ <div style="font-size: 11px; opacity: 0.8; word-break: break-all;">${file.filePath}</div>
210
+ <div style="font-size: 11px; margin-top: 4px;">${file.errors.length} 个错误</div>
211
+ </div>
212
+ `;
213
+ }).join('')}
214
+ </div>
215
+ </div>
216
+ `;
217
+ }
218
+
219
+ // 构建当前文件错误信息HTML
177
220
  var errorsHtml = '';
178
- errorData.errors.forEach(function(error, index) {
179
- var errorClass = error.severity === 'error' ? 'error' : 'warning';
221
+ currentFile.errors.forEach(function(error, index) {
180
222
  errorsHtml += `
181
223
  <div style="margin-bottom: 15px; padding: 15px; background: ${error.severity === 'error' ? '#ffebee' : '#fff3e0'}; border-left: 4px solid ${error.severity === 'error' ? '#e74c3c' : '#ff9800'}; border-radius: 4px;">
182
224
  <div style="font-weight: bold; color: ${error.severity === 'error' ? '#e74c3c' : '#ff9800'}; margin-bottom: 8px;">
@@ -188,34 +230,81 @@
188
230
  `;
189
231
  });
190
232
 
191
- container.innerHTML = `
192
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; border-bottom: 2px solid #e74c3c; padding-bottom: 15px;">
193
- <h2 style="margin: 0; color: #e74c3c; font-size: 24px;">JavaScript 兼容性语法错误</h2>
194
- <!-- <button onclick="closeSyntaxErrorOverlay()" style="background: #e74c3c; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 14px;">关闭</button> -->
195
- </div>
196
- <div style="margin-bottom: 20px;">
197
- <div style="font-weight: bold; color: #333; margin-bottom: 8px;">文件路径:</div>
198
- <div style="background: #f8f9fa; padding: 10px; border-radius: 4px; font-family: monospace; color: #666; word-break: break-all;">${errorData.filePath}</div>
199
- </div>
200
- <div style="margin-bottom: 20px;">
201
- <div style="font-weight: bold; color: #333; margin-bottom: 12px;">错误详情:</div>
202
- ${errorsHtml}
203
- </div>
204
- <div style="text-align: center; color: #666; font-size: 12px;">
205
- 检测时间:${errorData.timestamp}
233
+ // 主内容区域
234
+ var mainContentHtml = `
235
+ <div style="flex: 1; display: flex; flex-direction: column;">
236
+ <div style="padding: 20px; border-bottom: 2px solid #e74c3c; background: #fff;">
237
+ <div style="display: flex; justify-content: space-between; align-items: center;">
238
+ <h2 style="margin: 0; color: #e74c3c; font-size: 20px;">JavaScript 兼容性语法错误</h2>
239
+ ${totalErrorFiles > 1 ? '<span style="background: #e74c3c; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;">' + totalErrorFiles + ' 个文件</span>' : ''}
240
+ </div>
241
+ </div>
242
+ <div style="flex: 1; overflow-y: auto; padding: 20px;">
243
+ <div style="margin-bottom: 20px;">
244
+ <div style="font-weight: bold; color: #333; margin-bottom: 8px;">当前文件:</div>
245
+ <div style="background: #f8f9fa; padding: 10px; border-radius: 4px; font-family: monospace; color: #666; word-break: break-all;">${currentFile.filePath}</div>
246
+ </div>
247
+ <div style="margin-bottom: 20px;">
248
+ <div style="font-weight: bold; color: #333; margin-bottom: 12px;">错误详情 (${currentFile.errors.length} 个):</div>
249
+ ${errorsHtml}
250
+ </div>
251
+ <div style="text-align: center; color: #666; font-size: 12px; border-top: 1px solid #dee2e6; padding-top: 15px;">
252
+ 检测时间:${currentFile.timestamp}
253
+ </div>
254
+ </div>
206
255
  </div>
207
256
  `;
208
257
 
258
+ container.innerHTML = fileListHtml + mainContentHtml;
209
259
  overlay.appendChild(container);
210
260
  document.body.appendChild(overlay);
261
+
262
+ // 存储当前错误数据供切换使用
263
+ window.currentErrorData = errorData;
211
264
  }
212
265
 
266
+ // 处理文件项的鼠标悬停效果
267
+ window.handleFileHover = function(element, isHover) {
268
+ // 如果是激活状态的文件,不改变样式
269
+ if (element.classList.contains('active-file')) {
270
+ return;
271
+ }
272
+
273
+ if (isHover) {
274
+ element.style.background = '#f8f9fa';
275
+ } else {
276
+ element.style.background = '#fff';
277
+ }
278
+ };
279
+
280
+ // 切换错误文件显示
281
+ window.switchErrorFile = function(filePath) {
282
+ if (!window.currentErrorData || !window.currentErrorData.allErrorFiles) {
283
+ return;
284
+ }
285
+
286
+ // 找到对应的文件数据
287
+ var targetFile = window.currentErrorData.allErrorFiles.find(function(file) {
288
+ return file.filePath === filePath;
289
+ });
290
+
291
+ if (targetFile) {
292
+ // 更新当前文件并重新显示
293
+ var newErrorData = Object.assign({}, window.currentErrorData, {
294
+ currentFile: targetFile
295
+ });
296
+ showSyntaxErrorOverlay(newErrorData);
297
+ }
298
+ };
299
+
213
300
  // 关闭语法错误覆盖层
214
301
  window.closeSyntaxErrorOverlay = function() {
215
302
  var overlay = document.getElementById('syntax-error-overlay');
216
303
  if (overlay) {
217
304
  overlay.remove();
218
305
  }
306
+ // 清理存储的错误数据
307
+ window.currentErrorData = null;
219
308
  };
220
309
 
221
310
  waitCraba();
@@ -46,7 +46,9 @@ class OpenFileWatcher {
46
46
  this.openFiles = new Set(); // 当前打开的文件
47
47
  this.changeQueue = new Map(); // 变化队列
48
48
  this.debounceTimers = new Map(); // 防抖定时器
49
-
49
+ // 错误文件缓存,存储所有有异常语法的文件信息
50
+ this.errorFilesCache = new Map();
51
+
50
52
  // 绑定方法
51
53
  this.handleFileChange = this.handleFileChange.bind(this);
52
54
  this.processFileChange = this.processFileChange.bind(this);
@@ -116,11 +118,14 @@ class OpenFileWatcher {
116
118
  this.isWatching = false;
117
119
  this.openFiles.clear();
118
120
  this.changeQueue.clear();
119
-
121
+
120
122
  // 清理所有防抖定时器
121
123
  this.debounceTimers.forEach(timer => clearTimeout(timer));
122
124
  this.debounceTimers.clear();
123
-
125
+
126
+ // 清空错误文件缓存
127
+ this.clearErrorFilesCache();
128
+
124
129
  utils.log('文件监听器已停止');
125
130
  }
126
131
  return this;
@@ -583,28 +588,42 @@ class OpenFileWatcher {
583
588
  });
584
589
  }
585
590
 
586
- // 如果有严重错误,发送到前端
591
+ // 处理错误文件缓存
587
592
  if (errors.length > 0) {
593
+ // 有错误:将文件信息添加到缓存中
588
594
  const errorData = {
589
- mode: 'syntaxError',
590
595
  filePath: relativePath,
591
596
  fullPath: path.resolve(this.watchPath, relativePath),
592
597
  errors: errors.slice(0, 5), // 最多显示5个错误
593
598
  timestamp: new Date().toLocaleString()
594
599
  };
595
600
 
596
- // console.log(chalk.blue(`发送${errors.length}个语法错误到前端: ${relativePath}`));
597
- this.emit('syntaxError', errorData);
598
- } else {
599
- // 没有严重错误时,发送清除错误覆盖层的消息
600
- const clearData = {
601
- mode: 'clearSyntaxError',
602
- filePath: relativePath,
603
- timestamp: new Date().toLocaleString()
604
- };
601
+ this.errorFilesCache.set(relativePath, errorData);
602
+ console.log(chalk.blue(`文件有${errors.length}个语法错误,已缓存: ${relativePath}`));
603
+
604
+ // 发送包含所有错误文件的信息到前端
605
+ this.sendAllErrorsToFrontend();
605
606
 
606
- console.log(chalk.green(`文件已修复,发送清除错误覆盖层消息: ${relativePath}`));
607
- this.emit('clearSyntaxError', clearData);
607
+ } else {
608
+ // 没有错误:从缓存中移除该文件
609
+ if (this.errorFilesCache.has(relativePath)) {
610
+ this.errorFilesCache.delete(relativePath);
611
+ console.log(chalk.green(`文件已修复,从错误缓存中移除: ${relativePath}`));
612
+
613
+ // 检查是否还有其他错误文件
614
+ if (this.errorFilesCache.size === 0) {
615
+ // 所有文件都修复了,发送清除错误覆盖层的消息
616
+ const clearData = {
617
+ mode: 'clearSyntaxError',
618
+ timestamp: new Date().toLocaleString()
619
+ };
620
+ console.log(chalk.green('所有错误文件都已修复,发送清除错误覆盖层消息'));
621
+ this.emit('clearSyntaxError', clearData);
622
+ } else {
623
+ // 还有其他错误文件,更新前端显示
624
+ this.sendAllErrorsToFrontend();
625
+ }
626
+ }
608
627
  }
609
628
  }
610
629
 
@@ -718,6 +737,40 @@ class OpenFileWatcher {
718
737
  return 'ES6+语法';
719
738
  }
720
739
 
740
+ /**
741
+ * 发送所有错误文件信息到前端
742
+ */
743
+ sendAllErrorsToFrontend() {
744
+ if (this.errorFilesCache.size === 0) {
745
+ return;
746
+ }
747
+
748
+ // 将Map转换为数组,按时间戳排序(最新的在前)
749
+ const allErrorFiles = Array.from(this.errorFilesCache.values()).sort((a, b) => {
750
+ return new Date(b.timestamp) - new Date(a.timestamp);
751
+ });
752
+
753
+ // 构造发送给前端的数据
754
+ const errorData = {
755
+ mode: 'syntaxError',
756
+ allErrorFiles: allErrorFiles,
757
+ totalErrorFiles: allErrorFiles.length,
758
+ currentFile: allErrorFiles[0], // 默认显示最新的错误文件
759
+ timestamp: new Date().toLocaleString()
760
+ };
761
+
762
+ console.log(chalk.blue(`发送${allErrorFiles.length}个错误文件信息到前端`));
763
+ this.emit('syntaxError', errorData);
764
+ }
765
+
766
+ /**
767
+ * 清空错误文件缓存
768
+ */
769
+ clearErrorFilesCache() {
770
+ this.errorFilesCache.clear();
771
+ console.log(chalk.yellow('已清空错误文件缓存'));
772
+ }
773
+
721
774
  /**
722
775
  * 获取指定行的内容
723
776
  * @param {string} content - 文件内容