增加ai去特征

This commit is contained in:
2026-07-09 23:48:58 +08:00
parent 21cca6513b
commit 6d6bd2a638
9 changed files with 290 additions and 6 deletions
+29 -2
View File
@@ -28,6 +28,7 @@ const prompt = ref(draft.prompt || '')
const ratio = ref(draft.ratio || '')
const resolution = ref(draft.resolution || '')
const duration = ref(draft.duration || '')
const deai = ref(draft.deai || false)
watch(mode, (v) => { draft.mode = v })
watch(modelId, (v) => { draft.modelId = v })
@@ -35,6 +36,7 @@ watch(prompt, (v) => { draft.prompt = v })
watch(ratio, (v) => { draft.ratio = v })
watch(resolution, (v) => { draft.resolution = v })
watch(duration, (v) => { draft.duration = v })
watch(deai, (v) => { draft.deai = v })
const refImages = ref([]) // [{ name, dataUrl }]
const fileInput = ref(null)
@@ -136,6 +138,12 @@ function tierPrice(normalMap, agentMap, key) {
}
return Number(n)
}
// 去AI特征 per-tier surcharge (loaded from /deai-pricing; defaults 1/2/3 分).
const deaiPricing = ref({ price_1k: 1, price_2k: 2, price_4k: 3 })
const deaiSurcharge = computed(() => {
const key = { '1K': 'price_1k', '2K': 'price_2k', '4K': 'price_4k' }[resolution.value] || 'price_1k'
return Number(deaiPricing.value[key] ?? 0)
})
const price = computed(() => {
if (!model.value) return null
const m = model.value
@@ -145,7 +153,9 @@ const price = computed(() => {
if (rp == null || dp == null) return null
return rp + dp
}
return tierPrice(m.prices, m.prices_agent, resolution.value)
const base = tierPrice(m.prices, m.prices_agent, resolution.value)
if (base == null) return null
return base + (deai.value ? deaiSurcharge.value : 0)
})
const priceLabel = computed(() => price.value == null ? '—' : pointsLabel(price.value))
const canAfford = computed(() => price.value == null || credits.value >= price.value)
@@ -392,6 +402,7 @@ async function fireOne() {
ratio: ratio.value,
resolution: resolution.value,
duration: mode.value === 'video' ? duration.value : '',
deai: mode.value === 'image' ? deai.value : false,
status: 'pending',
url: '',
error: '',
@@ -414,6 +425,7 @@ async function fireOne() {
model: task.model, prompt: task.prompt, ratio: task.ratio, resolution: task.resolution,
}
if (task.kind === 'video') payload.duration = task.duration
if (task.kind === 'image' && task.deai) payload.deai = true
if (refsSnapshot.length) {
const refs = await Promise.all(refsSnapshot.map(refToBase64))
payload.reference_images = refs.filter(Boolean)
@@ -574,9 +586,10 @@ function onKey(e) { if (e.key === 'Escape') lightbox.value = null }
onMounted(async () => {
refreshMe() // pull the latest real balance
const [mm, pp] = await Promise.all([api('/managed-models'), api('/video-presets')])
const [mm, pp, dp] = await Promise.all([api('/managed-models'), api('/video-presets'), api('/deai-pricing')])
allModels.value = mm.data?.data || []
presets.value = pp.data?.data || []
if (dp.ok && dp.data) deaiPricing.value = dp.data
// Pre-fill from query string (?prompt=...&model=...) — used by the home
// page's example cards to seed the form in one click.
const qPrompt = String(route.query.prompt || '')
@@ -683,6 +696,20 @@ onUnmounted(() => {
</div>
</div>
<!-- 去AI特征 (image only): opt-in post-processing with a per-tier surcharge -->
<div v-if="mode === 'image'" class="flex items-center justify-between">
<label class="text-xs font-medium text-slate-500">
去AI特征
<span class="text-slate-400 font-normal">(+{{ deaiSurcharge }} 积分)</span>
</label>
<button type="button" role="switch" :aria-checked="deai" @click="deai = !deai"
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors"
:class="deai ? 'bg-slate-900' : 'bg-slate-200'">
<span class="inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform"
:class="deai ? 'translate-x-[18px]' : 'translate-x-0.5'"></span>
</button>
</div>
<div v-if="mode === 'video' && durations.length > 0">
<label class="block text-xs font-medium text-slate-500 mb-1.5">时长</label>
<div class="flex flex-wrap gap-1.5">