maque 0.2.1__py3-none-any.whl

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.
Files changed (143) hide show
  1. maque/__init__.py +30 -0
  2. maque/__main__.py +926 -0
  3. maque/ai_platform/__init__.py +0 -0
  4. maque/ai_platform/crawl.py +45 -0
  5. maque/ai_platform/metrics.py +258 -0
  6. maque/ai_platform/nlp_preprocess.py +67 -0
  7. maque/ai_platform/webpage_screen_shot.py +195 -0
  8. maque/algorithms/__init__.py +78 -0
  9. maque/algorithms/bezier.py +15 -0
  10. maque/algorithms/bktree.py +117 -0
  11. maque/algorithms/core.py +104 -0
  12. maque/algorithms/hilbert.py +16 -0
  13. maque/algorithms/rate_function.py +92 -0
  14. maque/algorithms/transform.py +27 -0
  15. maque/algorithms/trie.py +272 -0
  16. maque/algorithms/utils.py +63 -0
  17. maque/algorithms/video.py +587 -0
  18. maque/api/__init__.py +1 -0
  19. maque/api/common.py +110 -0
  20. maque/api/fetch.py +26 -0
  21. maque/api/static/icon.png +0 -0
  22. maque/api/static/redoc.standalone.js +1782 -0
  23. maque/api/static/swagger-ui-bundle.js +3 -0
  24. maque/api/static/swagger-ui.css +3 -0
  25. maque/cli/__init__.py +1 -0
  26. maque/cli/clean_invisible_chars.py +324 -0
  27. maque/cli/core.py +34 -0
  28. maque/cli/groups/__init__.py +26 -0
  29. maque/cli/groups/config.py +205 -0
  30. maque/cli/groups/data.py +615 -0
  31. maque/cli/groups/doctor.py +259 -0
  32. maque/cli/groups/embedding.py +222 -0
  33. maque/cli/groups/git.py +29 -0
  34. maque/cli/groups/help.py +410 -0
  35. maque/cli/groups/llm.py +223 -0
  36. maque/cli/groups/mcp.py +241 -0
  37. maque/cli/groups/mllm.py +1795 -0
  38. maque/cli/groups/mllm_simple.py +60 -0
  39. maque/cli/groups/quant.py +210 -0
  40. maque/cli/groups/service.py +490 -0
  41. maque/cli/groups/system.py +570 -0
  42. maque/cli/mllm_run.py +1451 -0
  43. maque/cli/script.py +52 -0
  44. maque/cli/tree.py +49 -0
  45. maque/clustering/__init__.py +52 -0
  46. maque/clustering/analyzer.py +347 -0
  47. maque/clustering/clusterers.py +464 -0
  48. maque/clustering/sampler.py +134 -0
  49. maque/clustering/visualizer.py +205 -0
  50. maque/constant.py +13 -0
  51. maque/core.py +133 -0
  52. maque/cv/__init__.py +1 -0
  53. maque/cv/image.py +219 -0
  54. maque/cv/utils.py +68 -0
  55. maque/cv/video/__init__.py +3 -0
  56. maque/cv/video/keyframe_extractor.py +368 -0
  57. maque/embedding/__init__.py +43 -0
  58. maque/embedding/base.py +56 -0
  59. maque/embedding/multimodal.py +308 -0
  60. maque/embedding/server.py +523 -0
  61. maque/embedding/text.py +311 -0
  62. maque/git/__init__.py +24 -0
  63. maque/git/pure_git.py +912 -0
  64. maque/io/__init__.py +29 -0
  65. maque/io/core.py +38 -0
  66. maque/io/ops.py +194 -0
  67. maque/llm/__init__.py +111 -0
  68. maque/llm/backend.py +416 -0
  69. maque/llm/base.py +411 -0
  70. maque/llm/server.py +366 -0
  71. maque/mcp_server.py +1096 -0
  72. maque/mllm_data_processor_pipeline/__init__.py +17 -0
  73. maque/mllm_data_processor_pipeline/core.py +341 -0
  74. maque/mllm_data_processor_pipeline/example.py +291 -0
  75. maque/mllm_data_processor_pipeline/steps/__init__.py +56 -0
  76. maque/mllm_data_processor_pipeline/steps/data_alignment.py +267 -0
  77. maque/mllm_data_processor_pipeline/steps/data_loader.py +172 -0
  78. maque/mllm_data_processor_pipeline/steps/data_validation.py +304 -0
  79. maque/mllm_data_processor_pipeline/steps/format_conversion.py +411 -0
  80. maque/mllm_data_processor_pipeline/steps/mllm_annotation.py +331 -0
  81. maque/mllm_data_processor_pipeline/steps/mllm_refinement.py +446 -0
  82. maque/mllm_data_processor_pipeline/steps/result_validation.py +501 -0
  83. maque/mllm_data_processor_pipeline/web_app.py +317 -0
  84. maque/nlp/__init__.py +14 -0
  85. maque/nlp/ngram.py +9 -0
  86. maque/nlp/parser.py +63 -0
  87. maque/nlp/risk_matcher.py +543 -0
  88. maque/nlp/sentence_splitter.py +202 -0
  89. maque/nlp/simple_tradition_cvt.py +31 -0
  90. maque/performance/__init__.py +21 -0
  91. maque/performance/_measure_time.py +70 -0
  92. maque/performance/_profiler.py +367 -0
  93. maque/performance/_stat_memory.py +51 -0
  94. maque/pipelines/__init__.py +15 -0
  95. maque/pipelines/clustering.py +252 -0
  96. maque/quantization/__init__.py +42 -0
  97. maque/quantization/auto_round.py +120 -0
  98. maque/quantization/base.py +145 -0
  99. maque/quantization/bitsandbytes.py +127 -0
  100. maque/quantization/llm_compressor.py +102 -0
  101. maque/retriever/__init__.py +35 -0
  102. maque/retriever/chroma.py +654 -0
  103. maque/retriever/document.py +140 -0
  104. maque/retriever/milvus.py +1140 -0
  105. maque/table_ops/__init__.py +1 -0
  106. maque/table_ops/core.py +133 -0
  107. maque/table_viewer/__init__.py +4 -0
  108. maque/table_viewer/download_assets.py +57 -0
  109. maque/table_viewer/server.py +698 -0
  110. maque/table_viewer/static/element-plus-icons.js +5791 -0
  111. maque/table_viewer/static/element-plus.css +1 -0
  112. maque/table_viewer/static/element-plus.js +65236 -0
  113. maque/table_viewer/static/main.css +268 -0
  114. maque/table_viewer/static/main.js +669 -0
  115. maque/table_viewer/static/vue.global.js +18227 -0
  116. maque/table_viewer/templates/index.html +401 -0
  117. maque/utils/__init__.py +56 -0
  118. maque/utils/color.py +68 -0
  119. maque/utils/color_string.py +45 -0
  120. maque/utils/compress.py +66 -0
  121. maque/utils/constant.py +183 -0
  122. maque/utils/core.py +261 -0
  123. maque/utils/cursor.py +143 -0
  124. maque/utils/distance.py +58 -0
  125. maque/utils/docker.py +96 -0
  126. maque/utils/downloads.py +51 -0
  127. maque/utils/excel_helper.py +542 -0
  128. maque/utils/helper_metrics.py +121 -0
  129. maque/utils/helper_parser.py +168 -0
  130. maque/utils/net.py +64 -0
  131. maque/utils/nvidia_stat.py +140 -0
  132. maque/utils/ops.py +53 -0
  133. maque/utils/packages.py +31 -0
  134. maque/utils/path.py +57 -0
  135. maque/utils/tar.py +260 -0
  136. maque/utils/untar.py +129 -0
  137. maque/web/__init__.py +0 -0
  138. maque/web/image_downloader.py +1410 -0
  139. maque-0.2.1.dist-info/METADATA +450 -0
  140. maque-0.2.1.dist-info/RECORD +143 -0
  141. maque-0.2.1.dist-info/WHEEL +4 -0
  142. maque-0.2.1.dist-info/entry_points.txt +3 -0
  143. maque-0.2.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,669 @@
