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:
王佑琳 2026-06-15 17:10:18 +08:00
parent 4d76899488
commit 7379488839
4 changed files with 108 additions and 60 deletions

View File

@ -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 = {

View File

@ -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
}
}

View File

@ -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 创建任务

View File

@ -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 },