graceSelectImgAndUpload.nvue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <view class="grace-add-list">
  3. <view class="grace-add-list-items" v-for="(item, index) in imgLists" :key="index">
  4. <image
  5. :src="item.url" :data-imgurl="item.url" @tap="showImgs" @load="imgLoad" :data-index="index" class="grace-add-list-img" mode="widthFix"
  6. :style="{width:'222rpx', height:item.height}"></image>
  7. <text class="grace-add-list-remove grace-icons" :style="{color:closeBtnColor}" @tap.stop="removeImg" :id="'grace-items-img-'+index">&#xe632;</text>
  8. <view class="upload-progress">
  9. <progress :percent="item.progress" :stroke-width="progressSize" :activeColor="progressColor" :backgroundColor="progressBGColor" />
  10. </view>
  11. <view class="grace-add-list-reup" v-if="item.error">
  12. <text class="grace-add-list-reup-icon grace-icons" @tap.stop="retry" :data-index="index">&#xe635;</text>
  13. <text class="grace-add-list-reup-text">失败重试</text>
  14. </view>
  15. </view>
  16. <view class="grace-add-list-items grace-add-list-btn" @tap="addImg" v-if="imgLists.length < maxFileNumber">
  17. <text class="grace-add-list-btn-icon">+</text>
  18. <text class="grace-add-list-btn-text">{{btnName}}</text>
  19. </view>
  20. </view>
  21. </template>
  22. <script>
  23. export default {
  24. props:{
  25. maxFileNumber : {
  26. type : Number,
  27. default : 9
  28. },
  29. btnName : {
  30. type : String,
  31. default : "添加照片"
  32. },
  33. items : {
  34. type : Array,
  35. default : function () {
  36. return [];
  37. }
  38. },
  39. closeBtnColor : {
  40. type : String,
  41. default : "#666666"
  42. },
  43. uploadServerUrl : {
  44. type : String,
  45. default : ''
  46. },
  47. progressSize :{
  48. type:Number,
  49. default:1
  50. },
  51. progressColor :{
  52. type:String,
  53. default:'#27BD81'
  54. },
  55. progressBGColor :{
  56. type:String,
  57. default:'#F8F8F8'
  58. },
  59. fileName : {type:String, default:'img'},
  60. formData : {type:Object, default:function(){return {};}}
  61. },
  62. data() {
  63. return {
  64. imgLists : [],
  65. updatting : false
  66. }
  67. },
  68. watch:{
  69. imgLists : function(newVal, oldVal){
  70. if(!this.updatting){this.$emit('change', newVal);}
  71. }
  72. },
  73. methods:{
  74. clearAllImgs : function(){
  75. this.imgLists = [];
  76. },
  77. addImg : function(){
  78. var num = this.maxFileNumber - this.imgLists.length;
  79. if(num < 1){return false;}
  80. uni.showLoading({title:""});
  81. uni.chooseImage({
  82. count: num,
  83. sizeType: ['compressed'],
  84. success:(res) => {
  85. for(let i = 0; i < res.tempFilePaths.length; i++){
  86. this.imgLists.push({url : res.tempFilePaths[i], progress : 0, error : false});
  87. }
  88. uni.hideLoading();
  89. },
  90. complete:function(){
  91. uni.hideLoading();
  92. },
  93. fail:function(){
  94. uni.hideLoading();
  95. }
  96. });
  97. },
  98. removeImg : function(e){
  99. var index = e.currentTarget.id.replace('grace-items-img-', '');
  100. this.imgLists.splice(index, 1);
  101. },
  102. showImgs : function(e){
  103. var currentImg = e.currentTarget.dataset.imgurl;
  104. var imgs = [];
  105. for(let i = 0; i < this.imgLists.length; i++){
  106. imgs.push(this.imgLists[i].url);
  107. }
  108. uni.previewImage({
  109. urls: imgs,
  110. current : currentImg
  111. })
  112. },
  113. upload : function(index){
  114. if(this.updatting){return ;}
  115. this.updatting = true;
  116. if(!index){index = 0;}
  117. uni.showLoading({title:"图片上传中" });
  118. this.uploadBase(index);
  119. },
  120. retry : function (e) {
  121. var index = e.currentTarget.dataset.index;
  122. this.upload(index);
  123. },
  124. uploadBase : function (index) {
  125. // 全部上传完成
  126. if(index > (this.imgLists.length - 1)){
  127. uni.hideLoading();
  128. this.updatting = false;
  129. this.$emit('uploaded', this.imgLists);
  130. return ;
  131. }
  132. // 验证后端
  133. if(this.uploadServerUrl == ''){
  134. uni.showToast({title:"请设置上传服务器地址", icon:"none"});
  135. return ;
  136. }
  137. // 检查是否是默认值
  138. if(this.imgLists[index].progress >= 1){
  139. this.uploadBase(index+1);
  140. return ;
  141. }
  142. this.imgLists[index].error = false;
  143. // 创建上传对象
  144. const task = uni.uploadFile({
  145. url : this.uploadServerUrl,
  146. filePath : this.imgLists[index].url,
  147. name : this.fileName,
  148. formData : this.formData,
  149. success : (uploadRes) => {
  150. uploadRes = JSON.parse(uploadRes.data);
  151. if(uploadRes.status != 'ok'){
  152. uni.showToast({title:"上传失败 : "+uploadRes.data, icon:"none"});
  153. this.error(index);
  154. }else{
  155. //上传图片成功
  156. this.imgLists[index].progress = 100;
  157. this.imgLists[index].url = uploadRes.data;
  158. this.imgLists[index].result = uploadRes;
  159. this.uploadBase(index+1);
  160. }
  161. },
  162. fail : (e) => {
  163. uni.showToast({title:"上传失败,请点击图片重试", icon:"none"});
  164. this.error(index);
  165. }
  166. });
  167. task.onProgressUpdate((res) => {
  168. if(res.progress > 0){
  169. this.imgLists[index].progress = res.progress;
  170. this.imgLists.splice(index, 1, this.imgLists[index]);
  171. }
  172. });
  173. },
  174. // 上传错误
  175. error : function(index){
  176. this.updatting = false;
  177. setTimeout(()=>{
  178. this.imgLists[index].progress = 0;
  179. this.imgLists[index].error = true;
  180. this.$emit('uploaderror');
  181. }, 500);
  182. },
  183. // 设置默认值
  184. setItems : function(items){
  185. for(let i = 0; i < items.length; i++){
  186. this.imgLists.push({url : items[i], progress : 100, error : false});
  187. }
  188. },
  189. imgLoad : function (e) {
  190. var height = e.detail.height;
  191. var width = e.detail.width;
  192. var index = e.currentTarget.dataset.index;
  193. this.imgLists[index].height = (height/width*uni.upx2px(222)) + 'px';
  194. this.imgLists.splice(index, 1, this.imgLists[index]);
  195. }
  196. }
  197. }
  198. </script>
  199. <style scoped>
  200. .grace-add-list{flex-wrap:wrap; flex-direction:row;}
  201. .grace-add-list-btn{flex-direction:column; align-items:center; justify-content:center;}
  202. .grace-add-list-btn-text{font-size:26rpx; line-height:36rpx; text-align:center; color:#999999;}
  203. .grace-add-list-btn-icon{font-size:80rpx; height:80rpx; line-height:80rpx; margin-bottom:20rpx; color:#999999;}
  204. .grace-add-list-items{width:222rpx; height:222rpx; overflow:hidden; margin-bottom:10rpx; margin-right:11rpx; background-color:#F6F7F8; font-size:0; border-radius:10rpx;}
  205. .grace-add-list-image{width:222rpx;}
  206. .grace-add-list-remove{width:50rpx; height:50rpx; line-height:50rpx; text-align:center; font-size:40rpx; position:absolute; right:10rpx; top:10rpx; color:#888888;}
  207. .upload-progress{position:absolute; left:22rpx; bottom:10rpx; width:180rpx;}
  208. .grace-add-list-reup{position:absolute; left:0; top:60rpx; width:222rpx; height:160rpx; flex-direction:column;}
  209. .grace-add-list-reup-icon{text-align:center; color:#FFFFFF; font-size:80rpx; line-height:80rpx;}
  210. .grace-add-list-reup-text{text-align:center; color:#FFFFFF; font-size:20rpx; line-height:30rpx;}
  211. .grace-add-list-img{width:222rpx;}
  212. </style>