feat(channels): 拉模型改为勾选即绑定,启动清扫遗留模型

- fetch-models 返回 bound 标记,渠道页勾选=立即导入绑定,
  取消=解绑(无其他渠道接入时本地模型行一并删除)
- 新增 POST /channels/unbind-model
- 启动时 PurgeOrphanModels 清掉 provider 时代的无绑定模型行
- 模型管理页移除「渠道导入模型」按钮

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-10-16 21:35:30 +08:00
co-authored by Devin
parent b4efe6b192
commit abd7b5c23b
7 changed files with 146 additions and 68 deletions
+3 -5
View File
@@ -124,14 +124,11 @@ 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 / 别名…" />
</div>
<button @click="loadModels" class="btn-soft">
<Icon name="refresh" class="w-3.5 h-3.5" /> 刷新
</button>
<router-link to="/admin/channels" class="btn-primary inline-flex items-center gap-1">
<Icon name="plug" class="w-3.5 h-3.5" /> 渠道导入模型
</router-link>
</div>
<!-- Table -->
@@ -139,7 +136,8 @@ onMounted(loadModels)
<div v-if="loading && !models.length" class="text-center text-sm text-white/40 py-20">加载中…</div>
<div v-else-if="!filtered.length" class="flex flex-col items-center gap-3 text-white/40 py-20">
<span class="w-14 h-14 rounded-2xl bg-white/[0.04] grid place-items-center"><Icon name="models" class="w-6 h-6" /></span>
<span class="text-sm">{{ models.length ? '没有匹配的模型' : '还没有模型,先到「渠道管理」拉取上游模型导入' }}</span>
<span v-if="models.length" class="text-sm">没有匹配的模型</span>
<router-link v-else to="/admin/channels" class="text-sm text-sky-300 underline underline-offset-2">还没有模型,先到「渠道管理」勾选上游模型自动导入</router-link>
</div>
<table v-else class="w-full text-sm table-fixed">