gui-upload-images.vue 8.8 KB

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