@ticatec/batch-data-uploader 0.0.4 → 0.0.10
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/README.md +74 -121
- package/dist/BaseEncodingTemplate.d.ts +30 -0
- package/dist/BaseEncodingTemplate.js +34 -0
- package/dist/BaseTemplate.d.ts +5 -0
- package/dist/BaseTemplate.js +19 -2
- package/dist/BaseUploadTemplate.d.ts +3 -3
- package/dist/BaseUploadTemplate.js +15 -10
- package/dist/DataColumn.d.ts +4 -4
- package/dist/EncodingWizard.svelte +89 -0
- package/dist/EncodingWizard.svelte.d.ts +26 -0
- package/dist/FileUploadWizard.svelte +18 -16
- package/dist/FileUploadWizard.svelte.d.ts +1 -0
- package/dist/i18n_resources/batch_cn_resource.d.ts +1 -0
- package/dist/i18n_resources/batch_cn_resource.js +2 -1
- package/dist/i18n_resources/batch_en_resource.d.ts +5 -0
- package/dist/i18n_resources/batch_en_resource.js +16 -11
- package/dist/i18n_resources/i18nKeys.d.ts +20 -0
- package/dist/i18n_resources/i18nKeys.js +20 -0
- package/documents/BaseEncodingTemplate.md +156 -0
- package/documents/BaseEncodingTemplate_cn.md +156 -0
- package/documents/BaseTemplate.md +222 -0
- package/documents/BaseTemplate_cn.md +225 -0
- package/documents/BaseUploadTemplate.md +170 -0
- package/documents/BaseUploadTemplate_cn.md +172 -0
- package/documents/EncodingWizard.md +89 -0
- package/documents/EncodingWizard_cn.md +90 -0
- package/documents/FileUploadWizard.md +91 -0
- package/documents/FileUploadWizard_cn.md +94 -0
- package/package.json +19 -6
- package/dist/BaseLoadTemplate.d.ts +0 -18
- package/dist/BaseLoadTemplate.js +0 -25
package/README.md
CHANGED
|
@@ -1,154 +1,107 @@
|
|
|
1
|
-
# Excel Batch Data
|
|
1
|
+
# Excel Data Batch Upload Processing Component / Data Recognition Component
|
|
2
2
|
|
|
3
|
-
[
|
|
3
|
+
## [中文文档](./README_CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# @ticatec/batch-data-uploader
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* Parse `.xls` / `.xlsx` files
|
|
10
|
-
* Custom column mapping and formatting
|
|
11
|
-
* Batch upload with configurable batch size
|
|
12
|
-
* Extensible data preprocessing logic (e.g., merging, grouping)
|
|
13
|
-
* Upload status display: Pending, Uploading, Success, Failed
|
|
14
|
-
* Export error rows to Excel
|
|
15
|
-
* Multilingual support (based on `@ticatec/i18n`)
|
|
7
|
+
A universal Svelte component for batch data uploading, supporting Excel file parsing, local preprocessing, field mapping validation, multilingual prompts, import validation, and error messaging.
|
|
16
8
|
|
|
17
9
|
---
|
|
18
10
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
### Installation
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm i @ticatec/batch-data-uploader
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### 1. Define a Template Class
|
|
28
|
-
|
|
29
|
-
Extend `BaseTemplate`, provide field definitions and upload logic, and optionally override `consolidateData` to process data.
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
import BaseUploadTemplate from '@ticatec/batch-data-uploader/BaseUploadTemplate';
|
|
33
|
-
import type DataColumn from '@ticatec/batch-data-uploader/DataColumn';
|
|
34
|
-
|
|
35
|
-
class MyDataTemplate extends BaseUploadTemplate {
|
|
36
|
-
constructor(uploadFun: UploadFun) {
|
|
37
|
-
const columns: DataColumn[] = [
|
|
38
|
-
{ text: 'Name', field: 'name', pos: 0 },
|
|
39
|
-
{ text: 'Email', field: 'email', pos: 1 },
|
|
40
|
-
{ text: 'Age', field: 'age', pos: 2, parser: val => parseInt(val) },
|
|
41
|
-
];
|
|
42
|
-
super(columns, uploadFun, 50);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Optional: Override to implement merge/group logic
|
|
46
|
-
protected consolidateData(rows: Array<any>) {
|
|
47
|
-
return super.consolidateData(rows);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
11
|
+
## ✨ Features
|
|
51
12
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let showDialog = false;
|
|
60
|
-
|
|
61
|
-
function doUpload(rows: any[]): Promise<void> {
|
|
62
|
-
const dataChunk = rows.map(row => row.data);
|
|
63
|
-
return fetch('/api/upload', {
|
|
64
|
-
method: 'POST',
|
|
65
|
-
body: JSON.stringify(dataChunk),
|
|
66
|
-
}).then(res => {
|
|
67
|
-
if (!res.ok) throw new Error('Upload failed');
|
|
68
|
-
// After upload, write result info to row.error if needed
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const template = new MyDataTemplate(doUpload);
|
|
73
|
-
|
|
74
|
-
const showUploadDialog = () => {
|
|
75
|
-
window.Dialog.showModal(UploadDialog, {
|
|
76
|
-
title: 'Batch Add Employees',
|
|
77
|
-
template,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
</script>
|
|
81
|
-
|
|
82
|
-
<button on:click={() => showUploadDialog()}>Import Data</button>
|
|
83
|
-
```
|
|
13
|
+
- 📂 Supports drag-and-drop and file selection for uploading `.xlsx` files
|
|
14
|
+
- 🧠 Local parsing of Excel data without server preprocessing
|
|
15
|
+
- 🧩 Supports field mapping and custom parsers
|
|
16
|
+
- 📝 Data preview and validation with highlighted error prompts
|
|
17
|
+
- 🌐 Multilingual support (built-in Chinese and English)
|
|
18
|
+
- 🔌 Compatible with the UI element style of `@ticatec/uniface-element`
|
|
84
19
|
|
|
85
20
|
---
|
|
86
21
|
|
|
87
|
-
##
|
|
88
|
-
|
|
89
|
-
### `BaseTemplate` Constructor Parameters
|
|
90
|
-
|
|
91
|
-
| Name | Type | Description |
|
|
92
|
-
| ----------- | ------------------------------- | -------------------------------------------- |
|
|
93
|
-
| `columns` | `DataColumn[]` | Defines column position and format |
|
|
94
|
-
| `uploadFun` | `(arr: any[]) => Promise<void>` | Upload function, called in batches |
|
|
95
|
-
| `batchSize` | `number` (default: 50) | Number of rows per upload batch |
|
|
96
|
-
| `rowOffset` | `number` (default: 1) | Row offset for data start (e.g. skip header) |
|
|
22
|
+
## 📦 Installation
|
|
97
23
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
interface DataColumn {
|
|
102
|
-
text: string; // Column display text
|
|
103
|
-
field: string; // Data field path (supports nesting)
|
|
104
|
-
pos: number; // Excel column index (starting from 0)
|
|
105
|
-
parser?: (val: any) => any; // Optional parser function for cell values
|
|
106
|
-
}
|
|
24
|
+
```bash
|
|
25
|
+
npm install @ticatec/batch-data-uploader xlsx
|
|
107
26
|
```
|
|
108
27
|
|
|
109
28
|
---
|
|
110
29
|
|
|
111
|
-
##
|
|
30
|
+
## 📁 Project Structure
|
|
112
31
|
|
|
113
|
-
|
|
114
|
-
2. Call `BaseTemplate.parseExcelFile(file)` to parse data
|
|
115
|
-
3. Display preview data table with `Pending` status
|
|
116
|
-
4. User clicks upload, system calls `uploadFun` in batches
|
|
117
|
-
5. Mark successful items, retain `error` info for failed items
|
|
118
|
-
6. Failed rows can be exported to Excel
|
|
32
|
+
The main components and classes are as follows:
|
|
119
33
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
34
|
+
| File | Description |
|
|
35
|
+
| -------------------------- | ----------------------------------------------------- |
|
|
36
|
+
| `FileUploadWizard.svelte` | Main upload dialog, uses `BaseUploadTemplate` to upload and validate data |
|
|
37
|
+
| `EncodingWizard.svelte` | Field mapping dialog, uses `BaseEncodingTemplate` to map Excel fields |
|
|
38
|
+
| `BaseTemplate.ts` | Abstract base class encapsulating Excel parsing and column definition logic |
|
|
39
|
+
| `BaseUploadTemplate.ts` | Upload template base class for validation, preprocessing, and data uploading |
|
|
40
|
+
| `BaseEncodingTemplate.ts` | Encoding template base class for dynamic field mapping and transformation |
|
|
41
|
+
| `utils.ts` | Utility functions, such as `setNestedValue` and `getNestedValue` |
|
|
42
|
+
| `i18n_resources` | Multilingual resource definitions, supporting Chinese and English switching |
|
|
125
43
|
|
|
126
44
|
---
|
|
127
45
|
|
|
128
|
-
##
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
46
|
+
## 🚀 Usage
|
|
47
|
+
|
|
48
|
+
### Batch Data Upload
|
|
49
|
+
|
|
50
|
+
[Implementing Batch Data Upload](./documents/FileUploadWizard.md)
|
|
51
|
+
|
|
52
|
+
### Data Parsing and Validation
|
|
53
|
+
|
|
54
|
+
[Implementing Data Parsing and Validation](./documents/EncodingWizard.md)
|
|
55
|
+
|
|
56
|
+
## 🌐 Multilingual Support
|
|
57
|
+
|
|
58
|
+
By leveraging `@ticatec/i18n` and `i18n_resources`, automatic switching between Chinese and English is supported. You can customize internationalization by extending `i18nKeys` and resource files.
|
|
59
|
+
|
|
60
|
+
English resource file, loadable via i18n tools:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"batchUploading": {
|
|
65
|
+
"status": {
|
|
66
|
+
"pending": "To upload",
|
|
67
|
+
"uploading": "Uploading...",
|
|
68
|
+
"successful": "Success",
|
|
69
|
+
"fail": "Failure"
|
|
70
|
+
},
|
|
71
|
+
"parsing": "Parsing file...",
|
|
72
|
+
"parseFailure": "Cannot parse file: {{name}}",
|
|
73
|
+
"waitUploading": "Cannot exit during uploading!",
|
|
74
|
+
"button": {
|
|
75
|
+
"upload": "Upload",
|
|
76
|
+
"save": "Save error data",
|
|
77
|
+
"open": "Open",
|
|
78
|
+
"confirm": "Confirm"
|
|
79
|
+
},
|
|
80
|
+
"errorTitle": "Error",
|
|
81
|
+
"sheetName": "Abnormal data",
|
|
82
|
+
"labelStatus": "Status",
|
|
83
|
+
"labelValid": "Validity",
|
|
84
|
+
"textValid": "Yes",
|
|
85
|
+
"textInvalid": "No"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
134
89
|
|
|
135
90
|
---
|
|
136
91
|
|
|
137
|
-
##
|
|
92
|
+
## 🧪 Examples
|
|
138
93
|
|
|
139
|
-
|
|
140
|
-
* [`@ticatec/uniface-element`](https://www.npmjs.com/package/@ticatec/uniface-element)
|
|
141
|
-
* [`@ticatec/i18n`](https://www.npmjs.com/package/@ticatec/i18n)
|
|
94
|
+
Refer to the `src/routes/+page.svelte` example page for a complete usage flow and template definitions.
|
|
142
95
|
|
|
143
96
|
---
|
|
144
97
|
|
|
145
|
-
## License
|
|
98
|
+
## 🪪 License
|
|
146
99
|
|
|
147
|
-
MIT License
|
|
100
|
+
MIT License © Ticatec
|
|
148
101
|
|
|
149
102
|
---
|
|
150
103
|
|
|
151
104
|
## Author
|
|
152
105
|
|
|
153
|
-
Henry Feng
|
|
154
|
-
|
|
106
|
+
Henry Feng
|
|
107
|
+
huili.f@gmail.com
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import BaseTemplate from "./BaseTemplate";
|
|
2
|
+
import type DataColumn from "./DataColumn";
|
|
3
|
+
import type { DataColumn as TableColumn } from "@ticatec/uniface-element/DataTable";
|
|
4
|
+
export default abstract class BaseEncodingTemplate extends BaseTemplate {
|
|
5
|
+
private validColumn;
|
|
6
|
+
protected constructor(columns: Array<DataColumn>, rowOffset?: number);
|
|
7
|
+
/**
|
|
8
|
+
* 检查一行的数据是否合法
|
|
9
|
+
* @param row
|
|
10
|
+
* @protected
|
|
11
|
+
*/
|
|
12
|
+
protected abstract isDataValid(row: any): boolean;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param rows
|
|
16
|
+
* @protected
|
|
17
|
+
*/
|
|
18
|
+
protected abstract encodeData(rows: Array<any>): Promise<Array<any>>;
|
|
19
|
+
/**
|
|
20
|
+
* 数据集是否有效
|
|
21
|
+
*/
|
|
22
|
+
abstract get valid(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 从服务器抓取数据,然后根据主键进行数据合并
|
|
25
|
+
* @param rows
|
|
26
|
+
* @protected
|
|
27
|
+
*/
|
|
28
|
+
protected consolidateData(rows: Array<any>): Promise<Array<any>>;
|
|
29
|
+
get columns(): Array<TableColumn>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import BaseTemplate from "./BaseTemplate";
|
|
2
|
+
import { getI18nText } from "@ticatec/i18n";
|
|
3
|
+
import i18nKeys from "./i18n_resources/i18nKeys";
|
|
4
|
+
const ValidData = `<span style="color: #76FF03">${getI18nText(i18nKeys.textValid)}</span>`;
|
|
5
|
+
const InvalidData = `<span style="color: #ff3e00">${getI18nText(i18nKeys.textInvalid)}</span>`;
|
|
6
|
+
export default class BaseEncodingTemplate extends BaseTemplate {
|
|
7
|
+
validColumn = {
|
|
8
|
+
text: getI18nText(i18nKeys.labelValid),
|
|
9
|
+
width: 90,
|
|
10
|
+
align: 'center',
|
|
11
|
+
escapeHTML: true,
|
|
12
|
+
formatter: row => this.isDataValid(row) ? ValidData : InvalidData
|
|
13
|
+
};
|
|
14
|
+
constructor(columns, rowOffset = 1) {
|
|
15
|
+
super(columns, rowOffset);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 从服务器抓取数据,然后根据主键进行数据合并
|
|
19
|
+
* @param rows
|
|
20
|
+
* @protected
|
|
21
|
+
*/
|
|
22
|
+
async consolidateData(rows) {
|
|
23
|
+
let list = await this.encodeData(this.extractData(rows));
|
|
24
|
+
rows.forEach((item, idx) => {
|
|
25
|
+
if (list[idx]) {
|
|
26
|
+
rows[idx] = { ...item, ...list[idx] };
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
31
|
+
get columns() {
|
|
32
|
+
return [...this._columns, this.validColumn];
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/BaseTemplate.d.ts
CHANGED
package/dist/BaseTemplate.js
CHANGED
|
@@ -34,8 +34,9 @@ export default class BaseTemplate {
|
|
|
34
34
|
const rows = [];
|
|
35
35
|
for (let rowIndex = range.s.r + this.rowOffset; rowIndex <= range.e.r; rowIndex++) {
|
|
36
36
|
const rowObject = {};
|
|
37
|
-
for (
|
|
38
|
-
const
|
|
37
|
+
for (let i = 0; i < this._columns.length; i++) {
|
|
38
|
+
const colDef = this._columns[i];
|
|
39
|
+
const cellAddress = { r: rowIndex, c: i };
|
|
39
40
|
const cellRef = XLSX.utils.encode_cell(cellAddress);
|
|
40
41
|
const cell = sheet[cellRef];
|
|
41
42
|
const rawValue = cell?.v;
|
|
@@ -46,6 +47,22 @@ export default class BaseTemplate {
|
|
|
46
47
|
}
|
|
47
48
|
this._list = await this.consolidateData(rows);
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 获取实际待上传的数据
|
|
52
|
+
* @param arr
|
|
53
|
+
*/
|
|
54
|
+
extractData(arr) {
|
|
55
|
+
let list = arr.map(item => {
|
|
56
|
+
let result = {};
|
|
57
|
+
for (let col of this._columns) {
|
|
58
|
+
if (col.visible != false && col.ignore != false) {
|
|
59
|
+
utils.setNestedValue(result, col.field, utils.getNestedValue(item.data, col.field));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
});
|
|
64
|
+
return list;
|
|
65
|
+
}
|
|
49
66
|
/**
|
|
50
67
|
* 包裹数据
|
|
51
68
|
* @param data
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import BaseTemplate from "./BaseTemplate";
|
|
2
2
|
import type { DataColumn as TableColumn } from "@ticatec/uniface-element/DataTable";
|
|
3
3
|
import type DataColumn from "./DataColumn";
|
|
4
|
-
export type UploadFun = (arr: Array<any>) => Promise<
|
|
4
|
+
export type UploadFun = (arr: Array<any>) => Promise<Array<any>>;
|
|
5
5
|
export type UpdateProgressStatus = () => void;
|
|
6
6
|
export default abstract class BaseUploadTemplate extends BaseTemplate {
|
|
7
|
-
protected uploadFun: UploadFun;
|
|
8
7
|
protected batchSize: number;
|
|
9
8
|
protected updateProgressStatus: UpdateProgressStatus | null;
|
|
10
|
-
protected constructor(columns: Array<DataColumn>,
|
|
9
|
+
protected constructor(columns: Array<DataColumn>, batchSize?: number, rowOffset?: number);
|
|
11
10
|
/**
|
|
12
11
|
* 状态更新的监听器
|
|
13
12
|
* @param value
|
|
14
13
|
*/
|
|
15
14
|
setProgressStatusListener(value: UpdateProgressStatus): void;
|
|
15
|
+
protected abstract uploadData(list: Array<any>): Promise<Array<any>>;
|
|
16
16
|
/**
|
|
17
17
|
* 上传数据
|
|
18
18
|
*/
|
|
@@ -4,8 +4,8 @@ import i18nKeys from "./i18n_resources/i18nKeys";
|
|
|
4
4
|
import utils from "./utils";
|
|
5
5
|
import * as XLSX from 'xlsx';
|
|
6
6
|
const statusColumn = {
|
|
7
|
-
text:
|
|
8
|
-
width:
|
|
7
|
+
text: getI18nText(i18nKeys.labelStatus),
|
|
8
|
+
width: 240,
|
|
9
9
|
resizable: true,
|
|
10
10
|
formatter: row => {
|
|
11
11
|
if (row.status == 'P') {
|
|
@@ -25,13 +25,10 @@ const statusColumn = {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
export default class BaseUploadTemplate extends BaseTemplate {
|
|
28
|
-
uploadFun;
|
|
29
28
|
batchSize;
|
|
30
29
|
updateProgressStatus = null;
|
|
31
|
-
constructor(columns,
|
|
30
|
+
constructor(columns, batchSize = 50, rowOffset = 1) {
|
|
32
31
|
super(columns, rowOffset);
|
|
33
|
-
;
|
|
34
|
-
this.uploadFun = uploadFun;
|
|
35
32
|
this.batchSize = batchSize;
|
|
36
33
|
}
|
|
37
34
|
/**
|
|
@@ -45,12 +42,20 @@ export default class BaseUploadTemplate extends BaseTemplate {
|
|
|
45
42
|
* 上传数据
|
|
46
43
|
*/
|
|
47
44
|
async upload() {
|
|
48
|
-
for (let i = 0; i < this.
|
|
49
|
-
const chunk = this.
|
|
45
|
+
for (let i = 0; i < this._list.length; i += this.batchSize) {
|
|
46
|
+
const chunk = this._list.slice(i, i + this.batchSize);
|
|
50
47
|
chunk.forEach(item => item.status = 'U');
|
|
51
48
|
this.updateProgressStatus?.();
|
|
52
|
-
await this.
|
|
53
|
-
|
|
49
|
+
let list = await this.uploadData(this.extractData(chunk));
|
|
50
|
+
for (let j = 0; j < chunk.length; j++) {
|
|
51
|
+
this._list[i + j].status = 'D';
|
|
52
|
+
if (list[j]) {
|
|
53
|
+
if (list[j].error) {
|
|
54
|
+
this._list[i + j].error = list[j].error;
|
|
55
|
+
this._list[i + j].errorText = list[j].errorText;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
this.updateProgressStatus?.();
|
|
55
60
|
}
|
|
56
61
|
}
|
package/dist/DataColumn.d.ts
CHANGED
|
@@ -2,13 +2,13 @@ import type { DataColumn as TableColumn } from "@ticatec/uniface-element/DataTab
|
|
|
2
2
|
export type ParserText = (text: string) => any;
|
|
3
3
|
export default interface DataColumn extends TableColumn {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* 字段名
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
field: string;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* 是否忽略,上传的时候不采用,仅用于前台显示
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
ignore?: boolean;
|
|
12
12
|
/**
|
|
13
13
|
* 解析函数
|
|
14
14
|
*/
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Dialog from "@ticatec/uniface-element/Dialog";
|
|
3
|
+
import type {ButtonAction, ButtonActions} from "@ticatec/uniface-element/ActionBar";
|
|
4
|
+
import DataTable, {type IndicatorColumn} from "@ticatec/uniface-element/DataTable";
|
|
5
|
+
import {getI18nText} from "@ticatec/i18n";
|
|
6
|
+
import Box from "@ticatec/uniface-element/Box"
|
|
7
|
+
import {onMount} from "svelte";
|
|
8
|
+
import type DataColumn from "./DataColumn";
|
|
9
|
+
import i18nKeys from "./i18n_resources/i18nKeys";
|
|
10
|
+
import type BaseEncodingTemplate from "./BaseEncodingTemplate";
|
|
11
|
+
|
|
12
|
+
export let title: string;
|
|
13
|
+
export let width: string = "800px";
|
|
14
|
+
export let height: string = "600px"
|
|
15
|
+
export let closeHandler: any;
|
|
16
|
+
export let template: BaseEncodingTemplate;
|
|
17
|
+
export let confirmCallback: any;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const btnChoose: ButtonAction = {
|
|
21
|
+
label: getI18nText(i18nKeys.button.open),
|
|
22
|
+
type: 'primary',
|
|
23
|
+
handler: () => {
|
|
24
|
+
uploadField.value = '';
|
|
25
|
+
uploadField.click();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const btnConfirm: ButtonAction = {
|
|
30
|
+
label: getI18nText(i18nKeys.button.confirm),
|
|
31
|
+
type: 'primary',
|
|
32
|
+
handler: ()=> {
|
|
33
|
+
confirmCallback?.(template.list);
|
|
34
|
+
closeHandler?.();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let actions: ButtonActions = [btnChoose];
|
|
39
|
+
let uploadField: any;
|
|
40
|
+
let list: Array<any> = [];
|
|
41
|
+
let filename: string;
|
|
42
|
+
|
|
43
|
+
const parseExcelFile = async (excelFile: File) => {
|
|
44
|
+
if (excelFile) {
|
|
45
|
+
filename = excelFile.name;
|
|
46
|
+
window.Indicator.show(getI18nText(i18nKeys.parsing));
|
|
47
|
+
try {
|
|
48
|
+
await template.parseExcelFile(excelFile);
|
|
49
|
+
list = template.list;
|
|
50
|
+
if (template.valid) {
|
|
51
|
+
actions = [btnConfirm, ...actions]
|
|
52
|
+
}
|
|
53
|
+
} catch (ex) {
|
|
54
|
+
window.Toast.show(getI18nText(i18nKeys.parseFailure, {name: excelFile.name}));
|
|
55
|
+
} finally {
|
|
56
|
+
window.Indicator.hide();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
let columns: Array<DataColumn>;
|
|
63
|
+
|
|
64
|
+
onMount(async () => {
|
|
65
|
+
columns = template.columns;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const indicatorColumn: IndicatorColumn = {
|
|
70
|
+
width: 40,
|
|
71
|
+
selectable: false,
|
|
72
|
+
displayNo: true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<Dialog {title} {closeHandler} {actions}
|
|
79
|
+
content$style="width: {width}; height: {height}; padding: 12px;">
|
|
80
|
+
<Box style="border: 1px solid var(--uniface-editor-border-color, #F8FAFC); width: 100%; height: 100%; "
|
|
81
|
+
round>
|
|
82
|
+
<DataTable style="width: 100%; height: 100%" {list} {indicatorColumn} {columns}>
|
|
83
|
+
|
|
84
|
+
</DataTable>
|
|
85
|
+
</Box>
|
|
86
|
+
<input type="file" bind:this={uploadField} on:change={(e) => parseExcelFile(e.target.files?.[0])} style="display: none"
|
|
87
|
+
accept=".xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
|
|
88
|
+
|
|
89
|
+
</Dialog>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type BaseEncodingTemplate from "./BaseEncodingTemplate";
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const EncodingWizard: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
title: string;
|
|
17
|
+
width?: string;
|
|
18
|
+
height?: string;
|
|
19
|
+
closeHandler: any;
|
|
20
|
+
template: BaseEncodingTemplate;
|
|
21
|
+
confirmCallback: any;
|
|
22
|
+
}, {
|
|
23
|
+
[evt: string]: CustomEvent<any>;
|
|
24
|
+
}, {}, {}, string>;
|
|
25
|
+
type EncodingWizard = InstanceType<typeof EncodingWizard>;
|
|
26
|
+
export default EncodingWizard;
|
|
@@ -2,21 +2,19 @@
|
|
|
2
2
|
import Dialog from "@ticatec/uniface-element/Dialog";
|
|
3
3
|
import type {ButtonAction, ButtonActions} from "@ticatec/uniface-element/ActionBar";
|
|
4
4
|
import DataTable, {type IndicatorColumn} from "@ticatec/uniface-element/DataTable";
|
|
5
|
-
import
|
|
5
|
+
import {getI18nText} from "@ticatec/i18n";
|
|
6
6
|
import Box from "@ticatec/uniface-element/Box"
|
|
7
7
|
import {onMount} from "svelte";
|
|
8
|
-
import type
|
|
9
|
-
import type DataColumn from "@ticatec/uniface-element/DataTable";
|
|
8
|
+
import type DataColumn from "./DataColumn";
|
|
10
9
|
import i18nKeys from "./i18n_resources/i18nKeys";
|
|
11
10
|
import type BaseUploadTemplate from "./BaseUploadTemplate.js";
|
|
12
11
|
|
|
13
12
|
export let title: string;
|
|
14
|
-
|
|
15
13
|
export let width: string = "800px";
|
|
16
14
|
export let height: string = "600px"
|
|
17
|
-
|
|
18
15
|
export let closeHandler: any;
|
|
19
16
|
export let template: BaseUploadTemplate;
|
|
17
|
+
export let afterUploaded: ()=>Promise<void>;
|
|
20
18
|
|
|
21
19
|
type ProcessStatus = 'Init' | 'Pending' | 'Uploading' | 'Done'; //初始状态,待上传,上传中,处理完成
|
|
22
20
|
|
|
@@ -27,6 +25,7 @@
|
|
|
27
25
|
label: getI18nText(i18nKeys.button.open),
|
|
28
26
|
type: 'primary',
|
|
29
27
|
handler: () => {
|
|
28
|
+
uploadField.value = '';
|
|
30
29
|
uploadField.click();
|
|
31
30
|
}
|
|
32
31
|
}
|
|
@@ -38,6 +37,7 @@
|
|
|
38
37
|
status = 'Uploading';
|
|
39
38
|
try {
|
|
40
39
|
await template.upload();
|
|
40
|
+
await afterUploaded?.();
|
|
41
41
|
} finally {
|
|
42
42
|
status = 'Done';
|
|
43
43
|
}
|
|
@@ -58,16 +58,18 @@
|
|
|
58
58
|
let filename: string;
|
|
59
59
|
|
|
60
60
|
const parseExcelFile = async (excelFile: File) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
if (excelFile) {
|
|
62
|
+
filename = excelFile.name;
|
|
63
|
+
window.Indicator.show(getI18nText(i18nKeys.parsing));
|
|
64
|
+
try {
|
|
65
|
+
await template.parseExcelFile(excelFile);
|
|
66
|
+
list = template.list;
|
|
67
|
+
status = list.length > 0 ? 'Pending' : 'Init';
|
|
68
|
+
} catch (ex) {
|
|
69
|
+
window.Toast.show(getI18nText(i18nKeys.parseFailure, {name: excelFile.name}));
|
|
70
|
+
} finally {
|
|
71
|
+
window.Indicator.hide();
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -84,7 +86,7 @@
|
|
|
84
86
|
|
|
85
87
|
|
|
86
88
|
const indicatorColumn: IndicatorColumn = {
|
|
87
|
-
width:
|
|
89
|
+
width: 40,
|
|
88
90
|
selectable: false,
|
|
89
91
|
displayNo: true
|
|
90
92
|
}
|
|
@@ -13,9 +13,14 @@ declare const langRes: {
|
|
|
13
13
|
upload: string;
|
|
14
14
|
save: string;
|
|
15
15
|
open: string;
|
|
16
|
+
confirm: string;
|
|
16
17
|
};
|
|
17
18
|
errorTitle: string;
|
|
18
19
|
sheetName: string;
|
|
20
|
+
labelStatus: string;
|
|
21
|
+
labelValid: string;
|
|
22
|
+
textValid: string;
|
|
23
|
+
textInvalid: string;
|
|
19
24
|
};
|
|
20
25
|
};
|
|
21
26
|
export default langRes;
|