gui-upload-images.vue 8.7 KB

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