mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-04 05:08:42 +08:00
feat: print button for descriptions
This commit is contained in:
parent
acb769b0c1
commit
b8b5940205
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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}
|
||||||
|
<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}
|
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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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' },
|
||||||
|
Loading…
Reference in New Issue
Block a user