index copy.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <!-- <template>
  2. <text>头条</text>
  3. </template>
  4. <script>
  5. </script>
  6. <style>
  7. </style> -->
  8. <template>
  9. <view class="wrap">
  10. <view class="pre-box" v-if="!showUploadList">
  11. <view class="pre-item" v-for="(item, index) in lists" :key="index" :style="{
  12. width: $u.addUnit(width),
  13. height: $u.addUnit(height)
  14. }">
  15. <!-- 删除图片按钮 -->
  16. <view class="u-delete-icon" @tap.stop="deleteItem(index)" :style="{
  17. background: delBgColor
  18. }">
  19. <u-icon class="u-icon" name="close" size="20" :color="delColor"></u-icon>
  20. </view>
  21. <!-- 图片上传进度条 -->
  22. <u-line-progress
  23. v-if="showProgress && item.progress > 0 && !item.error"
  24. :show-percent="false"
  25. height="16"
  26. class="u-progress"
  27. :percent="item.progress"
  28. ></u-line-progress>
  29. <!-- 点击重试按钮 -->
  30. <view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
  31. <image
  32. @tap.stop="doPreviewImage(item.url || item.path, index)"
  33. class="pre-item-image"
  34. v-if="!item.isImage"
  35. :src="item.url || item.path"
  36. :mode="imageMode"
  37. ></image>
  38. </view>
  39. </view>
  40. <u-upload :custom-btn="true" ref="uUpload" :show-upload-list="showUploadList" :action="action"
  41. :max-count="type=='video'?1:9" :file-list="fileList">
  42. <view slot="addBtn" class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
  43. <!-- <u-icon name="photo" size="60" color="#c0c4cc"></u-icon> -->
  44. <u-icon name="plus" class="u-add-btn" size="70"></u-icon>
  45. </view>
  46. </u-upload>
  47. </view>
  48. </template>
  49. <script>
  50. export default {
  51. data() {
  52. return {
  53. action: 'http://www.example.com', // 演示地址
  54. showUploadList: false,
  55. // 如果将某个ref的组件实例赋值给data中的变量,在小程序中会因为循环引用而报错
  56. // 这里直接获取内部的lists变量即可
  57. lists: [],
  58. delBgColor: '#fa3534',
  59. delColor: '#ffffff' ,
  60. fileList: [],
  61. type: 'image',
  62. // 内部预览图片区域和选择图片按钮的区域宽度
  63. width: 175,
  64. // 内部预览图片区域和选择图片按钮的区域高度
  65. height: 175,
  66. imageMode: 'aspectFill',
  67. // 是否在点击预览图后展示全屏图片预览
  68. previewFullImage: true,
  69. // 是否显示进度条
  70. showProgress: true,
  71. }
  72. },
  73. // 只有onReady生命周期才能调用refs操作组件
  74. onReady() {
  75. // 得到整个组件对象,内部图片列表变量为"lists"
  76. this.lists = this.$refs.uUpload.lists;
  77. },
  78. watch: {
  79. fileList: {
  80. immediate: true,
  81. handler(val) {
  82. val.map(value => {
  83. // 首先检查内部是否已经添加过这张图片,因为外部绑定了一个对象给fileList的话(对象引用),进行修改外部fileList
  84. // 时,会触发watch,导致重新把原来的图片再次添加到this.lists
  85. // 数组的some方法意思是,只要数组元素有任意一个元素条件符合,就返回true,而另一个数组的every方法的意思是数组所有元素都符合条件才返回true
  86. let tmp = this.lists.some(val => {
  87. return val.url == value.url;
  88. })
  89. // 如果内部没有这个图片(tmp为false),则添加到内部
  90. !tmp && this.lists.push({ url: value.url, error: false, progress: 100 });
  91. });
  92. }
  93. }
  94. },
  95. methods:{
  96. // 删除一个图片
  97. deleteItem(index) {
  98. uni.showModal({
  99. title: '提示',
  100. content: '您确定要删除此项吗?',
  101. success: async (res) => {
  102. if (res.confirm) {
  103. // 如果不存在before-remove钩子,
  104. this.handlerDeleteItem(index);
  105. }
  106. }
  107. });
  108. },
  109. // 执行移除图片的动作,上方代码只是判断是否可以移除
  110. handlerDeleteItem(index) {
  111. // 如果文件正在上传中,终止上传任务,进度在0 < progress < 100则意味着正在上传
  112. if (this.lists[index].process < 100 && this.lists[index].process > 0) {
  113. typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
  114. }
  115. this.lists.splice(index, 1);
  116. this.$forceUpdate();
  117. // this.$emit('on-remove', index, this.lists, this.index);
  118. this.showToast('移除成功');
  119. },
  120. // 预览图片
  121. doPreviewImage(url, index) {
  122. if (!this.previewFullImage) return;
  123. const images = this.lists.map(item => item.url || item.path);
  124. uni.previewImage({
  125. urls: images,
  126. current: url,
  127. success: () => {
  128. // this.$emit('on-preview', url, this.lists, this.index);
  129. },
  130. fail: () => {
  131. uni.showToast({
  132. title: '预览图片失败',
  133. icon: 'none'
  134. });
  135. }
  136. });
  137. },
  138. // 对失败的图片重新上传
  139. retry(index) {
  140. this.lists[index].progress = 0;
  141. this.lists[index].error = false;
  142. this.lists[index].response = null;
  143. uni.showLoading({
  144. title: '重新上传'
  145. });
  146. this.uploadFile(index);
  147. },
  148. }
  149. }
  150. </script>
  151. <style lang="scss">
  152. @import '../../uview-ui/libs/css/style.components.scss';
  153. // @import '../../libs/css/style.components.scss';
  154. .wrap {
  155. // padding: 24rpx;
  156. }
  157. .slot-btn {
  158. width: 175rpx;
  159. height: 175rpx;
  160. display: flex;
  161. justify-content: center;
  162. align-items: center;
  163. background: rgb(244, 245, 246);
  164. border-radius: 10rpx;
  165. }
  166. .slot-btn__hover {
  167. background-color: rgb(235, 236, 238);
  168. }
  169. .pre-box {
  170. display: flex;
  171. align-items: center;
  172. // justify-content: space-b;
  173. flex-wrap: wrap;
  174. }
  175. .pre-item {
  176. // flex: 0 0 48.5%;
  177. border-radius: 10rpx;
  178. height: 200rpx;
  179. overflow: hidden;
  180. position: relative;
  181. // margin-bottom: 20rpx;
  182. }
  183. .u-delete-icon {
  184. position: absolute;
  185. top: 10rpx;
  186. right: 10rpx;
  187. z-index: 10;
  188. background-color: $u-type-error;
  189. border-radius: 100rpx;
  190. width: 44rpx;
  191. height: 44rpx;
  192. @include vue-flex;
  193. align-items: center;
  194. justify-content: center;
  195. }
  196. .pre-item-image {
  197. width: 170rpx;
  198. height: 170rpx;
  199. padding: 10rpx;
  200. }
  201. .u-error-btn {
  202. color: #ffffff;
  203. background-color: $u-type-error;
  204. font-size: 20rpx;
  205. padding: 4px 0;
  206. text-align: center;
  207. position: absolute;
  208. bottom: 0;
  209. left: 0;
  210. right: 0;
  211. z-index: 9;
  212. line-height: 1;
  213. }
  214. </style>