/** * 镭射卡人像抠图 — 网关 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 使用 } }