100 lines
2.8 KiB
JavaScript
100 lines
2.8 KiB
JavaScript
/**
|
||
* 镭射卡人像抠图 — 网关 POST /api/v1/segment(imageseg / VIAPI)
|
||
* 抠图失败即抛错,中断 thinking,不做椭圆降级。
|
||
*/
|
||
|
||
import { segmentPortraitApi } from '@/utils/api.js'
|
||
import { CASTLOVE_FORM_KEY } from '@/utils/castloveGenerationFlow.js'
|
||
|
||
async function downloadToLocal(url) {
|
||
const target = String(url || '').trim()
|
||
if (!target) {
|
||
throw new Error('缺少抠图下载地址')
|
||
}
|
||
|
||
// H5:OSS 跨域时 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 = uni.getStorageSync(CASTLOVE_FORM_KEY)
|
||
if (!raw) return
|
||
const form = typeof raw === 'string' ? JSON.parse(raw) : { ...raw }
|
||
form.cutoutImage = cutoutLocalPath
|
||
if (cutoutOssKey) {
|
||
form.cutout_oss_key = cutoutOssKey
|
||
}
|
||
uni.setStorageSync(CASTLOVE_FORM_KEY, JSON.stringify(form))
|
||
} catch (e) {
|
||
console.warn('[useLaserSegment] persistCutoutToForm failed:', e)
|
||
}
|
||
}
|
||
|
||
export function clearCutoutFromForm() {
|
||
try {
|
||
const raw = uni.getStorageSync(CASTLOVE_FORM_KEY)
|
||
if (!raw) return
|
||
const form = typeof raw === 'string' ? JSON.parse(raw) : { ...raw }
|
||
delete form.cutoutImage
|
||
delete form.cutout_oss_key
|
||
uni.setStorageSync(CASTLOVE_FORM_KEY, JSON.stringify(form))
|
||
} 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
|
||
if (!data?.success || !data?.cutout_url_signed) {
|
||
const msg = data?.message || data?.error_code || 'LC_SEGMENT_FAILED'
|
||
throw new Error(msg)
|
||
}
|
||
|
||
const 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 || '', // OSS 签名的抠图 PNG 地址,供 Dify 使用
|
||
}
|
||
}
|