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.

upload-images.vue 6.6 KiB

4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <template>
  2. <view class="upload-content">
  3. <block v-for="(item, index) in imageList" :key="index">
  4. <view class="upload-item">
  5. <image class="upload-img" :src="item.filePath" mode="aspectFill" @click="previewImage(index)"></image>
  6. <image class="upload-del-btn"
  7. @click="delImage(index)"
  8. src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAmCAYAAACoPemuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjNBODgzQjUwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjNBODgzQjYwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGM0E4ODNCMzA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGM0E4ODNCNDA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuYQTIAAAAHNSURBVHjazJgxasMwFIbjnsD4BDmCLxDQDZrNQ5bcILlBvXvpDRLIWmiHFkyH2t0LyVbwEkPpbE/eYlUCGYQax096UuIffkIgij7ryU/vyZuYy2e+Z56K70R8lsJcOfPn5AriMCvmZ2YKdMW8EQ/hRA9iEorwXlpZtObMRySQ6kysvrFWloHUEIcmUBuHUDLccmxQskErt7wyVLdy00tQ4Q2g5De2V9kNwWjffiNDA33f/42i6E13Qj5uNptlwJD+SyODuaqqqi/KVBTFOxSKA7VtW/NxSZI8AcbE2nuraZpvKgSBk6G4drsdBOwogz1CwAghH/JEl+BUKJ1VltPHHjoIAoeE4l53YFqb+RKcBSgqyqXhtxEKZwkKB3YOThYCqjPuCDoHZwGK3mGLtdPp5LmqTI1Dqe4p26EkNqA4iE6eg2z+iQ0okyQMATvYgLIIt9Y6knTyFBIudHqIq3BpmkL60VJ9O0sXZY8MBwSLtdNGEAQ/i8XiVXcz83EcEPDbuq/fzMdYWt+6GTmMsX2rh9q3TtsxNrzXhKt1rwg6rR1Dhdjqo7QMlWOvoWTF4imxQMRF7eaL8L5ohmwrLgDB8pCQc8DlcG7y538CDABJNGPqfaJgfgAAAABJRU5ErkJggg=="
  9. mode="scaleToFill">
  10. </image>
  11. <view class="upload-progress" v-if="item.progress < 100">{{item.progress}}%</view>
  12. </view>
  13. </block>
  14. <view class="upload-add-btn" v-if="rduLength > 0" @click="chooseImage"></view>
  15. </view>
  16. </template>
  17. <script>
  18. export default {
  19. data() {
  20. return {
  21. imageList: []
  22. };
  23. },
  24. props: {
  25. url: {
  26. type: String,
  27. value: '' //上传接口地址
  28. },
  29. count: {
  30. type: Number,
  31. value: 4 //单次可选择的图片数量
  32. },
  33. length: {
  34. type: Number,
  35. value: 50 //可上传总数量
  36. }
  37. },
  38. computed: {
  39. rduLength(){
  40. return this.length - this.imageList.length;
  41. }
  42. },
  43. methods: {
  44. //选择图片
  45. chooseImage: function(){
  46. uni.chooseImage({
  47. count: this.rduLength < this.count ? this.rduLength : this.count, //最多可以选择的图片张数,默认9
  48. sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有
  49. sourceType: ['album'], //album 从相册选图,camera 使用相机,默认二者都有
  50. success: (res)=> {
  51. const images = res.tempFilePaths;
  52. this.uploadFiles(images);
  53. }
  54. });
  55. },
  56. //上传图片
  57. async uploadFiles(images){
  58. this.imageList.push({
  59. filePath: images[0],
  60. progress: 0
  61. });
  62. uni.showLoading({
  63. title: '请稍后..',
  64. mask: true,
  65. })
  66. try{
  67. const uploadUrl = await this.uploadImage(images[0]);
  68. }catch(err){
  69. console.log(err);
  70. return;
  71. }
  72. if(uploadUrl !== false){
  73. images.splice(0, 1);
  74. this.imageList[this.imageList.length - 1].src = uploadUrl;
  75. //判断是否需要继续上传
  76. if(images.length > 0 && this.rduLength > 0){
  77. this.uploadFiles(images);
  78. }else{
  79. uni.hideLoading();
  80. }
  81. }else{
  82. //上传失败处理
  83. this.imageList.pop();
  84. uni.hideLoading();
  85. uni.showToast({
  86. title: '上传中出现问题,已终止上传',
  87. icon: 'none',
  88. mask: true,
  89. duration: 2000
  90. });
  91. }
  92. },
  93. uploadImage: function(file){
  94. return new Promise((resolve, reject)=> {
  95. //发送给后端的附加参数
  96. const formData = {
  97. thumb_mode: 1,
  98. };
  99. this.uploadTask = uni.uploadFile({
  100. url: this.url,
  101. filePath: file,
  102. name: 'file',
  103. formData: formData,
  104. success(uploadFileResult){
  105. const uploadFileRes = JSON.parse(uploadFileResult.data) || {};
  106. if(uploadFileRes.status === 1 && uploadFileRes.data){
  107. resolve(uploadFileRes.data);
  108. }else{
  109. reject('接口返回错误');
  110. }
  111. },
  112. fail(){
  113. reject('网络链接错误');
  114. }
  115. });
  116. //上传进度
  117. this.uploadTask.onProgressUpdate((progressRes)=> {
  118. this.imageList[this.imageList.length - 1].progress = progressRes.progress;
  119. });
  120. });
  121. },
  122. //删除图片
  123. delImage: function(index){
  124. uni.showModal({
  125. cancelText:'Cancel',
  126. confirmText:'OK',
  127. content: '确定要放弃这张图片么?',
  128. success: (confirmRes)=> {
  129. if (confirmRes.confirm) {
  130. this.imageList.splice(index, 1);
  131. }
  132. }
  133. });
  134. },
  135. //预览图片
  136. previewImage: function(index){
  137. const urls = [];
  138. this.imageList.forEach((item)=> {
  139. urls.push(item.filePath);
  140. })
  141. uni.previewImage({
  142. current: urls[index],
  143. urls: urls,
  144. indicator: "number"
  145. })
  146. }
  147. }
  148. }
  149. </script>
  150. <style lang="scss">
  151. .upload-content{
  152. padding:24upx 0 0 28upx;
  153. background-color: #fff;
  154. overflow:hidden;
  155. }
  156. .upload-item{
  157. position: relative;
  158. float:left;
  159. width:150upx;
  160. height:150upx;
  161. margin-right:30upx;
  162. margin-bottom:30upx;
  163. &:nth-child(4n){
  164. margin-right:0;
  165. }
  166. .upload-img{
  167. width:100%;
  168. height:100%;
  169. border-radius:8upx;
  170. }
  171. .upload-del-btn{
  172. position: absolute;
  173. right:-16upx;
  174. top:-14upx;
  175. width:36upx;
  176. height:36upx;
  177. border: 4upx solid #fff;
  178. border-radius: 100px;
  179. }
  180. .upload-progress{
  181. position: absolute;
  182. left:0;
  183. top:0;
  184. display:flex;
  185. align-items:center;
  186. justify-content: center;
  187. width:100%;
  188. height:100%;
  189. background-color: rgba(0,0,0,.4);
  190. color:#fff;
  191. font-size:24upx;
  192. border-radius:8upx;
  193. }
  194. }
  195. .upload-add-btn {
  196. position: relative;
  197. float:left;
  198. width: 150upx;
  199. height: 150upx;
  200. z-index: 99;
  201. border-radius:8upx;
  202. background:#f9f9f9;
  203. &:before,
  204. &:after {
  205. content: " ";
  206. position: absolute;
  207. top: 50%;
  208. left: 50%;
  209. -webkit-transform: translate(-50%, -50%);
  210. transform: translate(-50%, -50%);
  211. width: 4upx;
  212. height: 60upx;
  213. background-color: #d6d6d6;
  214. }
  215. &:after {
  216. width: 60upx;
  217. height: 4upx;
  218. }
  219. &:active {
  220. background-color: #f7f7f7;
  221. }
  222. }
  223. </style>