修改看版配置

master
夜笙歌 3 weeks ago
parent ea2754a41c
commit a8791791d7

@ -1,214 +1,215 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" /> <meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no" />
<title>智造MOM平台系统</title> <link rel="icon" href="/favicon.ico" />
<!--[if lt IE 11 <title>智造MOM平台系统</title>
]><script> <!--[if lt IE 11
window.location.href = '/html/ie.html'; ]><script>
</script><! window.location.href = '/html/ie.html';
[endif]--> </script><!
<style> [endif]-->
html, <style>
body, html,
#app { body,
height: 100%; #app {
margin: 0px; height: 100%;
padding: 0px; margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-webkit-animation: spin 2s linear infinite;
-ms-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
z-index: 1001;
}
#loader:before {
content: '';
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite;
-ms-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
#loader:after {
content: '';
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite;
-ms-animation: spin 1.5s linear infinite;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
} }
.chromeframe { 100% {
margin: 0.2em 0; -webkit-transform: rotate(360deg);
background: #ccc; -ms-transform: rotate(360deg);
color: #000; transform: rotate(360deg);
padding: 0.2em 0; }
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
} }
#loader-wrapper { 100% {
position: fixed; -webkit-transform: rotate(360deg);
top: 0; -ms-transform: rotate(360deg);
left: 0; transform: rotate(360deg);
width: 100%;
height: 100%;
z-index: 999999;
} }
}
#loader { #loader-wrapper .loader-section {
display: block; position: fixed;
position: relative; top: 0;
left: 50%; width: 51%;
top: 50%; height: 100%;
width: 150px; background: #7171c6;
height: 150px; z-index: 1000;
margin: -75px 0 0 -75px; -webkit-transform: translateX(0);
border-radius: 50%; -ms-transform: translateX(0);
border: 3px solid transparent; transform: translateX(0);
border-top-color: #fff; }
-webkit-animation: spin 2s linear infinite;
-ms-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
z-index: 1001;
}
#loader:before { #loader-wrapper .loader-section.section-left {
content: ''; left: 0;
position: absolute; }
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite;
-ms-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
#loader:after { #loader-wrapper .loader-section.section-right {
content: ''; right: 0;
position: absolute; }
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
-moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite;
-ms-animation: spin 1.5s linear infinite;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin { .loaded #loader-wrapper .loader-section.section-left {
0% { -webkit-transform: translateX(-100%);
-webkit-transform: rotate(0deg); -ms-transform: translateX(-100%);
-ms-transform: rotate(0deg); transform: translateX(-100%);
transform: rotate(0deg); -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
} transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
100% { .loaded #loader-wrapper .loader-section.section-right {
-webkit-transform: rotate(360deg); -webkit-transform: translateX(100%);
-ms-transform: rotate(360deg); -ms-transform: translateX(100%);
transform: rotate(360deg); transform: translateX(100%);
} -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
} transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
@keyframes spin { .loaded #loader {
0% { opacity: 0;
-webkit-transform: rotate(0deg); -webkit-transition: all 0.3s ease-out;
-ms-transform: rotate(0deg); transition: all 0.3s ease-out;
transform: rotate(0deg); }
}
100% { .loaded #loader-wrapper {
-webkit-transform: rotate(360deg); visibility: hidden;
-ms-transform: rotate(360deg); -webkit-transform: translateY(-100%);
transform: rotate(360deg); -ms-transform: translateY(-100%);
} transform: translateY(-100%);
} -webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out;
}
#loader-wrapper .loader-section { .no-js #loader-wrapper {
position: fixed; display: none;
top: 0; }
width: 51%;
height: 100%;
background: #7171c6;
z-index: 1000;
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
#loader-wrapper .loader-section.section-left { .no-js h1 {
left: 0; color: #222222;
} }
#loader-wrapper .loader-section.section-right { #loader-wrapper .load_title {
right: 0; font-family: 'Open Sans';
} color: #fff;
font-size: 19px;
width: 100%;
text-align: center;
z-index: 9999999999999;
position: absolute;
top: 60%;
opacity: 1;
line-height: 30px;
}
.loaded #loader-wrapper .loader-section.section-left { #loader-wrapper .load_title span {
-webkit-transform: translateX(-100%); font-weight: normal;
-ms-transform: translateX(-100%); font-style: italic;
transform: translateX(-100%); font-size: 13px;
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); color: #fff;
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); opacity: 0.5;
} }
</style>
</head>
.loaded #loader-wrapper .loader-section.section-right { <body>
-webkit-transform: translateX(100%); <div id="app">
-ms-transform: translateX(100%); <div id="loader-wrapper">
transform: translateX(100%); <div id="loader"></div>
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); <div class="loader-section section-left"></div>
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); <div class="loader-section section-right"></div>
} <div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
.loaded #loader { </div>
opacity: 0; <script type="module" src="/src/main.ts"></script>
-webkit-transition: all 0.3s ease-out; </body>
transition: all 0.3s ease-out;
}
.loaded #loader-wrapper {
visibility: hidden;
-webkit-transform: translateY(-100%);
-ms-transform: translateY(-100%);
transform: translateY(-100%);
-webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out;
}
.no-js #loader-wrapper {
display: none;
}
.no-js h1 {
color: #222222;
}
#loader-wrapper .load_title {
font-family: 'Open Sans';
color: #fff;
font-size: 19px;
width: 100%;
text-align: center;
z-index: 9999999999999;
position: absolute;
top: 60%;
opacity: 1;
line-height: 30px;
}
#loader-wrapper .load_title span {
font-weight: normal;
font-style: italic;
font-size: 13px;
color: #fff;
opacity: 0.5;
}
</style>
</head>
<body>
<div id="app">
<div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html> </html>

