file-upload2.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <view class="file-upload">
  3. <view class="preview" v-for="(item, index) in fileList" :key="index">
  4. <image
  5. class="preview-image"
  6. mode="aspectFill"
  7. :src="
  8. item.fileType === 'image' ? item.tempFilePath : item.thumbTempFilePath
  9. "
  10. @tap="previewFile(index, item)"
  11. >
  12. </image>
  13. <image
  14. class="delete-icon"
  15. src="@/static/images/upload/delete.png"
  16. @tap="deleteFile(index)"
  17. />
  18. </view>
  19. <view class="upload-btn" v-if="!disabled" @click="chooseFile">
  20. <image
  21. class="upload-icon"
  22. src="@/static/images/upload/camera.png"
  23. alt=""
  24. />
  25. <view class="text">添加图片</view>
  26. </view>
  27. <view class="video" v-if="isPreviewVideo">
  28. <video
  29. id="myVideo"
  30. :src="videoUrl"
  31. autoplay
  32. controls
  33. @error="videoErrorCallback"
  34. ></video>
  35. <image src="@/static/images/upload/delete.png" @tap="closeVideo" />
  36. </view>
  37. </view>
  38. </template>
  39. <script>
  40. import { uploadFile } from "@/api/system";
  41. import CanvasCompress from "canvas-compress";
  42. import { fileToBase64 } from "@/utils";
  43. export default {
  44. name: "uploadFile",
  45. props: {
  46. maxCount: {
  47. type: Number,
  48. default: 5,
  49. },
  50. catalog: {
  51. type: String,
  52. default: "house", // 当前默认租房
  53. },
  54. },
  55. data() {
  56. return {
  57. fileList: [],
  58. disabled: false,
  59. isPreviewVideo: false,
  60. videoUrl: "",
  61. };
  62. },
  63. created() {
  64. this.compressor = new CanvasCompress({
  65. type: CanvasCompress.MIME.JPEG,
  66. width: 600,
  67. height: 600,
  68. quality: 0.8,
  69. });
  70. },
  71. methods: {
  72. async compress(file) {
  73. const res = await this.compressor.process(file);
  74. return res.result;
  75. },
  76. chooseFile() {
  77. var that = this;
  78. // #ifdef MP-WEIXIN
  79. uni.chooseMedia({
  80. count: this.maxCount,
  81. mediaType: ["image"],
  82. sourceType: ["album", "camera"],
  83. maxDuration: 60,
  84. camera: "back",
  85. success(res) {
  86. const fileInfo = res.tempFiles;
  87. const fileType = res.type;
  88. fileInfo.forEach((item) => {
  89. console.log(item);
  90. item.fileType = fileType; //兼容ios15.3
  91. if (fileType === "image" && item.size > 500 * 1024) {
  92. console.log("压缩再上传");
  93. uni.compressImage({
  94. src: item.tempFilePath,
  95. quality: 80,
  96. success: (res) => {
  97. item.tempFilePath = res.tempFilePath;
  98. that.upload(item);
  99. },
  100. fail: (err) => console.log(err),
  101. });
  102. } else {
  103. that.upload(item);
  104. }
  105. });
  106. },
  107. fail(err) {
  108. console.log(err);
  109. },
  110. });
  111. // #endif
  112. // #ifdef MP-ALIPAY || H5
  113. uni.chooseImage({
  114. count: this.maxCount,
  115. success(res) {
  116. console.log(res);
  117. /* res.tempFiles.forEach(async (tempFile,index) => {
  118. const compressedFile=await that.compress(tempFile);
  119. const fileInfo = await uploadFile({
  120. file:compressedFile.blob,
  121. formData: {
  122. catalog: that.catalog,
  123. },
  124. });
  125. that.fileList.push({
  126. tempFilePath: res.tempFilePaths[index],
  127. fileType: "image",
  128. fileId: fileInfo.data,
  129. });
  130. }); */
  131. /* rpc上传接口有大小限制,iphone相册图片上传413 */
  132. res.tempFiles.forEach(async (file, index) => {
  133. const compressedFile = await that.compress(file);
  134. const fileBase64 = await fileToBase64(compressedFile.blob);
  135. const fileInfo = await uploadFile({
  136. fileBase64Vos: [
  137. { fileName: file.name, contentBase64: fileBase64 },
  138. ],
  139. catalog: that.catalog,
  140. });
  141. console.log("本地路径地址", res.tempFilePaths[index]);
  142. that.fileList.push({
  143. tempFilePath: res.tempFilePaths[index],
  144. fileType: "image",
  145. fileId: fileInfo.data,
  146. });
  147. });
  148. if (that.fileList.length >= that.maxCount) {
  149. that.disabled = true;
  150. }
  151. },
  152. fail(err) {
  153. console.log(err);
  154. },
  155. });
  156. // #endif
  157. },
  158. upload(res) {
  159. let item = { ...res };
  160. uploadFile(res.tempFilePath).then((res) => {
  161. item.fileId = res.data;
  162. this.fileList.push(item);
  163. if (this.fileList.length >= this.maxCount) {
  164. this.disabled = true;
  165. }
  166. });
  167. },
  168. // 删除选择的文件
  169. deleteFile(val) {
  170. this.fileList.splice(val, 1);
  171. },
  172. // 预览图片和视频
  173. previewFile(index, val) {
  174. if (val.fileType === "image") {
  175. const imageUrls = [];
  176. this.fileList.forEach((item) => {
  177. if (item.fileType === "image") {
  178. imageUrls.push(item.tempFilePath);
  179. } else if (item.fileType === "video") {
  180. imageUrls.push(item.thumbTempFilePath);
  181. }
  182. });
  183. uni.previewImage({
  184. current: index,
  185. urls: imageUrls,
  186. });
  187. } else if (val.fileType === "video") {
  188. this.videoUrl = val.tempFilePath;
  189. this.isPreviewVideo = true;
  190. } else if (val.fileType === "audio") {
  191. const innerAudioContext = uni.createInnerAudioContext();
  192. innerAudioContext.autoplay = true;
  193. innerAudioContext.src = val.tempFilePath;
  194. innerAudioContext.play();
  195. }
  196. },
  197. // 关闭正在预览的视频
  198. closeVideo() {
  199. this.isPreviewVideo = false;
  200. },
  201. // 播放视频失败
  202. videoErrorCallback(e) {
  203. uni.showModal({
  204. content: e.target.errMsg,
  205. showCancel: false,
  206. });
  207. },
  208. },
  209. };
  210. </script>
  211. <style lang="scss" scoped>
  212. .file-upload {
  213. display: flex;
  214. align-items: center;
  215. flex-wrap: wrap;
  216. .preview {
  217. display: flex;
  218. flex-wrap: wrap;
  219. position: relative;
  220. margin: 5px;
  221. border-radius: 5px;
  222. border: 1px solid #e5e2e2;
  223. .preview-image {
  224. width: 70px;
  225. height: 70px;
  226. border-radius: 5px;
  227. }
  228. .delete-icon {
  229. width: 22px;
  230. height: 22px;
  231. position: absolute;
  232. top: 0;
  233. right: 0;
  234. }
  235. }
  236. .upload-btn {
  237. width: 80px;
  238. height: 80px;
  239. margin: 5px;
  240. border: 0.5px solid #ebe6e6;
  241. border-radius: 5px;
  242. display: flex;
  243. justify-content: center;
  244. align-items: center;
  245. flex-direction: column;
  246. .upload-icon {
  247. width: 35px;
  248. height: 35px;
  249. }
  250. .text {
  251. font-size: 10px;
  252. font-weight: 200;
  253. color: #999999;
  254. margin-top: 2px;
  255. }
  256. }
  257. .video {
  258. position: absolute;
  259. z-index: 999;
  260. image {
  261. width: 25px;
  262. height: 25px;
  263. position: absolute;
  264. right: 8px;
  265. }
  266. }
  267. }
  268. </style>