mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-28 04:10:31 +08:00
feat: add watermark & canvas size modification
This commit is contained in:
parent
2859efd0e7
commit
f6903eee7c
75
src/assets/data/PageSizeData.ts
Normal file
75
src/assets/data/PageSizeData.ts
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-07 17:49:06
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 00:37:33
|
||||
*/
|
||||
export default [
|
||||
{
|
||||
name: '手机海报',
|
||||
width: 1242,
|
||||
height: 2208,
|
||||
icon: 'sd-shouji'
|
||||
},
|
||||
{
|
||||
name: '横版海报',
|
||||
width: 900,
|
||||
height: 500,
|
||||
icon: 'sd-wangye'
|
||||
},
|
||||
{
|
||||
name: '公众号首图',
|
||||
width: 900,
|
||||
height: 383,
|
||||
icon: 'sd-weixin'
|
||||
},
|
||||
{
|
||||
name: '公众号次图',
|
||||
width: 500,
|
||||
height: 500,
|
||||
icon: 'sd-weixin'
|
||||
},
|
||||
{
|
||||
name: '小红书配图',
|
||||
width: 1242,
|
||||
height: 1660,
|
||||
icon: 'sd-shouji'
|
||||
},
|
||||
{
|
||||
name: '商品主图',
|
||||
width: 800,
|
||||
height: 800,
|
||||
icon: 'sd-wangye'
|
||||
},
|
||||
{
|
||||
name: '电商详情页',
|
||||
width: 750,
|
||||
height: 1000,
|
||||
icon: 'sd-wangye'
|
||||
},
|
||||
{
|
||||
name: '电商竖版海报',
|
||||
width: 750,
|
||||
height: 950,
|
||||
icon: 'sd-shouji'
|
||||
},
|
||||
{
|
||||
name: '电商横版海报',
|
||||
width: 750,
|
||||
height: 390,
|
||||
icon: 'sd-wangye'
|
||||
},
|
||||
{
|
||||
name: '小程序封面',
|
||||
width: 520,
|
||||
height: 416,
|
||||
icon: 'sd-weixin'
|
||||
},
|
||||
{
|
||||
name: '壁纸 / PPT(16:9)',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
icon: 'sd-wangye'
|
||||
}
|
||||
]
|
@ -1,8 +1,8 @@
|
||||
// element UI fix
|
||||
.el-collapse-item__header {
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
font-size: 14px !important;
|
||||
color: #666666 !important;
|
||||
user-select: none;
|
||||
}
|
||||
.el-collapse-item__wrap {
|
||||
|
@ -61,6 +61,9 @@
|
||||
// font-size: 18px;
|
||||
color: #333333;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 14px;
|
||||
}
|
||||
.text {
|
||||
font-weight: 600;
|
||||
margin-left: .4rem;
|
||||
|
@ -2,17 +2,17 @@
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2022-02-03 16:30:18
|
||||
* @Description: Type: success / info / warning / error
|
||||
* @LastEditors: ShawnPhang <site: book.palxp.com>, Jeremy Yu <https://github.com/JeremyYu-cn>
|
||||
* @LastEditTime: 2024-03-02 11:50:00
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 18:55:12
|
||||
*/
|
||||
import { ElMessageBox, messageType } from 'element-plus'
|
||||
export default (title: string = '提示', message: string = '', type: messageType = 'success') => {
|
||||
export default (title: string = '提示', message: string = '', type: messageType = 'success', extra?: any) => {
|
||||
return new Promise((resolve: Function) => {
|
||||
ElMessageBox.confirm(message, title, {
|
||||
ElMessageBox.confirm(message, title, Object.assign({
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type,
|
||||
})
|
||||
}, extra))
|
||||
.then(() => {
|
||||
resolve(true)
|
||||
})
|
||||
|
112
src/components/business/create-design/createDesign.vue
Normal file
112
src/components/business/create-design/createDesign.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-09 11:24:57
|
||||
* @Description: 创建/编辑画布尺寸
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 17:29:15
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog v-model="dialogVisible" center destroy-on-close :align-center="false" :title="params ? '编辑尺寸' : '新建空白设计'" width="380" draggable>
|
||||
<!-- <el-divider content-position="left">自定义尺寸</el-divider> -->
|
||||
<el-checkbox v-if="params" v-model="isAdaptive" label="自动调整元素大小位置" size="large" />
|
||||
<sizeEditor :params="page" :class="params ? 'editor-mode' : 'add-mode'">
|
||||
<el-button @click="finish" plain size="large" type="primary">{{ params ? '应用' : '创建' }}</el-button>
|
||||
</sizeEditor>
|
||||
<el-divider content-position="left">使用推荐尺寸</el-divider>
|
||||
<ul class="pre-list">
|
||||
<li @click="applySize(s)" class="item" v-for="(s, si) in sizes" :key="'s' + si">
|
||||
<i :class="['icon', s.icon]" /> {{ s.name }} <span class="info">{{ s.width }} × {{ s.height }} px</span>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- <template #footer>
|
||||
<el-button type="primary" @click="dialogVisible = false"> Confirm </el-button>
|
||||
</template> -->
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, Ref } from 'vue'
|
||||
import { ElCheckbox } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import sizeEditor from './sizeEditor.vue'
|
||||
import sizes from '@/assets/data/PageSizeData'
|
||||
import { useWidgetStore } from '@/store';
|
||||
|
||||
const router = useRouter()
|
||||
const widgetStore = useWidgetStore()
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
params?: any
|
||||
}>(),
|
||||
{
|
||||
params: undefined,
|
||||
},
|
||||
)
|
||||
const dialogVisible: Ref<boolean> = ref(false)
|
||||
const isAdaptive: Ref<boolean> = ref(true)
|
||||
const page: any = ref({ width: 100, height: 100 })
|
||||
|
||||
const applySize = ({ width, height }: any) => {
|
||||
page.value.width = width
|
||||
page.value.height = height
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
if (props.params) {
|
||||
page.value.width = props.params.width
|
||||
page.value.height = props.params.height
|
||||
}
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function finish() {
|
||||
const { width, height } = page.value
|
||||
if (props.params) {
|
||||
const lastPageData = JSON.parse(JSON.stringify(props.params))
|
||||
props.params.width = width
|
||||
props.params.height = height
|
||||
isAdaptive.value && widgetStore.autoResizeAll(lastPageData)
|
||||
} else window.open(router.resolve(`/home?mode=create&w_h=${width}*${height}`).href, '_blank')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.el-dialog__header) {
|
||||
padding-bottom: 7px !important;
|
||||
}
|
||||
.editor-mode {
|
||||
padding: 0 0 0.5rem 0;
|
||||
}
|
||||
.add-mode {
|
||||
padding: 1rem 0 0.5rem 0;
|
||||
}
|
||||
.pre-list {
|
||||
margin: 1rem 0;
|
||||
height: 245px;
|
||||
overflow-y: scroll;
|
||||
.item {
|
||||
padding: 10px 8px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
.icon {
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
.info {
|
||||
margin-left: 0.4rem;
|
||||
font-size: 12px;
|
||||
color: #b4b8bf;
|
||||
}
|
||||
}
|
||||
.item:hover {
|
||||
background-color: #f6f7f9;
|
||||
}
|
||||
}
|
||||
</style>
|
2
src/components/business/create-design/index.ts
Normal file
2
src/components/business/create-design/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import v from './createDesign.vue'
|
||||
export default v
|
101
src/components/business/create-design/sizeEditor.vue
Normal file
101
src/components/business/create-design/sizeEditor.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-08 21:33:59
|
||||
* @Description: 尺寸编辑
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-09 15:55:33
|
||||
-->
|
||||
<template>
|
||||
<div class="position-size">
|
||||
<number-input v-model="params.width" label="宽" :maxValue="5000" />
|
||||
<el-tooltip :show-after="300" :hide-after="0" effect="dark" :content="lockRatio ? '锁定宽高比' : '自由改变'" placement="top">
|
||||
<i @click="changeRatio" :class="['icon', lockRatio ? 'sd-db' : 'sd-fdb']" />
|
||||
</el-tooltip>
|
||||
<number-input v-model="params.height" label="高" :maxValue="5000" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import numberInput from '@/components/modules/settings/numberInput.vue'
|
||||
|
||||
type TProps = {
|
||||
params: any
|
||||
}
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
params: {},
|
||||
})
|
||||
|
||||
const lockRatio = ref(false) // 锁定比例缩放画布
|
||||
let scale = 0,
|
||||
temp = { width: 0, height: 0 }
|
||||
|
||||
watch(
|
||||
() => props.params.width,
|
||||
(val, old) => {
|
||||
if (scale && isNumber(val) && isNumber(old)) {
|
||||
temp.width === 0 && (temp.width = props.params.width)
|
||||
setChange()
|
||||
}
|
||||
},
|
||||
)
|
||||
watch(
|
||||
() => props.params.height,
|
||||
(val, old) => {
|
||||
if (scale && isNumber(val) && isNumber(old)) {
|
||||
temp.height === 0 && (temp.height = props.params.height)
|
||||
setChange()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// 锁定宽高比
|
||||
function changeRatio() {
|
||||
lockRatio.value = !lockRatio.value
|
||||
if (lockRatio.value) {
|
||||
scale = props.params.width / props.params.height
|
||||
} else scale = 0
|
||||
}
|
||||
|
||||
// 应用更改
|
||||
let timer: any = null
|
||||
function setChange() {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
temp.width > 0 && temp.height === 0 && (props.params.height = props.params.width / scale)
|
||||
temp.height > 0 && temp.width === 0 && (props.params.width = props.params.height * scale)
|
||||
if (temp.width > 0 && temp.height > 0) {
|
||||
temp = { width: 0, height: 0 }
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
|
||||
function isNumber(val: any) {
|
||||
return typeof val === 'number'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.position-size {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: space-between;
|
||||
width: 100%;
|
||||
.number-input {
|
||||
flex: 0.2;
|
||||
}
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
font-size: 19px;
|
||||
}
|
||||
.sd-fdb,
|
||||
.sd-db {
|
||||
color: #999999;
|
||||
margin: 0 6px 0 -4px;
|
||||
}
|
||||
.sd-db {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2021-08-04 11:46:39
|
||||
* @Description: 原版movable插件
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-11-14 11:41:23
|
||||
* @LastEditTime: 2024-04-06 14:56:35
|
||||
-->
|
||||
<template>
|
||||
<div id="empty" class="moveable__remove-item zk-moveable-style"></div>
|
||||
@ -275,7 +275,9 @@ onMounted(() => {
|
||||
triggerAblesSimultaneously: true,
|
||||
}
|
||||
|
||||
moveable = new Moveable(document.body, moveableOptions)
|
||||
// moveable = new Moveable(document.body, moveableOptions)
|
||||
const containerEl = document.querySelector('#main') as HTMLElement | SVGElement;
|
||||
moveable = new Moveable(containerEl, moveableOptions)
|
||||
|
||||
const helper = new MoveableHelper()
|
||||
|
||||
@ -578,12 +580,6 @@ onMounted(() => {
|
||||
key: 'left',
|
||||
value: item.left,
|
||||
})
|
||||
// store.dispatch("updateWidgetData", {
|
||||
// uuid: key,
|
||||
// key: 'left',
|
||||
// value: item.left,
|
||||
// })
|
||||
|
||||
widgetStore.updateWidgetData({
|
||||
uuid: key,
|
||||
key: 'top',
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2021-07-13 22:51:29
|
||||
* @Description: require.context自动引用
|
||||
* @LastEditors: ShawnPhang
|
||||
* @LastEditTime: 2022-04-08 10:28:47
|
||||
* @Description: Widgets、panel中所有组件将会自动全局引入
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-09 22:31:08
|
||||
*/
|
||||
import { App } from "vue"
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-08 19:19:17
|
||||
* @Description: 水印组件封装
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 21:30:12
|
||||
-->
|
||||
<template>
|
||||
<slot v-if="isDrawPage" />
|
||||
<el-watermark v-else :style="props.customStyle" :gap="[140, 120]" :content="watermark">
|
||||
<slot />
|
||||
</el-watermark>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { ElWatermark } from 'element-plus'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useBaseStore } from '@/store'
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
|
||||
type TProps = {
|
||||
customStyle: any
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
customStyle: {}
|
||||
})
|
||||
|
||||
const isDrawPage = computed(() => route.name === 'Draw')
|
||||
const baseStore = useBaseStore()
|
||||
const { watermark } = storeToRefs(baseStore)
|
||||
</script>
|
133
src/components/modules/layout/designBoard/comps/resize.vue
Normal file
133
src/components/modules/layout/designBoard/comps/resize.vue
Normal file
@ -0,0 +1,133 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-06 15:17:03
|
||||
* @Description: 画布尺寸操作柄
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 12:28:15
|
||||
-->
|
||||
<template>
|
||||
<div v-show="show" class="page-resize" :style="{ width: Math.floor(pw) + 'px', height: Math.floor(ph) + 'px' }">
|
||||
<div @mousedown="handlemousedown($event, 'ns', true)" class="resize__bar resize__bar-top"></div>
|
||||
<div @mousedown="handlemousedown($event, 'ew')" class="resize__bar resize__bar-right"></div>
|
||||
<div @mousedown="handlemousedown($event, 'ns')" class="resize__bar resize__bar-bottom"></div>
|
||||
<div @mousedown="handlemousedown($event, 'ew', true)" class="resize__bar resize__bar-left"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useWidgetStore, useCanvasStore } from '@/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
const widgetStore = useWidgetStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
|
||||
const props = defineProps<{
|
||||
width: number
|
||||
height: number
|
||||
}>()
|
||||
|
||||
type Direction = 'ns' | 'ew' // 上下 | 左右
|
||||
|
||||
const { dActiveElement } = storeToRefs(widgetStore)
|
||||
const show = computed(() => dActiveElement.value?.uuid === '-1')
|
||||
|
||||
let initData = { x: 0, y: 0, w: 0, h: 0 }
|
||||
let moveDir = ''
|
||||
let moveRev: any = undefined
|
||||
|
||||
const handlemousedown = (e: any, dir: Direction, isReverse?: boolean) => {
|
||||
moveDir = dir
|
||||
moveRev = isReverse
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
initData = { x: e.pageX, y: e.pageY, w: canvasStore.dPage.width, h: canvasStore.dPage.height }
|
||||
document.addEventListener('mousemove', handlemousemove, true)
|
||||
document.addEventListener('mouseup', stopMove, true)
|
||||
}
|
||||
|
||||
const stopMove = () => {
|
||||
document.removeEventListener('mousemove', handlemousemove, true)
|
||||
document.removeEventListener('mouseup', stopMove, true)
|
||||
}
|
||||
|
||||
function handlemousemove(e: any) {
|
||||
const { x, y, w, h } = initData
|
||||
if (moveDir === 'ew') {
|
||||
const dx = e.pageX - x
|
||||
const moveX = Math.floor((dx * 100) / canvasStore.dZoom)
|
||||
const result = moveRev ? w - moveX * 2 : w + moveX * 2
|
||||
result <= 5000 && result > 0 && (canvasStore.dPage.width = result)
|
||||
} else {
|
||||
const dy = e.pageY - y
|
||||
const moveY = Math.floor((dy * 100) / canvasStore.dZoom)
|
||||
const result = moveRev ? h - moveY * 2 : h + moveY * 2
|
||||
result <= 5000 && result > 0 && (canvasStore.dPage.height = result)
|
||||
}
|
||||
}
|
||||
|
||||
const pw = computed(() => props.width)
|
||||
const ph = computed(() => props.height)
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@bar-color: rgba(0, 0, 0, 0.2);
|
||||
|
||||
.page-resize {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
.resize__bar {
|
||||
pointer-events: auto;
|
||||
position: absolute;
|
||||
&-left {
|
||||
left: -14px;
|
||||
}
|
||||
&-right {
|
||||
right: -14px;
|
||||
}
|
||||
&-left,
|
||||
&-right {
|
||||
position: reactive;
|
||||
cursor: ew-resize;
|
||||
width: 10px;
|
||||
height: 24px;
|
||||
top: 50%;
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
&-left:after,
|
||||
&-right:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
left: 3px;
|
||||
width: 4px;
|
||||
height: 24px;
|
||||
border-radius: 12px;
|
||||
background: @bar-color;
|
||||
}
|
||||
&-top {
|
||||
top: -14px;
|
||||
}
|
||||
&-bottom {
|
||||
bottom: -12px;
|
||||
}
|
||||
&-top,
|
||||
&-bottom {
|
||||
cursor: ns-resize;
|
||||
width: 24px;
|
||||
height: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-12px);
|
||||
}
|
||||
&-top:after,
|
||||
&-bottom:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 4px;
|
||||
width: 24px;
|
||||
height: 4px;
|
||||
border-radius: 12px;
|
||||
background: @bar-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -10,7 +10,9 @@
|
||||
opacity: 1 - (dZoom < 100 ? dPage.tag : 0),
|
||||
}"
|
||||
>
|
||||
<slot />
|
||||
<slot />
|
||||
<resize-page :width="(dPage.width * dZoom) / 100" :height="(dPage.height * dZoom) / 100" />
|
||||
<watermark :customStyle="{ height: (dPage.height * dZoom) / 100 + 'px'}">
|
||||
<div
|
||||
:id="pageDesignCanvasId"
|
||||
class="design-canvas"
|
||||
@ -33,12 +35,6 @@
|
||||
@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()"
|
||||
@ -69,6 +65,7 @@
|
||||
<!-- <ref-line v-if="dSelectWidgets.length === 0" /> -->
|
||||
<!-- <size-control v-if="dSelectWidgets.length === 0" /> -->
|
||||
</div>
|
||||
</watermark>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -82,9 +79,11 @@ 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 { useCanvasStore, useControlStore, useGroupStore, useWidgetStore } from '@/store'
|
||||
import { useCanvasStore, useControlStore, useWidgetStore } from '@/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { TPageState } from '@/store/design/canvas/d'
|
||||
import resizePage from './comps/resize.vue'
|
||||
import watermark from './comps/pageWatermark.vue'
|
||||
// 页面设计组件
|
||||
type TProps = {
|
||||
pageDesignCanvasId: string
|
||||
|
@ -8,10 +8,9 @@
|
||||
</div>
|
||||
<el-collapse v-else v-model="state.activeNames">
|
||||
<el-collapse-item title="画布尺寸" name="1">
|
||||
<div class="position-size">
|
||||
<number-input v-model="state.innerElement.width" label="宽" :maxValue="5000" @finish="(value) => finish('width', value)" />
|
||||
<number-input v-model="state.innerElement.height" label="高" :maxValue="5000" @finish="(value) => finish('height', value)" />
|
||||
</div>
|
||||
<sizeEditor :params="state.innerElement">
|
||||
<i @click="openSizeEdit" class="icon sd-edit"></i>
|
||||
</sizeEditor>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="背景设置" name="2">
|
||||
<el-button style="width: 100%; margin: 0 0 1rem 0;" type="primary" link @click="state.showBgLib = true">在背景库中选择</el-button>
|
||||
@ -49,29 +48,27 @@
|
||||
<el-button v-show="state.mode === '图片' && state.innerElement.backgroundImage" class="btn-wrap" @click="shiftOut">将背景分离为图层</el-button>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<createDesign ref="sizeEditRef" :params="state.innerElement" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// 画布组件样式
|
||||
// const NAME = 'page-style'
|
||||
import { nextTick, onMounted, reactive, watch } from 'vue'
|
||||
|
||||
import numberInput from '../settings/numberInput.vue'
|
||||
import colorSelect, { colorChangeData } from '../settings/colorSelect.vue'
|
||||
import { nextTick, onMounted, reactive, watch, ref, Ref } from 'vue'
|
||||
import colorSelect, { colorChangeData } from '@/components/modules/settings/colorSelect.vue'
|
||||
import uploader, { TUploadDoneData } from '@/components/common/Uploader/index.vue'
|
||||
import api from '@/api'
|
||||
import _dl from '@/common/methods/download'
|
||||
// import ColorPipette from '@/utils/plugins/color-pipette'
|
||||
import Tabs from '@palxp/color-picker/comps/Tabs.vue'
|
||||
import TabPanel from '@palxp/color-picker/comps/TabPanel.vue'
|
||||
// import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||
import { useCanvasStore, useWidgetStore } from '@/store'
|
||||
import { TPageState } from '@/store/design/canvas/d'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { Delete as iconDelete, Download as iconDownload } from '@element-plus/icons-vue'
|
||||
import wImageSetting from '@/components/modules/widgets/wImage/wImageSetting'
|
||||
// import setImageData from '@/common/methods/DesignFeatures/setImage'
|
||||
import sizeEditor from '@/components/business/create-design/sizeEditor.vue'
|
||||
import createDesign from '@/components/business/create-design'
|
||||
|
||||
type TState = {
|
||||
activeNames: string[]
|
||||
@ -84,7 +81,6 @@ type TState = {
|
||||
showBgLib: boolean
|
||||
}
|
||||
|
||||
|
||||
const pageStore = useCanvasStore()
|
||||
const widgetStore = useWidgetStore()
|
||||
const state = reactive<TState>({
|
||||
@ -97,6 +93,7 @@ const state = reactive<TState>({
|
||||
modes: ['颜色', '图片'],
|
||||
showBgLib: false
|
||||
})
|
||||
const sizeEditRef: Ref<typeof createDesign | null> = ref(null)
|
||||
// const { dActiveElement } = useSetupMapGetters(['dActiveElement'])
|
||||
const { dActiveElement } = storeToRefs(widgetStore)
|
||||
let _localTempBG: string | null = null
|
||||
@ -164,8 +161,6 @@ function changeValue() {
|
||||
}
|
||||
|
||||
function finish(key: keyof TPageState, value: string | number) {
|
||||
console.log('111');
|
||||
|
||||
pageStore.updatePageData({
|
||||
key: key,
|
||||
value: value,
|
||||
@ -202,30 +197,32 @@ async function shiftOut() {
|
||||
setting.width = state.innerElement.width
|
||||
setting.height = state.innerElement.height
|
||||
setting.imgUrl = state.innerElement.backgroundImage
|
||||
// store.dispatch('addWidget', setting)
|
||||
setting.uuid = `bg-${(new Date()).getTime()}`
|
||||
widgetStore.dWidgets.unshift(setting)
|
||||
widgetStore.selectWidget({
|
||||
uuid: widgetStore.dWidgets[0].uuid,
|
||||
})
|
||||
// store.dispatch('selectWidget', {
|
||||
// uuid: store.getters.dWidgets[0].uuid,
|
||||
// })
|
||||
deleteBg()
|
||||
}
|
||||
|
||||
// 打开
|
||||
function openSizeEdit() {
|
||||
sizeEditRef.value?.open()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#page-style {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.position-size {
|
||||
display: flex;
|
||||
// justify-content: space-between;
|
||||
width: 100%;
|
||||
.number-input {
|
||||
flex: 0.25;
|
||||
.sd-edit {
|
||||
cursor: pointer;
|
||||
color: #666666;
|
||||
font-size: 22px;
|
||||
}
|
||||
.sd-edit:hover {
|
||||
color: #333333;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
.select {
|
@ -68,38 +68,12 @@ function alignAction(item: TIconItemSelectData) {
|
||||
uuid: element.uuid,
|
||||
group,
|
||||
})
|
||||
// store.dispatch('updateAlign', {
|
||||
// align: item.value,
|
||||
// uuid: element.uuid,
|
||||
// group,
|
||||
// })
|
||||
});
|
||||
historyStore.pushHistory()
|
||||
// store.dispatch('pushHistory')
|
||||
// pushHistory()
|
||||
})
|
||||
// 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: TdWidgetData[]) {
|
||||
widgetStore.setDWidgets(newLayer.toReversed())
|
||||
// store.commit('setDWidgets', newLayer.toReversed())
|
||||
|
||||
// store.commit('setShowMoveable', false)
|
||||
controlStore.setShowMoveable(false)
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2021-08-27 15:16:07
|
||||
* @Description: 背景图
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-03-11 01:42:36
|
||||
* @LastEditTime: 2024-04-09 22:29:51
|
||||
-->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
@ -50,13 +50,10 @@ type TState = {
|
||||
bgList: TGetImageListResult[]
|
||||
showList: boolean
|
||||
colors: string[]
|
||||
|
||||
}
|
||||
|
||||
const { model } = defineProps<TProps>()
|
||||
|
||||
|
||||
|
||||
const pageStore = useCanvasStore()
|
||||
const widgetStore = useWidgetStore()
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2021-08-27 15:16:07
|
||||
* @Description: 素材列表,主要用于文字组合列表
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-02-29 16:54:28
|
||||
* @LastEditTime: 2024-04-09 22:30:10
|
||||
-->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
@ -55,7 +55,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted } from 'vue'
|
||||
import api from '@/api'
|
||||
|
||||
import getComponentsData from '@/common/methods/DesignFeatures/setComponents'
|
||||
import DragHelper from '@/common/hooks/dragHelper'
|
||||
import setItem2Data from '@/common/methods/DesignFeatures/setImage'
|
||||
|
@ -118,13 +118,14 @@ function checkHeight() {
|
||||
isLess && load()
|
||||
}
|
||||
|
||||
let hideReplacePrompt: any = localStorage.getItem('hide_replace_prompt')
|
||||
async function selectItem(item: IGetTempListData) {
|
||||
controlStore.setShowMoveable(false) // 清理掉上一次的选择框
|
||||
|
||||
if (dHistoryParams.value.length > 0) {
|
||||
const isPass = await useConfirm('提示', '使用模板后,当前页面将会被替换,是否继续', 'warning')
|
||||
if (!isPass) {
|
||||
return false
|
||||
if (!hideReplacePrompt && dHistoryParams.value.length > 0) {
|
||||
const doNotPrompt = await useConfirm('添加到作品', '模板内容将替换页面内容', 'warning', {confirmButtonText: '知道了',cancelButtonText: '不再提示'})
|
||||
if (!doNotPrompt) {
|
||||
localStorage.setItem('hide_replace_prompt', '1')
|
||||
hideReplacePrompt = true
|
||||
}
|
||||
}
|
||||
userStore.managerEdit(false)
|
||||
|
@ -2,14 +2,14 @@
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2021-07-29 18:31:27
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang
|
||||
* @LastEditTime: 2022-04-07 23:26:51
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 07:36:58
|
||||
-->
|
||||
<template>
|
||||
<div class="icon-item-select">
|
||||
<span v-if="label" class="label">{{ label }}</span>
|
||||
<ul class="list btn__bar flex">
|
||||
<el-tooltip v-for="(item, index) in data" :key="index" class="item" effect="dark" :content="item.tip" placement="top" :auto-close="400">
|
||||
<el-tooltip v-for="(item, index) in data" :key="index" class="item" effect="dark" :content="item.tip" placement="top" :show-after="300" >
|
||||
<li :class="{ 'list-item': true, active: item.select }" @click="selectItem(item)">
|
||||
<i :class="`${item.extraIcon ? 'icon' : 'iconfont'} ${item.icon}`"></i>
|
||||
</li>
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-05 07:31:45
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 00:34:21
|
||||
*/
|
||||
// const prefix = import.meta.env
|
||||
const prefix = process.env
|
||||
|
||||
@ -16,7 +23,7 @@ export default {
|
||||
IMG_URL: 'https://store.palxp.cn/', // 七牛云资源地址
|
||||
// ICONFONT_URL: '//at.alicdn.com/t/font_3223711_74mlzj4jdue.css',
|
||||
ICONFONT_URL: '//at.alicdn.com/t/font_2717063_ypy8vprc3b.css?display=swap',
|
||||
ICONFONT_EXTRA: '//at.alicdn.com/t/c/font_3228074_8r5ffak8d5q.css',
|
||||
ICONFONT_EXTRA: '//at.alicdn.com/t/c/font_3228074_ljv2tbkwgqp.css',
|
||||
QINIUYUN_PLUGIN: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/qiniu-js/2.5.5/qiniu.min.js',
|
||||
supportSubFont: true, // 是否开启服务端字体压缩
|
||||
}
|
||||
|
@ -2,13 +2,12 @@
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2022-03-03 14:13:16
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>, Jeremy Yu <https://github.com/JeremyYu-cn>
|
||||
* @LastEditTime: 2024-02-26 17:54:00
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 18:19:35
|
||||
*/
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
// import store from './store'
|
||||
import utils from './utils'
|
||||
import 'normalize.css/normalize.css'
|
||||
import '@/assets/styles/index.less'
|
||||
|
@ -2,8 +2,8 @@
|
||||
* @Author: Jeremy Yu
|
||||
* @Date: 2024-03-17 15:00:00
|
||||
* @Description: Base全局状态管理
|
||||
* @LastEditors: Jeremy Yu <https://github.com/JeremyYu-cn>
|
||||
* @LastEditTime: 2024-03-18 21:00:00
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 17:00:12
|
||||
*/
|
||||
|
||||
import { Store, defineStore } from 'pinia'
|
||||
@ -13,7 +13,7 @@ import { Store, defineStore } from 'pinia'
|
||||
|
||||
type TStoreBaseState = {
|
||||
loading: boolean | null
|
||||
scroll: boolean
|
||||
watermark: string | string[]
|
||||
/** fonts */
|
||||
fonts: string[]
|
||||
}
|
||||
@ -21,13 +21,14 @@ type TStoreBaseState = {
|
||||
type TUserAction = {
|
||||
hideLoading: () => void
|
||||
setFonts: (list: string[]) => void
|
||||
changeWatermark: (e: string[] | string) => void
|
||||
}
|
||||
|
||||
/** Base全局状态管理 */
|
||||
const useBaseStore = defineStore<'base', TStoreBaseState, {}, TUserAction>('base', {
|
||||
state: () => ({
|
||||
loading: null,
|
||||
scroll: true,
|
||||
watermark: ['迅排设计', 'poster-design'],
|
||||
fonts: [], // 缓存字体列表
|
||||
}),
|
||||
actions: {
|
||||
@ -40,6 +41,9 @@ const useBaseStore = defineStore<'base', TStoreBaseState, {}, TUserAction>('base
|
||||
setFonts(list: string[]) {
|
||||
this.fonts = list
|
||||
},
|
||||
changeWatermark(wm: any) {
|
||||
this.watermark = wm
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* @Date: 2024-03-18 21:00:00
|
||||
* @Description: 画布全局配置
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-05 14:52:06
|
||||
* @LastEditTime: 2024-04-08 21:23:38
|
||||
*/
|
||||
|
||||
import { Store, defineStore } from 'pinia'
|
||||
|
@ -2,13 +2,13 @@
|
||||
* @Author: Jeremy Yu
|
||||
* @Date: 2024-03-18 21:00:00
|
||||
* @Description: Store方法export
|
||||
* @LastEditors: Jeremy Yu <https://github.com/JeremyYu-cn>
|
||||
* @LastEditTime: 2024-03-28 14:00:00
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 18:01:14
|
||||
*/
|
||||
|
||||
import { useCanvasStore, useControlStore } from "@/store"
|
||||
import { TWidgetStore } from ".."
|
||||
import { updateGroupSize } from "."
|
||||
import { useCanvasStore, useControlStore } from '@/store'
|
||||
import { TWidgetStore } from '..'
|
||||
import { updateGroupSize } from '.'
|
||||
|
||||
export type TInitResize = {
|
||||
startX: number
|
||||
@ -19,6 +19,18 @@ export type TInitResize = {
|
||||
height: number
|
||||
}
|
||||
|
||||
export type TSize = {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export type TdResizePayload = {
|
||||
x: number
|
||||
y: number
|
||||
/** 方向 */
|
||||
dirs: 'top' | 'left' | 'bottom' | 'right'
|
||||
}
|
||||
|
||||
/** 设置 resize 操作的初始值 */
|
||||
export function initDResize(store: TWidgetStore, payload: TInitResize) {
|
||||
const mouseXY = store.dMouseXY
|
||||
@ -32,24 +44,14 @@ export function initDResize(store: TWidgetStore, payload: TInitResize) {
|
||||
resizeWH.height = payload.height
|
||||
}
|
||||
|
||||
|
||||
export type TdResizePayload = {
|
||||
x: number
|
||||
y: number
|
||||
/** 方向 */
|
||||
dirs: "top" | "left" | "bottom" | "right"
|
||||
}
|
||||
|
||||
/** 更新组件宽高 */
|
||||
export function dResize(store: TWidgetStore, { x, y, dirs }: TdResizePayload) {
|
||||
const pageStore = useCanvasStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
const controlStore = useControlStore()
|
||||
|
||||
controlStore.setdResizeing(true)
|
||||
// store.state.dResizeing = true
|
||||
|
||||
const page = pageStore.dPage
|
||||
const page = canvasStore.dPage
|
||||
const target = store.dActiveElement
|
||||
const mouseXY = store.dMouseXY
|
||||
const widgetXY = store.dActiveWidgetXY
|
||||
@ -105,22 +107,39 @@ export function dResize(store: TWidgetStore, { x, y, dirs }: TdResizePayload) {
|
||||
}
|
||||
if (parent.uuid !== '-1') {
|
||||
updateGroupSize(store, parent.uuid)
|
||||
// store.dispatch('updateGroupSize', parent.uuid)
|
||||
}
|
||||
|
||||
canvasStore.reChangeCanvas()
|
||||
// store.dispatch('reChangeCanvas')
|
||||
}
|
||||
|
||||
export type TResize = {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export function resize(state: TWidgetStore, data: TResize) {
|
||||
const { width, height } = data
|
||||
const target = state.dActiveElement
|
||||
export function resize(store: TWidgetStore, size: TSize) {
|
||||
const { width, height } = size
|
||||
const target = store.dActiveElement
|
||||
if (!target) return target
|
||||
target.width = width
|
||||
target.height = height
|
||||
}
|
||||
|
||||
/** 自适应适配所有元素 */
|
||||
export function autoResizeAll(store: TWidgetStore, lastPageSize: TSize) {
|
||||
if (!lastPageSize) return
|
||||
const canvasStore = useCanvasStore()
|
||||
const { width: lastWidth, height: lastHeight } = lastPageSize
|
||||
const { width: pageWidth, height: pageHeight } = canvasStore.dPage
|
||||
const originWHRatio = lastWidth / lastHeight // 原始比例
|
||||
const WHRatio = pageWidth / pageHeight // 当前比例
|
||||
const changeFn = originWHRatio > WHRatio ? 'max' : 'min'
|
||||
const degree = [pageWidth / lastWidth, pageHeight / lastHeight]
|
||||
const ratio = Math[changeFn](...degree)
|
||||
const pageDiff = (pageWidth - lastWidth) / 2
|
||||
for (const widget of store.dWidgets) {
|
||||
const originWidth = widget.width
|
||||
let diff = 0
|
||||
if (widget.type === 'w-text') {
|
||||
widget.fontSize && (widget.fontSize *= ratio)
|
||||
} else widget.height *= ratio
|
||||
widget.width *= ratio
|
||||
diff = (originWidth - widget.width) / 2
|
||||
widget.left = widget.left + diff + pageDiff
|
||||
widget.top *= degree[1]
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,6 @@ export function selectWidget(store: TWidgetStore, { uuid }: TSelectWidgetData) {
|
||||
return
|
||||
}
|
||||
store.dSelectWidgets = []
|
||||
console.log("uuid", uuid);
|
||||
|
||||
if (uuid === '-1') {
|
||||
store.dActiveElement = pageStore.dPage
|
||||
const pageHistory = historyStore.dPageHistory
|
||||
|
@ -2,14 +2,14 @@
|
||||
* @Author: Jeremy Yu
|
||||
* @Date: 2024-03-18 21:00:00
|
||||
* @Description: Store方法export
|
||||
* @LastEditors: Jeremy Yu <https://github.com/JeremyYu-cn>
|
||||
* @LastEditTime: 2024-03-28 14:00:00
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-10 08:17:16
|
||||
*/
|
||||
|
||||
import { Store, defineStore } from "pinia";
|
||||
import { TInidDMovePayload, TMovePayload, dMove, initDMove, setDropOver, setMouseEvent, setdActiveElement, updateGroupSize, updateHoverUuid } from "./actions";
|
||||
import { TPageState } from "@/store/design/canvas/d";
|
||||
import { TInitResize, TResize, TdResizePayload, dResize, initDResize, resize } from "./actions/resize";
|
||||
import { TInitResize, TSize, TdResizePayload, dResize, initDResize, resize, autoResizeAll } from "./actions/resize";
|
||||
import { TUpdateWidgetMultiplePayload, TUpdateWidgetPayload, TsetWidgetStyleData, addWidget, deleteWidget, setDWidgets, setWidgetStyle, updateWidgetData, updateWidgetMultiple, lockWidgets } from "./actions/widget";
|
||||
import { addGroup } from "./actions/group";
|
||||
import { setTemplate } from "./actions/template";
|
||||
@ -113,12 +113,13 @@ type TAction = {
|
||||
/** 设置拖拽时在哪个图层 */
|
||||
setDropOver: (uuid: string) => void
|
||||
setSelectItem: (data: TselectItem) => void
|
||||
resize: (data: TResize) => void
|
||||
resize: (data: TSize) => void
|
||||
setWidgetStyle: (data: TsetWidgetStyleData) => void
|
||||
setDWidgets: (data: TdWidgetData[]) => void
|
||||
lockWidgets: () => void
|
||||
setMouseEvent: (e: MouseEvent | null) => void
|
||||
setdActiveElement: (data: TdWidgetData) => void
|
||||
autoResizeAll: (data: TSize) => void
|
||||
}
|
||||
|
||||
const WidgetStore = defineStore<"widgetStore", TWidgetState, TGetter, TAction>("widgetStore", {
|
||||
@ -180,6 +181,7 @@ const WidgetStore = defineStore<"widgetStore", TWidgetState, TGetter, TAction>("
|
||||
lockWidgets() { lockWidgets(this) },
|
||||
setMouseEvent(event) { setMouseEvent(this, event) },
|
||||
setdActiveElement(data) { setdActiveElement(this, data) },
|
||||
autoResizeAll(data) { autoResizeAll(this, data) }
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2021-07-14 11:43:13
|
||||
* @Description: 全局组件注册方法
|
||||
* @LastEditors: ShawnPhang
|
||||
* @LastEditTime: 2021-08-10 17:39:01
|
||||
* @Description: 全局组件导入
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 18:23:15
|
||||
*/
|
||||
// import { Button, Field, Divider, NavBar, Toast, Popup } from 'vant'
|
||||
import coms from '@/components/modules'
|
||||
import pageStyle from '@/components/modules/layout/designBoard/pageStyle.vue'
|
||||
import { App } from 'vue'
|
||||
|
||||
export default (Vue: App) => {
|
||||
coms(Vue)
|
||||
// Vue.component(Button.name, Button)
|
||||
Vue.component('page-style', pageStyle) // 背景属性已不在 modules/widgets 中,单独注册
|
||||
// Vue.use(Field).use(Divider).use(NavBar).use(Toast).use(Popup)
|
||||
}
|
||||
|
@ -11,13 +11,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { StyleValue, onMounted, reactive, nextTick } from 'vue'
|
||||
import api from '@/api'
|
||||
// import wGroup from '@/components/modules/widgets/wGroup/wGroup.vue'
|
||||
import Preload from '@/utils/plugins/preload'
|
||||
import FontFaceObserver from 'fontfaceobserver'
|
||||
import { fontWithDraw, font2style } from '@/utils/widgets/loadFontRule'
|
||||
import designBoard from '@/components/modules/layout/designBoard/index.vue'
|
||||
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
||||
// import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { wGroupSetting } from '@/components/modules/widgets/wGroup/groupSetting'
|
||||
import { storeToRefs } from 'pinia'
|
||||
@ -50,7 +48,7 @@ onMounted(() => {
|
||||
async function load() {
|
||||
let backgroundImage = ''
|
||||
let loadFlag = false
|
||||
const { id, tempid, tempType: type } = route.query
|
||||
const { id, tempid, tempType: type = 0 } = route.query
|
||||
if (id || tempid) {
|
||||
const postData = {
|
||||
id: Number(id || tempid),
|
||||
|
@ -4,7 +4,7 @@
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastUpdateContent: Support typescript
|
||||
* @LastEditTime: 2024-04-05 05:34:43
|
||||
* @LastEditTime: 2024-04-10 07:16:48
|
||||
-->
|
||||
<template>
|
||||
<div id="page-design-index" ref="pageDesignIndex" class="page-design-bg-color">
|
||||
@ -59,6 +59,8 @@
|
||||
/>
|
||||
<!-- 漫游导航 -->
|
||||
<Tour ref="tourRef" :steps="[ref1, ref2, ref3, ref4]" />
|
||||
<!-- 创建设计 -->
|
||||
<createDesign ref="createDesignRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -66,7 +68,7 @@
|
||||
import _config from '../config'
|
||||
import {
|
||||
CSSProperties, computed, nextTick,
|
||||
onBeforeUnmount, onMounted, reactive, ref,
|
||||
onBeforeUnmount, onMounted, reactive, ref, Ref
|
||||
} from 'vue'
|
||||
import RightClickMenu from '@/components/business/right-click-menu/RcMenu.vue'
|
||||
import Moveable from '@/components/business/moveable/Moveable.vue'
|
||||
@ -74,18 +76,16 @@ import designBoard from '@/components/modules/layout/designBoard/index.vue'
|
||||
import zoomControl from '@/components/modules/layout/zoomControl/index.vue'
|
||||
import lineGuides from '@/components/modules/layout/lineGuides.vue'
|
||||
import shortcuts from '@/mixins/shortcuts'
|
||||
// import wGroup from '@/components/modules/widgets/wGroup/wGroup.vue'
|
||||
import HeaderOptions from './components/HeaderOptions.vue'
|
||||
import Folder from './components/Folder.vue'
|
||||
import Helper from './components/Helper.vue'
|
||||
import ProgressLoading from '@/components/common/ProgressLoading/download.vue'
|
||||
// import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { wGroupSetting } from '@/components/modules/widgets/wGroup/groupSetting'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useCanvasStore, useControlStore, useHistoryStore, useWidgetStore, useGroupStore } from '@/store'
|
||||
import type { ButtonInstance } from 'element-plus'
|
||||
import Tour from './components/Tour.vue'
|
||||
import createDesign from '@/components/business/create-design'
|
||||
|
||||
const ref1 = ref<ButtonInstance>()
|
||||
const ref2 = ref<ButtonInstance>()
|
||||
@ -111,7 +111,6 @@ const groupStore = useGroupStore()
|
||||
const { dPage } = storeToRefs(useCanvasStore())
|
||||
const { dZoom } = storeToRefs(useCanvasStore())
|
||||
const { dHistoryParams } = storeToRefs(useHistoryStore())
|
||||
// const { dActiveElement, dCopyElement } = storeToRefs(widgetStore)
|
||||
|
||||
const state = reactive<TState>({
|
||||
style: {
|
||||
@ -128,7 +127,7 @@ const state = reactive<TState>({
|
||||
const optionsRef = ref<typeof HeaderOptions | null>(null)
|
||||
const zoomControlRef = ref<typeof zoomControl | null>(null)
|
||||
const controlStore = useControlStore()
|
||||
const route = useRoute()
|
||||
const createDesignRef: Ref<typeof createDesign | null> = ref(null)
|
||||
|
||||
const beforeUnload = function (e: Event): any {
|
||||
if (dHistoryParams.value.length > 0) {
|
||||
@ -211,16 +210,13 @@ function downloadCancel() {
|
||||
|
||||
function loadData() {
|
||||
// 初始化加载页面
|
||||
const { id, tempid, tempType } = route.query
|
||||
if (!optionsRef.value) return
|
||||
optionsRef.value.load(id, tempid, tempType, async () => {
|
||||
optionsRef.value.load(async () => {
|
||||
if (!zoomControlRef.value) return
|
||||
// await nextTick()
|
||||
// zoomControlRef.value.screenChange()
|
||||
|
||||
// 初始化激活的控件为page
|
||||
widgetStore.selectWidget({ uuid: '-1' })
|
||||
// store.dispatch('selectWidget', { uuid: '-1' })
|
||||
})
|
||||
}
|
||||
|
||||
@ -246,7 +242,10 @@ const fns: any = {
|
||||
download: () => {
|
||||
optionsRef.value?.download()
|
||||
},
|
||||
changeLineGuides
|
||||
changeLineGuides,
|
||||
newDesign: () => {
|
||||
createDesignRef.value?.open()
|
||||
}
|
||||
}
|
||||
const dealWith = (fnName: string, params?: any) => {
|
||||
fns[fnName](params)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2024-04-03 19:15:21
|
||||
* @Description: 文件
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-05 06:01:20
|
||||
* @LastEditTime: 2024-04-10 07:16:00
|
||||
-->
|
||||
<template>
|
||||
<el-dropdown trigger="click" size="large" placement="bottom-start">
|
||||
@ -12,7 +12,7 @@
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item><div class="item">创建设计</div></el-dropdown-item>
|
||||
<el-dropdown-item><div @click="$emit('select', 'newDesign')" class="item">创建设计</div></el-dropdown-item>
|
||||
<el-dropdown-item @click="openPSD">导入文件</el-dropdown-item>
|
||||
<el-dropdown-item @click="$emit('select', 'save')" divided>保存</el-dropdown-item>
|
||||
<el-dropdown-item @click="$emit('select', 'download')">导出文件</el-dropdown-item>
|
||||
@ -25,8 +25,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import { ref } from 'vue'
|
||||
import { useRouter} from 'vue-router'
|
||||
// import { ref, Ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElDropdown, ElDropdownItem, ElDropdownMenu } from 'element-plus'
|
||||
|
||||
const router = useRouter()
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2022-01-12 11:26:53
|
||||
* @Description: 顶部操作按钮组
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-05 05:37:53
|
||||
* @LastEditTime: 2024-04-09 23:39:24
|
||||
-->
|
||||
<template>
|
||||
<div class="top-title"><el-input v-model="state.title" placeholder="未命名的设计" class="input-wrap" /></div>
|
||||
@ -16,6 +16,7 @@
|
||||
<!-- <el-button @click="$store.commit('managerEdit', false)">取消</el-button> -->
|
||||
<div class="divide__line">|</div>
|
||||
</template>
|
||||
<watermark-option style="margin-right: .5rem;" />
|
||||
<!-- <el-button @click="draw">绘制(测试)</el-button> -->
|
||||
<!-- <copyRight> -->
|
||||
<slot />
|
||||
@ -39,6 +40,7 @@ import _config from '@/config'
|
||||
import useConfirm from '@/common/methods/confirm'
|
||||
import { useControlStore, useHistoryStore, useCanvasStore, useUserStore, useWidgetStore } from '@/store/index'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import watermarkOption from './Watermark.vue'
|
||||
|
||||
type TProps = {
|
||||
modelValue?: boolean
|
||||
@ -51,6 +53,7 @@ type TEmits = {
|
||||
|
||||
type TState= {
|
||||
stateBollean: boolean,
|
||||
wmBollean: boolean,
|
||||
title: string,
|
||||
loading: boolean,
|
||||
}
|
||||
@ -80,6 +83,7 @@ const { dHistory, dPageHistory } = storeToRefs(useHistoryStore())
|
||||
|
||||
const state = reactive<TState>({
|
||||
stateBollean: false,
|
||||
wmBollean: false,
|
||||
title: '',
|
||||
loading: false,
|
||||
})
|
||||
@ -91,7 +95,6 @@ async function save(hasCover: boolean = false) {
|
||||
return
|
||||
}
|
||||
|
||||
// store.commit('setShowMoveable', false) // 清理掉上一次的选择框
|
||||
controlStore.setShowMoveable(false) // 清理掉上一次的选择框
|
||||
|
||||
// console.log(proxy?.dPage, proxy?.dWidgets)
|
||||
@ -189,11 +192,17 @@ async function saveTemp() {
|
||||
|
||||
// ...mapActions(['pushHistory', 'addGroup']),
|
||||
|
||||
async function load(id: number, tempId: number, type: number, cb: () => void) {
|
||||
async function load(cb: () => void) {
|
||||
const { id, tempid: tempId, tempType: type, w_h } = route.query
|
||||
if (route.name !== 'Draw') {
|
||||
await useFontStore.init() // 初始化加载字体
|
||||
}
|
||||
const apiName = tempId && !id ? 'getTempDetail' : 'getWorks'
|
||||
if (w_h) {
|
||||
const wh: any = w_h.toString().split('*')
|
||||
wh[0] && (dPage.value.width = wh[0])
|
||||
wh[1] && (dPage.value.height = wh[1])
|
||||
}
|
||||
if (!id && !tempId) {
|
||||
cb()
|
||||
return
|
||||
|
22
src/views/components/Watermark.vue
Normal file
22
src/views/components/Watermark.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2024-04-08 16:50:04
|
||||
* @Description: 画布加水印
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2024-04-08 18:00:37
|
||||
-->
|
||||
<template>
|
||||
<el-switch v-model="wmBollean" @change="wmChange" size="large" inline-prompt style="--el-switch-off-color: #9999999e" active-text="移除水印" inactive-text="官方水印" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useBaseStore } from '@/store'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const wmBollean = ref(false)
|
||||
|
||||
function wmChange(isRemove: string | number | boolean) {
|
||||
baseStore.changeWatermark(isRemove ? '' : ['迅排设计', 'poster-design'])
|
||||
}
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user