create-bubbles 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/index.js +4 -3
  2. package/package.json +1 -1
  3. package/template-taro-vue-eslint/.editorconfig +12 -0
  4. package/template-taro-vue-eslint/.env +3 -0
  5. package/template-taro-vue-eslint/.env.development +5 -0
  6. package/template-taro-vue-eslint/.env.production +5 -0
  7. package/template-taro-vue-eslint/.vscode/settings.json +57 -0
  8. package/template-taro-vue-eslint/babel.config.js +12 -0
  9. package/template-taro-vue-eslint/commitlint.config.mjs +1 -0
  10. package/template-taro-vue-eslint/config/dev.ts +27 -0
  11. package/template-taro-vue-eslint/config/index.ts +129 -0
  12. package/template-taro-vue-eslint/config/output-root.ts +11 -0
  13. package/template-taro-vue-eslint/config/prod.ts +39 -0
  14. package/template-taro-vue-eslint/config/release.ts +113 -0
  15. package/template-taro-vue-eslint/eslint.config.mjs +22 -0
  16. package/template-taro-vue-eslint/lefthook.yaml +13 -0
  17. package/template-taro-vue-eslint/package.json +115 -0
  18. package/template-taro-vue-eslint/patches/@tarojs__plugin-mini-ci.patch +13 -0
  19. package/template-taro-vue-eslint/pnpm-workspace.yaml +2 -0
  20. package/template-taro-vue-eslint/project.config.json +16 -0
  21. package/template-taro-vue-eslint/src/api/common/upload.ts +53 -0
  22. package/template-taro-vue-eslint/src/app.config.ts +19 -0
  23. package/template-taro-vue-eslint/src/app.ts +14 -0
  24. package/template-taro-vue-eslint/src/assets/image/.gitkeep +0 -0
  25. package/template-taro-vue-eslint/src/index.html +17 -0
  26. package/template-taro-vue-eslint/src/pages/example/upload/index.config.ts +3 -0
  27. package/template-taro-vue-eslint/src/pages/example/upload/index.module.scss +4 -0
  28. package/template-taro-vue-eslint/src/pages/example/upload/index.vue +71 -0
  29. package/template-taro-vue-eslint/src/pages/index/index.config.ts +3 -0
  30. package/template-taro-vue-eslint/src/pages/index/index.module.scss +4 -0
  31. package/template-taro-vue-eslint/src/pages/index/index.vue +71 -0
  32. package/template-taro-vue-eslint/src/store/index.ts +10 -0
  33. package/template-taro-vue-eslint/src/store/modules/user.ts +15 -0
  34. package/template-taro-vue-eslint/src/store/taroStorage.ts +7 -0
  35. package/template-taro-vue-eslint/src/styles/index.css +1 -0
  36. package/template-taro-vue-eslint/src/styles/nut-theme.css +4 -0
  37. package/template-taro-vue-eslint/src/utils/env.ts +13 -0
  38. package/template-taro-vue-eslint/src/utils/index.ts +40 -0
  39. package/template-taro-vue-eslint/src/utils/request/core/index.ts +193 -0
  40. package/template-taro-vue-eslint/src/utils/request/core/utils.ts +30 -0
  41. package/template-taro-vue-eslint/src/utils/request/index.ts +73 -0
  42. package/template-taro-vue-eslint/tsconfig.json +30 -0
  43. package/template-taro-vue-eslint/types/components.d.ts +12 -0
  44. package/template-taro-vue-eslint/types/global.d.ts +31 -0
  45. package/template-taro-vue-eslint/types/vue.d.ts +10 -0
  46. package/template-taro-vue-eslint/unocss.config.ts +38 -0
