graceSelectImgAndUpload.nvue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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="imgMode"
  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. imgMode:{ type:String, default:'widthFix'},
  62. header:{type:Object, default:function(){return {};}}
  63. },
  64. data() {
  65. return {
  66. imgLists : [],
  67. updatting : false
  68. }
  69. },
  70. watch:{
  71. imgLists : function(newVal, oldVal){
  72. if(!this.updatting){this.$emit('change', newVal);}
  73. }
  74. },
  75. methods:{
  76. clearAllImgs : function(){
  77. this.imgLists = [];
  78. },
  79. addImg : function(){
  80. var num = this.maxFileNumber - this.imgLists.length;
  81. if(num < 1){return false;}
  82. uni.showLoading({title:""});
  83. uni.chooseImage({
  84. count: num,
  85. sizeType: ['compressed'],
  86. success:(res) => {
  87. for(let i = 0; i < res.tempFilePaths.length; i++){
  88. this.imgLists.push({url : res.tempFilePaths[i], progress : 0, error : false});
  89. }
  90. uni.hideLoading();
  91. },
  92. complete:function(){
  93. uni.hideLoading();
  94. },
  95. fail:function(){
  96. uni.hideLoading();
  97. }
  98. });
  99. },
  100. removeImg : function(e){
  101. var index = e.currentTarget.id.replace('grace-items-img-', '');
  102. var removeImg = this.imgLists.splice(index, 1);
  103. this.$emit('removeImg', removeImg[0]);
  104. },
  105. showImgs : function(e){
  106. var currentImg = e.currentTarget.dataset.imgurl;
  107. var imgs = [];
  108. for(let i = 0; i < this.imgLists.length; i++){
  109. imgs.push(this.imgLists[i].url);
  110. }
  111. uni.previewImage({
  112. urls: imgs,
  113. current : currentImg
  114. })
  115. },
  116. upload : function(index){
  117. if(this.updatting){return ;}
  118. this.updatting = true;
  119. if(!index){index = 0;}
  120. uni.showLoading({title:"图片上传中" });
  121. this.uploadBase(index);
  122. },
  123. retry : function (e) {
  124. var index = e.currentTarget.dataset.index;
  125. this.upload(index);
  126. },
  127. uploadBase : function (index) {
  128. // 全部上传完成
  129. if(index > (this.imgLists.length - 1)){
  130. uni.hideLoading();
  131. this.updatting = false;
  132. this.$emit('uploaded', this.imgLists);
  133. return ;
  134. }
  135. // 验证后端
  136. if(this.uploadServerUrl == ''){
  137. uni.showToast({title:"请设置上传服务器地址", icon:"none"});
  138. return ;
  139. }
  140. // 检查是否是默认值
  141. if(this.imgLists[index].progress >= 1){
  142. this.uploadBase(index+1);
  143. return ;
  144. }
  145. this.imgLists[index].error = false;
  146. // 创建上传对象
  147. const task = uni.uploadFile({
  148. url : this.uploadServerUrl,
  149. filePath : this.imgLists[index].url,
  150. name : this.fileName,
  151. formData : this.formData,
  152. header : this.header,
  153. success : (uploadRes) => {
  154. uploadRes = JSON.parse(uploadRes.data);
  155. if(uploadRes.status != 'ok'){
  156. uni.showToast({title:"上传失败 : "+uploadRes.data, icon:"none"});
  157. this.error(index);
  158. }else{
  159. //上传图片成功
  160. this.imgLists[index].progress = 100;
  161. this.imgLists[index].url = uploadRes.data;
  162. this.imgLists[index].result = uploadRes;
  163. this.uploadBase(index+1);
  164. }
  165. },
  166. fail : (e) => {
  167. uni.showToast({title:"上传失败,请点击图片重试", icon:"none"});
  168. this.error(index);
  169. }
  170. });
  171. task.onProgressUpdate((res) => {
  172. if(res.progress > 0){
  173. this.imgLists[index].progress = res.progress;
  174. this.imgLists.splice(index, 1, this.imgLists[index]);
  175. }
  176. });
  177. },
  178. // 上传错误
  179. error : function(index){
  180. this.updatting = false;
  181. setTimeout(()=>{
  182. this.imgLists[index].progress = 0;
  183. this.imgLists[index].error = true;
  184. this.$emit('uploaderror');
  185. }, 500);
  186. },
  187. // 设置默认值
  188. setItems : function(items){
  189. this.imgLists = [];
  190. for(let i = 0; i < items.length; i++){
  191. this.imgLists.push({url : items[i], progress : 100});
  192. }
  193. },
  194. imgLoad : function (e) {
  195. var height = e.detail.height;
  196. var width = e.detail.width;
  197. var index = e.currentTarget.dataset.index;
  198. this.imgLists[index].height = (height/width*uni.upx2px(222)) + 'px';
  199. this.imgLists.splice(index, 1, this.imgLists[index]);
  200. }
  201. }
  202. }
  203. </script>
  204. <style scoped>
  205. .grace-add-list{flex-wrap:wrap; flex-direction:row;}
  206. .grace-add-list-btn{flex-direction:column; align-items:center; justify-content:center;}
  207. .grace-add-list-btn-text{font-size:26rpx; line-height:36rpx; text-align:center; color:#999999;}
  208. .grace-add-list-btn-icon{font-size:80rpx; height:80rpx; line-height:80rpx; margin-bottom:20rpx; color:#999999;}
  209. .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;}
  210. .grace-add-list-image{width:222rpx;}
  211. .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;}
  212. .upload-progress{position:absolute; left:22rpx; bottom:10rpx; width:180rpx;}
  213. .grace-add-list-reup{position:absolute; left:0; top:60rpx; width:222rpx; height:160rpx; flex-direction:column;}
  214. .grace-add-list-reup-icon{text-align:center; color:#FFFFFF; font-size:80rpx; line-height:80rpx;}
  215. .grace-add-list-reup-text{text-align:center; color:#FFFFFF; font-size:20rpx; line-height:30rpx;}
  216. .grace-add-list-img{width:222rpx;}
  217. </style>