amis 1.8.0-beta.13 → 1.8.0-beta.15
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/WithStore.js +1 -1
- package/lib/WithStore.js.map +2 -2
- package/lib/components/DatePicker.js +3 -1
- package/lib/components/DatePicker.js.map +2 -2
- package/lib/components/Tree.js +3 -1
- package/lib/components/Tree.js.map +2 -2
- package/lib/helper.css +1 -1
- package/lib/helper.css.map +1 -1
- package/lib/index.js +1 -1
- package/lib/renderers/Date.js +6 -1
- package/lib/renderers/Date.js.map +2 -2
- package/lib/renderers/Form/TreeSelect.js.map +2 -2
- package/lib/renderers/Nav.d.ts +21 -20
- package/lib/renderers/Nav.js +8 -1
- package/lib/renderers/Nav.js.map +2 -2
- package/lib/renderers/Page.js +1 -1
- package/lib/renderers/Page.js.map +2 -2
- package/lib/renderers/Service.js +1 -1
- package/lib/renderers/Service.js.map +2 -2
- package/lib/renderers/Table/exportExcel.d.ts +6 -0
- package/lib/renderers/Table/exportExcel.js +288 -0
- package/lib/renderers/Table/exportExcel.js.map +13 -0
- package/lib/renderers/Table/index.d.ts +1 -1
- package/lib/renderers/Table/index.js +4 -251
- package/lib/renderers/Table/index.js.map +2 -2
- package/lib/themes/ang-ie11.css +18 -15
- package/lib/themes/ang.css +4 -0
- package/lib/themes/ang.css.map +1 -1
- package/lib/themes/antd-ie11.css +18 -15
- package/lib/themes/antd.css +4 -0
- package/lib/themes/antd.css.map +1 -1
- package/lib/themes/cxd-ie11.css +3 -0
- package/lib/themes/cxd.css +4 -0
- package/lib/themes/cxd.css.map +1 -1
- package/lib/themes/dark-ie11.css +18 -15
- package/lib/themes/dark.css +4 -0
- package/lib/themes/dark.css.map +1 -1
- package/lib/themes/default-ie11.css +3 -0
- package/lib/themes/default.css +4 -0
- package/lib/themes/default.css.map +1 -1
- package/lib/utils/api.js +28 -6
- package/lib/utils/api.js.map +2 -2
- package/package.json +1 -1
- package/scss/_properties.scss +1 -0
- package/scss/components/form/_date.scss +1 -0
- package/scss/helper/layout/_display.scss +1 -1
- package/sdk/ang-ie11.css +19 -15
- package/sdk/ang.css +5 -0
- package/sdk/antd-ie11.css +19 -15
- package/sdk/antd.css +5 -0
- package/sdk/barcode.js +51 -51
- package/sdk/charts.js +14 -14
- package/sdk/codemirror.js +7 -7
- package/sdk/color-picker.js +65 -65
- package/sdk/cropperjs.js +2 -2
- package/sdk/cxd-ie11.css +4 -0
- package/sdk/cxd.css +5 -0
- package/sdk/dark-ie11.css +19 -15
- package/sdk/dark.css +5 -0
- package/sdk/exceljs.js +1 -1
- package/sdk/helper.css +1 -1
- package/sdk/helper.css.map +1 -1
- package/sdk/markdown.js +69 -69
- package/sdk/papaparse.js +1 -1
- package/sdk/renderers/Form/CityDB.js +1 -1
- package/sdk/rest.js +17 -17
- package/sdk/rich-text.js +62 -62
- package/sdk/sdk-ie11.css +4 -0
- package/sdk/sdk.css +5 -0
- package/sdk/sdk.js +1269 -1267
- package/sdk/thirds/hls.js/hls.js +1 -1
- package/sdk/thirds/mpegts.js/mpegts.js +1 -1
- package/sdk/tinymce.js +57 -57
- package/src/WithStore.tsx +1 -1
- package/src/components/DatePicker.tsx +2 -1
- package/src/components/Tree.tsx +3 -1
- package/src/renderers/Date.tsx +14 -1
- package/src/renderers/Form/TreeSelect.tsx +15 -12
- package/src/renderers/Nav.tsx +7 -1
- package/src/renderers/Page.tsx +9 -2
- package/src/renderers/Service.tsx +8 -2
- package/src/renderers/Table/exportExcel.ts +289 -0
- package/src/renderers/Table/index.tsx +5 -252
- package/src/utils/api.ts +36 -10
@@ -59,6 +59,9 @@ import ColumnToggler from './ColumnToggler';
|
|
59
59
|
import {BadgeSchema} from '../../components/Badge';
|
60
60
|
import offset from '../../utils/offset';
|
61
61
|
import {getStyleNumber} from '../../utils/dom';
|
62
|
+
import {DateSchema} from '../Date';
|
63
|
+
import moment from 'moment';
|
64
|
+
import {exportExcel} from './exportExcel';
|
62
65
|
|
63
66
|
/**
|
64
67
|
* 表格列,不指定类型时默认为文本类型。
|
@@ -367,25 +370,13 @@ export interface TableProps extends RendererProps {
|
|
367
370
|
itemBadge?: BadgeSchema;
|
368
371
|
}
|
369
372
|
|
370
|
-
type ExportExcelToolbar = SchemaNode & {
|
373
|
+
export type ExportExcelToolbar = SchemaNode & {
|
371
374
|
api?: SchemaApi;
|
372
375
|
columns?: string[];
|
373
376
|
exportColumns?: any[];
|
374
377
|
filename?: string;
|
375
378
|
};
|
376
379
|
|
377
|
-
/**
|
378
|
-
* 将 url 转成绝对地址
|
379
|
-
*/
|
380
|
-
const getAbsoluteUrl = (function () {
|
381
|
-
let link: HTMLAnchorElement;
|
382
|
-
return function (url: string) {
|
383
|
-
if (!link) link = document.createElement('a');
|
384
|
-
link.href = url;
|
385
|
-
return link.href;
|
386
|
-
};
|
387
|
-
})();
|
388
|
-
|
389
380
|
export default class Table extends React.Component<TableProps, object> {
|
390
381
|
static propsList: Array<string> = [
|
391
382
|
'header',
|
@@ -2281,245 +2272,7 @@ export default class Table extends React.Component<TableProps, object> {
|
|
2281
2272
|
{
|
2282
2273
|
onAction: () => {
|
2283
2274
|
import('exceljs').then(async (ExcelJS: any) => {
|
2284
|
-
|
2285
|
-
let tmpStore;
|
2286
|
-
let filename = 'data';
|
2287
|
-
// 支持配置 api 远程获取
|
2288
|
-
if (typeof toolbar === 'object' && toolbar.api) {
|
2289
|
-
const res = await env.fetcher(toolbar.api, data);
|
2290
|
-
if (!res.data) {
|
2291
|
-
env.notify('warning', __('placeholder.noData'));
|
2292
|
-
return;
|
2293
|
-
}
|
2294
|
-
if (Array.isArray(res.data)) {
|
2295
|
-
rows = res.data;
|
2296
|
-
} else {
|
2297
|
-
rows = res.data.rows || res.data.items;
|
2298
|
-
}
|
2299
|
-
// 因为很多方法是 store 里的,所以需要构建 store 来处理
|
2300
|
-
tmpStore = TableStore.create(getSnapshot(store));
|
2301
|
-
tmpStore.initRows(rows);
|
2302
|
-
rows = tmpStore.rows;
|
2303
|
-
} else {
|
2304
|
-
rows = store.rows;
|
2305
|
-
}
|
2306
|
-
|
2307
|
-
if (typeof toolbar === 'object' && toolbar.filename) {
|
2308
|
-
filename = filter(toolbar.filename, data, '| raw');
|
2309
|
-
}
|
2310
|
-
|
2311
|
-
if (rows.length === 0) {
|
2312
|
-
env.notify('warning', __('placeholder.noData'));
|
2313
|
-
return;
|
2314
|
-
}
|
2315
|
-
|
2316
|
-
const workbook = new ExcelJS.Workbook();
|
2317
|
-
const worksheet = workbook.addWorksheet('sheet', {
|
2318
|
-
properties: {defaultColWidth: 15}
|
2319
|
-
});
|
2320
|
-
worksheet.views = [{state: 'frozen', xSplit: 0, ySplit: 1}];
|
2321
|
-
|
2322
|
-
let exportColumnNames = toolbar.columns;
|
2323
|
-
|
2324
|
-
if (isPureVariable(exportColumnNames)) {
|
2325
|
-
exportColumnNames = resolveVariableAndFilter(
|
2326
|
-
exportColumnNames,
|
2327
|
-
data,
|
2328
|
-
'| raw'
|
2329
|
-
);
|
2330
|
-
}
|
2331
|
-
|
2332
|
-
// 自定义导出列配置
|
2333
|
-
if (toolbar.exportColumns && Array.isArray(toolbar.exportColumns)) {
|
2334
|
-
columns = toolbar.exportColumns;
|
2335
|
-
}
|
2336
|
-
|
2337
|
-
const filteredColumns = exportColumnNames
|
2338
|
-
? columns.filter(column => {
|
2339
|
-
const filterColumnsNames = exportColumnNames!;
|
2340
|
-
if (
|
2341
|
-
column.name &&
|
2342
|
-
filterColumnsNames.indexOf(column.name) !== -1
|
2343
|
-
) {
|
2344
|
-
return true;
|
2345
|
-
}
|
2346
|
-
return false;
|
2347
|
-
})
|
2348
|
-
: columns;
|
2349
|
-
|
2350
|
-
const firstRowLabels = filteredColumns.map(column => {
|
2351
|
-
return column.label;
|
2352
|
-
});
|
2353
|
-
const firstRow = worksheet.getRow(1);
|
2354
|
-
firstRow.values = firstRowLabels;
|
2355
|
-
worksheet.autoFilter = {
|
2356
|
-
from: {
|
2357
|
-
row: 1,
|
2358
|
-
column: 1
|
2359
|
-
},
|
2360
|
-
to: {
|
2361
|
-
row: 1,
|
2362
|
-
column: firstRowLabels.length
|
2363
|
-
}
|
2364
|
-
};
|
2365
|
-
// 用于 mapping source 的情况
|
2366
|
-
const remoteMappingCache: any = {};
|
2367
|
-
// 数据从第二行开始
|
2368
|
-
let rowIndex = 1;
|
2369
|
-
for (const row of rows) {
|
2370
|
-
rowIndex += 1;
|
2371
|
-
const sheetRow = worksheet.getRow(rowIndex);
|
2372
|
-
let columIndex = 0;
|
2373
|
-
for (const column of filteredColumns) {
|
2374
|
-
columIndex += 1;
|
2375
|
-
const name = column.name!;
|
2376
|
-
const value = getVariable(row.data, name);
|
2377
|
-
if (
|
2378
|
-
typeof value === 'undefined' &&
|
2379
|
-
!(column as TplSchema).tpl
|
2380
|
-
) {
|
2381
|
-
continue;
|
2382
|
-
}
|
2383
|
-
// 处理合并单元格
|
2384
|
-
if (name in row.rowSpans) {
|
2385
|
-
if (row.rowSpans[name] === 0) {
|
2386
|
-
continue;
|
2387
|
-
} else {
|
2388
|
-
// start row, start column, end row, end column
|
2389
|
-
worksheet.mergeCells(
|
2390
|
-
rowIndex,
|
2391
|
-
columIndex,
|
2392
|
-
rowIndex + row.rowSpans[name] - 1,
|
2393
|
-
columIndex
|
2394
|
-
);
|
2395
|
-
}
|
2396
|
-
}
|
2397
|
-
|
2398
|
-
const type = (column as BaseSchema).type || 'plain';
|
2399
|
-
if (type === 'image' && value) {
|
2400
|
-
try {
|
2401
|
-
const imageData = await toDataURL(value);
|
2402
|
-
const imageDimensions = await getImageDimensions(imageData);
|
2403
|
-
let imageWidth = imageDimensions.width;
|
2404
|
-
let imageHeight = imageDimensions.height;
|
2405
|
-
// 限制一下图片高宽
|
2406
|
-
const imageMaxSize = 100;
|
2407
|
-
if (imageWidth > imageHeight) {
|
2408
|
-
if (imageWidth > imageMaxSize) {
|
2409
|
-
imageHeight = (imageMaxSize * imageHeight) / imageWidth;
|
2410
|
-
imageWidth = imageMaxSize;
|
2411
|
-
}
|
2412
|
-
} else {
|
2413
|
-
if (imageHeight > imageMaxSize) {
|
2414
|
-
imageWidth = (imageMaxSize * imageWidth) / imageHeight;
|
2415
|
-
imageHeight = imageMaxSize;
|
2416
|
-
}
|
2417
|
-
}
|
2418
|
-
const imageMatch = imageData.match(/data:image\/(.*);/);
|
2419
|
-
let imageExt = 'png';
|
2420
|
-
if (imageMatch) {
|
2421
|
-
imageExt = imageMatch[1];
|
2422
|
-
}
|
2423
|
-
// 目前 excel 只支持这些格式,所以其它格式直接输出 url
|
2424
|
-
if (
|
2425
|
-
imageExt != 'png' &&
|
2426
|
-
imageExt != 'jpeg' &&
|
2427
|
-
imageExt != 'gif'
|
2428
|
-
) {
|
2429
|
-
sheetRow.getCell(columIndex).value = value;
|
2430
|
-
continue;
|
2431
|
-
}
|
2432
|
-
const imageId = workbook.addImage({
|
2433
|
-
base64: imageData,
|
2434
|
-
extension: imageExt
|
2435
|
-
});
|
2436
|
-
const linkURL = getAbsoluteUrl(value);
|
2437
|
-
worksheet.addImage(imageId, {
|
2438
|
-
// 这里坐标位置是从 0 开始的,所以要减一
|
2439
|
-
tl: {col: columIndex - 1, row: rowIndex - 1},
|
2440
|
-
ext: {
|
2441
|
-
width: imageWidth,
|
2442
|
-
height: imageHeight
|
2443
|
-
},
|
2444
|
-
hyperlinks: {
|
2445
|
-
tooltip: linkURL
|
2446
|
-
}
|
2447
|
-
});
|
2448
|
-
} catch (e) {
|
2449
|
-
console.warn(e.stack);
|
2450
|
-
}
|
2451
|
-
} else if (type == 'link') {
|
2452
|
-
const linkURL = getAbsoluteUrl(value);
|
2453
|
-
sheetRow.getCell(columIndex).value = {
|
2454
|
-
text: value,
|
2455
|
-
hyperlink: linkURL
|
2456
|
-
};
|
2457
|
-
} else if (type === 'mapping') {
|
2458
|
-
// 拷贝自 Mapping.tsx
|
2459
|
-
let map = (column as MappingSchema).map;
|
2460
|
-
const source = (column as MappingSchema).source;
|
2461
|
-
if (source) {
|
2462
|
-
let sourceValue = source;
|
2463
|
-
if (isPureVariable(source)) {
|
2464
|
-
sourceValue = resolveVariableAndFilter(
|
2465
|
-
source as string,
|
2466
|
-
data,
|
2467
|
-
'| raw'
|
2468
|
-
);
|
2469
|
-
}
|
2470
|
-
|
2471
|
-
const mapKey = JSON.stringify(source);
|
2472
|
-
if (mapKey in remoteMappingCache) {
|
2473
|
-
map = remoteMappingCache[mapKey];
|
2474
|
-
} else {
|
2475
|
-
const res = await env.fetcher(sourceValue, data);
|
2476
|
-
if (res.data) {
|
2477
|
-
remoteMappingCache[mapKey] = res.data;
|
2478
|
-
map = res.data;
|
2479
|
-
}
|
2480
|
-
}
|
2481
|
-
}
|
2482
|
-
|
2483
|
-
if (
|
2484
|
-
typeof value !== 'undefined' &&
|
2485
|
-
map &&
|
2486
|
-
(map[value] ?? map['*'])
|
2487
|
-
) {
|
2488
|
-
const viewValue =
|
2489
|
-
map[value] ??
|
2490
|
-
(value === true && map['1']
|
2491
|
-
? map['1']
|
2492
|
-
: value === false && map['0']
|
2493
|
-
? map['0']
|
2494
|
-
: map['*']); // 兼容平台旧用法:即 value 为 true 时映射 1 ,为 false 时映射 0
|
2495
|
-
sheetRow.getCell(columIndex).value =
|
2496
|
-
removeHTMLTag(viewValue);
|
2497
|
-
} else {
|
2498
|
-
sheetRow.getCell(columIndex).value = removeHTMLTag(value);
|
2499
|
-
}
|
2500
|
-
} else {
|
2501
|
-
if ((column as TplSchema).tpl) {
|
2502
|
-
sheetRow.getCell(columIndex).value = removeHTMLTag(
|
2503
|
-
filter(
|
2504
|
-
(column as TplSchema).tpl,
|
2505
|
-
createObject(data, row.data)
|
2506
|
-
)
|
2507
|
-
);
|
2508
|
-
} else {
|
2509
|
-
sheetRow.getCell(columIndex).value = value;
|
2510
|
-
}
|
2511
|
-
}
|
2512
|
-
}
|
2513
|
-
}
|
2514
|
-
|
2515
|
-
const buffer = await workbook.xlsx.writeBuffer();
|
2516
|
-
|
2517
|
-
if (buffer) {
|
2518
|
-
var blob = new Blob([buffer], {
|
2519
|
-
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
2520
|
-
});
|
2521
|
-
saveAs(blob, filename + '.xlsx');
|
2522
|
-
}
|
2275
|
+
exportExcel(ExcelJS, this.props, toolbar);
|
2523
2276
|
});
|
2524
2277
|
}
|
2525
2278
|
}
|
package/src/utils/api.ts
CHANGED
@@ -12,10 +12,12 @@ import {
|
|
12
12
|
cloneObject,
|
13
13
|
createObject,
|
14
14
|
qsparse,
|
15
|
-
uuid
|
15
|
+
uuid,
|
16
|
+
JSONTraverse
|
16
17
|
} from './helper';
|
17
18
|
import isPlainObject from 'lodash/isPlainObject';
|
18
19
|
import {debug} from './debug';
|
20
|
+
import {evaluate, parse} from 'amis-formula';
|
19
21
|
|
20
22
|
const rSchema = /(?:^|raw\:)(get|post|put|delete|patch|options|head|jsonp):/i;
|
21
23
|
|
@@ -94,24 +96,48 @@ export function buildApi(
|
|
94
96
|
}
|
95
97
|
|
96
98
|
const raw = (api.url = api.url || '');
|
97
|
-
const
|
99
|
+
const ast: any = parse(api.url);
|
100
|
+
const url = ast.body
|
101
|
+
.map((item: any, index: number) => {
|
102
|
+
return item.type === 'raw' ? item.value : `__expression__${index}__`;
|
103
|
+
})
|
104
|
+
.join('');
|
105
|
+
|
106
|
+
const idx = url.indexOf('?');
|
107
|
+
let replaceExpression = (fragment: string) => {
|
108
|
+
return fragment.replace(
|
109
|
+
/__expression__(\d+)__/g,
|
110
|
+
(_: any, index: string) => {
|
111
|
+
return evaluate(ast.body[index], data, {
|
112
|
+
defaultFilter: 'url_encode'
|
113
|
+
});
|
114
|
+
}
|
115
|
+
);
|
116
|
+
};
|
98
117
|
|
99
118
|
if (~idx) {
|
100
|
-
const hashIdx =
|
119
|
+
const hashIdx = url.indexOf('#');
|
101
120
|
const params = qsparse(
|
102
|
-
|
103
|
-
idx + 1,
|
104
|
-
~hashIdx && hashIdx > idx ? hashIdx : undefined
|
105
|
-
)
|
121
|
+
url.substring(idx + 1, ~hashIdx && hashIdx > idx ? hashIdx : undefined)
|
106
122
|
);
|
123
|
+
|
124
|
+
// 将里面的表达式运算完
|
125
|
+
JSONTraverse(params, (value: any, key: string | number, host: any) => {
|
126
|
+
if (typeof value === 'string' && /^__expression__(\d+)__$/.test(value)) {
|
127
|
+
host[key] = evaluate(ast.body[RegExp.$1].body, data);
|
128
|
+
}
|
129
|
+
});
|
130
|
+
|
107
131
|
api.url =
|
108
|
-
|
132
|
+
replaceExpression(url.substring(0, idx + 1)) +
|
109
133
|
qsstringify(
|
110
134
|
(api.query = dataMapping(params, data, undefined, api.convertKeyToPath))
|
111
135
|
) +
|
112
|
-
(~hashIdx && hashIdx > idx
|
136
|
+
(~hashIdx && hashIdx > idx
|
137
|
+
? replaceExpression(url.substring(hashIdx))
|
138
|
+
: '');
|
113
139
|
} else {
|
114
|
-
api.url =
|
140
|
+
api.url = replaceExpression(url);
|
115
141
|
}
|
116
142
|
|
117
143
|
if (ignoreData) {
|