待接入历史记录与生成逻辑

This commit is contained in:
王佑琳 2026-03-09 10:20:10 +08:00
parent cc3eeb001f
commit d9d7ff22b6
20 changed files with 143 additions and 362 deletions

View File

@ -1,18 +0,0 @@
import service from '@/utils/request'
const BASE_URL = '/business'
/** @desc 传入userId、url、clothesId */
export function setCollectImg(req) {
return service.post(`${BASE_URL}/collect`, req)
}
/** @desc 根据id批量取消收藏 */
export function delCollectImg(req) {
return service.del(`${BASE_URL}/collect/batchDelete`, req)
}
/** @desc 根据userId分页查询收藏 */
export function getCollectImg(req) {
return service.get(`${BASE_URL}/collect/page`, req)
}

View File

@ -1,18 +0,0 @@
import service from '@/utils/request'
const BASE_URL = '/business'
/** @desc 通过rootid查询包含的任务列表 */
export function setTaskRootId(req) {
return service.post(`${BASE_URL}/rootTask`, req)
}
/** @desc 查询用户所含的rootId */
export function AllRootTask(req) {
return service.get(`${BASE_URL}/rootTask/page`, { params: req })
}
/** @desc 查询用户所含的rootId */
// export function getLibraryImg(req) {
// return service.put(`${BASE_URL}/rootTask/${req}`)
// }

View File

@ -0,0 +1,6 @@
import service from '@/utils/request'
// 获取生成历史列表
export function getGenerateHistoryList(query) {
return service.get('/taskRecordHistory/list', { params: query })
}

View File

@ -1,13 +0,0 @@
import service from '@/utils/request'
const BASE_URL = '/billing'
/** @desc 通过rootid查询包含的任务列表 */
export function getTaskListByRootId(req) {
return service.post(`${BASE_URL}/queryTaskListByRootId`, req)
}
/** @desc 查询用户所含的rootId */
export function getLibraryImg(req) {
return service.get(`${BASE_URL}/page`, { params: req })
}

View File

@ -1,18 +0,0 @@
import service from '@/utils/request'
const BASE_URL = '/business/huandaResource'
/** @desc 添加图片 */
export function addLibraryImg(req) {
return service.post(`${BASE_URL}`, req)
}
/** @desc 删除图片 */
export function delLibraryImg(req) {
return service.post(`${BASE_URL}/batchDelete`, req)
}
/** @desc 查询单个库的所有图片 */
export function getLibraryImg(req) {
return service.get(`${BASE_URL}/page`, { params: req })
}

View File

@ -1,28 +0,0 @@
// axios 发送ajax请求
import service from '@/utils/request'
export default {
// 发起支付请求
tradePagePay(productId, userId, totalFee) {
return service({
url: `/pay/ali-pay/trade/page/pay/${productId}`,
params: { userId, totalFee },
method: 'post'
})
},
cancel(orderNo) {
return service({
url: `/pay/ali-pay/trade/close/${orderNo}`,
method: 'post'
})
},
refunds(orderNo, reason) {
return service({
url: `/pay/ali-pay/trade/refund/${orderNo}/${reason}`,
method: 'post'
})
}
}

View File

@ -1,11 +0,0 @@
import aliPayApi from './aliPay'
import orderInfoApi from './orderInfo'
import productApi from './product'
import wxPayApi from './wxPay'
export {
aliPayApi,
orderInfoApi,
productApi,
wxPayApi
}

View File

@ -1,27 +0,0 @@
import request from '@/utils/request'
export default {
// 查询订单列表
list() {
return request({
url: '/apy/order-info/list',
method: 'get'
})
},
// 查询订单状态
queryOrderStatus(orderNo) {
return request({
url: `/pay/order-info/query-order-status/${orderNo}`,
method: 'get'
})
},
// 查询用户的sysBeans
queryUserSysBeans(userId) {
return request({
url: `/pay/beans/getSysBeans/${userId}`,
method: 'get'
})
}
}

View File

@ -1,13 +0,0 @@
// axios 发送ajax请求
import request from '@/utils/request'
export default {
// 查询商品列表(对远程接口调用)
list() {
return request({
url: '/pay/product/list',
method: 'get'
})
}
}

View File

@ -1,36 +0,0 @@
// axios 发送ajax请求
import request from '@/utils/request'
export default {
// Native下单
nativePay(productId, userId, totalFee) {
return request({
url: `/pay/wx-pay/native/${productId}`,
params: { userId, totalFee },
method: 'post'
})
},
// Native下单(v2)
nativePayV2(productId) {
return request({
url: `/pay/wx-pay-v2/native/${productId}`,
method: 'post'
})
},
cancel(orderNo) {
return request({
url: `/pay/wx-pay/cancel/${orderNo}`,
method: 'post'
})
},
refunds(orderNo, reason) {
return request({
url: `/pay/wx-pay/refunds/${orderNo}/${reason}`,
method: 'post'
})
}
}

