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 lines
3.2 KiB

  1. import md5 from '~/utils/md5'
  2. export function useIdPhoto() {
  3. const tokenCookie = useCookie('token', { path: '/' })
  4. const macCookie = useCookie('mac', { maxAge: 365 * 24 * 3600, path: '/' })
  5. const openIdCookie = useCookie('open_id', { path: '/' })
  6. const sourceCookie = useCookie('source', { path: '/' })
  7. const { getClientId, getClientIos } = useClientDevice()
  8. const tokenState = useState('auth_token', () => tokenCookie.value || '')
  9. const openIdState = useState('auth_open_id', () => openIdCookie.value || '')
  10. if (import.meta.client && !macCookie.value) {
  11. macCookie.value = createUuid()
  12. }
  13. function createUuid() {
  14. if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID()
  15. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
  16. const random = Math.floor(Math.random() * 16)
  17. const value = char === 'x' ? random : (random & 0x3) | 0x8
  18. return value.toString(16)
  19. })
  20. }
  21. function getNonce() {
  22. const timeStr = Date.now().toString()
  23. return {
  24. timeStr,
  25. nonce: md5(timeStr).substring(4, 14),
  26. }
  27. }
  28. async function create(file, settings) {
  29. if (!file) throw new Error('请选择一张照片')
  30. const token = tokenState.value || tokenCookie.value || ''
  31. const { timeStr, nonce } = getNonce()
  32. const formData = new FormData()
  33. // ThinkJS 2 会先读取公共参数,必须将普通字段放在文件字段之前。
  34. formData.append('token', token)
  35. formData.append('uid', openIdState.value || openIdCookie.value || '')
  36. formData.append('mac', macCookie.value || 'pc-id-photo')
  37. formData.append('base_timestamp', String(Math.floor(Date.now() / 1000)))
  38. formData.append('client', String(getClientId()))
  39. formData.append('source', sourceCookie.value || '')
  40. formData.append('client_ios', String(getClientIos()))
  41. formData.append('version', '1.0.0')
  42. formData.append('version_code', '1')
  43. formData.append('request_id', settings.request_id || createUuid())
  44. formData.append('spec_key', settings.spec_key)
  45. formData.append('background', settings.background)
  46. formData.append('beauty', settings.beauty)
  47. formData.append('scale', String(settings.scale))
  48. formData.append('offset_x', String(settings.offset_x))
  49. formData.append('offset_y', String(settings.offset_y))
  50. formData.append('file', file)
  51. let result
  52. try {
  53. result = await $fetch('/api/idphoto/create', {
  54. method: 'POST',
  55. headers: {
  56. token,
  57. timestr: timeStr,
  58. nonce,
  59. },
  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. }