diff --git a/src/platforms/painting/index.js b/src/platforms/painting/index.js index d68341c..4c908a3 100644 --- a/src/platforms/painting/index.js +++ b/src/platforms/painting/index.js @@ -1,23 +1,13 @@ -import { ref, reactive, markRaw } from 'vue' -import { fetchPlatformModels, getPlatformCode } from '@/utils/modelApi' -import { getModelConfig } from './models/index.js' -import PaintingModelSelector from './modelSelector.vue' -import PaintingProportion from './controls/proportion.vue' +import { markRaw, reactive, ref } from 'vue' +import { fetchPlatformModels, getModelConfig, getModelId, getPlatformCode, preloadModelConfigs } from '@/utils/modelApi' +import { syncDefaults as _syncDefaults, syncParamValues as _syncParamValues, checkShowWhen, getDimConfig } from '@/utils/modelConfigHelper.js' +import { registerPlatform } from '../registry.js' import DimensionInput from './controls/dimension.vue' +import PaintingProportion from './controls/proportion.vue' import QualitySelect from './controls/quality.vue' import Quantity from './controls/quantity.vue' import ImageUploader from './imageUploader.vue' -import { registerPlatform } from '../registry.js' - -function getDimConfig(config) { - if (!config) return null - const dimParam = config.params.find(p => p.ui === 'dimension') - if (dimParam) return { type: 'combined', config: dimParam.dimension, paramName: dimParam.name } - const wParam = config.params.find(p => p.ui === 'dimensionWidth') - const hParam = config.params.find(p => p.ui === 'dimensionHeight') - if (wParam && hParam) return { type: 'split', wParam, hParam } - return null -} +import PaintingModelSelector from './modelSelector.vue' export function definePaintingPlatform() { const model = ref('Flux 2') @@ -35,142 +25,118 @@ export function definePaintingPlatform() { const paramValues = reactive({}) const state = { - model, modelType, - proportion, resolution, - customWidth, customHight, - dimWidth, dimHeight, - quantity, quality, - paramValues, modelConfig, + model, + modelType, + proportion, + resolution, + customWidth, + customHight, + dimWidth, + dimHeight, + quantity, + quality, + paramValues, + modelConfig + } + + // state 对象供 helper 函数使用 + const paintingState = { + modelConfig, + paramValues, + proportion, + resolution, + quantity, + quality, + customWidth, + customHight, + dimWidth, + dimHeight, + promptPlaceholder } function syncDefaults(config) { - modelConfig.value = config - if (!config) return - config.params.forEach(p => { - if (!(p.name in paramValues)) { - paramValues[p.name] = p.default ?? (p.name === 'outputFormat' ? 'png' : '') - } - }) - const ratioParam = config.params.find(p => p.ui === 'proportion') - if (ratioParam) proportion.value = ratioParam.default || '1:1' - const resParam = config.params.find(p => p.ui === 'resolution') - if (resParam) resolution.value = resParam.default || '2k' - const qtyParam = config.params.find(p => p.ui === 'quantity') - if (qtyParam) quantity.value = qtyParam.default || 1 - const cwParam = config.params.find(p => p.name === 'customWidth') - if (cwParam) customWidth.value = cwParam.default || 1024 - const chParam = config.params.find(p => p.name === 'customHight') - if (chParam) customHight.value = chParam.default || 1024 - const qualityParam = config.params.find(p => p.name === 'quality') - if (qualityParam) quality.value = qualityParam.default || 'medium' - const dc = getDimConfig(config) - if (dc?.type === 'split') { - dimWidth.value = dc.wParam.default || 1024 - dimHeight.value = dc.hParam.default || 1024 - } else if (dc?.type === 'combined') { - const dimParam = config.params.find(p => p.name === dc.paramName) - const raw = dimParam?.default || '' - const parsed = dc.config.parse(raw) - dimWidth.value = parsed.width - dimHeight.value = parsed.height - } + _syncDefaults(config, paintingState) } function syncParamValues() { - const ratioParam = modelConfig.value?.params?.find(p => p.ui === 'proportion') - if (ratioParam) paramValues[ratioParam.name] = proportion.value - const resParam = modelConfig.value?.params?.find(p => p.ui === 'resolution') - if (resParam) paramValues[resParam.name] = resolution.value - const qtyParam = modelConfig.value?.params?.find(p => p.ui === 'quantity') - if (qtyParam) paramValues[qtyParam.name] = quantity.value - if (modelConfig.value?.params?.find(p => p.name === 'customWidth')) { - paramValues.customWidth = customWidth.value - } - if (modelConfig.value?.params?.find(p => p.name === 'customHight')) { - paramValues.customHight = customHight.value - } - if (modelConfig.value?.params?.find(p => p.name === 'quality')) { - paramValues.quality = quality.value - } - const dc = getDimConfig(modelConfig.value) - if (dc?.type === 'split') { - paramValues[dc.wParam.name] = dimWidth.value - paramValues[dc.hParam.name] = dimHeight.value - } else if (dc?.type === 'combined') { - paramValues[dc.paramName] = dc.config.format(dimWidth.value, dimHeight.value) - } + _syncParamValues(modelConfig.value, paintingState) } const controls = [ { name: 'proportion', component: markRaw(PaintingProportion), - show: (config) => !!config?.params?.find(p => p.ui === 'proportion'), + show: (config) => !!config?.params?.find((p) => p.ui === 'proportion'), props: (config) => { - const ratioParam = config?.params?.find(p => p.ui === 'proportion') - const resParam = config?.params?.find(p => p.ui === 'resolution') + const ratioParam = config?.params?.find((p) => p.ui === 'proportion') + const resParam = config?.params?.find((p) => p.ui === 'resolution') return { - modelValue: proportion.value, + 'modelValue': proportion.value, 'onUpdate:modelValue': (v) => { proportion.value = v }, - resolution: resolution.value, + 'resolution': resolution.value, 'onUpdate:resolution': (v) => { resolution.value = v }, - width: customWidth.value, + 'width': customWidth.value, 'onUpdate:width': (v) => { customWidth.value = v }, - height: customHight.value, + 'height': customHight.value, 'onUpdate:height': (v) => { customHight.value = v }, - proportionOptions: ratioParam?.options - ?.filter(o => o !== 'custom') - .map(o => ({ value: o, label: o })) || [], - resolutionOptions: resParam?.options - ?.map(o => ({ value: o, label: o.toUpperCase() })) || [], - allowCustom: ratioParam?.options?.includes('custom') || false, + 'proportionOptions': ratioParam?.options + ?.filter((o) => o !== 'custom') + .map((o) => ({ value: o, label: o })) || [], + 'resolutionOptions': resParam?.options + ?.map((o) => ({ value: o, label: o.toUpperCase() })) || [], + 'allowCustom': ratioParam?.options?.includes('custom') || false } - }, + } }, { name: 'dimension', component: markRaw(DimensionInput), - show: (config) => !!config?.params?.find(p => p.ui === 'dimension' || p.ui === 'dimensionWidth'), + show: (config) => { + const hasDim = config?.params?.find((p) => + (p.ui === 'dimension' || p.ui === 'dimensionWidth') && checkShowWhen(p, paramValues) + ) + return !!hasDim + }, props: (config) => { const dc = getDimConfig(config) return { - width: dimWidth.value, + 'width': dimWidth.value, 'onUpdate:width': (v) => { dimWidth.value = v }, - height: dimHeight.value, + 'height': dimHeight.value, 'onUpdate:height': (v) => { dimHeight.value = v }, - minW: dc?.config?.width?.min || dc?.wParam?.min || 256, - maxW: dc?.config?.width?.max || dc?.wParam?.max || 6197, - minH: dc?.config?.height?.min || dc?.hParam?.min || 256, - maxH: dc?.config?.height?.max || dc?.hParam?.max || 4096, + 'minW': dc?.config?.width?.min || dc?.wParam?.min || 256, + 'maxW': dc?.config?.width?.max || dc?.wParam?.max || 6197, + 'minH': dc?.config?.height?.min || dc?.hParam?.min || 256, + 'maxH': dc?.config?.height?.max || dc?.hParam?.max || 4096 } - }, + } }, { name: 'quality', component: markRaw(QualitySelect), - show: (config) => !!config?.params?.find(p => p.name === 'quality'), + show: (config) => !!config?.params?.find((p) => p.name === 'quality'), props: (config) => { - const q = config?.params?.find(p => p.name === 'quality') + const q = config?.params?.find((p) => p.name === 'quality') return { - modelValue: quality.value, + 'modelValue': quality.value, 'onUpdate:modelValue': (v) => { quality.value = v }, - options: q?.options?.map(o => ({ value: o, label: o })) || [], + 'options': q?.options?.map((o) => ({ value: o, label: o })) || [] } - }, + } }, { name: 'quantity', component: markRaw(Quantity), - 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') return { - modelValue: quantity.value, + 'modelValue': quantity.value, 'onUpdate:modelValue': (v) => { quantity.value = v }, - max: qtyParam?.options?.length ? Math.max(...qtyParam.options) : 4, + 'max': qtyParam?.options?.length ? Math.max(...qtyParam.options) : 4 } - }, - }, + } + } ] const platform = { @@ -188,11 +154,18 @@ export function definePaintingPlatform() { async loadModels() { const code = getPlatformCode('Painting') - return fetchPlatformModels(code) + const models = await fetchPlatformModels(code) + if (models?.length) { + const modelIds = models.map((m) => m.id) + await preloadModelConfigs(modelIds) + } + return models }, async loadConfig(modelName, _modelType) { - const config = getModelConfig(modelName) + const modelId = await getModelId('Painting', modelName) + if (!modelId) return null + const config = await getModelConfig(modelId) syncDefaults(config) return config }, @@ -216,12 +189,12 @@ export function definePaintingPlatform() { imageUploadLimit() { if (!modelConfig.value) return 4 - const imageParam = modelConfig.value.params.find(p => p.ui === 'imageUpload') + const imageParam = modelConfig.value.params.find((p) => p.ui === 'imageUpload') return imageParam?.maxCount || modelConfig.value.maxImages || 4 }, isImageRequired() { - return !!(modelConfig.value?.params?.find(p => p.ui === 'imageUpload')) + return !!(modelConfig.value?.params?.find((p) => p.ui === 'imageUpload')) }, buildTaskBody(shared) { @@ -252,7 +225,7 @@ export function definePaintingPlatform() { } } if (paramValues.quality !== undefined) quality.value = paramValues.quality - }, + } } return platform