@skyfox2000/webui 1.5.3 → 1.5.7

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 (65) hide show
  1. package/lib/assets/modules/{baseLayout-LU1ysAJM.js → baseLayout-DfTxHOFc.js} +7 -7
  2. package/lib/assets/modules/file-upload-DTOdV5vM.js +211 -0
  3. package/lib/assets/modules/index-BDoBUrYA.js +114 -0
  4. package/lib/assets/modules/{index-C6RrxZBR.js → index-BwMaOrJT.js} +1 -1
  5. package/lib/assets/modules/{index-CHG5bbZG.js → index-M1qERbea.js} +99 -99
  6. package/lib/assets/modules/{menuTabs-Bk8A-zzL.js → menuTabs-DWaBSRNr.js} +42 -42
  7. package/lib/assets/modules/{toolIcon-ADz-Bt4_.js → toolIcon-BYnHhAy-.js} +1 -1
  8. package/lib/assets/modules/upload-template-BKm9mFq8.js +6764 -0
  9. package/lib/assets/modules/uploadList-CHvr6Hp1.js +472 -0
  10. package/lib/es/AceEditor/index.js +3 -3
  11. package/lib/es/BasicLayout/index.js +2 -2
  12. package/lib/es/Error403/index.js +14 -15
  13. package/lib/es/Error404/index.js +16 -17
  14. package/lib/es/ExcelForm/index.js +244 -244
  15. package/lib/es/MenuLayout/index.js +5 -5
  16. package/lib/es/TemplateFile/index.js +53 -54
  17. package/lib/es/UploadForm/index.js +61 -63
  18. package/lib/locales/default.d.ts +287 -103
  19. package/lib/webui.css +1 -1
  20. package/lib/webui.es.js +1440 -1586
  21. package/package.json +1 -1
  22. package/src/components/common/icon/fullscreen.vue +1 -1
  23. package/src/components/content/dialog/excelForm.vue +32 -28
  24. package/src/components/content/dialog/index.vue +3 -3
  25. package/src/components/content/dialog/templateFile.vue +3 -2
  26. package/src/components/content/dialog/uploadForm.vue +5 -4
  27. package/src/components/content/drawer/index.vue +5 -3
  28. package/src/components/content/list/index.vue +2 -1
  29. package/src/components/content/list/listOperate.vue +6 -7
  30. package/src/components/content/search/index.vue +2 -2
  31. package/src/components/content/table/index.vue +2 -1
  32. package/src/components/content/table/tableOperate.vue +8 -9
  33. package/src/components/content/toolbar/icontool.vue +1 -5
  34. package/src/components/content/toolbar/index.vue +4 -5
  35. package/src/components/content/toolpanel/index.vue +20 -20
  36. package/src/components/error/error403.vue +2 -2
  37. package/src/components/error/error404.vue +2 -2
  38. package/src/components/form/input/index.vue +3 -1
  39. package/src/components/form/select/index.vue +3 -2
  40. package/src/components/form/textarea/index.vue +3 -1
  41. package/src/components/form/transfer/index.vue +2 -1
  42. package/src/components/form/upload/uploadList.vue +23 -19
  43. package/src/components/layout/header/headerExits.vue +5 -5
  44. package/src/components/layout/menu/menuTabs.vue +1 -1
  45. package/src/const/options.ts +17 -16
  46. package/src/locales/default.ts +297 -176
  47. package/src/locales/index.ts +12 -4
  48. package/src/stores/appInfo.ts +2 -1
  49. package/src/stores/userInfo.ts +6 -5
  50. package/src/utils/data.ts +9 -8
  51. package/src/utils/download.ts +5 -4
  52. package/src/utils/excel-preview.ts +4 -3
  53. package/src/utils/export-table.ts +7 -6
  54. package/src/utils/file-upload.ts +15 -14
  55. package/src/utils/form-csv.ts +4 -3
  56. package/src/utils/form-excel.ts +14 -13
  57. package/src/utils/form-validate.ts +18 -17
  58. package/src/utils/form.ts +6 -5
  59. package/src/utils/icon-loader.ts +3 -2
  60. package/src/utils/options.ts +2 -1
  61. package/src/utils/tools.ts +18 -17
  62. package/lib/assets/modules/file-upload-BvIYPDBD.js +0 -211
  63. package/lib/assets/modules/index-Bi3hR8Gf.js +0 -114
  64. package/lib/assets/modules/upload-template-mzLL4UUU.js +0 -6462
  65. package/lib/assets/modules/uploadList-DRGJEXDH.js +0 -466
