|
|
|
@ -59,6 +59,7 @@
|
|
|
|
|
@node-click="logEvent('click', $event)"
|
|
|
|
|
@pane-click="logEvent('paneClick', $event)"
|
|
|
|
|
@node-drag-start="logEvent('nodeDrag', $event)"
|
|
|
|
|
@node-drag-stop="logEvent('nodeDragEnd', $event)"
|
|
|
|
|
>
|
|
|
|
|
<Background variant="lines" :size="0.4" :gap="cmToPx(0.5)" pattern-color="#ddd"
|
|
|
|
|
style="background-color: #fff" />
|
|
|
|
@ -96,6 +97,24 @@
|
|
|
|
|
</div>
|
|
|
|
|
<div class="rightPanel" style="padding: 8px">
|
|
|
|
|
<el-form :model="nodeAttrForm" label-width="auto" style="max-width: 600px">
|
|
|
|
|
<el-form-item label="组件大小" v-if="Object.keys(nodeData).length>0">
|
|
|
|
|
<el-input-number :min="1" :controls="false" v-model="nodeData.dimensions.width"
|
|
|
|
|
style="width: calc(50% - 12px)"
|
|
|
|
|
@change="nodeData.dimensions.width = Math.max(1,nodeData.dimensions.width);nodeChange()" />
|
|
|
|
|
<div style="display: inline-block;width: 20px;text-align: center">x</div>
|
|
|
|
|
<el-input-number :min="1" :controls="false" v-model="nodeData.dimensions.height"
|
|
|
|
|
style="width: calc(50% - 12px)"
|
|
|
|
|
@change="nodeData.dimensions.height = Math.max(1,nodeData.dimensions.height);nodeChange()" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="组件位置" v-if="Object.keys(nodeData).length>0">
|
|
|
|
|
<el-input-number :precision="2" :min="1" :controls="false" v-model="nodeData.position.x"
|
|
|
|
|
style="width: calc(50% - 12px)"
|
|
|
|
|
@change="nodeData.position.x = Math.max(1,nodeData.position.x);nodeChange()" />
|
|
|
|
|
<div style="display: inline-block;width: 20px;text-align: center">x</div>
|
|
|
|
|
<el-input-number :precision="2" :min="1" :controls="false" v-model="nodeData.position.y"
|
|
|
|
|
style="width: calc(50% - 12px)"
|
|
|
|
|
@change="nodeData.position.y = Math.max(1,nodeData.position.y);nodeChange()" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="名称" v-if="Object.keys(nodeAttrForm).includes('name')">
|
|
|
|
|
<el-input v-model="nodeAttrForm.name" style="width: 100%" />
|
|
|
|
|
</el-form-item>
|
|
|
|
@ -119,32 +138,60 @@
|
|
|
|
|
/>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item v-if="Object.keys(nodeAttrForm).includes('selectOptions')" label="选项集合">
|
|
|
|
|
<el-input-tag
|
|
|
|
|
v-model="nodeAttrForm.selectOptions"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item v-if="Object.keys(nodeAttrForm).includes('horizontalAlign')" label="水平对齐">
|
|
|
|
|
<el-select
|
|
|
|
|
v-model="nodeAttrForm.horizontalAlign"
|
|
|
|
|
placeholder="Select"
|
|
|
|
|
>
|
|
|
|
|
<el-option
|
|
|
|
|
label="左对齐"
|
|
|
|
|
value="left"
|
|
|
|
|
/>
|
|
|
|
|
<el-option
|
|
|
|
|
label="居中对齐"
|
|
|
|
|
value="center"
|
|
|
|
|
/>
|
|
|
|
|
<el-option
|
|
|
|
|
label="右对齐"
|
|
|
|
|
value="right"
|
|
|
|
|
/>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item v-if="Object.keys(nodeAttrForm).includes('verticalAlign')" label="垂直对齐">
|
|
|
|
|
<el-select
|
|
|
|
|
v-model="nodeAttrForm.verticalAlign"
|
|
|
|
|
placeholder="Select"
|
|
|
|
|
>
|
|
|
|
|
<el-option
|
|
|
|
|
label="顶部对齐"
|
|
|
|
|
value="start"
|
|
|
|
|
/>
|
|
|
|
|
<el-option
|
|
|
|
|
label="居中对齐"
|
|
|
|
|
value="center"
|
|
|
|
|
/>
|
|
|
|
|
<el-option
|
|
|
|
|
label="底部对齐"
|
|
|
|
|
value="end"
|
|
|
|
|
/>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<View v-if="isView" v-model:isView="isView" />
|
|
|
|
|
</div>
|
|
|
|
|
<el-dialog v-model="isView" title="预览">
|
|
|
|
|
<div id="printInfo" v-if="isView" ref="printRef">
|
|
|
|
|
<View />
|
|
|
|
|
</div>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<span class="dialog-footer">
|
|
|
|
|
<el-button type="primary" @click="printFun">打印</el-button>
|
|
|
|
|
<!-- <el-button type="primary" v-print="printInfoObj">打印</el-button>-->
|
|
|
|
|
<el-button @click="isView = false">关闭</el-button>
|
|
|
|
|
</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
|
|
|
|
import html2canvas from 'html2canvas';
|
|
|
|
|
import jsPDF from 'jspdf';
|
|
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
|
import { useRouter } from 'vue-router';
|
|
|
|
|
import { VueFlow, useVueFlow } from '@vue-flow/core';
|
|
|
|
|
import { useVueFlow, VueFlow } from '@vue-flow/core';
|
|
|
|
|
import { Background } from '@vue-flow/background';
|
|
|
|
|
import { StarFilled } from '@element-plus/icons-vue';
|
|
|
|
|
import tool, { options } from './tool';
|
|
|
|
|
import AreaNode from './nodes/areaNode.vue';
|
|
|
|
|
import TextNode from './nodes/textNode.vue';
|
|
|
|
@ -156,13 +203,13 @@ import SelectNode from './nodes/selectNode.vue';
|
|
|
|
|
import View from './view.vue';
|
|
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const { updateNode } = useVueFlow();
|
|
|
|
|
// 获取自定义的方法
|
|
|
|
|
const { onDragStart, onDrop, onDragOver } = tool();
|
|
|
|
|
const { cmToPx } = options;
|
|
|
|
|
|
|
|
|
|
const printRef = ref();
|
|
|
|
|
const isView = ref(false);
|
|
|
|
|
const flowRef = ref();
|
|
|
|
|
const isView = ref(false);
|
|
|
|
|
const isSnapToGrid = ref(true);
|
|
|
|
|
const pageWidth = ref(21);
|
|
|
|
|
const pageHeight = ref(29.7);
|
|
|
|
@ -170,21 +217,35 @@ const pageType = ref('A4');
|
|
|
|
|
const zoom = ref(1);
|
|
|
|
|
const zoomInput = ref('100%');
|
|
|
|
|
const nodeAttrForm = ref({});
|
|
|
|
|
const nodeData = ref({});
|
|
|
|
|
const pid = ref(`area_${uuidv4().replaceAll('-', '_')}`);
|
|
|
|
|
|
|
|
|
|
const logEvent = async (eventname, event) => {
|
|
|
|
|
switch (eventname) {
|
|
|
|
|
case 'paneClick':
|
|
|
|
|
nodeAttrForm.value = {};
|
|
|
|
|
nodeData.value = {};
|
|
|
|
|
break;
|
|
|
|
|
case 'click':
|
|
|
|
|
nodeAttrForm.value = event.node.data.options;
|
|
|
|
|
nodeData.value = JSON.parse(JSON.stringify(event.node));
|
|
|
|
|
break;
|
|
|
|
|
case 'nodeDrag':
|
|
|
|
|
case 'nodeDrag':
|
|
|
|
|
if (event.nodes.length === 1) {
|
|
|
|
|
nodeAttrForm.value = event.node.data.options;
|
|
|
|
|
nodeData.value = JSON.parse(JSON.stringify(event.node));
|
|
|
|
|
} else {
|
|
|
|
|
nodeAttrForm.value = {};
|
|
|
|
|
nodeData.value = {};
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'nodeDragEnd':
|
|
|
|
|
if (event.nodes.length === 1) {
|
|
|
|
|
nodeAttrForm.value = event.node.data.options;
|
|
|
|
|
nodeData.value = JSON.parse(JSON.stringify(event.node));
|
|
|
|
|
} else {
|
|
|
|
|
nodeAttrForm.value = {};
|
|
|
|
|
nodeData.value = {};
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -263,37 +324,8 @@ const keyup = () => {
|
|
|
|
|
};
|
|
|
|
|
window.addEventListener('keydown', toggleSnapToGrid);
|
|
|
|
|
window.addEventListener('keyup', keyup);
|
|
|
|
|
// flow内置方法
|
|
|
|
|
const {
|
|
|
|
|
updateNode
|
|
|
|
|
} = useVueFlow();
|
|
|
|
|
const printInfoObj = {
|
|
|
|
|
id: 'printInfo',
|
|
|
|
|
preview: false, // 是否开启预览
|
|
|
|
|
beforeOpenCallback(vue) {
|
|
|
|
|
console.log('触发打印工具打开前回调');
|
|
|
|
|
},
|
|
|
|
|
openCallback(vue) {
|
|
|
|
|
console.log('触发打印工具打开的回调');
|
|
|
|
|
},
|
|
|
|
|
closeCallback() {
|
|
|
|
|
console.log('触发关闭打印工具回调');
|
|
|
|
|
},
|
|
|
|
|
previewBeforeOpenCallback() {
|
|
|
|
|
console.log('触发预览前回调');
|
|
|
|
|
},
|
|
|
|
|
previewOpenCallback() {
|
|
|
|
|
console.log('触发预览的回调');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const printFun = () => {
|
|
|
|
|
const element = printRef.value;
|
|
|
|
|
html2canvas(element).then(canvas => {
|
|
|
|
|
const imgData = canvas.toDataURL('image/png');
|
|
|
|
|
const pdf = new jsPDF();
|
|
|
|
|
pdf.addImage(imgData, 'PNG', 0, 0);
|
|
|
|
|
pdf.save(`${new Date().getTime()}.pdf`);
|
|
|
|
|
});
|
|
|
|
|
const nodeChange = () => {
|
|
|
|
|
updateNode(nodeData.value.id, JSON.parse(JSON.stringify(nodeData.value)), { replace: false });
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|