@ -10,7 +10,7 @@ import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission'; import usePermissionStore from '@/store/modules/permission';
NProgress.configure({ showSpinner: false }); NProgress.configure({ showSpinner: false });
const whiteList = ['/boardGenerate', '/boardView', '/boardConstruction', '/board1', '/board2', '/login', '/register', '/social-callback']; const whiteList = ['/print', '/boardGenerate', '/boardView', '/boardConstruction', '/board1', '/board2', '/login', '/register', '/social-callback'];
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
NProgress.start(); NProgress.start();

@ -565,8 +565,9 @@ onMounted(async () => {
sourceHandle: e.sourceHandleId sourceHandle: e.sourceHandleId
}; };
}) || []; }) || [];
pageData.value = JSON.parse(data.customContent) || {};
}); });
pageData.value = JSON.parse(localStorage.getItem('PAGEDATA')); // pageData.value = JSON.parse(localStorage.getItem('PAGEDATA'));
}); });
const customDataForm = ref({}); const customDataForm = ref({});
const nodeAttrForm = ref({}); const nodeAttrForm = ref({});
@ -599,6 +600,7 @@ const logEvent = async (eventname, event) => {
console.log(event.node.data); console.log(event.node.data);
break; break;
case 'nodeDrag': case 'nodeDrag':
console.log(event.nodes);
if (event.nodes.length === 1) { if (event.nodes.length === 1) {
nodeAttrForm.value = event.node.data.options; nodeAttrForm.value = event.node.data.options;
nodeDataForm.value = event.node; nodeDataForm.value = event.node;
@ -642,12 +644,14 @@ const getInputData = (e) => {
}; };
const pageSetting = () => { const pageSetting = () => {
pageSettingVisible.value = true; pageSettingVisible.value = true;
pageSettingForm.value = JSON.parse(localStorage.getItem('PAGEDATA')); // pageSettingForm.value = JSON.parse(localStorage.getItem('PAGEDATA')) || {};
pageSettingForm.value = pageData.value;
}; };
const save = () => { const save = () => {
editBoardApi({ editBoardApi({
...boardData.value, ...boardData.value,
customContent: JSON.stringify(pageSettingForm.value),
designPagePointList: nodes.value.map(e => { designPagePointList: nodes.value.map(e => {
let data = {}; let data = {};
let savaField = ['customData', 'options']; let savaField = ['customData', 'options'];
@ -766,7 +770,7 @@ const pageBgUploadSuccess = (file) => {
}; };
const setPageData = () => { const setPageData = () => {
pageData.value = JSON.parse(JSON.stringify(pageSettingForm.value)); pageData.value = JSON.parse(JSON.stringify(pageSettingForm.value));
localStorage.setItem('PAGEDATA', JSON.stringify(pageData.value)); // localStorage.setItem('PAGEDATA', JSON.stringify(pageData.value));
pageSettingVisible.value = false; pageSettingVisible.value = false;
}; };
</script> </script>

@ -1,39 +1,255 @@
<template> <template>
<div> <div style="overflow:hidden;">
<div class="ep-draggable-item" /> <div class="top">
<div id="hiprint-printTemplate" /> <div style="line-height: 60px;margin-left: 12px;">
<div id="PrintElementOptionSetting" /> <el-button-group>
<el-button :type="pageType === 'A3' ? 'primary' : ''" @click="setPage('A3',42,29.7)">A3</el-button>
<el-button :type="pageType === 'A4' ? 'primary' : ''" @click="setPage('A4',21,29.7)">A4</el-button>
<el-button :type="pageType === 'A5' ? 'primary' : ''" @click="setPage('A5',14.8,21)">A5</el-button>
<el-button :type="pageType === 'B3' ? 'primary' : ''" @click="setPage('B3',35.3,50)">B3</el-button>
<el-button :type="pageType === 'B4' ? 'primary' : ''" @click="setPage('B4',25,35.2)">B4</el-button>
<el-button :type="pageType === 'B5' ? 'primary' : ''" @click="setPage('B5',17.6,25)">B5</el-button>
</el-button-group>
<el-button @click="zoomChange(-0.1)" icon="ZoomOut" circle style="margin-left: 12px;" />
<el-input v-model="zoomInput" disabled style="margin-left: 8px;width:100px" />
<el-button @click="zoomChange(0.1)" icon="ZoomIn" circle style="margin-left: 8px;" />
<el-button type="primary" @click="view" style="margin-left: 12px;">预览</el-button>
<el-button type="primary" @click="save" style="margin-left: 12px;">保存</el-button>
<el-button type="primary" @click="clear" style="margin-left: 12px;">清空</el-button>
</div>
</div>
<div class="bottom">
<div class="leftPanel">
<h4>基础组件</h4>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'text',pid)" class="mx-1" size="large">文字</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'image',pid)" class="mx-1" size="large">图片</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'barCode',pid)" class="mx-1" size="large">条形码
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'QRCode',pid)" class="mx-1" size="large">二维码
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'dateTime',pid)" class="mx-1" size="large">日期时间
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'transverseLine',pid)" class="mx-1" size="large">横线
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'verticalLine',pid)" class="mx-1" size="large">竖线
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'rectangle',pid)" class="mx-1" size="large">矩形
</el-tag>
<el-tag :draggable="true" @dragstart="onDragStart($event, 'circle',pid)" class="mx-1" size="large">圆形
</el-tag>
<h4>表单组件</h4>
</div>
<div class="content" @drop="onDrop">
<div class="flowArea" :style="{width:zoom * cmToPx(pageWidth)+'px',height:zoom * cmToPx(pageHeight)+'px'}">
<VueFlow :autoPanSpeed="0" :min-zoom="0.01" ref="flowRef" v-model:nodes="nodes" v-model:edges="edges"
:zoomOnScroll="false"
:snapToGrid="isSnapToGrid" :snapGrid="[cmToPx(0.5), cmToPx(0.5)]"
:panOnDrag="false"
fit-view-on-init
default-marker-color="#409EFF"
@dragover="onDragOver"
@node-click="logEvent('click', $event)"
@pane-click="logEvent('paneClick', $event)"
@node-drag-start="logEvent('nodeDrag', $event)"
>
<Background variant="lines" :size="0.4" :gap="cmToPx(0.5)" pattern-color="#ddd"
style="background-color: #fff" />
<template #node-area="areaNodeProps">
<AreaNode v-bind="areaNodeProps"
:pageData="{width: cmToPx(pageWidth)+'px',height: cmToPx(pageHeight)+'px'}"></AreaNode>
</template>
<template #node-text="textNodeProps">
<TextNode v-bind="textNodeProps"
:pageSize="{width:zoom * cmToPx(pageWidth) ,height:zoom * cmToPx(pageHeight) }"></TextNode>
</template>
</VueFlow>
</div>
</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(nodeAttrForm).includes('name')">
<el-input v-model="nodeAttrForm.name" style="width: 100%" />
</el-form-item>
<el-form-item label="字段名" v-if="Object.keys(nodeAttrForm).includes('field')">
<el-input v-model="nodeAttrForm.field" style="width: 100%" />
</el-form-item>
<el-form-item label="缺省显示" v-if="Object.keys(nodeAttrForm).includes('default')">
<el-input v-model="nodeAttrForm.default" style="width: 100%" />
</el-form-item>
</el-form>
</div>
</div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { hiprint, defaultElementTypeProvider } from 'vue-plugin-hiprint'; import { v4 as uuidv4 } from 'uuid';
import { useRouter } from 'vue-router';
import { VueFlow, useVueFlow } 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';
console.log([new defaultElementTypeProvider()]); const router = useRouter();
hiprint.init({ //
providers: [new defaultElementTypeProvider()] const { onDragStart, onDrop, onDragOver } = tool();
}); const { cmToPx } = options;
hiprint.PrintElementTypeManager.buildByHtml($('.ep-draggable-item'));
let hiprintTemplate = new hiprint.PrintTemplate({ const flowRef = ref();
template: {}, // json const isSnapToGrid = ref(true);
settingContainer: '#PrintElementOptionSetting', // const pageWidth = ref(21);
history: true, // const pageHeight = ref(29.7);
onDataChanged: (type, json) => { const pageType = ref('A4');
// const zoom = ref(1);
console.log(type); // () const zoomInput = ref('100%');
console.log(json); // template const nodeAttrForm = ref({});
}, const pid = ref(`area_${uuidv4().replaceAll('-', '_')}`);
onUpdateError: (e) => {
// const logEvent = async (eventname, event) => {
console.log(e); switch (eventname) {
case 'paneClick':
nodeAttrForm.value = {};
break;
case 'click':
nodeAttrForm.value = event.node.data.options;
break;
case 'nodeDrag':
console.log(event.nodes);
if (event.nodes.length === 1) {
nodeAttrForm.value = event.node.data.options;
} else {
nodeAttrForm.value = {};
}
break;
} }
};
const nodes = ref([{
id: pid.value,
name: 'area',
type: 'area',
position: {
x: 0,
y: 0
},
data: {}
}]);
const edges = ref([]);
const setPage = (type, width, height) => {
pageType.value = type;
pageHeight.value = height;
pageWidth.value = width;
};
const zoomChange = (e) => {
console.log(flowRef.value.autoPanSpeed);
flowRef.value.viewport.x = 0;
flowRef.value.viewport.y = 0;
let num = zoom.value;
num += e;
zoom.value = parseFloat(Math.min(2, Math.max(0.2, num)).toFixed(2));
zoomInput.value = (zoom.value * 100).toFixed(0) + '%';
flowRef.value.setTransform({
x: 0,
y: 0,
zoom: zoom.value
});
};
const view = () => {
};
const save = () => {
};
const clear = () => {
};
onMounted(() => {
flowRef.value.onInit(() => {
flowRef.value.setTransform({
x: 0,
y: 0,
zoom: 1
});
});
}); });
// watch(() => flowRef.value?.viewport, () => {
hiprintTemplate.design('#hiprint-printTemplate'); if (flowRef.value && (flowRef.value.viewport.x !== 0 || flowRef.value.viewport.y !== 0)) {
console.log('重置原点');
flowRef.value.setTransform({
x: 0,
y: 0,
zoom: zoom.value
});
}
}, { deep: true });
const toggleSnapToGrid = (e) => {
if (e.key === 'Alt') {
isSnapToGrid.value = false;
}
};
const keyup = () => {
isSnapToGrid.value = true;
};
window.addEventListener('keydown', toggleSnapToGrid);
window.addEventListener('keyup', keyup);
// flow
const {
updateNode
} = useVueFlow();
</script> </script>
<style scoped> <style lang="less" scoped>
.ep-draggable-item, #hiprint-printTemplate, #PrintElementOptionSetting { :deep(.vue-flow__node-area) {
z-index: -1 !important;
pointer-events: none !important;
}
:deep(.el-tag) {
margin-bottom: 8px;
}
.top {
height: 64px;
margin: 8px 8px 0 8px;
border: 1px solid #ccc;
width: calc(100% - 16px);
display: inline-block;
}
.bottom {
height: calc(100vh - 64px - 16px - 8px);
}
.leftPanel, .rightPanel {
vertical-align: top;
display: inline-block; display: inline-block;
width: 300px; width: 300px;
height: 100vh; height: 100%;
margin: 8px 8px 0;
overflow: auto;
border: 1px solid #ccc;
}
.content {
vertical-align: top;
display: inline-block;
width: calc(100vw - 300px - 300px - 16px - 16px);
height: 100%;
margin-top: 8px;
border: 1px solid #ccc;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
}
.flowArea {
border-right: 1px solid #ccc;
} }
</style> </style>

