index.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <template>
  2. <view class="imgs-row-scroll" :style="{ maxWidth: containerWidth + 'rpx' }">
  3. <u-scroll-list :indicator="true" :indicator-width="indicatorWidth" :indicator-bar-width="indicatorBarWidth" class="scroll-list">
  4. <view class="img-list">
  5. <view
  6. class="img-item"
  7. v-for="(item, index) in imageUrls"
  8. :key="index"
  9. @click.stop="handleImageClick(item, index)"
  10. :style="{
  11. marginRight: itemMargin + 'rpx',
  12. width: imageWidth + 'rpx',
  13. height: imageHeight + 'rpx'
  14. }"
  15. >
  16. <image
  17. :src="item"
  18. :mode="imgMode"
  19. :lazy-load="true"
  20. class="img-content"
  21. @error="handleImageError"
  22. />
  23. <view
  24. v-if="isShowDeleteIcon"
  25. class="delete-icon"
  26. @click.stop="handleDelete(index, item)"
  27. >
  28. <u-icon name="close" color="#fff" size="16"></u-icon>
  29. </view>
  30. </view>
  31. </view>
  32. </u-scroll-list>
  33. </view>
  34. </template>
  35. <script>
  36. export default {
  37. name: 'ImgsRowScroll',
  38. props: {
  39. images: {
  40. type: Array,
  41. default: () => []
  42. },
  43. // 从数组对象中读取图片地址的属性名
  44. keyName: {
  45. type: String,
  46. default: ''
  47. },
  48. // 是否启用预览功能
  49. previewEnabled: {
  50. type: Boolean,
  51. default: true
  52. },
  53. // 图片裁剪模式
  54. imgMode: {
  55. type: String,
  56. default: 'aspectFill'
  57. // - aspectFit :完整显示(保持比例,不裁剪)
  58. // - aspectFill :填充显示(裁剪图片填充容器)
  59. // - scaleToFill :拉伸显示(可能变形)
  60. },
  61. // 图片间距
  62. itemMargin: {
  63. type: Number,
  64. default: 16
  65. },
  66. // 图片宽度
  67. imageWidth: {
  68. type: Number,
  69. default: 200
  70. },
  71. // 图片高度
  72. imageHeight: {
  73. type: Number,
  74. default: 200
  75. },
  76. // 容器总宽度
  77. totalWidth: {
  78. type: Number,
  79. default: 0,
  80. // 说明:不传或传0时,默认100%宽度;传入正数时使用指定的rpx宽度
  81. // 例如:传600表示容器宽度为600rpx
  82. },
  83. // 是否显示指示器
  84. showIndicator: {
  85. type: Boolean,
  86. default: true
  87. },
  88. // 指示器宽度
  89. indicatorWidth: {
  90. type: Number,
  91. default: 50
  92. },
  93. // 指示器滑块宽度
  94. indicatorBarWidth: {
  95. type: Number,
  96. default: 30
  97. },
  98. // 是否显示删除图标
  99. isShowDeleteIcon: {
  100. type: Boolean,
  101. default: false
  102. }
  103. },
  104. computed: {
  105. // 处理图片地址数组
  106. imageUrls() {
  107. if (!this.images || this.images.length === 0) {
  108. return [];
  109. }
  110. // 如果没有指定keyName,直接返回数组内容
  111. if (!this.keyName) {
  112. return this.images;
  113. }
  114. // 如果指定了keyName,从对象中提取指定属性
  115. return this.images.map(item => {
  116. if (typeof item === 'object' && item !== null) {
  117. return item[this.keyName] || '';
  118. }
  119. return item;
  120. }).filter(url => url); // 过滤掉空值
  121. },
  122. // 容器宽度
  123. containerWidth() {
  124. if (this.totalWidth > 0) {
  125. return this.totalWidth + 'rpx';
  126. }
  127. return '100%';
  128. }
  129. },
  130. methods: {
  131. handleImageClick(item, index) {
  132. if (!this.previewEnabled) {
  133. return;
  134. }
  135. this.previewImage(item, index);
  136. },
  137. // 预览图片
  138. previewImage(current, currentIndex) {
  139. // 过滤掉无效的图片地址
  140. const validUrls = this.imageUrls.filter(url => url && url.trim());
  141. if (validUrls.length === 0) {
  142. uni.showToast({
  143. title: '没有可预览的图片',
  144. icon: 'none'
  145. });
  146. return;
  147. }
  148. uni.previewImage({
  149. current: current, // 当前显示图片的http链接
  150. urls: validUrls, // 需要预览的图片http链接列表
  151. success: () => {
  152. console.log('图片预览成功');
  153. },
  154. fail: (err) => {
  155. console.error('图片预览失败:', err);
  156. uni.showToast({
  157. title: '预览失败',
  158. icon: 'none'
  159. });
  160. }
  161. });
  162. },
  163. // 处理图片加载错误
  164. handleImageError(e) {
  165. console.error('图片加载失败:', e.detail.errMsg);
  166. },
  167. // 处理删除图片
  168. handleDelete(index, item) {
  169. const newImages = this.images.slice();
  170. newImages.splice(index, 1);
  171. this.$emit('deleteImgInfo', {
  172. delIndex: index,
  173. delUrl: item,
  174. newImages
  175. });
  176. }
  177. }
  178. };
  179. </script>
  180. <style lang="scss" scoped>
  181. @import './index.scss'
  182. </style>