mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
Merge pull request #71 from JeremyYu-cn/feat-upgrade-vue3
Fix: convert userWrap to composition API and fix panel component problems
This commit is contained in:
commit
c5b35f4e7d
@ -29,6 +29,12 @@ export type IGetTempListData = {
|
||||
top: number
|
||||
left: number
|
||||
data?: string
|
||||
listWidth?: number
|
||||
gap?: number
|
||||
thumb?: string
|
||||
url: string
|
||||
model?: string
|
||||
color?: string
|
||||
}
|
||||
type IGetTempListResult = TPageRequestResult<IGetTempListData[]>
|
||||
|
||||
@ -73,5 +79,12 @@ export const saveMyTemp = (params: Type.Object = {}) => fetch('design/user/temp'
|
||||
// 获取作品
|
||||
export const getWorks = (params: Type.Object = {}) => fetch('design/poster', params, 'get')
|
||||
|
||||
type TGetMyDesignParams = {
|
||||
page: number
|
||||
pageSize: number
|
||||
}
|
||||
|
||||
type TGetMyDesignResult = TPageRequestResult<IGetTempListData[]>
|
||||
|
||||
// 作品列表
|
||||
export const getMyDesign = (params: Type.Object = {}) => fetch('design/my', params, 'get')
|
||||
export const getMyDesign = (params: TGetMyDesignParams) => fetch<TGetMyDesignResult>('design/my', params, 'get')
|
||||
|
@ -6,6 +6,7 @@
|
||||
* @LastEditTime: 2023-12-11 11:40:47
|
||||
*/
|
||||
import fetch from '@/utils/axios'
|
||||
import { IGetTempListData } from './home'
|
||||
|
||||
// 获取素材分类:
|
||||
export const getKinds = (params: Type.Object = {}) => fetch('design/cate', params)
|
||||
@ -75,7 +76,7 @@ export type TGetImageListResult = {
|
||||
user_id: number
|
||||
id: string
|
||||
thumb: string
|
||||
}
|
||||
} & IGetTempListData
|
||||
|
||||
// 图库列表
|
||||
export const getImagesList = (params: TGetImageListParams) => fetch<TPageRequestResult<TGetImageListResult[]>>('design/imgs', params, 'get')
|
||||
|
@ -9,6 +9,7 @@ import store from '@/store'
|
||||
import { getImage } from '../getImgDetail'
|
||||
|
||||
export type TItem2DataParam = {
|
||||
id?: string | number
|
||||
width: number
|
||||
height: number
|
||||
url: string
|
||||
|
@ -26,7 +26,7 @@ type TModelData = {
|
||||
ratio?: string
|
||||
}
|
||||
|
||||
type TUploadDoneData = {
|
||||
export type TUploadDoneData = {
|
||||
width: number
|
||||
height: number
|
||||
url: string
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div v-show="activeTab === 0" class="style-wrap">
|
||||
<div v-show="showGroupCombined" style="padding: 2rem 0">
|
||||
<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="iconList" @finish="alignAction" />
|
||||
</div>
|
||||
<component :is="dActiveElement.type + '-style'" v-show="!showGroupCombined" v-if="dActiveElement.type" />
|
||||
</div>
|
||||
|
@ -22,78 +22,74 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
const NAME = 'text-list-wrap'
|
||||
<script lang="ts" setup>
|
||||
// const NAME = 'text-list-wrap'
|
||||
|
||||
import wText from '../../widgets/wText/wText.vue'
|
||||
|
||||
import { mapActions, useStore } from 'vuex'
|
||||
import { getCurrentInstance, ComponentInternalInstance } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
setup() {
|
||||
const store: any = useStore()
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance
|
||||
|
||||
const selectBasicText = (item: any) => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wText.setting))
|
||||
setting.text = '双击编辑文字' // item.text
|
||||
setting.width = item.fontSize * setting.text.length
|
||||
setting.fontSize = item.fontSize
|
||||
setting.fontWeight = item.fontWeight
|
||||
const { width: pW, height: pH } = store.getters.dPage
|
||||
setting.left = pW / 2 - item.fontSize * 3
|
||||
setting.top = pH / 2 - item.fontSize / 2
|
||||
;(proxy as any).addWidget(setting)
|
||||
}
|
||||
|
||||
const dragStart = (e: Element, item: any) => {
|
||||
store.commit('setDraging', true)
|
||||
store.commit('selectItem', { data: { value: item }, type: 'text' })
|
||||
}
|
||||
|
||||
return {
|
||||
selectBasicText,
|
||||
dragStart,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
basicTextList: [
|
||||
// {
|
||||
// text: '大标题',
|
||||
// fontSize: 96,
|
||||
// fontWeight: 'bold',
|
||||
// },
|
||||
{
|
||||
text: '+ 添加文字',
|
||||
fontSize: 60,
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
// {
|
||||
// text: '+ 添加文字',
|
||||
// fontSize: 40,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
// {
|
||||
// text: '小标题',
|
||||
// fontSize: 36,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
// {
|
||||
// text: '正文内容',
|
||||
// fontSize: 28,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['addWidget']),
|
||||
},
|
||||
type TBasicTextData = {
|
||||
text: string
|
||||
fontSize: number
|
||||
fontWeight: string
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
|
||||
|
||||
const selectBasicText = (item: TBasicTextData) => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wText.setting))
|
||||
setting.text = '双击编辑文字' // item.text
|
||||
setting.width = item.fontSize * setting.text.length
|
||||
setting.fontSize = item.fontSize
|
||||
setting.fontWeight = item.fontWeight
|
||||
const { width: pW, height: pH } = store.getters.dPage
|
||||
setting.left = pW / 2 - item.fontSize * 3
|
||||
setting.top = pH / 2 - item.fontSize / 2
|
||||
store.dispatch('addWidget', setting)
|
||||
// addWidget(setting)
|
||||
}
|
||||
|
||||
const dragStart = (_: MouseEvent, item: any) => {
|
||||
store.commit('setDraging', true)
|
||||
store.commit('selectItem', { data: { value: item }, type: 'text' })
|
||||
}
|
||||
|
||||
const basicTextList: TBasicTextData[] = [
|
||||
// {
|
||||
// text: '大标题',
|
||||
// fontSize: 96,
|
||||
// fontWeight: 'bold',
|
||||
// },
|
||||
{
|
||||
text: '+ 添加文字',
|
||||
fontSize: 60,
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
// {
|
||||
// text: '+ 添加文字',
|
||||
// fontSize: 40,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
// {
|
||||
// text: '小标题',
|
||||
// fontSize: 36,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
// {
|
||||
// text: '正文内容',
|
||||
// fontSize: 28,
|
||||
// fontWeight: 'normal',
|
||||
// },
|
||||
]
|
||||
defineExpose({
|
||||
selectBasicText,
|
||||
dragStart,
|
||||
})
|
||||
|
||||
// ...mapActions(['addWidget'])
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@ -21,54 +21,55 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
// 图片列表
|
||||
const NAME = 'tool-list-wrap'
|
||||
// const NAME = 'tool-list-wrap'
|
||||
// import api from '@/api'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute } from 'vue-router'
|
||||
import wQrcode from '../../widgets/wQrcode/wQrcode.vue'
|
||||
import imageCutout from '@/components/business/image-cutout'
|
||||
import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
components: { imageCutout },
|
||||
data() {
|
||||
return {
|
||||
loadDone: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['dPage']),
|
||||
},
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
|
||||
mounted() {
|
||||
// this.getDataList()
|
||||
setTimeout(() => {
|
||||
const { koutu } = this.$route.query
|
||||
koutu && this.openImageCutout()
|
||||
}, 300)
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['addWidget']),
|
||||
async getDataList() {
|
||||
if (this.loadDone || this.loading) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.page += 1
|
||||
},
|
||||
addQrcode() {
|
||||
this.$store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wQrcode.setting))
|
||||
const { width: pW, height: pH } = this.dPage
|
||||
setting.left = pW / 2 - setting.width / 2
|
||||
setting.top = pH / 2 - setting.height / 2
|
||||
this.addWidget(setting)
|
||||
},
|
||||
openImageCutout() {
|
||||
this.$refs.imageCutout.open()
|
||||
},
|
||||
},
|
||||
const loadDone = ref(false)
|
||||
const imageCutoutRef = ref<typeof imageCutout | null>(null)
|
||||
const { dPage } = useSetupMapGetters(['dPage'])
|
||||
|
||||
onMounted(() => {
|
||||
// this.getDataList()
|
||||
setTimeout(() => {
|
||||
const { koutu } = route.query
|
||||
koutu && openImageCutout()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
// ...mapActions(['addWidget'])
|
||||
|
||||
// async function getDataList() {
|
||||
// if (loadDone || loading) {
|
||||
// return
|
||||
// }
|
||||
// loading = true
|
||||
// page += 1
|
||||
// }
|
||||
|
||||
function addQrcode() {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wQrcode.setting))
|
||||
const { width: pW, height: pH } = dPage.value
|
||||
setting.left = pW / 2 - setting.width / 2
|
||||
setting.top = pH / 2 - setting.height / 2
|
||||
store.dispatch('addWidget', setting)
|
||||
// addWidget(setting)
|
||||
}
|
||||
|
||||
function openImageCutout() {
|
||||
if (!imageCutoutRef.value) return
|
||||
imageCutoutRef.value.open()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -7,206 +7,250 @@
|
||||
-->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<el-tabs v-model="tabActiveName" :stretch="true" class="tabs" @tab-change="tabChange">
|
||||
<el-tabs v-model="state.tabActiveName" :stretch="true" class="tabs" @tab-change="tabChange">
|
||||
<el-tab-pane label="资源管理" name="pics"> </el-tab-pane>
|
||||
<el-tab-pane label="我的作品" name="design"> </el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-show="tabActiveName === 'pics'">
|
||||
<uploader v-model="percent" class="upload" @done="uploadDone">
|
||||
<div v-show="state.tabActiveName === 'pics'">
|
||||
<uploader v-model="state.percent" class="upload" @done="uploadDone">
|
||||
<el-button class="upload-btn" plain>上传图片 <i class="iconfont icon-upload" /></el-button>
|
||||
</uploader>
|
||||
<el-button class="upload-btn upload-psd" plain type="primary" @click="openPSD">上传 PSD 模板</el-button>
|
||||
<div style="margin: 1rem; height: 100vh">
|
||||
<photo-list ref="imgListRef" :edit="editOptions.photo" :isDone="isDone" :listData="imgList" @load="load" @drag="dragStart" @select="selectImg" />
|
||||
<photo-list
|
||||
ref="imgListRef"
|
||||
:edit="state.editOptions.photo" :isDone="state.isDone"
|
||||
:listData="state.imgList"
|
||||
@load="load" @drag="dragStart" @select="selectImg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="tabActiveName === 'design'" class="wrap">
|
||||
<div v-show="state.tabActiveName === 'design'" class="wrap">
|
||||
<ul ref="listRef" v-infinite-scroll="loadDesign" class="infinite-list" :infinite-scroll-distance="150" style="overflow: auto">
|
||||
<img-water-fall :edit="editOptions.works" :listData="designList" @select="selectDesign" />
|
||||
<img-water-fall :edit="state.editOptions.works" :listData="state.designList" @select="selectDesign" />
|
||||
<!-- <div v-show="loading" class="loading"><i class="el-icon-loading"></i>拼命加载中..</div> -->
|
||||
<div v-show="isDone" class="loading">全部加载完毕</div>
|
||||
<div v-show="state.isDone" class="loading">全部加载完毕</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs, watch, nextTick, ref, onMounted } from 'vue'
|
||||
import { ElTabPane, ElTabs } from 'element-plus'
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, watch, nextTick, ref, onMounted, defineProps, defineExpose } from 'vue'
|
||||
import { ElTabPane, ElTabs, TabPaneName } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import uploader from '@/components/common/Uploader'
|
||||
import api from '@/api'
|
||||
import wImage from '../../widgets/wImage/wImage.vue'
|
||||
import setImageData from '@/common/methods/DesignFeatures/setImage'
|
||||
import setImageData, { TItem2DataParam } from '@/common/methods/DesignFeatures/setImage'
|
||||
import useConfirm from '@/common/methods/confirm'
|
||||
import { TGetImageListResult } from '@/api/material'
|
||||
import photoList from './components/photoList.vue'
|
||||
import imgWaterFall from './components/imgWaterFall.vue'
|
||||
import { TUploadDoneData } from '@/components/common/Uploader/index.vue'
|
||||
import { IGetTempListData } from '@/api/home'
|
||||
|
||||
export default defineComponent({
|
||||
components: { uploader, ElTabPane, ElTabs },
|
||||
props: ['active'],
|
||||
setup(props) {
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const state: any = reactive({
|
||||
prePath: 'user',
|
||||
percent: { num: 0 }, // 当前上传进度
|
||||
imgList: [],
|
||||
designList: [],
|
||||
isDone: false,
|
||||
editOptions: [],
|
||||
listRef: null,
|
||||
imgListRef: null,
|
||||
tabActiveName: '',
|
||||
})
|
||||
let loading = false
|
||||
let page = 0
|
||||
let listPage = 0
|
||||
type TProps = {
|
||||
active: number
|
||||
}
|
||||
|
||||
const load = (init: boolean) => {
|
||||
if (init) {
|
||||
state.imgList = []
|
||||
page = 0
|
||||
state.isDone = false
|
||||
}
|
||||
if (state.isDone || loading) {
|
||||
return
|
||||
}
|
||||
loading = true
|
||||
page += 1
|
||||
api.material.getMyPhoto({ page }).then(({ list }: any) => {
|
||||
list.length <= 0 ? (state.isDone = true) : (state.imgList = state.imgList.concat(list))
|
||||
setTimeout(() => {
|
||||
loading = false
|
||||
checkHeight(state.imgListRef.getRef(), load)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
const loadDesign = (init: boolean = false) => {
|
||||
if (init) {
|
||||
state.designList = []
|
||||
listPage = 0
|
||||
state.isDone = false
|
||||
}
|
||||
if (state.isDone || loading) {
|
||||
return
|
||||
}
|
||||
loading = true
|
||||
listPage += 1
|
||||
api.home.getMyDesign({ page: listPage, pageSize: 10 }).then(({ list }: any) => {
|
||||
list.length <= 0
|
||||
? (state.isDone = true)
|
||||
: (state.designList = state.designList.concat(
|
||||
list.map((x: any) => {
|
||||
x.cover = x.cover + '?r=' + Math.random()
|
||||
return x
|
||||
}),
|
||||
))
|
||||
setTimeout(() => {
|
||||
loading = false
|
||||
checkHeight(state.listRef, loadDesign)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
type TState = {
|
||||
prePath: string,
|
||||
percent: { num: number }, // 当前上传进度
|
||||
imgList: IGetTempListData[],
|
||||
designList: IGetTempListData[],
|
||||
isDone: boolean,
|
||||
editOptions: Record<string, any>,
|
||||
tabActiveName: string,
|
||||
}
|
||||
|
||||
function checkHeight(el: any, loadFn: Function) {
|
||||
// 检查高度是否占满,否则继续请求下一页
|
||||
const isLess = el.offsetHeight > el.firstElementChild.offsetHeight
|
||||
isLess && loadFn()
|
||||
}
|
||||
const props = defineProps<TProps>()
|
||||
|
||||
onMounted(() => {
|
||||
load(true)
|
||||
nextTick(() => {
|
||||
state.tabActiveName = 'pics'
|
||||
})
|
||||
})
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const listRef = ref<HTMLElement | null>(null)
|
||||
const imgListRef = ref<typeof photoList | null>(null)
|
||||
|
||||
const selectImg = async (index: number) => {
|
||||
const item: any = state.imgList[index]
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wImage.setting))
|
||||
const img: any = await setImageData(item)
|
||||
setting.width = img.width
|
||||
setting.height = img.height // parseInt(100 / item.value.ratio, 10)
|
||||
setting.imgUrl = item.url
|
||||
const { width: pW, height: pH } = store.getters.dPage
|
||||
setting.left = pW / 2 - img.width / 2
|
||||
setting.top = pH / 2 - img.height / 2
|
||||
store.dispatch('addWidget', setting)
|
||||
}
|
||||
const deleteImg = async ({ i, item }: any) => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择框
|
||||
const isPass = await useConfirm('警告', '删除后不可找回,已引用资源将会失效,请谨慎操作', 'warning')
|
||||
if (!isPass) {
|
||||
return false
|
||||
}
|
||||
const arr = item.url.split('/')
|
||||
let key = arr.splice(3, arr.length - 1).join('/')
|
||||
api.material.deleteMyPhoto({ id: item.id, key })
|
||||
state.imgListRef.delItem(i) // 通知标记
|
||||
}
|
||||
const deleteWorks = async ({ i, item }: any) => {
|
||||
const isPass = await useConfirm('警告', '删除后不可找回,请确认操作', 'warning')
|
||||
if (isPass) {
|
||||
await api.material.deleteMyWorks({ id: item.id })
|
||||
setTimeout(() => {
|
||||
router.push({ path: '/home', query: { }, replace: true })
|
||||
loadDesign(true)
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
state.editOptions = {
|
||||
photo: [
|
||||
{
|
||||
name: '删除',
|
||||
fn: deleteImg,
|
||||
},
|
||||
],works: [
|
||||
{
|
||||
name: '删除',
|
||||
fn: deleteWorks,
|
||||
},
|
||||
]
|
||||
}
|
||||
const dragStart = (index: number) => {
|
||||
const item = state.imgList[index]
|
||||
store.commit('selectItem', { data: { value: item }, type: 'image' })
|
||||
}
|
||||
const uploadDone = async (res: any) => {
|
||||
await api.material.addMyPhoto(res)
|
||||
state.imgList = []
|
||||
load(true)
|
||||
}
|
||||
const state = reactive<TState>({
|
||||
prePath: 'user',
|
||||
percent: { num: 0 }, // 当前上传进度
|
||||
imgList: [],
|
||||
designList: [],
|
||||
isDone: false,
|
||||
editOptions: [],
|
||||
tabActiveName: '',
|
||||
})
|
||||
|
||||
const tabChange = (tabName: string) => {
|
||||
if (tabName === 'design') {
|
||||
loadDesign(true)
|
||||
}
|
||||
}
|
||||
let loading = false
|
||||
let page = 0
|
||||
let listPage = 0
|
||||
|
||||
const selectDesign = async (item: any) => {
|
||||
// const { id }: any = state.designList[index]
|
||||
const { id }: any = item
|
||||
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${id}`)
|
||||
const load = (init?: boolean) => {
|
||||
if (init) {
|
||||
state.imgList = []
|
||||
page = 0
|
||||
state.isDone = false
|
||||
}
|
||||
if (state.isDone || loading) {
|
||||
return
|
||||
}
|
||||
loading = true
|
||||
page += 1
|
||||
api.material.getMyPhoto({ page }).then(({ list }) => {
|
||||
|
||||
if (list.length <= 0) {
|
||||
state.isDone = true
|
||||
} else {
|
||||
state.imgList = state.imgList.concat(list)
|
||||
}
|
||||
console.log('state.imgList', state.imgList)
|
||||
setTimeout(() => {
|
||||
loading = false
|
||||
if (!imgListRef.value) return
|
||||
checkHeight(imgListRef.value.getRef(), load)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
const openPSD = () => {
|
||||
window.open(router.resolve('/psd').href, '_blank')
|
||||
}
|
||||
const loadDesign = (init: boolean = false) => {
|
||||
if (init) {
|
||||
state.designList = []
|
||||
listPage = 0
|
||||
state.isDone = false
|
||||
}
|
||||
if (state.isDone || loading) {
|
||||
return
|
||||
}
|
||||
loading = true
|
||||
listPage += 1
|
||||
api.home.getMyDesign({ page: listPage, pageSize: 10 }).then(({ list }) => {
|
||||
list.length <= 0
|
||||
? (state.isDone = true)
|
||||
: (state.designList = state.designList.concat(
|
||||
list.map((x) => {
|
||||
x.cover = x.cover + '?r=' + Math.random()
|
||||
return x
|
||||
}),
|
||||
))
|
||||
console.log('state.designList', state.designList)
|
||||
setTimeout(() => {
|
||||
loading = false
|
||||
if (!listRef.value) return
|
||||
console.log('listRef.value', listRef.value)
|
||||
checkHeight(listRef.value, loadDesign)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
selectDesign,
|
||||
loadDesign,
|
||||
load,
|
||||
uploadDone,
|
||||
selectImg,
|
||||
deleteImg,
|
||||
dragStart,
|
||||
tabChange,
|
||||
openPSD,
|
||||
}
|
||||
},
|
||||
function checkHeight(el: HTMLElement, loadFn: Function) {
|
||||
// 检查高度是否占满,否则继续请求下一页
|
||||
if (el.offsetHeight && el.firstElementChild) {
|
||||
const isLess = el.offsetHeight > (el.firstElementChild as HTMLElement).offsetHeight
|
||||
isLess && loadFn()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load(true)
|
||||
nextTick(() => {
|
||||
state.tabActiveName = 'pics'
|
||||
})
|
||||
})
|
||||
|
||||
const selectImg = async (index: number) => {
|
||||
const item = state.imgList[index]
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||
let setting = JSON.parse(JSON.stringify(wImage.setting))
|
||||
const img = await setImageData(item)
|
||||
setting.width = img.width
|
||||
setting.height = img.height // parseInt(100 / item.value.ratio, 10)
|
||||
setting.imgUrl = item.url
|
||||
const { width: pW, height: pH } = store.getters.dPage
|
||||
setting.left = pW / 2 - img.width / 2
|
||||
setting.top = pH / 2 - img.height / 2
|
||||
store.dispatch('addWidget', setting)
|
||||
}
|
||||
|
||||
type controlImgParam = {
|
||||
i: number
|
||||
item: Required<TItem2DataParam>
|
||||
}
|
||||
|
||||
const deleteImg = async ({ i, item }: controlImgParam) => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择框
|
||||
const isPass = await useConfirm('警告', '删除后不可找回,已引用资源将会失效,请谨慎操作', 'warning')
|
||||
if (!isPass) {
|
||||
return false
|
||||
}
|
||||
const arr = item.url.split('/')
|
||||
let key = arr.splice(3, arr.length - 1).join('/')
|
||||
api.material.deleteMyPhoto({ id: item.id, key })
|
||||
if (!imgListRef.value) return
|
||||
imgListRef.value.delItem(i) // 通知标记
|
||||
}
|
||||
const deleteWorks = async ({ i, item }: controlImgParam) => {
|
||||
const isPass = await useConfirm('警告', '删除后不可找回,请确认操作', 'warning')
|
||||
if (isPass) {
|
||||
await api.material.deleteMyWorks({ id: item.id })
|
||||
setTimeout(() => {
|
||||
router.push({ path: '/home', query: { }, replace: true })
|
||||
loadDesign(true)
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
state.editOptions = {
|
||||
photo: [
|
||||
{
|
||||
name: '删除',
|
||||
fn: deleteImg,
|
||||
},
|
||||
],
|
||||
works: [
|
||||
{
|
||||
name: '删除',
|
||||
fn: deleteWorks,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const dragStart = (index: number) => {
|
||||
const item = state.imgList[index]
|
||||
store.commit('selectItem', { data: { value: item }, type: 'image' })
|
||||
}
|
||||
const uploadDone = async (res: TUploadDoneData) => {
|
||||
await api.material.addMyPhoto(res)
|
||||
state.imgList = []
|
||||
load(true)
|
||||
}
|
||||
|
||||
const tabChange = (tabName: TabPaneName) => {
|
||||
if (tabName === 'design') {
|
||||
loadDesign(true)
|
||||
}
|
||||
}
|
||||
|
||||
const selectDesign = async (item: IGetTempListData) => {
|
||||
// const { id }: any = state.designList[index]
|
||||
const { id } = item
|
||||
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${id}`)
|
||||
}
|
||||
|
||||
const openPSD = () => {
|
||||
window.open(router.resolve('/psd').href, '_blank')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
selectDesign,
|
||||
loadDesign,
|
||||
load,
|
||||
uploadDone,
|
||||
selectImg,
|
||||
deleteImg,
|
||||
dragStart,
|
||||
tabChange,
|
||||
openPSD,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* @Date: 2024-03-06 21:16:00
|
||||
-->
|
||||
<template>
|
||||
<ul ref="listRef" class="img-list-wrap" :style="{ paddingBottom: isShort ? '15px' : '200px' }" @scroll="scrollEvent($event)">
|
||||
<ul ref="listRef" class="img-list-wrap" :style="{ paddingBottom: props.isShort ? '15px' : '200px' }" @scroll="scrollEvent($event)">
|
||||
<div class="list">
|
||||
<div
|
||||
v-for="(item, i) in state.list" :key="i + 'i'"
|
||||
@ -18,7 +18,7 @@
|
||||
@click.stop="select(i)"
|
||||
@dragstart="dragStart($event, i)"
|
||||
>
|
||||
<edit-model v-if="edit" :options="edit" :data="{ item, i }">
|
||||
<edit-model v-if="props.edit" :options="props.edit" :data="{ item, i }">
|
||||
<div v-if="item.isDelect" class="list__mask">已删除</div>
|
||||
<el-image class="img transparent-bg" :src="item.thumb || item.url" :style="{ height: getInnerHeight(item) + 'px' }" lazy loading="lazy" />
|
||||
</edit-model>
|
||||
@ -33,7 +33,7 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isDone" v-show="state.loading" class="loading"><i class="el-icon-loading" /> 拼命加载中</div>
|
||||
<div v-if="!props.isDone" v-show="state.loading" class="loading"><i class="el-icon-loading" /> 拼命加载中</div>
|
||||
<div v-else class="loading">全部加载完毕</div>
|
||||
</ul>
|
||||
</template>
|
||||
@ -42,11 +42,12 @@
|
||||
import { reactive, watch, nextTick, defineProps, defineExpose, defineEmits, ref } from 'vue'
|
||||
import DragHelper from '@/common/hooks/dragHelper'
|
||||
import setImageData, { TItem2DataParam } from '@/common/methods/DesignFeatures/setImage'
|
||||
import { IGetTempListData } from '@/api/home';
|
||||
|
||||
type TProps = {
|
||||
listData: TCommonPhotoListData[]
|
||||
listData: IGetTempListData[]
|
||||
edit: Record<string, any>
|
||||
isDone: Record<string, any>
|
||||
isDone: boolean
|
||||
isShort: boolean
|
||||
}
|
||||
|
||||
@ -59,10 +60,10 @@ type TEmits = {
|
||||
|
||||
type TState = {
|
||||
loading: boolean
|
||||
list: TCommonPhotoListData[]
|
||||
list: IGetTempListData[]
|
||||
}
|
||||
|
||||
const { listData, edit, isDone, isShort } = withDefaults(defineProps<TProps>(), {
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
isShort: false
|
||||
})
|
||||
const emit = defineEmits<TEmits>()
|
||||
@ -92,21 +93,21 @@ const mousemove = (e: MouseEvent) => {
|
||||
}
|
||||
|
||||
watch(
|
||||
() => listData,
|
||||
async (newList: TCommonPhotoListData[], oldList: TCommonPhotoListData[]) => {
|
||||
() => props.listData,
|
||||
async (newList: IGetTempListData[], oldList: IGetTempListData[]) => {
|
||||
!oldList && (oldList = [])
|
||||
if (newList.length <= 0) {
|
||||
state.list.length = 0
|
||||
return
|
||||
}
|
||||
let list = newList.filter((v: TCommonPhotoListData) => !newList.includes(v) || !oldList.includes(v)) // difference
|
||||
let list = newList.filter((v: IGetTempListData) => !newList.includes(v) || !oldList.includes(v)) // difference
|
||||
list = JSON.parse(JSON.stringify(list))
|
||||
const marginRight = 6 // 间距
|
||||
const limitWidth = (await getFatherWidth()) - marginRight
|
||||
const standardHeight = 280 // 高度阈值
|
||||
const neatArr: TCommonPhotoListData[][] = [] // 整理后的数组
|
||||
function factory(cutArr: TCommonPhotoListData[]) {
|
||||
return new Promise<{ height: number, list: TCommonPhotoListData[] }>((resolve) => {
|
||||
const neatArr: IGetTempListData[][] = [] // 整理后的数组
|
||||
function factory(cutArr: IGetTempListData[]) {
|
||||
return new Promise<{ height: number, list: IGetTempListData[] }>((resolve) => {
|
||||
const lineup = list.shift()
|
||||
if (!lineup) {
|
||||
resolve({ height: calculate(cutArr), list: cutArr })
|
||||
@ -121,7 +122,7 @@ watch(
|
||||
}
|
||||
})
|
||||
}
|
||||
function calculate(cutArr: TCommonPhotoListData[]) {
|
||||
function calculate(cutArr: IGetTempListData[]) {
|
||||
let cumulate = 0
|
||||
for (const iterator of cutArr) {
|
||||
const { width, height } = iterator
|
||||
@ -133,9 +134,9 @@ watch(
|
||||
if (list.length <= 0) {
|
||||
return
|
||||
}
|
||||
const { list: newList, height } = await factory([(list.shift() as TCommonPhotoListData)])
|
||||
const { list: newList, height } = await factory([(list.shift() as IGetTempListData)])
|
||||
neatArr.push(
|
||||
newList.map((x: TCommonPhotoListData, index: number) => {
|
||||
newList.map((x: IGetTempListData, index: number) => {
|
||||
x.listWidth = (x.width / x.height) * height
|
||||
x.gap = index !== newList.length - 1 ? marginRight : 0
|
||||
return x
|
||||
@ -154,7 +155,7 @@ watch(
|
||||
async function getFatherWidth() {
|
||||
await nextTick()
|
||||
if (!listRef.value) return 0
|
||||
const father = listRef.value.parentElement || listRef.value.parentNode
|
||||
const father = listRef.value.parentElement ?? listRef.value.parentNode
|
||||
if (!father) return 0
|
||||
return (father as HTMLElement).offsetWidth
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import { useRoute } from 'vue-router'
|
||||
import api from '@/api'
|
||||
|
||||
type TProps = {
|
||||
type: string
|
||||
type?: string
|
||||
modelValue: string
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user