增加模型别名

This commit is contained in:
2026-07-04 14:49:52 +08:00
parent 641a021f7a
commit 03f9744dcb
16 changed files with 298 additions and 145 deletions
+9 -6
View File
@@ -19,8 +19,11 @@ onMounted(async () => {
const imageModels = computed(() => models.value.filter((m) => m.type === 'image'))
const videoModels = computed(() => models.value.filter((m) => m.type === 'video'))
const sampleImage = computed(() => imageModels.value[0]?.id || 'firefly-image-4')
const sampleVideo = computed(() => videoModels.value[0]?.id || 'firefly-kling3')
function pubName(m) {
return m?.alias || m?.id || ''
}
const sampleImage = computed(() => pubName(imageModels.value[0]) || 'firefly-image-4')
const sampleVideo = computed(() => pubName(videoModels.value[0]) || 'firefly-kling3')
const sampleSeconds = computed(() => String(videoModels.value[0]?.durations?.[0] || '8s').replace(/s$/, ''))
function priceOf(m) {
@@ -41,18 +44,18 @@ function priceOf(m) {
// ---- request parameter tables ----
const imageParams = [
['model', 'string', '必填', '模型 id,见上表(图像)'],
['model', 'string', '必填', '模型名(别名优先),见上表(图像)'],
['prompt', 'string', '必填', '文字描述'],
['size', 'string', '可选', '宽x高,如 "1024x1024"。同时决定「比例」+「分辨率档」(按长边)。具体怎么填见下方对照表;留空 = 1:1 · 2K'],
]
const editParams = [
['image', 'file', '必填', '输入图;多张参考图重复 image[] 字段(multipart 文件上传)'],
['prompt', 'string', '必填', '编辑/参考描述'],
['model', 'string', '必填', '模型 id(需支持图生图)'],
['model', 'string', '必填', '模型名(别名优先,需支持图生图)'],
['size', 'string', '可选', '同图像:决定比例 + 分辨率档(见下方对照表)'],
]
const videoParams = [
['model', 'string', '必填', '模型 id,见上表(视频)'],
['model', 'string', '必填', '模型名(别名优先),见上表(视频)'],
['prompt', 'string', '必填', '文字描述'],
['seconds', 'string|int', '必填', '时长秒数,如 "5" "8"(取决于模型支持)'],
['size', 'string', '可选', '如 "1280x720" / "720x1280" → 决定比例与分辨率'],
@@ -273,7 +276,7 @@ async function copy(text) {
</thead>
<tbody>
<tr v-for="m in models" :key="m.id" class="border-b border-white/[0.04] last:border-0">
<td class="px-4 py-3 font-mono text-white/90">{{ m.id }}</td>
<td class="px-4 py-3 font-mono text-white/90">{{ pubName(m) }}</td>
<td class="px-4 py-3 text-white/60">{{ m.type === 'video' ? '视频' : '图像' }}</td>
<td class="px-4 py-3 text-white/60">{{ (m.type === 'video' ? m.durations : m.resolutions || [])?.join(' · ') || '—' }}</td>
<td class="px-4 py-3 text-right tabular-nums text-white/80">{{ priceOf(m) }}</td>
+6 -3
View File
@@ -66,7 +66,7 @@ const filtered = computed(() => {
if (kindFilter.value && m.type !== kindFilter.value) return false
if (statusFilter.value === 'enabled' && m.enabled === false) return false
if (statusFilter.value === 'disabled' && m.enabled !== false) return false
if (q && !(m.id.toLowerCase().includes(q) || (m.provider || '').toLowerCase().includes(q))) return false
if (q && !(m.id.toLowerCase().includes(q) || (m.alias || '').toLowerCase().includes(q) || (m.provider || '').toLowerCase().includes(q))) return false
return true
})
})
@@ -114,7 +114,7 @@ onMounted(loadModels)
</button>
</div>
<div class="flex-1 min-w-[200px]">
<input v-model="search" class="field !py-1.5 text-xs" placeholder="搜索 模型 ID / Provider…" />
<input v-model="search" class="field !py-1.5 text-xs" placeholder="搜索 模型 ID / 别名 / Provider…" />
</div>
<button @click="loadModels" class="btn-soft">
<Icon name="refresh" class="w-3.5 h-3.5" /> 刷新
@@ -163,7 +163,10 @@ onMounted(loadModels)
class="border-b border-white/[0.04] hover:bg-white/[0.03] transition-colors">
<!-- Model id + provider underneath -->
<td class="px-5 py-3.5 align-middle min-w-0">
<div class="font-mono text-xs text-white/90 truncate" :title="m.id">{{ m.id }}</div>
<div class="flex items-start gap-2 min-w-0">
<div class="font-mono text-xs text-white/90 truncate" :title="m.id">{{ m.id }}</div>
<span v-if="m.alias" class="inline-flex items-center rounded-full px-2 py-0.5 text-[10px] bg-sky-500/10 text-sky-300 ring-1 ring-sky-400/20 shrink-0">别名: {{ m.alias }}</span>
</div>
<div class="mt-1 text-[10px] text-white/45 capitalize truncate">{{ m.provider || '—' }}</div>
</td>
+2 -2
View File
@@ -69,7 +69,7 @@ const models = computed(() =>
allModels.value.filter((m) => m.enabled !== false && m.type === mode.value),
)
const modelOptions = computed(() =>
models.value.map((m) => ({ value: m.id, label: m.name || m.id })),
models.value.map((m) => ({ value: m.id, label: m.alias || m.name || m.id })),
)
const model = computed(() => allModels.value.find((m) => m.id === modelId.value) || null)
const familyPreset = computed(() => {
@@ -305,7 +305,7 @@ async function fireOne() {
// user edits the form (or fires another batch) while this one runs.
const task = {
id: Math.random().toString(36).slice(2, 10),
model: modelId.value,
model: model.value?.alias || modelId.value,
kind: mode.value,
prompt: prompt.value,
ratio: ratio.value,