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,12 +290,53 @@ 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(
action =>
ACTIONS.has(action.type) && (
<div className={`${action.type}-action-button action-button`}> <div className={`${action.type}-action-button action-button`}>
<Action <Action
{...restProps} {...restProps}
@ -297,7 +344,8 @@ export function Actions(props) {
schema={action} schema={action}
/> />
</div> </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,11 +107,13 @@ 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 }}
/> />
<div ref={contentRef} className={'print-content'}>
{groups.map(group => ( {groups.map(group => (
<AntdDescriptions <AntdDescriptions
// layout={'vertical'} // layout={'vertical'}
@ -156,5 +159,6 @@ export function Descriptions(props) {
</AntdDescriptions> </AntdDescriptions>
))} ))}
</div> </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' },