api.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import Taro from '@tarojs/taro'
  2. import { hc } from 'hono/client'
  3. import type { AuthRoutes, UserRoutes, RoleRoutes, FileRoutes } from '@/server/api'
  4. // API配置
  5. const API_BASE_URL = process.env.TARO_APP_API_BASE_URL || 'http://localhost:3000'
  6. const API_VERSION = process.env.TARO_APP_API_VERSION || 'v1'
  7. // 完整的API地址
  8. const BASE_URL = `${API_BASE_URL}/api/${API_VERSION}`
  9. // 创建自定义fetch函数,适配Taro.request
  10. const taroFetch: typeof fetch = async (input, init) => {
  11. const url = typeof input === 'string' ? input : input.url
  12. const method = init?.method || 'GET'
  13. // 构建Taro请求选项
  14. const options: Taro.request.Option = {
  15. url,
  16. method: method as any,
  17. data: init?.body,
  18. header: {
  19. 'Content-Type': 'application/json',
  20. ...Object.fromEntries(new Headers(init?.headers || {}))
  21. }
  22. }
  23. // 添加token
  24. const token = Taro.getStorageSync('token')
  25. if (token) {
  26. options.header = {
  27. ...options.header,
  28. 'Authorization': `Bearer ${token}`
  29. }
  30. }
  31. try {
  32. const response = await Taro.request(options)
  33. // 处理401未授权
  34. if (response.statusCode === 401) {
  35. Taro.removeStorageSync('token')
  36. Taro.removeStorageSync('userInfo')
  37. Taro.navigateTo({ url: '/pages/login/index' })
  38. throw new Error('请重新登录')
  39. }
  40. // 适配fetch响应格式
  41. return {
  42. ok: response.statusCode >= 200 && response.statusCode < 300,
  43. status: response.statusCode,
  44. statusText: response.errMsg || 'OK',
  45. headers: new Headers(response.header || {}),
  46. url: response.data?.url || url,
  47. json: async () => response.data,
  48. text: async () => JSON.stringify(response.data),
  49. blob: async () => new Blob([JSON.stringify(response.data)]),
  50. arrayBuffer: async () => new TextEncoder().encode(JSON.stringify(response.data)),
  51. clone: () => ({}) as Response,
  52. body: null as any,
  53. bodyUsed: true
  54. } as Response
  55. } catch (error) {
  56. console.error('API Error:', error)
  57. Taro.showToast({
  58. title: error.message || '网络错误',
  59. icon: 'none'
  60. })
  61. throw error
  62. }
  63. }
  64. // 创建Hono RPC客户端
  65. const createRpcClient = <T>(basePath: string) => {
  66. return hc<T>(`${BASE_URL}${basePath}`, {
  67. fetch: taroFetch
  68. })
  69. }
  70. // 创建各个模块的RPC客户端
  71. export const authClient = createRpcClient<AuthRoutes>('/auth')
  72. export const userClient = createRpcClient<UserRoutes>('/users')
  73. export const roleClient = createRpcClient<RoleRoutes>('/roles')
  74. export const fileClient = createRpcClient<FileRoutes>('/files')
  75. // 类型定义
  76. export type {
  77. AuthRoutes,
  78. UserRoutes,
  79. RoleRoutes,
  80. FileRoutes
  81. }
  82. // 默认导出RPC客户端
  83. export default {
  84. auth: authClient,
  85. users: userClient,
  86. roles: roleClient,
  87. files: fileClient,
  88. }