歷史:
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示例