commit
						2ca7f48131
					
				
							
								
								
									
										21
									
								
								.env
								
								
								
								
							
							
						
						
									
										21
									
								
								.env
								
								
								
								
							|  | @ -1,28 +1,31 @@ | |||
| # 版本号 | ||||
| SHOPRO_VERSION = v1.8.3 | ||||
| SHOPRO_VERSION=v1.8.3 | ||||
| 
 | ||||
| # 后端接口 - 正式环境(通过 process.env.NODE_ENV 非 development) | ||||
| SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn | ||||
| SHOPRO_BASE_URL=http://api-dashboard.yudao.iocoder.cn | ||||
| 
 | ||||
| # 后端接口 - 测试环境(通过 process.env.NODE_ENV = development) | ||||
| SHOPRO_DEV_BASE_URL = http://127.0.0.1:48080 | ||||
| SHOPRO_DEV_BASE_URL=http://127.0.0.1:48080 | ||||
| ### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc | ||||
| 
 | ||||
| # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务 | ||||
| SHOPRO_UPLOAD_TYPE=client | ||||
| 
 | ||||
| # 后端接口前缀(一般不建议调整) | ||||
| SHOPRO_API_PATH = /app-api | ||||
| SHOPRO_API_PATH=/app-api | ||||
| 
 | ||||
| # 后端 websocket 接口前缀 | ||||
| SHOPRO_WEBSOCKET_PATH = /infra/ws | ||||
| SHOPRO_WEBSOCKET_PATH=/infra/ws | ||||
| 
 | ||||
| # 开发环境运行端口 | ||||
| SHOPRO_DEV_PORT = 3000 | ||||
| SHOPRO_DEV_PORT=3000 | ||||
| 
 | ||||
| # 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地  |  http(s)://xxx.xxx=自定义静态资源地址前缀 | ||||
| SHOPRO_STATIC_URL = http://test.yudao.iocoder.cn | ||||
| SHOPRO_STATIC_URL=http://test.yudao.iocoder.cn | ||||
| ### SHOPRO_STATIC_URL = https://file.sheepjs.com | ||||
| 
 | ||||
| # 是否开启直播  1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启) | ||||
| SHOPRO_MPLIVE_ON = 0 | ||||
| SHOPRO_MPLIVE_ON=0 | ||||
| 
 | ||||
| # 租户ID 默认 1 | ||||
| SHOPRO_TENANT_ID = 1 | ||||
| SHOPRO_TENANT_ID=1 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import { baseUrl, apiPath, tenantId } from '@/sheep/config'; | ||||
| import request from '@/sheep/request'; | ||||
| 
 | ||||
| const FileApi = { | ||||
|   // 上传文件
 | ||||
|  | @ -40,6 +41,26 @@ const FileApi = { | |||
|       }); | ||||
|     }); | ||||
|   }, | ||||
| 
 | ||||
|   // 获取文件预签名地址
 | ||||
|   getFilePresignedUrl: (path) => { | ||||
|     return request({ | ||||
|       url: '/infra/file/presigned-url', | ||||
|       method: 'GET', | ||||
|       params: { | ||||
|         path, | ||||
|       }, | ||||
|     }); | ||||
|   }, | ||||
| 
 | ||||
|   // 创建文件
 | ||||
