mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
feat: convert psd page to composition API
This commit is contained in:
parent
7eb44396b4
commit
fddb5f3e7a
@ -12,10 +12,12 @@
|
|||||||
<div class="top-left">
|
<div class="top-left">
|
||||||
<div class="name" style="font-size: 15px">在线PSD解析</div>
|
<div class="name" style="font-size: 15px">在线PSD解析</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex: 1"><el-button plain type="primary" @click="jump2word">说明文档及PSD规范</el-button></div>
|
<div style="flex: 1">
|
||||||
<el-button v-show="isDone" @click="clear">清空模板</el-button>
|
<el-button plain type="primary" @click="jump2word">说明文档及PSD规范</el-button>
|
||||||
|
</div>
|
||||||
|
<el-button v-show="state.isDone" @click="clear">清空模板</el-button>
|
||||||
<div class="v-tips">
|
<div class="v-tips">
|
||||||
<HeaderOptions :isDone="isDone" @change="optionsChange" />
|
<HeaderOptions :isDone="state.isDone" @change="optionsChange" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -23,28 +25,38 @@
|
|||||||
<div class="page-design-index-wrap">
|
<div class="page-design-index-wrap">
|
||||||
<!-- <widget-panel></widget-panel> -->
|
<!-- <widget-panel></widget-panel> -->
|
||||||
<design-board class="page-design-wrap" pageDesignCanvasId="page-design-canvas">
|
<design-board class="page-design-wrap" pageDesignCanvasId="page-design-canvas">
|
||||||
<div v-if="isDone" class="shelter" :style="{ width: (dPage.width * dZoom) / 100 + 'px', height: (dPage.height * dZoom) / 100 + 'px' }"></div>
|
<div v-if="state.isDone" class="shelter" :style="{ width: (dPage.width * dZoom) / 100 + 'px', height: (dPage.height * dZoom) / 100 + 'px' }"></div>
|
||||||
<uploader v-else accept=".psd" :hold="true" :drag="true" class="uploader" @load="selectFile">
|
<uploader v-else accept=".psd" :hold="true" :drag="true" class="uploader" @load="selectFile">
|
||||||
<div class="uploader__box"><img style="margin-right: 1rem" src="https://cdn.dancf.com/design/svg/icon_psdimport.37e6f23e.svg" /> 在此拖入或选择PSD文件</div>
|
<div class="uploader__box">
|
||||||
|
<img
|
||||||
|
style="margin-right: 1rem"
|
||||||
|
src="https://cdn.dancf.com/design/svg/icon_psdimport.37e6f23e.svg"
|
||||||
|
alt="upload"
|
||||||
|
/> 在此拖入或选择PSD文件
|
||||||
|
</div>
|
||||||
</uploader>
|
</uploader>
|
||||||
</design-board>
|
</design-board>
|
||||||
<style-panel v-show="isDone"></style-panel>
|
<style-panel v-show="state.isDone"></style-panel>
|
||||||
</div>
|
</div>
|
||||||
<!-- 缩放控制 -->
|
<!-- 缩放控制 -->
|
||||||
<zoom-control v-if="isDone" ref="zoomControl" />
|
<zoom-control v-if="state.isDone" ref="zoomControlRef" />
|
||||||
<!-- 右键菜单 -->
|
<!-- 右键菜单 -->
|
||||||
<right-click-menu />
|
<right-click-menu />
|
||||||
<!-- 旋转缩放组件 -->
|
<!-- 旋转缩放组件 -->
|
||||||
<Moveable />
|
<Moveable />
|
||||||
<!-- 遮罩百分比进度条 -->
|
<!-- 遮罩百分比进度条 -->
|
||||||
<ProgressLoading :percent="downloadPercent" :text="downloadText" :cancelText="cancelText" :msg="downloadMsg" @cancel="cancel" @done="downloadPercent = 0" />
|
<ProgressLoading
|
||||||
|
:percent="state.downloadPercent" :text="state.downloadText"
|
||||||
|
:cancelText="state.cancelText" :msg="state.downloadMsg"
|
||||||
|
@cancel="cancel" @done="state.downloadPercent = 0"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, reactive, toRefs, getCurrentInstance, ComponentInternalInstance, onMounted, nextTick } from 'vue'
|
import { reactive, onMounted, nextTick, onBeforeMount, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { mapActions, mapGetters, useStore } from 'vuex'
|
import { useStore } 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 shortcuts from '@/mixins/shortcuts'
|
import shortcuts from '@/mixins/shortcuts'
|
||||||
@ -54,125 +66,138 @@ 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/index.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, { TEmitChangeData } from './components/UploadTemplate.vue'
|
||||||
import ProgressLoading from '@/components/common/ProgressLoading/index.vue'
|
import ProgressLoading from '@/components/common/ProgressLoading/index.vue'
|
||||||
// import MyWorker from '@/utils/plugins/webWorker'
|
// import MyWorker from '@/utils/plugins/webWorker'
|
||||||
import { processPSD2Page } from '@/utils/plugins/psd'
|
import { processPSD2Page } from '@/utils/plugins/psd'
|
||||||
|
import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||||
|
|
||||||
export default defineComponent({
|
type TState = {
|
||||||
components: { RightClickMenu, Moveable, uploader, designBoard, zoomControl, HeaderOptions, ProgressLoading },
|
isDone: boolean
|
||||||
mixins: [shortcuts],
|
downloadPercent: number // 下载进度
|
||||||
setup() {
|
downloadText: string
|
||||||
const state = reactive({
|
downloadMsg: string
|
||||||
isDone: true,
|
cancelText: string
|
||||||
downloadPercent: 0, // 下载进度
|
}
|
||||||
downloadText: '',
|
|
||||||
downloadMsg: '',
|
// mixins: [shortcuts],
|
||||||
cancelText: '',
|
const state = reactive<TState>({
|
||||||
})
|
isDone: true,
|
||||||
const store = useStore()
|
downloadPercent: 0, // 下载进度
|
||||||
const route = useRoute()
|
downloadText: '',
|
||||||
const { proxy }: any = getCurrentInstance() as ComponentInternalInstance
|
downloadMsg: '',
|
||||||
let loading: any = null
|
cancelText: '',
|
||||||
|
})
|
||||||
|
const store = useStore()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const { dPage, dZoom } = useSetupMapGetters(['dPage', 'dZoom'])
|
||||||
|
const zoomControlRef = ref<typeof zoomControl | null>()
|
||||||
|
|
||||||
|
let loading: ReturnType<typeof useLoading> | null = null
|
||||||
// const myWorker = new MyWorker('loadPSD')
|
// const myWorker = new MyWorker('loadPSD')
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
state.isDone = false
|
state.isDone = false
|
||||||
})
|
})
|
||||||
|
|
||||||
function loadJS() {
|
function loadJS() {
|
||||||
const link_element = document.createElement('script')
|
const link_element = document.createElement('script')
|
||||||
link_element.setAttribute('src', '/psd.js')
|
link_element.setAttribute('src', '/psd.js')
|
||||||
document.head.appendChild(link_element)
|
document.head.appendChild(link_element)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectFile(file: File) {
|
||||||
|
loading = useLoading()
|
||||||
|
await loadPSD(file)
|
||||||
|
loading.close()
|
||||||
|
state.isDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadPSD(file: File) {
|
||||||
|
// const { compositeBuffer, psdFile } = await myWorker.start(file)
|
||||||
|
const data = await processPSD2Page(file)
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
const types: any = {
|
||||||
|
text: wText.setting,
|
||||||
|
image: wImage.setting,
|
||||||
}
|
}
|
||||||
async function selectFile(file: any) {
|
for (let i = 0; i < data.clouds.length; i++) {
|
||||||
loading = useLoading()
|
const x: any = data.clouds[i]
|
||||||
await loadPSD(file)
|
const rawData = JSON.parse(JSON.stringify(types[x.type])) || {}
|
||||||
loading.close()
|
delete x.type
|
||||||
state.isDone = true
|
x.src && (x.imgUrl = x.src) && delete x.src
|
||||||
}
|
store.dispatch('addWidget', Object.assign(rawData, x))
|
||||||
async function loadPSD(file: any) {
|
|
||||||
// const { compositeBuffer, psdFile } = await myWorker.start(file)
|
|
||||||
const data = await processPSD2Page(file)
|
|
||||||
|
|
||||||
setTimeout(async () => {
|
|
||||||
const types: any = {
|
|
||||||
text: wText.setting,
|
|
||||||
image: wImage.setting,
|
|
||||||
}
|
|
||||||
for (let i = 0; i < data.clouds.length; i++) {
|
|
||||||
const x: any = data.clouds[i]
|
|
||||||
const rawData = JSON.parse(JSON.stringify(types[x.type])) || {}
|
|
||||||
delete x.type
|
|
||||||
x.src && (x.imgUrl = x.src) && delete x.src
|
|
||||||
store.dispatch('addWidget', Object.assign(rawData, x))
|
|
||||||
}
|
|
||||||
|
|
||||||
const { width, height, background: bg } = data
|
|
||||||
store.commit('setDPage', Object.assign(store.getters.dPage, { width, height, backgroundColor: bg.color, backgroundImage: bg.image }))
|
|
||||||
await proxy?.loadDone()
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clear() {
|
const { width, height, background: bg } = data
|
||||||
store.commit('setDWidgets', [])
|
store.commit('setDPage', Object.assign(store.getters.dPage, { width, height, backgroundColor: bg.color, backgroundImage: bg.image }))
|
||||||
store.commit('setDPage', Object.assign(store.getters.dPage, { width: 1920, height: 1080, backgroundColor: '#ffffff', backgroundImage: '' }))
|
await loadDone()
|
||||||
store.commit('setShowMoveable', false)
|
}, 10)
|
||||||
await nextTick()
|
}
|
||||||
state.isDone = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionsChange = ({ downloadPercent, downloadText, downloadMsg = '', cancelText = '' }: any) => {
|
async function clear() {
|
||||||
typeof downloadPercent === 'number' && (state.downloadPercent = downloadPercent)
|
store.commit('setDWidgets', [])
|
||||||
state.downloadText = downloadText
|
store.commit('setDPage', Object.assign(store.getters.dPage, { width: 1920, height: 1080, backgroundColor: '#ffffff', backgroundImage: '' }))
|
||||||
state.downloadMsg = downloadMsg
|
store.commit('setShowMoveable', false)
|
||||||
state.cancelText = cancelText
|
await nextTick()
|
||||||
}
|
state.isDone = false
|
||||||
const cancel = () => {
|
}
|
||||||
state.downloadPercent = 100
|
|
||||||
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${route.query.id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
const optionsChange = ({ downloadPercent, downloadText, downloadMsg = '', cancelText = '' }: TEmitChangeData) => {
|
||||||
...toRefs(state),
|
typeof downloadPercent === 'number' && (state.downloadPercent = downloadPercent)
|
||||||
loadJS,
|
state.downloadText = downloadText
|
||||||
selectFile,
|
state.downloadMsg = downloadMsg
|
||||||
clear,
|
state.cancelText = cancelText
|
||||||
cancel,
|
}
|
||||||
optionsChange,
|
|
||||||
}
|
const cancel = () => {
|
||||||
},
|
state.downloadPercent = 100
|
||||||
computed: {
|
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${route.query.id}`)
|
||||||
...mapGetters(['dPage', 'dZoom']),
|
}
|
||||||
},
|
|
||||||
async mounted() {
|
const {handleKeydowm, handleKeyup,} = shortcuts.methods
|
||||||
document.addEventListener('keydown', this.handleKeydowm, false)
|
|
||||||
document.addEventListener('keyup', this.handleKeyup, false)
|
// ...mapGetters(['dPage', 'dZoom']),
|
||||||
this.loadJS()
|
|
||||||
},
|
onMounted(() => {
|
||||||
beforeUnmount() {
|
document.addEventListener('keydown', handleKeydowm, false)
|
||||||
document.removeEventListener('keydown', this.handleKeydowm, false)
|
document.addEventListener('keyup', handleKeyup, false)
|
||||||
document.removeEventListener('keyup', this.handleKeyup, false)
|
loadJS()
|
||||||
document.oncontextmenu = null
|
})
|
||||||
},
|
|
||||||
methods: {
|
onBeforeMount(() => {
|
||||||
...mapActions(['selectWidget']),
|
document.removeEventListener('keydown', handleKeydowm, false)
|
||||||
async loadDone() {
|
document.removeEventListener('keyup', handleKeyup, false)
|
||||||
await this.$nextTick()
|
document.oncontextmenu = null
|
||||||
;(this.$refs as any).zoomControl.screenChange()
|
})
|
||||||
setTimeout(() => {
|
// ...mapActions(['selectWidget']),
|
||||||
this.selectWidget({
|
|
||||||
uuid: '-1',
|
async function loadDone() {
|
||||||
})
|
await nextTick()
|
||||||
// this.$store.commit('setShowMoveable', false)
|
if (!zoomControlRef.value) return
|
||||||
}, 100)
|
zoomControlRef.value.screenChange()
|
||||||
},
|
setTimeout(() => {
|
||||||
jump2word() {
|
store.dispatch('selectWidget', { uuid: '-1' })
|
||||||
window.open('https://xp.palxp.cn/#/articles/1687855172725')
|
// selectWidget({
|
||||||
// window.open('https://kdocs.cn/l/clmBsIkhve8d')
|
// uuid: '-1',
|
||||||
},
|
// })
|
||||||
},
|
// this.$store.commit('setShowMoveable', false)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
function jump2word() {
|
||||||
|
window.open('https://xp.palxp.cn/#/articles/1687855172725')
|
||||||
|
// window.open('https://kdocs.cn/l/clmBsIkhve8d')
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
loadJS,
|
||||||
|
selectFile,
|
||||||
|
clear,
|
||||||
|
cancel,
|
||||||
|
optionsChange,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -28,8 +28,15 @@ type TProps = {
|
|||||||
isDone?: boolean
|
isDone?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TEmitChangeData = {
|
||||||
|
downloadPercent: number | null
|
||||||
|
downloadText: string
|
||||||
|
downloadMsg?: string
|
||||||
|
cancelText?: string
|
||||||
|
}
|
||||||
|
|
||||||
type TEmits = {
|
type TEmits = {
|
||||||
(event: 'change', data: { downloadPercent: number | null, downloadText: string, downloadMsg?: string, cancelText?: string }): void
|
(event: 'change', data: TEmitChangeData): void
|
||||||
(event: 'update:modelValue', data: string): void
|
(event: 'update:modelValue', data: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user