363 lines
8.7 KiB
Vue
363 lines
8.7 KiB
Vue
<template>
|
|
<div id="display" class="content-area">
|
|
<RefreshOverlay :visible="refreshing" />
|
|
<Canvas v-model:visible="canvasVisible" :image="canvasImage" :reference-images="canvasReferenceImages" :source="canvasSource" :type="props.type" @send="handleCanvasSend" />
|
|
|
|
<div class="back" @click="handleExit">
|
|
<img src="@/assets/display/back.svg" alt="">
|
|
<span class="title-text">退出</span>
|
|
</div>
|
|
|
|
<div v-if="props.if" class="btn-container">
|
|
<div class="btn">
|
|
<img src="@/assets/display/search.svg" alt="">
|
|
</div>
|
|
<span class="line"></span>
|
|
<div class="btn">
|
|
<Select v-model="selectedTime" :options="timeOptions" width="auto">
|
|
<template #prefix>
|
|
<i-ep-Calendar />
|
|
</template>
|
|
|
|
<template #header>
|
|
<div class="header">
|
|
<el-date-picker
|
|
v-model="value1"
|
|
type="daterange"
|
|
start-placeholder="Start date"
|
|
end-placeholder="End date"
|
|
:size="size"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</Select>
|
|
</div>
|
|
<span class="line"></span>
|
|
<div class="btn">
|
|
<Select v-model="selectedFavorite" :options="favoriteOptions" width="auto" >
|
|
<template #prefix>
|
|
<i-ep-Star />
|
|
</template>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
|
|
<VirtualScroller
|
|
ref="scrollerRef"
|
|
v-if="props.if"
|
|
:items="list"
|
|
key-field="id"
|
|
:estimated-height="300"
|
|
:buffer-size="3"
|
|
direction="reverse"
|
|
:bottom-placeholder-height="350"
|
|
class="scroller"
|
|
@scroll="handleScroll"
|
|
@visible-change="handleVisibleChange"
|
|
>
|
|
<template #default="{ item, index }">
|
|
<Set :key="item.id" :item="item" @open-canvas="openCanvas" @delete-success="handleDeleteSuccess" />
|
|
</template>
|
|
<template #bottom-placeholder>
|
|
<div style="height: 350px;"></div>
|
|
</template>
|
|
</VirtualScroller>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { useDisplayStore, useParamStore, useUserStore } from '@/stores'
|
|
import { storeToRefs } from 'pinia'
|
|
import Set from './components/set.vue'
|
|
import RefreshOverlay from './components/RefreshOverlay.vue'
|
|
import Select from '@/components/Select/index.vue'
|
|
import { VirtualScroller } from '@/components/virtual-scroller'
|
|
import Canvas from '@/components/canvas/index.vue'
|
|
import { getGenerateHistoryList } from '@/apis/display'
|
|
import { useRouter } from 'vue-router'
|
|
import { getChargeType } from '@/utils/websocket'
|
|
|
|
const props = defineProps({
|
|
if: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
type: {
|
|
type: String,
|
|
default: 'painting'
|
|
}
|
|
})
|
|
|
|
const useDisplay = useDisplayStore()
|
|
const useParams = useParamStore()
|
|
const userStore = useUserStore()
|
|
const router = useRouter()
|
|
const refreshing = ref(false)
|
|
const scrollerRef = ref(null)
|
|
const isLoadingMoreLocked = ref(false)
|
|
const activeTab = ref('all')
|
|
const isInitializing = ref(true)
|
|
const { canvasVisible, canvasImage, canvasReferenceImages, canvasSource } = storeToRefs(useDisplay)
|
|
|
|
const chargeType = computed(() => getChargeType(props.type))
|
|
// console.log(chargeType.value)
|
|
|
|
const timeOptions = [
|
|
{ label: '全部', value: 'all' },
|
|
{ label: '最近一周', value: 'week' },
|
|
{ label: '最近一个月', value: 'month' },
|
|
{ label: '最近三个月', value: 'quarter' }
|
|
]
|
|
|
|
const favoriteOptions = [
|
|
{ label: '全部', value: 'all' },
|
|
{ label: '已收藏', value: 'favorite' }
|
|
]
|
|
|
|
const selectedTime = ref('all')
|
|
const selectedFavorite = ref('all')
|
|
const { tempList, currentPage, hasMoreData, isLoading } = storeToRefs(useDisplay)
|
|
|
|
const activeFilter = ref('all')
|
|
const list = computed(() => {
|
|
const data = tempList.value || []
|
|
if (activeFilter.value === 'all') {
|
|
return data
|
|
}
|
|
return data.filter((item) => item.type === activeFilter.value)
|
|
})
|
|
|
|
const toggleDisplay = (newValue, oldValue) => {
|
|
activeFilter.value = newValue
|
|
}
|
|
|
|
const conversion = (newlist) => {
|
|
const temp = newlist.map((item) => {
|
|
const files = item.fileUrl ? item.fileUrl.split(',').filter(url => url.trim()) : []
|
|
const generateData = JSON.parse(item.result || '{}')
|
|
return {
|
|
id: item.id,
|
|
taskId: item.taskId,
|
|
type: props.type,
|
|
collection: item.collection,
|
|
status: 'success',
|
|
generateData: generateData,
|
|
time: item.createTime,
|
|
files: files,
|
|
collectStatus: item.collectStatus || {}
|
|
}
|
|
})
|
|
console.log(temp)
|
|
return temp
|
|
}
|
|
|
|
const fetchHistory = async (isLoadMore = false) => {
|
|
if (isLoading.value || (!isLoadMore && !hasMoreData.value)) return
|
|
|
|
isLoading.value = true
|
|
|
|
try {
|
|
const pageToFetch = isLoadMore ? currentPage.value + 1 : 1
|
|
|
|
const result = await getGenerateHistoryList({
|
|
userId: userStore.userInfo.id,
|
|
chargeType: chargeType.value,
|
|
page: pageToFetch,
|
|
size: 10,
|
|
sort: 'createTime,desc'
|
|
})
|
|
|
|
const dataList = result.data?.list || result.data || []
|
|
|
|
if (dataList.length === 0) {
|
|
hasMoreData.value = false
|
|
if (!isLoadMore) {
|
|
refreshing.value = false
|
|
isInitializing.value = false
|
|
useDisplay.Sender_variant = 'updown'
|
|
router.push({ name: 'generate' })
|
|
}
|
|
return
|
|
}
|
|
|
|
const adaptedList = conversion(dataList)
|
|
|
|
if (isLoadMore) {
|
|
useDisplay.appendHistoryList(adaptedList)
|
|
currentPage.value = pageToFetch
|
|
} else {
|
|
useDisplay.initHistoryList(adaptedList)
|
|
currentPage.value = 1
|
|
|
|
await nextTick()
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
setTimeout(() => {
|
|
if (scrollerRef.value && typeof scrollerRef.value.scrollToBottom === 'function') {
|
|
scrollerRef.value.scrollToBottom()
|
|
}
|
|
}, 100 * i)
|
|
}
|
|
|
|
setTimeout(() => {
|
|
if (scrollerRef.value && typeof scrollerRef.value.scrollToBottom === 'function') {
|
|
scrollerRef.value.scrollToBottom()
|
|
}
|
|
setTimeout(() => {
|
|
refreshing.value = false
|
|
isInitializing.value = false
|
|
useDisplay.scrollToBottom()
|
|
}, 300)
|
|
}, 600)
|
|
}
|
|
|
|
hasMoreData.value = dataList.length === 10
|
|
|
|
} catch (error) {
|
|
console.error('获取历史失败:', error)
|
|
ElMessage({
|
|
message: '获取历史失败',
|
|
type: 'warning'
|
|
})
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
const handleScroll = (scrollInfo) => {
|
|
if (isInitializing.value) return
|
|
|
|
if (!scrollInfo) return
|
|
const { isAtPageTop, isAtPageBottom, distanceToPageTop, distanceToPageBottom } = scrollInfo
|
|
|
|
if (isAtPageTop && !isLoading.value && !isLoadingMoreLocked.value && hasMoreData.value) {
|
|
isLoadingMoreLocked.value = true
|
|
fetchHistory(true)
|
|
setTimeout(() => {
|
|
isLoadingMoreLocked.value = false
|
|
}, 3000)
|
|
}
|
|
|
|
if (isAtPageBottom) {
|
|
useDisplay.Sender_variant = 'updown'
|
|
} else if (distanceToPageTop >= 350) {
|
|
useDisplay.Sender_variant = 'default'
|
|
}
|
|
}
|
|
|
|
const handleVisibleChange = (startIndex, endIndex) => {
|
|
}
|
|
|
|
const handleScrollStart = () => {}
|
|
|
|
const handleScrollEnd = () => {}
|
|
|
|
const openCanvas = (data) => {
|
|
useDisplay.openCanvas(data)
|
|
}
|
|
|
|
const handleCanvasSend = (data) => {
|
|
console.log('Canvas send:', data)
|
|
}
|
|
|
|
const handleExit = () => {
|
|
if (window.parent !== window) {
|
|
window.parent.postMessage({
|
|
action: 'navigateBack',
|
|
source: 'display-exit'
|
|
}, 'https://sxwz.xueai.art')
|
|
} else {
|
|
router.go(-1)
|
|
}
|
|
}
|
|
|
|
const handleDeleteSuccess = (id) => {
|
|
useDisplay.deleteHistoryItem(id)
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!props.loading) return
|
|
refreshing.value = true
|
|
|
|
nextTick(() => {
|
|
useDisplay.scrollerRef = scrollerRef.value
|
|
useDisplay.resetPagination()
|
|
fetchHistory()
|
|
})
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
useDisplay.resetPagination()
|
|
})
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.content-area {
|
|
width: 100%;
|
|
min-width: 750px;
|
|
height: 100%;
|
|
overflow-y: auto;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.back{
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
height: 36px;
|
|
padding: 10px;
|
|
position: absolute;
|
|
left: 30px;
|
|
top: 22px;
|
|
z-index: 3;
|
|
cursor: pointer;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.back:hover{
|
|
background-color: #e4e7ed;
|
|
}
|
|
|
|
.btn-container{
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
height: auto;
|
|
padding: 4px;
|
|
right: 30px;
|
|
top: 22px;
|
|
z-index: 3;
|
|
|
|
border-radius: 10px;
|
|
background-color: #FAFBFC;
|
|
position: absolute;
|
|
|
|
.btn{
|
|
display: flex;
|
|
padding: 5px;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.btn-text{
|
|
color: #000;
|
|
font-family: "Microsoft YaHei";
|
|
font-size: 14px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 18px;
|
|
text-align: center;
|
|
}
|
|
|
|
.line{
|
|
width: 1px;
|
|
height: 8px;
|
|
background-color: #ccc;
|
|
}
|
|
}
|
|
|
|
</style>
|