mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
Merge pull request #69 from JeremyYu-cn/feat-upgrade-vue3
Feat: Convert panel components to composition API
This commit is contained in:
commit
3af51e58fd
@ -64,6 +64,7 @@ export const getFontSub = (params: Type.Object = {}, extra: any = {}) => fetch('
|
|||||||
|
|
||||||
type TGetImageListParams = {
|
type TGetImageListParams = {
|
||||||
page?: number
|
page?: number
|
||||||
|
cate?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TGetImageListResult = {
|
export type TGetImageListResult = {
|
||||||
@ -73,6 +74,7 @@ export type TGetImageListResult = {
|
|||||||
url: string
|
url: string
|
||||||
user_id: number
|
user_id: number
|
||||||
id: string
|
id: string
|
||||||
|
thumb: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图库列表
|
// 图库列表
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
* @LastEditTime: 2024-03-01 20:55:51
|
* @LastEditTime: 2024-03-01 20:55:51
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { StyleValue } from "vue"
|
||||||
|
|
||||||
export type TWidgetClassifyData = {
|
export type TWidgetClassifyData = {
|
||||||
name: string
|
name: string
|
||||||
icon: string
|
icon: string
|
||||||
show: boolean
|
show: boolean
|
||||||
component: string
|
component: string
|
||||||
|
style?: StyleValue
|
||||||
}
|
}
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
|
@ -1,304 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="page-design" ref="page-design" :style="{ paddingTop: dPaddingTop + 'px' }">
|
|
||||||
<div
|
|
||||||
id="out-page"
|
|
||||||
class="out-page"
|
|
||||||
:style="{
|
|
||||||
width: (dPage.width * dZoom) / 100 + 120 + 'px',
|
|
||||||
height: (dPage.height * dZoom) / 100 + 120 + 'px',
|
|
||||||
opacity: 1 - (dZoom < 100 ? dPage.tag : 0),
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
<div
|
|
||||||
:id="pageDesignCanvasId"
|
|
||||||
class="design-canvas"
|
|
||||||
:data-type="dPage.type"
|
|
||||||
:data-uuid="dPage.uuid"
|
|
||||||
:style="{
|
|
||||||
width: dPage.width + 'px',
|
|
||||||
height: dPage.height + 'px',
|
|
||||||
transform: 'scale(' + dZoom / 100 + ')',
|
|
||||||
transformOrigin: (dZoom >= 100 ? 'center' : 'left') + ' top',
|
|
||||||
backgroundColor: dPage.backgroundColor,
|
|
||||||
backgroundImage: `url(${dPage?.backgroundImage})`,
|
|
||||||
backgroundSize: dPage?.backgroundTransform?.x ? 'auto' : 'cover',
|
|
||||||
backgroundPositionX: (dPage?.backgroundTransform?.x || 0) + 'px',
|
|
||||||
backgroundPositionY: (dPage?.backgroundTransform?.y || 0) + 'px',
|
|
||||||
opacity: dPage.opacity + (dZoom < 100 ? dPage.tag : 0),
|
|
||||||
}"
|
|
||||||
@mousemove="dropOver($event)"
|
|
||||||
@drop="drop($event)"
|
|
||||||
@mouseup="drop($event)"
|
|
||||||
>
|
|
||||||
<!-- <grid-size /> -->
|
|
||||||
|
|
||||||
<!-- :class="{
|
|
||||||
layer: true,
|
|
||||||
'layer-active': getIsActive(layer.uuid),
|
|
||||||
'layer-hover': layer.uuid === dHoverUuid || dActiveElement.parent === layer.uuid,
|
|
||||||
}" -->
|
|
||||||
<component :is="layer.type" v-for="layer in getlayers()" :id="layer.uuid" :key="layer.uuid" :class="['layer', { 'layer-hover': layer.uuid === dHoverUuid || dActiveElement.parent === layer.uuid, 'layer-no-hover': dActiveElement.uuid === layer.uuid }]" :data-title="layer.type" :params="layer" :parent="dPage" :data-type="layer.type" :data-uuid="layer.uuid">
|
|
||||||
<template v-if="layer.isContainer">
|
|
||||||
<!-- :class="{
|
|
||||||
layer: true,
|
|
||||||
'layer-active': getIsActive(widget.uuid),
|
|
||||||
'layer-no-hover': dActiveElement.uuid !== widget.parent && dActiveElement.parent !== widget.parent,
|
|
||||||
'layer-hover': widget.uuid === dHoverUuid,
|
|
||||||
}" -->
|
|
||||||
<component :is="widget.type" v-for="widget in getChilds(layer.uuid)" :key="widget.uuid" child :class="['layer', { 'layer-no-hover': dActiveElement.uuid !== widget.parent && dActiveElement.parent !== widget.parent }]" :data-title="widget.type" :params="widget" :parent="layer" :data-type="widget.type" :data-uuid="widget.uuid" />
|
|
||||||
</template>
|
|
||||||
</component>
|
|
||||||
|
|
||||||
<!-- <ref-line v-if="dSelectWidgets.length === 0" /> -->
|
|
||||||
<!-- <size-control v-if="dSelectWidgets.length === 0" /> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent, nextTick } from 'vue'
|
|
||||||
import { mapGetters, mapActions } from 'vuex'
|
|
||||||
import { getTarget } from '@/common/methods/target'
|
|
||||||
|
|
||||||
import setWidgetData from '@/common/methods/DesignFeatures/setWidgetData'
|
|
||||||
import PointImg from '@/utils/plugins/pointImg'
|
|
||||||
import getComponentsData from '@/common/methods/DesignFeatures/setComponents'
|
|
||||||
import { debounce } from 'throttle-debounce'
|
|
||||||
|
|
||||||
// 页面设计组件
|
|
||||||
const NAME = 'page-design'
|
|
||||||
|
|
||||||
import { move, moveInit } from '@/mixins/move'
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: NAME,
|
|
||||||
// components: {lineGuides},
|
|
||||||
mixins: [moveInit],
|
|
||||||
props: ['pageDesignCanvasId'],
|
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['dPaddingTop', 'dPage', 'dZoom', 'dScreen', 'dWidgets', 'dActiveElement', 'dHoverUuid', 'dSelectWidgets', 'dAltDown', 'dDraging', 'showRotatable']),
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getScreen()
|
|
||||||
document.getElementById('page-design').addEventListener('mousedown', this.handleSelection, false)
|
|
||||||
document.getElementById('page-design').addEventListener('mousemove', debounce(100, false, this.handleMouseMove), false)
|
|
||||||
},
|
|
||||||
beforeUnmount() {},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['updateScreen', 'selectWidget', 'deleteWidget', 'addWidget', 'addGroup']),
|
|
||||||
// getBackground(data) {
|
|
||||||
// if (data.startsWith('http')) return `url(${data})`
|
|
||||||
// if (data.startsWith('linear-gradient')) return data
|
|
||||||
// },
|
|
||||||
async dropOver(e) {
|
|
||||||
if (this.dActiveElement.editable || this.dActiveElement.lock) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
|
||||||
let { data, type } = this.$store.getters.selectItem
|
|
||||||
if (type !== 'image') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const target = await getTarget(e.target)
|
|
||||||
const uuid = target.getAttribute('data-uuid')
|
|
||||||
this.$store.dispatch('setDropOver', uuid)
|
|
||||||
if (e.target.getAttribute('putIn')) {
|
|
||||||
this._dropIn = uuid
|
|
||||||
const imgUrl = data.value.thumb || data.value.url
|
|
||||||
!this._srcCache && (this._srcCache = target.firstElementChild.firstElementChild.src)
|
|
||||||
target.firstElementChild.firstElementChild.src = imgUrl
|
|
||||||
} else {
|
|
||||||
this._srcCache && (target.firstElementChild.firstElementChild.src = this._srcCache)
|
|
||||||
this._srcCache = ''
|
|
||||||
this._dropIn = ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async drop(e) {
|
|
||||||
if (!this.dDraging) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$store.commit('setDraging', false)
|
|
||||||
const dropIn = this._dropIn
|
|
||||||
this._dropIn = ''
|
|
||||||
this.$store.dispatch('setDropOver', '-1')
|
|
||||||
this.$store.commit('setShowMoveable', false) // 清理上一次的选择
|
|
||||||
let lost = e.target.className !== 'design-canvas' // className === 'design-canvas' , id: "page-design-canvas"
|
|
||||||
// e.stopPropagation()
|
|
||||||
e.preventDefault()
|
|
||||||
let { data: item, type } = JSON.parse(JSON.stringify(this.$store.getters.selectItem))
|
|
||||||
// 清除临时数据
|
|
||||||
this.$store.commit('selectItem', {})
|
|
||||||
let setting = {}
|
|
||||||
if (!type) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理数据
|
|
||||||
setting = await setWidgetData(type, item, setting)
|
|
||||||
// 绝对坐标
|
|
||||||
const lostX = e.x - document.getElementById('page-design-canvas').getBoundingClientRect().left
|
|
||||||
const lostY = e.y - document.getElementById('page-design-canvas').getBoundingClientRect().top
|
|
||||||
// 放置组合
|
|
||||||
if (type === 'group') {
|
|
||||||
let parent = {}
|
|
||||||
item = await getComponentsData(item)
|
|
||||||
item.forEach((element) => {
|
|
||||||
if (element.type === 'w-group') {
|
|
||||||
parent.width = element.width
|
|
||||||
parent.height = element.height
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const half = { x: parent.width ? (parent.width * this.$store.getters.dZoom) / 100 / 2 : 0, y: parent.height ? (parent.height * this.$store.getters.dZoom) / 100 / 2 : 0 }
|
|
||||||
item.forEach((element) => {
|
|
||||||
element.left += (lost ? lostX - half.x : e.layerX - half.x) * (100 / this.$store.getters.dZoom)
|
|
||||||
element.top += (lost ? lostY - half.y : e.layerY - half.y) * (100 / this.$store.getters.dZoom)
|
|
||||||
})
|
|
||||||
this.addGroup(item)
|
|
||||||
}
|
|
||||||
// 设置坐标
|
|
||||||
const half = { x: setting.width ? (setting.width * this.$store.getters.dZoom) / 100 / 2 : 0, y: setting.height ? (setting.height * this.$store.getters.dZoom) / 100 / 2 : 0 }
|
|
||||||
// const half = { x: (this.dDragInitData.offsetX * this.dZoom) / 100, y: (this.dDragInitData.offsetY * this.dZoom) / 100 }
|
|
||||||
setting.left = (lost ? lostX - half.x : e.layerX - half.x) * (100 / this.$store.getters.dZoom)
|
|
||||||
setting.top = (lost ? lostY - half.y : e.layerY - half.y) * (100 / this.$store.getters.dZoom)
|
|
||||||
if (lost && type === 'image') {
|
|
||||||
// 如果不从画布加入,且不是图片类型,则判断是否加入到svg中
|
|
||||||
const target = await getTarget(e.target)
|
|
||||||
const targetType = target.getAttribute('data-type')
|
|
||||||
const uuid = target.getAttribute('data-uuid')
|
|
||||||
if (targetType === 'w-mask') {
|
|
||||||
// 容器
|
|
||||||
this.$store.commit('setShowMoveable', true) // 恢复选择
|
|
||||||
const widget = this.dWidgets.find((item) => item.uuid === uuid)
|
|
||||||
widget.imgUrl = item.value.url
|
|
||||||
// if (e.target.className.baseVal) {
|
|
||||||
// !widget.imgs && (widget.imgs = {})
|
|
||||||
// widget.imgs[`${e.target.className.baseVal}`] = item.value.url
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
if (dropIn) {
|
|
||||||
const widget = this.dWidgets.find((item) => item.uuid == dropIn)
|
|
||||||
widget.imgUrl = item.value.url
|
|
||||||
console.log('加入+', widget)
|
|
||||||
this.$store.commit('setShowMoveable', true) // 恢复选择
|
|
||||||
} else {
|
|
||||||
this.addWidget(setting) // 正常加入面板
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type === 'bg') {
|
|
||||||
console.log('背景图片放置')
|
|
||||||
} else if (type !== 'group') {
|
|
||||||
console.log(setting)
|
|
||||||
this.addWidget(setting) // 正常加入面板
|
|
||||||
}
|
|
||||||
// 清除临时数据
|
|
||||||
// this.$store.commit('selectItem', {})
|
|
||||||
},
|
|
||||||
getScreen() {
|
|
||||||
let screen = this.$refs['page-design']
|
|
||||||
this.updateScreen({
|
|
||||||
width: screen.offsetWidth,
|
|
||||||
height: screen.offsetHeight,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async handleMouseMove(e) {
|
|
||||||
const pImg = new PointImg(e.target)
|
|
||||||
const { rgba } = pImg.getColorXY(e.offsetX, e.offsetY)
|
|
||||||
if (rgba && rgba === 'rgba(0,0,0,0)') {
|
|
||||||
console.log('解析点位颜色: ', rgba)
|
|
||||||
let target = await getTarget(e.target)
|
|
||||||
target.style.pointerEvents = 'none'
|
|
||||||
setTimeout(() => {
|
|
||||||
target.style.pointerEvents = 'auto'
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async handleSelection(e) {
|
|
||||||
if (e.which === 3) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let target = await getTarget(e.target)
|
|
||||||
let type = target.getAttribute('data-type')
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
let uuid = target.getAttribute('data-uuid')
|
|
||||||
if (uuid !== '-1' && !this.dAltDown) {
|
|
||||||
let widget = this.dWidgets.find((item) => item.uuid === uuid)
|
|
||||||
if (widget.parent !== '-1' && widget.parent !== this.dActiveElement.uuid && widget.parent !== this.dActiveElement.parent) {
|
|
||||||
uuid = widget.parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置选中元素
|
|
||||||
// this.$store.commit('setMoveable', false)
|
|
||||||
if (this.showRotatable !== false) {
|
|
||||||
this.selectWidget({
|
|
||||||
uuid: uuid,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uuid !== '-1') {
|
|
||||||
this.initmovement && this.initmovement(e) // 参见 mixins
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 取消选中元素
|
|
||||||
this.selectWidget({
|
|
||||||
uuid: '-1',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getlayers() {
|
|
||||||
return this.dWidgets.filter((item) => item.parent === this.dPage.uuid)
|
|
||||||
},
|
|
||||||
getChilds(uuid) {
|
|
||||||
return this.dWidgets.filter((item) => item.parent === uuid)
|
|
||||||
},
|
|
||||||
// getIsActive(uuid) {
|
|
||||||
// if (this.dSelectWidgets.length > 0) {
|
|
||||||
// let widget = this.dSelectWidgets.find((item) => item.uuid === uuid)
|
|
||||||
// if (widget) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// return false
|
|
||||||
// } else {
|
|
||||||
// return uuid === this.dActiveElement.uuid
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
#page-design {
|
|
||||||
height: 100%;
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
overflow: auto;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
.out-page {
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 60px;
|
|
||||||
position: relative;
|
|
||||||
.design-canvas {
|
|
||||||
// transition: all 0.3s;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
box-shadow: 1px 1px 10px 3px rgba(0, 0, 0, 0.1);
|
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
|
||||||
// z-index: -9999;
|
|
||||||
// overflow: hidden;
|
|
||||||
// overflow: auto;
|
|
||||||
}
|
|
||||||
// .design-canvas ::-webkit-scrollbar {
|
|
||||||
// display: none; /* Chrome Safari */
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
363
src/components/modules/layout/designBoard/index.vue
Normal file
363
src/components/modules/layout/designBoard/index.vue
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
<template>
|
||||||
|
<div id="page-design" ref="page_design" :style="{ paddingTop: dPaddingTop + 'px' }">
|
||||||
|
<div
|
||||||
|
id="out-page"
|
||||||
|
class="out-page"
|
||||||
|
:style="{
|
||||||
|
width: (dPage.width * dZoom) / 100 + 120 + 'px',
|
||||||
|
height: (dPage.height * dZoom) / 100 + 120 + 'px',
|
||||||
|
opacity: 1 - (dZoom < 100 ? dPage.tag : 0),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<div
|
||||||
|
:id="pageDesignCanvasId"
|
||||||
|
class="design-canvas"
|
||||||
|
:data-type="dPage.type"
|
||||||
|
:data-uuid="dPage.uuid"
|
||||||
|
:style="{
|
||||||
|
width: dPage.width + 'px',
|
||||||
|
height: dPage.height + 'px',
|
||||||
|
transform: 'scale(' + dZoom / 100 + ')',
|
||||||
|
transformOrigin: (dZoom >= 100 ? 'center' : 'left') + ' top',
|
||||||
|
backgroundColor: dPage.backgroundColor,
|
||||||
|
backgroundImage: `url(${dPage?.backgroundImage})`,
|
||||||
|
backgroundSize: dPage?.backgroundTransform?.x ? 'auto' : 'cover',
|
||||||
|
backgroundPositionX: (dPage?.backgroundTransform?.x || 0) + 'px',
|
||||||
|
backgroundPositionY: (dPage?.backgroundTransform?.y || 0) + 'px',
|
||||||
|
opacity: dPage.opacity + (dZoom < 100 ? dPage.tag : 0),
|
||||||
|
}"
|
||||||
|
@mousemove="dropOver($event)"
|
||||||
|
@drop="drop($event)"
|
||||||
|
@mouseup="drop($event)"
|
||||||
|
>
|
||||||
|
<!-- <grid-size /> -->
|
||||||
|
|
||||||
|
<!-- :class="{
|
||||||
|
layer: true,
|
||||||
|
'layer-active': getIsActive(layer.uuid),
|
||||||
|
'layer-hover': layer.uuid === dHoverUuid || dActiveElement.parent === layer.uuid,
|
||||||
|
}" -->
|
||||||
|
<component :is="layer.type" v-for="layer in getlayers()" :id="layer.uuid" :key="layer.uuid" :class="['layer', { 'layer-hover': layer.uuid === dHoverUuid || dActiveElement.parent === layer.uuid, 'layer-no-hover': dActiveElement.uuid === layer.uuid }]" :data-title="layer.type" :params="layer" :parent="dPage" :data-type="layer.type" :data-uuid="layer.uuid">
|
||||||
|
<template v-if="layer.isContainer">
|
||||||
|
<!-- :class="{
|
||||||
|
layer: true,
|
||||||
|
'layer-active': getIsActive(widget.uuid),
|
||||||
|
'layer-no-hover': dActiveElement.uuid !== widget.parent && dActiveElement.parent !== widget.parent,
|
||||||
|
'layer-hover': widget.uuid === dHoverUuid,
|
||||||
|
}" -->
|
||||||
|
<component :is="widget.type" v-for="widget in getChilds(layer.uuid)" :key="widget.uuid" child :class="['layer', { 'layer-no-hover': dActiveElement.uuid !== widget.parent && dActiveElement.parent !== widget.parent }]" :data-title="widget.type" :params="widget" :parent="layer" :data-type="widget.type" :data-uuid="widget.uuid" />
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<!-- <ref-line v-if="dSelectWidgets.length === 0" /> -->
|
||||||
|
<!-- <size-control v-if="dSelectWidgets.length === 0" /> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { nextTick, defineProps, onMounted, ref } from 'vue'
|
||||||
|
import { mapGetters, mapActions, useStore } from 'vuex'
|
||||||
|
import { getTarget } from '@/common/methods/target'
|
||||||
|
|
||||||
|
import setWidgetData from '@/common/methods/DesignFeatures/setWidgetData'
|
||||||
|
import PointImg from '@/utils/plugins/pointImg'
|
||||||
|
import getComponentsData from '@/common/methods/DesignFeatures/setComponents'
|
||||||
|
import { debounce } from 'throttle-debounce'
|
||||||
|
import { move, moveInit } from '@/mixins/move'
|
||||||
|
import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||||
|
// 页面设计组件
|
||||||
|
type TProps = {
|
||||||
|
pageDesignCanvasId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TParentData = {
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type TSetting = {
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
top?: number
|
||||||
|
left?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
const { pageDesignCanvasId } = defineProps<TProps>()
|
||||||
|
const {
|
||||||
|
dPaddingTop, dPage, dZoom, dScreen, dWidgets,
|
||||||
|
dActiveElement, dSelectWidgets, dAltDown, dDraging,
|
||||||
|
dHoverUuid, showRotatable
|
||||||
|
} = useSetupMapGetters(['dPaddingTop', 'dPage', 'dZoom', 'dScreen', 'dWidgets', 'dActiveElement', 'dHoverUuid', 'dSelectWidgets', 'dAltDown', 'dDraging', 'showRotatable'])
|
||||||
|
|
||||||
|
let _dropIn: string | null = ''
|
||||||
|
let _srcCache: string | null = ''
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getScreen()
|
||||||
|
const pageDesignEl = document.getElementById('page-design')
|
||||||
|
if (!pageDesignEl) return
|
||||||
|
pageDesignEl.addEventListener('mousedown', handleSelection, false)
|
||||||
|
pageDesignEl.addEventListener('mousemove', debounce(100, false, handleMouseMove), false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// components: {lineGuides},
|
||||||
|
// mixins: [moveInit],
|
||||||
|
// ...mapActions(['updateScreen', 'selectWidget', 'deleteWidget', 'addWidget', 'addGroup']),
|
||||||
|
|
||||||
|
// getBackground(data) {
|
||||||
|
// if (data.startsWith('http')) return `url(${data})`
|
||||||
|
// if (data.startsWith('linear-gradient')) return data
|
||||||
|
// },
|
||||||
|
|
||||||
|
async function dropOver(e: MouseEvent) {
|
||||||
|
if (dActiveElement.value.editable || dActiveElement.value.lock) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
let { data, type } = store.getters.selectItem
|
||||||
|
if (type !== 'image') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!e || !e.target) return
|
||||||
|
const eventTarget = e.target as HTMLElement
|
||||||
|
const target = await getTarget(eventTarget)
|
||||||
|
if (!target) return
|
||||||
|
const uuid = target.getAttribute('data-uuid')
|
||||||
|
store.dispatch('setDropOver', uuid)
|
||||||
|
|
||||||
|
const imgEl = target?.firstElementChild?.firstElementChild as HTMLImageElement
|
||||||
|
if (eventTarget.getAttribute('putIn')) {
|
||||||
|
_dropIn = uuid
|
||||||
|
const imgUrl = data.value.thumb || data.value.url
|
||||||
|
!_srcCache && (_srcCache = imgEl.src)
|
||||||
|
imgEl.src = imgUrl
|
||||||
|
} else {
|
||||||
|
_srcCache && (imgEl.src = _srcCache)
|
||||||
|
_srcCache = ''
|
||||||
|
_dropIn = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function drop(e: MouseEvent) {
|
||||||
|
if (!dDraging.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!e || !e.target) return
|
||||||
|
const eventTarget = e.target as HTMLElement
|
||||||
|
store.commit('setDraging', false)
|
||||||
|
const dropIn = _dropIn
|
||||||
|
_dropIn = ''
|
||||||
|
store.dispatch('setDropOver', '-1')
|
||||||
|
store.commit('setShowMoveable', false) // 清理上一次的选择
|
||||||
|
let lost = eventTarget.className !== 'design-canvas' // className === 'design-canvas' , id: "page-design-canvas"
|
||||||
|
// e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
let { data: item, type } = JSON.parse(JSON.stringify(store.getters.selectItem))
|
||||||
|
// 清除临时数据
|
||||||
|
store.commit('selectItem', {})
|
||||||
|
let setting: TSetting = {}
|
||||||
|
if (!type) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 处理数据
|
||||||
|
setting = await setWidgetData(type, item, setting)
|
||||||
|
console.log("setting", setting)
|
||||||
|
// 绝对坐标
|
||||||
|
const canvasEl = document.getElementById('page-design-canvas')
|
||||||
|
if (!canvasEl) return
|
||||||
|
const lostX = e.x - canvasEl.getBoundingClientRect().left
|
||||||
|
const lostY = e.y - canvasEl.getBoundingClientRect().top
|
||||||
|
// 放置组合
|
||||||
|
if (type === 'group') {
|
||||||
|
let parent: TParentData = {}
|
||||||
|
const componentItem = await getComponentsData(item)
|
||||||
|
// item = await getComponentsData(item)
|
||||||
|
componentItem.forEach((element) => {
|
||||||
|
if (element.type === 'w-group') {
|
||||||
|
parent.width = element.width
|
||||||
|
parent.height = element.height
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const half = {
|
||||||
|
x: parent.width ? (parent.width * store.getters.dZoom) / 100 / 2 : 0,
|
||||||
|
y: parent.height ? (parent.height * store.getters.dZoom) / 100 / 2 : 0
|
||||||
|
}
|
||||||
|
componentItem.forEach((element) => {
|
||||||
|
element.left += (lost ? lostX - half.x : e.layerX - half.x) * (100 / store.getters.dZoom)
|
||||||
|
element.top += (lost ? lostY - half.y : e.layerY - half.y) * (100 / store.getters.dZoom)
|
||||||
|
})
|
||||||
|
store.dispatch('addGroup', item)
|
||||||
|
// addGroup(item)
|
||||||
|
}
|
||||||
|
// 设置坐标
|
||||||
|
const half = {
|
||||||
|
x: setting.width ? (setting.width * store.getters.dZoom) / 100 / 2 : 0,
|
||||||
|
y: setting.height ? (setting.height * store.getters.dZoom) / 100 / 2 : 0
|
||||||
|
}
|
||||||
|
// const half = { x: (this.dDragInitData.offsetX * this.dZoom) / 100, y: (this.dDragInitData.offsetY * this.dZoom) / 100 }
|
||||||
|
setting.left = (lost ? lostX - half.x : e.layerX - half.x) * (100 / store.getters.dZoom)
|
||||||
|
setting.top = (lost ? lostY - half.y : e.layerY - half.y) * (100 / store.getters.dZoom)
|
||||||
|
if (lost && type === 'image') {
|
||||||
|
// 如果不从画布加入,且不是图片类型,则判断是否加入到svg中
|
||||||
|
const target = await getTarget(eventTarget)
|
||||||
|
if (!target) return
|
||||||
|
const targetType = target.getAttribute('data-type')
|
||||||
|
const uuid = target.getAttribute('data-uuid')
|
||||||
|
if (targetType === 'w-mask') {
|
||||||
|
// 容器
|
||||||
|
store.commit('setShowMoveable', true) // 恢复选择
|
||||||
|
const widget = dWidgets.value.find((item: {uuid: string}) => item.uuid === uuid)
|
||||||
|
widget.imgUrl = item.value.url
|
||||||
|
// if (e.target.className.baseVal) {
|
||||||
|
// !widget.imgs && (widget.imgs = {})
|
||||||
|
// widget.imgs[`${e.target.className.baseVal}`] = item.value.url
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
if (dropIn) {
|
||||||
|
const widget = dWidgets.value.find((item: {uuid: string}) => item.uuid == dropIn)
|
||||||
|
widget.imgUrl = item.value.url
|
||||||
|
console.log('加入+', widget)
|
||||||
|
store.commit('setShowMoveable', true) // 恢复选择
|
||||||
|
} else {
|
||||||
|
store.dispatch('addWidget', setting) // 正常加入面板
|
||||||
|
// addWidget(setting) // 正常加入面板
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type === 'bg') {
|
||||||
|
console.log('背景图片放置')
|
||||||
|
} else if (type !== 'group') {
|
||||||
|
console.log(setting)
|
||||||
|
store.dispatch('addWidget', setting) // 正常加入面板
|
||||||
|
// addWidget(setting) // 正常加入面板
|
||||||
|
}
|
||||||
|
// 清除临时数据
|
||||||
|
// this.$store.commit('selectItem', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScreen() {
|
||||||
|
const pageDesignEl = document.getElementById('page-design')
|
||||||
|
if (!pageDesignEl) return
|
||||||
|
store.dispatch('updateScreen', {
|
||||||
|
width: pageDesignEl.offsetWidth,
|
||||||
|
height: pageDesignEl.offsetHeight,
|
||||||
|
})
|
||||||
|
// updateScreen({
|
||||||
|
// width: pageDesignEl.offsetWidth,
|
||||||
|
// height: pageDesignEl.offsetHeight,
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleMouseMove(e: MouseEvent) {
|
||||||
|
if (!e || !e.target) return
|
||||||
|
const imageTarget = e.target as HTMLImageElement
|
||||||
|
const pImg = new PointImg(imageTarget)
|
||||||
|
const { rgba } = pImg.getColorXY(e.offsetX, e.offsetY)
|
||||||
|
if (rgba && rgba === 'rgba(0,0,0,0)') {
|
||||||
|
console.log('解析点位颜色: ', rgba)
|
||||||
|
let target = await getTarget(imageTarget)
|
||||||
|
if (!target) return
|
||||||
|
target.style.pointerEvents = 'none'
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!target) return
|
||||||
|
target.style.pointerEvents = 'auto'
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSelection(e: MouseEvent) {
|
||||||
|
if (e.which === 3) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!e || !e.target) return
|
||||||
|
let target = await getTarget(e.target as HTMLElement)
|
||||||
|
if (!target) return
|
||||||
|
let type = target.getAttribute('data-type')
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
let uuid = target.getAttribute('data-uuid')
|
||||||
|
if (uuid !== '-1' && !dAltDown.value) {
|
||||||
|
let widget = dWidgets.value.find((item: {uuid: string}) => item.uuid === uuid)
|
||||||
|
if (widget.parent !== '-1' && widget.parent !== dActiveElement.value.uuid && widget.parent !== dActiveElement.value.parent) {
|
||||||
|
uuid = widget.parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置选中元素
|
||||||
|
// this.$store.commit('setMoveable', false)
|
||||||
|
if (showRotatable.value !== false) {
|
||||||
|
store.dispatch('selectWidget', {
|
||||||
|
uuid: uuid,
|
||||||
|
})
|
||||||
|
// selectWidget({
|
||||||
|
// uuid: uuid,
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid !== '-1') {
|
||||||
|
moveInit.methods.initmovement(e) // 参见 mixins
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 取消选中元素
|
||||||
|
store.dispatch('selectWidget', {
|
||||||
|
uuid: '-1',
|
||||||
|
})
|
||||||
|
// selectWidget({
|
||||||
|
// uuid: '-1',
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getlayers() {
|
||||||
|
return dWidgets.value.filter((item: { parent: string }) => item.parent === dPage.value.uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChilds(uuid: string) {
|
||||||
|
return dWidgets.value.filter((item: { parent: string }) => item.parent === uuid)
|
||||||
|
}
|
||||||
|
// getIsActive(uuid) {
|
||||||
|
// if (this.dSelectWidgets.length > 0) {
|
||||||
|
// let widget = this.dSelectWidgets.find((item) => item.uuid === uuid)
|
||||||
|
// if (widget) {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// } else {
|
||||||
|
// return uuid === this.dActiveElement.uuid
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
#page-design {
|
||||||
|
height: 100%;
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
.out-page {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 60px;
|
||||||
|
position: relative;
|
||||||
|
.design-canvas {
|
||||||
|
// transition: all 0.3s;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
box-shadow: 1px 1px 10px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
// z-index: -9999;
|
||||||
|
// overflow: hidden;
|
||||||
|
// overflow: auto;
|
||||||
|
}
|
||||||
|
// .design-canvas ::-webkit-scrollbar {
|
||||||
|
// display: none; /* Chrome Safari */
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
* @Author: ShawnPhang
|
* @Author: ShawnPhang
|
||||||
* @Date: 2021-08-03 17:50:21
|
* @Date: 2021-08-03 17:50:21
|
||||||
* @Description: 旧大小控制组件,已交由moveable控制
|
* @Description: 旧大小控制组件,已交由moveable控制 (已不使用)
|
||||||
* @LastEditors: ShawnPhang
|
* @LastEditors: ShawnPhang
|
||||||
* @LastEditTime: 2021-08-09 11:13:09
|
* @LastEditTime: 2021-08-09 11:13:09
|
||||||
-->
|
-->
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
export type TZoomData = {
|
||||||
|
text: string
|
||||||
|
value: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ZoomList: TZoomData[] = [
|
||||||
|
{
|
||||||
|
text: '25%',
|
||||||
|
value: 25,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '50%',
|
||||||
|
value: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '75%',
|
||||||
|
value: 75,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '100%',
|
||||||
|
value: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '125%',
|
||||||
|
value: 125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '150%',
|
||||||
|
value: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '200%',
|
||||||
|
value: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最佳尺寸',
|
||||||
|
value: -1,
|
||||||
|
// icon: 'icon-best-size',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const OtherList: TZoomData[] = [
|
||||||
|
{
|
||||||
|
text: '250%',
|
||||||
|
value: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '300%',
|
||||||
|
value: 300,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '350%',
|
||||||
|
value: 350,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '400%',
|
||||||
|
value: 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '450%',
|
||||||
|
value: 450,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '500%',
|
||||||
|
value: 500,
|
||||||
|
},
|
||||||
|
]
|
@ -19,270 +19,250 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { mapGetters, mapActions } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { defineComponent } from 'vue'
|
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
import addMouseWheel from '@/common/methods/addMouseWheel'
|
import addMouseWheel from '@/common/methods/addMouseWheel'
|
||||||
|
import { OtherList, TZoomData, ZoomList } from './data';
|
||||||
|
import { useSetupMapGetters } from '@/common/hooks/mapGetters';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
// 组件大小控制器
|
// 组件大小控制器
|
||||||
const NAME = 'zoom-control'
|
|
||||||
let holder: number | undefined
|
let holder: number | undefined
|
||||||
|
|
||||||
// TODO: TS类型补全
|
const hideControl = ref(false)
|
||||||
export default defineComponent({
|
const activezoomIndex = ref(0)
|
||||||
name: NAME,
|
const zoomList = ref<TZoomData[]>(ZoomList)
|
||||||
data() {
|
const show = ref(false)
|
||||||
return {
|
const zoom = ref<TZoomData>({
|
||||||
hideControl: false,
|
value: 0,
|
||||||
activezoomIndex: 0,
|
text: '',
|
||||||
zoomList: [
|
|
||||||
{
|
|
||||||
text: '25%',
|
|
||||||
value: 25,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '50%',
|
|
||||||
value: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '75%',
|
|
||||||
value: 75,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '100%',
|
|
||||||
value: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '125%',
|
|
||||||
value: 125,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '150%',
|
|
||||||
value: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '200%',
|
|
||||||
value: 200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '最佳尺寸',
|
|
||||||
value: -1,
|
|
||||||
// icon: 'icon-best-size',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
show: false,
|
|
||||||
zoom: {
|
|
||||||
value: 0,
|
|
||||||
text: 0,
|
|
||||||
},
|
|
||||||
otherList: [
|
|
||||||
{
|
|
||||||
text: '250%',
|
|
||||||
value: 250,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '300%',
|
|
||||||
value: 300,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '350%',
|
|
||||||
value: 350,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '400%',
|
|
||||||
value: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '450%',
|
|
||||||
value: 450,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '500%',
|
|
||||||
value: 500,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
otherIndex: -1,
|
|
||||||
bestZoom: 0,
|
|
||||||
curAction: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['dPage', 'dScreen', 'zoomScreenChange', 'dZoom']),
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
activezoomIndex(value) {
|
|
||||||
if (value < 0 || value > this.zoomList.length - 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.zoom = JSON.parse(JSON.stringify(this.zoomList[value]))
|
|
||||||
},
|
|
||||||
otherIndex(value) {
|
|
||||||
if (value < 0 || value > this.otherList.length - 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.zoom = JSON.parse(JSON.stringify(this.otherList[value]))
|
|
||||||
},
|
|
||||||
zoom(value) {
|
|
||||||
let realValue = value.value
|
|
||||||
if (realValue === -1) {
|
|
||||||
realValue = this.calcZoom()
|
|
||||||
}
|
|
||||||
this.updateZoom(realValue)
|
|
||||||
this.autoFixTop()
|
|
||||||
},
|
|
||||||
dScreen: {
|
|
||||||
handler() {
|
|
||||||
this.screenChange()
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
zoomScreenChange() {
|
|
||||||
this.activezoomIndex = this.zoomList.length - 1
|
|
||||||
this.screenChange()
|
|
||||||
},
|
|
||||||
dPage: {
|
|
||||||
handler(val) {
|
|
||||||
this.screenChange()
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
await this.$nextTick()
|
|
||||||
window.addEventListener('click', this.close)
|
|
||||||
if (this.$route.path === '/draw') {
|
|
||||||
this.activezoomIndex = 3
|
|
||||||
this.hideControl = true
|
|
||||||
} else {
|
|
||||||
this.activezoomIndex = this.zoomList.length - 1
|
|
||||||
}
|
|
||||||
// 添加滚轮监听
|
|
||||||
addMouseWheel('page-design', (isDown: boolean) => {
|
|
||||||
this.mousewheelZoom(isDown)
|
|
||||||
})
|
|
||||||
// 添加窗口大小监听
|
|
||||||
window.addEventListener('resize', (event) => {
|
|
||||||
this.changeScreen()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
window.removeEventListener('click', this.close)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['updateZoom', 'updateScreen']),
|
|
||||||
changeScreen() {
|
|
||||||
clearTimeout(holder)
|
|
||||||
holder = setTimeout(() => {
|
|
||||||
const screen = document.getElementById('page-design')
|
|
||||||
if (!screen) return
|
|
||||||
this.updateScreen({
|
|
||||||
width: screen.offsetWidth,
|
|
||||||
height: screen.offsetHeight,
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
},
|
|
||||||
screenChange() {
|
|
||||||
// 弹性尺寸即时修改
|
|
||||||
if (this.activezoomIndex === this.zoomList.length - 1) {
|
|
||||||
this.updateZoom(this.calcZoom())
|
|
||||||
this.autoFixTop()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectItem(index: number) {
|
|
||||||
this.activezoomIndex = index
|
|
||||||
this.otherIndex = -1
|
|
||||||
this.show = false
|
|
||||||
},
|
|
||||||
close(_: MouseEvent) {
|
|
||||||
this.show = false
|
|
||||||
},
|
|
||||||
add() {
|
|
||||||
this.curAction = 'add'
|
|
||||||
this.show = false
|
|
||||||
if (this.activezoomIndex === this.zoomList.length - 2 || this.activezoomIndex === this.zoomList.length - 1) {
|
|
||||||
this.activezoomIndex = this.zoomList.length
|
|
||||||
// this.otherIndex += 1
|
|
||||||
if (this.bestZoom) {
|
|
||||||
this.nearZoom(true)
|
|
||||||
} else {
|
|
||||||
this.otherIndex += 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.activezoomIndex != this.zoomList.length) {
|
|
||||||
this.activezoomIndex++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.otherIndex < this.otherList.length - 1) {
|
|
||||||
this.otherIndex++
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sub() {
|
|
||||||
this.curAction = null as any
|
|
||||||
this.show = false
|
|
||||||
if (this.otherIndex === 0) {
|
|
||||||
this.otherIndex = -1
|
|
||||||
this.activezoomIndex = this.zoomList.length - 2
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.otherIndex != -1) {
|
|
||||||
this.otherIndex--
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.activezoomIndex === this.zoomList.length - 1) {
|
|
||||||
if (this.bestZoom) {
|
|
||||||
this.nearZoom()
|
|
||||||
} else {
|
|
||||||
this.activezoomIndex = this.zoomList.length - 2
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.activezoomIndex != 0) {
|
|
||||||
this.activezoomIndex--
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mousewheelZoom(down: boolean) {
|
|
||||||
const value = Number(this.dZoom.toFixed(0))
|
|
||||||
if (down && value <= 1) return
|
|
||||||
this.updateZoom(down ? value - 1 : value + 1)
|
|
||||||
this.zoom.text = (value + '%') as any
|
|
||||||
this.autoFixTop()
|
|
||||||
},
|
|
||||||
nearZoom(add?: boolean) {
|
|
||||||
for (let i = 0; i < this.zoomList.length; i++) {
|
|
||||||
this.activezoomIndex = i
|
|
||||||
if (this.zoomList[i].value > this.bestZoom) {
|
|
||||||
if (add) break
|
|
||||||
} else if (this.zoomList[i].value < this.bestZoom) {
|
|
||||||
if (!add) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.bestZoom = 0
|
|
||||||
},
|
|
||||||
calcZoom() {
|
|
||||||
let widthZoom = ((this.dScreen.width - 142) * 100) / this.dPage.width
|
|
||||||
let heightZoom = ((this.dScreen.height - 122) * 100) / this.dPage.height
|
|
||||||
|
|
||||||
this.bestZoom = Math.min(widthZoom, heightZoom)
|
|
||||||
return this.bestZoom
|
|
||||||
},
|
|
||||||
async autoFixTop() {
|
|
||||||
await this.$nextTick()
|
|
||||||
const presetPadding = 60
|
|
||||||
const el = document.getElementById('out-page')
|
|
||||||
if (!el) return
|
|
||||||
// const clientHeight = document.body.clientHeight - 54
|
|
||||||
|
|
||||||
const parentHeight = (el.offsetParent as HTMLElement).offsetHeight - 54
|
|
||||||
let padding = (parentHeight - el.offsetHeight) / 2
|
|
||||||
if (typeof this.curAction === 'undefined') {
|
|
||||||
padding += presetPadding / 2
|
|
||||||
}
|
|
||||||
this.curAction === 'add' && (padding -= presetPadding)
|
|
||||||
this.$store.commit('updatePaddingTop', padding > 0 ? padding : 0)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
const otherList = ref<TZoomData[]>(OtherList)
|
||||||
|
const otherIndex = ref(-1)
|
||||||
|
const bestZoom = ref(0)
|
||||||
|
const curAction = ref('')
|
||||||
|
|
||||||
|
const { dPage, dScreen, zoomScreenChange, dZoom } = useSetupMapGetters(['dPage', 'dScreen', 'zoomScreenChange', 'dZoom'])
|
||||||
|
|
||||||
|
watch(
|
||||||
|
activezoomIndex,
|
||||||
|
(data) => {
|
||||||
|
if (data < 0 || data > zoomList.value.length - 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
zoom.value = JSON.parse(JSON.stringify(zoomList.value[data]))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
otherIndex,
|
||||||
|
(data) => {
|
||||||
|
if (data < 0 || data > otherList.value.length - 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
zoom.value = JSON.parse(JSON.stringify(otherList.value[data]))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
zoom,
|
||||||
|
(data) => {
|
||||||
|
let realValue = data.value
|
||||||
|
if (realValue === -1) {
|
||||||
|
realValue = calcZoom()
|
||||||
|
}
|
||||||
|
store.dispatch('updateZoom', realValue)
|
||||||
|
// updateZoom(realValue)
|
||||||
|
autoFixTop()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
dScreen,
|
||||||
|
() => {
|
||||||
|
screenChange()
|
||||||
|
},
|
||||||
|
{ deep: true, }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
zoomScreenChange,
|
||||||
|
() => {
|
||||||
|
activezoomIndex.value = zoomList.value.length - 1
|
||||||
|
screenChange()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
dPage,
|
||||||
|
() => {
|
||||||
|
screenChange()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick()
|
||||||
|
window.addEventListener('click', close)
|
||||||
|
if (route.path === '/draw') {
|
||||||
|
activezoomIndex.value = 3
|
||||||
|
hideControl.value = true
|
||||||
|
} else {
|
||||||
|
activezoomIndex.value = zoomList.value.length - 1
|
||||||
|
}
|
||||||
|
// 添加滚轮监听
|
||||||
|
addMouseWheel('page-design', (isDown: boolean) => {
|
||||||
|
mousewheelZoom(isDown)
|
||||||
|
})
|
||||||
|
// 添加窗口大小监听
|
||||||
|
window.addEventListener('resize', (event) => {
|
||||||
|
changeScreen()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('click', close)
|
||||||
|
})
|
||||||
|
|
||||||
|
// ...mapActions(['updateZoom', 'updateScreen']),
|
||||||
|
function changeScreen() {
|
||||||
|
clearTimeout(holder)
|
||||||
|
holder = setTimeout(() => {
|
||||||
|
const screen = document.getElementById('page-design')
|
||||||
|
if (!screen) return
|
||||||
|
store.dispatch('updateScreen', {
|
||||||
|
width: screen.offsetWidth,
|
||||||
|
height: screen.offsetHeight,
|
||||||
|
})
|
||||||
|
// updateScreen({
|
||||||
|
// width: screen.offsetWidth,
|
||||||
|
// height: screen.offsetHeight,
|
||||||
|
// })
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
function screenChange() {
|
||||||
|
// 弹性尺寸即时修改
|
||||||
|
if (activezoomIndex.value === zoomList.value.length - 1) {
|
||||||
|
store.dispatch('updateZoom', calcZoom())
|
||||||
|
// this.updateZoom(this.calcZoom())
|
||||||
|
autoFixTop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectItem(index: number) {
|
||||||
|
activezoomIndex.value = index
|
||||||
|
otherIndex.value = -1
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(_: MouseEvent) {
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
curAction.value = 'add'
|
||||||
|
show.value = false
|
||||||
|
if (
|
||||||
|
activezoomIndex.value === zoomList.value.length - 2 ||
|
||||||
|
activezoomIndex.value === zoomList.value.length - 1
|
||||||
|
) {
|
||||||
|
activezoomIndex.value = zoomList.value.length
|
||||||
|
// this.otherIndex += 1
|
||||||
|
if (bestZoom.value) {
|
||||||
|
nearZoom(true)
|
||||||
|
} else {
|
||||||
|
otherIndex.value += 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (activezoomIndex.value != zoomList.value.length) {
|
||||||
|
activezoomIndex.value++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (otherIndex.value < otherList.value.length - 1) {
|
||||||
|
otherIndex.value++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sub() {
|
||||||
|
curAction.value = ''
|
||||||
|
show.value = false
|
||||||
|
if (otherIndex.value === 0) {
|
||||||
|
otherIndex.value = -1
|
||||||
|
activezoomIndex.value = zoomList.value.length - 2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (otherIndex.value != -1) {
|
||||||
|
otherIndex.value--
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (activezoomIndex.value === zoomList.value.length - 1) {
|
||||||
|
if (bestZoom) {
|
||||||
|
nearZoom()
|
||||||
|
} else {
|
||||||
|
activezoomIndex.value = zoomList.value.length - 2
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (activezoomIndex.value != 0) {
|
||||||
|
activezoomIndex.value--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousewheelZoom(down: boolean) {
|
||||||
|
const value = Number(dZoom.value.toFixed(0))
|
||||||
|
if (down && value <= 1) return
|
||||||
|
store.dispatch('updateZoom', down ? value - 1 : value + 1)
|
||||||
|
// updateZoom(down ? value - 1 : value + 1)
|
||||||
|
zoom.value.text = (value + '%') as any
|
||||||
|
autoFixTop()
|
||||||
|
}
|
||||||
|
|
||||||
|
function nearZoom(add?: boolean) {
|
||||||
|
for (let i = 0; i < zoomList.value.length; i++) {
|
||||||
|
activezoomIndex.value = i
|
||||||
|
if (zoomList.value[i].value > bestZoom.value) {
|
||||||
|
if (add) break
|
||||||
|
} else if (zoomList.value[i].value < bestZoom.value) {
|
||||||
|
if (!add) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bestZoom.value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcZoom() {
|
||||||
|
let widthZoom = ((dScreen.value.width - 142) * 100) / dPage.value.width
|
||||||
|
let heightZoom = ((dScreen.value.height - 122) * 100) / dPage.value.height
|
||||||
|
|
||||||
|
bestZoom.value = Math.min(widthZoom, heightZoom)
|
||||||
|
return bestZoom.value
|
||||||
|
}
|
||||||
|
|
||||||
|
async function autoFixTop() {
|
||||||
|
await nextTick()
|
||||||
|
const presetPadding = 60
|
||||||
|
const el = document.getElementById('out-page')
|
||||||
|
if (!el) return
|
||||||
|
// const clientHeight = document.body.clientHeight - 54
|
||||||
|
|
||||||
|
const parentHeight = (el.offsetParent as HTMLElement).offsetHeight - 54
|
||||||
|
let padding = (parentHeight - el.offsetHeight) / 2
|
||||||
|
if (typeof curAction.value === 'undefined') {
|
||||||
|
padding += presetPadding / 2
|
||||||
|
}
|
||||||
|
curAction.value === 'add' && (padding -= presetPadding)
|
||||||
|
store.commit('updatePaddingTop', padding > 0 ? padding : 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
screenChange
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-show="activeTab === 0" class="style-wrap">
|
<div v-show="activeTab === 0" class="style-wrap">
|
||||||
<div v-show="showGroupCombined" style="padding: 2rem 0">
|
<div v-show="showGroupCombined" style="padding: 2rem 0">
|
||||||
<el-button plain type="primary" class="gounp__btn" @click="realCombined">成组</el-button>
|
<el-button plain type="primary" class="gounp__btn" @click="handleCombine">成组</el-button>
|
||||||
<icon-item-select label="" :data="alignIconList" @finish="alignAction" />
|
<icon-item-select label="" :data="alignIconList" @finish="alignAction" />
|
||||||
</div>
|
</div>
|
||||||
<component :is="dActiveElement.type + '-style'" v-show="!showGroupCombined" v-if="dActiveElement.type" />
|
<component :is="dActiveElement.type + '-style'" v-show="!showGroupCombined" v-if="dActiveElement.type" />
|
||||||
@ -17,58 +17,64 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
// 样式设置面板
|
// 样式设置面板
|
||||||
const NAME = 'style-panel'
|
// const NAME = 'style-panel'
|
||||||
import { mapGetters, mapActions } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import alignIconList from '@/assets/data/AlignListData'
|
import alignIconList, { AlignListData } from '@/assets/data/AlignListData'
|
||||||
import iconItemSelect from '../settings/iconItemSelect.vue'
|
import iconItemSelect from '../settings/iconItemSelect.vue'
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { useSetupMapGetters } from '@/common/hooks/mapGetters';
|
||||||
|
|
||||||
export default {
|
const store = useStore();
|
||||||
name: NAME,
|
|
||||||
components: { iconItemSelect },
|
const activeTab = ref(0)
|
||||||
data() {
|
const iconList = ref<AlignListData[]>(alignIconList)
|
||||||
return {
|
const showGroupCombined = ref(false)
|
||||||
activeTab: 0,
|
|
||||||
alignIconList,
|
const { dActiveElement, dWidgets, dSelectWidgets } = useSetupMapGetters(['dActiveElement', 'dWidgets', 'dSelectWidgets'])
|
||||||
showGroupCombined: false,
|
|
||||||
}
|
watch(
|
||||||
},
|
dSelectWidgets,
|
||||||
computed: {
|
(items) => {
|
||||||
...mapGetters(['dActiveElement', 'dWidgets', 'dSelectWidgets']),
|
setTimeout(() => {
|
||||||
},
|
showGroupCombined.value = items.length > 1
|
||||||
watch: {
|
}, 100)
|
||||||
dSelectWidgets: {
|
|
||||||
handler(items) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showGroupCombined = items.length > 1
|
|
||||||
}, 100)
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['selectWidget', 'updateAlign', 'updateHoverUuid', 'getCombined', 'realCombined', 'ungroup', 'pushHistory']),
|
|
||||||
alignAction(item) {
|
|
||||||
const sWidgets = JSON.parse(JSON.stringify(this.dSelectWidgets))
|
|
||||||
this.getCombined().then((group) => {
|
|
||||||
for (let i = 0; i < sWidgets.length; i++) {
|
|
||||||
const element = sWidgets[i]
|
|
||||||
this.updateAlign({
|
|
||||||
align: item.value,
|
|
||||||
uuid: element.uuid,
|
|
||||||
group,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.pushHistory()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
layerChange(newLayer) {
|
|
||||||
this.$store.commit('setDWidgets', newLayer.reverse())
|
|
||||||
this.$store.commit('setShowMoveable', false)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function handleCombine() {
|
||||||
|
store.dispatch('realCombined')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...mapActions(['selectWidget', 'updateAlign', 'updateHoverUuid', 'getCombined', 'realCombined', 'ungroup', 'pushHistory']),
|
||||||
|
function alignAction(item: AlignListData) {
|
||||||
|
const sWidgets = JSON.parse(JSON.stringify(dSelectWidgets.value))
|
||||||
|
store.dispatch('getCombined').then((group) => {
|
||||||
|
sWidgets.forEach((element: Record<string, any>) => {
|
||||||
|
store.dispatch('updateAlign', {
|
||||||
|
align: item.value,
|
||||||
|
uuid: element.uuid,
|
||||||
|
group,
|
||||||
|
})
|
||||||
|
// updateAlign({
|
||||||
|
// align: item.value,
|
||||||
|
// uuid: element.uuid,
|
||||||
|
// group,
|
||||||
|
// })
|
||||||
|
});
|
||||||
|
store.dispatch('pushHistory')
|
||||||
|
// pushHistory()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function layerChange(newLayer: Record<string, any>[]) {
|
||||||
|
store.commit('setDWidgets', newLayer.toReversed())
|
||||||
|
store.commit('setShowMoveable', false)
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -2,87 +2,80 @@
|
|||||||
<div id="widget-panel">
|
<div id="widget-panel">
|
||||||
<div class="widget-classify">
|
<div class="widget-classify">
|
||||||
<ul class="classify-wrap">
|
<ul class="classify-wrap">
|
||||||
<li v-for="(item, index) in widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': activeWidgetClassify === index }]" @click="clickClassify(index)">
|
<li v-for="(item, index) in state.widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': state.activeWidgetClassify === index }]" @click="clickClassify(index)">
|
||||||
<div class="icon-box"><i :class="['iconfont', 'icon', item.icon]" :style="item.style" /></div>
|
<div class="icon-box"><i :class="['iconfont', 'icon', item.icon]" :style="item.style" /></div>
|
||||||
<p>{{ item.name }}</p>
|
<p>{{ item.name }}</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="https://github.com/palxiao/poster-design" target="_blank" class="github"><img src="https://fe-doc.palxp.cn/images/github.svg" alt="Github" title="Github" /> 源码</a>
|
<a href="https://github.com/palxiao/poster-design" target="_blank" class="github"><img src="https://fe-doc.palxp.cn/images/github.svg" alt="Github" title="Github" /> 源码</a>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="active" class="widget-wrap">
|
<div v-show="state.active" class="widget-wrap">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="widgetClassifyList[activeWidgetClassify].component" />
|
<component :is="state.widgetClassifyList[state.activeWidgetClassify].component" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-show="active" class="side-wrap"><div class="pack__up" @click="active = false"><</div></div> -->
|
<!-- <div v-show="active" class="side-wrap"><div class="pack__up" @click="active = false"><</div></div> -->
|
||||||
<div v-show="active" class="side-wrap">
|
<div v-show="state.active" class="side-wrap">
|
||||||
<!-- <el-tooltip effect="dark" content="收起侧边栏" placement="right"> -->
|
<!-- <el-tooltip effect="dark" content="收起侧边栏" placement="right"> -->
|
||||||
<div class="pack__up" @click="active = false"></div>
|
<div class="pack__up" @click="state.active = false"></div>
|
||||||
<!-- </el-tooltip> -->
|
<!-- </el-tooltip> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
// 组件面板
|
// 组件面板
|
||||||
const NAME = 'widget-panel'
|
// const NAME = 'widget-panel'
|
||||||
import widgetClassifyListData from '@/assets/data/WidgetClassifyList.ts'
|
import widgetClassifyListData from '@/assets/data/WidgetClassifyList'
|
||||||
import { reactive, toRefs, onMounted, watch, nextTick, getCurrentInstance, ComponentInternalInstance } from 'vue'
|
import { reactive, onMounted, watch, nextTick, } from 'vue'
|
||||||
import { mapActions } from 'vuex'
|
// import { useStore } from 'vuex'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
export default {
|
// const store = useStore()
|
||||||
name: NAME,
|
const route = useRoute()
|
||||||
setup() {
|
const state = reactive({
|
||||||
// const store = useStore()
|
widgetClassifyList: widgetClassifyListData,
|
||||||
const route = useRoute()
|
activeWidgetClassify: 0,
|
||||||
const state = reactive({
|
active: true,
|
||||||
widgetClassifyList: widgetClassifyListData,
|
})
|
||||||
activeWidgetClassify: 0,
|
const clickClassify = (index: number) => {
|
||||||
active: true,
|
state.activeWidgetClassify = index
|
||||||
})
|
state.active = true
|
||||||
const clickClassify = (index: number) => {
|
|
||||||
state.activeWidgetClassify = index
|
|
||||||
state.active = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await nextTick()
|
|
||||||
const { koutu } = route.query
|
|
||||||
koutu && (state.activeWidgetClassify = 4)
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => state.activeWidgetClassify,
|
|
||||||
(index) => {
|
|
||||||
if (index >= 0 && index < state.widgetClassifyList.length) {
|
|
||||||
state.widgetClassifyList[index].show = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
|
||||||
// watch(
|
|
||||||
// () => state.active,
|
|
||||||
// () => {
|
|
||||||
// let screen = document.getElementById('page-design')
|
|
||||||
// nextTick(() => {
|
|
||||||
// proxy?.updateScreen({
|
|
||||||
// width: screen.offsetWidth,
|
|
||||||
// height: screen.offsetHeight,
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
|
|
||||||
return {
|
|
||||||
clickClassify,
|
|
||||||
...toRefs(state),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['updateScreen']),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick()
|
||||||
|
const { koutu } = route.query
|
||||||
|
koutu && (state.activeWidgetClassify = 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => state.activeWidgetClassify,
|
||||||
|
(index) => {
|
||||||
|
if (index >= 0 && index < state.widgetClassifyList.length) {
|
||||||
|
state.widgetClassifyList[index].show = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
||||||
|
// watch(
|
||||||
|
// () => state.active,
|
||||||
|
// () => {
|
||||||
|
// let screen = document.getElementById('page-design')
|
||||||
|
// nextTick(() => {
|
||||||
|
// proxy?.updateScreen({
|
||||||
|
// width: screen.offsetWidth,
|
||||||
|
// height: screen.offsetHeight,
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
clickClassify
|
||||||
|
})
|
||||||
|
// ...mapActions(['updateScreen']),
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -8,132 +8,166 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<div class="color__box" :style="modelStyle.color">
|
<div class="color__box" :style="modelStyle.color">
|
||||||
<div v-for="c in colors" :key="c" :style="{ background: c }" class="color__item" @click="setBGcolor(c)"></div>
|
<div v-for="c in state.colors" :key="c" :style="{ background: c }" class="color__item" @click="setBGcolor(c)"></div>
|
||||||
</div>
|
</div>
|
||||||
<ul v-if="showList" v-infinite-scroll="loadData" class="infinite-list" :infinite-scroll-distance="150" style="overflow: auto">
|
<ul v-if="state.showList" v-infinite-scroll="loadData" class="infinite-list" :infinite-scroll-distance="150" style="overflow: auto">
|
||||||
<div class="list" :style="modelStyle.list">
|
<div class="list" :style="modelStyle.list">
|
||||||
<imageTip v-for="(item, i) in bgList" :key="i + 'i'" :detail="item">
|
<imageTip v-for="(item, i) in state.bgList" :key="i + 'i'" :detail="item">
|
||||||
<el-image class="list__img" :src="item.thumb" fit="cover" lazy loading="lazy" @click.stop="selectItem(item)" @dragstart="dragStart($event, item)"></el-image>
|
<el-image class="list__img" :src="item.thumb" fit="cover" lazy loading="lazy" @click.stop="selectItem(item)" @dragstart="dragStart($event, item)"></el-image>
|
||||||
</imageTip>
|
</imageTip>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="loading" class="loading"><i class="el-icon-loading"></i> 拼命加载中</div>
|
<div v-show="state.loading" class="loading"><i class="el-icon-loading"></i> 拼命加载中</div>
|
||||||
<div v-show="loadDone" class="loading">全部加载完毕</div>
|
<div v-show="state.loadDone" class="loading">全部加载完毕</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, reactive, toRefs, computed } from 'vue'
|
import { reactive, computed, defineProps, defineExpose } from 'vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { mapActions, useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { ElImage } from 'element-plus'
|
||||||
|
import { TGetImageListResult } from '@/api/material';
|
||||||
|
|
||||||
export default defineComponent({
|
type TCommonPanelData = {
|
||||||
props: {
|
color: string
|
||||||
model: {
|
list: string
|
||||||
default: 'widgetPanel'
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
setup(props) {
|
|
||||||
const store = useStore()
|
|
||||||
const state = reactive({
|
|
||||||
loading: false,
|
|
||||||
loadDone: false,
|
|
||||||
bgList: [],
|
|
||||||
showList: true,
|
|
||||||
colors: ['#000000ff', '#999999ff', '#CCCCCCff', '#FFFFFFff', '#E65353ff', '#FFD835ff', '#70BC59ff', '#607AF4ff', '#976BEEff'],
|
|
||||||
})
|
|
||||||
// 临时用于改变样式
|
|
||||||
const models: any = {
|
|
||||||
widgetPanel: {
|
|
||||||
color: 'padding: 1.2rem 1rem',
|
|
||||||
list: 'grid-template-columns: auto auto auto;padding: 0 1rem;',
|
|
||||||
},
|
|
||||||
stylePanel: {
|
|
||||||
color: 'padding: 1.2rem 0;',
|
|
||||||
list: 'grid-template-columns: repeat(3, 76px);',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const modelStyle = computed(() => models[props.model])
|
|
||||||
|
|
||||||
const pageOptions = { page: 0, pageSize: 20 }
|
type TTmpModalData = {
|
||||||
|
widgetPanel: TCommonPanelData
|
||||||
|
stylePanel: TCommonPanelData
|
||||||
|
}
|
||||||
|
|
||||||
const loadData = () => {
|
type TProps = {
|
||||||
if (state.loading) {
|
model: 'widgetPanel'
|
||||||
return
|
}
|
||||||
}
|
|
||||||
load()
|
|
||||||
}
|
|
||||||
|
|
||||||
const load = async (init: boolean = false) => {
|
type TState = {
|
||||||
if (state.loadDone) {
|
loading: boolean
|
||||||
return
|
loadDone: boolean
|
||||||
}
|
bgList: TGetImageListResult[]
|
||||||
state.loading = true
|
showList: boolean
|
||||||
pageOptions.page += 1
|
colors: string[]
|
||||||
|
|
||||||
if (init) {
|
}
|
||||||
state.bgList = []
|
|
||||||
pageOptions.page = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
await api.material.getImagesList({ cate: 16, page: pageOptions.page }).then(({ list }: any) => {
|
const { model } = defineProps<TProps>()
|
||||||
if (list.length > 0) {
|
|
||||||
state.bgList.push(...list)
|
|
||||||
} else {
|
|
||||||
state.loadDone = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
state.loading = false
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setBGcolor(color: string) {
|
const store = useStore()
|
||||||
store.dispatch('updatePageData', {
|
const state = reactive<TState>({
|
||||||
key: 'backgroundImage',
|
loading: false,
|
||||||
value: '',
|
loadDone: false,
|
||||||
})
|
bgList: [],
|
||||||
store.dispatch('updatePageData', {
|
showList: true,
|
||||||
key: 'backgroundColor',
|
colors: ['#000000ff', '#999999ff', '#CCCCCCff', '#FFFFFFff', '#E65353ff', '#FFD835ff', '#70BC59ff', '#607AF4ff', '#976BEEff'],
|
||||||
value: color,
|
|
||||||
pushHistory: true,
|
|
||||||
})
|
|
||||||
store.dispatch('selectWidget', {
|
|
||||||
uuid: '-1',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(state),
|
|
||||||
load,
|
|
||||||
setBGcolor,
|
|
||||||
loadData,
|
|
||||||
modelStyle
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['selectWidget', 'updatePageData']),
|
|
||||||
async selectItem(item: any) {
|
|
||||||
// this.$store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
|
||||||
this.updatePageData({
|
|
||||||
key: 'backgroundTransform',
|
|
||||||
value: {},
|
|
||||||
})
|
|
||||||
this.updatePageData({
|
|
||||||
key: 'backgroundImage',
|
|
||||||
value: item.url,
|
|
||||||
pushHistory: true,
|
|
||||||
})
|
|
||||||
this.selectWidget({
|
|
||||||
uuid: '-1',
|
|
||||||
})
|
|
||||||
},
|
|
||||||
dragStart(e: any, item: any) {
|
|
||||||
this.$store.commit('selectItem', { data: {}, type: 'bg' })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 临时用于改变样式
|
||||||
|
const models: TTmpModalData = {
|
||||||
|
widgetPanel: {
|
||||||
|
color: 'padding: 1.2rem 1rem',
|
||||||
|
list: 'grid-template-columns: auto auto auto;padding: 0 1rem;',
|
||||||
|
},
|
||||||
|
stylePanel: {
|
||||||
|
color: 'padding: 1.2rem 0;',
|
||||||
|
list: 'grid-template-columns: repeat(3, 76px);',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelStyle = computed(() => models[model])
|
||||||
|
|
||||||
|
const pageOptions = { page: 0, pageSize: 20 }
|
||||||
|
|
||||||
|
const loadData = () => {
|
||||||
|
if (state.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
load()
|
||||||
|
}
|
||||||
|
|
||||||
|
const load = async (init: boolean = false) => {
|
||||||
|
if (state.loadDone) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.loading = true
|
||||||
|
pageOptions.page += 1
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
state.bgList = []
|
||||||
|
pageOptions.page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.material.getImagesList({ cate: 16, page: pageOptions.page }).then(({ list }) => {
|
||||||
|
if (list.length > 0) {
|
||||||
|
state.bgList.push(...list)
|
||||||
|
} else {
|
||||||
|
state.loadDone = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
state.loading = false
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBGcolor(color: string) {
|
||||||
|
store.dispatch('updatePageData', {
|
||||||
|
key: 'backgroundImage',
|
||||||
|
value: '',
|
||||||
|
})
|
||||||
|
store.dispatch('updatePageData', {
|
||||||
|
key: 'backgroundColor',
|
||||||
|
value: color,
|
||||||
|
pushHistory: true,
|
||||||
|
})
|
||||||
|
store.dispatch('selectWidget', {
|
||||||
|
uuid: '-1',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...mapActions(['selectWidget', 'updatePageData']),
|
||||||
|
async function selectItem(item: TGetImageListResult) {
|
||||||
|
// this.$store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||||
|
store.dispatch('updatePageData', {
|
||||||
|
key: 'backgroundTransform',
|
||||||
|
value: {},
|
||||||
|
})
|
||||||
|
store.dispatch('updatePageData', {
|
||||||
|
key: 'backgroundImage',
|
||||||
|
value: item.url,
|
||||||
|
pushHistory: true,
|
||||||
|
})
|
||||||
|
store.dispatch('selectWidget', {
|
||||||
|
uuid: '-1',
|
||||||
|
})
|
||||||
|
// this.updatePageData({
|
||||||
|
// key: 'backgroundTransform',
|
||||||
|
// value: {},
|
||||||
|
// })
|
||||||
|
// this.updatePageData({
|
||||||
|
// key: 'backgroundImage',
|
||||||
|
// value: item.url,
|
||||||
|
// pushHistory: true,
|
||||||
|
// })
|
||||||
|
// this.selectWidget({
|
||||||
|
// uuid: '-1',
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragStart(_: MouseEvent, _item: TGetImageListResult) {
|
||||||
|
store.commit('selectItem', { data: {}, type: 'bg' })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
load,
|
||||||
|
setBGcolor,
|
||||||
|
loadData,
|
||||||
|
modelStyle
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -48,7 +48,7 @@ const move = {
|
|||||||
|
|
||||||
const moveInit = {
|
const moveInit = {
|
||||||
methods: {
|
methods: {
|
||||||
initmovement(e: any) {
|
initmovement(e: MouseEvent) {
|
||||||
if (!store.getters.dAltDown) {
|
if (!store.getters.dAltDown) {
|
||||||
// 设置mouseevent给moveable初始
|
// 设置mouseevent给moveable初始
|
||||||
// 在组合操作时排除
|
// 在组合操作时排除
|
||||||
|
6
src/types/global.d.ts
vendored
6
src/types/global.d.ts
vendored
@ -56,3 +56,9 @@ interface Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface MouseEvent {
|
||||||
|
layerX: number
|
||||||
|
layerY: number
|
||||||
|
}
|
||||||
|
@ -16,7 +16,7 @@ import wGroup from '@/components/modules/widgets/wGroup/wGroup.vue'
|
|||||||
import Preload from '@/utils/plugins/preload'
|
import Preload from '@/utils/plugins/preload'
|
||||||
import FontFaceObserver from 'fontfaceobserver'
|
import FontFaceObserver from 'fontfaceobserver'
|
||||||
import { fontWithDraw, font2style } from '@/utils/widgets/loadFontRule'
|
import { fontWithDraw, font2style } from '@/utils/widgets/loadFontRule'
|
||||||
import designBoard from '@/components/modules/layout/designBoard.vue'
|
import designBoard from '@/components/modules/layout/designBoard/index.vue'
|
||||||
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -58,7 +58,7 @@ import { defineComponent, reactive, toRefs } from 'vue'
|
|||||||
import { mapActions, mapGetters } from 'vuex'
|
import { mapActions, mapGetters } from 'vuex'
|
||||||
import RightClickMenu from '@/components/business/right-click-menu/RcMenu.vue'
|
import RightClickMenu from '@/components/business/right-click-menu/RcMenu.vue'
|
||||||
import Moveable from '@/components/business/moveable/Moveable.vue'
|
import Moveable from '@/components/business/moveable/Moveable.vue'
|
||||||
import designBoard from '@/components/modules/layout/designBoard.vue'
|
import designBoard from '@/components/modules/layout/designBoard/index.vue'
|
||||||
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
||||||
import lineGuides from '@/components/modules/layout/lineGuides.vue'
|
import lineGuides from '@/components/modules/layout/lineGuides.vue'
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ import wText from '@/components/modules/widgets/wText/wText.vue'
|
|||||||
import wImage from '@/components/modules/widgets/wImage/wImage.vue'
|
import wImage from '@/components/modules/widgets/wImage/wImage.vue'
|
||||||
import useLoading from '@/common/methods/loading'
|
import useLoading from '@/common/methods/loading'
|
||||||
import uploader from '@/components/common/Uploader/index.vue'
|
import uploader from '@/components/common/Uploader/index.vue'
|
||||||
import designBoard from '@/components/modules/layout/designBoard.vue'
|
import designBoard from '@/components/modules/layout/designBoard/index.vue'
|
||||||
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
||||||
import HeaderOptions from './components/UploadTemplate.vue'
|
import HeaderOptions from './components/UploadTemplate.vue'
|
||||||
import ProgressLoading from '@/components/common/ProgressLoading/index.vue'
|
import ProgressLoading from '@/components/common/ProgressLoading/index.vue'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user