@@ -0,0 +1,53 @@
1
+ import { isH5, uploadApiAffix } from '@/utils/env'
2
+ import { alovaUploadRequest } from '@/utils/request'
3
+
4
+ interface UploadBaseParams {
5
+ fileMd5: string
6
+ fileSize: number
7
+ filename: string
8
+ companyId: string
9
+ projectId: string
10
+ indexDbId: number
11
+ }
12
+
13
+ export interface H5UploadParams extends UploadBaseParams {
14
+ file: Blob
15
+ }
16
+
17
+ export interface MpUploadParams extends UploadBaseParams {
18
+ filePath: string
19
+ }
20
+
21
+ export type UploadParams = H5UploadParams | MpUploadParams
22
+
23
+ export function uploadFile(data: any) {
24
+ if (isH5) {
25
+ // H5 端用 fetch 发送 FormData,绕过 Taro 适配器的序列化问题
26
+ return fetch(`/${uploadApiAffix}/files/uploadFileAppend`, {
27
+ method: 'POST',
28
+ body: data,
29
+ // headers: {
30
+ // 'Content-Type': 'multipart/form-data',
31
+ // authorization: 'Bearer 9a2d60a8-d9a6-40a3-9b13-4288225d855d',
32
+ // },
33
+ }).then(res => res.json())
34
+ }
35
+ else {
36
+ // 小程序端:用 Taro uploadFile 适配器
37
+ const { filePath, fileMd5, fileSize, filename, companyId, projectId, indexDbId } = data
38
+ return alovaUploadRequest.Post(`/files/uploadFileAppend`, {
39
+ name: 'file',
40
+ filePath,
41
+ fileMd5,
42
+ fileSize,
43
+ filename,
44
+ companyId,
45
+ projectId,
46
+ indexDbId,
47
+ }, {
48
+ requestType: 'upload',
49
+ fileName: filename,
50
+ meta: { isWrapped: false },
51
+ })
52
+ }
53
+ }
@@ -0,0 +1,19 @@
1
+ export default defineAppConfig({
2
+ pages: [
3
+ 'pages/index/index',
4
+ ],
5
+ subPackages: [
6
+ {
7
+ root: 'pages/example',
8
+ pages: [
9
+ 'upload/index',
10
+ ],
11
+ },
12
+ ],
13
+ window: {
14
+ backgroundTextStyle: 'light',
15
+ navigationBarBackgroundColor: '#fff',
16
+ navigationBarTitleText: 'WeChat',
17
+ navigationBarTextStyle: 'black',
18
+ },
19
+ })
@@ -0,0 +1,14 @@
1
+ import { createApp } from 'vue'
2
+
3
+ import { setupStore } from './store'
4
+ import '@nutui/touch-emulator'
5
+ import 'uno.css'
6
+ import '@/styles/index.css'
7
+
8
+ const App = createApp({
9
+ onShow(_options) {},
10
+ })
11
+
12
+ setupStore(App)
13
+
14
+ export default App
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
5
+ <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="apple-touch-fullscreen" content="yes">
8
+ <meta name="format-detection" content="telephone=no,address=no">
9
+ <meta name="apple-mobile-web-app-status-bar-style" content="white">
10
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
11
+ <title>myApp</title>
12
+ <script><%= htmlWebpackPlugin.options.script %></script>
13
+ </head>
14
+ <body>
15
+ <div id="app"></div>
16
+ </body>
17
+ </html>
@@ -0,0 +1,3 @@
1
+ export default definePageConfig({
2
+ navigationBarTitleText: '首页',
3
+ })
@@ -0,0 +1,4 @@
1
+ .red {
2
+ color: #fff;
3
+ background-color: red;
4
+ }
@@ -0,0 +1,71 @@
1
+ <script lang="ts" setup>
2
+ import Taro from '@tarojs/taro'
3
+ import { uploadFile } from '@/api/common/upload'
4
+ import { canvasToFile, file2Md5 } from '@/utils'
5
+ import { isH5 } from '@/utils/env'
6
+
7
+ async function handleConfirm(canvas: any, data: string) {
8
+ if (isH5) {
9
+ const file = await canvasToFile(canvas)
10
+ const fileMd5 = await file2Md5(file)
11
+ const data = new FormData()
12
+ data.append('file', file)
13
+ data.append('companyId', 'c35bd5e0d5834eccb1cfbf4dd538eb61')
14
+ data.append('projectId', 'eb42a2b7e680a4124e78951ccf7f1268')
15
+ data.append('indexDbId', '0')
16
+ data.append('fileMd5', fileMd5)
17
+ data.append('fileSize', `${file.size}`)
18
+ data.append('filename', file.name)
19
+ try {
20
+ const res = await uploadFile(data)
21
+ if (res.code === 200) {
22
+ // console.log('💦res.data', res.data)
23
+ }
24
+ else {
25
+ Taro.showToast({
26
+ title: res.message,
27
+ })
28
+ }
29
+ }
30
+ catch {
31
+ Taro.showToast({
32
+ title: '服务异常',
33
+ })
34
+ }
35
+ }
36
+ else {
37
+ // 小程序端:用 Taro uploadFile 适配器
38
+ Taro.getFileSystemManager().getFileInfo({
39
+ filePath: data,
40
+ success: async (res) => {
41
+ const params = {
42
+ filePath: data,
43
+ companyId: 'c35bd5e0d5834eccb1cfbf4dd538eb61',
44
+ projectId: 'eb42a2b7e680a4124e78951ccf7f1268',
45
+ indexDbId: '0',
46
+ fileMd5: res.digest,
47
+ fileSize: res.size,
48
+ filename: `${res.digest}.png`,
49
+ }
50
+ const uploadResStr = await uploadFile(params)
51
+ const uploadRes = JSON.parse(uploadResStr)
52
+ if (uploadRes.code === 200) {
53
+ // console.log('💦uploadRes.data', uploadRes.data)
54
+ }
55
+ else {
56
+ Taro.showToast({
57
+ title: uploadRes.message,
58
+ })
59
+ }
60
+ },
61
+ })
62
+ }
63
+ }
64
+ </script>
65
+
66
+ <template>
67
+ <div class="text-red">
68
+ 1112
69
+ <nut-signature @confirm="handleConfirm" />
70
+ </div>
71
+ </template>
@@ -0,0 +1,3 @@
1
+ export default definePageConfig({
2
+ navigationBarTitleText: '首页'
3
+ })
@@ -0,0 +1,4 @@
1
+ .red {
2
+ color: #fff;
3
+ background-color: red;
4
+ }
@@ -0,0 +1,71 @@
1
+ <script lang="ts" setup>
2
+ import Taro from '@tarojs/taro'
3
+ import { uploadFile } from '@/api/common/upload'
4
+ import { canvasToFile, file2Md5 } from '@/utils'
5
+ import { isH5 } from '@/utils/env'
6
+
7
+ async function handleConfirm(canvas: any, data: string) {
8
+ if (isH5) {
9
+ const file = await canvasToFile(canvas)
10
+ const fileMd5 = await file2Md5(file)
11
+ const data = new FormData()
12
+ data.append('file', file)
13
+ data.append('companyId', 'c35bd5e0d5834eccb1cfbf4dd538eb61')
14
+ data.append('projectId', 'eb42a2b7e680a4124e78951ccf7f1268')
15
+ data.append('indexDbId', '0')
16
+ data.append('fileMd5', fileMd5)
17
+ data.append('fileSize', `${file.size}`)
18
+ data.append('filename', file.name)
19
+ try {
20
+ const res = await uploadFile(data)
21
+ if (res.code === 200) {
22
+ // console.log('💦res.data', res.data)
23
+ }
24
+ else {
25
+ Taro.showToast({
26
+ title: res.message,
27
+ })
28
+ }
29
+ }
30
+ catch {
31
+ Taro.showToast({
32
+ title: '服务异常',
33
+ })
34
+ }
35
+ }
36
+ else {
37
+ // 小程序端:用 Taro uploadFile 适配器
38
+ Taro.getFileSystemManager().getFileInfo({
39
+ filePath: data,
40
+ success: async (res) => {
41
+ const params = {
42
+ filePath: data,
43
+ companyId: 'c35bd5e0d5834eccb1cfbf4dd538eb61',
44
+ projectId: 'eb42a2b7e680a4124e78951ccf7f1268',
45
+ indexDbId: '0',
46
+ fileMd5: res.digest,
47
+ fileSize: res.size,
48
+ filename: `${res.digest}.png`,
49
+ }
50
+ const uploadResStr = await uploadFile(params)
51
+ const uploadRes = JSON.parse(uploadResStr)
52
+ if (uploadRes.code === 200) {
53
+ // console.log('💦uploadRes.data', uploadRes.data)
54
+ }
55
+ else {
56
+ Taro.showToast({
57
+ title: uploadRes.message,
58
+ })
59
+ }
60
+ },
61
+ })
62
+ }
63
+ }
64
+ </script>
65
+
66
+ <template>
67
+ <div class="text-red">
68
+ 1112
69
+ <nut-signature @confirm="handleConfirm" />
70
+ </div>
71
+ </template>
@@ -0,0 +1,10 @@
1
+ import type { App } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
4
+
5
+ export const store = createPinia()
6
+ store.use(piniaPluginPersistedstate)
7
+
8
+ export function setupStore(app: App) {
9
+ app.use(store)
10
+ }
@@ -0,0 +1,15 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
+ import { TaroStorage } from '../taroStorage'
4
+
5
+ export const useUserStore = defineStore('user', () => {
6
+ const user = ref('1')
7
+
8
+ return {
9
+ user,
10
+ }
11
+ }, {
12
+ persist: {
13
+ storage: TaroStorage,
14
+ },
15
+ })
@@ -0,0 +1,7 @@
1
+ import Taro from '@tarojs/taro'
2
+
3
+ export const TaroStorage = {
4
+ getItem: (name: string) => Taro.getStorageSync(name),
5
+ setItem: (name: string, value: string) => Taro.setStorageSync(name, value),
6
+ removeItem: (name: string) => Taro.removeStorageSync(name),
7
+ }
@@ -0,0 +1 @@
1
+ @import './nut-theme.css';
@@ -0,0 +1,4 @@
1
+ :root,
2
+ page {
3
+ --nut-primary-color: #1677ff;
4
+ }
@@ -0,0 +1,13 @@
1
+ const apiUrl = process.env.TARO_APP_API_URL
2
+ const apiAffix = process.env.TARO_APP_API_AFFIX
3
+ const uploadApiAffix = process.env.TARO_APP_UPLOAD_API_AFFIX
4
+ const weappId = process.env.TARO_APP_ID
5
+ const isH5 = process.env.TARO_ENV === 'h5'
6
+
7
+ export {
8
+ apiAffix,
9
+ apiUrl,
10
+ isH5,
11
+ uploadApiAffix,
12
+ weappId,
13
+ }
@@ -0,0 +1,40 @@
1
+ import Taro from '@tarojs/taro'
2
+ import SparkMD5 from 'spark-md5'
3
+
4
+ /**
5
+ * H5 端:canvas 元素转 File
6
+ */
7
+ export function canvasToFile(canvas, filename = 'image.png', mimeType = 'image/png', quality = 1): Promise<File> {
8
+ return new Promise((resolve) => {
9
+ canvas.toBlob((blob) => {
10
+ const file = new File([blob], filename, { type: mimeType })
11
+ resolve(file)
12
+ }, mimeType, quality)
13
+ })
14
+ }
15
+
16
+ /**
17
+ * 获取本地文件信息(小程序端)
18
+ */
19
+ export function getFileInfo(filePath: string): Promise<Taro.getFileInfo.SuccessCallbackResult> {
20
+ return new Promise((resolve, reject) => {
21
+ Taro.getFileInfo({
22
+ filePath,
23
+ success: resolve,
24
+ fail: reject,
25
+ })
26
+ })
27
+ }
28
+
29
+ export function file2Md5(file): Promise<string> {
30
+ return new Promise((resolve, reject) => {
31
+ const reader = new FileReader()
32
+ reader.onload = (e: ProgressEvent<FileReader>) => {
33
+ const spark = new SparkMD5.ArrayBuffer()
34
+ spark.append(e.target?.result)
35
+ resolve(spark.end())
36
+ }
37
+ reader.onerror = reject
38
+ reader.readAsArrayBuffer(file)
39
+ })
40
+ }
@@ -0,0 +1,193 @@
1
+ import type { TaroConfig } from '@alova/adapter-taro'
2
+ import type Taro from '@tarojs/taro'
3
+ import type {
4
+ AlovaGlobalCacheAdapter,
5
+ AlovaOptions,
6
+ AlovaRequestAdapter,
7
+ GlobalCacheConfig,
8
+ StatesExport,
9
+ StatesHook,
10
+ } from 'alova'
11
+ import type { FetchRequestInit } from 'alova/fetch'
12
+ import { createAlova } from 'alova'
13
+ import adapterFetch from 'alova/fetch'
14
+ import { deepMergeObject, isReadableStream } from './utils'
15
+
16
+ // ---- Taro 适配器的响应类型 ----
17
+ type TaroResponse
18
+ = | Taro.request.SuccessCallbackResult<any>
19
+ | Taro.uploadFile.SuccessCallbackResult
20
+ | Taro.downloadFile.FileSuccessCallbackResult
21
+
22
+ type TaroResponseHeader = Taro.request.SuccessCallbackResult<any>['header']
23
+
24
+ // ---- 支持的适配器联合类型 ----
25
+ type SupportedRequestConfig = TaroConfig | FetchRequestInit
26
+ type SupportedResponse = TaroResponse | Response
27
+ type SupportedResponseHeader = TaroResponseHeader | Headers
28
+
29
+ interface StatusMap {
30
+ success?: number
31
+ unAuthorized?: number
32
+ }
33
+
34
+ interface CodeMap {
35
+ success?: number[]
36
+ unAuthorized?: number[]
37
+ }
38
+
39
+ export interface BaseRequestOption<
40
+ RC extends SupportedRequestConfig = SupportedRequestConfig,
41
+ RE extends SupportedResponse = SupportedResponse,
42
+ RH extends SupportedResponseHeader = SupportedResponseHeader,
43
+ SE extends StatesExport<any> = StatesExport<any>,
44
+ > {
45
+ baseUrl?: string
46
+ timeout?: number
47
+ commonHeaders?: Record<string, string | (() => string)>
48
+ statusMap?: StatusMap
49
+ isWrapped?: boolean
50
+ cacheFor?: GlobalCacheConfig<any>
51
+ cacheLogger?: boolean
52
+ codeMap?: CodeMap
53
+ responseDataKey?: string
54
+ responseMessageKey?: string
55
+ isTransformResponse?: boolean
56
+ isShowSuccessMessage?: boolean
57
+ successDefaultMessage?: string
58
+ isShowErrorMessage?: boolean
59
+ errorDefaultMessage?: string
60
+ statesHook?: StatesHook<SE>
61
+ successMessageFunc?: (message: string) => void
62
+ errorMessageFunc?: (message: string) => void
63
+ unAuthorizedResponseFunc?: () => void
64
+ requestAdapter?: AlovaRequestAdapter<RC, RE, RH>
65
+ storageAdapter?: AlovaGlobalCacheAdapter
66
+ }
67
+
68
+ /** method.meta 中可按请求覆盖的字段 */
69
+ export interface RequestMeta {
70
+ isTransformResponse?: boolean
71
+ isShowSuccessMessage?: boolean
72
+ isShowErrorMessage?: boolean
73
+ }
74
+
75
+ function getMetaFlag(meta: Record<string, any> | undefined, key: string, fallback: boolean): boolean {
76
+ if (meta && typeof meta[key] === 'boolean')
77
+ return meta[key]
78
+ return fallback
79
+ }
80
+
81
+ export function createInstance<
82
+ RC extends SupportedRequestConfig = SupportedRequestConfig,
83
+ RE extends SupportedResponse = SupportedResponse,
84
+ RH extends SupportedResponseHeader = SupportedResponseHeader,
85
+ SE extends StatesExport<any> = StatesExport<any>,
86
+ >(option: BaseRequestOption<RC, RE, RH, SE>) {
87
+ const defaultOption: BaseRequestOption = {
88
+ baseUrl: '/',
89
+ timeout: 0,
90
+ statusMap: { success: 200, unAuthorized: 401 },
91
+ isWrapped: true,
92
+ cacheFor: null,
93
+ cacheLogger: true,
94
+ codeMap: { success: [200], unAuthorized: [401] },
95
+ responseDataKey: 'data',
96
+ responseMessageKey: 'message',
97
+ isTransformResponse: true,
98
+ isShowSuccessMessage: false,
99
+ successDefaultMessage: '操作成功',
100
+ isShowErrorMessage: true,
101
+ errorDefaultMessage: '服务异常',
102
+ requestAdapter: adapterFetch() as AlovaRequestAdapter<any, any, any>,
103
+ }
104
+
105
+ const config = deepMergeObject(defaultOption, option) as Required<
106
+ Pick<BaseRequestOption, 'statusMap' | 'codeMap' | 'responseDataKey' | 'responseMessageKey'>
107
+ > & BaseRequestOption<RC, RE, RH, SE>
108
+
109
+ const alovaOptions: AlovaOptions<{
110
+ Responded: any
111
+ Transformed: any
112
+ RequestConfig: RC
113
+ Response: RE
114
+ ResponseHeader: RH
115
+ L1Cache: AlovaGlobalCacheAdapter
116
+ L2Cache: AlovaGlobalCacheAdapter
117
+ StatesExport: SE
118
+ }> = {
119
+ baseURL: config.baseUrl,
120
+ timeout: config.timeout,
121
+ cacheFor: config.cacheFor as any,
122
+ cacheLogger: config.cacheLogger,
123
+ statesHook: config.statesHook,
124
+ l2Cache: config.storageAdapter,
125
+ requestAdapter: config.requestAdapter!,
126
+ beforeRequest: async (method) => {
127
+ for (const [key, value] of Object.entries(config.commonHeaders ?? {})) {
128
+ method.config.headers[key] = typeof value === 'function' ? value() : value
129
+ }
130
+ },
131
+ responded: {
132
+ onSuccess: async (response, method) => {
133
+ const meta = method.meta as Record<string, any> | undefined
134
+ const shouldTransform = getMetaFlag(meta, 'isTransformResponse', config.isTransformResponse ?? true)
135
+ const showSuccess = getMetaFlag(meta, 'isShowSuccessMessage', config.isShowSuccessMessage ?? false)
136
+ const showError = getMetaFlag(meta, 'isShowErrorMessage', config.isShowErrorMessage ?? true)
137
+ const isWrapped = getMetaFlag(meta, 'isWrapped', config.isWrapped ?? true)
138
+
139
+ if (!shouldTransform)
140
+ return response
141
+
142
+ // 兼容 fetch (status) 和 Taro (statusCode)
143
+ const status = (response as any).statusCode ?? (response as any).status
144
+ // 兼容 fetch (body 是 ReadableStream) 和 Taro (data 直接可用)
145
+ const data
146
+ = (response as any)?.body && isReadableStream((response as any).body)
147
+ ? await (response as Response).json()
148
+ : (response as any).data ?? response
149
+
150
+ if (status !== config.statusMap.success) {
151
+ if (config.statusMap.unAuthorized === status)
152
+ config.unAuthorizedResponseFunc?.()
153
+ if (showError)
154
+ config.errorMessageFunc?.(config.errorDefaultMessage ?? '服务异常')
155
+ return Promise.reject(response)
156
+ }
157
+
158
+ if (!isWrapped || (isWrapped === undefined || !config.isWrapped)) {
159
+ if (showSuccess)
160
+ config.successMessageFunc?.(config.successDefaultMessage ?? '操作成功')
161
+ return data
162
+ }
163
+
164
+ const code = data?.code
165
+ const responseData = data?.[config.responseDataKey]
166
+ const responseMessage = data?.[config.responseMessageKey]
167
+
168
+ if (!config.codeMap.success?.includes(+code)) {
169
+ if (config.codeMap.unAuthorized?.includes(+code)) {
170
+ config.unAuthorizedResponseFunc?.()
171
+ return Promise.reject(response)
172
+ }
173
+ if (showError)
174
+ config.errorMessageFunc?.(responseMessage ?? config.errorDefaultMessage ?? '服务异常')
175
+ return Promise.reject(response)
176
+ }
177
+
178
+ if (showSuccess)
179
+ config.successMessageFunc?.(responseMessage ?? config.successDefaultMessage)
180
+ return responseData
181
+ },
182
+ onError: (error, method) => {
183
+ const meta = method.meta as Record<string, any> | undefined
184
+ const showError = getMetaFlag(meta, 'isShowErrorMessage', config.isShowErrorMessage ?? true)
185
+ if (showError)
186
+ config.errorMessageFunc?.(config.errorDefaultMessage ?? error.message)
187
+ return Promise.reject(error)
188
+ },
189
+ },
190
+ }
191
+
192
+ return createAlova(alovaOptions)
193
+ }
@@ -0,0 +1,30 @@
1
+ export function deepMergeObject<T = any>(source: T, target: Partial<T>): T {
2
+ const isObject = (obj: any): obj is Record<string, any> =>
3
+ obj && typeof obj === 'object' && !Array.isArray(obj)
4
+
5
+ const merge = (src: any, tgt: any): any => {
6
+ const result = { ...src }
7
+ if (isObject(result) && isObject(tgt)) {
8
+ Object.keys(tgt).forEach((key) => {
9
+ if (isObject(tgt[key])) {
10
+ result[key] = merge(result[key] || {}, tgt[key])
11
+ }
12
+ else {
13
+ result[key] = tgt[key]
14
+ }
15
+ })
16
+ }
17
+ return result
18
+ }
19
+
20
+ return merge(source, target)
21
+ }
22
+
23
+ /**
24
+ * 判断一个变量是不是可读流
25
+ */
26
+ export function isReadableStream(data: unknown): boolean {
27
+ if (typeof ReadableStream === 'undefined')
28
+ return false
29
+ return data instanceof ReadableStream
30
+ }
@@ -0,0 +1,73 @@
1
+ import type { TaroConfig } from '@alova/adapter-taro'
2
+ import type { VueHookExportType } from 'alova/vue'
3
+ import AdapterTaroVue from '@alova/adapter-taro/vue'
4
+ import Taro from '@tarojs/taro'
5
+ import { apiAffix, apiUrl, isH5, uploadApiAffix } from '@/utils/env'
6
+ import { createInstance } from './core'
7
+
8
+ type TaroResponse
9
+ = | Taro.request.SuccessCallbackResult<any>
10
+ | Taro.uploadFile.SuccessCallbackResult
11
+ | Taro.downloadFile.FileSuccessCallbackResult
12
+
13
+ type TaroResponseHeader = Taro.request.SuccessCallbackResult<any>['header']
14
+
15
+ const taroAdapter = AdapterTaroVue()
16
+
17
+ const alovaRequest = createInstance<
18
+ TaroConfig,
19
+ TaroResponse,
20
+ TaroResponseHeader,
21
+ VueHookExportType<unknown>
22
+ >({
23
+ baseUrl: isH5 ? `/${apiAffix}` : `${apiUrl}/${apiAffix}`,
24
+ statusMap: { success: 200, unAuthorized: 401 },
25
+ codeMap: { success: [200] },
26
+ responseDataKey: 'data',
27
+ responseMessageKey: 'msg',
28
+ commonHeaders: {},
29
+ successMessageFunc: (msg) => {
30
+ Taro.showToast({ title: msg })
31
+ },
32
+ errorMessageFunc: (msg) => {
33
+ Taro.showToast({ title: msg, icon: 'error' })
34
+ },
35
+ unAuthorizedResponseFunc: () => {
36
+ Taro.showToast({ title: '登录过期或未登录' })
37
+ Taro.navigateTo({ url: '/pages/login/index' })
38
+ },
39
+ statesHook: taroAdapter.statesHook,
40
+ requestAdapter: taroAdapter.requestAdapter,
41
+ storageAdapter: taroAdapter.storageAdapter,
42
+ })
43
+
44
+ export default alovaRequest
45
+
46
+ const alovaUploadRequest = createInstance<
47
+ TaroConfig,
48
+ TaroResponse,
49
+ TaroResponseHeader,
50
+ VueHookExportType<unknown>
51
+ >({
52
+ baseUrl: isH5 ? `/${uploadApiAffix}` : `${apiUrl}/${uploadApiAffix}`,
53
+ statusMap: { success: 200, unAuthorized: 401 },
54
+ codeMap: { success: [200] },
55
+ responseDataKey: 'data',
56
+ responseMessageKey: 'msg',
57
+ commonHeaders: {},
58
+ successMessageFunc: (msg) => {
59
+ Taro.showToast({ title: msg })
60
+ },
61
+ errorMessageFunc: (msg) => {
62
+ Taro.showToast({ title: msg, icon: 'error' })
63
+ },
64
+ unAuthorizedResponseFunc: () => {
65
+ Taro.showToast({ title: '登录过期或未登录' })
66
+ Taro.navigateTo({ url: '/pages/login/index' })
67
+ },
68
+ statesHook: taroAdapter.statesHook,
69
+ requestAdapter: taroAdapter.requestAdapter,
70
+ storageAdapter: taroAdapter.storageAdapter,
71
+ })
72
+
73
+ export { alovaUploadRequest }