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
|
top: number
|
||||||
left: number
|
left: number
|
||||||
data?: string
|
data?: string
|
||||||
|
listWidth?: number
|
||||||
|
gap?: number
|
||||||
|
thumb?: string
|
||||||
|
url: string
|
||||||
|
model?: string
|
||||||
|
color?: string
|
||||||
}
|
}
|
||||||
type IGetTempListResult = TPageRequestResult<IGetTempListData[]>
|
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')
|
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
|
* @LastEditTime: 2023-12-11 11:40:47
|
||||||
*/
|
*/
|
||||||
import fetch from '@/utils/axios'
|
import fetch from '@/utils/axios'
|
||||||
|
import { IGetTempListData } from './home'
|
||||||
|
|
||||||
// 获取素材分类:
|
// 获取素材分类:
|
||||||
export const getKinds = (params: Type.Object = {}) => fetch('design/cate', params)
|
export const getKinds = (params: Type.Object = {}) => fetch('design/cate', params)
|
||||||
@ -75,7 +76,7 @@ export type TGetImageListResult = {
|
|||||||
user_id: number
|
user_id: number
|
||||||
id: string
|
id: string
|
||||||
thumb: string
|
thumb: string
|
||||||
}
|
} & IGetTempListData
|
||||||
|
|
||||||
// 图库列表
|
// 图库列表
|
||||||
export const getImagesList = (params: TGetImageListParams) => fetch<TPageRequestResult<TGetImageListResult[]>>('design/imgs', params, 'get')
|
export const getImagesList = (params: TGetImageListParams) => fetch<TPageRequestResult<TGetImageListResult[]>>('design/imgs', params, 'get')
|
||||||
|
@ -9,6 +9,7 @@ import store from '@/store'
|
|||||||
import { getImage } from '../getImgDetail'
|
import { getImage } from '../getImgDetail'
|
||||||
|
|
||||||
export type TItem2DataParam = {
|
export type TItem2DataParam = {
|
||||||
|
id?: string | number
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
url: string
|
url: string
|
||||||
|
@ -26,7 +26,7 @@ type TModelData = {
|
|||||||
ratio?: string
|
ratio?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TUploadDoneData = {
|
export type TUploadDoneData = {
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
url: string
|
url: string
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<div v-show="activeTab === 0" class="style-wrap">
|
<div v-show="activeTab === 0" class="style-wrap">
|
||||||
<div v-show="showGroupCombined" style="padding: 2rem 0">
|
<div v-show="showGroupCombined" style="padding: 2rem 0">
|
||||||
<el-button plain type="primary" class="gounp__btn" @click="handleCombine">成组</el-button>
|
<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>
|
</div>
|
||||||
<component :is="dActiveElement.type + '-style'" v-show="!showGroupCombined" v-if="dActiveElement.type" />
|
<component :is="dActiveElement.type + '-style'" v-show="!showGroupCombined" v-if="dActiveElement.type" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,78 +22,74 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
const NAME = 'text-list-wrap'
|
// const NAME = 'text-list-wrap'
|
||||||
|
|
||||||
import wText from '../../widgets/wText/wText.vue'
|
import wText from '../../widgets/wText/wText.vue'
|
||||||
|
|
||||||
import { mapActions, useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { getCurrentInstance, ComponentInternalInstance } from 'vue'
|
|
||||||
|
|
||||||
export default {
|
type TBasicTextData = {
|
||||||
name: NAME,
|
text: string
|
||||||
setup() {
|
fontSize: number
|
||||||
const store: any = useStore()
|
fontWeight: string
|
||||||
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']),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -21,54 +21,55 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
// 图片列表
|
// 图片列表
|
||||||
const NAME = 'tool-list-wrap'
|
// const NAME = 'tool-list-wrap'
|
||||||
// import api from '@/api'
|
// 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 wQrcode from '../../widgets/wQrcode/wQrcode.vue'
|
||||||
import imageCutout from '@/components/business/image-cutout'
|
import imageCutout from '@/components/business/image-cutout'
|
||||||
|
import { useSetupMapGetters } from '@/common/hooks/mapGetters'
|
||||||
|
|
||||||
export default {
|
const store = useStore()
|
||||||
name: NAME,
|
const route = useRoute()
|
||||||
components: { imageCutout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loadDone: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['dPage']),
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
const loadDone = ref(false)
|
||||||
// this.getDataList()
|
const imageCutoutRef = ref<typeof imageCutout | null>(null)
|
||||||
setTimeout(() => {
|
const { dPage } = useSetupMapGetters(['dPage'])
|
||||||
const { koutu } = this.$route.query
|
|
||||||
koutu && this.openImageCutout()
|
onMounted(() => {
|
||||||
}, 300)
|
// this.getDataList()
|
||||||
},
|
setTimeout(() => {
|
||||||
methods: {
|
const { koutu } = route.query
|
||||||
...mapActions(['addWidget']),
|
koutu && openImageCutout()
|
||||||
async getDataList() {
|
}, 300)
|
||||||
if (this.loadDone || this.loading) {
|
})
|
||||||
return
|
|
||||||
}
|
// ...mapActions(['addWidget'])
|
||||||
this.loading = true
|
|
||||||
this.page += 1
|
// async function getDataList() {
|
||||||
},
|
// if (loadDone || loading) {
|
||||||
addQrcode() {
|
// return
|
||||||
this.$store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
// }
|
||||||
let setting = JSON.parse(JSON.stringify(wQrcode.setting))
|
// loading = true
|
||||||
const { width: pW, height: pH } = this.dPage
|
// page += 1
|
||||||
setting.left = pW / 2 - setting.width / 2
|
// }
|
||||||
setting.top = pH / 2 - setting.height / 2
|
|
||||||
this.addWidget(setting)
|
function addQrcode() {
|
||||||
},
|
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
||||||
openImageCutout() {
|
let setting = JSON.parse(JSON.stringify(wQrcode.setting))
|
||||||
this.$refs.imageCutout.open()
|
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>
|
</script>
|
||||||
|
|
||||||
|
@ -7,206 +7,250 @@
|
|||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="wrap">
|
<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="pics"> </el-tab-pane>
|
||||||
<el-tab-pane label="我的作品" name="design"> </el-tab-pane>
|
<el-tab-pane label="我的作品" name="design"> </el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div v-show="tabActiveName === 'pics'">
|
<div v-show="state.tabActiveName === 'pics'">
|
||||||
<uploader v-model="percent" class="upload" @done="uploadDone">
|
<uploader v-model="state.percent" class="upload" @done="uploadDone">
|
||||||
<el-button class="upload-btn" plain>上传图片 <i class="iconfont icon-upload" /></el-button>
|
<el-button class="upload-btn" plain>上传图片 <i class="iconfont icon-upload" /></el-button>
|
||||||
</uploader>
|
</uploader>
|
||||||
<el-button class="upload-btn upload-psd" plain type="primary" @click="openPSD">上传 PSD 模板</el-button>
|
<el-button class="upload-btn upload-psd" plain type="primary" @click="openPSD">上传 PSD 模板</el-button>
|
||||||
<div style="margin: 1rem; height: 100vh">
|
<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>
|
</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">
|
<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="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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, reactive, toRefs, watch, nextTick, ref, onMounted } from 'vue'
|
import { reactive, toRefs, watch, nextTick, ref, onMounted, defineProps, defineExpose } from 'vue'
|
||||||
import { ElTabPane, ElTabs } from 'element-plus'
|
import { ElTabPane, ElTabs, TabPaneName } from 'element-plus'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import uploader from '@/components/common/Uploader'
|
import uploader from '@/components/common/Uploader'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import wImage from '../../widgets/wImage/wImage.vue'
|
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 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({
|
type TProps = {
|
||||||
components: { uploader, ElTabPane, ElTabs },
|
active: number
|
||||||
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
|
|
||||||
|
|
||||||
const load = (init: boolean) => {
|
type TState = {
|
||||||
if (init) {
|
prePath: string,
|
||||||
state.imgList = []
|
percent: { num: number }, // 当前上传进度
|
||||||
page = 0
|
imgList: IGetTempListData[],
|
||||||
state.isDone = false
|
designList: IGetTempListData[],
|
||||||
}
|
isDone: boolean,
|
||||||
if (state.isDone || loading) {
|
editOptions: Record<string, any>,
|
||||||
return
|
tabActiveName: string,
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkHeight(el: any, loadFn: Function) {
|
const props = defineProps<TProps>()
|
||||||
// 检查高度是否占满,否则继续请求下一页
|
|
||||||
const isLess = el.offsetHeight > el.firstElementChild.offsetHeight
|
|
||||||
isLess && loadFn()
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
const router = useRouter()
|
||||||
load(true)
|
const store = useStore()
|
||||||
nextTick(() => {
|
const listRef = ref<HTMLElement | null>(null)
|
||||||
state.tabActiveName = 'pics'
|
const imgListRef = ref<typeof photoList | null>(null)
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const selectImg = async (index: number) => {
|
const state = reactive<TState>({
|
||||||
const item: any = state.imgList[index]
|
prePath: 'user',
|
||||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择
|
percent: { num: 0 }, // 当前上传进度
|
||||||
let setting = JSON.parse(JSON.stringify(wImage.setting))
|
imgList: [],
|
||||||
const img: any = await setImageData(item)
|
designList: [],
|
||||||
setting.width = img.width
|
isDone: false,
|
||||||
setting.height = img.height // parseInt(100 / item.value.ratio, 10)
|
editOptions: [],
|
||||||
setting.imgUrl = item.url
|
tabActiveName: '',
|
||||||
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 tabChange = (tabName: string) => {
|
let loading = false
|
||||||
if (tabName === 'design') {
|
let page = 0
|
||||||
loadDesign(true)
|
let listPage = 0
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectDesign = async (item: any) => {
|
const load = (init?: boolean) => {
|
||||||
// const { id }: any = state.designList[index]
|
if (init) {
|
||||||
const { id }: any = item
|
state.imgList = []
|
||||||
window.open(`${window.location.protocol + '//' + window.location.host}/home?id=${id}`)
|
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 = () => {
|
const loadDesign = (init: boolean = false) => {
|
||||||
window.open(router.resolve('/psd').href, '_blank')
|
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 {
|
function checkHeight(el: HTMLElement, loadFn: Function) {
|
||||||
...toRefs(state),
|
// 检查高度是否占满,否则继续请求下一页
|
||||||
selectDesign,
|
if (el.offsetHeight && el.firstElementChild) {
|
||||||
loadDesign,
|
const isLess = el.offsetHeight > (el.firstElementChild as HTMLElement).offsetHeight
|
||||||
load,
|
isLess && loadFn()
|
||||||
uploadDone,
|
}
|
||||||
selectImg,
|
}
|
||||||
deleteImg,
|
|
||||||
dragStart,
|
onMounted(() => {
|
||||||
tabChange,
|
load(true)
|
||||||
openPSD,
|
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>
|
</script>
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* @Date: 2024-03-06 21:16:00
|
* @Date: 2024-03-06 21:16:00
|
||||||
-->
|
-->
|
||||||
<template>
|
<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 class="list">
|
||||||
<div
|
<div
|
||||||
v-for="(item, i) in state.list" :key="i + 'i'"
|
v-for="(item, i) in state.list" :key="i + 'i'"
|
||||||
@ -18,7 +18,7 @@
|
|||||||
@click.stop="select(i)"
|
@click.stop="select(i)"
|
||||||
@dragstart="dragStart($event, 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>
|
<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" />
|
<el-image class="img transparent-bg" :src="item.thumb || item.url" :style="{ height: getInnerHeight(item) + 'px' }" lazy loading="lazy" />
|
||||||
</edit-model>
|
</edit-model>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
<div v-else class="loading">全部加载完毕</div>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
@ -42,11 +42,12 @@
|
|||||||
import { reactive, watch, nextTick, defineProps, defineExpose, defineEmits, ref } from 'vue'
|
import { reactive, watch, nextTick, defineProps, defineExpose, defineEmits, ref } from 'vue'
|
||||||
import DragHelper from '@/common/hooks/dragHelper'
|
import DragHelper from '@/common/hooks/dragHelper'
|
||||||
import setImageData, { TItem2DataParam } from '@/common/methods/DesignFeatures/setImage'
|
import setImageData, { TItem2DataParam } from '@/common/methods/DesignFeatures/setImage'
|
||||||
|
import { IGetTempListData } from '@/api/home';
|
||||||
|
|
||||||
type TProps = {
|
type TProps = {
|
||||||
listData: TCommonPhotoListData[]
|
listData: IGetTempListData[]
|
||||||
edit: Record<string, any>
|
edit: Record<string, any>
|
||||||
isDone: Record<string, any>
|
isDone: boolean
|
||||||
isShort: boolean
|
isShort: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,10 +60,10 @@ type TEmits = {
|
|||||||
|
|
||||||
type TState = {
|
type TState = {
|
||||||
loading: boolean
|
loading: boolean
|
||||||
list: TCommonPhotoListData[]
|
list: IGetTempListData[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const { listData, edit, isDone, isShort } = withDefaults(defineProps<TProps>(), {
|
const props = withDefaults(defineProps<TProps>(), {
|
||||||
isShort: false
|
isShort: false
|
||||||
})
|
})
|
||||||
const emit = defineEmits<TEmits>()
|
const emit = defineEmits<TEmits>()
|
||||||
@ -92,21 +93,21 @@ const mousemove = (e: MouseEvent) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => listData,
|
() => props.listData,
|
||||||
async (newList: TCommonPhotoListData[], oldList: TCommonPhotoListData[]) => {
|
async (newList: IGetTempListData[], oldList: IGetTempListData[]) => {
|
||||||
!oldList && (oldList = [])
|
!oldList && (oldList = [])
|
||||||
if (newList.length <= 0) {
|
if (newList.length <= 0) {
|
||||||
state.list.length = 0
|
state.list.length = 0
|
||||||
return
|
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))
|
list = JSON.parse(JSON.stringify(list))
|
||||||
const marginRight = 6 // 间距
|
const marginRight = 6 // 间距
|
||||||
const limitWidth = (await getFatherWidth()) - marginRight
|
const limitWidth = (await getFatherWidth()) - marginRight
|
||||||
const standardHeight = 280 // 高度阈值
|
const standardHeight = 280 // 高度阈值
|
||||||
const neatArr: TCommonPhotoListData[][] = [] // 整理后的数组
|
const neatArr: IGetTempListData[][] = [] // 整理后的数组
|
||||||
function factory(cutArr: TCommonPhotoListData[]) {
|
function factory(cutArr: IGetTempListData[]) {
|
||||||
return new Promise<{ height: number, list: TCommonPhotoListData[] }>((resolve) => {
|
return new Promise<{ height: number, list: IGetTempListData[] }>((resolve) => {
|
||||||
const lineup = list.shift()
|
const lineup = list.shift()
|
||||||
if (!lineup) {
|
if (!lineup) {
|
||||||
resolve({ height: calculate(cutArr), list: cutArr })
|
resolve({ height: calculate(cutArr), list: cutArr })
|
||||||
@ -121,7 +122,7 @@ watch(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function calculate(cutArr: TCommonPhotoListData[]) {
|
function calculate(cutArr: IGetTempListData[]) {
|
||||||
let cumulate = 0
|
let cumulate = 0
|
||||||
for (const iterator of cutArr) {
|
for (const iterator of cutArr) {
|
||||||
const { width, height } = iterator
|
const { width, height } = iterator
|
||||||
@ -133,9 +134,9 @@ watch(
|
|||||||
if (list.length <= 0) {
|
if (list.length <= 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { list: newList, height } = await factory([(list.shift() as TCommonPhotoListData)])
|
const { list: newList, height } = await factory([(list.shift() as IGetTempListData)])
|
||||||
neatArr.push(
|
neatArr.push(
|
||||||
newList.map((x: TCommonPhotoListData, index: number) => {
|
newList.map((x: IGetTempListData, index: number) => {
|
||||||
x.listWidth = (x.width / x.height) * height
|
x.listWidth = (x.width / x.height) * height
|
||||||
x.gap = index !== newList.length - 1 ? marginRight : 0
|
x.gap = index !== newList.length - 1 ? marginRight : 0
|
||||||
return x
|
return x
|
||||||
@ -154,7 +155,7 @@ watch(
|
|||||||
async function getFatherWidth() {
|
async function getFatherWidth() {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
if (!listRef.value) return 0
|
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
|
if (!father) return 0
|
||||||
return (father as HTMLElement).offsetWidth
|
return (father as HTMLElement).offsetWidth
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ import { useRoute } from 'vue-router'
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
type TProps = {
|
type TProps = {
|
||||||
type: string
|
type?: string
|
||||||
modelValue: string
|
modelValue: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user