优化显示逻辑
This commit is contained in:
parent
6c2ac44b33
commit
e6290b53e5
|
|
@ -2,9 +2,11 @@
|
|||
<Transition name="slide-up">
|
||||
<div class="input-container" :class="{ generate : !props.isGenerate }" @click="handleContainerClick">
|
||||
<div v-if="!props.isGenerate" class="title">AI绘画2026</div>
|
||||
|
||||
<div v-if="useDisplay.Sender_variant === 'default'" class="scroll-to-bottom-btn" @click.stop="handleScrollToBottom">
|
||||
<div class="scroll-to-bottom-text">回到底部</div>
|
||||
</div>
|
||||
|
||||
<Sender :key="useDisplay.Sender_variant" v-model="prompt" :variant="useDisplay.Sender_variant" :placeholder="promptPlaceholder" :submit-btn-disabled="isgerenate.value" :auto-size="autoSizeConfig">
|
||||
<template #prefix>
|
||||
<div v-show="useDisplay.Sender_variant !== 'default'" class="prefix-self-wrap">
|
||||
|
|
@ -18,7 +20,7 @@
|
|||
</div>
|
||||
|
||||
<Model v-model="model" />
|
||||
<Proportion v-model="proportion" />
|
||||
<Proportion v-model="proportion" v-model:resolution="resolution" />
|
||||
<Quantity v-model="quantity" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -82,9 +84,10 @@ const uploadRef = ref(null)
|
|||
const model = ref('flux')
|
||||
const proportion = ref('9:16')
|
||||
const quantity = ref(1)
|
||||
const resolution = ref('1k')
|
||||
|
||||
const promptPlaceholder = '描述你想生成的画面和动作。'
|
||||
const prompt = ref('')
|
||||
const prompt = ref('一个女孩在树下吃苹果')
|
||||
const imageurl = ref('')
|
||||
const imageurlShow = ref('')
|
||||
const isgerenate = ref(false)
|
||||
|
|
@ -164,11 +167,16 @@ const handleStart = async () => {
|
|||
isgerenate.value = true
|
||||
console.log('生成开始', isgerenate.value)
|
||||
const data = {
|
||||
videoImg: imageurl.value,
|
||||
text: prompt.value,
|
||||
file_type: 'video',
|
||||
AIGC: 'Painting',
|
||||
platform: 'runninghub',
|
||||
file_type: 'image',
|
||||
modelName: model.value,
|
||||
prompt: prompt.value,
|
||||
quantity: quantity.value,
|
||||
aspect_ratio: proportion.value,
|
||||
resolution: resolution.value,
|
||||
}
|
||||
await generate(data, 1, 1)
|
||||
await generate('text', data)
|
||||
console.log('生成中', isgerenate.value)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,16 +63,25 @@ const props = defineProps({
|
|||
modelValue: {
|
||||
type: String,
|
||||
default: '1:1'
|
||||
},
|
||||
resolution: {
|
||||
type: String,
|
||||
default: '2k'
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'update:width', 'update:height'])
|
||||
const emit = defineEmits(['update:modelValue', 'update:resolution', 'update:width', 'update:height'])
|
||||
|
||||
const proportion = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
})
|
||||
|
||||
const resolution = computed({
|
||||
get: () => props.resolution,
|
||||
set: (value) => emit('update:resolution', value)
|
||||
})
|
||||
|
||||
const proportionOptions = [
|
||||
{ value: '智能', label: '智能' },
|
||||
{ value: '21:9', label: '21:9' },
|
||||
|
|
@ -91,7 +100,6 @@ const resolutionOptions = [
|
|||
{ value: '4k', label: '超清 4K' }
|
||||
]
|
||||
|
||||
const resolution = ref('2k')
|
||||
const width = ref(2048)
|
||||
const height = ref(2048)
|
||||
|
||||
|
|
@ -199,8 +207,9 @@ const getProportionStyle = (value) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
updateDimensionsByResolution(resolution.value)
|
||||
watch(() => [props.modelValue, props.resolution], () => {
|
||||
updateDimensionsByResolution(resolution.value)
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
import * as runninghub from './runninghub/index.js'
|
||||
// import * as suno from './suno.js'
|
||||
|
||||
export default { runninghub }
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
export function Playload(data, type) {
|
||||
data = getWidthHeight(data)
|
||||
console.log('宽与高', data)
|
||||
if(data.modelName === 'flux'){
|
||||
return flux(data)
|
||||
}
|
||||
}
|
||||
|
||||
export function result(result) {
|
||||
if (result.code === 0 && result.msg === 'success') {
|
||||
return { type: true, url: result.data[0].fileUrl }
|
||||
}
|
||||
return { type: false, message: result.data.exception_message }
|
||||
}
|
||||
function getWidthHeight(data) {
|
||||
// 去除分辨率字符串中的'p'并转换为数字
|
||||
// const resolution = 720
|
||||
const resolution = Number.parseInt(data.resolution.replace('p', '')) || Number.parseInt(data.resolution)
|
||||
// 解析宽高比
|
||||
const aspectRatioParts = data.aspect_ratio.split(':') || data.aspect_ratio.split(':')
|
||||
const widthRatio = Number.parseInt(aspectRatioParts[0])
|
||||
const heightRatio = Number.parseInt(aspectRatioParts[1])
|
||||
if (widthRatio > heightRatio) {
|
||||
data.height = resolution
|
||||
data.width = Math.round(resolution * widthRatio / heightRatio)
|
||||
} else {
|
||||
data.width = resolution
|
||||
data.height = Math.round(resolution * heightRatio / widthRatio)
|
||||
}
|
||||
console.log(data.width, data.height)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
function LTX2(data) {
|
||||
|
||||
const nodeInfoList = [
|
||||
{ nodeId: '9', fieldName: 'text', fieldValue: data.prompt },
|
||||
{ nodeId: '40', fieldName: 'text', fieldValue: data.aspect_ratio },
|
||||
{ nodeId: '39', fieldName: 'text', fieldValue: data.resolution },
|
||||
{ nodeId: '29', fieldName: 'index', fieldValue: '' }
|
||||
]
|
||||
switch (index){
|
||||
case 1:
|
||||
nodeInfoList[3].fieldValue = '1'
|
||||
break
|
||||
case 2:
|
||||
nodeInfoList[3].fieldValue = '2'
|
||||
break
|
||||
case 3:
|
||||
nodeInfoList[3].fieldValue = '3'
|
||||
break
|
||||
case 4:
|
||||
nodeInfoList[3].fieldValue = '4'
|
||||
break
|
||||
}
|
||||
if (data.image1) nodeInfoList.push({ nodeId: '2', fieldName: 'image', fieldValue: data.image1 })
|
||||
if (data.image2) nodeInfoList.push({ nodeId: '3', fieldName: 'image', fieldValue: data.image2 })
|
||||
if (data.image3) nodeInfoList.push({ nodeId: '4', fieldName: 'image', fieldValue: data.image3 })
|
||||
if (data.image4) nodeInfoList.push({ nodeId: '13', fieldName: 'image', fieldValue: data.image4 })
|
||||
if (data.image5) nodeInfoList.push({ nodeId: '14', fieldName: 'image', fieldValue: data.image5 })
|
||||
|
||||
return {
|
||||
workflowId: '2031032712240304130',
|
||||
nodeInfoList
|
||||
}
|
||||
}
|
||||
|
||||
function flux(data) {
|
||||
|
||||
const nodeInfoList = [
|
||||
{ nodeId: '23', fieldName: 'text', fieldValue: data.prompt },
|
||||
{ nodeId: '129', fieldName: 'aspect_ratio', fieldValue: data.aspect_ratio },
|
||||
{ nodeId: '101', fieldName: 'control_after_generate', fieldValue: 'randomize' }
|
||||
]
|
||||
|
||||
return {
|
||||
workflowId: '2011689651156819970',
|
||||
nodeInfoList
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ const router = createRouter({
|
|||
routes
|
||||
})
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
router.beforeEach(async (to, from) => {
|
||||
if(to.query.token){
|
||||
setToken(to.query.token)
|
||||
} else {
|
||||
|
|
@ -37,7 +37,7 @@ router.beforeEach(async (to, from, next) => {
|
|||
const token = getToken()
|
||||
if (!token) {
|
||||
// 没有 token,重定向到登录页
|
||||
return next('/login')
|
||||
return '/login'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ router.beforeEach(async (to, from, next) => {
|
|||
const userStore = useUserStore()
|
||||
// 如果访问的是白名单路径,直接放行
|
||||
if (whiteList.includes(to.path)) {
|
||||
return next()
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查 token 是否有效
|
||||
|
|
@ -60,15 +60,15 @@ router.beforeEach(async (to, from, next) => {
|
|||
// 如果用户信息不存在,则从服务器获取
|
||||
await userStore.getInfo()
|
||||
}
|
||||
next()
|
||||
return true
|
||||
} else {
|
||||
// token 无效,重定向到登录页
|
||||
next('/login')
|
||||
return '/login'
|
||||
}
|
||||
} catch (error) {
|
||||
// 验证过程中出错,重定向到登录页
|
||||
console.error('验证 token 时出错:', error)
|
||||
next('/login')
|
||||
return '/login'
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,53 +1,71 @@
|
|||
const DisplayStoreSetup = () => {
|
||||
const Sender_variant = ref('updown')
|
||||
const scrollerRef = ref(null)
|
||||
const tempList = ref([])
|
||||
|
||||
const scrollToBottom = () => {
|
||||
console.log('store - 尝试滚动到底部')
|
||||
const addGeneratingItem = (item) => {
|
||||
const newItem = {
|
||||
id: item.taskId || crypto.randomUUID(),
|
||||
status: 'generate',
|
||||
text: item.text || '生成中...',
|
||||
name: item.name || '生成中...',
|
||||
type: item.type || 'image',
|
||||
time: item.time || new Date().toLocaleString(),
|
||||
files: [],
|
||||
...item
|
||||
}
|
||||
tempList.value.push(newItem)
|
||||
return newItem
|
||||
}
|
||||
|
||||
const updateItemToSuccess = (taskId, fileUrl) => {
|
||||
const index = tempList.value.findIndex(item => item.id === taskId)
|
||||
if (index !== -1) {
|
||||
tempList.value[index].status = 'success'
|
||||
tempList.value[index].files = [fileUrl]
|
||||
}
|
||||
}
|
||||
|
||||
const initHistoryList = (historyList) => {
|
||||
tempList.value = historyList
|
||||
}
|
||||
|
||||
const scrollToBottom = async () => {
|
||||
console.log('store - 滚动到底部')
|
||||
const refValue = scrollerRef.value
|
||||
console.log('store - scrollerRef.value:', refValue)
|
||||
|
||||
if (refValue) {
|
||||
console.log('store - scrollerRef.value.$el:', refValue.$el)
|
||||
|
||||
try {
|
||||
if (typeof refValue.scrollToItem === 'function') {
|
||||
console.log('store - 使用 scrollToItem 方法')
|
||||
refValue.scrollToItem(refValue.items?.length - 1)
|
||||
} else {
|
||||
console.log('store - scrollToItem 方法不存在')
|
||||
|
||||
const scrollerEl = refValue.$el
|
||||
if (!scrollerEl) {
|
||||
console.log('store - scrollerEl 不存在')
|
||||
if (!refValue) {
|
||||
console.log('store - scrollerRef 不存在')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('store - scrollerEl:', scrollerEl)
|
||||
|
||||
try {
|
||||
const scrollerEl = refValue.$el
|
||||
if (scrollerEl) {
|
||||
const viewport = scrollerEl.querySelector('.vue-recycle-scroller__viewport')
|
||||
if (viewport) {
|
||||
console.log('store - 找到 viewport 元素')
|
||||
console.log('store - 原生滚动, scrollHeight:', viewport.scrollHeight)
|
||||
viewport.scrollTop = viewport.scrollHeight
|
||||
console.log('store - viewport.scrollTop:', viewport.scrollTop)
|
||||
console.log('store - viewport.scrollHeight:', viewport.scrollHeight)
|
||||
|
||||
setTimeout(() => {
|
||||
viewport.scrollTop = viewport.scrollHeight
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof refValue.scrollToItem === 'function' && tempList.value && tempList.value.length > 0) {
|
||||
console.log('store - scrollToItem, index:', tempList.value.length - 1)
|
||||
await nextTick()
|
||||
refValue.scrollToItem(tempList.value.length - 1)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('store - 滚动出错:', error)
|
||||
}
|
||||
} else {
|
||||
console.log('store - scrollerRef 不存在')
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Sender_variant,
|
||||
scrollerRef,
|
||||
tempList,
|
||||
addGeneratingItem,
|
||||
updateItemToSuccess,
|
||||
initHistoryList,
|
||||
scrollToBottom
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +1,23 @@
|
|||
import { useParamStore } from '@/stores'
|
||||
|
||||
export async function getFormattedTime(date = new Date()) {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0') // 月份从0开始,需要+1
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
import outPlatform from '@/config/index'
|
||||
|
||||
// 处理音频生成任务的数据并返回
|
||||
export async function createTask(taskType = 1, params, title = '模特展示图') {
|
||||
const paramStore = useParamStore()
|
||||
const data = {
|
||||
taskId: params.taskId,
|
||||
taskRootId: params.taskRootId || paramStore.taskRootId,
|
||||
parentTaskId: params.parentTaskId || '0',
|
||||
AIGC: 'huanda',
|
||||
platform: 'runninghub',
|
||||
taskType,
|
||||
modelName: 'Flux',
|
||||
title,
|
||||
file_type: params.file_type,
|
||||
payload: {},
|
||||
createTime: params.time,
|
||||
parentCreateTime: params.parentCreateTime || '',
|
||||
parentIndex: params.parentIndex || '',
|
||||
token: params.token
|
||||
export async function createTask(data, type, taskId, token) {
|
||||
console.log(data, type)
|
||||
const payload = await outPlatform[data.platform].Playload(data)
|
||||
|
||||
return {
|
||||
AIGC: data.AIGC,
|
||||
platform: data.platform,
|
||||
prompt: data.prompt,
|
||||
taskType: type === 'text' ? 1 : 2,
|
||||
modelName: data.modelName,
|
||||
payload,
|
||||
taskId,
|
||||
token
|
||||
}
|
||||
|
||||
if (taskType === 1) {
|
||||
data.payload = workflows.huanda
|
||||
data.payload.nodeInfoList[0].fieldValue = paramStore.params.clothes
|
||||
data.payload.nodeInfoList[1].fieldValue = paramStore.params.model
|
||||
data.payload.nodeInfoList[2].fieldValue = paramStore.params.pose
|
||||
data.payload.nodeInfoList[3].fieldValue = paramStore.params.background
|
||||
data.payload.nodeInfoList[4].fieldValue = paramStore.params.model ? 0 : 1
|
||||
data.payload.nodeInfoList[5].fieldValue = paramStore.params.pose ? 0 : 1
|
||||
data.payload.nodeInfoList[6].fieldValue = paramStore.params.background ? 0 : 1
|
||||
data.payload.nodeInfoList[7].fieldValue = params.prompt
|
||||
data.payload.nodeInfoList[7].fieldValue = params.aspectRatio
|
||||
} else if (taskType === 2) { // 对话修改
|
||||
data.parentTaskId = params.parentTaskId
|
||||
|
||||
data.payload = workflows.talk
|
||||
data.payload.nodeInfoList[0].fieldValue = params.text
|
||||
data.payload.nodeInfoList[1].fieldValue = params.talkImg
|
||||
} else if (taskType === 3) { // 生成视频
|
||||
data.parentTaskId = params.parentTaskId
|
||||
|
||||
data.payload = workflows.video
|
||||
data.payload.nodeInfoList[0].fieldValue = params.text
|
||||
data.payload.nodeInfoList[1].fieldValue = params.videoImg
|
||||
} else if (taskType === 4) { // AI生成模特
|
||||
data.payload = workflows.model
|
||||
data.payload.nodeInfoList[0].fieldValue = params.text
|
||||
data.payload.nodeInfoList[1].fieldValue = params.aspectRatio
|
||||
} else if (taskType === 5 || taskType === 6) { // AI生成服装背景
|
||||
// data.parentTaskId = params.parentTaskId
|
||||
|
||||
data.payload = workflows.background_pose
|
||||
data.payload.nodeInfoList[0].fieldValue = params.text
|
||||
data.payload.nodeInfoList[1].fieldValue = params.aspectRatio
|
||||
}
|
||||
console.log('data:', data)
|
||||
return data
|
||||
}
|
||||
|
||||
// 获取音频结果
|
||||
// 获取结果
|
||||
export async function getTask(result) {
|
||||
if (result.code === 0 && result.msg === 'success') {
|
||||
return { type: true, url: result.data[0].fileUrl }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ElNotification } from 'element-plus'
|
||||
import { h, ref } from 'vue'
|
||||
import { useDisplayStore, useParamStore, useUserStore } from '@/stores'
|
||||
import { useDisplayStore } from '@/stores'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { createTask, getFormattedTime, getTask } from '@/utils/createTask'
|
||||
import { createTask, getTask } from '@/utils/createTask'
|
||||
import { userError } from '@/utils/tokenError'
|
||||
|
||||
export function websocketError(code, msg) {
|
||||
|
|
@ -47,14 +47,17 @@ export function websocketSuccess() {
|
|||
})
|
||||
}
|
||||
|
||||
export async function generate(taskType, data, type) {
|
||||
export async function generate(type, data) {
|
||||
const progress_text = ref('')
|
||||
const message = ref('')
|
||||
const previewUrl = ref('')
|
||||
const useDisplay = useDisplayStore()
|
||||
const token = getToken()
|
||||
const taskId = crypto.randomUUID()
|
||||
let currentTaskId = null
|
||||
|
||||
const result = await createTask(taskType, { text: data.prompt, aspect_ratio: data.aspectRatio, token })
|
||||
const result = await createTask(data, type, taskId, token)
|
||||
console.log(result)
|
||||
// const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjY0NDEwODAyMjk1OTgzNzIzMCwicm5TdHIiOiJiWkVwS2JLWFJyZmRIaFFHWXZKTkdzOGdGM0JSRmxQOCJ9.5eQ2GtVdrDntQDe2tnF8vl_DhTfd2uW-KNqzvl1imc0'
|
||||
const wsURL = `${import.meta.env.VITE_API_WORKFLOW_WS}/?token=${token}`
|
||||
const socket = new WebSocket(wsURL)
|
||||
|
|
@ -73,7 +76,7 @@ export async function generate(taskType, data, type) {
|
|||
return
|
||||
} else if (event.data === 'please give me taskId') {
|
||||
socket.send(`setTaskId:${taskId}`)
|
||||
progerss_text.value = '信息提交中...'
|
||||
progress_text.value = '信息提交中...'
|
||||
return
|
||||
} else if (event.data === 'OK! Please continue. ') {
|
||||
socket.send(JSON.stringify({
|
||||
|
|
@ -82,12 +85,16 @@ export async function generate(taskType, data, type) {
|
|||
}))
|
||||
return
|
||||
} else if (event.data === '任务提交成功,正在排队中...') {
|
||||
progerss_text.value = '视频生成中...'
|
||||
// 启动进度条更新
|
||||
startTime.value = Date.now()
|
||||
progressPercent.value = 0
|
||||
progressInterval.value = window.setInterval(updateProgress, 1000)
|
||||
progress.value = true
|
||||
progress_text.value = '视频生成中...'
|
||||
currentTaskId = taskId
|
||||
|
||||
useDisplay.addGeneratingItem({
|
||||
taskId: taskId,
|
||||
text: data.prompt || '生成中...',
|
||||
name: data.prompt || '生成中...',
|
||||
type: type
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
message.value = event.data
|
||||
|
|
@ -114,7 +121,6 @@ export async function generate(taskType, data, type) {
|
|||
// 处理链接关闭
|
||||
socket.onclose = async (event) => {
|
||||
console.log('WebSocket已关闭:', event)
|
||||
isGenerating.value = false
|
||||
|
||||
// 清理心跳定时器
|
||||
if (heartbeatInterval) {
|
||||
|
|
@ -126,9 +132,14 @@ export async function generate(taskType, data, type) {
|
|||
userError()
|
||||
} else if (event.code === 1000 && event.reason === 'success') {
|
||||
console.log('收到服务器消息:', res)
|
||||
const result = await getVideo(tempPlatform.value, res)
|
||||
const result = await getTask(res)
|
||||
if (result.type) {
|
||||
previewUrl.value = result.url
|
||||
|
||||
if (currentTaskId) {
|
||||
useDisplay.updateItemToSuccess(currentTaskId, result.url)
|
||||
}
|
||||
|
||||
websocketSuccess()
|
||||
} else {
|
||||
websocketError(4403, res.message)
|
||||
|
|
@ -136,10 +147,7 @@ export async function generate(taskType, data, type) {
|
|||
} else {
|
||||
websocketError(event.code, event.reason)
|
||||
}
|
||||
progress.value = false
|
||||
clearInterval(progressInterval.value)
|
||||
progressInterval.value = null
|
||||
isGenerating.value = false
|
||||
// clearInterval(progressInterval.value)
|
||||
// 清理心跳定时器
|
||||
if (heartbeatInterval) {
|
||||
clearInterval(heartbeatInterval)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ defineProps({
|
|||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
background-color: rgb(255, 255, 255);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
<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'
|
||||
|
|
@ -91,6 +92,7 @@ const refreshing = ref(false)
|
|||
const scrollerRef = ref(null)
|
||||
const isLoadingMore = ref(false)
|
||||
const activeTab = ref('all')
|
||||
const isInitializing = ref(true)
|
||||
let total = 0
|
||||
|
||||
const timeOptions = [
|
||||
|
|
@ -107,27 +109,30 @@ const favoriteOptions = [
|
|||
|
||||
const selectedTime = ref('all')
|
||||
const selectedFavorite = ref('all')
|
||||
const tempList = ref([])
|
||||
const { tempList } = storeToRefs(useDisplay)
|
||||
|
||||
// const tempList = ref([
|
||||
// { id: 0, type: 'image', status: 'none', name: '局部重绘', time: '2025-12-01 18:26', files: [] },
|
||||
// { id: 1, type: 'image', status: 'success', name: '局部重绘', time: '2025-12-01 18:26', parentName: '2', parentTime: '2025-12-01 12:26', files: ['https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png'] },
|
||||
// { id: 2, type: 'image', status: 'success', name: '局部重绘', time: '2025-12-01 18:26', parentName: '2', parentTime: '2025-12-01 12:26', files: ['https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png'] },
|
||||
// { id: 3, type: 'image', status: 'success', name: '局部重绘', time: '2025-12-01 18:26', parentName: '2', parentTime: '2025-12-01 12:26', files: ['https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png'] },
|
||||
// { id: 4, type: 'image', status: 'success', name: '局部重绘', time: '2025-12-01 18:26', parentName: '2', parentTime: '2025-12-01 12:26', files: ['https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png', 'https://sxwz.xueai.art/static/png/image4-1-1-BZWQeEAk.png'] }
|
||||
|
||||
|
||||
// ])
|
||||
const list = ref()
|
||||
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 page = ref(1)
|
||||
list.value = tempList.value
|
||||
// 筛选列表里的不同生成类型: 图片,视频
|
||||
const toggleDisplay = (newValue, oldValue) => {
|
||||
if ((newValue === 'image' || newValue === 'video') && oldValue === 'all') {
|
||||
list.value = tempList.value.filter((item) => item.type === newValue)
|
||||
} else if ((newValue === 'image' || newValue === 'video') && (oldValue === 'image' || oldValue === 'video')) {
|
||||
list.value = tempList.value.filter((item) => item.type === newValue)
|
||||
} else {
|
||||
list.value = tempList.value
|
||||
}
|
||||
console.log(list.value)
|
||||
activeFilter.value = newValue
|
||||
}
|
||||
|
||||
// 转换数据
|
||||
|
|
@ -149,8 +154,12 @@ const conversion = (newlist) => {
|
|||
// 获取历史列表
|
||||
const fetchHistory= async (isScrollTopLoad = false) => {
|
||||
try {
|
||||
if (isScrollTopLoad) {
|
||||
return
|
||||
}
|
||||
|
||||
const result = await getGenerateHistoryList({ userId: userStore.userInfo.id, chargeType: 1 })
|
||||
total = result.data.length
|
||||
total = result.data ? result.data.length : 0
|
||||
if (total === 0) {
|
||||
useDisplay.Sender_variant = 'updown'
|
||||
router.push({ name: 'home' })
|
||||
|
|
@ -175,19 +184,48 @@ const fetchHistory= async (isScrollTopLoad = false) => {
|
|||
})
|
||||
|
||||
if (!isScrollTopLoad && adaptedList.length > 0) {
|
||||
tempList.value = [adaptedList[adaptedList.length - 1]]
|
||||
list.value = tempList.value
|
||||
useDisplay.initHistoryList(adaptedList)
|
||||
|
||||
await nextTick()
|
||||
|
||||
const scrollToBottomDirect = (force = false) => {
|
||||
if (scrollerRef.value) {
|
||||
const el = scrollerRef.value.$el
|
||||
if (el) {
|
||||
const viewport = el.querySelector('.vue-recycle-scroller__viewport')
|
||||
if (viewport) {
|
||||
console.log('直接滚动 - scrollHeight:', viewport.scrollHeight, 'force:', force)
|
||||
if (force) {
|
||||
viewport.scrollTop = viewport.scrollHeight + 1000
|
||||
} else {
|
||||
viewport.scrollTop = viewport.scrollHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof scrollerRef.value.scrollToItem === 'function') {
|
||||
console.log('直接 scrollToItem')
|
||||
scrollerRef.value.scrollToItem(list.value.length - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
setTimeout(() => {
|
||||
scrollToBottomDirect(i >= 15)
|
||||
}, 60 * i)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const remainingItems = adaptedList.slice(0, -1)
|
||||
tempList.value = [...remainingItems, ...tempList.value]
|
||||
list.value = tempList.value
|
||||
console.log('添加剩余数据后列表长度:', tempList.value.length)
|
||||
}, 1000)
|
||||
await nextTick()
|
||||
scrollToBottomDirect(true)
|
||||
setTimeout(() => {
|
||||
refreshing.value = false
|
||||
isInitializing.value = false
|
||||
useDisplay.scrollToBottom()
|
||||
}, 600)
|
||||
}, 1500)
|
||||
} else {
|
||||
tempList.value = adaptedList
|
||||
list.value = tempList.value
|
||||
useDisplay.initHistoryList(adaptedList)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取历史失败:', error)
|
||||
|
|
@ -201,25 +239,28 @@ const fetchHistory= async (isScrollTopLoad = false) => {
|
|||
// 获取下一页数据
|
||||
const getList = async () => {
|
||||
if (isLoadingMore.value) return
|
||||
|
||||
isLoadingMore.value = true
|
||||
|
||||
try {
|
||||
await fetchHistory(true)
|
||||
} finally {
|
||||
isLoadingMore.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理滚动事件
|
||||
const handleScroll = (event) => {
|
||||
if (isInitializing.value) return
|
||||
|
||||
const { scrollTop, scrollHeight, clientHeight } = event.target
|
||||
const distanceToBottom = scrollHeight - scrollTop - clientHeight
|
||||
|
||||
if (scrollTop <= 50 && !isLoadingMore.value) {
|
||||
getList()
|
||||
}
|
||||
// 临时禁用滚动到顶部获取历史记录
|
||||
// if (scrollTop <= 50 && !isLoadingMore.value) {
|
||||
// getList()
|
||||
// }
|
||||
|
||||
if (distanceToBottom <= 50) {
|
||||
useDisplay.Sender_variant = 'updown'
|
||||
refreshing.value = false
|
||||
} else if (distanceToBottom >= 350) {
|
||||
useDisplay.Sender_variant = 'default'
|
||||
}
|
||||
|
|
@ -229,21 +270,14 @@ onMounted(() => {
|
|||
console.log('display 组件已挂载')
|
||||
if (!props.loading) return
|
||||
refreshing.value = true
|
||||
fetchHistory()
|
||||
|
||||
nextTick(() => {
|
||||
console.log('设置 scrollerRef 到 store')
|
||||
useDisplay.scrollerRef = scrollerRef.value
|
||||
useDisplay.scrollToBottom()
|
||||
fetchHistory()
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('setTimeout 后尝试滚动')
|
||||
useDisplay.scrollToBottom()
|
||||
setTimeout(() => {
|
||||
refreshing.value = false
|
||||
}, 1000)
|
||||
}, 1000)
|
||||
page.value++
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue