历史:
vue2 + Lodop 制作可视化设计页面 实现打印设计功能(一)
前言:
之前本来打算用直接拿之前做的vue2版本改改就发的,但考虑到现在主流都是vue3了,所以从这篇文章开始使用vue3来写,以及最后的demo也使用vue3
考虑到之前发的一些点过于分散,这篇开始打算就从头开始写这个功能,每篇最后发个本篇的示例demo
主要技术栈:vue3+vite+pinia+less+typescript
目录:
- 项目创建及模块定义,简单实现拖拽新增
- 组件点击拖拽移动
- 新增第一个自定义组件-HPText(文本组件)
- 新增HPText组件的菜单,组件菜单设置时组件动态变化
- 框选组件,批量移动
- 引入lodop,打印预览
- 待定...
正文:
创建vue3+vite项目
这个不用多说了,不属于本系列的范围
项目目录
最后项目创建后的目录大概长这样
定义设计页面viewport
<script setup lang="ts">
import {ref,h,resolveComponent} from 'vue'
import {QYComponent} from "../../../domains/qy-component.ts";const edit = ref(null)
const page = ref({height: 560,width: 944,
})const widgetStore = ref<QYComponent[]>([])const 测试数据 = [{uuid:'123',attr: {x: 10,y: 10,width: 90,height: 20,},
}]const dropToAddCom = (ev) => {ev.preventDefault()const rest = edit.value.getBoundingClientRect();测试数据[0].attr.x = Math.round(ev.clientX - rest.x)测试数据[0].attr.y = Math.round(ev.clientY - rest.y)widgetStore.value = [...测试数据];
}const dragOver = (ev) => {ev.preventDefault()
}const handleMouseDown = (ev) => {}</script><template><div class="holder" id="viewport" ref="viewport" data-type="viewport"><div:style="{height: page.height + 'px',width: page.width + 'px'}"ref="edit"class="screen"@dragover.prevent="dragOver"@drop="dropToAddCom($event)"><!-- 组件 --><divv-for="(moduleData,index) in widgetStore":style="{position: 'absolute',top: `${moduleData.attr.y}px`,left: `${moduleData.attr.x}px`,width: `${moduleData.attr.width}px`,height:`${moduleData.attr.height}px`}"><component:is="input":com="moduleData"></component></div></div></div>
</template><style scoped>
.holder {position: relative;width: 100%;display: flex;justify-content: left;overflow: auto;font-size: 0;border: 1px solid #f5f5f5;border-width: 0 1px;background-image: linear-gradient(45deg, #f5f5f5 25%, transparent 0, transparent 75%, #f5f5f5 0),linear-gradient(45deg, #f5f5f5 25%, transparent 0, transparent 75%, #f5f5f5 0);background-position: 0 0, 13px 13px;background-size: 26px 26px;
}.screen {margin: 20px;transform-origin: center top;position: relative;box-shadow: 0 0 5px 1px #cccccc;background-color: #ffffff;background-repeat: no-repeat;
}.wrapper {margin: 20px;position: relative;
}
</style>
定义组件列表components-panel
<script setup lang="ts">
import {ref} from 'vue'const dragStart = (ev) => {}
</script><template><div class="component-main" style="display: flex;flex-direction: column"><div style="margin: 5px;background: lightskyblue;color: white":draggable="true"@dragstart="dragStart($event)">文本</div></div>
</template><style scoped>
.component-main {border-radius: 5px;height: 100%;width: 200px;overflow-x: hidden;overflow-y: auto;
}
</style>
修改App.vue
<script setup lang="ts">
import viewport from './components/print-designer/viewport/index.vue'
import componentsPanel from './components/print-designer/components-panel/index.vue'</script><template><div class="main" data-theme="qy-designer"><components-panel/><viewport/></div>
</template><style scoped>
.main {display: flex;flex-direction: row;width: 100%;height: 100%;user-select: none;
}
</style>
效果
注:这里使用的技术点因为已经在第一篇讲了,所以这里就不再赘述了
demo示例