topfans/frontend/composables/useLaserSegment.js
2026-07-29 16:03:33 +08:00

116 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 镭射卡人像抠图 — 网关 POST /api/v1/segmentimageseg / VIAPI
* 抠图失败即抛错,中断 thinking不做椭圆降级。
*/
import { segmentPortraitApi } from '@/utils/api.js'
import { readDraft, writeDraft } from '@/utils/draftStorage'
async function downloadToLocal(url) {
const target = String(url || '').trim()
if (!target) {
throw new Error('缺少抠图下载地址')
}
// H5OSS 跨域时 uni.downloadFile 易丢 PNG alpha改用 fetch + blob URL
// #ifdef H5
const response = await fetch(target)
if (!response.ok) {
throw new Error(`下载抠图失败 HTTP ${response.status}`)
}
const blob = await response.blob()
return URL.createObjectURL(blob)
// #endif
// #ifndef H5
return new Promise((resolve, reject) => {
uni.downloadFile({
url: target,
timeout: 120000,
success: (res) => {
if (res.statusCode === 200 && res.tempFilePath) {
resolve(res.tempFilePath)
return
}
reject(new Error(`下载抠图失败 HTTP ${res.statusCode}`))
},
fail: (e) => reject(new Error(e?.errMsg || '下载抠图失败')),
})
})
// #endif
}
/** 将抠图本地路径写入 castlove 表单,供 craftMintSubmit 上传 cutout 层 */
export function persistCutoutToForm(cutoutLocalPath, cutoutOssKey = '') {
try {
const raw = readDraft('castlove_form_data')
if (!raw) return
const form = typeof raw === 'string' ? JSON.parse(raw) : { ...raw }
form.cutoutImage = cutoutLocalPath
if (cutoutOssKey) {
form.cutout_oss_key = cutoutOssKey
}
const saved = writeDraft('castlove_form_data', JSON.stringify(form))
if (!saved) {
console.error('[useLaserSegment] persistCutoutToForm: 保存表单数据失败')
return
}
} catch (e) {
console.warn('[useLaserSegment] persistCutoutToForm failed:', e)
}
}
export function clearCutoutFromForm() {
try {
const raw = readDraft('castlove_form_data')
if (!raw) return
const form = typeof raw === 'string' ? JSON.parse(raw) : { ...raw }
delete form.cutoutImage
delete form.cutout_oss_key
const saved = writeDraft('castlove_form_data', JSON.stringify(form))
if (!saved) {
console.error('[useLaserSegment] clearCutoutFromForm: 保存表单数据失败')
return
}
} catch (e) {
/* noop */
}
}
/**
* 服务端人像抠图
* @param {string} imagePath 用户原图本地路径
* @returns {Promise<{ localPath: string, ossKey: string }>}
*/
export async function segmentPortrait(imagePath, options = {}) {
const path = String(imagePath || '').trim()
if (!path) {
throw new Error('缺少原图')
}
const res = await segmentPortraitApi(path, {
imageBase64: options.imageBase64 || '',
})
const data = res?.data
// 只要原图上传到 OSS 就算成功抠图失败不影响OpenAI 模式不需要抠图)
// 只有连原图都没上传成功才抛错
if (!data?.success && !data?.original_url_signed) {
throw new Error(data?.message || data?.error_code || 'LC_SEGMENT_FAILED')
}
// 抠图成功才下载存本地
let localPath = ''
if (data.cutout_url_signed) {
localPath = await downloadToLocal(data.cutout_url_signed)
persistCutoutToForm(localPath, data.cutout_oss_key || '')
}
return {
localPath,
ossKey: data.cutout_oss_key || '',
cutoutUrl: data.cutout_url_signed || '',
originalUrl: data.original_url_signed || '',
}
}