mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
Merge pull request #108 from JeremyYu-cn/feat-upgrade-vue3
Merge: main branch
This commit is contained in:
commit
5049f059e0
@ -1,10 +1,15 @@
|
||||
// element UI fix
|
||||
.el-collapse-item__header {
|
||||
padding: 0px 10px;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
user-select: none;
|
||||
}
|
||||
.el-collapse-item__wrap {
|
||||
padding: 0px 10px;
|
||||
padding: 0;
|
||||
}
|
||||
.el-collapse-item__content {
|
||||
padding-bottom: 18px !important;
|
||||
}
|
||||
.el-collapse {
|
||||
border: 0px;
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div id="widget-panel">
|
||||
<div class="widget-classify">
|
||||
<ul class="classify-wrap">
|
||||
<li v-for="(item, index) in state.widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': state.activeWidgetClassify === index }]" @click="clickClassify(index)">
|
||||
<li v-for="(item, index) in state.widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': state.activeWidgetClassify === index && state.active }]" @click="clickClassify(index)">
|
||||
<div class="icon-box"><i :class="['iconfont', 'icon', item.icon]" :style="item.style" /></div>
|
||||
<p>{{ item.name }}</p>
|
||||
</li>
|
||||
@ -16,9 +16,9 @@
|
||||
</div>
|
||||
<!-- <div v-show="active" class="side-wrap"><div class="pack__up" @click="active = false"><</div></div> -->
|
||||
<div v-show="state.active" class="side-wrap">
|
||||
<!-- <el-tooltip effect="dark" content="收起侧边栏" placement="right"> -->
|
||||
<el-tooltip :show-after="300" :hide-after="0" effect="dark" content="关闭侧边栏" placement="right">
|
||||
<div class="pack__up" @click="state.active = false"></div>
|
||||
<!-- </el-tooltip> -->
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -142,6 +142,7 @@ defineExpose({
|
||||
}
|
||||
.widget-wrap {
|
||||
width: 328px;
|
||||
transition: all .3s;
|
||||
background-color: @color-white;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
|
@ -12,18 +12,17 @@
|
||||
<template v-if="state.effectSelect">
|
||||
<component :is="state.effectSelect" class="demo" />
|
||||
</template>
|
||||
<div v-show="!state.effectSelect">无</div>
|
||||
<span class="title">图片容器</span>
|
||||
<!-- <div v-show="!state.effectSelect">无</div> -->
|
||||
<span class="title">图片蒙版</span>
|
||||
<el-popover :visible="state.visiable" placement="bottom-end" :width="260" trigger="click">
|
||||
<div class="box__header">
|
||||
<el-radio-group v-model="state.type" size="small">
|
||||
<el-radio-button label="160">形状</el-radio-button>
|
||||
<el-radio-button label="166">框架</el-radio-button>
|
||||
<el-radio-button label="图形" value="tuxing"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="select__box">
|
||||
<div class="select__box__select-item" @click="select()">无</div>
|
||||
<el-image v-for="(item, i) in state.list" :key="i + 'l'" class="select__box__select-item" :src="item.thumbUrl" fit="contain" @click="select(item.imgUrl)"></el-image>
|
||||
<div class="select__box__select-item" @click="select()"> 无 </div>
|
||||
<el-image v-for="(item, i) in state.list" :key="i + 'l'" class="select__box__select-item" :src="item.thumb" fit="contain" @click="select(item.url)"></el-image>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button class="button" link @click="state.visiable = !state.visiable">{{ state.visiable ? '取消' : '选择' }}</el-button>
|
||||
@ -31,10 +30,6 @@
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <div v-show="effectSelect" class="text item">
|
||||
<span class="strength">强度</span>
|
||||
<el-slider v-model="strength" show-input input-size="small" :show-input-controls="false"> </el-slider>
|
||||
</div> -->
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
@ -59,7 +54,7 @@ type TState = {
|
||||
effectSelect: string
|
||||
visiable: boolean
|
||||
type: string
|
||||
list: {thumbUrl: string, imgUrl: string}[]
|
||||
list: {thumb: string, url: string}[]
|
||||
}
|
||||
|
||||
const props = defineProps<TProps>()
|
||||
@ -67,10 +62,9 @@ const props = defineProps<TProps>()
|
||||
const emit = defineEmits<TEmits>()
|
||||
|
||||
const state = reactive<TState>({
|
||||
// strength: 20, // 强度
|
||||
effectSelect: '', // 选择的模板
|
||||
visiable: false, // 弹出选择层控制
|
||||
type: '166', // 类型
|
||||
type: '1', // 类型
|
||||
list: [],
|
||||
})
|
||||
|
||||
@ -91,11 +85,11 @@ onMounted(async () => {
|
||||
|
||||
async function getList() {
|
||||
const res = await api.material.getList({
|
||||
first_id: 2,
|
||||
second_id: state.type,
|
||||
cate: 8,
|
||||
pageSize: 29
|
||||
})
|
||||
state.list = res.list.map(({ thumbUrl, imgUrl }) => {
|
||||
return { thumbUrl, imgUrl }
|
||||
state.list = res.list.map(({ thumb, url }) => {
|
||||
return { thumb, url }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -18,17 +18,35 @@
|
||||
<Tabs :value="state.mode" @update:value="onChangeMode">
|
||||
<TabPanel v-for="label in state.modes" :key="label" :label="label"></TabPanel>
|
||||
</Tabs>
|
||||
<color-select v-show="state.mode === '颜色'" v-model="state.innerElement.backgroundColor" :modes="['纯色']" @change="colorChange" @finish="(value) => finish('backgroundColor', value)" />
|
||||
<!-- <bg-img-select :img="innerElement.backgroundImage"/> -->
|
||||
<div v-if="state.mode === '图片' && state.innerElement.backgroundImage" style="margin-top: 2rem">
|
||||
<el-image style="max-height: 428px" :src="state.innerElement.backgroundImage" fit="contain"></el-image>
|
||||
<el-button class="btn-wrap" size="small" @click="deleteBg">删除</el-button>
|
||||
<color-select v-show="state.mode === '颜色'" v-model="state.innerElement.backgroundColor" :modes="['纯色','渐变']" @change="colorChange" @finish="(value) => finish('backgroundColor', value)" />
|
||||
<div v-if="state.mode === '图片' && state.innerElement.backgroundImage" style="margin-top: 1.2rem">
|
||||
<div class="backgroud-wrap">
|
||||
<el-image style="height: 100%" :src="state.innerElement.backgroundImage" fit="contain"></el-image>
|
||||
<div class="bg-control">
|
||||
<div class="btns">
|
||||
<uploader style="width: 47%;" @done="uploadImgDone">
|
||||
<el-button style="width: 100%;" plain>上传图片</el-button>
|
||||
</uploader>
|
||||
<el-button style="width: 47%;" @click="state.showBgLib = true" plain>背景库</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-options">
|
||||
<el-tooltip :show-after="300" :hide-after="0" effect="dark" content="下载图片" placement="top">
|
||||
<div @click="downloadBG" class="btn-item"><icon-download width="16" /></div>
|
||||
</el-tooltip>
|
||||
<el-tooltip :show-after="300" :hide-after="0" effect="dark" content="删除" placement="top">
|
||||
<div @click="deleteBg" class="btn-item"><icon-delete width="16" /></div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <el-image style="max-height: 428px" :src="state.innerElement.backgroundImage" fit="contain"></el-image> -->
|
||||
<!-- <el-button class="btn-wrap" size="small" @click="deleteBg">删除</el-button> -->
|
||||
</div>
|
||||
<uploader v-show="state.mode === '图片'" class="btn-wrap" @done="uploadImgDone">
|
||||
<el-button style="width: 100%" plain>{{ state.innerElement.backgroundImage ? '更换背景' : '上传背景' }}图</el-button>
|
||||
<uploader v-show="state.mode === '图片' && !state.innerElement.backgroundImage" class="btn-wrap" @done="uploadImgDone">
|
||||
<el-button style="width: 100%" plain>上传背景图</el-button>
|
||||
</uploader>
|
||||
<el-button v-show="state.mode === '图片' && state.innerElement.backgroundImage" class="btn-wrap" size="small" @click="downloadBG">{{ state.downP ? state.downP + ' %' : '下载背景图' }}</el-button>
|
||||
|
||||
<!-- <el-button v-show="state.mode === '图片' && state.innerElement.backgroundImage" class="btn-wrap" size="small" @click="downloadBG">{{ state.downP ? state.downP + ' %' : '下载背景图' }}</el-button> -->
|
||||
<el-button v-show="state.mode === '图片' && state.innerElement.backgroundImage" class="btn-wrap" @click="shiftOut">将背景分离为图层</el-button>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
@ -48,6 +66,9 @@ import _dl from '@/common/methods/download'
|
||||
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 { 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'
|
||||
|
||||
type TState = {
|
||||
activeNames: string[]
|
||||
@ -97,6 +118,8 @@ onMounted(() => {
|
||||
// ...mapActions(['updatePageData']),
|
||||
function colorChange(e: colorChangeData) {
|
||||
if (e.mode === '渐变') {
|
||||
console.log('渐变背景');
|
||||
|
||||
// setTimeout(() => {
|
||||
// console.log(1, e)
|
||||
// this.finish('backgroundImage', e.color)
|
||||
@ -171,26 +194,22 @@ async function downloadBG() {
|
||||
state.downP = p < 99 ? p / 100 : 0
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* :deep(.el-collapse-item__header) {
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
} */
|
||||
.el-collapse-item__header {
|
||||
padding: 0 !important;
|
||||
font-size: 14px !important;
|
||||
color: #666666 !important;
|
||||
// 分离背景图,添加到画布中
|
||||
async function shiftOut() {
|
||||
let setting = JSON.parse(JSON.stringify(wImageSetting))
|
||||
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()}`
|
||||
store.getters.dWidgets.unshift(setting)
|
||||
store.dispatch('selectWidget', {
|
||||
uuid: store.getters.dWidgets[0].uuid,
|
||||
})
|
||||
deleteBg()
|
||||
}
|
||||
.el-collapse-item__wrap {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.el-collapse-item__content {
|
||||
padding-bottom: 18px !important;
|
||||
}
|
||||
</style>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#page-style {
|
||||
@ -209,7 +228,7 @@ async function downloadBG() {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.btn-wrap {
|
||||
width: 100%; margin-top: 0.7rem;
|
||||
width: 100%; margin-top: 1.2rem;
|
||||
}
|
||||
.header {
|
||||
&-back {
|
||||
@ -229,4 +248,56 @@ async function downloadBG() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.backgroud-wrap {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 160px;
|
||||
padding: 16px;
|
||||
background-color: #f1f2f4;
|
||||
border-radius: 8px;
|
||||
.bg-options {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
display: flex;
|
||||
}
|
||||
.btn-item {
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
background-color: #ffffff;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: none;
|
||||
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.08), 0px 4px 12px 0px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.bg-control {
|
||||
transition: all 0.3s;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.07);
|
||||
.btns {
|
||||
padding: 0 2%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
.bg-control:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -21,7 +21,7 @@
|
||||
>
|
||||
<img class="edit__model" :src="params.imgUrl" />
|
||||
</div>
|
||||
<div :style="{ transform: params.flip ? `rotate${params.flip}(180deg)` : undefined, borderRadius: params.radius + 'px', '-webkit-mask-image': `${params.mask ? `url('${params.mask}')` : undefined}` }" :class="['img__box', { mask: params.mask }]">
|
||||
<div :style="{ transform: params.flip ? `rotate${params.flip}(180deg)` : undefined, borderRadius: params.radius + 'px', '-webkit-mask-image': `${params.mask ? `url('${params.mask}')` : 'initial'}` }" :class="['img__box', { mask: params.mask }]">
|
||||
<div v-if="params.isNinePatch" ref="targetRef" class="target" :style="{ border: `${(params.height * params.sliceData.ratio) / 2}px solid transparent`, borderImage: `url('${params.imgUrl}') ${params.sliceData.left} round` }"></div>
|
||||
<img v-else ref="targetRef" class="target" style="transform-origin: center" :src="params.imgUrl" />
|
||||
</div>
|
||||
|
@ -28,8 +28,7 @@
|
||||
</uploader> -->
|
||||
<el-button size="small" disabled plain @click="openCropper">美化</el-button>
|
||||
</div>
|
||||
<!-- <container-wrap @change="changeContainer" />
|
||||
<br /> -->
|
||||
<container-wrap @change="changeContainer" />
|
||||
<div class="slide-wrap">
|
||||
<number-slider v-model="state.innerElement.opacity" style="font-size: 14px" label="不透明" :step="0.05" :maxValue="1" @finish="(value) => finish('opacity', value)" />
|
||||
<number-slider v-model="state.innerElement.radius" style="font-size: 14px" label="圆角" :maxValue="Math.min(Number(state.innerElement.record?.width), Number(state.innerElement.record?.height))" @finish="(value) => finish('radius', value)" />
|
||||
@ -78,7 +77,7 @@ import iconItemSelect, { TIconItemSelectData } from '../../settings/iconItemSele
|
||||
import numberSlider from '../../settings/numberSlider.vue'
|
||||
// import textInput from '../../settings/textInput.vue'
|
||||
// import CropImage from '@/components/business/cropper/CropImage.vue'
|
||||
// import ContainerWrap from '../../settings/EffectSelect/ContainerWrap.vue'
|
||||
import ContainerWrap from '../../settings/EffectSelect/ContainerWrap.vue'
|
||||
// import uploader from '@/components/common/Uploader/index.vue'
|
||||
import { getImage } from '@/common/methods/getImgDetail'
|
||||
import api from '@/api'
|
||||
@ -282,17 +281,18 @@ function openCropper() {
|
||||
// }
|
||||
|
||||
|
||||
// async function changeContainer(setting) {
|
||||
// const index = this.dWidgets.findIndex((x) => x.uuid == this.innerElement.uuid)
|
||||
// const img = await getImage(setting.svgUrl)
|
||||
// setting.width = this.innerElement.width
|
||||
// setting.height = img.height * (this.innerElement.width / img.width)
|
||||
// setting.left = this.innerElement.left
|
||||
// setting.top = this.innerElement.top
|
||||
// setting.imgUrl = this.innerElement.imgUrl
|
||||
// this.dWidgets.splice(index, 1)
|
||||
// this.addWidget(setting)
|
||||
// }
|
||||
async function changeContainer(setting: any) {
|
||||
state.innerElement.mask = setting.svgUrl
|
||||
// const index = this.dWidgets.findIndex((x) => x.uuid == this.innerElement.uuid)
|
||||
// const img = await getImage(setting.svgUrl)
|
||||
// setting.width = this.innerElement.width
|
||||
// setting.height = img.height * (this.innerElement.width / img.width)
|
||||
// setting.left = this.innerElement.left
|
||||
// setting.top = this.innerElement.top
|
||||
// setting.imgUrl = this.innerElement.imgUrl
|
||||
// this.dWidgets.splice(index, 1)
|
||||
// this.addWidget(setting)
|
||||
}
|
||||
|
||||
// async function uploadImgDone(img) {
|
||||
// this.$store.commit('setShowMoveable', false)
|
||||
|
@ -77,8 +77,6 @@ function paste() {
|
||||
* 撤销
|
||||
*/
|
||||
function undo(shiftKey: any) {
|
||||
console.log(store.getters.dHistoryParams);
|
||||
|
||||
if (shiftKey) {
|
||||
if (!(store.getters.dHistoryParams.index === store.getters.dHistoryParams.length - 1)) {
|
||||
// this.handleHistory('redo')
|
||||
|
Loading…
x
Reference in New Issue
Block a user