View File

@ -1,107 +0,0 @@
{
"model": {
"workflowId": "1998946903104610306",
"nodeInfoList": [
{
"nodeId": "12",
"fieldName": "text",
"fieldValue": "一位中年女医生,短发利落清爽,身着薄荷绿医务衬衫。她以站立的姿势,面向镜头。背景为柔和的白色眼神明亮而充满鼓励。"
},
{
"nodeId": "16",
"fieldName": "aspect_ratio",
"fieldValue": "aspect_ratio"
}
]
},
"background_pose": {
"workflowId": "1996842562587611138",
"nodeInfoList": [
{
"nodeId": "11",
"fieldName": "text",
"fieldValue": ""
},
{
"nodeId": "10",
"fieldName": "aspect_ratio",
"fieldValue": "aspect_ratio"
}
]
},
"huanda": {
"workflowId": "1996836769582784513",
"nodeInfoList": [
{
"nodeId": "2",
"fieldName": "image",
"fieldValue": "image"
},
{
"nodeId": "3",
"fieldName": "image",
"fieldValue": "image"
},
{
"nodeId": "10",
"fieldName": "image",
"fieldValue": "image"
},
{
"nodeId": "14",
"fieldName": "image",
"fieldValue": "image"
},
{
"nodeId": "18",
"fieldName": "index",
"fieldValue": "index"
},
{
"nodeId": "34",
"fieldName": "index",
"fieldValue": "index"
},
{
"nodeId": "37",
"fieldName": "index",
"fieldValue": "index"
},
{
"nodeId": "29",
"fieldName": "aspect_ratio",
"fieldValue": "aspect_ratio"
}
]
},
"video": {
"workflowId": "1996136037531500545",
"nodeInfoList": [
{
"nodeId": "55",
"fieldName": "prompt",
"fieldValue": ""
},
{
"nodeId": "16",
"fieldName": "image",
"fieldValue": "image"
}
]
},
"talk": {
"workflowId": "1996137696278069250",
"nodeInfoList": [
{
"nodeId": "1",
"fieldName": "prompt",
"fieldValue": ""
},
{
"nodeId": "2",
"fieldName": "image",
"fieldValue": "image"
}
]
}
}

View File

@ -1,7 +1,7 @@
<template> <template>
<Transition name="slide-up"> <Transition name="slide-up">
<div class="input-container" :class="{ generate : props.isGenerate}"> <div class="input-container" :class="{ generate : !props.isGenerate}">
<div v-if="props.isGenerate" class="title">AI绘画2026</div> <div v-if="!props.isGenerate" class="title">AI绘画2026</div>
<Sender :key="useDisplay.Sender_variant" v-model="prompt" :variant="useDisplay.Sender_variant" :placeholder="promptPlaceholder" :submit-btn-disabled="isgerenate.value" :auto-size="autoSizeConfig"> <Sender :key="useDisplay.Sender_variant" v-model="prompt" :variant="useDisplay.Sender_variant" :placeholder="promptPlaceholder" :submit-btn-disabled="isgerenate.value" :auto-size="autoSizeConfig">
<template #prefix> <template #prefix>
<div v-show="useDisplay.Sender_variant !== 'default'" class="prefix-self-wrap"> <div v-show="useDisplay.Sender_variant !== 'default'" class="prefix-self-wrap">
@ -58,14 +58,19 @@ import Model from './model/index.vue'
import { Sender } from 'vue-element-plus-x' import { Sender } from 'vue-element-plus-x'
import { useDisplayStore, useParamStore } from '@/stores' import { useDisplayStore, useParamStore } from '@/stores'
import { generateSubImage } from '@/utils/websocket' import { generateSubImage } from '@/utils/websocket'
import { useRouter } from 'vue-router'
const props = defineProps({ const props = defineProps({
isGenerate: { isGenerate: {
type: Boolean, type: Boolean,
default: false default: false
},
generate: {
type: Boolean,
default: false
} }
}) })
console.log(props.isGenerate) const router = useRouter()
const useDisplay = useDisplayStore() const useDisplay = useDisplayStore()
const useParams = useParamStore() const useParams = useParamStore()
const uploadurl = import.meta.env.VITE_API_WORKFLOW_UPLOAD const uploadurl = import.meta.env.VITE_API_WORKFLOW_UPLOAD
@ -145,6 +150,9 @@ const Errors = (error) => {
} }
const generate = async () => { const generate = async () => {
if (!props.isGenerate) {
router.push({ name: 'home', query: { loading: false, Generate: true } })
}
if (!imageurl.value && !prompt.value) { if (!imageurl.value && !prompt.value) {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
ElMessage.error('请输入提示词') ElMessage.error('请输入提示词')
@ -177,6 +185,11 @@ watch(() => useParams.AIvideoImage, (newValue) => {
useParams.AIvideoImage = '' useParams.AIvideoImage = ''
} }
}) })
onMounted(() => {
if (props.generate) {
generate()
}
})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -1,5 +1,5 @@
const DisplayStoreSetup = () => { const DisplayStoreSetup = () => {
const Sender_variant = ref('default') const Sender_variant = ref('updown')
return { return {
Sender_variant Sender_variant
} }

View File

@ -1,11 +1,8 @@
import { import {
accountLogin as accountLoginApi, accountLogin as accountLoginApi,
checkUsertoken as checkUsertokenApi, checkUsertoken as checkUsertokenApi,
getCodePhone,
getUserInfo as getUserInfoApi, getUserInfo as getUserInfoApi,
logout as logoutApi, logout as logoutApi
phoneLogin as phoneLoginApi,
socialLogin as socialLoginApi
} from '@/apis/auth' } from '@/apis/auth'
import { clearToken, getToken, setToken } from '@/utils/auth' import { clearToken, getToken, setToken } from '@/utils/auth'

View File

@ -1,4 +1,3 @@
import workflows from '@/apis/workflows.json'
import { useParamStore } from '@/stores' import { useParamStore } from '@/stores'
export async function getFormattedTime(date = new Date()) { export async function getFormattedTime(date = new Date()) {

View File

@ -1,6 +1,5 @@
import { ElNotification } from 'element-plus' import { ElNotification } from 'element-plus'
import { h, ref } from 'vue' import { h, ref } from 'vue'
import { setTaskRootId } from '@/apis/createRoot'
import { useDisplayStore, useParamStore, useUserStore } from '@/stores' import { useDisplayStore, useParamStore, useUserStore } from '@/stores'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import { createTask, getFormattedTime, getTask } from '@/utils/createTask' import { createTask, getFormattedTime, getTask } from '@/utils/createTask'

View File

@ -0,0 +1,74 @@
<template>
<div v-if="visible" class="refresh-overlay">
<div class="refresh-content">
<div class="spinner"></div>
<span class="refresh-text">{{ text }}</span>
</div>
</div>
</template>
<script setup>
defineProps({
visible: {
type: Boolean,
default: false
},
text: {
type: String,
default: '加载中...'
}
})
</script>
<style lang="less" scoped>
.refresh-overlay {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.refresh-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.spinner {
width: 40px;
height: 40px;
border: 3px solid #e0e0e0;
border-top-color: #409eff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.refresh-text {
color: #606266;
font-size: 14px;
font-weight: 400;
}
</style>

View File

@ -75,7 +75,6 @@
<script setup> <script setup>
import brush from '@/assets/display/brush.svg' import brush from '@/assets/display/brush.svg'
import { setCollectImg } from '@/apis/collection'
import { useDisplayStore, useParamStore, useUserStore } from '@/stores' import { useDisplayStore, useParamStore, useUserStore } from '@/stores'
import { downloadImage } from '@/utils/downloadImage.js' import { downloadImage } from '@/utils/downloadImage.js'

View File

@ -1,11 +1,13 @@
<template> <template>
<div id="display" class="content-area"> <div id="display" class="content-area">
<RefreshOverlay :visible="refreshing" />
<div class="back"> <div class="back">
<img src="@/assets/display/back.svg" alt=""> <img src="@/assets/display/back.svg" alt="">
<span class="title-text">退出</span> <span class="title-text">退出</span>
</div> </div>
<div v-if="!props.if" class="btn-container"> <div v-if="props.if" class="btn-container">
<div class="btn" @click="activeTab = 'all'"> <div class="btn" @click="activeTab = 'all'">
<!-- <span class="btn-text">全部</span> --> <!-- <span class="btn-text">全部</span> -->
<img src="@/assets/display/arrow.svg" alt=""> <img src="@/assets/display/arrow.svg" alt="">
@ -23,7 +25,7 @@
</div> </div>
<DynamicScroller <DynamicScroller
v-if="!props.if" v-if="props.if"
:items="list" :items="list"
:min-item-size="54" :min-item-size="54"
class="scroller" class="scroller"
@ -45,20 +47,25 @@
</template> </template>
<script setup> <script setup>
import { getTaskListByRootId } from '@/apis/history'
import { useDisplayStore, useParamStore } from '@/stores' import { useDisplayStore, useParamStore } from '@/stores'
import Set from './components/set.vue' import Set from './components/set.vue'
import RefreshOverlay from './components/RefreshOverlay.vue'
const props = defineProps({ const props = defineProps({
if: { if: {
type: Boolean, type: Boolean,
default: false default: false
},
loading: {
type: Boolean,
default: false
} }
}) })
const useDisplay = useDisplayStore() const useDisplay = useDisplayStore()
const useParams = useParamStore() // const useParams = useParamStore() //
const refreshing = ref(false)
const activeTab = ref('all') const activeTab = ref('all')
// const tempList = ref([]) // const tempList = ref([])
const tempList = ref([ const tempList = ref([
@ -102,6 +109,34 @@ const conversion = (newlist) => {
return temp return temp
} }
//
const fetchHistoryVideos = async () => {
try {
const result = await getGenerateHistoryList({ userId: userStore.userInfo.id, chargeType: 1 })
total = result.data.length
if (total === 0) {
useDisplay.Sender_variant = 'updown'
router.push({ name: 'home' })
}
console.log(result.data)
historys.value = result.data.map((value) => ({
...value,
thumbnail: null
})).sort((a, b) => new Date(b.createTime) - new Date(a.createTime))
console.log(historys.value)
} catch (error) {
console.error('获取历史视频失败:', error)
// eslint-disable-next-line no-undef
ElMessage({
message: '获取历史视频失败,内测状态,请及时下载视频文件,暂不支持云端储存与历史记录',
type: 'warning'
})
} finally {
refreshing.value = false
}
}
// //
const getList = async () => { const getList = async () => {
// if (page.value === 0) return // if (page.value === 0) return
@ -135,62 +170,10 @@ watch(() => activeTab.value, (newValue, oldValue) => {
toggleDisplay(newValue, oldValue) toggleDisplay(newValue, oldValue)
}) })
//
watch(() => useParams.setRootTask, (newValue) => {
// console.log('setDisplayList', newValue)
console.log('setRootTask', newValue)
console.log(useParams.newTaskRootId, useParams.taskRootId)
if (useParams.newTaskRootId !== useParams.taskRootId) return
console.log('是否在生成', useDisplay.isRootGerenate)
if (useDisplay.isRootGerenate) {
tempList.value = [newValue]
console.log('初始化tempList', tempList.value)
if (activeTab.value !== 'all') {
activeTab.value = 'all'
return
}
list.value = [...tempList.value]
// Object.assign(list.value[0], newValue)
console.log('初始化list', list.value)
return
}
Object.assign(tempList.value[0], newValue)
if (activeTab.value === newValue.type || activeTab.value === 'all') Object.assign(list.value[0], newValue)
console.log('tempList更新', tempList.value)
console.log('list更新', list.value)
})
//
watch(() => useParams.setSubTask, (newValue) => {
// console.log('setDisplayList', newValue)
console.log('setSubTask', newValue)
console.log(useDisplay.taskRootId, useParams.taskRootId)
if (useDisplay.taskRootId !== useParams.taskRootId) return
if (useDisplay.isSubGerenate) {
tempList.value.unshift(newValue)
if (activeTab.value === newValue.type) list.value.unshift(newValue)
console.log('初始化子任务tempList', tempList.value)
console.log('初始化子任务list', list.value)
return
}
Object.assign(tempList.value[0], newValue)
if (activeTab.value === newValue.type) Object.assign(list.value[0], newValue)
console.log('tempList更新', tempList.value)
console.log('list更新', list.value)
})
// id
watch(() => useDisplay.taskRootId, async (newValue) => {
console.log('选择历史记录', newValue)
const newlist = await getTaskListByRootId({ taskRootId: newValue, page: 1, size: 15 })
const temp = conversion(newlist)
tempList.value = temp
list.value = tempList.value
page.value = 1
console.log('初始化list', list.value)
useParams.taskRootId = newValue
})
onMounted(() => { onMounted(() => {
console.log('display mounted') if (!props.loading) return
useDisplay.displayOnMounted = true refreshing.value = true
fetchHistoryVideos()
}) })
</script> </script>
@ -202,7 +185,6 @@ onMounted(() => {
overflow-y: auto; overflow-y: auto;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.back{ .back{
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -5,14 +5,15 @@ import display from './display/index.vue'
const route = useRoute() const route = useRoute()
const shouldShowDisplay = route.path === '/home' const shouldShowDisplay = route.path === '/home'
const loading = route.query.loading ? false : (route.path === '/home')
const Generate = route.query.Generate || false
</script> </script>
<template> <template>
<div class="app-container"> <div class="app-container">
<dialogBox :is-generate="shouldShowDisplay" /> <dialogBox :is-generate="shouldShowDisplay" :generate="Generate" />
<display :if="shouldShowDisplay" /> <display :if="shouldShowDisplay" :loading="loading" />
</div> </div>
</template> </template>