@ -0,0 +1,25 @@
<template>
<div style="pointer-events: none">
<div class="custom-node">
<div class="area"
:style='`width:${props.pageData?.width || "100px"};height:${props.pageData?.height || "100px"};border: 1px solid #fff;`'></div>
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
pageData: {
type: Object,
required: false
}
});
</script>
<style scoped>
.area {
background-repeat: no-repeat;
background-size: 100% 100%;
}
</style>

@ -0,0 +1,56 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer :min-width="96 / 2.54" :min-height="96 / 2.54" :max-width="pageSize.width"
:max-height="pageSize.height" color="#000"
v-if="!props.isView && !props.isHideHandle && props.selected" />
<div class="custom-node"
:style="{textAlign:props.data.options.align,width:props.dimensions.width+'px',lineHeight:props.dimensions.height+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<img :src="props.data.options.imageSrc"
:style="{color:props.data.options.color,fontSize:props.dimensions.height+'px'}" alt="" />
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
import { NodeResizer } from '@vue-flow/node-resizer';
const props = defineProps({
isView: {
type: Boolean,
required: false
},
isHideHandle: {
type: Boolean,
required: false
},
selected: {
type: Boolean,
required: false
},
data: {
type: Object,
required: true
},
dimensions: {
type: Object,
required: true
},
pageSize: {
type: Object,
required: true
},
pageData: {
type: Object,
required: true
}
});
</script>
<style scoped>
.custom-node {
position: absolute;
}
</style>

