graceNvueSelectImgAndUpload.vue 7.0 KB

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