You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

100 rivejä
3.4 KiB

  1. import md5 from '~/utils/md5'
  2. /**
  3. * 老照片修复 / 上色(混元生图 3.0)
  4. *
  5. * create 走 multipart 直传原图(和证件照一样,避免先传 CDN 再由后端回源下载一次),
  6. * 其余查询类接口用 useApi() 的普通 POST 即可。
  7. */
  8. export function useOldPhoto() {
  9. const tokenCookie = useCookie('token', { path: '/' })
  10. const macCookie = useCookie('mac', { maxAge: 365 * 24 * 3600, path: '/' })
  11. const openIdCookie = useCookie('open_id', { path: '/' })
  12. const sourceCookie = useCookie('source', { path: '/' })
  13. const { getClientId, getClientIos } = useClientDevice()
  14. const tokenState = useState('auth_token', () => tokenCookie.value || '')
  15. const openIdState = useState('auth_open_id', () => openIdCookie.value || '')
  16. if (import.meta.client && !macCookie.value) {
  17. macCookie.value = createUuid()
  18. }
  19. function createUuid() {
  20. if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID()
  21. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
  22. const random = Math.floor(Math.random() * 16)
  23. const value = char === 'x' ? random : (random & 0x3) | 0x8
  24. return value.toString(16)
  25. })
  26. }
  27. function getNonce() {
  28. const timeStr = Date.now().toString()
  29. return { timeStr, nonce: md5(timeStr).substring(4, 14) }
  30. }
  31. /**
  32. * 提交修复任务
  33. * @param {File} file 原图
  34. * @param {{ mode: string, extra_prompt?: string, request_id?: string }} settings
  35. */
  36. async function create(file, settings = {}) {
  37. if (!file) throw new Error('请选择一张照片')
  38. const token = tokenState.value || tokenCookie.value || ''
  39. const { timeStr, nonce } = getNonce()
  40. const formData = new FormData()
  41. // ThinkJS 2 会先读公共参数,普通字段必须排在文件字段之前
  42. formData.append('token', token)
  43. formData.append('uid', openIdState.value || openIdCookie.value || '')
  44. formData.append('mac', macCookie.value || 'pc-old-photo')
  45. formData.append('base_timestamp', String(Math.floor(Date.now() / 1000)))
  46. formData.append('client', String(getClientId()))
  47. formData.append('source', sourceCookie.value || '')
  48. formData.append('client_ios', String(getClientIos()))
  49. formData.append('version', '1.0.0')
  50. formData.append('version_code', '1')
  51. formData.append('request_id', settings.request_id || createUuid())
  52. formData.append('mode', settings.mode || 'colorize')
  53. if (settings.extra_prompt) formData.append('extra_prompt', settings.extra_prompt)
  54. formData.append('file', file)
  55. let result
  56. try {
  57. result = await $fetch('/api/oldphoto/create', {
  58. method: 'POST',
  59. headers: { token, timestr: timeStr, nonce },
  60. body: formData,
  61. })
  62. } catch (error) {
  63. const data = error?.data
  64. if (data && typeof data === 'object' && data.msg) {
  65. const normalized = new Error(data.msg)
  66. normalized.code = data.code || 1000
  67. normalized.data = data.data || {}
  68. throw normalized
  69. }
  70. throw error
  71. }
  72. if (result.code === 1009) {
  73. const { logout, showLogin } = useUser()
  74. logout()
  75. showLogin.value = true
  76. }
  77. if (result.code !== 0) {
  78. const error = new Error(result.msg || '提交失败,请稍后重试')
  79. error.code = result.code || 1000
  80. error.data = result.data || {}
  81. throw error
  82. }
  83. return result
  84. }
  85. return {
  86. create,
  87. createRequestId: createUuid,
  88. }
  89. }