1
+ const { createApp } = Vue;
2
+ const { ElMessage, ElMessageBox } = ElementPlus;
3
+
4
+ createApp({
5
+ data() {
6
+ return {
7
+ loading: false,
8
+ tableInfo: null,
9
+ tableData: {
10
+ data: [],
11
+ total: 0,
12
+ page: 1,
13
+ page_size: 100,
14
+ total_pages: 0
15
+ },
16
+ pagination: {
17
+ currentPage: 1,
18
+ pageSize: 100
19
+ },
20
+ sortConfig: {
21
+ prop: null,
22
+ order: null
23
+ },
24
+ activeFilters: [],
25
+ showFilterDialog: false,
26
+ filterConfigs: [],
27
+
28
+ // 列显示控制
29
+ showColumnDialog: false,
30
+ visibleColumns: [],
31
+ allColumns: [],
32
+
33
+ // 编辑相关
34
+ editingCell: null,
35
+ editingValue: '',
36
+
37
+ // 图片预览
38
+ showImagePreview: false,
39
+ currentImageUrl: '',
40
+ currentImageList: [], // 当前行的所有图片列表
41
+ currentImageIndex: 0, // 当前显示的图片索引
42
+
43
+ // 文件上传
44
+ showUploadDialog: false,
45
+ isDragOver: false,
46
+
47
+ // 图像尺寸设置
48
+ imageSize: 'medium', // small, medium, large, xlarge
49
+
50
+ // 图像分隔符设置
51
+ imageSeparator: 'auto', // auto, comma, semicolon, newline, custom
52
+ customSeparator: '', // 自定义分隔符
53
+
54
+ // 图像加载状态管理
55
+ loadedImages: new Set() // 存储已成功加载的图像URL
56
+ };
57
+ },
58
+
59
+ computed: {
60
+ tableColumns() {
61
+ // 如果有列筛选,使用筛选后的列,否则使用全部列
62
+ if (this.visibleColumns.length > 0) {
63
+ return this.visibleColumns;
64
+ }
65
+ return this.tableInfo ? this.tableInfo.columns : [];
66
+ },
67
+
68
+ // 计算当前图像尺寸
69
+ currentImageSizes() {
70
+ const sizeMap = {
71
+ 'small': { width: 80, height: 60 },
72
+ 'medium': { width: 120, height: 90 },
73
+ 'large': { width: 160, height: 120 },
74
+ 'xlarge': { width: 200, height: 150 },
75
+ 'xxlarge': { width: 400, height: 300 }
76
+ };
77
+ return sizeMap[this.imageSize] || sizeMap.medium;
78
+ }
79
+ },
80
+
81
+ async mounted() {
82
+ // 加载保存的设置
83
+ this.loadImageSizeFromStorage();
84
+ this.loadSeparatorFromStorage();
85
+
86
+ // 初始化CSS变量
87
+ this.updateImageSizeCss();
88
+
89
+ await this.loadTableInfo();
90
+ await this.loadTableData();
91
+ },
92
+
93
+ methods: {
94
+ // 加载表格信息
95
+ async loadTableInfo() {
96
+ try {
97
+ const response = await fetch('/api/table/info');
98
+ this.tableInfo = await response.json();
99
+ // 初始化列数据
100
+ if (this.tableInfo && this.tableInfo.columns) {
101
+ this.allColumns = [...this.tableInfo.columns];
102
+ if (this.visibleColumns.length === 0) {
103
+ this.visibleColumns = [...this.tableInfo.columns];
104
+ }
105
+ }
106
+ } catch (error) {
107
+ ElMessage.error('加载表格信息失败: ' + error.message);
108
+ }
109
+ },
110
+
111
+ // 加载表格数据
112
+ async loadTableData() {
113
+ this.loading = true;
114
+ try {
115
+ const params = new URLSearchParams({
116
+ page: this.pagination.currentPage,
117
+ page_size: this.pagination.pageSize
118
+ });
119
+
120
+ if (this.sortConfig.prop) {
121
+ params.append('sort_by', this.sortConfig.prop);
122
+ params.append('sort_order', this.sortConfig.order === 'ascending' ? 'asc' : 'desc');
123
+ }
124
+
125
+ if (this.activeFilters.length > 0) {
126
+ params.append('filters', JSON.stringify(this.activeFilters));
127
+ }
128
+
129
+ // 添加列筛选参数
130
+ if (this.visibleColumns.length > 0 && this.visibleColumns.length < this.allColumns.length) {
131
+ params.append('visible_columns', JSON.stringify(this.visibleColumns));
132
+ }
133
+
134
+ // 添加分隔符参数
135
+ if (this.imageSeparator !== 'auto') {
136
+ let separator = '';
137
+ switch (this.imageSeparator) {
138
+ case 'semicolon':
139
+ separator = ';';
140
+ break;
141
+ case 'newline':
142
+ separator = '\\n'; // 使用字符串形式
143
+ break;
144
+ case 'custom':
145
+ separator = this.customSeparator;
146
+ break;
147
+ }
148
+ if (separator) {
149
+ params.append('separator', separator);
150
+ }
151
+ }
152
+
153
+ const response = await fetch(`/api/table/data?${params}`);
154
+ this.tableData = await response.json();
155
+
156
+ // 更新可见列(如果后端返回了)
157
+ if (this.tableData.visible_columns) {
158
+ this.visibleColumns = this.tableData.visible_columns;
159
+ }
160
+ } catch (error) {
161
+ ElMessage.error('加载数据失败: ' + error.message);
162
+ } finally {
163
+ this.loading = false;
164
+ }
165
+ },
166
+
167
+ // 刷新数据
168
+ async refreshData() {
169
+ await this.loadTableInfo();
170
+ await this.loadTableData();
171
+ ElMessage.success('数据已刷新');
172
+ },
173
+
174
+ // 排序处理
175
+ handleSort(column, direction) {
176
+ if (this.sortConfig.prop === column &&
177
+ this.sortConfig.order === (direction === 'asc' ? 'ascending' : 'descending')) {
178
+ // 如果点击的是当前排序列和方向,则清除排序
179
+ this.sortConfig = { prop: null, order: null };
180
+ } else {
181
+ // 设置新的排序
182
+ this.sortConfig = {
183
+ prop: column,
184
+ order: direction === 'asc' ? 'ascending' : 'descending'
185
+ };
186
+ }
187
+ this.pagination.currentPage = 1;
188
+ this.loadTableData();
189
+ },
190
+
191
+ // 分页处理
192
+ handleSizeChange(size) {
193
+ this.pagination.pageSize = size;
194
+ this.pagination.currentPage = 1;
195
+ this.loadTableData();
196
+ },
197
+
198
+ handleCurrentChange(page) {
199
+ this.pagination.currentPage = page;
200
+ this.loadTableData();
201
+ },
202
+
203
+ // 判断是否为图片列
204
+ isImageColumn(column) {
205
+ return this.tableInfo && this.tableInfo.image_columns.includes(column);
206
+ },
207
+
208
+ // 获取列宽度
209
+ getColumnWidth(column) {
210
+ if (this.isImageColumn(column)) {
211
+ // 根据图像尺寸动态调整列宽,预留3张图片的空间 + 边距
212
+ const imageWidth = this.currentImageSizes.width;
213
+ return Math.max(imageWidth * 3 + 40, 250); // 最小250px
214
+ }
215
+ return null;
216
+ },
217
+
218
+
219
+ // 检查图像是否已加载
220
+ isImageLoaded(imageUrl) {
221
+ return this.loadedImages.has(imageUrl);
222
+ },
223
+
224
+ // 图像加载成功处理
225
+ onImageLoadSuccess(imageUrl) {
226
+ this.loadedImages.add(imageUrl);
227
+ this.$forceUpdate(); // 强制更新视图
228
+ },
229
+
230
+ // 图像加载失败处理
231
+ onImageLoadError(imageUrl) {
232
+ this.loadedImages.delete(imageUrl);
233
+ },
234
+
235
+ // 筛选相关
236
+ addFilter() {
237
+ this.filterConfigs.push({
238
+ column: '',
239
+ operator: 'contains',
240
+ value: ''
241
+ });
242
+ },
243
+
244
+ removeFilter(index) {
245
+ this.filterConfigs.splice(index, 1);
246
+ },
247
+
248
+ addColumnFilter(column) {
249
+ this.filterConfigs.push({
250
+ column: column,
251
+ operator: 'contains',
252
+ value: ''
253
+ });
254
+ this.showFilterDialog = true;
255
+ },
256
+
257
+ applyFilters() {
258
+ this.activeFilters = this.filterConfigs.filter(f => f.column && f.value);
259
+ this.pagination.currentPage = 1;
260
+ this.showFilterDialog = false;
261
+ this.loadTableData();
262
+ },
263
+
264
+ clearFilters() {
265
+ this.activeFilters = [];
266
+ this.filterConfigs = [];
267
+ this.pagination.currentPage = 1;
268
+ this.loadTableData();
269
+ },
270
+
271
+ // 列管理相关
272
+ applyColumnFilter() {
273
+ this.pagination.currentPage = 1;
274
+ this.showColumnDialog = false;
275
+ this.loadTableData();
276
+ },
277
+
278
+ resetColumns() {
279
+ this.visibleColumns = [...this.allColumns];
280
+ this.applyColumnFilter();
281
+ },
282
+
283
+ selectAllColumns() {
284
+ this.visibleColumns = [...this.allColumns];
285
+ },
286
+
287
+ selectNoColumns() {
288
+ this.visibleColumns = [];
289
+ },
290
+
291
+ toggleColumn(column) {
292
+ const index = this.visibleColumns.indexOf(column);
293
+ if (index > -1) {
294
+ this.visibleColumns.splice(index, 1);
295
+ } else {
296
+ this.visibleColumns.push(column);
297
+ }
298
+ },
299
+
300
+ // 编辑相关
301
+ startEdit(row, column, value) {
302
+ if (this.isImageColumn(column)) return;
303
+
304
+ this.editingCell = { row, column };
305
+ this.editingValue = value || '';
306
+
307
+ this.$nextTick(() => {
308
+ const input = this.$refs.cellInput;
309
+ if (input && input[0]) {
310
+ input[0].focus();
311
+ }
312
+ });
313
+ },
314
+
315
+ async saveCell(rowIndex, column) {
316
+ try {
317
+ const response = await fetch(`/api/table/cell/${rowIndex}/${column}`, {
318
+ method: 'PUT',
319
+ headers: {
320
+ 'Content-Type': 'application/json'
321
+ },
322
+ body: JSON.stringify({ value: this.editingValue })
323
+ });
324
+
325
+ let result;
326
+ try {
327
+ result = await response.json();
328
+ } catch (jsonError) {
329
+ ElMessage.error('更新失败: 服务器返回了无效的响应');
330
+ return;
331
+ }
332
+
333
+ // 检查HTTP状态码
334
+ if (!response.ok) {
335
+ const errorMsg = result?.detail || result?.message || `HTTP ${response.status}`;
336
+ ElMessage.error('更新失败: ' + errorMsg);
337
+ return;
338
+ }
339
+
340
+ if (result && result.success) {
341
+ await this.loadTableData();
342
+ ElMessage.success('更新成功');
343
+ } else {
344
+ const errorMsg = result?.message || '操作失败';
345
+ ElMessage.error('更新失败: ' + errorMsg);
346
+ }
347
+ } catch (error) {
348
+ console.error('Save cell error:', error);
349
+ let errorMsg = '网络错误';
350
+ if (error instanceof Error) {
351
+ errorMsg = error.message;
352
+ } else if (typeof error === 'string') {
353
+ errorMsg = error;
354
+ } else if (error && error.message) {
355
+ errorMsg = error.message;
356
+ } else if (error && typeof error === 'object') {
357
+ errorMsg = JSON.stringify(error);
358
+ }
359
+ ElMessage.error('更新失败: ' + errorMsg);
360
+ } finally {
361
+ this.editingCell = null;
362
+ this.editingValue = '';
363
+ }
364
+ },
365
+
366
+ cancelEdit() {
367
+ this.editingCell = null;
368
+ this.editingValue = '';
369
+ },
370
+
371
+ // 图片相关
372
+ showImageDialog(imageUrl, allImagesData, clickedIndex) {
373
+ // 如果提供了完整的图片数据和索引,设置图片列表
374
+ if (allImagesData !== undefined && clickedIndex !== undefined) {
375
+ // allImagesData 现在是后端已处理好的 paths 数组
376
+ if (Array.isArray(allImagesData)) {
377
+ this.currentImageList = allImagesData;
378
+ } else {
379
+ // 兼容旧版本:如果传入的是字符串,使用简单切分逻辑
380
+ var paths = allImagesData.split(/[,;]+/);
381
+ var imagePaths = [];
382
+ for (var i = 0; i < paths.length; i++) {
383
+ var path = paths[i].trim();
384
+ if (path) imagePaths.push(path);
385
+ }
386
+ this.currentImageList = imagePaths;
387
+ }
388
+ this.currentImageIndex = clickedIndex;
389
+ } else {
390
+ // 兼容单图片模式
391
+ this.currentImageList = [imageUrl];
392
+ this.currentImageIndex = 0;
393
+ }
394
+
395
+ this.currentImageUrl = imageUrl;
396
+ this.showImagePreview = true;
397
+ },
398
+
399
+ // 显示上一张图片
400
+ showPreviousImage: function() {
401
+ if (this.currentImageIndex > 0) {
402
+ this.currentImageIndex--;
403
+ this.currentImageUrl = this.currentImageList[this.currentImageIndex];
404
+ }
405
+ },
406
+
407
+ // 显示下一张图片
408
+ showNextImage: function() {
409
+ if (this.currentImageIndex < this.currentImageList.length - 1) {
410
+ this.currentImageIndex++;
411
+ this.currentImageUrl = this.currentImageList[this.currentImageIndex];
412
+ }
413
+ },
414
+
415
+ handleImageError(event) {
416
+ event.target.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE1MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2Y1ZjVmNSIvPjx0ZXh0IHg9IjEwMCIgeT0iNzUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuWbvueJh+WKoOi9veWksei0pTwvdGV4dD48L3N2Zz4=';
417
+ },
418
+
419
+ // 表格操作
420
+ async saveTable() {
421
+ try {
422
+ const response = await fetch('/api/table/save', { method: 'POST' });
423
+ let result;
424
+ try {
425
+ result = await response.json();
426
+ } catch (jsonError) {
427
+ ElMessage.error('保存失败: 服务器返回了无效的响应');
428
+ return;
429
+ }
430
+
431
+ if (!response.ok) {
432
+ const errorMsg = result?.detail || result?.message || `HTTP ${response.status}`;
433
+ ElMessage.error('保存失败: ' + errorMsg);
434
+ return;
435
+ }
436
+
437
+ if (result && result.success) {
438
+ ElMessage.success('保存成功');
439
+ } else {
440
+ const errorMsg = result?.message || '操作失败';
441
+ ElMessage.error('保存失败: ' + errorMsg);
442
+ }
443
+ } catch (error) {
444
+ console.error('Save table error:', error);
445
+ let errorMsg = '网络错误';
446
+ if (error instanceof Error) {
447
+ errorMsg = error.message;
448
+ } else if (typeof error === 'string') {
449
+ errorMsg = error;
450
+ } else if (error && error.message) {
451
+ errorMsg = error.message;
452
+ } else if (error && typeof error === 'object') {
453
+ errorMsg = JSON.stringify(error);
454
+ }
455
+ ElMessage.error('保存失败: ' + errorMsg);
456
+ }
457
+ },
458
+
459
+ async resetTable() {
460
+ try {
461
+ await ElMessageBox.confirm('确定要重置表格到原始状态吗?这将丢失所有未保存的修改。', '确认重置', {
462
+ type: 'warning'
463
+ });
464
+
465
+ const response = await fetch('/api/table/reset', { method: 'POST' });
466
+ let result;
467
+ try {
468
+ result = await response.json();
469
+ } catch (jsonError) {
470
+ ElMessage.error('重置失败: 服务器返回了无效的响应');
471
+ return;
472
+ }
473
+
474
+ if (!response.ok) {
475
+ const errorMsg = result?.detail || result?.message || `HTTP ${response.status}`;
476
+ ElMessage.error('重置失败: ' + errorMsg);
477
+ return;
478
+ }
479
+
480
+ if (result && result.success) {
481
+ await this.loadTableData();
482
+ ElMessage.success('重置成功');
483
+ } else {
484
+ const errorMsg = result?.message || '操作失败';
485
+ ElMessage.error('重置失败: ' + errorMsg);
486
+ }
487
+ } catch (error) {
488
+ if (error !== 'cancel') {
489
+ console.error('Reset table error:', error);
490
+ let errorMsg = '网络错误';
491
+ if (error instanceof Error) {
492
+ errorMsg = error.message;
493
+ } else if (typeof error === 'string') {
494
+ errorMsg = error;
495
+ } else if (error && error.message) {
496
+ errorMsg = error.message;
497
+ } else if (error && typeof error === 'object') {
498
+ errorMsg = JSON.stringify(error);
499
+ }
500
+ ElMessage.error('重置失败: ' + errorMsg);
501
+ }
502
+ }
503
+ },
504
+
505
+ // 图像尺寸相关
506
+ onImageSizeChange() {
507
+ // 保存到本地存储
508
+ try {
509
+ localStorage.setItem('maque_table_viewer_image_size', this.imageSize);
510
+ } catch (e) {
511
+ // 忽略localStorage错误
512
+ }
513
+
514
+ // 更新CSS变量
515
+ this.updateImageSizeCss();
516
+
517
+ // 强制表格重新计算列宽
518
+ this.$nextTick(() => {
519
+ // 通过改变一个响应式属性触发表格重新渲染
520
+ const temp = this.tableData.data;
521
+ this.tableData.data = [];
522
+ this.$nextTick(() => {
523
+ this.tableData.data = temp;
524
+ });
525
+ });
526
+ },
527
+
528
+ updateImageSizeCss() {
529
+ const sizes = this.currentImageSizes;
530
+ const root = document.documentElement;
531
+ root.style.setProperty('--image-width', sizes.width + 'px');
532
+ root.style.setProperty('--image-height', sizes.height + 'px');
533
+ },
534
+
535
+ loadImageSizeFromStorage() {
536
+ try {
537
+ const saved = localStorage.getItem('maque_table_viewer_image_size');
538
+ if (saved && ['small', 'medium', 'large', 'xlarge', 'xxlarge'].includes(saved)) {
539
+ this.imageSize = saved;
540
+ }
541
+ } catch (e) {
542
+ // 忽略localStorage错误
543
+ }
544
+ },
545
+
546
+ // 分隔符相关方法
547
+ async onSeparatorChange() {
548
+ console.log('分隔符改变:', this.imageSeparator);
549
+
550
+ // 保存到本地存储
551
+ this.saveSeparatorToStorage();
552
+
553
+ // 清空图像加载状态
554
+ this.loadedImages.clear();
555
+
556
+ // 重新加载数据,使用新的分隔符设置
557
+ console.log('开始重新加载数据...');
558
+ try {
559
+ await this.loadTableData();
560
+ console.log('数据重新加载完成');
561
+ } catch (error) {
562
+ console.error('数据重新加载失败:', error);
563
+ ElMessage.error('重新加载数据失败: ' + error.message);
564
+ // 不要清空现有数据,保持用户能看到之前的内容
565
+ }
566
+ },
567
+
568
+ saveSeparatorToStorage() {
569
+ try {
570
+ localStorage.setItem('maque_table_viewer_separator', this.imageSeparator);
571
+ if (this.customSeparator) {
572
+ localStorage.setItem('maque_table_viewer_custom_separator', this.customSeparator);
573
+ }
574
+ } catch (e) {
575
+ // 忽略localStorage错误
576
+ }
577
+ },
578
+
579
+ loadSeparatorFromStorage() {
580
+ try {
581
+ const savedSeparator = localStorage.getItem('maque_table_viewer_separator');
582
+ if (savedSeparator && ['auto', 'semicolon', 'newline', 'custom'].includes(savedSeparator)) {
583
+ this.imageSeparator = savedSeparator;
584
+ }
585
+
586
+ const savedCustom = localStorage.getItem('maque_table_viewer_custom_separator');
587
+ if (savedCustom) {
588
+ this.customSeparator = savedCustom;
589
+ }
590
+ } catch (e) {
591
+ // 忽略localStorage错误
592
+ }
593
+ },
594
+
595
+ // 文件上传相关方法
596
+ triggerFileInput() {
597
+ this.$refs.fileInput.click();
598
+ },
599
+
600
+ handleDragOver(event) {
601
+ event.preventDefault();
602
+ this.isDragOver = true;
603
+ },
604
+
605
+ handleDragLeave(event) {
606
+ event.preventDefault();
607
+ this.isDragOver = false;
608
+ },
609
+
610
+ async handleFileDrop(event) {
611
+ event.preventDefault();
612
+ this.isDragOver = false;
613
+
614
+ const files = event.dataTransfer.files;
615
+ if (files.length > 0) {
616
+ await this.uploadFile(files[0]);
617
+ }
618
+ },
619
+
620
+ async handleFileSelect(event) {
621
+ const files = event.target.files;
622
+ if (files.length > 0) {
623
+ await this.uploadFile(files[0]);
624
+ }
625
+ },
626
+
627
+ async uploadFile(file) {
628
+ // 检查文件类型
629
+ const allowedTypes = ['.xlsx', '.xls', '.csv'];
630
+ const fileExtension = '.' + file.name.split('.').pop().toLowerCase();
631
+
632
+ if (!allowedTypes.includes(fileExtension)) {
633
+ ElMessage.error('不支持的文件格式,请选择 .xlsx, .xls 或 .csv 文件');
634
+ return;
635
+ }
636
+
637
+ this.loading = true;
638
+
639
+ try {
640
+ const formData = new FormData();
641
+ formData.append('file', file);
642
+
643
+ const response = await fetch('/api/table/upload', {
644
+ method: 'POST',
645
+ body: formData
646
+ });
647
+
648
+ const result = await response.json();
649
+
650
+ if (result.success) {
651
+ ElMessage.success('文件上传成功,正在加载数据...');
652
+ this.showUploadDialog = false;
653
+
654
+ // 重新加载表格信息和数据
655
+ await this.loadTableInfo();
656
+ await this.loadTableData();
657
+ } else {
658
+ ElMessage.error('上传失败: ' + result.message);
659
+ }
660
+ } catch (error) {
661
+ ElMessage.error('上传失败: ' + error.message);
662
+ } finally {
663
+ this.loading = false;
664
+ // 清空文件输入
665
+ this.$refs.fileInput.value = '';
666
+ }
667
+ }
668
+ }
669
+ }).use(ElementPlus).mount('#app');