@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.
- package/lib/assets/modules/{baseLayout-LU1ysAJM.js → baseLayout-DfTxHOFc.js} +7 -7
- package/lib/assets/modules/file-upload-DTOdV5vM.js +211 -0
- package/lib/assets/modules/index-BDoBUrYA.js +114 -0
- package/lib/assets/modules/{index-C6RrxZBR.js → index-BwMaOrJT.js} +1 -1
- package/lib/assets/modules/{index-CHG5bbZG.js → index-M1qERbea.js} +99 -99
- package/lib/assets/modules/{menuTabs-Bk8A-zzL.js → menuTabs-DWaBSRNr.js} +42 -42
- package/lib/assets/modules/{toolIcon-ADz-Bt4_.js → toolIcon-BYnHhAy-.js} +1 -1
- package/lib/assets/modules/upload-template-BKm9mFq8.js +6764 -0
- package/lib/assets/modules/uploadList-CHvr6Hp1.js +472 -0
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +2 -2
- package/lib/es/Error403/index.js +14 -15
- package/lib/es/Error404/index.js +16 -17
- package/lib/es/ExcelForm/index.js +244 -244
- package/lib/es/MenuLayout/index.js +5 -5
- package/lib/es/TemplateFile/index.js +53 -54
- package/lib/es/UploadForm/index.js +61 -63
- package/lib/locales/default.d.ts +287 -103
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +1440 -1586
- package/package.json +1 -1
- package/src/components/common/icon/fullscreen.vue +1 -1
- package/src/components/content/dialog/excelForm.vue +32 -28
- package/src/components/content/dialog/index.vue +3 -3
- package/src/components/content/dialog/templateFile.vue +3 -2
- package/src/components/content/dialog/uploadForm.vue +5 -4
- package/src/components/content/drawer/index.vue +5 -3
- package/src/components/content/list/index.vue +2 -1
- package/src/components/content/list/listOperate.vue +6 -7
- package/src/components/content/search/index.vue +2 -2
- package/src/components/content/table/index.vue +2 -1
- package/src/components/content/table/tableOperate.vue +8 -9
- package/src/components/content/toolbar/icontool.vue +1 -5
- package/src/components/content/toolbar/index.vue +4 -5
- package/src/components/content/toolpanel/index.vue +20 -20
- package/src/components/error/error403.vue +2 -2
- package/src/components/error/error404.vue +2 -2
- package/src/components/form/input/index.vue +3 -1
- package/src/components/form/select/index.vue +3 -2
- package/src/components/form/textarea/index.vue +3 -1
- package/src/components/form/transfer/index.vue +2 -1
- package/src/components/form/upload/uploadList.vue +23 -19
- package/src/components/layout/header/headerExits.vue +5 -5
- package/src/components/layout/menu/menuTabs.vue +1 -1
- package/src/const/options.ts +17 -16
- package/src/locales/default.ts +297 -176
- package/src/locales/index.ts +12 -4
- package/src/stores/appInfo.ts +2 -1
- package/src/stores/userInfo.ts +6 -5
- package/src/utils/data.ts +9 -8
- package/src/utils/download.ts +5 -4
- package/src/utils/excel-preview.ts +4 -3
- package/src/utils/export-table.ts +7 -6
- package/src/utils/file-upload.ts +15 -14
- package/src/utils/form-csv.ts +4 -3
- package/src/utils/form-excel.ts +14 -13
- package/src/utils/form-validate.ts +18 -17
- package/src/utils/form.ts +6 -5
- package/src/utils/icon-loader.ts +3 -2
- package/src/utils/options.ts +2 -1
- package/src/utils/tools.ts +18 -17
- package/lib/assets/modules/file-upload-BvIYPDBD.js +0 -211
- package/lib/assets/modules/index-Bi3hR8Gf.js +0 -114
- package/lib/assets/modules/upload-template-mzLL4UUU.js +0 -6462
- 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
|
});
|
package/src/utils/download.ts
CHANGED
|
@@ -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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
|
package/src/utils/file-upload.ts
CHANGED
|
@@ -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('
|
|
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('
|
|
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(
|
|
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
|
);
|
package/src/utils/form-csv.ts
CHANGED
|
@@ -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 || '
|
|
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('
|
|
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
|
};
|
package/src/utils/form-excel.ts
CHANGED
|
@@ -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('
|
|
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: '
|
|
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('
|
|
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('
|
|
195
|
-
message.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(
|
|
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('
|
|
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}
|
|
20
|
+
enum: '${label}' + $t('webui.utils.formValidate.enum'),
|
|
20
21
|
string: {
|
|
21
|
-
len: '${label}
|
|
22
|
-
min: '${label}
|
|
23
|
-
max: '${label}
|
|
24
|
-
range: '${label}
|
|
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}
|
|
28
|
-
min: '${label}
|
|
29
|
-
max: '${label}
|
|
30
|
-
range: '${label}
|
|
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}
|
|
34
|
-
min: '${label}
|
|
35
|
-
max: '${label}
|
|
36
|
-
range: '${label}
|
|
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('
|
|
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('
|
|
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(
|
|
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
|
}
|
package/src/utils/icon-loader.ts
CHANGED
|
@@ -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('
|
|
244
|
+
console.error($t('webui.utils.iconLoader.networkError') + ':', error);
|
|
244
245
|
return null;
|
|
245
246
|
}
|
|
246
247
|
};
|
package/src/utils/options.ts
CHANGED
|
@@ -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
|
}
|