mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
Merge pull request #6823 from nwind/feat-export-excel-color-background-color
feat: export-excel 支持文字颜色及背景色 Closes #6174
This commit is contained in:
commit
75c90ad630
@ -158,7 +158,8 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'engine.name',
|
name: 'engine.name',
|
||||||
label: '引擎'
|
label: '引擎',
|
||||||
|
className: 'text-primary'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'browser',
|
name: 'browser',
|
||||||
@ -170,9 +171,11 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'engine.version',
|
name: 'engine.version',
|
||||||
label: 'CSS版本',
|
label: '引擎版本',
|
||||||
type: 'tpl',
|
type: 'tpl',
|
||||||
tpl: '<b>${engine.version}</b>'
|
tpl: '<b>${engine.version}</b>',
|
||||||
|
classNameExpr:
|
||||||
|
"<%= data.engine.version > 4 ? 'bg-green-100' : 'bg-red-50' %>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'grade',
|
name: 'grade',
|
||||||
|
@ -15,10 +15,8 @@ import {
|
|||||||
import {isPureVariable, resolveVariableAndFilter} from 'amis-core';
|
import {isPureVariable, resolveVariableAndFilter} from 'amis-core';
|
||||||
import {BaseSchema} from '../../Schema';
|
import {BaseSchema} from '../../Schema';
|
||||||
import {toDataURL, getImageDimensions} from 'amis-core';
|
import {toDataURL, getImageDimensions} from 'amis-core';
|
||||||
import {TplSchema} from '../Tpl';
|
import memoize from 'lodash/memoize';
|
||||||
import {MappingSchema} from '../Mapping';
|
|
||||||
import {getSnapshot} from 'mobx-state-tree';
|
import {getSnapshot} from 'mobx-state-tree';
|
||||||
import {DateSchema} from '../Date';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import type {TableProps, ExportExcelToolbar} from './index';
|
import type {TableProps, ExportExcelToolbar} from './index';
|
||||||
|
|
||||||
@ -38,6 +36,123 @@ const getAbsoluteUrl = (function () {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
interface CellStyleFont {
|
||||||
|
name?: string;
|
||||||
|
color?: {argb: string};
|
||||||
|
underline?: boolean;
|
||||||
|
bold?: boolean;
|
||||||
|
italic?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CellStyleFill {
|
||||||
|
type?: string;
|
||||||
|
pattern?: string;
|
||||||
|
fgColor?: {argb: string};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CellStyle {
|
||||||
|
font?: CellStyleFont;
|
||||||
|
fill?: CellStyleFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 computedStyle 的 rgba 转成 argb hex
|
||||||
|
*/
|
||||||
|
const rgba2argb = memoize((rgba: string) => {
|
||||||
|
const color = `${rgba
|
||||||
|
.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/)!
|
||||||
|
.slice(1)
|
||||||
|
.map((n, i) =>
|
||||||
|
(i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n))
|
||||||
|
.toString(16)
|
||||||
|
.padStart(2, '0')
|
||||||
|
.replace('NaN', '')
|
||||||
|
)
|
||||||
|
.join('')}`;
|
||||||
|
if (color.length === 6) {
|
||||||
|
return 'FF' + color;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 classname 转成对应的 excel 样式,只支持字体颜色、粗细、背景色
|
||||||
|
*/
|
||||||
|
const getCellStyleByClassName = memoize((className: string): CellStyle => {
|
||||||
|
if (!className) return {};
|
||||||
|
const classNameElm = document.getElementsByClassName(className).item(0);
|
||||||
|
if (classNameElm) {
|
||||||
|
const computedStyle = getComputedStyle(classNameElm);
|
||||||
|
const font: CellStyleFont = {};
|
||||||
|
let fill: CellStyleFill = {};
|
||||||
|
if (computedStyle.color && computedStyle.color.indexOf('rgb') !== -1) {
|
||||||
|
const color = rgba2argb(computedStyle.color);
|
||||||
|
// 似乎不支持完全透明的情况,所以就不设置
|
||||||
|
if (!color.startsWith('00')) {
|
||||||
|
font['color'] = {argb: color};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (computedStyle.fontWeight && parseInt(computedStyle.fontWeight) >= 700) {
|
||||||
|
font['bold'] = true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
computedStyle.backgroundColor &&
|
||||||
|
computedStyle.backgroundColor.indexOf('rgb') !== -1
|
||||||
|
) {
|
||||||
|
const color = rgba2argb(computedStyle.backgroundColor);
|
||||||
|
if (!color.startsWith('00')) {
|
||||||
|
fill = {
|
||||||
|
type: 'pattern',
|
||||||
|
pattern: 'solid',
|
||||||
|
fgColor: {argb: color}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {font, fill};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单元格样式
|
||||||
|
*/
|
||||||
|
const applyCellStyle = (
|
||||||
|
sheetRow: any,
|
||||||
|
columIndex: number,
|
||||||
|
schema: any,
|
||||||
|
data: any
|
||||||
|
) => {
|
||||||
|
let cellStyle: CellStyle = {};
|
||||||
|
if (schema.className) {
|
||||||
|
for (const className of schema.className.split(/\s+/)) {
|
||||||
|
const style = getCellStyleByClassName(className);
|
||||||
|
if (style) {
|
||||||
|
cellStyle = {...cellStyle, ...style};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.classNameExpr) {
|
||||||
|
const classNames = filter(schema.classNameExpr, data);
|
||||||
|
if (classNames) {
|
||||||
|
for (const className of classNames.split(/\s+/)) {
|
||||||
|
const style = getCellStyleByClassName(className);
|
||||||
|
if (style) {
|
||||||
|
cellStyle = {...cellStyle, ...style};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStyle.font && Object.keys(cellStyle.font).length > 0) {
|
||||||
|
sheetRow.getCell(columIndex).font = cellStyle.font;
|
||||||
|
}
|
||||||
|
if (cellStyle.fill && Object.keys(cellStyle.fill).length > 0) {
|
||||||
|
sheetRow.getCell(columIndex).fill = cellStyle.fill;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export async function exportExcel(
|
export async function exportExcel(
|
||||||
ExcelJS: any,
|
ExcelJS: any,
|
||||||
props: TableProps,
|
props: TableProps,
|
||||||
@ -173,6 +288,8 @@ export async function exportExcel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyCellStyle(sheetRow, columIndex, column.pristine, rowData);
|
||||||
|
|
||||||
const type = (column as BaseSchema).type || 'plain';
|
const type = (column as BaseSchema).type || 'plain';
|
||||||
// TODO: 这里很多组件都是拷贝对应渲染的逻辑实现的,导致每种都得实现一遍
|
// TODO: 这里很多组件都是拷贝对应渲染的逻辑实现的,导致每种都得实现一遍
|
||||||
if ((type === 'image' || (type as any) === 'static-image') && value) {
|
if ((type === 'image' || (type as any) === 'static-image') && value) {
|
||||||
|
Loading…
Reference in New Issue
Block a user