feat: convert psd page to composition API

This commit is contained in:
IchliebedichZhu 2024-03-07 15:19:50 +00:00
parent 7eb44396b4
commit fddb5f3e7a
2 changed files with 151 additions and 119 deletions

View File

@ -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,16 +66,22 @@ 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
cancelText: string
}
// mixins: [shortcuts],
const state = reactive<TState>({
isDone: true, isDone: true,
downloadPercent: 0, // downloadPercent: 0, //
downloadText: '', downloadText: '',
@ -72,8 +90,11 @@ export default defineComponent({
}) })
const store = useStore() const store = useStore()
const route = useRoute() const route = useRoute()
const { proxy }: any = getCurrentInstance() as ComponentInternalInstance
let loading: any = null 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 () => {
@ -86,13 +107,15 @@ export default defineComponent({
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: any) {
async function selectFile(file: File) {
loading = useLoading() loading = useLoading()
await loadPSD(file) await loadPSD(file)
loading.close() loading.close()
state.isDone = true state.isDone = true
} }
async function loadPSD(file: any) {
async function loadPSD(file: File) {
// const { compositeBuffer, psdFile } = await myWorker.start(file) // const { compositeBuffer, psdFile } = await myWorker.start(file)
const data = await processPSD2Page(file) const data = await processPSD2Page(file)
@ -111,7 +134,7 @@ export default defineComponent({
const { width, height, background: bg } = data const { width, height, background: bg } = data
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, height, backgroundColor: bg.color, backgroundImage: bg.image }))
await proxy?.loadDone() await loadDone()
}, 10) }, 10)
} }
@ -123,56 +146,58 @@ export default defineComponent({
state.isDone = false state.isDone = false
} }
const optionsChange = ({ downloadPercent, downloadText, downloadMsg = '', cancelText = '' }: any) => { const optionsChange = ({ downloadPercent, downloadText, downloadMsg = '', cancelText = '' }: TEmitChangeData) => {
typeof downloadPercent === 'number' && (state.downloadPercent = downloadPercent) typeof downloadPercent === 'number' && (state.downloadPercent = downloadPercent)
state.downloadText = downloadText state.downloadText = downloadText
state.downloadMsg = downloadMsg state.downloadMsg = downloadMsg
state.cancelText = cancelText state.cancelText = cancelText
} }
const cancel = () => { const cancel = () => {
state.downloadPercent = 100 state.downloadPercent = 100
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${route.query.id}`) window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${route.query.id}`)
} }
return { const {handleKeydowm, handleKeyup,} = shortcuts.methods
...toRefs(state),
// ...mapGetters(['dPage', 'dZoom']),
onMounted(() => {
document.addEventListener('keydown', handleKeydowm, false)
document.addEventListener('keyup', handleKeyup, false)
loadJS()
})
onBeforeMount(() => {
document.removeEventListener('keydown', handleKeydowm, false)
document.removeEventListener('keyup', handleKeyup, false)
document.oncontextmenu = null
})
// ...mapActions(['selectWidget']),
async function loadDone() {
await nextTick()
if (!zoomControlRef.value) return
zoomControlRef.value.screenChange()
setTimeout(() => {
store.dispatch('selectWidget', { uuid: '-1' })
// selectWidget({
// 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, loadJS,
selectFile, selectFile,
clear, clear,
cancel, cancel,
optionsChange, optionsChange,
}
},
computed: {
...mapGetters(['dPage', 'dZoom']),
},
async mounted() {
document.addEventListener('keydown', this.handleKeydowm, false)
document.addEventListener('keyup', this.handleKeyup, false)
this.loadJS()
},
beforeUnmount() {
document.removeEventListener('keydown', this.handleKeydowm, false)
document.removeEventListener('keyup', this.handleKeyup, false)
document.oncontextmenu = null
},
methods: {
...mapActions(['selectWidget']),
async loadDone() {
await this.$nextTick()
;(this.$refs as any).zoomControl.screenChange()
setTimeout(() => {
this.selectWidget({
uuid: '-1',
})
// this.$store.commit('setShowMoveable', false)
}, 100)
},
jump2word() {
window.open('https://xp.palxp.cn/#/articles/1687855172725')
// window.open('https://kdocs.cn/l/clmBsIkhve8d')
},
},
}) })
</script> </script>

View File

@ -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
} }