@ -0,0 +1,58 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer :min-width="96 / 2.54" :min-height="96 / 2.54" :max-width="pageSize.width"
:max-height="pageSize.height" color="#000"
v-if="!props.isView && !props.isHideHandle && props.selected" />
<div class="custom-node"
:style="{textAlign:props.data.options.align,width:props.dimensions.width+'px',lineHeight:props.dimensions.height+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<span
:style="{color:props.data.options.color,fontSize:props.dimensions.height+'px'}">
{{ props.data.options.name || '文字' }}
</span>
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
import { NodeResizer } from '@vue-flow/node-resizer';
const props = defineProps({
isView: {
type: Boolean,
required: false
},
isHideHandle: {
type: Boolean,
required: false
},
selected: {
type: Boolean,
required: false
},
data: {
type: Object,
required: true
},
dimensions: {
type: Object,
required: true
},
pageSize: {
type: Object,
required: true
},
pageData: {
type: Object,
required: true
}
});
</script>
<style scoped>
.custom-node {
position: absolute;
}
</style>

@ -0,0 +1,109 @@
import { useVueFlow } from '@vue-flow/core';
import { ref, watch } from 'vue';
import { v4 as uuidv4 } from 'uuid';
const getId = (type) => {
return `${type}_${uuidv4().replaceAll('-', '_')}`;
};
const cmToPx = (cm) => {
return cm * 96 / 2.54;
};
const getOption = (e) => {
if (e === 'text') {
return { name: '', field: '', default: '' };
} else if (e === 'image') {
return { name: '', field: '', imageSrc: '', imageType: '' };
} else {
return {};
}
};
const getNodeSize = (e) => {
if (e === 'line' || e === 'multiLines' || e === 'bar' || e === 'multiBars' || e === 'curve' || e === 'multiCurves' || e === 'customBoard' || e === 'pie') {
return { width: cmToPx(5), height: cmToPx(2) };
} else {
return { width: cmToPx(5), height: cmToPx(2) };
}
};
const tool = () => {
const nodeType = ref('');
const parentId = ref('');
const { addNodes, screenToFlowCoordinate, onNodesInitialized, updateNode } = useVueFlow();
const onDragStart = (event, type, pid) => {
if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', type);
event.dataTransfer.effectAllowed = 'move';
}
nodeType.value = type;
parentId.value = pid;
document.addEventListener('drop', onDragEnd);
};
const onDragEnd = () => {
nodeType.value = null;
document.removeEventListener('drop', onDragEnd);
};
const onDrop = (event) => {
const dimensions = getNodeSize(nodeType.value);
const position = screenToFlowCoordinate({
x: event.clientX, y: event.clientY
});
const nodeId = getId(nodeType.value);
const newNode = {
id: nodeId,
name: nodeType.value,
type: nodeType.value,
parentNode: parentId.value,
extent: 'parent',
dimensions,
position,
data: { options: getOption(nodeType.value), outputData: {} }
};
const { off } = onNodesInitialized(() => {
updateNode(nodeId, (node) => ({
position: { x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2 }
}));
off();
});
addNodes(newNode);
};
const onDragOver = (event) => {
event.preventDefault();
if (nodeType.value) {
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
}
};
return {
onDragStart, onDragEnd, onDrop, onDragOver
};
};
export default tool;
export const options = {
isD: false, isJSON: (str) => {
if (typeof str === 'string') {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
}
return false;
}, cmToPx: cmToPx
};
Loading…
Cancel
Save