Commit a9c60907 authored by 彭俊龙's avatar 彭俊龙

fix: 自定义导出单据模板

parent 0a982f46
/*
* @Author: ZengJing
* @Date: 2024-02-04 10:01:59
* @LastEditTime: 2024-02-04 10:10:35
* @LastEditors: ZengJing
* @Description:
* @FilePath: \xform\src\core\Account\components\ExportTemplate\index.js
*/
import Receipt from './receipt'
export {
Receipt
}
\ No newline at end of file
/*
* @Author: ZengJing
* @Date: 2024-02-04 09:39:21
* @LastEditTime: 2024-02-04 17:27:27
* @LastEditors: ZengJing
* @Description:
* @FilePath: \xform\src\core\Account\components\ExportTemplate\Receipt.js
*/
import React, { useState, useImperativeHandle, forwardRef, useMemo, useRef } from 'react';
import styles from './receipt.less';
import moment from 'moment';
const Receipt = props => {
moment.locale('zh-cn');
const { dataList, title } = props;
const arr = ['坐标', '地址', '图片'];
const dataSource =
dataList?.length > 0
? dataList.map((x, index) => {
return {
id: x.id,
webRow: x.webRow.filter((v, i) => {
if (!arr.some(n => v.shape.includes(n))) {
return v;
}
}),
};
})
: null;
const columnCount = dataSource?.length > 0 ? dataSource[0].webRow.length + 1 : 0;
const footRows = ['记账', '保管', '验收', '提货人', '制单'];
const splitOddNumber = oddNumber => {
if (oddNumber % 2 !== 1) {
[oddNumber / 2, oddNumber / 2];
}
const firstNumber = Math.floor(oddNumber / 2);
const secondNumber = firstNumber + 1;
return [firstNumber, secondNumber];
};
return (
<>
<div className={styles.content}>
<table>
<tr>
<th colSpan={columnCount} className={styles.headerTxt}>
<span>{title}</span>
</th>
</tr>
<tr>
<th colSpan={splitOddNumber(columnCount)[0]} className={styles.headerLeft}>
单位:
</th>
<th colSpan={splitOddNumber(columnCount)[1]} className={styles.headerRight}>
日期:{moment().format('LL')}
</th>
</tr>
<tr>
<th>序号</th>
{dataSource?.length > 0 ? dataSource[0].webRow.map((x, index) => <th>{x.fieldName}</th>) : null}
</tr>
{dataSource?.length > 0
? dataSource.map((x, index) => (
<tr>
<td>{index + 1}</td>
{x.webRow.map((v, i) => (
<td>{v.fieldValue}</td>
))}
</tr>
))
: null}
<tr>
<td>合计</td>
{dataSource?.length > 0 ? dataSource[0].webRow.map((x, index) => <td></td>) : null}
</tr>
<tr>
{dataSource?.length > 0
? dataSource[0].webRow.map((x, i) => {
if (footRows.length >= i + 1) {
return <td>{footRows[i]}</td>;
} else {
return <td></td>;
}
})
: null}
<td></td>
</tr>
</table>
</div>
</>
);
};
export default Receipt;
.content{
width: auto;
height: auto;
}
table {
border-collapse: collapse; /* 合并单元格边框 */
width: 100%;
}
th, td {
border-bottom: 1px solid #ddd; /* 添加底部边框 */
padding: 8px;
text-align: center;
font-size: 13px;
}
.headerLeft{
text-align: left !important;
font-weight: bold;
}
.headerRight{
text-align: right !important;
font-weight: bold;
}
.headerTxt{
padding: 5px;
text-align: center;
font-size: 13px;
border: none !important;
span{
border-bottom: 1px solid gray;
font-weight: bold;
width: auto;
}
}
\ No newline at end of file
...@@ -18,7 +18,7 @@ const SearchGroup = forwardRef((props, ref) => { ...@@ -18,7 +18,7 @@ const SearchGroup = forwardRef((props, ref) => {
})) }))
const { accountName, config, notUse, checkName, btnsClick, keys } = props const { accountName, config, notUse, checkName, btnsClick, keys } = props
const { enableBatchOperation, enableImportExport, enablePrint, enableQuickSearch, enableTimeFilter, parent, accountFieids } = config const { enableBatchOperation, enableImportExport, exportTemplateName, enablePrint, enableQuickSearch, enableTimeFilter, parent, accountFieids } = config
const [form] = Form.useForm() const [form] = Form.useForm()
const [dateArray, setDateArray] = useState([]) const [dateArray, setDateArray] = useState([])
const [formatterStr, setFormatterStr] = useState('YYYY-MM-DD HH:mm:ss') const [formatterStr, setFormatterStr] = useState('YYYY-MM-DD HH:mm:ss')
...@@ -265,7 +265,21 @@ const SearchGroup = forwardRef((props, ref) => { ...@@ -265,7 +265,21 @@ const SearchGroup = forwardRef((props, ref) => {
</Button> </Button>
), ),
key: '导出全字段数据', key: '导出全字段数据',
} },
exportTemplateName ? {
label: (
<Button
style={{ width: '100%', textAlign: 'left' }}
size='middle'
type='text'
onClick={() => btnsClick({ type: '导出单据' })}
icon={<ExportOutlined />}
>
导出单据
</Button>
),
key: '导出单据',
}: null
] ]
const onSearch = e => { const onSearch = e => {
......
import React, { useEffect, useRef, useState, useImperativeHandle, forwardRef } from 'react' import React, { useEffect, useRef, useState, useImperativeHandle, forwardRef } from 'react';
import styles from './index.less' import styles from './index.less';
import { message, Button, Pagination, Modal, Input, Tree } from 'antd' import { message, Button, Pagination, Modal, Input, Tree, Space, Dropdown, Menu } from 'antd';
import { DownOutlined } from '@ant-design/icons' import { DownOutlined, ExceptionOutlined } from '@ant-design/icons';
import { ExclamationCircleOutlined } from '@ant-design/icons' import {
import SearchGroup from './components/SearchGroup' ExclamationCircleOutlined,
import TablePack from './components/TablePack' FileExcelOutlined,
import BatchEdit from './components/BatchEdit' FileImageOutlined,
FilePdfOutlined,
FileWordOutlined,
} from '@ant-design/icons';
import SearchGroup from './components/SearchGroup';
import TablePack from './components/TablePack';
import BatchEdit from './components/BatchEdit';
import { Receipt } from './components/ExportTemplate';
import { import {
GetAccountConfigInfo, GetAccountConfigInfo,
GetAccountTree, GetAccountTree,
...@@ -16,9 +23,15 @@ import { ...@@ -16,9 +23,15 @@ import {
DeleteTableDataInfo, DeleteTableDataInfo,
ExportAccountData, ExportAccountData,
ExportAccountModel, ExportAccountModel,
} from '../../apis/process' } from '../../apis/process';
import { isJson, isObject } from '../../utils/index' import { isJson, isObject } from '../../utils/index';
import FormRender from '../FormRender' import exportStyle from './components/ExportTemplate/receipt.less';
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
import { exportWord } from 'mhtml-to-word';
import { saveAs } from 'file-saver';
import FormRender from '../FormRender';
import { set } from 'lodash';
const initConfig = { const initConfig = {
accountFieids: [], accountFieids: [],
...@@ -29,18 +42,15 @@ const initConfig = { ...@@ -29,18 +42,15 @@ const initConfig = {
enableQuickSearch: 0, //快捷搜索 enableQuickSearch: 0, //快捷搜索
enableSiteFilter: 0, //站点过滤 enableSiteFilter: 0, //站点过滤
enableTimeFilter: 0, //时间筛选 enableTimeFilter: 0, //时间筛选
} };
const Account = (props, ref) => { const Account = (props, ref) => {
useImperativeHandle(ref, () => ({
getTableColumns,
}));
useImperativeHandle(ref, () => ( const { accountName, parentConfig, notUse, superAccount } = props;
{ const userID = window?.globalConfig?.userInfo?.OID || 1;
getTableColumns
}
))
const { accountName, parentConfig, notUse, superAccount } = props
const userID = window?.globalConfig?.userInfo?.OID || 1
const initParams = { const initParams = {
user: userID, user: userID,
accountName, accountName,
...@@ -52,65 +62,68 @@ const Account = (props, ref) => { ...@@ -52,65 +62,68 @@ const Account = (props, ref) => {
timeFrom: '', timeFrom: '',
timeTo: '', timeTo: '',
queryWheres: [], queryWheres: [],
} };
const [treeShow, setTreeShow] = useState(true) const [treeShow, setTreeShow] = useState(true);
const [treeData, setTreeData] = useState([]) const [treeData, setTreeData] = useState([]);
const [expandedKeys, setExpandedKeys] = useState([]) const [expandedKeys, setExpandedKeys] = useState([]);
const [treeValue, setTreeValue] = useState([accountName]) const [treeValue, setTreeValue] = useState([accountName]);
const [detailShow, setDetailShow] = useState(false) const [detailShow, setDetailShow] = useState(false);
const [params, setParams] = useState(initParams) const [params, setParams] = useState(initParams);
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const [dataSource, setDataSource] = useState([]) const [dataSource, setDataSource] = useState([]);
const [config, setConfig] = useState(initConfig) const [dataList, setDataList] = useState([]);
const [configLoading, setConfigLoading] = useState(true) const [config, setConfig] = useState(initConfig);
const [schemaValues, setSchemaValues] = useState({ formJson: {}, values: [] }) const [configLoading, setConfigLoading] = useState(true);
const [submitLoading, setSubmitLoading] = useState(false) const [schemaValues, setSchemaValues] = useState({ formJson: {}, values: [] });
const [operation, setOperation] = useState({ id: null, state: '添加' }) const [submitLoading, setSubmitLoading] = useState(false);
const [keys, setKeys] = useState([]) const [operation, setOperation] = useState({ id: null, state: '添加' });
const formRenderRef = useRef(null) const [keys, setKeys] = useState([]);
const tablePackRef = useRef(null) const [exportCase, setExportCase] = useState([]);
const batchEditRef = useRef(null) const [openPreview, setOpenPreview] = useState(false);
const formRenderRef = useRef(null);
const tablePackRef = useRef(null);
const batchEditRef = useRef(null);
const getTableColumns = () => { const getTableColumns = () => {
return tablePackRef?.current?.fileColumns || [] return tablePackRef?.current?.fileColumns || [];
} };
const btnsClick = async ({ type, row }) => { const btnsClick = async ({ type, row }) => {
const { accountFieids, formJson } = config const { accountFieids, formJson } = config;
const addField = accountFieids.filter(v => v.isAdd).map(v => v.fieldName) const addField = accountFieids.filter(v => v.isAdd).map(v => v.fieldName);
const editField = accountFieids.filter(v => v.isEdit).map(v => v.fieldName) const editField = accountFieids.filter(v => v.isEdit).map(v => v.fieldName);
if (type === '添加') { if (type === '添加') {
setOperation({ type, id: null }) setOperation({ type, id: null });
saveClick(addField, formJson, [], type) saveClick(addField, formJson, [], type);
} }
if (type === '重置') { if (type === '重置') {
tablePackRef.current.setFilteredInfo({}) tablePackRef.current.setFilteredInfo({});
tablePackRef.current.setSortedInfo({}) tablePackRef.current.setSortedInfo({});
setParams(initParams) setParams(initParams);
getDataSource(initParams) getDataSource(initParams);
} }
if (type === '编辑' || type === '详情') { if (type === '编辑' || type === '详情') {
setOperation({ type, id: row.ID }) setOperation({ type, id: row.ID });
const { code, data, msg } = await GetTableDataInfo({ accountName, id: row.ID }) const { code, data, msg } = await GetTableDataInfo({ accountName, id: row.ID });
if (code === 0) { if (code === 0) {
saveClick(editField, formJson, data, type) saveClick(editField, formJson, data, type);
} else { } else {
message.error(msg) message.error(msg);
} }
} }
if (type === '删除') { if (type === '删除') {
setOperation({ type, id: row.ID }) setOperation({ type, id: row.ID });
const { code, data, msg } = await DeleteTableDataInfo({ accountTable: accountName, ids: row.ID }) const { code, data, msg } = await DeleteTableDataInfo({ accountTable: accountName, ids: row.ID });
if (code === 0) { if (code === 0) {
message.success('删除成功!') message.success('删除成功!');
getDataSource() getDataSource();
} else { } else {
message.error(msg) message.error(msg);
} }
} }
if (type === '批量删除') { if (type === '批量删除') {
if (!keys.length) { if (!keys.length) {
return message.info('请勾选要删除的数据!') return message.info('请勾选要删除的数据!');
} }
Modal.confirm({ Modal.confirm({
icon: <ExclamationCircleOutlined />, icon: <ExclamationCircleOutlined />,
...@@ -119,32 +132,47 @@ const Account = (props, ref) => { ...@@ -119,32 +132,47 @@ const Account = (props, ref) => {
cancelText: '取消', cancelText: '取消',
onOk: async () => { onOk: async () => {
return await new Promise(async (resolve, reject) => { return await new Promise(async (resolve, reject) => {
const { code, data, msg } = await DeleteTableDataInfo({ accountTable: accountName, ids: keys.join(',') }) const { code, data, msg } = await DeleteTableDataInfo({ accountTable: accountName, ids: keys.join(',') });
if (code === 0) { if (code === 0) {
message.success('批量删除成功!') message.success('批量删除成功!');
getDataSource() getDataSource();
resolve() resolve();
} else { } else {
message.error(msg) message.error(msg);
reject() reject();
} }
}) });
}, },
}) });
} }
if (type === '批量修改') { if (type === '批量修改') {
if (!keys.length) { if (!keys.length) {
return message.info('请勾选要修改的数据!') return message.info('请勾选要修改的数据!');
} }
batchEditRef.current.open({ accountTable: accountName, id: keys.join(','), }) batchEditRef.current.open({ accountTable: accountName, id: keys.join(',') });
} }
if (['导出数据', '导出全字段数据'].includes(type)) { if (['导出数据', '导出全字段数据'].includes(type)) {
exportData({ exportAll: type === '导出全字段数据' }) exportData({ exportAll: type === '导出全字段数据' });
} }
if (['导出模板', '导出全字段模板'].includes(type)) { if (['导出模板', '导出全字段模板'].includes(type)) {
exportTemplate({ exportAll: type === '导出全字段模板' }) exportTemplate({ exportAll: type === '导出全字段模板' });
}
if (type === '导出单据') {
if (!keys.length) {
return message.info('请勾选要导出的数据!');
} }
if (!['入库单', '出库单'].includes(config.exportTemplateName)) {
return message.info('未找到可使用的单据模板!');
} }
const filterData = dataList.filter((x, i) => {
if (keys.includes(String(x.id))) {
return x;
}
});
setExportCase(filterData || []);
setOpenPreview(true);
}
};
const exportData = ({ exportAll }) => { const exportData = ({ exportAll }) => {
Modal.confirm({ Modal.confirm({
...@@ -152,213 +180,352 @@ const Account = (props, ref) => { ...@@ -152,213 +180,352 @@ const Account = (props, ref) => {
content: keys.length > 0 ? `共选择${keys.length}条数据,确定要导出吗` : '确定要导出全部数据吗?', content: keys.length > 0 ? `共选择${keys.length}条数据,确定要导出吗` : '确定要导出全部数据吗?',
onOk: async () => { onOk: async () => {
return await new Promise(async (resolve, reject) => { return await new Promise(async (resolve, reject) => {
const blob = await ExportAccountData({ accountName: accountName, ids: keys.join(','), exportAll }) const blob = await ExportAccountData({ accountName: accountName, ids: keys.join(','), exportAll });
const reader = new FileReader(); const reader = new FileReader();
reader.onload = function () { reader.onload = function() {
const text = reader.result; const text = reader.result;
if (text?.includes('code')) { if (text?.includes('code')) {
let obj = JSON.parse(text) let obj = JSON.parse(text);
message.error(obj.msg) message.error(obj.msg);
reject() reject();
} else { } else {
const url = window.URL.createObjectURL(new Blob([blob])) const url = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement('a') const a = document.createElement('a');
a.href = url a.href = url;
a.target = '_blank' a.target = '_blank';
a.download = '数据文件.xls' a.download = '数据文件.xls';
a.click() a.click();
a.remove() a.remove();
resolve() resolve();
} }
}; };
reader.onerror = function (error) { reader.onerror = function(error) {
console.error('Error reading the blob', error); console.error('Error reading the blob', error);
}; };
reader.readAsText(blob, 'UTF-8'); // 指定编码 reader.readAsText(blob, 'UTF-8'); // 指定编码
}) });
}, },
okText: '确定', okText: '确定',
cancelText: '取消', cancelText: '取消',
}) });
} };
const exportTemplate = async ({ exportAll }) => { const exportTemplate = async ({ exportAll }) => {
let res = await ExportAccountModel({ accountName: accountName, exportAll }) let res = await ExportAccountModel({ accountName: accountName, exportAll });
if (res && res.code === -1) { if (res && res.code === -1) {
message.error(res.msg) message.error(res.msg);
reject() reject();
} else { } else {
const url = window.URL.createObjectURL(new Blob([res])) const url = window.URL.createObjectURL(new Blob([res]));
const a = document.createElement('a') const a = document.createElement('a');
a.href = url a.href = url;
a.target = '_blank' a.target = '_blank';
a.download = '模板文件.xls' a.download = '模板文件.xls';
a.click() a.click();
a.remove() a.remove();
resolve() resolve();
}
} }
};
const saveClick = (field, formJson, values, type) => { const saveClick = (field, formJson, values, type) => {
let json = JSON.parse(JSON.stringify(formJson)) let json = JSON.parse(JSON.stringify(formJson));
let parent = json?.properties let parent = json?.properties;
if (isObject(parent)) { if (isObject(parent)) {
for (let v in parent) { for (let v in parent) {
let hidden = true let hidden = true;
let child = parent[v]?.properties let child = parent[v]?.properties;
if (isObject(child)) { if (isObject(child)) {
for (let s in child) { for (let s in child) {
if (type === '详情') { if (type === '详情') {
child[s].disabled = true child[s].disabled = true;
} }
if (field.includes(s)) { if (field.includes(s)) {
child[s].hidden = false child[s].hidden = false;
hidden = false hidden = false;
} else { } else {
child[s].hidden = true child[s].hidden = true;
} }
} }
} }
parent[v].hidden = hidden parent[v].hidden = hidden;
} }
} }
setSchemaValues({ formJson: json, values }) setSchemaValues({ formJson: json, values });
setDetailShow(true) setDetailShow(true);
} };
const back = () => { const back = () => {
setDetailShow(false) setDetailShow(false);
getDataSource() getDataSource();
} };
const submit = async () => { const submit = async () => {
const { formValue, relationForm, errors } = await formRenderRef.current.getValues() const { formValue, relationForm, errors } = await formRenderRef.current.getValues();
if (errors.length) { if (errors.length) {
return message.error('请完善表单内容') return message.error('请完善表单内容');
} }
const { type, id } = operation const { type, id } = operation;
setSubmitLoading(true) setSubmitLoading(true);
if (type === '添加') { if (type === '添加') {
let params = { userID, accountTable: accountName, id: operation.id, values: formValue, relationForm } let params = { userID, accountTable: accountName, id: operation.id, values: formValue, relationForm };
const { code, data, msg } = await SaveTableDataInfo(params) const { code, data, msg } = await SaveTableDataInfo(params);
if (code === 0) { if (code === 0) {
message.success('保存成功!') message.success('保存成功!');
setDetailShow(false) setDetailShow(false);
getDataSource() getDataSource();
} else { } else {
message.error(msg) message.error(msg);
} }
} }
if (type === '编辑') { if (type === '编辑') {
let params = { userID, accountTable: accountName, id: operation.id, values: formValue, relationForm } let params = { userID, accountTable: accountName, id: operation.id, values: formValue, relationForm };
const { code, data, msg } = await EditTableDataInfo(params) const { code, data, msg } = await EditTableDataInfo(params);
if (code === 0) { if (code === 0) {
message.success('修改成功!') message.success('修改成功!');
setSubmitLoading(false) setSubmitLoading(false);
setDetailShow(false) setDetailShow(false);
getDataSource() getDataSource();
} else { } else {
message.error(msg) message.error(msg);
}
} }
setSubmitLoading(false)
} }
setSubmitLoading(false);
};
const search = (values) => { const search = values => {
getDataSource({ ...values }) getDataSource({ ...values });
} };
const getConfig = async ({ accountName }) => { const getConfig = async ({ accountName }) => {
setConfigLoading(true) setConfigLoading(true);
const { code, data, msg } = await GetAccountConfigInfo(accountName) const { code, data, msg } = await GetAccountConfigInfo(accountName);
if (code === 0) { if (code === 0) {
setConfig({ ...data, formJson: isJson(data.formJson) ? JSON.parse(data.formJson) : {} }) setConfig({ ...data, formJson: isJson(data.formJson) ? JSON.parse(data.formJson) : {} });
setParams({ ...params, pageSize: data.pageSize || 20 }) setParams({ ...params, pageSize: data.pageSize || 20 });
getDataSource({ siteFilter: Boolean(data.enableSiteFilter), accountName, pageSize: data.pageSize || 20 }) getDataSource({ siteFilter: Boolean(data.enableSiteFilter), accountName, pageSize: data.pageSize || 20 });
} else { } else {
message.error(msg) message.error(msg);
}
setConfigLoading(false)
} }
setConfigLoading(false);
};
const getDataSource = async (param = {}) => { const getDataSource = async (param = {}) => {
setLoading(true) setLoading(true);
const { code, data, msg } = await GetAccountPageList({ ...params, ...param }) const { code, data, msg } = await GetAccountPageList({ ...params, ...param });
if (code === 0) { if (code === 0) {
setDataSource(isJson(data.jsonData) ? JSON.parse(data.jsonData) : []) setDataSource(isJson(data.jsonData) ? JSON.parse(data.jsonData) : []);
setParams({ ...params, ...param, total: data.totalCount, pageIndex: data.pageIndex, pageSize: data.pageSize }) setDataList(data.list);
setParams({ ...params, ...param, total: data.totalCount, pageIndex: data.pageIndex, pageSize: data.pageSize });
} else { } else {
setDataSource([]) setDataSource([]);
message.error(msg) setDataList([]);
} message.error(msg);
setLoading(false)
} }
setLoading(false);
};
const pageChange = (pageIndex, pageSize) => { const pageChange = (pageIndex, pageSize) => {
getDataSource({ pageIndex, pageSize }) getDataSource({ pageIndex, pageSize });
} };
const tableChange = (page, filters, sorter) => { const tableChange = (page, filters, sorter) => {
let queryWheres = [] let queryWheres = [];
Object.keys(filters).forEach(k => { Object.keys(filters).forEach(k => {
if (filters[k]?.[0]) { if (filters[k]?.[0]) {
queryWheres.push({ field: k, type: '模糊查询', value: filters[k].join(',') }) queryWheres.push({ field: k, type: '模糊查询', value: filters[k].join(',') });
} }
}) });
let param = { let param = {
sortFields: sorter.order ? sorter.field : '录入时间', sortFields: sorter.order ? sorter.field : '录入时间',
direction: sorter.order !== 'ascend' ? 'desc' : 'asc', direction: sorter.order !== 'ascend' ? 'desc' : 'asc',
queryWheres queryWheres,
} };
setParams({ ...params, ...param }) setParams({ ...params, ...param });
getDataSource(param) getDataSource(param);
} };
const batchEditOk = () => { const batchEditOk = () => {
setKeys([]) setKeys([]);
getDataSource() getDataSource();
} };
const treeChange = (value) => { const treeChange = value => {
if (value.length) { if (value.length) {
setTreeValue(value) setTreeValue(value);
getConfig({ accountName: value[0] }) getConfig({ accountName: value[0] });
}
} }
};
const getTree = async () => { const getTree = async () => {
const { code, data, msg } = await GetAccountTree(superAccount) const { code, data, msg } = await GetAccountTree(superAccount);
if (code === 0) { if (code === 0) {
setExpandedKeys([data.accountName]) setExpandedKeys([data.accountName]);
setTreeData([data]) setTreeData([data]);
} else { } else {
message.error(msg) message.error(msg);
}
} }
};
useEffect(() => { useEffect(() => {
if (parentConfig) { if (parentConfig) {
setConfig(parentConfig) setConfig(parentConfig);
getDataSource({ siteFilter: Boolean(parentConfig.enableSiteFilter) }) getDataSource({ siteFilter: Boolean(parentConfig.enableSiteFilter) });
} else { } else {
getConfig({ accountName }) getConfig({ accountName });
}
getTree();
}, []);
const items = (
<Menu>
<Menu.Item onClick={() => toExcel('content', '单据')} icon={<FileExcelOutlined />}>
导出Excel
</Menu.Item>
<Menu.Item onClick={() => toImage('content', '单据')} icon={<FileImageOutlined />}>
导出图片
</Menu.Item>
<Menu.Item onClick={() => topdf('content', '单据')} icon={<FilePdfOutlined />}>
导出PDF
</Menu.Item>
<Menu.Item onClick={() => toWrod('content', '单据')} icon={<FileWordOutlined />}>
导出Word
</Menu.Item>
</Menu>
);
const toImage = (id, fileName) => {
const canvasEle = document.getElementsByClassName(id)[1];
html2canvas(canvasEle, {
scale: 1, //缩放
}).then(canvas => {
//处理你生成的canvas
// document.body.appendChild(canvas);
let a = document.createElement('a');
a.setAttribute('href', canvas.toDataURL()); //toDataUrl:将canvas画布信息转化为base64格式图片
a.setAttribute('download', fileName); //这个是必须的,否则会报错
a.setAttribute('target', '_self');
a.click();
});
};
const getModelHtml = (mhtml, style) => {
return `
Content-Type: text/html; charset="utf-8"
<!DOCTYPE html>
<html>
<head>
<style>
${style}
</style>
</head>
<body>
${mhtml}
</body>
</html>
`;
};
const topdf = async (id, title) => {
const ele = document.getElementsByClassName(id)[1];
// 根据dpi放大,防止图片模糊
const scale = 1; // window.devicePixelRatio > 1 ? window.devicePixelRatio : 2;
// 下载尺寸 a4 纸 比例
let pdf = new jsPDF('p', 'pt', 'a4');
let width = ele.offsetWidth;
let height = ele.offsetHeight;
const canvas = document.createElement('canvas');
canvas.width = width * scale;
canvas.height = height * scale;
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一页pdf显示html页面生成的canvas高度;
var pageHeight = (contentWidth / 592.28) * 841.89;
//未生成pdf的html页面高度
var leftHeight = contentHeight;
//页面偏移
var position = 0;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = (592.28 / contentWidth) * contentHeight;
const pdfCanvas = await html2canvas(ele, {
useCORS: true,
canvas,
scale,
width,
height,
x: 0,
y: 0,
});
const imgDataUrl = pdfCanvas.toDataURL();
if (height > 14400) {
// 超出jspdf高度限制时
const ratio = 14400 / height;
// height = 14400;
width = width * ratio;
} }
getTree()
}, [])
// 缩放为 a4 大小 pdfpdf.internal.pageSize 获取当前pdf设定的宽高
height = (height * pdf.internal.pageSize.getWidth()) / width;
width = pdf.internal.pageSize.getWidth();
if (leftHeight < pageHeight) {
pdf.addImage(imgDataUrl, 'png', 0, 0, imgWidth, imgHeight);
} else {
// 分页
while (leftHeight > 0) {
pdf.addImage(imgDataUrl, 'png', 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
// 导出下载
await pdf.save(`${title}.pdf`);
};
const toWrod = (id, fileName) => {
var table = document.getElementsByClassName(id)[1].outerHTML;
let html = getModelHtml(table, exportStyle);
let blob = new Blob([html], { type: 'application/msword;charset=utf-8' });
// 调用FileSaver.saveAs导出下载word
saveAs(blob, `${fileName}.doc`);
};
const toExcel = (id, name) => {
var table = document.getElementsByClassName(id)[1].outerHTML;
var exportFileContent =
'<html xmlns:x="urn:schemas-microsoft-com:office:excel"><head><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>' +
'sheet' +
'</x:Name><x:WorksheetOptions><x:Print><x:ValidPrinterInfo /></x:Print></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml></head>' +
table +
'</html>';
var blob = new Blob([exportFileContent], { type: 'text/plain;charset=utf-8' });
blob = new Blob([String.fromCharCode(0xfeff), blob], { type: blob.type });
var link = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = name + '.xls';
a.href = link;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
return ( return (
<div className={styles.account}> <div className={styles.account}>
<div className={styles.tableRender} style={{ display: !detailShow ? 'block' : 'none' }}> <div className={styles.tableRender} style={{ display: !detailShow ? 'block' : 'none' }}>
<div className={styles.content}> <div className={styles.content}>
{ {superAccount ? (
superAccount ? (
<div <div
style={{ style={{
width: treeShow ? '236px' : '0', width: treeShow ? '236px' : '0',
}} }}
className={styles.left} className={styles.left}
> >
<div className={styles['t-header']} style={{ padding: treeShow ? '5px 10px' : '0' }}>台账列表</div> <div className={styles['t-header']} style={{ padding: treeShow ? '5px 10px' : '0' }}>
台账列表
</div>
<Tree <Tree
style={{ overflow: 'hidden' }} style={{ overflow: 'hidden' }}
checkable checkable
...@@ -366,7 +533,7 @@ const Account = (props, ref) => { ...@@ -366,7 +533,7 @@ const Account = (props, ref) => {
showIcon showIcon
blockNode blockNode
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
onExpand={(expandedKeys) => setExpandedKeys(expandedKeys)} onExpand={expandedKeys => setExpandedKeys(expandedKeys)}
fieldNames={{ title: 'accountName', key: 'accountName', children: 'children' }} fieldNames={{ title: 'accountName', key: 'accountName', children: 'children' }}
switcherIcon={<DownOutlined />} switcherIcon={<DownOutlined />}
checkedKeys={treeValue} checkedKeys={treeValue}
...@@ -375,8 +542,7 @@ const Account = (props, ref) => { ...@@ -375,8 +542,7 @@ const Account = (props, ref) => {
/> />
<div className={styles.shrink} type={`${treeShow}`} onClick={() => setTreeShow(!treeShow)}></div> <div className={styles.shrink} type={`${treeShow}`} onClick={() => setTreeShow(!treeShow)}></div>
</div> </div>
) : null ) : null}
}
<div className={styles.right} style={{ width: superAccount && treeShow ? 'calc(100% - 250px)' : '100%' }}> <div className={styles.right} style={{ width: superAccount && treeShow ? 'calc(100% - 250px)' : '100%' }}>
<div className={styles.top}> <div className={styles.top}>
<SearchGroup <SearchGroup
...@@ -389,8 +555,7 @@ const Account = (props, ref) => { ...@@ -389,8 +555,7 @@ const Account = (props, ref) => {
/> />
</div> </div>
<div className={styles.bottom}> <div className={styles.bottom}>
{ {!configLoading ? (
!configLoading ? (
<TablePack <TablePack
loading={loading} loading={loading}
notUse={notUse} notUse={notUse}
...@@ -400,14 +565,13 @@ const Account = (props, ref) => { ...@@ -400,14 +565,13 @@ const Account = (props, ref) => {
type: 'checkbox', type: 'checkbox',
selectedRowKeys: keys, selectedRowKeys: keys,
fixed: 'left', fixed: 'left',
onChange: (keys) => setKeys(keys) onChange: keys => setKeys(keys),
}} }}
btnsClick={btnsClick} btnsClick={btnsClick}
tableChange={tableChange} tableChange={tableChange}
ref={tablePackRef} ref={tablePackRef}
/> />
) : null ) : null}
}
</div> </div>
<div className={styles.footer}> <div className={styles.footer}>
<div className={styles.total}>共计{params.total}条数据</div> <div className={styles.total}>共计{params.total}条数据</div>
...@@ -425,21 +589,16 @@ const Account = (props, ref) => { ...@@ -425,21 +589,16 @@ const Account = (props, ref) => {
</div> </div>
<BatchEdit config={config} ref={batchEditRef} onOk={batchEditOk} /> <BatchEdit config={config} ref={batchEditRef} onOk={batchEditOk} />
</div> </div>
{ {detailShow ? (
detailShow ? (
<div className={styles.tableDetail}> <div className={styles.tableDetail}>
<div className={styles.formBox}> <div className={styles.formBox}>
<FormRender ref={formRenderRef} schemaValues={schemaValues} /> <FormRender ref={formRenderRef} schemaValues={schemaValues} />
</div> </div>
<div className={styles.formBtns}> <div className={styles.formBtns}>
<Button <Button onClick={back}>返回</Button>
onClick={back}
>
返回
</Button>
<Button <Button
style={{ marginLeft: '10px', display: ['添加', '编辑'].includes(operation.type) ? 'block' : 'none' }} style={{ marginLeft: '10px', display: ['添加', '编辑'].includes(operation.type) ? 'block' : 'none' }}
type='primary' type="primary"
loading={submitLoading} loading={submitLoading}
onClick={submit} onClick={submit}
> >
...@@ -447,11 +606,36 @@ const Account = (props, ref) => { ...@@ -447,11 +606,36 @@ const Account = (props, ref) => {
</Button> </Button>
</div> </div>
</div> </div>
) : null ) : null}
} <Modal
width={'80%'}
visible={openPreview}
title="导出预览"
onCancel={() => setOpenPreview(false)}
footer={[
<Button
key="back"
onClick={() => setOpenPreview(false)}
style={{
marginRight: '10px',
}}
>
取消
</Button>,
<Dropdown key="export" overlay={items}>
<Button>
<Space>
导出类型
<DownOutlined />
</Space>
</Button>
</Dropdown>,
]}
>
{['入库单', '出库单'].includes(config.exportTemplateName) ? <Receipt dataList={exportCase} title={config.exportTemplateName} /> : null}
</Modal>
</div> </div>
) );
};
}
export default forwardRef(Account) export default forwardRef(Account);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment