fix: 修复按钮状态恢复、Music 任务内容显示与比例标签为空,新增 platform_code 参数
- taskPolling: isSubGerenate=true 提前至 modelId 校验前,确保错误时按钮恢复;请求体新增 platform_code - dialogBox: generateData 集成平台 getGenerateDataExtras 扩展字段 - Music 平台: 新增 getGenerateDataExtras() 输出 pureMusic/mode,供列表展示和再生成使用 - set.vue: 硬编码比例标签改为 secondTagText 计算属性,Music 显示纯音乐/有歌词,Painting/Video 从 modelParams 提取比例
This commit is contained in:
parent
4d76899488
commit
7379488839
@ -157,7 +157,8 @@ const handleStart = async () => {
|
||||
modelType: p.modelType.value,
|
||||
prompt: prompt.value,
|
||||
referenceImages: referenceImages.value,
|
||||
modelParams: body
|
||||
modelParams: body,
|
||||
...(p.getGenerateDataExtras?.() || {})
|
||||
}
|
||||
|
||||
const data = {
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
import { markRaw, reactive, ref, computed } from 'vue'
|
||||
import { registerPlatform } from '@/platforms/registry.js'
|
||||
import { fetchPlatformModels, getPlatformCode, getModelConfig, getModelId, preloadModelConfigs } from '@/utils/modelApi'
|
||||
import { syncParamValues, checkShowWhen } from '@/utils/modelConfigHelper.js'
|
||||
import ModelSelector from './modelSelector.vue'
|
||||
import ImageUploader from './imageUploader.vue'
|
||||
import ModeSelector from './controls/modeSelector.vue'
|
||||
import PureMusicGroup from './controls/pureMusicGroup.vue'
|
||||
import LyricsInput from './controls/lyricsInput.vue'
|
||||
import TimeControl from './controls/timeControl.vue'
|
||||
import { computed, markRaw, reactive, ref } from 'vue'
|
||||
import ParamGroup from '@/components/ParamGroup/index.vue'
|
||||
import Select from '@/components/Select/index.vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { registerPlatform } from '@/platforms/registry.js'
|
||||
import { fetchPlatformModels, getModelConfig, getModelId, getPlatformCode, preloadModelConfigs } from '@/utils/modelApi'
|
||||
import { checkShowWhen } from '@/utils/modelConfigHelper.js'
|
||||
import LyricsInput from './controls/lyricsInput.vue'
|
||||
import ModeSelector from './controls/modeSelector.vue'
|
||||
import PureMusicGroup from './controls/pureMusicGroup.vue'
|
||||
import TimeControl from './controls/timeControl.vue'
|
||||
import ImageUploader from './imageUploader.vue'
|
||||
import ModelSelector from './modelSelector.vue'
|
||||
|
||||
// 由专用控件处理的 ui 类型
|
||||
const handledUis = ['textarea', 'proportion', 'imageUpload', 'hidden', 'quantity']
|
||||
@ -37,11 +36,11 @@ export function defineMusicPlatform() {
|
||||
async function loadModels() {
|
||||
models.value = await fetchPlatformModels(code.value)
|
||||
if (!model.value && models.value.length) {
|
||||
const first = models.value.find(m => !m.disabled)
|
||||
const first = models.value.find((m) => !m.disabled)
|
||||
if (first) model.value = first.id
|
||||
}
|
||||
if (models.value.length) {
|
||||
const ids = models.value.map(m => m.id)
|
||||
const ids = models.value.map((m) => m.id)
|
||||
preloadModelConfigs(ids)
|
||||
}
|
||||
}
|
||||
@ -65,22 +64,22 @@ export function defineMusicPlatform() {
|
||||
})
|
||||
|
||||
// 同步专用 ref
|
||||
const modeParam = config.params.find(p => p.name === 'mode' || p.ui === 'mode')
|
||||
const modeParam = config.params.find((p) => p.name === 'mode' || p.ui === 'mode')
|
||||
if (modeParam) mode.value = modeParam.default || '常用模式'
|
||||
|
||||
const qtyParam = config.params.find(p => p.ui === 'quantity')
|
||||
const qtyParam = config.params.find((p) => p.ui === 'quantity')
|
||||
if (qtyParam) quantity.value = qtyParam.default || 1
|
||||
|
||||
const durParam = config.params.find(p => p.name === 'duration')
|
||||
const durParam = config.params.find((p) => p.name === 'duration')
|
||||
if (durParam) duration.value = durParam.default || 'Auto'
|
||||
|
||||
const lyricsParam = config.params.find(p => p.name === 'lyrics')
|
||||
const lyricsParam = config.params.find((p) => p.name === 'lyrics')
|
||||
if (lyricsParam) lyrics.value = lyricsParam.default || ''
|
||||
|
||||
const seedParam = config.params.find(p => p.name === 'randomSeed' || p.name === 'seed')
|
||||
const seedParam = config.params.find((p) => p.name === 'randomSeed' || p.name === 'seed')
|
||||
if (seedParam) randomSeed.value = seedParam.default || ''
|
||||
|
||||
const pmParam = config.params.find(p => p.name === 'pureMusic')
|
||||
const pmParam = config.params.find((p) => p.name === 'pureMusic')
|
||||
if (pmParam) pureMusic.value = pmParam.default !== undefined ? pmParam.default : true
|
||||
|
||||
if (config.promptPlaceholder) {
|
||||
@ -93,7 +92,7 @@ export function defineMusicPlatform() {
|
||||
function imageUploadLimit() {
|
||||
if (!modelConfig.value) return 0
|
||||
return modelConfig.value.params
|
||||
.filter(p => p.ui === 'imageUpload')
|
||||
.filter((p) => p.ui === 'imageUpload')
|
||||
.reduce((sum, p) => sum + (p.maxCount || 1), 0)
|
||||
}
|
||||
|
||||
@ -118,12 +117,12 @@ export function defineMusicPlatform() {
|
||||
function buildTaskBody({ prompt, referenceImages }) {
|
||||
syncMusicParamValues()
|
||||
// 将 prompt 写入 paramValues(如果 config 中有 prompt 参数)
|
||||
const promptParam = modelConfig.value?.params?.find(p => p.ui === 'textarea')
|
||||
const promptParam = modelConfig.value?.params?.find((p) => p.ui === 'textarea')
|
||||
if (promptParam) paramValues[promptParam.name] = prompt
|
||||
|
||||
// 将参考音频映射到 imageUpload 参数
|
||||
if (modelConfig.value) {
|
||||
const imageUploadParams = modelConfig.value.params.filter(p => p.ui === 'imageUpload')
|
||||
const imageUploadParams = modelConfig.value.params.filter((p) => p.ui === 'imageUpload')
|
||||
imageUploadParams.forEach((p, i) => {
|
||||
if (referenceAudio.value[i]) {
|
||||
paramValues[p.name] = referenceAudio.value[i].url
|
||||
@ -133,26 +132,34 @@ export function defineMusicPlatform() {
|
||||
return { ...paramValues }
|
||||
}
|
||||
|
||||
// 附加平台专属字段到 generateData,用于任务列表展示和再次生成/重新编辑
|
||||
function getGenerateDataExtras() {
|
||||
return {
|
||||
pureMusic: pureMusic.value,
|
||||
mode: mode.value
|
||||
}
|
||||
}
|
||||
|
||||
function syncMusicParamValues() {
|
||||
if (!modelConfig.value) return
|
||||
const config = modelConfig.value
|
||||
|
||||
const qtyParam = config.params.find(p => p.ui === 'quantity')
|
||||
const qtyParam = config.params.find((p) => p.ui === 'quantity')
|
||||
if (qtyParam) paramValues[qtyParam.name] = quantity.value
|
||||
|
||||
const durParam = config.params.find(p => p.name === 'duration')
|
||||
const durParam = config.params.find((p) => p.name === 'duration')
|
||||
if (durParam) paramValues[durParam.name] = duration.value
|
||||
|
||||
const lyricsParam = config.params.find(p => p.name === 'lyrics')
|
||||
const lyricsParam = config.params.find((p) => p.name === 'lyrics')
|
||||
if (lyricsParam) paramValues[lyricsParam.name] = lyrics.value
|
||||
|
||||
const seedParam = config.params.find(p => p.name === 'randomSeed' || p.name === 'seed')
|
||||
const seedParam = config.params.find((p) => p.name === 'randomSeed' || p.name === 'seed')
|
||||
if (seedParam) paramValues[seedParam.name] = randomSeed.value
|
||||
|
||||
const pmParam = config.params.find(p => p.name === 'pureMusic')
|
||||
const pmParam = config.params.find((p) => p.name === 'pureMusic')
|
||||
if (pmParam) paramValues[pmParam.name] = pureMusic.value
|
||||
|
||||
const modeParam = config.params.find(p => p.name === 'mode' || p.ui === 'mode')
|
||||
const modeParam = config.params.find((p) => p.name === 'mode' || p.ui === 'mode')
|
||||
if (modeParam) paramValues[modeParam.name] = mode.value
|
||||
}
|
||||
|
||||
@ -171,13 +178,13 @@ export function defineMusicPlatform() {
|
||||
name: 'modeSelector',
|
||||
component: markRaw(ModeSelector),
|
||||
beforeModel: true,
|
||||
show: (config) => !!config?.params?.find(p => p.name === 'mode' || p.ui === 'mode'),
|
||||
show: (config) => !!config?.params?.find((p) => p.name === 'mode' || p.ui === 'mode'),
|
||||
props: (config) => {
|
||||
const modeParam = config?.params?.find(p => p.name === 'mode' || p.ui === 'mode')
|
||||
const modeParam = config?.params?.find((p) => p.name === 'mode' || p.ui === 'mode')
|
||||
return {
|
||||
modelValue: mode.value,
|
||||
'modelValue': mode.value,
|
||||
'onUpdate:modelValue': (v) => { mode.value = v },
|
||||
options: modeParam?.options || []
|
||||
'options': modeParam?.options || []
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -185,11 +192,11 @@ export function defineMusicPlatform() {
|
||||
name: 'pureMusicGroup',
|
||||
component: markRaw(PureMusicGroup),
|
||||
beforeModel: false,
|
||||
show: (config) => mode.value === '常用模式' && !!config?.params?.find(p => p.name === 'pureMusic'),
|
||||
show: (config) => mode.value === '常用模式' && !!config?.params?.find((p) => p.name === 'pureMusic'),
|
||||
props: (config) => ({
|
||||
modelValue: pureMusic.value,
|
||||
'modelValue': pureMusic.value,
|
||||
'onUpdate:modelValue': (v) => { pureMusic.value = v },
|
||||
lyrics: lyrics.value,
|
||||
'lyrics': lyrics.value,
|
||||
'onUpdate:lyrics': (v) => { lyrics.value = v }
|
||||
})
|
||||
},
|
||||
@ -197,9 +204,9 @@ export function defineMusicPlatform() {
|
||||
name: 'lyricsInput',
|
||||
component: markRaw(LyricsInput),
|
||||
beforeModel: false,
|
||||
show: (config) => mode.value === '专业模式' && !!config?.params?.find(p => p.name === 'lyrics'),
|
||||
show: (config) => mode.value === '专业模式' && !!config?.params?.find((p) => p.name === 'lyrics'),
|
||||
props: (config) => ({
|
||||
modelValue: lyrics.value,
|
||||
'modelValue': lyrics.value,
|
||||
'onUpdate:modelValue': (v) => { lyrics.value = v }
|
||||
})
|
||||
},
|
||||
@ -207,14 +214,14 @@ export function defineMusicPlatform() {
|
||||
name: 'timeControl',
|
||||
component: markRaw(TimeControl),
|
||||
beforeModel: false,
|
||||
show: (config) => mode.value === '常用模式' && !!config?.params?.find(p => p.name === 'duration'),
|
||||
show: (config) => mode.value === '常用模式' && !!config?.params?.find((p) => p.name === 'duration'),
|
||||
props: (config) => {
|
||||
const durParam = config?.params?.find(p => p.name === 'duration')
|
||||
const durParam = config?.params?.find((p) => p.name === 'duration')
|
||||
return {
|
||||
modelValue: duration.value,
|
||||
'modelValue': duration.value,
|
||||
'onUpdate:modelValue': (v) => { duration.value = v },
|
||||
min: durParam?.min || 10,
|
||||
max: durParam?.max || 240
|
||||
'min': durParam?.min || 10,
|
||||
'max': durParam?.max || 240
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -222,15 +229,15 @@ export function defineMusicPlatform() {
|
||||
name: 'quantity',
|
||||
component: markRaw(Select),
|
||||
beforeModel: false,
|
||||
show: (config) => !!config?.params?.find(p => p.ui === 'quantity'),
|
||||
show: (config) => !!config?.params?.find((p) => p.ui === 'quantity'),
|
||||
props: (config) => {
|
||||
const qtyParam = config?.params?.find(p => p.ui === 'quantity')
|
||||
const qtyParam = config?.params?.find((p) => p.ui === 'quantity')
|
||||
const maxQty = Math.max(...(qtyParam?.options || [1]))
|
||||
const limited = mode.value === '专业模式' ? 1 : maxQty
|
||||
return {
|
||||
modelValue: quantity.value,
|
||||
'modelValue': quantity.value,
|
||||
'onUpdate:modelValue': (v) => { quantity.value = v },
|
||||
options: Array.from({ length: limited }, (_, i) => ({ value: i + 1, label: `${i + 1}条` }))
|
||||
'options': Array.from({ length: limited }, (_, i) => ({ value: i + 1, label: `${i + 1}条` }))
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -263,15 +270,36 @@ export function defineMusicPlatform() {
|
||||
controls,
|
||||
ImageUploader: markRaw(ImageUploader),
|
||||
state: {
|
||||
model, modelType, mode, modelConfig, paramValues,
|
||||
promptPlaceholder, referenceAudio, models,
|
||||
quantity, duration, lyrics, randomSeed, pureMusic
|
||||
model,
|
||||
modelType,
|
||||
mode,
|
||||
modelConfig,
|
||||
paramValues,
|
||||
promptPlaceholder,
|
||||
referenceAudio,
|
||||
models,
|
||||
quantity,
|
||||
duration,
|
||||
lyrics,
|
||||
randomSeed,
|
||||
pureMusic
|
||||
},
|
||||
model, modelType, mode, modelConfig, promptPlaceholder,
|
||||
loadModels, loadConfig, getDefaultModel,
|
||||
imageUploadLimit, validateBeforeSubmit,
|
||||
getUploaderBindings, showImageUploader, isImageRequired,
|
||||
buildTaskBody, fillFromResult
|
||||
model,
|
||||
modelType,
|
||||
mode,
|
||||
modelConfig,
|
||||
promptPlaceholder,
|
||||
loadModels,
|
||||
loadConfig,
|
||||
getDefaultModel,
|
||||
imageUploadLimit,
|
||||
validateBeforeSubmit,
|
||||
getUploaderBindings,
|
||||
showImageUploader,
|
||||
isImageRequired,
|
||||
buildTaskBody,
|
||||
fillFromResult,
|
||||
getGenerateDataExtras
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { ElNotification } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import { requestCreateTask, requestTaskStatus } from '@/apis/display'
|
||||
import { useDisplayStore, useUserStore } from '@/stores'
|
||||
import { getPlatformCode } from '@/utils/modelApi'
|
||||
import { userError } from '@/utils/tokenError'
|
||||
|
||||
export function getChargeType(chargeType) {
|
||||
@ -67,17 +68,18 @@ export async function generate(data, generateData) {
|
||||
let taskId = null
|
||||
let pollInterval = null
|
||||
|
||||
useDisplay.isSubGerenate = true
|
||||
|
||||
if (!data.modelId) {
|
||||
ElNotification({
|
||||
title: '生成失败',
|
||||
message: h('i', { style: 'color: teal' }, '未找到模型ID,请联系管理员配置'),
|
||||
type: 'error'
|
||||
})
|
||||
useDisplay.isSubGerenate = false
|
||||
return
|
||||
}
|
||||
|
||||
useDisplay.isSubGerenate = true
|
||||
|
||||
// 从登录态获取 sessionId
|
||||
const sessionId = useUserStore().userInfo.sessionId
|
||||
if (!sessionId) {
|
||||
@ -97,7 +99,8 @@ export async function generate(data, generateData) {
|
||||
const requestBody = {
|
||||
model_id: data.modelId,
|
||||
body,
|
||||
request: data.request
|
||||
request: data.request,
|
||||
platform_code: getPlatformCode(data.type)
|
||||
}
|
||||
|
||||
// POST 创建任务
|
||||
|
||||
@ -10,13 +10,13 @@
|
||||
</span>
|
||||
<div :style="{ visibility: !isHovering && !showExternalGenerateData ? 'visible' : 'hidden' }" class="generate-data internal">
|
||||
<div class="detailed-data first-detailed-data">{{ props.item.generateData.model }}</div>
|
||||
<div class="detailed-data">{{ props.item.generateData.proportion }}</div>
|
||||
<div class="detailed-data">{{ secondTagText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="!isHovering && showExternalGenerateData" class="generate-data external">
|
||||
<div class="detailed-data first-detailed-data">{{ props.item.generateData.model }}</div>
|
||||
<div class="detailed-data">{{ props.item.generateData.proportion }}</div>
|
||||
<div class="detailed-data">{{ secondTagText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -212,6 +212,22 @@ const generateStatusText = computed(() => {
|
||||
return ''
|
||||
})
|
||||
|
||||
// 根据平台类型动态生成第二个标签文本
|
||||
const secondTagText = computed(() => {
|
||||
const gd = props.item.generateData
|
||||
if (props.item.type === 'Music') {
|
||||
if (gd.pureMusic === true) return '纯音乐'
|
||||
if (gd.pureMusic === false) return '有歌词'
|
||||
return ''
|
||||
}
|
||||
// Painting/Video:尝试从 modelParams 中提取比例信息
|
||||
const params = gd.modelParams || {}
|
||||
const key = Object.keys(params).find((k) =>
|
||||
['aspectRatio', 'ratio', 'proportion'].includes(k)
|
||||
)
|
||||
return key ? params[key] : ''
|
||||
})
|
||||
|
||||
const AIbrush = (file, index) => {
|
||||
emit('open-canvas', {
|
||||
mainImage: { url: file, index: index + 1 },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user