package/src/utils/data.ts CHANGED
@@ -4,6 +4,7 @@ import message from 'vue-m-message';
4
4
  import { isEmpty } from './isEmpty';
5
5
  import { combineParams } from '@skyfox2000/microbase';
6
6
  import { LoginExpiredError, useUserInfo } from '@/stores/userInfo';
7
+ import { $t } from '@/locales/index';
7
8
 
8
9
  /**
9
10
  * 合并URL信息
@@ -114,12 +115,12 @@ export const doExecute = <T>(control: AnyControl, options: ExecuteOptions<T>): P
114
115
  if (!options.params) options.params = {};
115
116
  if (!options.params!.Query) options.params!.Query = {};
116
117
 
117
- options.loadingText = options.loadingText === false ? false : options.loadingText || '开始执行...';
118
+ options.loadingText = options.loadingText === false ? false : options.loadingText || $t('webui.utils.data.startExecute');
118
119
  options.url = combineUrl(control, options);
119
120
 
120
121
  return doPost<T>(control, options).then((result) => {
121
122
  if (result?.status === ResStatus.SUCCESS) {
122
- if (!options.hideErrorToast) message.success('执行成功!');
123
+ if (!options.hideErrorToast) message.success($t('webui.utils.data.executeSuccess'));
123
124
  }
124
125
  return result as ApiResponse<T> | null;
125
126
  });
@@ -139,14 +140,14 @@ export const doSave = <T>(
139
140
  if (!options.params) options.params = {};
140
141
  if (!options.params!.Query) options.params!.Query = {};
141
142
  if (!options.params!.Data) {
142
- message.error('错误!无保存数据!');
143
+ message.error($t('webui.utils.data.noSaveData'));
143
144
  return Promise.resolve(null);
144
145
  }
145
146
 
146
147
  const execOptions: ExecuteOptions<T> = {
147
148
  ...(options as ExecuteOptions<T>),
148
149
  urlKey: options.urlKey || 'save',
149
- loadingText: options.loadingText === false ? false : options.loadingText || '数据保存中...',
150
+ loadingText: options.loadingText === false ? false : options.loadingText || $t('webui.utils.data.savingData'),
150
151
  };
151
152
 
152
153
  // 如果有主键,添加到查询条件中
@@ -157,7 +158,7 @@ export const doSave = <T>(
157
158
 
158
159
  return doPost(control, execOptions).then((result) => {
159
160
  if (result?.status === ResStatus.SUCCESS) {
160
- if (!options.hideErrorToast) message.success('保存成功!');
161
+ if (!options.hideErrorToast) message.success($t('webui.utils.data.saveSuccess'));
161
162
  }
162
163
  return result as ApiResponse<T> | null;
163
164
  });
@@ -182,7 +183,7 @@ export const doDelete = <T>(
182
183
  const execOptions: ExecuteOptions<T> = {
183
184
  ...(options as ExecuteOptions<T>),
184
185
  urlKey: 'delete',
185
- loadingText: options.loadingText === false ? false : options.loadingText || '数据删除中...',
186
+ loadingText: options.loadingText === false ? false : options.loadingText || $t('webui.utils.data.deletingData'),
186
187
  };
187
188
 
188
189
  // 处理记录
@@ -193,7 +194,7 @@ export const doDelete = <T>(
193
194
  }
194
195
 
195
196
  if (isEmpty(execOptions.params!.Query) || isEmpty(execOptions.params!.Query![primaryKey])) {
196
- message.error('错误!禁止无条件删除数据!');
197
+ message.error($t('webui.utils.data.forbidDeleteWithoutCondition'));
197
198
  return Promise.resolve(null);
198
199
  }
199
200
  const url = combineUrl(control, execOptions);
@@ -201,7 +202,7 @@ export const doDelete = <T>(
201
202
 
202
203
  return doPost(control, execOptions).then((result) => {
203
204
  if (result?.status === ResStatus.SUCCESS) {
204
- if (!options.hideErrorToast) message.success('删除成功!');
205
+ if (!options.hideErrorToast) message.success($t('webui.utils.data.deleteSuccess'));
205
206
  }
206
207
  return result as ApiResponse<T> | null;
207
208
  });
@@ -4,6 +4,7 @@ import { ApiResponse, httpPost, IUrlInfo, ReqParams, ResStatus } from '@skyfox20
4
4
  import message from 'vue-m-message';
5
5
  import { combineParams } from '@skyfox2000/microbase';
6
6
  import { LoginExpiredError, useUserInfo } from '@/stores/userInfo';
7
+ import { $t } from '@/locales/index';
7
8
 
8
9
  /** 通用 Blob 下载方法
9
10
  *
@@ -73,14 +74,14 @@ export const donwloadFromMinio = <T>(url: IUrlInfo, params?: ReqParams, pageCtrl
73
74
  userInfoStore.logout(false);
74
75
  return;
75
76
  } else {
76
- message.error('下载文件失败!');
77
+ message.error($t('webui.utils.download.downloadFailed'));
77
78
  }
78
79
  return undefined;
79
80
  });
80
81
  } catch (error) {
81
82
  console.error('下载失败:', error);
82
83
  // throw new Error('文件导出失败,请稍后重试');
83
- message.error('文件下载失败,请稍后重试');
84
+ message.error($t('webui.utils.download.fileDownloadFailedRetry'));
84
85
  }
85
86
  };
86
87
 
@@ -91,7 +92,7 @@ export const previewFromMinio = (url: IUrlInfo, fileName: string, params?: ReqPa
91
92
  if (CanPreviewFileExt.includes(fileExt!)) {
92
93
  console.log(url);
93
94
  } else {
94
- message.error('文件类型不支持预览');
95
+ message.error($t('webui.utils.download.fileTypeNotSupported'));
95
96
  return false;
96
97
  }
97
98
 
@@ -113,7 +114,7 @@ export const previewFromMinio = (url: IUrlInfo, fileName: string, params?: ReqPa
113
114
  userInfoStore.logout(false);
114
115
  return;
115
116
  } else {
116
- message.error('文件预览失败!');
117
+ message.error($t('webui.utils.download.previewFailed'));
117
118
  }
118
119
  return undefined;
119
120
  });
@@ -7,6 +7,7 @@ import { csvToExcelView } from './excel-view';
7
7
  import { AnyData, ResStatus, IUrlInfo, httpGet, ApiResponse } from '@skyfox2000/fapi';
8
8
  import { doQuery } from '@/index';
9
9
  import message from 'vue-m-message';
10
+ import { $t } from '@/locales/index';
10
11
 
11
12
  /**
12
13
  * 判断是否为CSV格式的内容
@@ -138,7 +139,7 @@ export const loadPreviewFile = async (
138
139
  excelCtrl: any,
139
140
  ): Promise<{ success: boolean; blobUrl?: string; fileName?: string }> => {
140
141
  if (!previewUrl || !excelCtrl) {
141
- message.error('预览URL或Excel控制器未配置');
142
+ message.error($t('webui.utils.excelPreview.previewUrlNotConfigured'));
142
143
  return { success: false };
143
144
  }
144
145
 
@@ -178,12 +179,12 @@ export const loadPreviewFile = async (
178
179
  // 处理返回的文件数据
179
180
  return await handleFileData(data, false);
180
181
  } else {
181
- throw new Error(result?.msg || '文件加载失败');
182
+ throw new Error(result?.msg || $t('webui.utils.excelPreview.fileLoadFailed'));
182
183
  }
183
184
  }
184
185
  } catch (error: any) {
185
186
  console.error('预览文件加载错误:', error);
186
- message.error('文件加载失败:' + (error?.message || '未知错误'));
187
+ message.error($t('webui.utils.excelPreview.fileLoadFailed') + ':' + (error?.message || '未知错误'));
187
188
  throw error;
188
189
  }
189
190
  };
@@ -4,6 +4,7 @@ import dayjs from 'dayjs';
4
4
  import message from 'vue-m-message';
5
5
  import { downloadBlob } from './download';
6
6
  import { LoginExpiredError, useUserInfo } from '@/stores/userInfo';
7
+ import { $t } from '@/locales/index';
7
8
 
8
9
  // 下载当前选择行
9
10
  // 表头相同
@@ -92,8 +93,8 @@ const downloadCSV = async <T extends Record<string, any>>(
92
93
  const blob = new Blob([`\uFEFF${csvContent}`], { type: 'text/csv' });
93
94
  downloadBlob(blob, fileName);
94
95
  } catch (error) {
95
- console.error('导出失败:', error);
96
- message.error('文件导出失败,请稍后重试');
96
+ console.error($t('webui.utils.exportTable.exportFailed') + ':', error);
97
+ message.error($t('webui.utils.exportTable.fileExportFailed'));
97
98
  }
98
99
  };
99
100
 
@@ -124,8 +125,8 @@ export const exportSelectedRows = async <T extends Record<string, any>>(
124
125
  // 5. 生成 CSV 内容并下载
125
126
  await downloadCSV(processedFileName, fields, processedData);
126
127
  } catch (error) {
127
- console.error('导出失败:', error);
128
- message.error('文件导出失败,请稍后重试');
128
+ console.error($t('webui.utils.exportTable.exportFailed') + ':', error);
129
+ message.error($t('webui.utils.exportTable.fileExportFailed'));
129
130
  }
130
131
  };
131
132
 
@@ -182,8 +183,8 @@ export const exportResults = async <T extends Record<string, any>>(
182
183
  return undefined;
183
184
  });
184
185
  } catch (error) {
185
- console.error('导出失败:', error);
186
- message.error('文件导出失败,请稍后重试');
186
+ console.error($t('webui.utils.exportTable.exportFailed') + ':', error);
187
+ message.error($t('webui.utils.exportTable.fileExportFailed'));
187
188
  }
188
189
  };
189
190
 
@@ -7,6 +7,7 @@ import { Ref } from 'vue';
7
7
  import { MicroOpenApis } from './micro-openapis';
8
8
  import { isMicroApp } from '@skyfox2000/microbase';
9
9
  import { useUserInfo } from '@/stores/userInfo';
10
+ import { $t } from '@/locales/index';
10
11
 
11
12
  export class path {
12
13
  /**
@@ -72,7 +73,7 @@ export class AsyncUploader {
72
73
  if (!fileList.length) return;
73
74
 
74
75
  if (fileList.length === 0) {
75
- message.warning('请选择上传的文件!');
76
+ message.warning($t('webui.utils.fileUpload.pleaseSelectFile'));
76
77
  return;
77
78
  }
78
79
 
@@ -88,17 +89,17 @@ export class AsyncUploader {
88
89
  }
89
90
  }
90
91
  if (!err_count) {
91
- message.success('全部文件上传成功!');
92
+ message.success($t('webui.utils.fileUpload.allUploadSuccess'));
92
93
  result = true;
93
94
  } else if (err_count < files.length) {
94
95
  if (continueOnError) {
95
- message.error('上传结束,部分文件上传失败!');
96
- message.warning('保存上传成功的文件!');
96
+ message.error($t('webui.utils.fileUpload.partialUploadFailed'));
97
+ message.warning($t('webui.utils.fileUpload.saveUploadSuccess'));
97
98
  result = true;
98
99
  } else {
99
- message.error('上传结束,部分文件上传失败,取消保存!');
100
+ message.error($t('webui.utils.fileUpload.partialUploadFailedCancel'));
100
101
  }
101
- } else message.error('上传结束,所有文件上传失败!');
102
+ } else message.error($t('webui.utils.fileUpload.allUploadFailed'));
102
103
 
103
104
  loading.value = false;
104
105
  onComplete?.(result, files);
@@ -237,7 +238,7 @@ export class AsyncUploader {
237
238
  if (this.urlInfo.authorize) {
238
239
  const token = isMicroApp() ? await MicroOpenApis.getToken() : useUserInfo().getToken(); // 假设 getToken 是获取 Token 的方法
239
240
  if (!token) {
240
- reject(new Error('未授权或授权过期'));
241
+ reject(new Error($t('webui.utils.fileUpload.unauthorized')));
241
242
  return;
242
243
  }
243
244
  xhr.setRequestHeader('Authorization', 'Bearer ' + token);
@@ -257,7 +258,7 @@ export class AsyncUploader {
257
258
  // 检查返回的内容类型是否是 JSON
258
259
  const contentType = xhr.getResponseHeader('Content-Type');
259
260
  if (!contentType || !contentType.includes('application/json')) {
260
- reject(new Error('返回的结果不是 JSON 格式'));
261
+ reject(new Error($t('webui.utils.fileUpload.invalidJsonFormat')));
261
262
  return;
262
263
  }
263
264
 
@@ -292,13 +293,13 @@ export class AsyncUploader {
292
293
  // 更新文件状态为"上传失败"
293
294
  file.status = UploadStatus.Error;
294
295
  // 如果 JSON 格式无效,抛出错误
295
- reject(new Error('无法解析返回的 JSON 数据: ' + error));
296
+ reject(new Error($t('webui.utils.fileUpload.jsonParseError') + ': ' + error));
296
297
  }
297
298
  } else {
298
299
  // 更新文件状态为"上传失败"
299
300
  file.status = UploadStatus.Error;
300
301
  // 根据 HTTP 状态码判断上传失败的原因
301
- reject(new Error(`上传失败,状态码:${xhr.status}`));
302
+ reject(new Error($t('webui.utils.fileUpload.uploadFailed') + `:${xhr.status}`));
302
303
  }
303
304
  });
304
305
 
@@ -306,7 +307,7 @@ export class AsyncUploader {
306
307
  xhr.addEventListener('error', () => {
307
308
  // 更新文件状态为"上传失败"
308
309
  file.status = UploadStatus.Error;
309
- reject(new Error('上传失败,网络异常'));
310
+ reject(new Error($t('webui.utils.fileUpload.networkError')));
310
311
  });
311
312
 
312
313
  // 发送请求
@@ -315,7 +316,7 @@ export class AsyncUploader {
315
316
  // 绑定中断信号
316
317
  signal.addEventListener('abort', () => {
317
318
  xhr.abort(); // 中断上传
318
- reject(new Error('上传已取消'));
319
+ reject(new Error($t('webui.utils.fileUpload.uploadCancelled')));
319
320
  });
320
321
  });
321
322
  }
@@ -350,10 +351,10 @@ export const fastUpload = async (uploadUrl: IUrlInfo, uploadFile: UploadFile): P
350
351
 
351
352
  if (file.status === UploadStatus.Success) {
352
353
  uploadFile.status = UploadStatus.Online;
353
- message.success('文件上传成功!');
354
+ message.success($t('webui.utils.fileUpload.fileUploadSuccess'));
354
355
  } else {
355
356
  uploadFile.status = UploadStatus.Error;
356
- message.error('上传文件失败!');
357
+ message.error($t('webui.utils.fileUpload.fileUploadFailed'));
357
358
  }
358
359
  },
359
360
  );
@@ -2,6 +2,7 @@
2
2
  * CSV数据处理工具 - 统一使用excel-view处理
3
3
  */
