cloud-web-corejs 1.0.54-dev.807 → 1.0.54-dev.809
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/package.json +1 -1
- package/src/components/VabUpload/image-viewer.vue +1 -1
- package/src/components/VabUpload/mixins.js +48 -15
- package/src/components/VabUpload/previewGroup.js +128 -0
- package/src/components/VabUpload/view.vue +1 -1
- package/src/components/excelExport/exportFieldDialog.vue +23 -12
- package/src/components/excelExport/exportItemConfigUtil.js +30 -0
- package/src/components/excelExport/mixins.js +3 -3
- package/src/components/table/plugins/cell-area/index.js +1055 -0
- package/src/components/table/plugins/cell-area/index.scss +77 -0
- package/src/components/table/plugins/cell-area/util.js +224 -0
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +6 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +10 -10
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/exportItemColumns-dialog.vue +7 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +51 -0
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +4 -0
- package/src/components/xform/form-render/container-item/data-table-mixin.js +118 -81
- package/src/components/xform/utils/textMaskUtil.js +6 -3
- package/src/index.js +6 -1
- package/src/utils/pdfUtil.js +130 -2
|
@@ -124,8 +124,10 @@ export function resolveTextMaskFlag(widgetOptions, ctx) {
|
|
|
124
124
|
*
|
|
125
125
|
* @param {Object} $grid vxe-grid 实例。
|
|
126
126
|
* @param {Object} ctx 判定上下文,由 buildTextMaskContext 生成。
|
|
127
|
+
* @param {Array} [exportItemColumns] 本次明细导出实际使用的列(导出按钮上单独维护时由调用方
|
|
128
|
+
* 传入);不传则回落到表格属性上配的那套。
|
|
127
129
|
*/
|
|
128
|
-
export function markMaskedExportColumns($grid, ctx) {
|
|
130
|
+
export function markMaskedExportColumns($grid, ctx, exportItemColumns) {
|
|
129
131
|
if (!$grid || typeof $grid.getTableColumn !== "function") return;
|
|
130
132
|
|
|
131
133
|
/** 打标记。列本就被其它规则(isNonDataExportColumn)剔除时不接管,避免撤销时误删。 */
|
|
@@ -174,6 +176,7 @@ export function markMaskedExportColumns($grid, ctx) {
|
|
|
174
176
|
}
|
|
175
177
|
};
|
|
176
178
|
let originOption = $grid.params?.originOption;
|
|
177
|
-
let
|
|
178
|
-
exportItemColumns
|
|
179
|
+
let tableItemColumns = originOption?.exportItemConfig?.columns;
|
|
180
|
+
let itemColumns = exportItemColumns || tableItemColumns || [];
|
|
181
|
+
itemColumns.forEach(markItemColumn);
|
|
179
182
|
}
|
package/src/index.js
CHANGED
|
@@ -28,7 +28,12 @@ Vue.component("BaseKeepAlive", BaseKeepAlive);
|
|
|
28
28
|
import VXETable from "vxe-table";
|
|
29
29
|
import "vxe-table/lib/style.css";
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// 区域选取/复制粘贴:自研实现,通过 window.VXETableMixin 挂载,
|
|
32
|
+
// 必须在下面的 Vue.use(VXETable) 之前求值(core 在 install 时读取一次并 delete)
|
|
33
|
+
import "@base/components/table/plugins/cell-area/index.js";
|
|
34
|
+
import "@base/components/table/plugins/cell-area/index.scss";
|
|
35
|
+
|
|
36
|
+
// 引入扩展插件(官方付费插件,已由上面的自研 cell-area 替代,保留仅作回退参考)
|
|
32
37
|
// import "@base/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.es6.min.js";
|
|
33
38
|
// import "@base/components/table/plugins/extend-cell-area/vxe-table-extend-cell-area.min.css";
|
|
34
39
|
|
package/src/utils/pdfUtil.js
CHANGED
|
@@ -106,6 +106,132 @@ function pickScale(width, height, expected) {
|
|
|
106
106
|
return Math.max(scale, 1);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
//Safari(WebKit) 的 getComputedStyle 会把颜色序列化成 color(srgb …) / color(display-p3 …),
|
|
110
|
+
//而 html2canvas 1.4.1 只认 rgb/rgba/hsl/hsla 四种,撞上就抛
|
|
111
|
+
//"Attempting to parse an unsupported color function" 直接整个导出失败。
|
|
112
|
+
//项目源码里并没有写过 color(),是浏览器自己吐出来的,改样式没用——只能在克隆体上就地换算。
|
|
113
|
+
const COLOR_FUNCTION = /color\([^()]*\)/g;
|
|
114
|
+
|
|
115
|
+
//html2canvas 会按颜色解析的属性(format: 'color'),外加三个值里可能夹着颜色的:
|
|
116
|
+
//渐变、阴影里的 color() 一样会把解析器打挂。
|
|
117
|
+
const COLOR_PROPS = [
|
|
118
|
+
"color",
|
|
119
|
+
"background-color",
|
|
120
|
+
"border-top-color",
|
|
121
|
+
"border-right-color",
|
|
122
|
+
"border-bottom-color",
|
|
123
|
+
"border-left-color",
|
|
124
|
+
"text-decoration-color",
|
|
125
|
+
"-webkit-text-stroke-color",
|
|
126
|
+
"background-image",
|
|
127
|
+
"box-shadow",
|
|
128
|
+
"text-shadow",
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
//探针色:用来判断 canvas 到底认没认这个值(不认的话 fillStyle 会保持原样)
|
|
132
|
+
const PROBE_COLOR = "#010203";
|
|
133
|
+
|
|
134
|
+
function isWebKit() {
|
|
135
|
+
const ua = typeof navigator === "undefined" ? "" : navigator.userAgent || "";
|
|
136
|
+
//Chrome 系的 UA 里也有 AppleWebKit 字样,但它不会这么序列化,得排掉
|
|
137
|
+
return /AppleWebKit/.test(ua) && !/Chrome|Chromium|Edg\//.test(ua);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function probeContext() {
|
|
141
|
+
try {
|
|
142
|
+
const canvas = document.createElement("canvas");
|
|
143
|
+
return typeof canvas.getContext === "function" ? canvas.getContext("2d") : null;
|
|
144
|
+
} catch (err) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function toByte(raw) {
|
|
150
|
+
const num = parseFloat(raw);
|
|
151
|
+
if (isNaN(num)) return 0;
|
|
152
|
+
const ratio = raw.indexOf("%") === -1 ? num : num / 100;
|
|
153
|
+
return Math.max(0, Math.min(255, Math.round(ratio * 255)));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function toAlpha(raw) {
|
|
157
|
+
const num = parseFloat(raw);
|
|
158
|
+
if (isNaN(num)) return 1;
|
|
159
|
+
const alpha = raw.indexOf("%") === -1 ? num : num / 100;
|
|
160
|
+
return Math.max(0, Math.min(1, alpha));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//浏览器不肯换算时的兜底:按 sRGB 直接取分量。
|
|
164
|
+
//display-p3 这样算是近似(色域没做映射),但截图里看不出差别,总好过整个导出失败。
|
|
165
|
+
function fallbackColor(value) {
|
|
166
|
+
const inside = value.slice(value.indexOf("(") + 1, value.lastIndexOf(")"));
|
|
167
|
+
const parts = inside.split("/");
|
|
168
|
+
//第一段是色彩空间名(srgb / display-p3 …),分量从第二段开始
|
|
169
|
+
const numbers = parts[0].trim().split(/\s+/).slice(1);
|
|
170
|
+
const channels = [0, 1, 2].map((i) => toByte(numbers[i] || "0"));
|
|
171
|
+
const alpha = parts.length > 1 ? toAlpha(parts[1]) : 1;
|
|
172
|
+
return "rgba(" + channels.join(", ") + ", " + alpha + ")";
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function toLegacyColor(value, ctx) {
|
|
176
|
+
return value.replace(COLOR_FUNCTION, (match) => {
|
|
177
|
+
//优先让浏览器自己换:它认识 color(),换出来的 sRGB 值是准的
|
|
178
|
+
if (ctx) {
|
|
179
|
+
ctx.fillStyle = PROBE_COLOR;
|
|
180
|
+
ctx.fillStyle = match;
|
|
181
|
+
const converted = ctx.fillStyle;
|
|
182
|
+
const usable = typeof converted === "string" && converted.indexOf("color(") === -1;
|
|
183
|
+
if (usable && converted !== PROBE_COLOR) return converted;
|
|
184
|
+
}
|
|
185
|
+
return fallbackColor(match);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
//在 html2canvas 的克隆体上把 color() 全部换成 rgba(),写成内联样式(优先级最高)。
|
|
190
|
+
//只在需要时才挂上去:这一趟要给每个节点再算一次样式,白跑一遍就是白卡一下。
|
|
191
|
+
export function normalizeColorFunctions(clonedDoc, clonedElement) {
|
|
192
|
+
const view = clonedDoc.defaultView;
|
|
193
|
+
if (!view || typeof view.getComputedStyle !== "function") return;
|
|
194
|
+
const ctx = probeContext();
|
|
195
|
+
const targets = [];
|
|
196
|
+
//除了目标元素,html2canvas 还会读 html/body 的背景色(parseBackgroundColor),一起带上
|
|
197
|
+
if (clonedDoc.documentElement) targets.push(clonedDoc.documentElement);
|
|
198
|
+
if (clonedDoc.body) targets.push(clonedDoc.body);
|
|
199
|
+
targets.push(clonedElement);
|
|
200
|
+
const children = clonedElement.querySelectorAll("*");
|
|
201
|
+
for (let i = 0; i < children.length; i++) targets.push(children[i]);
|
|
202
|
+
|
|
203
|
+
for (let i = 0; i < targets.length; i++) {
|
|
204
|
+
const el = targets[i];
|
|
205
|
+
if (!el || !el.style) continue;
|
|
206
|
+
const style = view.getComputedStyle(el);
|
|
207
|
+
for (let j = 0; j < COLOR_PROPS.length; j++) {
|
|
208
|
+
const prop = COLOR_PROPS[j];
|
|
209
|
+
const value = style.getPropertyValue(prop);
|
|
210
|
+
if (!value || value.indexOf("color(") === -1) continue;
|
|
211
|
+
el.style.setProperty(prop, toLegacyColor(value, ctx));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function isUnsupportedColorError(err) {
|
|
217
|
+
const message = err && err.message ? err.message : String(err || "");
|
|
218
|
+
return message.indexOf("unsupported color function") !== -1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function withColorFix(options) {
|
|
222
|
+
return Object.assign({}, options, { onclone: normalizeColorFunctions });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function renderCanvas(dom, options, fixColors) {
|
|
226
|
+
try {
|
|
227
|
+
return await html2canvas(dom, fixColors ? withColorFix(options) : options);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
//别的引擎哪天也开始这么序列化,兜一次;已经带着换算跑过就别再重来了
|
|
230
|
+
if (fixColors || !isUnsupportedColorError(err)) throw err;
|
|
231
|
+
return html2canvas(dom, withColorFix(options));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
109
235
|
function buildIgnore(selectors) {
|
|
110
236
|
let list = [LOADING_MASK];
|
|
111
237
|
if (selectors) list = list.concat(selectors);
|
|
@@ -273,7 +399,7 @@ export async function exportPDF(option) {
|
|
|
273
399
|
//只能靠文案说明进度,真要更快就得降 scale 或少截点内容。
|
|
274
400
|
if (loading) loading.setText("正在渲染页面,请稍候…");
|
|
275
401
|
await nextFrame();
|
|
276
|
-
const
|
|
402
|
+
const options = {
|
|
277
403
|
backgroundColor: "#ffffff",
|
|
278
404
|
useCORS: true,
|
|
279
405
|
logging: false,
|
|
@@ -285,7 +411,9 @@ export async function exportPDF(option) {
|
|
|
285
411
|
windowWidth: Math.max(document.documentElement.clientWidth, fullWidth),
|
|
286
412
|
windowHeight: fullHeight + 200,
|
|
287
413
|
ignoreElements: buildIgnore(option.ignoreSelectors),
|
|
288
|
-
}
|
|
414
|
+
};
|
|
415
|
+
//WebKit 上直接带着颜色换算跑:先失败一次再重来,等于把那几秒的冻结再来一遍
|
|
416
|
+
const canvas = await renderCanvas(dom, options, isWebKit());
|
|
289
417
|
await canvasToPdf(canvas, fileName, loading);
|
|
290
418
|
return true;
|
|
291
419
|
} catch (err) {
|