263 lines
7.8 KiB
Vue
263 lines
7.8 KiB
Vue
|
|
<template>
|
||
|
|
<a-modal
|
||
|
|
v-model:visible="visible"
|
||
|
|
title="打印预览"
|
||
|
|
width="100%"
|
||
|
|
wrap-class-name="full-modal"
|
||
|
|
:bodyStyle="{ padding: '10px' }"
|
||
|
|
@cancel="emits('update:isShowPrint', false)"
|
||
|
|
>
|
||
|
|
<div class="btn-box">
|
||
|
|
<a-button style="color: #606266; font-size: 13px" @click="handlePrint">
|
||
|
|
<template #icon>
|
||
|
|
<PrinterOutlined />
|
||
|
|
</template>
|
||
|
|
打印
|
||
|
|
</a-button>
|
||
|
|
</div>
|
||
|
|
<div v-if="printData?.style === '1' && !!configs?.formProps">
|
||
|
|
<SimpleForm
|
||
|
|
class="print-style1-box"
|
||
|
|
:formProps="configs?.formProps"
|
||
|
|
:formModel="configs?.formModel"
|
||
|
|
:isWorkFlow="true"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div :class="`print-style${props.printData?.style}-box`" v-else>
|
||
|
|
<template v-for="(item, index) in formInfo" :key="index">
|
||
|
|
<TableStyle :item="item" :componentType="item.type" />
|
||
|
|
</template>
|
||
|
|
</div>
|
||
|
|
</a-modal>
|
||
|
|
</template>
|
||
|
|
<script lang="ts" setup>
|
||
|
|
import { ref, computed, Ref, StyleValue, provide, inject, onMounted } from 'vue';
|
||
|
|
import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
|
||
|
|
import TableStyle from './TableStyle.vue';
|
||
|
|
import { getUserMulti } from '/@/api/system/user';
|
||
|
|
import { getDicItemDetail } from '/@/api/system/dic';
|
||
|
|
import { getDepartment } from '/@/api/system/department';
|
||
|
|
import { getAreaMulti } from '/@/api/system/area';
|
||
|
|
import { PrinterOutlined } from '@ant-design/icons-vue';
|
||
|
|
import { buildComponentType } from '/@/utils/helper/designHelper';
|
||
|
|
import html2canvas from 'html2canvas';
|
||
|
|
import printJS from 'print-js';
|
||
|
|
import { cloneDeep, isNil } from 'lodash-es';
|
||
|
|
import domtoimage from 'dom-to-image';
|
||
|
|
const props = defineProps({
|
||
|
|
formConfigs: Object,
|
||
|
|
printData: Object,
|
||
|
|
isShowPrint: Boolean,
|
||
|
|
});
|
||
|
|
|
||
|
|
const emits = defineEmits(['update:isShowPrint']);
|
||
|
|
const configs = ref({
|
||
|
|
formProps: {} as any,
|
||
|
|
formModel: {},
|
||
|
|
});
|
||
|
|
const formInfo = ref<any>([]);
|
||
|
|
const activeKey = inject<Ref<number>>('tabActiveKey');
|
||
|
|
const visible = ref<boolean>(props.isShowPrint);
|
||
|
|
const borderColorStyle = computed(() => {
|
||
|
|
return { 'border-color': `${props.printData?.borderColor} !important` };
|
||
|
|
});
|
||
|
|
const underlineStyle = computed(() => {
|
||
|
|
return { 'border-bottom': props.printData?.underline === '1' ? '1px solid' : 0 };
|
||
|
|
});
|
||
|
|
|
||
|
|
provide<Ref<StyleValue>>('borderColorStyle', borderColorStyle);
|
||
|
|
provide<Ref<StyleValue>>('underlineStyle', underlineStyle);
|
||
|
|
onMounted(async () => {
|
||
|
|
configs.value.formProps = cloneDeep(props.formConfigs?.formProps);
|
||
|
|
formInfo.value = [];
|
||
|
|
if (props.printData?.style !== '1') {
|
||
|
|
await changeFormat(configs.value.formProps.schemas, formInfo.value);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
configs.value.formModel = cloneDeep(props.formConfigs?.formModel);
|
||
|
|
|
||
|
|
const handlePrint = async () => {
|
||
|
|
let element: HTMLElement = window.document.querySelector(
|
||
|
|
`.print-style${props.printData?.style || 1}-box`,
|
||
|
|
)!;
|
||
|
|
|
||
|
|
let url;
|
||
|
|
if (props.printData?.style === '1') {
|
||
|
|
url = await domtoimage.toPng(element);
|
||
|
|
} else {
|
||
|
|
let canvas = await html2canvas(element, {
|
||
|
|
backgroundColor: null,
|
||
|
|
useCORS: true,
|
||
|
|
windowHeight: document.body.scrollHeight,
|
||
|
|
});
|
||
|
|
url = canvas.toDataURL();
|
||
|
|
}
|
||
|
|
printJS({
|
||
|
|
printable: url,
|
||
|
|
type: 'image',
|
||
|
|
documentTitle: '打印',
|
||
|
|
});
|
||
|
|
};
|
||
|
|
const changeFormat = async (schemas, info) => {
|
||
|
|
if (!configs.value) return;
|
||
|
|
const keys = Object.keys(configs.value.formModel);
|
||
|
|
for (const item of schemas) {
|
||
|
|
if (['tab', 'grid', 'card'].includes(item.type)) {
|
||
|
|
const layoutChildren = {};
|
||
|
|
for (let index = 0; index < item.children.length; index++) {
|
||
|
|
const name =
|
||
|
|
item.type === 'grid'
|
||
|
|
? index
|
||
|
|
: item.type === 'card'
|
||
|
|
? item.componentProps?.title
|
||
|
|
: item.children[index].name;
|
||
|
|
layoutChildren[name] = [];
|
||
|
|
if ((index === activeKey?.value && item.type === 'tab') || item.type !== 'tab') {
|
||
|
|
await changeFormat(item.children[index].list, layoutChildren[name]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
info.push({
|
||
|
|
type: item.type,
|
||
|
|
value: layoutChildren,
|
||
|
|
});
|
||
|
|
} else if (item.type === 'form') {
|
||
|
|
if (keys.includes(item.componentProps.mainKey)) {
|
||
|
|
// const children: object[] = [];
|
||
|
|
// configs.value.formModel[item.componentProps.mainKey].forEach((sub) => {
|
||
|
|
// const subInfo = {};
|
||
|
|
// item.componentProps.columns.forEach((col) => {
|
||
|
|
// if (Object.keys(sub).includes(col.dataIndex) && !!col.show) {
|
||
|
|
// subInfo[col.title] = sub[col.dataIndex];
|
||
|
|
// }
|
||
|
|
// });
|
||
|
|
// children.push(subInfo);
|
||
|
|
// });
|
||
|
|
const columns: any[] = [];
|
||
|
|
const value: any[] = [];
|
||
|
|
configs.value.formModel[item.componentProps.mainKey].forEach((sub) => {
|
||
|
|
let val = {};
|
||
|
|
item.componentProps.columns.forEach(async (col) => {
|
||
|
|
if (Object.keys(sub).includes(col.dataIndex) && !!col.show) {
|
||
|
|
if (!columns.map((x) => x.key).includes(col.dataIndex)) {
|
||
|
|
columns.push({
|
||
|
|
title: col.title,
|
||
|
|
key: col.dataIndex,
|
||
|
|
dataIndex: col.dataIndex,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
val[col.dataIndex] = await changeValue(col, sub[col.dataIndex]);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
value.push(val);
|
||
|
|
});
|
||
|
|
info.push({
|
||
|
|
type: item.type,
|
||
|
|
label: item.label,
|
||
|
|
value,
|
||
|
|
columns,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} else if (keys.includes(item.field) && !!item.show) {
|
||
|
|
let value = await changeValue(item, configs.value.formModel[item.field]);
|
||
|
|
info.push({
|
||
|
|
label: item.label,
|
||
|
|
type: item.type,
|
||
|
|
componentProps: item.componentProps,
|
||
|
|
value,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const changeValue = async (item, fieldValue) => {
|
||
|
|
const type = item.type ? buildComponentType(item.type) : item.componentType;
|
||
|
|
if (isNil(fieldValue)) return fieldValue;
|
||
|
|
if (type === 'User' || (type === 'Info' && item.componentProps?.infoType === 0)) {
|
||
|
|
const res = await getUserMulti(fieldValue);
|
||
|
|
return res?.map((x) => x.name).toString();
|
||
|
|
} else if (type === 'Dept' || (type === 'Info' && item.componentProps?.infoType === 1)) {
|
||
|
|
const res = await getDepartment(fieldValue);
|
||
|
|
return res?.name;
|
||
|
|
} else if (type === 'Area') {
|
||
|
|
const res = await getAreaMulti(fieldValue);
|
||
|
|
return res?.map((x) => x.name).join(' / ');
|
||
|
|
} else if (item.componentProps?.datasourceType === 'dic') {
|
||
|
|
const res = await getDicItemDetail(item.componentProps?.params.itemId, fieldValue);
|
||
|
|
return res?.map((x) => x.name).toString();
|
||
|
|
}
|
||
|
|
return fieldValue;
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
<style lang="less" scoped>
|
||
|
|
.btn-box {
|
||
|
|
width: 100%;
|
||
|
|
text-align: right;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.borderClass {
|
||
|
|
border: 0 !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-style2-box,
|
||
|
|
.print-style3-box,
|
||
|
|
.print-style4-box {
|
||
|
|
margin: 10px 20px;
|
||
|
|
|
||
|
|
:deep(.ant-row) {
|
||
|
|
font-size: 16px;
|
||
|
|
border: 1px solid !important;
|
||
|
|
|
||
|
|
.ant-col {
|
||
|
|
padding: 15px 5px;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-style3-box {
|
||
|
|
:deep(.ant-col:last-child) {
|
||
|
|
border-left: 0 !important;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-style2-box {
|
||
|
|
:deep(.ant-col:first-child) {
|
||
|
|
border-right: 1px solid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.print-style4-box {
|
||
|
|
:deep(.ant-row) {
|
||
|
|
border-left: 0 !important;
|
||
|
|
border-right: 0 !important;
|
||
|
|
border-top: 0 !important;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
<style lang="less">
|
||
|
|
.full-modal {
|
||
|
|
.ant-modal {
|
||
|
|
max-width: 100%;
|
||
|
|
top: 0 !important;
|
||
|
|
padding-bottom: 0;
|
||
|
|
margin: 0;
|
||
|
|
height: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ant-modal-content {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
min-height: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ant-modal-body {
|
||
|
|
flex: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ant-modal-footer {
|
||
|
|
display: none !important;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|