AI_Painting_V2.0/src/components/dialogBox/model/painting.vue
WangLeo 239b32fb95 重构 Painting 模型参数架构:每模型独立配置、动态参数表单、移除 workflow 适配
- 新增 src/config/models/ 每模型独立参数 schema(8 个模型)
- 新增 src/components/dialogBox/params/ 动态参数控件
- 模型选择器改为从 API 获取并按 tag 分组
- dialogBox 参数区改为根据模型 config 动态渲染控件
- createTask.js Painting 直接返回扁平 modelParams,Video 保留旧 workflow
- 删除旧的 proportion/painting.vue 和 quantity 组件
- 更新 CLAUDE.md 架构文档
2026-06-03 19:00:49 +08:00

133 lines
3.4 KiB
Vue

<template>
<Select
v-model="model"
:grouped-options="modelGroups"
class="model-select"
position="top"
>
<template #prefix>
<img src="@/assets/dialog/model.svg" alt="" style="width: 16px;">
</template>
</Select>
</template>
<script setup>
import Select from '@/components/Select/index.vue'
import { fetchPlatformModels, getPlatformCode } from '@/utils/modelApi'
import { getModelConfig } from '@/config/models/index.js'
const props = defineProps({
modelValue: { type: String, default: 'Flux 2' },
typeValue: { type: String, default: 'text' },
})
const emit = defineEmits(['update:modelValue', 'update:typeValue'])
const platformModels = ref([])
// 从 API 加载模型列表并按 tag 分组
const loadModels = async () => {
try {
const code = getPlatformCode('Painting')
const models = await fetchPlatformModels(code)
platformModels.value = models || []
} catch (error) {
console.error('加载平台模型列表失败:', error)
}
}
loadModels()
// 模型列表加载后自动纠正不可用模型
watch(platformModels, (models) => {
if (models.length === 0) return
const currentModel = models.find(m => m.name === props.modelValue || m.id === props.modelValue)
if (!currentModel || currentModel.disabled) {
const firstEnabled = models.find(m => !m.disabled)
if (firstEnabled) {
emit('update:modelValue', firstEnabled.name)
const config = getModelConfig(firstEnabled.name)
emit('update:typeValue', config?.inputType || 'text')
}
}
}, { immediate: true })
// 按 tag 分组
const modelGroups = computed(() => {
const models = platformModels.value
if (models.length === 0) return []
const groups = {}
models.forEach(m => {
const tag = m.tag || '其他'
if (!groups[tag]) groups[tag] = []
groups[tag].push({
value: m.name,
label: m.name,
disabled: m.disabled || false,
})
})
return Object.entries(groups).map(([label, options]) => ({ label, options }))
})
const model = computed({
get: () => props.modelValue,
set: (value) => {
emit('update:modelValue', value)
const config = getModelConfig(value)
emit('update:typeValue', config?.inputType || 'text')
},
})
// 外部改变 modelValue 时校验是否可用
watch(() => props.modelValue, (newValue) => {
const models = platformModels.value
if (models.length === 0) return
const currentModel = models.find(m => m.name === newValue)
if (currentModel && currentModel.disabled) {
const firstEnabled = models.find(m => !m.disabled)
if (firstEnabled) {
emit('update:modelValue', firstEnabled.name)
const config = getModelConfig(firstEnabled.name)
emit('update:typeValue', config?.inputType || 'text')
}
}
})
</script>
<style lang="less" scoped>
.model-select {
:deep(.select-header) {
height: 40px;
padding: 0 15px;
border-radius: 10px;
border: 1px solid #E8E9EB;
background: #f5f6f7;
&:hover {
background: #e9eaeb;
}
}
:deep(.select-text) {
font-size: 14px;
}
:deep(.dropdown-menu) {
max-height: 510px;
overflow-y: auto;
}
:deep(.dropdown-item) {
min-width: 120px;
&.active {
background: rgba(0, 15, 51, 0.10);
color: #000F33;
font-weight: 600;
}
}
}
</style>