4
4
  import { csvToExcelView } from './excel-view';
5
+ import {$t} from '@/locales/index';
5
6
 
6
7
  /**
7
8
  * 将CSV文本内容转换为Excel blob URL用于预览
@@ -19,7 +20,7 @@ export const csvToExcelBlob = async (csvContent: string, fileName: string) => {
19
20
  blob: null, // 不再返回blob对象,使用URL即可
20
21
  };
21
22
  } else {
22
- throw new Error(result.error || 'CSV转Excel失败');
23
+ throw new Error(result.error || $t('webui.utils.formCsv.csvToExcelFailed'));
23
24
  }
24
25
  };
25
26
 
@@ -46,10 +47,10 @@ export const processCsvFile = async (csvBuffer: ArrayBuffer, fileName: string) =
46
47
  csvContent: text, // 保留原始CSV内容
47
48
  };
48
49
  } catch (error) {
49
- console.error('CSV文件处理失败:', error);
50
+ console.error($t('webui.utils.formCsv.csvProcessFailed') + ':', error);
50
51
  return {
51
52
  success: false,
52
- error: error instanceof Error ? error.message : '未知错误',
53
+ error: error instanceof Error ? error.message : $t('webui.utils.formCsv.unknownError'),
53
54
  };
54
55
  }
55
56
  };
@@ -9,6 +9,7 @@ import { validMessages } from './form-validate';
9
9
  import { UploadFile } from '@/typings/upload';
10
10
  import { toExcel, type ExcelMarkInfo, excelToNormalized } from './excel-view';
11
11
  import { LoginExpiredError, useUserInfo } from '@/stores/userInfo';
12
+ import { $t } from '@/locales/index';
12
13
 
13
14
  // ExcelMarkCell 和 ExcelMarkInfo 类型已移至 excel-view.ts 统一管理
14
15
 
@@ -22,7 +23,7 @@ export const processExcelFile = async (excelBuffer: ArrayBuffer) => {
22
23
  const normalized = await excelToNormalized(excelBuffer);
23
24
 
24
25
  if (normalized.headers.length === 0) {
25
- message.error('Excel文件不包含工作表');
26
+ message.error($t('webui.utils.formExcel.noWorksheet'));
26
27
  return null;
27
28
  }
28
29
 
@@ -56,7 +57,7 @@ export const createMarkedExcelView = async (excelBuffer: ArrayBuffer, markInfo:
56
57
  // 处理Excel文件获取数据
57
58
  const excelData = await processExcelFile(excelBuffer);
58
59
  if (!excelData) {
59
- return { success: false, error: 'Excel文件处理失败' };
60
+ return { success: false, error: $t('webui.utils.formExcel.processFailed') };
60
61
  }
61
62
 
62
63
  const { headers: originalHeaders, excelRows } = excelData;
@@ -119,7 +120,7 @@ export const validateExcel = async (
119
120
  });
120
121
 
121
122
  if (headers.length === 0 || excelJson.length === 0) {
122
- message.error('Excel文件不包含足够的数据');
123
+ message.error($t('webui.utils.formExcel.insufficientData'));
123
124
  return { hasError: true };
124
125
  }
125
126
 
@@ -191,8 +192,8 @@ const validateExcelData = async (headers: string[], excelJson: Record<string, an
191
192
  validationErrors.push(...rowErrors);
192
193
  });
193
194
  } catch (error) {
194
- console.error('验证表格数据时发生错误:', error);
195
- message.error('验证表格数据时发生错误:' + error);
195
+ console.error($t('webui.utils.formExcel.validationError') + ':', error);
196
+ message.error($t('webui.utils.formExcel.validationError') + ':' + error);
196
197
  }
197
198
  }
198
199
 
@@ -233,7 +234,7 @@ export const checkExcelDuplicates = async (
233
234
  });
234
235
 
235
236
  if (missingDuplicateFields.length > 0) {
236
- message.error(`表头缺少重复检测所需字段: ${missingDuplicateFields.join(', ')}`);
237
+ message.error($t('webui.utils.formExcel.missingDuplicateFields') + `: ${missingDuplicateFields.join(', ')}`);
237
238
  return { hasError: true };
238
239
  }
239
240
 
@@ -331,14 +332,14 @@ export const validateExcelUnified = async (
331
332
  const allMarkHeaders: string[] = [];
332
333
  let hasFormatError = false;
333
334
  let hasDuplicateError = false;
334
- let validationMsg = '数据验证成功';
335
- let duplicateMsg = '待验证重复数据';
335
+ let validationMsg = $t('webui.utils.formExcel.validationSuccess');
336
+ let duplicateMsg = $t('webui.utils.formExcel.duplicateValidationPending');
336
337
 
337
338
  // 1. 格式验证
338
339
  const validationResult = await validateExcel(excelBuffer, rules);
339
340
  if (validationResult.hasError) {
340
341
  hasFormatError = true;
341
- validationMsg = '数据验证失败';
342
+ validationMsg = $t('webui.utils.formExcel.validationFailed');
342
343
  if (validationResult.markCells) {
343
344
  allMarkCells.push(...validationResult.markCells);
344
345
  }
@@ -346,7 +347,7 @@ export const validateExcelUnified = async (
346
347
  allMarkHeaders.push(...validationResult.markHeaders);
347
348
  }
348
349
  } else if (rules && Object.keys(rules).length > 0) {
349
- validationMsg = '数据验证通过';
350
+ validationMsg = $t('webui.utils.formExcel.validationPassed');
350
351
  }
351
352
 
352
353
  // 2. 重复验证
@@ -354,7 +355,7 @@ export const validateExcelUnified = async (
354
355
  const duplicateResult = await checkExcelDuplicates(excelBuffer, duplicateRules, duplicateUrl);
355
356
  if (duplicateResult.hasError) {
356
357
  hasDuplicateError = true;
357
- duplicateMsg = '检测到重复数据';
358
+ duplicateMsg = $t('webui.utils.formExcel.duplicateDetected');
358
359
  if (duplicateResult.markCells) {
359
360
  // 检查是否有重复标记的单元格,如果有则改为深红色
360
361
  duplicateResult.markCells.forEach((duplicateCell) => {
@@ -372,7 +373,7 @@ export const validateExcelUnified = async (
372
373
  allMarkHeaders.push(...duplicateResult.markHeaders);
373
374
  }
374
375
  } else {
375
- duplicateMsg = '重复性检验通过';
376
+ duplicateMsg = $t('webui.utils.formExcel.duplicateCheckPassed');
376
377
  }
377
378
  }
378
379
 
@@ -433,7 +434,7 @@ export const appendExcelData = async (fileInfo: UploadFile, fileData: Record<str
433
434
  // 获取Excel数据,并转换成指定数据对象结构
434
435
  const excelFileData = await processExcelFile(buffer);
435
436
  if (!excelFileData) {
436
- message.error('上传的文件不是Excel文件');
437
+ message.error($t('webui.utils.formExcel.fileNotExcel'));
437
438
  return;
438
439
  }
439
440
  const { headers, excelRows, excelData } = excelFileData;
@@ -4,6 +4,7 @@ import { EditorControl, InputFactoryItems, ValidateError, ValidateRule, Validate
4
4
  import { ProviderKeys } from '@/typings/page.d';
5
5
  import { AnyData } from '@skyfox2000/fapi';
6
6
  import { isEmpty } from './isEmpty';
7
+ import { $t } from '@/locales/index';
7
8
 
8
9
  export let validMessages: Validator;
9
10
  /**
@@ -12,28 +13,28 @@ export let validMessages: Validator;
12
13
  export const initValidate = (messages?: Record<string, any>) => {
13
14
  validMessages = new Validator({});
14
15
  validMessages.messages({
15
- required: '${label}不能为空',
16
+ required: '${label}' + $t('webui.utils.formValidate.required'),
16
17
  types: {
17
- number: '${label}必须是数字',
18
+ number: '${label}' + $t('webui.utils.formValidate.numberType'),
18
19
  },
19
- enum: '${label}必须是${enum}中的一个',
20
+ enum: '${label}' + $t('webui.utils.formValidate.enum'),
20
21
  string: {
21
- len: '${label}长度必须为${len}',
22
- min: '${label}长度不能小于${min}',
23
- max: '${label}长度不能大于${max}',
24
- range: '${label}长度必须在${min}和${max}之间',
22
+ len: '${label}' + $t('webui.utils.formValidate.stringLen'),
23
+ min: '${label}' + $t('webui.utils.formValidate.stringMin'),
24
+ max: '${label}' + $t('webui.utils.formValidate.stringMax'),
25
+ range: '${label}' + $t('webui.utils.formValidate.stringRange'),
25
26
  },
26
27
  number: {
27
- len: '${label}必须为${len}',
28
- min: '${label}不能小于${min}',
29
- max: '${label}不能大于${max}',
30
- range: '${label}必须在${min}和${max}之间',
28
+ len: '${label}' + $t('webui.utils.formValidate.numberLen'),
29
+ min: '${label}' + $t('webui.utils.formValidate.numberMin'),
30
+ max: '${label}' + $t('webui.utils.formValidate.numberMax'),
31
+ range: '${label}' + $t('webui.utils.formValidate.numberRange'),
31
32
  },
32
33
  array: {
33
- len: '${label}长度必须为${len}',
34
- min: '${label}长度不能小于${min}',
35
- max: '${label}长度不能大于${max}',
36
- range: '${label}长度必须在${min}和${max}之间',
34
+ len: '${label}' + $t('webui.utils.formValidate.arrayLen'),
35
+ min: '${label}' + $t('webui.utils.formValidate.arrayMin'),
36
+ max: '${label}' + $t('webui.utils.formValidate.arrayMax'),
37
+ range: '${label}' + $t('webui.utils.formValidate.arrayRange'),
37
38
  },
38
39
  ...messages,
39
40
  });
@@ -125,7 +126,7 @@ export const getRuleTexts = (rules?: Record<string, ValidateRule>) => {
125
126
  }
126
127
  } catch (error) {
127
128
  // 出错时忽略该消息
128
- console.error('格式化验证消息出错:', error);
129
+ console.error($t('webui.utils.formValidate.formatValidationError') + ':', error);
129
130
  }
130
131
  };
131
132
 
@@ -151,7 +152,7 @@ export const getRuleTexts = (rules?: Record<string, ValidateRule>) => {
151
152
  // 嵌套对象规则不显示任何消息
152
153
  }
153
154
  } catch (error) {
154
- console.error('处理验证规则出错:', error);
155
+ console.error($t('webui.utils.formValidate.processValidationError') + ':', error);
155
156
  }
156
157
 
157
158
  // 确保不重复添加相同的规则文字
package/src/utils/form.ts CHANGED
@@ -4,6 +4,7 @@ import { AnyData, AnyJsonData, ResStatus } from '@skyfox2000/fapi';
4
4
  import { doSave } from './data';
5
5
  import { getRecordDetail } from './table';
6
6
  import { formValidate, resetRules } from './form-validate';
7
+ import {$t} from '@/locales/index';
7
8
 
8
9
  /**
9
10
  * 表单存储事件
@@ -59,7 +60,7 @@ export const saveForm = async <T>(editorCtrl: EditorControl<T>): Promise<void> =
59
60
  }
60
61
 
61
62
  if (editorCtrl.ruleResults.value) {
62
- message.error('提交表单时,验证失败!');
63
+ message.error($t('webui.utils.form.submitValidationFailed'));
63
64
  console.error('表单验证失败!', editorCtrl.ruleResults.value);
64
65
  /**
65
66
  * 验证失败
@@ -89,7 +90,7 @@ export const saveForm = async <T>(editorCtrl: EditorControl<T>): Promise<void> =
89
90
  },
90
91
  ).then((result) => {
91
92
  if (result?.status === ResStatus.SUCCESS) {
92
- message.success('保存成功!');
93
+ message.success($t('webui.utils.form.saveSuccess'));
93
94
  if (editorCtrl.grid) {
94
95
  editorCtrl.grid!.reload.value = true;
95
96
  }
@@ -126,13 +127,13 @@ export const saveForm = async <T>(editorCtrl: EditorControl<T>): Promise<void> =
126
127
  editorCtrl.ruleResults.value = ruleResults;
127
128
  }
128
129
  }
129
- message.error(`保存失败!数据 \`${fieldValue}\` 已存在!`);
130
- } else message.error(result?.msg ?? '保存失败!');
130
+ message.error($t('webui.utils.form.dataAlreadyExists').replace('{0}', fieldValue));
131
+ } else message.error(result?.msg ?? $t('webui.utils.form.saveFailed'));
131
132
  if (editorCtrl.afterSave) {
132
133
  editorCtrl.afterSave(result);
133
134
  }
134
135
  } else {
135
- message.error(result?.msg ?? '保存失败!');
136
+ message.error(result?.msg ?? $t('webui.utils.form.saveFailed'));
136
137
  if (editorCtrl.afterSave) {
137
138
  editorCtrl.afterSave(result);
138
139
  }
@@ -1,5 +1,6 @@
1
1
  import { defineComponent, h, Ref, ref, toRaw, watch } from 'vue';
2
2
  import message from 'vue-m-message';
3
+ import {$t} from '@/locales/index';
3
4
 
4
5
  type IconCacheData = {
5
6
  /// 存储到window里面的key
@@ -222,7 +223,7 @@ const loadAndCacheScript = async (url: string, monoColor: boolean) => {
222
223
  try {
223
224
  const response = await fetch(url);
224
225
  if (!response.ok) {
225
- message.error('网络异常,无法加载图标库!');
226
+ message.error($t('webui.utils.iconLoader.networkError'));
226
227
  return;
227
228
  }
228
229
  let scriptContent = await response.text();
@@ -240,7 +241,7 @@ const loadAndCacheScript = async (url: string, monoColor: boolean) => {
240
241
  loadScript(scriptContent);
241
242
  return;
242
243
  } catch (error) {
243
- console.error('网络异常,无法加载图标库:', error);
244
+ console.error($t('webui.utils.iconLoader.networkError') + ':', error);
244
245
  return null;
245
246
  }
246
247
  };
@@ -8,6 +8,7 @@ import {
8
8
  ReqParams,
9
9
  ResStatus,
10
10
  } from '@skyfox2000/fapi';
11
+ import {$t} from '@/locales/index';
11
12
  import { inject, ref, watch } from 'vue';
12
13
  import { OptionItemProps, SelectValue, OptionControl, OptionProps } from '@/typings/option.d';
13
14
  import { ProviderKeys } from '@/typings/page.d';
@@ -44,7 +45,7 @@ export const loadOption = (load: boolean, optionCtrl: OptionControl, props?: Opt
44
45
  if (load) doQueryOptions(optionCtrl.url, optionCtrl, optionCtrl.params ?? {});
45
46
  } else {
46
47
  const labelText = ref<string>(inject(ProviderKeys.LabelText, ''));
47
- message.error('`' + labelText.value + '` 未配置选项数据!', {
48
+ message.error('`' + labelText.value + '` ' + $t('webui.utils.options.notConfigured'), {
48
49
  duration: 5000,
49
50
  });
50
51
  }