import md5 from '~/utils/md5' /** * 老照片修复 / 上色(混元生图 3.0) * * create 走 multipart 直传原图(和证件照一样,避免先传 CDN 再由后端回源下载一次), * 其余查询类接口用 useApi() 的普通 POST 即可。 */ export function useOldPhoto() { const tokenCookie = useCookie('token', { path: '/' }) const macCookie = useCookie('mac', { maxAge: 365 * 24 * 3600, path: '/' }) const openIdCookie = useCookie('open_id', { path: '/' }) const sourceCookie = useCookie('source', { path: '/' }) const { getClientId, getClientIos } = useClientDevice() const tokenState = useState('auth_token', () => tokenCookie.value || '') const openIdState = useState('auth_open_id', () => openIdCookie.value || '') if (import.meta.client && !macCookie.value) { macCookie.value = createUuid() } function createUuid() { if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID() return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => { const random = Math.floor(Math.random() * 16) const value = char === 'x' ? random : (random & 0x3) | 0x8 return value.toString(16) }) } function getNonce() { const timeStr = Date.now().toString() return { timeStr, nonce: md5(timeStr).substring(4, 14) } } /** * 提交修复任务 * @param {File} file 原图 * @param {{ mode: string, extra_prompt?: string, request_id?: string }} settings */ async function create(file, settings = {}) { if (!file) throw new Error('请选择一张照片') const token = tokenState.value || tokenCookie.value || '' const { timeStr, nonce } = getNonce() const formData = new FormData() // ThinkJS 2 会先读公共参数,普通字段必须排在文件字段之前 formData.append('token', token) formData.append('uid', openIdState.value || openIdCookie.value || '') formData.append('mac', macCookie.value || 'pc-old-photo') formData.append('base_timestamp', String(Math.floor(Date.now() / 1000))) formData.append('client', String(getClientId())) formData.append('source', sourceCookie.value || '') formData.append('client_ios', String(getClientIos())) formData.append('version', '1.0.0') formData.append('version_code', '1') formData.append('request_id', settings.request_id || createUuid()) formData.append('mode', settings.mode || 'colorize') if (settings.extra_prompt) formData.append('extra_prompt', settings.extra_prompt) formData.append('file', file) let result try { result = await $fetch('/api/oldphoto/create', { method: 'POST', headers: { token, timestr: timeStr, nonce }, body: formData, }) } catch (error) { const data = error?.data if (data && typeof data === 'object' && data.msg) { const normalized = new Error(data.msg) normalized.code = data.code || 1000 normalized.data = data.data || {} throw normalized } throw error } if (result.code === 1009) { const { logout, showLogin } = useUser() logout() showLogin.value = true } if (result.code !== 0) { const error = new Error(result.msg || '提交失败,请稍后重试') error.code = result.code || 1000 error.data = result.data || {} throw error } return result } return { create, createRequestId: createUuid, } }