|   createFile: (data) => { | ||||
|     return request({ | ||||
|       url: '/infra/file/create', // 请求的 URL
 | ||||
|       method: 'POST', // 请求方法
 | ||||
|       data: data, // 要发送的数据
 | ||||
|     }); | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| export default FileApi; | ||||
|  |  | |||
|  | @ -116,6 +116,28 @@ function normalizeChooseAndUploadFileRes(res, fileType) { | |||
|   return res; | ||||
| } | ||||
| 
 | ||||
| function convertToArrayBuffer(uniFile) { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     const fs = uni.getFileSystemManager(); | ||||
| 
 | ||||
|     fs.readFile({ | ||||
|       filePath: uniFile.path, // 确保路径正确
 | ||||
|       success: (fileRes) => { | ||||
|         try { | ||||
|           // 将读取的内容转换为 ArrayBuffer
 | ||||
|           const arrayBuffer = new Uint8Array(fileRes.data).buffer; | ||||
|           resolve(arrayBuffer); | ||||
|         } catch (error) { | ||||
|           reject(new Error(`转换为 ArrayBuffer 失败: ${error.message}`)); | ||||
|         } | ||||
|       }, | ||||
|       fail: (error) => { | ||||
|         reject(new Error(`读取文件失败: ${error.errMsg}`)); | ||||
|       }, | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| function uploadCloudFiles(files, max = 5, onUploadProgress) { | ||||
|   files = JSON.parse(JSON.stringify(files)); | ||||
|   const len = files.length; | ||||
|  | @ -165,36 +187,58 @@ function uploadCloudFiles(files, max = 5, onUploadProgress) { | |||
|   }); | ||||
| } | ||||
| 
 | ||||
| function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) { | ||||
|   return choosePromise | ||||
|     .then((res) => { | ||||
|       if (onChooseFile) { | ||||
|         const customChooseRes = onChooseFile(res); | ||||
|         if (typeof customChooseRes !== 'undefined') { | ||||
|           return Promise.resolve(customChooseRes).then((chooseRes) => | ||||
|             typeof chooseRes === 'undefined' ? res : chooseRes, | ||||
|           ); | ||||
|         } | ||||
| async function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) { | ||||
|   // 获取选择的文件
 | ||||
|   const res = await choosePromise; | ||||
|   // 处理文件选择回调
 | ||||
|   let files = res.tempFiles || []; | ||||
|   if (onChooseFile) { | ||||
|     const customChooseRes = onChooseFile(res); | ||||
|     if (typeof customChooseRes !== 'undefined') { | ||||
|       files = await Promise.resolve(customChooseRes); | ||||
|       if (typeof files === 'undefined') { | ||||
|         files = res.tempFiles || []; // Fallback
 | ||||
|       } | ||||
|       return res; | ||||
|     }) | ||||
|     .then((res) => { | ||||
|       if (res === false) { | ||||
|         return { | ||||
|           errMsg: ERR_MSG_OK, | ||||
|           tempFilePaths: [], | ||||
|           tempFiles: [], | ||||
|         }; | ||||
|       } | ||||
|       return res; | ||||
|     }) | ||||
|     .then(async (files) => { | ||||
|       for (let file of files.tempFiles) { | ||||
|         const { data } = await FileApi.uploadFile(file.path); | ||||
|         file.url = data; | ||||
|       } | ||||
|       return files; | ||||
|     }); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // 如果是前端直连上传
 | ||||
|   if (UPLOAD_TYPE.CLIENT === import.meta.env.SHOPRO_UPLOAD_TYPE) { | ||||
|     for (const file of files) { | ||||
|       // 1.1 获取文件预签名地址
 | ||||
|       const { data: presignedInfo } = await FileApi.getFilePresignedUrl(file.name); | ||||
|       // 1.2 获取二进制文件对象
 | ||||
|       const fileBuffer = await convertToArrayBuffer(file); | ||||
|       // 1.3 上传文件
 | ||||
|       await uni.request({ | ||||
|         url: presignedInfo.uploadUrl, // 预签名的上传 URL
 | ||||
|         method: 'PUT', // 使用 PUT 方法
 | ||||
|         header: { | ||||
|           'Content-Type': file.fileType + '/' + file.name.substring(file.name.lastIndexOf('.') + 1), // 设置内容类型
 | ||||
|         }, | ||||
|         data: fileBuffer, // 文件的路径,适用于小程序
 | ||||
|         success: (res) => { | ||||
|           // 1.4. 记录文件信息到后端(异步)
 | ||||
|           createFile(presignedInfo, file); | ||||
|           // 1.5. 重新赋值
 | ||||
|           file.url = presignedInfo.url; | ||||
|           console.log('上传成功:', res); | ||||
|         }, | ||||
|         fail: (err) => { | ||||
|           console.error('上传失败:', err); | ||||
|         }, | ||||
|       }); | ||||
|     } | ||||
|     return files; | ||||
|   } else { | ||||
|     // 后端上传
 | ||||
|     for (let file of files) { | ||||
|       const { data } = await FileApi.uploadFile(file.path); | ||||
|       file.url = data; | ||||
|     } | ||||
| 
 | ||||
|     return files; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function chooseAndUploadFile( | ||||
|  | @ -210,4 +254,32 @@ function chooseAndUploadFile( | |||
|   return uploadFiles(chooseAll(opts), opts); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 创建文件信息 | ||||
|  * @param vo 文件预签名信息 | ||||
|  * @param file 文件 | ||||
|  */ | ||||
| function createFile(vo, file) { | ||||
|   const fileVo = { | ||||
|     configId: vo.configId, | ||||
|     url: vo.url, | ||||
|     path: file.name, | ||||
|     name: file.name, | ||||
|     type: file.fileType, | ||||
|     size: file.size, | ||||
|   }; | ||||
|   FileApi.createFile(fileVo); | ||||
|   return fileVo; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 上传类型 | ||||
|  */ | ||||
| const UPLOAD_TYPE = { | ||||
|   // 客户端直接上传(只支持S3服务)
 | ||||
|   CLIENT: 'client', | ||||
|   // 客户端发送到后端上传
 | ||||
|   SERVER: 'server', | ||||
| }; | ||||
| 
 | ||||
| export { chooseAndUploadFile, uploadCloudFiles }; | ||||
|  |  | |||
|  | @ -369,7 +369,7 @@ | |||
|             }, | ||||
|           }) | ||||
|           .then((result) => { | ||||
|             this.setSuccessAndError(result.tempFiles); | ||||
|             this.setSuccessAndError(result); | ||||
|           }) | ||||
|           .catch((err) => { | ||||
|             console.log('选择失败', err); | ||||
|  | @ -453,7 +453,7 @@ | |||
| 
 | ||||
|           if (index === -1 || !this.files) break; | ||||
|           if (item.errMsg === 'request:fail') { | ||||
|             this.files[index].url = item.path; | ||||
|             this.files[index].url = item.url; | ||||
|             this.files[index].status = 'error'; | ||||
|             this.files[index].errMsg = item.errMsg; | ||||
|             // this.files[index].progress = -1 | ||||
|  | @ -587,7 +587,7 @@ | |||
|             path: v.path, | ||||
|             size: v.size, | ||||
|             fileID: v.fileID, | ||||
|             url: v.url, | ||||
|             url: v.path, | ||||
|           }); | ||||
|         }); | ||||
|         return newFilesData; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 芋道源码
						芋道源码