feat: print button for descriptions

This commit is contained in:
chenos 2021-04-01 21:15:51 +08:00
parent acb769b0c1
commit b8b5940205
4 changed files with 110 additions and 55 deletions

View File

@ -43,6 +43,7 @@
"react-drag-listview": "^0.1.8", "react-drag-listview": "^0.1.8",
"react-image-lightbox": "^5.1.1", "react-image-lightbox": "^5.1.1",
"react-sortable-hoc": "^1.11.0", "react-sortable-hoc": "^1.11.0",
"react-to-print": "^2.12.3",
"styled-components": "^5.2.1", "styled-components": "^5.2.1",
"umi": "^3.2.23", "umi": "^3.2.23",
"yorkie": "^2.0.0" "yorkie": "^2.0.0"

View File

@ -5,11 +5,17 @@ import {
PlusOutlined, PlusOutlined,
SelectOutlined, SelectOutlined,
DeleteOutlined, DeleteOutlined,
PrinterOutlined,
ExportOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import Drawer from '@/components/pages/AdminLoader/Drawer'; import Drawer from '@/components/pages/AdminLoader/Drawer';
import View from '@/components/pages/AdminLoader/View'; import View from '@/components/pages/AdminLoader/View';
import get from 'lodash/get'; import get from 'lodash/get';
import set from 'lodash/set'; import set from 'lodash/set';
import ReactToPrint from 'react-to-print';
import api from '@/api-client';
const ACTIONS = new Map<string, any>();
export function Create(props) { export function Create(props) {
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
@ -284,20 +290,62 @@ export function Filter(props) {
); );
} }
export function Print(props) {
const { schema = {}, contentRef } = props;
const { title, buttonProps = {} } = schema;
return (
<ReactToPrint
trigger={() => (
<Button {...buttonProps} icon={<PrinterOutlined />}>
{title}
</Button>
)}
content={() => contentRef.current}
pageStyle={`
@page {
margin: 1cm;
}
table { page-break-inside:auto }
tr { page-break-inside:avoid; page-break-after:auto }
`}
documentTitle={' '}
/>
);
}
export function Export(props) {
const { schema = {}, onFinish } = props;
const { title, buttonProps = {} } = schema;
return (
<Button
{...buttonProps}
icon={<ExportOutlined />}
onClick={async () => {
onFinish && (await onFinish({ fields: [] }));
}}
>
{title}
</Button>
);
}
export function Actions(props) { export function Actions(props) {
const { onTrigger = {}, actions = [], style, ...restProps } = props; const { onTrigger = {}, actions = [], style, ...restProps } = props;
return ( return (
actions.length > 0 && ( actions.length > 0 && (
<div className={'action-buttons'} style={style}> <div className={'action-buttons'} style={style}>
{actions.map(action => ( {actions.map(
<div className={`${action.type}-action-button action-button`}> action =>
<Action ACTIONS.has(action.type) && (
{...restProps} <div className={`${action.type}-action-button action-button`}>
onFinish={onTrigger[action.type]} <Action
schema={action} {...restProps}
/> onFinish={onTrigger[action.type]}
</div> schema={action}
))} />
</div>
),
)}
</div> </div>
) )
); );
@ -305,8 +353,6 @@ export function Actions(props) {
export default Actions; export default Actions;
const ACTIONS = new Map<string, any>();
export function registerAction(type: string, Action: any) { export function registerAction(type: string, Action: any) {
ACTIONS.set(type, Action); ACTIONS.set(type, Action);
} }
@ -328,3 +374,5 @@ registerAction('update', Update);
registerAction('create', Create); registerAction('create', Create);
registerAction('destroy', Destroy); registerAction('destroy', Destroy);
registerAction('filter', Filter); registerAction('filter', Filter);
registerAction('print', Print);
registerAction('export', Export);

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useRef } from 'react';
import './style.less'; import './style.less';
import { Helmet } from 'umi'; import { Helmet } from 'umi';
import { Spin } from '@nocobase/client'; import { Spin } from '@nocobase/client';
@ -24,7 +24,6 @@ import Field from '@/components/views/Field';
import { Form } from './Form'; import { Form } from './Form';
import { configResponsive, useResponsive } from 'ahooks'; import { configResponsive, useResponsive } from 'ahooks';
import { InfoCircleOutlined } from '@ant-design/icons'; import { InfoCircleOutlined } from '@ant-design/icons';
import scopes from '@/components/views/Form/scopes';
configResponsive({ configResponsive({
small: 0, small: 0,
@ -84,6 +83,7 @@ export function Descriptions(props) {
'fields[appends]': appends, 'fields[appends]': appends,
}); });
}); });
const contentRef = useRef();
if (loading) { if (loading) {
return <Spin />; return <Spin />;
} }
@ -97,6 +97,7 @@ export function Descriptions(props) {
}; };
} }
const groups = toGroups(fields); const groups = toGroups(fields);
return ( return (
<div> <div>
<Actions <Actions
@ -106,55 +107,58 @@ export function Descriptions(props) {
onDataChange && onDataChange(values); onDataChange && onDataChange(values);
}, },
}} }}
contentRef={contentRef}
associatedKey={associatedKey} associatedKey={associatedKey}
data={data} data={data}
actions={actions} actions={actions}
style={{ marginBottom: 14 }} style={{ marginBottom: 14 }}
/> />
{groups.map(group => ( <div ref={contentRef} className={'print-content'}>
<AntdDescriptions {groups.map(group => (
// layout={'vertical'} <AntdDescriptions
// size={'middle'} // layout={'vertical'}
// bordered // size={'middle'}
{...descriptionsProps} // bordered
title={ {...descriptionsProps}
group.title && ( title={
<span> group.title && (
{group.title}{' '} <span>
{group.tooltip && ( {group.title}{' '}
<Tooltip title={group.tooltip}> {group.tooltip && (
<Tooltip title={group.tooltip}>
<InfoCircleOutlined />
</Tooltip>
)}
</span>
)
}
column={1}
>
{group.children.map((field: any) => {
const label = field.tooltip ? (
<>
{field.title || field.name}&nbsp;
<Tooltip title={field.tooltip}>
<InfoCircleOutlined /> <InfoCircleOutlined />
</Tooltip> </Tooltip>
)} </>
</span> ) : (
) field.title || field.name
} );
column={1} return (
> <AntdDescriptions.Item label={label}>
{group.children.map((field: any) => { <Field
const label = field.tooltip ? ( data={data}
<> viewType={'descriptions'}
{field.title || field.name}&nbsp; schema={field}
<Tooltip title={field.tooltip}> value={get(data, field.name)}
<InfoCircleOutlined /> />
</Tooltip> </AntdDescriptions.Item>
</> );
) : ( })}
field.title || field.name </AntdDescriptions>
); ))}
return ( </div>
<AntdDescriptions.Item label={label}>
<Field
data={data}
viewType={'descriptions'}
schema={field}
value={get(data, field.name)}
/>
</AntdDescriptions.Item>
);
})}
</AntdDescriptions>
))}
</div> </div>
); );
} }

View File

@ -25,6 +25,8 @@ export default {
title: '操作类型', title: '操作类型',
dataSource: [ dataSource: [
{ label: '筛选', value: 'filter' }, { label: '筛选', value: 'filter' },
{ label: '打印', value: 'print' },
{ label: '导出', value: 'export' },
{ label: '新增', value: 'create' }, { label: '新增', value: 'create' },
{ label: '编辑', value: 'update' }, { label: '编辑', value: 'update' },
{ label: '删除', value: 'destroy' }, { label: '删除', value: 'destroy' },