@gct-paas/render-web 0.1.6-dev.19 → 0.1.6-dev.20
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/dist/index.min.css +1 -1
- package/dist/loader.esm.min.js +3 -2
- package/es/components/collapse-detail/components/collapse-list.vue_vue_type_script_setup_true_lang.mjs +2 -2
- package/es/components/collapse-detail/index.vue.d.ts +9 -1
- package/es/components/collapse-detail/index.vue.mjs +2 -2
- package/es/components/collapse-detail/index.vue_vue_type_script_setup_true_name_collapse-detail_lang.mjs +4 -3
- package/es/components/collapse-detail/{index.vue_vue_type_style_index_0_scoped_53e7e2bf_lang.css → index.vue_vue_type_style_index_0_scoped_b4b9903c_lang.css} +19 -19
- package/es/components/field-search-cascader/field-cascader.vue.d.ts +17 -0
- package/es/components/field-search-cascader/field-cascader.vue.mjs +8 -0
- package/es/components/field-search-cascader/field-cascader.vue_vue_type_script_setup_true_lang.mjs +297 -0
- package/es/components/field-search-cascader/field-cascader.vue_vue_type_style_index_0_scoped_cb5e4d67_lang.css +52 -0
- package/es/components/field-search-cascader/field-cascader.vue_vue_type_style_index_1_lang.css +3 -0
- package/es/components/field-search-cascader/index.d.ts +2 -0
- package/es/components/field-search-cascader/index.mjs +1 -0
- package/es/components/index.d.ts +2 -0
- package/es/components/index.mjs +4 -0
- package/es/components/rich-editor/index.d.ts +2 -0
- package/es/components/rich-editor/index.mjs +1 -0
- package/es/components/rich-editor/rich-editor.vue.d.ts +22 -0
- package/es/components/rich-editor/rich-editor.vue.mjs +5 -0
- package/es/components/rich-editor/rich-editor.vue_vue_type_script_setup_true_lang.mjs +150 -0
- package/es/components/rich-editor/style.css +747 -0
- package/es/constants/xlsx-parser.d.ts +15 -0
- package/es/constants/xlsx-parser.mjs +58 -0
- package/es/enums/xlsx-parser.d.ts +293 -0
- package/es/enums/xlsx-parser.mjs +36 -0
- package/es/index.d.ts +1 -0
- package/es/index.mjs +5 -1
- package/es/interface/xlsx-parser/base.d.ts +151 -0
- package/es/interface/xlsx-parser/index.d.ts +246 -0
- package/es/types/shims-modules.d.ts +11 -0
- package/es/utils/cell-border.d.ts +73 -0
- package/es/utils/cell-border.mjs +203 -0
- package/es/utils/index.d.ts +1 -0
- package/es/utils/index.mjs +1 -0
- package/es/utils/xlsx-parser.d.ts +141 -0
- package/es/utils/xlsx-parser.mjs +262 -0
- package/package.json +16 -11
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { FIELD_TYPE_BUSINESS } from "../enums/xlsx-parser.mjs";
|
|
2
|
+
import { DefaultPaper, FIELD_PROP_LABEL_MAP, FIELD_TYPE_LABEL_MAP } from "../constants/xlsx-parser.mjs";
|
|
3
|
+
import { CellBorder } from "./cell-border.mjs";
|
|
4
|
+
import { FIELD_TYPE, FIELD_TYPE_TRACE, t } from "@gct-paas/core";
|
|
5
|
+
import { cloneDeep } from "lodash-es";
|
|
6
|
+
import ExcelJs from "exceljs";
|
|
7
|
+
import toPx from "unit-to-px";
|
|
8
|
+
//#region src/utils/xlsx-parser.ts
|
|
9
|
+
var isTypeInGroup = (type, group) => group.includes(type);
|
|
10
|
+
var generateAutoFieldKey = (type, fieldGroup, keyList) => {
|
|
11
|
+
if (!isTypeInGroup(type, fieldGroup)) return;
|
|
12
|
+
const nums = keyList.filter((i) => i.startsWith(type)).map((i) => parseInt(i.match(/\d+/)?.[0] || "0", 10));
|
|
13
|
+
return `${type}_${(nums.length ? Math.max(...nums) : 0) + 1}_`;
|
|
14
|
+
};
|
|
15
|
+
var FieldPropLabels = Object.entries(FIELD_PROP_LABEL_MAP);
|
|
16
|
+
var FieldTypeLabels = Object.entries(FIELD_TYPE_LABEL_MAP);
|
|
17
|
+
var TRACE_FIELDS = Object.values(FIELD_TYPE_TRACE);
|
|
18
|
+
var BUSINESS_FIELDS = Object.values(FIELD_TYPE_BUSINESS);
|
|
19
|
+
var XlsxParser = class XlsxParser {
|
|
20
|
+
static async xlsx2json(file) {
|
|
21
|
+
const workbook = new ExcelJs.Workbook();
|
|
22
|
+
const xlsxData = await workbook.xlsx.load(file);
|
|
23
|
+
const paperSheet = workbook.getWorksheet(t("sys.onlineForm.formStyle")) || workbook.getWorksheet();
|
|
24
|
+
if (!paperSheet) return;
|
|
25
|
+
return XlsxParser.sheetToPaper(paperSheet, xlsxData);
|
|
26
|
+
}
|
|
27
|
+
static async xlsx2jsonWithFields(file, keyList) {
|
|
28
|
+
const workbook = new ExcelJs.Workbook();
|
|
29
|
+
const xlsxData = await workbook.xlsx.load(file);
|
|
30
|
+
const paperSheet = workbook.getWorksheet(t("sys.onlineForm.formStyle")) || workbook.getWorksheet();
|
|
31
|
+
const fieldSheet = workbook.getWorksheet(t("sys.onlineForm.formFields"));
|
|
32
|
+
const paper = paperSheet ? XlsxParser.sheetToPaper(paperSheet, xlsxData) : null;
|
|
33
|
+
const fields = fieldSheet ? XlsxParser.sheetToFields(fieldSheet, keyList) : null;
|
|
34
|
+
const paperFields = [];
|
|
35
|
+
paper?.cells?.forEach((row, rowIndex) => {
|
|
36
|
+
row.forEach((cell, colIndex) => {
|
|
37
|
+
console.log("cell", cell);
|
|
38
|
+
const matches = typeof cell?.value === "string" ? cell?.value?.match(/^\$\{(.+?)\}$/) : null;
|
|
39
|
+
if (!matches) return;
|
|
40
|
+
const matchKey = matches[1];
|
|
41
|
+
const fieldMeta = fields?.find((item) => item.tmpOldKey === matchKey || item.key === matchKey || item.name === matchKey);
|
|
42
|
+
if (!fieldMeta) return;
|
|
43
|
+
paperFields.push({
|
|
44
|
+
x: colIndex + 1,
|
|
45
|
+
y: rowIndex + 1,
|
|
46
|
+
fieldKey: fieldMeta.key,
|
|
47
|
+
fieldName: fieldMeta.name,
|
|
48
|
+
fieldType: fieldMeta.type
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
paper,
|
|
54
|
+
fields,
|
|
55
|
+
paperFields
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
static sheetToPaper(paperSheet, xlsxData) {
|
|
59
|
+
const SheetRowCount = Math.min(paperSheet.dimensions.bottom, 300);
|
|
60
|
+
const SheetColCount = Math.min(paperSheet.dimensions.right, 75);
|
|
61
|
+
const paper = {};
|
|
62
|
+
const { defaultRowHeight, defaultColWidth } = paperSheet.properties;
|
|
63
|
+
const defaultRowHeightPx = parseInt(toPx(`${defaultRowHeight}pt`));
|
|
64
|
+
const rows = [];
|
|
65
|
+
Array(SheetRowCount).fill("").forEach((_r, i) => {
|
|
66
|
+
const row = paperSheet._rows?.[i];
|
|
67
|
+
rows.push({ height: parseInt(toPx(`${row?.height ?? defaultRowHeight}pt`)) });
|
|
68
|
+
});
|
|
69
|
+
paper.rows = rows;
|
|
70
|
+
const cols = [];
|
|
71
|
+
Array(SheetColCount).fill("").forEach((_c, i) => {
|
|
72
|
+
const { width } = paperSheet.columns[i];
|
|
73
|
+
const _w = width ?? defaultColWidth;
|
|
74
|
+
cols.push({ width: _w === void 0 ? 80 : Math.floor(_w * toPx("ch")) });
|
|
75
|
+
});
|
|
76
|
+
paper.cols = cols;
|
|
77
|
+
const cells = Array(SheetRowCount).fill("").map(() => Array(SheetColCount).fill("").map(() => ({})));
|
|
78
|
+
Array(SheetRowCount).fill("").forEach((_, rowIndex) => {
|
|
79
|
+
if (!paperSheet._rows?.[rowIndex]) return;
|
|
80
|
+
Array(SheetColCount).fill("").forEach((_, colIndex) => {
|
|
81
|
+
const cell = paperSheet._rows?.[rowIndex]._cells?.[colIndex];
|
|
82
|
+
if (!cell) return;
|
|
83
|
+
const { alignment, fill, font } = cell.style;
|
|
84
|
+
const cellName = cell._address;
|
|
85
|
+
const cellStyle = {
|
|
86
|
+
"text-align": alignment?.horizontal ?? "left",
|
|
87
|
+
"vertical-align": alignment?.vertical ?? "middle",
|
|
88
|
+
"background-color": fill?.fgColor?.argb?.substring(2).padStart(7, "#"),
|
|
89
|
+
color: font?.color?.argb?.substring(2).padStart(7, "#"),
|
|
90
|
+
"font-size": `${font?.size < 12 ? 12 : font?.size}px`,
|
|
91
|
+
"white-space": alignment?.wrapText ? "pre-line" : void 0,
|
|
92
|
+
"line-height": "1em"
|
|
93
|
+
};
|
|
94
|
+
if (alignment?.wrapText) cellStyle["line-height"] = "1.5em";
|
|
95
|
+
cells[rowIndex][colIndex].style = cellStyle;
|
|
96
|
+
if (cellName !== cell.master.address) return;
|
|
97
|
+
let cellValue = "";
|
|
98
|
+
if (typeof cell.value !== "object") cellValue = cell.value;
|
|
99
|
+
else if (typeof cell.text !== "object") cellValue = cell.text;
|
|
100
|
+
cells[rowIndex][colIndex].value = cellValue;
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
paper.cells = cells;
|
|
104
|
+
const mergedCells = [];
|
|
105
|
+
Object.entries(paperSheet._merges ?? {}).forEach((m) => {
|
|
106
|
+
const { top: t, bottom: b, left: l, right: r } = m[1];
|
|
107
|
+
if (t > SheetRowCount || l > SheetColCount) return;
|
|
108
|
+
mergedCells.push({
|
|
109
|
+
t,
|
|
110
|
+
l,
|
|
111
|
+
b: Math.min(SheetRowCount, b),
|
|
112
|
+
r: Math.min(SheetColCount, r)
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
paper.mergedCells = mergedCells;
|
|
116
|
+
/**
|
|
117
|
+
* 抽离边框设置逻辑 与设计器中保持一致
|
|
118
|
+
*/
|
|
119
|
+
Array(SheetRowCount).fill("").forEach((_, rowIndex) => {
|
|
120
|
+
if (!paperSheet._rows?.[rowIndex]) return;
|
|
121
|
+
Array(SheetColCount).fill("").forEach((_, colIndex) => {
|
|
122
|
+
const cell = paperSheet._rows?.[rowIndex]._cells?.[colIndex];
|
|
123
|
+
if (!cell) return;
|
|
124
|
+
const { border } = cell.style;
|
|
125
|
+
if (border?.top) CellBorder.setTop(colIndex + 1, rowIndex + 1, paper);
|
|
126
|
+
if (border?.bottom) CellBorder.setBottom(colIndex + 1, rowIndex + 1, paper);
|
|
127
|
+
if (border?.left) CellBorder.setLeft(colIndex + 1, rowIndex + 1, paper);
|
|
128
|
+
if (border?.right) CellBorder.setRight(colIndex + 1, rowIndex + 1, paper);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
const medias = (xlsxData.media ?? []).map((m) => {
|
|
132
|
+
return {
|
|
133
|
+
id: Math.random().toString(36).substring(2, 10),
|
|
134
|
+
src: `data:image/${m.extension};base64,` + m.buffer.toString("base64")
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
const images = [];
|
|
138
|
+
paperSheet._media?.forEach((m) => {
|
|
139
|
+
const { imageId, range } = m;
|
|
140
|
+
const imageLayout = {
|
|
141
|
+
height: parseInt(toPx(`${(range.br.nativeRowOff - range.tl.nativeRowOff) / 914400}in`)) + (range.br.nativeRow - range.tl.nativeRow > 0 ? Array(range.br.nativeRow - range.tl.nativeRow).fill("").reduce((total, _r, i) => {
|
|
142
|
+
total = total + (paper.rows?.[i + range.tl.nativeRow]?.height ?? defaultRowHeightPx);
|
|
143
|
+
return total;
|
|
144
|
+
}, 0) : 0),
|
|
145
|
+
width: parseInt(toPx(`${(range.br.nativeColOff - range.tl.nativeColOff) / 914400}in`)) + (range.br.nativeCol - range.tl.nativeCol > 0 ? Array(range.br.nativeCol - range.tl.nativeCol).fill("").reduce((total, _c, i) => {
|
|
146
|
+
total = total + paper.cols?.[i + range.tl.nativeCol].width;
|
|
147
|
+
return total;
|
|
148
|
+
}, 0) : 0),
|
|
149
|
+
top: parseInt(toPx(`${range.tl.nativeRowOff / 914400}in`)),
|
|
150
|
+
left: parseInt(toPx(`${range.tl.nativeColOff / 914400}in`))
|
|
151
|
+
};
|
|
152
|
+
const deltaX = Array(range.tl.nativeCol).fill("").reduce((result, _i, index) => {
|
|
153
|
+
result += paper.cols?.[index]?.width ?? 0;
|
|
154
|
+
return result;
|
|
155
|
+
}, 0);
|
|
156
|
+
const deltaY = Array(range.tl.nativeRow).fill("").reduce((result, _i, index) => {
|
|
157
|
+
result += paper.rows?.[index]?.height ?? defaultRowHeightPx;
|
|
158
|
+
return result;
|
|
159
|
+
}, 0);
|
|
160
|
+
const img = {
|
|
161
|
+
id: Math.random().toString(36).substring(2, 10),
|
|
162
|
+
mediaId: medias[imageId].id,
|
|
163
|
+
layout: {
|
|
164
|
+
height: imageLayout.height,
|
|
165
|
+
width: imageLayout.width,
|
|
166
|
+
top: imageLayout.top + deltaY,
|
|
167
|
+
left: imageLayout.left + deltaX
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
images.push(img);
|
|
171
|
+
});
|
|
172
|
+
paper.medias = medias;
|
|
173
|
+
paper.images = images;
|
|
174
|
+
return {
|
|
175
|
+
...cloneDeep(DefaultPaper),
|
|
176
|
+
...paper
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 根据 sheet 内容解析字段信息
|
|
181
|
+
* @param sheet
|
|
182
|
+
* @returns
|
|
183
|
+
*/
|
|
184
|
+
static sheetToFields(sheet, keyList) {
|
|
185
|
+
const SheetRowCount = Math.min(sheet.rowCount, 300);
|
|
186
|
+
const SheetColCount = Math.min(sheet.columnCount, 10);
|
|
187
|
+
const colFieldPropMap = /* @__PURE__ */ new Map();
|
|
188
|
+
Array(SheetColCount).fill("").forEach((_, colIndex) => {
|
|
189
|
+
const cell = sheet._rows?.[0]._cells?.[colIndex];
|
|
190
|
+
const fieldProp = FieldPropLabels.find((f) => f[1] === (cell?.text ?? "").replaceAll("*", "").trim());
|
|
191
|
+
if (fieldProp) colFieldPropMap.set(colIndex, fieldProp[0]);
|
|
192
|
+
});
|
|
193
|
+
const fields = [];
|
|
194
|
+
Array(SheetRowCount).fill("").forEach((_, rowIndex) => {
|
|
195
|
+
if (rowIndex === 0) return;
|
|
196
|
+
if (!sheet._rows?.[rowIndex]) return;
|
|
197
|
+
const field = {};
|
|
198
|
+
Array(SheetColCount).fill("").forEach((_, colIndex) => {
|
|
199
|
+
const cell = sheet._rows?.[rowIndex]._cells?.[colIndex];
|
|
200
|
+
if (colFieldPropMap.has(colIndex)) field[colFieldPropMap.get(colIndex)] = cell?.text ?? "";
|
|
201
|
+
});
|
|
202
|
+
fields.push(field);
|
|
203
|
+
});
|
|
204
|
+
const cloneKeyList = [...keyList];
|
|
205
|
+
fields.forEach((f) => {
|
|
206
|
+
XlsxParser._field2Meta(f, cloneKeyList);
|
|
207
|
+
});
|
|
208
|
+
return fields;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* 字段信息转换为元数据
|
|
212
|
+
* @param field
|
|
213
|
+
*/
|
|
214
|
+
static _field2Meta(field, keyList) {
|
|
215
|
+
const { type, required } = field;
|
|
216
|
+
field.required = required === t("sys.true") ? 1 : 0;
|
|
217
|
+
const fieldType = FieldTypeLabels.find((f) => f[1] === type);
|
|
218
|
+
if (fieldType) field.type = fieldType[0];
|
|
219
|
+
else field.type = FIELD_TYPE.TEXT;
|
|
220
|
+
if (isTypeInGroup(field.type, BUSINESS_FIELDS)) {
|
|
221
|
+
field.tmpOldKey = field.key;
|
|
222
|
+
field.key = generateAutoFieldKey(field.type, BUSINESS_FIELDS, []);
|
|
223
|
+
} else if (isTypeInGroup(field.type, TRACE_FIELDS)) {
|
|
224
|
+
field.tmpOldKey = field.key;
|
|
225
|
+
const key = generateAutoFieldKey(field.type, TRACE_FIELDS, keyList);
|
|
226
|
+
field.key = key;
|
|
227
|
+
keyList.push(key);
|
|
228
|
+
}
|
|
229
|
+
field.uniqueConstraint = { type: field.uniqueConstraint === t("sys.true") ? "GLOBAL" : "NONE" };
|
|
230
|
+
field.disabled = field.disabled === t("sys.true") ? 1 : 0;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* @param paper 导入的纸张数据
|
|
234
|
+
* @param range 最大显示范围
|
|
235
|
+
* @param mode 缩放模式 x: 横向 y: 纵向
|
|
236
|
+
*/
|
|
237
|
+
static contentFitToPaper(paper, range, mode = "x") {
|
|
238
|
+
const contentWidth = paper?.cols.reduce((total, item) => {
|
|
239
|
+
total += item.width;
|
|
240
|
+
return total;
|
|
241
|
+
}, 0);
|
|
242
|
+
const contentHeight = paper?.rows.reduce((total, item) => {
|
|
243
|
+
total += item.height;
|
|
244
|
+
return total;
|
|
245
|
+
}, 0);
|
|
246
|
+
const viewportWidth = parseInt(toPx(range[0]));
|
|
247
|
+
const viewportHeight = parseInt(toPx(range[1]));
|
|
248
|
+
const xRatio = contentWidth / viewportWidth;
|
|
249
|
+
const yRatio = contentHeight / viewportHeight;
|
|
250
|
+
const maxRatio = mode === "x" ? xRatio : Math.max(xRatio, yRatio);
|
|
251
|
+
if (maxRatio > 1) {
|
|
252
|
+
paper.cols.forEach((item) => {
|
|
253
|
+
item.width = item.width / maxRatio;
|
|
254
|
+
});
|
|
255
|
+
paper.rows.forEach((item) => {
|
|
256
|
+
item.height = item.height / maxRatio;
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
//#endregion
|
|
262
|
+
export { XlsxParser };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gct-paas/render-web",
|
|
3
|
-
"version": "0.1.6-dev.
|
|
3
|
+
"version": "0.1.6-dev.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "paas 平台网页端底包",
|
|
6
6
|
"loader": "dist/loader.esm.min.js",
|
|
@@ -31,24 +31,29 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"author": "gct",
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@gct-paas/api": "^0.1.6-dev.11",
|
|
35
|
+
"@vueuse/core": "^14.1.0",
|
|
36
|
+
"@wangeditor/editor-for-vue": "^5.1.12",
|
|
34
37
|
"ant-design-vue": "~3.2.20",
|
|
35
38
|
"colord": "^2.9.3",
|
|
36
39
|
"exceljs": "^4.4.0",
|
|
37
40
|
"lodash-es": "^4.17.23",
|
|
41
|
+
"unit-to-px": "^1.0.5",
|
|
38
42
|
"vue": "^3.5.30",
|
|
39
|
-
"@gct-paas/core
|
|
40
|
-
"@gct-paas/core": "0.1.6-dev.
|
|
41
|
-
"@gct-paas/render": "0.1.6-dev.
|
|
42
|
-
"@gct-paas/schema": "0.1.6-dev.
|
|
43
|
-
"@gct-paas/scss": "0.1.6-dev.
|
|
43
|
+
"@gct-paas/core": "0.1.6-dev.20",
|
|
44
|
+
"@gct-paas/core-web": "0.1.6-dev.20",
|
|
45
|
+
"@gct-paas/render": "0.1.6-dev.20",
|
|
46
|
+
"@gct-paas/schema": "0.1.6-dev.20",
|
|
47
|
+
"@gct-paas/scss": "0.1.6-dev.20"
|
|
44
48
|
},
|
|
45
49
|
"peerDependencies": {
|
|
50
|
+
"@gct-paas/api": "^0.1.6-dev.11",
|
|
46
51
|
"vue": ">=3",
|
|
47
|
-
"@gct-paas/
|
|
48
|
-
"@gct-paas/
|
|
49
|
-
"@gct-paas/schema": "0.1.6-dev.
|
|
50
|
-
"@gct-paas/core
|
|
51
|
-
"@gct-paas/scss": "0.1.6-dev.
|
|
52
|
+
"@gct-paas/core-web": "0.1.6-dev.20",
|
|
53
|
+
"@gct-paas/render": "0.1.6-dev.20",
|
|
54
|
+
"@gct-paas/schema": "0.1.6-dev.20",
|
|
55
|
+
"@gct-paas/core": "0.1.6-dev.20",
|
|
56
|
+
"@gct-paas/scss": "0.1.6-dev.20"
|
|
52
57
|
},
|
|
53
58
|
"devDependencies": {
|
|
54
59
|
"@types/lodash-es": "^4.17.12"
|