zhangyaowen 4 bulan lalu
induk
melakukan
34f9983b2c
1 mengubah file dengan 389 tambahan dan 425 penghapusan
  1. 389 425
      sheep/ui/su-swiper/su-swiper.vue

+ 389 - 425
sheep/ui/su-swiper/su-swiper.vue

@@ -1,63 +1,27 @@
 <template>
   <view>
     <view class="ui-swiper" :class="[props.mode, props.bg, props.ui]">
-      <swiper
-        :circular="props.circular"
-        :current="state.cur"
-        :autoplay="props.autoplay && !state.videoPlaySataus"
-        :interval="props.interval"
-        :duration="props.duration"
-        @transition="transition"
-        @animationfinish="animationfinish"
-        :style="customStyle"
-        @change="swiperChange"
-      >
-        <swiper-item
-          class="swiper-item"
-          v-for="(item, index) in props.list"
-          :key="index"
-          :class="{ cur: state.cur == index }"
-          @tap="onSwiperItem(item)"
-        >
+      <swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay && !state.videoPlaySataus"
+        :interval="props.interval" :duration="props.duration" @transition="transition"
+        @animationfinish="animationfinish" :style="customStyle" @change="swiperChange">
+        <swiper-item class="swiper-item" v-for="(item, index) in props.list" :key="index"
+          :class="{ cur: state.cur == index }" @tap="onSwiperItem(item)">
           <view class="ui-swiper-main">
-            <image
-              v-if="item.type === 'image'"
-              class="swiper-image"
-              :mode="props.imageMode"
-              :src="item.src"
-              width="100%"
-              height="100%"
-              @load="onImgLoad"
-            ></image>
-            <su-video
-              v-else
-              :ref="(el) => (refs.videoRef[`video_${index}`] = el)"
-              :poster="sheep.$url.cdn(item.poster)"
-              :src="sheep.$url.cdn(item.src)"
-              :index="index"
-              :moveX="state.moveX"
-              :initialTime="item.currentTime || 0"
-              :height="seizeHeight"
-              @videoTimeupdate="videoTimeupdate"
-            ></su-video>
+            <image v-if="item.type === 'image'" class="swiper-image" :mode="props.imageMode" :src="item.src"
+              width="100%" height="100%" @load="onImgLoad"></image>
+            <su-video v-else :ref="(el) => (refs.videoRef[`video_${index}`] = el)" :poster="sheep.$url.cdn(item.poster)"
+              :src="sheep.$url.cdn(item.src)" :index="index" :moveX="state.moveX" :initialTime="item.currentTime || 0"
+              :height="seizeHeight" @videoTimeupdate="videoTimeupdate"></su-video>
           </view>
         </swiper-item>
       </swiper>
       <template v-if="!state.videoPlaySataus">
         <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
-          <view
-            class="line-box"
-            v-for="(item, index) in props.list"
-            :key="index"
-            :class="[state.cur == index ? 'cur' : '', props.dotCur]"
-          ></view>
+          <view class="line-box" v-for="(item, index) in props.list" :key="index"
+            :class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
         </view>
         <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
-          <view
-            class="ui-tag radius-lg"
-            :class="[props.dotCur]"
-            style="pointer-events: none; padding: 0 10rpx"
-          >
+          <view class="ui-tag radius-lg" :class="[props.dotCur]" style="pointer-events: none; padding: 0 10rpx">
             <view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ props.list.length }}</view>
           </view>
         </view>
@@ -67,436 +31,436 @@
 </template>
 
 <script setup>
-  /**
-   * 轮播组件
-   *
-   * @property {Boolean} circular = false  	- 是否采用衔接滑动,即播放到末尾后重新回到开头
-   * @property {Boolean} autoplay = true  	- 是否自动切换
-   * @property {Number} interval = 5000  		- 自动切换时间间隔
-   * @property {Number} duration = 500  		- 滑动动画时长,app-nvue不支持
-   * @property {Array} list = [] 				- 轮播数据
-   * @property {String} ui = ''  				- 样式class
-   * @property {String} mode  				- 模式
-   * @property {String} dotStyle  			- 指示点样式
-   * @property {String} dotCur= 'ui-BG-Main' 	- 当前指示点样式,默认主题色
-   * @property {String} bg  					- 背景
-   * @property {String} height = 300  		- 组件高度
-   * @property {String} imgHeight = 300   	- 图片高度
-   *
-   * @example list = [{url:'跳转路径',urlType:'跳转方式',type:'轮播类型',src:'轮播内容地址',poster:'视频必传'}]
-   */
-
-  import { reactive, computed } from 'vue';
-  import sheep from '@/sheep';
-  import { clone } from 'lodash-es';
-
-  // 数据
-  const state = reactive({
-    imgHeight: 0,
-    cur: 0,
-    moveX: 0,
-    videoPlaySataus: false,
-    heightList: [],
-  });
-
-  const refs = reactive({
-    videoRef: {},
-  });
-
-  // 接收参数
-
-  const props = defineProps({
-    circular: {
-      type: Boolean,
-      default: true,
-    },
-    autoplay: {
-      type: Boolean,
-      default: false,
-    },
-    interval: {
-      type: Number,
-      default: 3000,
-    },
-    duration: {
-      type: Number,
-      default: 500,
-    },
-    mode: {
-      type: String,
-      default: 'default',
-    },
-    imageMode: {
-      type: String,
-      default: 'scaleToFill',
-    },
-    list: {
-      type: Array,
-      default() {
-        return [];
-      },
-    },
-    dotStyle: {
-      type: String,
-      default: 'long', //default long tag
-    },
-    dotCur: {
-      type: String,
-      default: 'ss-bg-opactity-block',
-    },
-    bg: {
-      type: String,
-      default: 'bg-none',
-    },
-    height: {
-      type: Number,
-      default: 0,
-    },
-    imgHeight: {
-      type: Number,
-      default: 0,
-    },
-    imgTopRadius: {
-      type: Number,
-      default: 0,
-    },
-    imgBottomRadius: {
-      type: Number,
-      default: 0,
-    },
-    isPreview: {
-      type: Boolean,
-      default: false,
+/**
+ * 轮播组件
+ *
+ * @property {Boolean} circular = false  	- 是否采用衔接滑动,即播放到末尾后重新回到开头
+ * @property {Boolean} autoplay = true  	- 是否自动切换
+ * @property {Number} interval = 5000  		- 自动切换时间间隔
+ * @property {Number} duration = 500  		- 滑动动画时长,app-nvue不支持
+ * @property {Array} list = [] 				- 轮播数据
+ * @property {String} ui = ''  				- 样式class
+ * @property {String} mode  				- 模式
+ * @property {String} dotStyle  			- 指示点样式
+ * @property {String} dotCur= 'ui-BG-Main' 	- 当前指示点样式,默认主题色
+ * @property {String} bg  					- 背景
+ * @property {String} height = 300  		- 组件高度
+ * @property {String} imgHeight = 300   	- 图片高度
+ *
+ * @example list = [{url:'跳转路径',urlType:'跳转方式',type:'轮播类型',src:'轮播内容地址',poster:'视频必传'}]
+ */
+
+import { reactive, computed } from 'vue';
+import sheep from '@/sheep';
+import { clone } from 'lodash-es';
+
+// 数据
+const state = reactive({
+  imgHeight: 0,
+  cur: 0,
+  moveX: 0,
+  videoPlaySataus: false,
+  heightList: [],
+});
+
+const refs = reactive({
+  videoRef: {},
+});
+
+// 接收参数
+
+const props = defineProps({
+  circular: {
+    type: Boolean,
+    default: true,
+  },
+  autoplay: {
+    type: Boolean,
+    default: false,
+  },
+  interval: {
+    type: Number,
+    default: 3000,
+  },
+  duration: {
+    type: Number,
+    default: 500,
+  },
+  mode: {
+    type: String,
+    default: 'default',
+  },
+  imageMode: {
+    type: String,
+    default: 'scaleToFill',
+  },
+  list: {
+    type: Array,
+    default() {
+      return [];
     },
-    seizeHeight: {
-      type: Number,
-      default: 200,
-    },
-  });
+  },
+  dotStyle: {
+    type: String,
+    default: 'long', //default long tag
+  },
+  dotCur: {
+    type: String,
+    default: 'ss-bg-opactity-block',
+  },
+  bg: {
+    type: String,
+    default: 'bg-none',
+  },
+  height: {
+    type: Number,
+    default: 0,
+  },
+  imgHeight: {
+    type: Number,
+    default: 0,
+  },
+  imgTopRadius: {
+    type: Number,
+    default: 0,
+  },
+  imgBottomRadius: {
+    type: Number,
+    default: 0,
+  },
+  isPreview: {
+    type: Boolean,
+    default: false,
+  },
+  seizeHeight: {
+    type: Number,
+    default: 200,
+  },
+});
+
+// current 改变时会触发 change 事件
+const swiperChange = (e) => {
+  if (e.detail.source !== 'touch' && e.detail.source !== 'autoplay') return;
+  state.cur = e.detail.current;
+  state.videoPlaySataus = false;
+  if (props.list[state.cur].type === 'video') {
+    refs.videoRef[`video_${state.cur}`].pausePlay();
+  }
+};
+// 点击轮播组件
+const onSwiperItem = (item) => {
+  if (item.type === 'video') {
+    state.videoPlaySataus = true;
+  } else {
+    sheep.$router.go(item.url);
+    onPreview();
+  }
+};
 
-  // current 改变时会触发 change 事件
-  const swiperChange = (e) => {
-    if (e.detail.source !== 'touch' && e.detail.source !== 'autoplay') return;
-    state.cur = e.detail.current;
-    state.videoPlaySataus = false;
-    if (props.list[state.cur].type === 'video') {
-      refs.videoRef[`video_${state.cur}`].pausePlay();
-    }
-  };
-  // 点击轮播组件
-  const onSwiperItem = (item) => {
+const onPreview = () => {
+  if (!props.isPreview) return;
+  let previewImage = clone(props.list);
+  previewImage.forEach((item, index) => {
     if (item.type === 'video') {
-      state.videoPlaySataus = true;
-    } else {
-      sheep.$router.go(item.url);
-      onPreview();
+      previewImage.splice(index, 1);
     }
-  };
+  });
+  uni.previewImage({
+    urls:
+      previewImage.length < 1
+        ? [props.src]
+        : previewImage.reduce((pre, cur) => {
+          pre.push(cur.src);
+          return pre;
+        }, []),
+    current: state.cur,
+    // longPressActions: {
+    //   itemList: ['发送给朋友', '保存图片', '收藏'],
+    //   success: function (data) {
+    //     console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
+    //   },
+    //   fail: function (err) {
+    //     console.log(err.errMsg);
+    //   },
+    // },
+  });
+};
+//
+
+// swiper-item 的位置发生改变时会触发 transition
+const transition = (e) => {
+  // #ifdef APP-PLUS
+  state.moveX = e.detail.dx;
+  // #endif
+};
+
+// 动画结束时会触发 animationfinish
+const animationfinish = (e) => {
+  state.moveX = 0;
+};
+
+const videoTimeupdate = (e) => {
+  props.list[state.cur].currentTime = e.detail.currentTime;
+};
+
+// 自动计算高度
+const customStyle = computed(() => {
+  let height;
+
+  // 固定高度情况
+  if (props.height !== 0) {
+    height = props.height;
+  }
 
-  const onPreview = () => {
-    if (!props.isPreview) return;
-    let previewImage = clone(props.list);
-    previewImage.forEach((item, index) => {
-      if (item.type === 'video') {
-        previewImage.splice(index, 1);
-      }
-    });
-    uni.previewImage({
-      urls:
-        previewImage.length < 1
-          ? [props.src]
-          : previewImage.reduce((pre, cur) => {
-              pre.push(cur.src);
-              return pre;
-            }, []),
-      current: state.cur,
-      // longPressActions: {
-      //   itemList: ['发送给朋友', '保存图片', '收藏'],
-      //   success: function (data) {
-      //     console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
-      //   },
-      //   fail: function (err) {
-      //     console.log(err.errMsg);
-      //   },
-      // },
-    });
-  };
-  //
+  // 自动高度情况
+  if (props.height === 0) {
+    // 图片预加载占位高度
+    if (state.imgHeight !== 0) {
+      height = state.imgHeight;
+    } else if (props.seizeHeight !== 0) {
+      height = props.seizeHeight;
+    }
+  }
 
-  // swiper-item 的位置发生改变时会触发 transition
-  const transition = (e) => {
-    // #ifdef APP-PLUS
-    state.moveX = e.detail.dx;
-    // #endif
+  return {
+    height: height + 'rpx',
   };
+});
+
+// 计算轮播图片最大高度
+function onImgLoad(e) {
+  if (props.height === 0) {
+    let newHeight = (e.detail.height / e.detail.width) * 750;
+    if (state.imgHeight < newHeight) {
+      state.imgHeight = newHeight;
+    }
+  }
+}
+</script>
 
-  // 动画结束时会触发 animationfinish
-  const animationfinish = (e) => {
-    state.moveX = 0;
-  };
+<style lang="scss" scoped>
+.ui-swiper {
+  position: relative;
 
-  const videoTimeupdate = (e) => {
-    props.list[state.cur].currentTime = e.detail.currentTime;
-  };
+  .ui-swiper-main {
+    width: 100%;
+    height: 100%;
+  }
 
-  // 自动计算高度
-  const customStyle = computed(() => {
-    let height;
+  .ui-swiper-main .swiper-image {
+    width: 100%;
+    height: 100%;
+  }
 
-    // 固定高度情况
-    if (props.height !== 0) {
-      height = props.height;
-    }
+  .ui-swiper-dot {
+    position: absolute;
+    width: 100%;
+    bottom: 20rpx;
+    height: 30rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    &.default .line-box {
+      display: inline-flex;
+      border-radius: 50rpx;
+      width: 6px;
+      height: 6px;
+      border: 2px solid transparent;
+      margin: 0 10rpx;
+      opacity: 0.3;
+      position: relative;
+      justify-content: center;
+      align-items: center;
 
-    // 自动高度情况
-    if (props.height === 0) {
-      // 图片预加载占位高度
-      if (state.imgHeight !== 0) {
-        height = state.imgHeight;
-      } else if (props.seizeHeight !== 0) {
-        height = props.seizeHeight;
+      &.cur {
+        width: 8px;
+        height: 8px;
+        opacity: 1;
+        border: 0px solid transparent;
       }
-    }
 
-    return {
-      height: height + 'rpx',
-    };
-  });
-
-  // 计算轮播图片最大高度
-  function onImgLoad(e) {
-    if (props.height === 0) {
-      let newHeight = (e.detail.height / e.detail.width) * 750;
-      if (state.imgHeight < newHeight) {
-        state.imgHeight = newHeight;
+      &.cur::after {
+        content: '';
+        border-radius: 50rpx;
+        width: 4px;
+        height: 4px;
+        background-color: #fff;
       }
     }
-  }
-</script>
 
-<style lang="scss" scoped>
-  .ui-swiper {
-    position: relative;
-
-    .ui-swiper-main {
-      width: 100%;
-      height: 100%;
-    }
+    &.long .line-box {
+      display: inline-block;
+      border-radius: 100rpx;
+      width: 6px;
+      height: 6px;
+      margin: 0 10rpx;
+      opacity: 0.3;
+      position: relative;
+
+      &.cur {
+        width: 24rpx;
+        opacity: 1;
+      }
 
-    .ui-swiper-main .swiper-image {
-      width: 100%;
-      height: 100%;
+      &.cur::after {}
     }
 
-    .ui-swiper-dot {
-      position: absolute;
-      width: 100%;
+    &.line {
       bottom: 20rpx;
-      height: 30rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-
-      &.default .line-box {
-        display: inline-flex;
-        border-radius: 50rpx;
-        width: 6px;
-        height: 6px;
-        border: 2px solid transparent;
-        margin: 0 10rpx;
-        opacity: 0.3;
-        position: relative;
-        justify-content: center;
-        align-items: center;
-
-        &.cur {
-          width: 8px;
-          height: 8px;
-          opacity: 1;
-          border: 0px solid transparent;
-        }
 
-        &.cur::after {
-          content: '';
-          border-radius: 50rpx;
-          width: 4px;
-          height: 4px;
-          background-color: #fff;
-        }
-      }
-
-      &.long .line-box {
+      .line-box {
         display: inline-block;
-        border-radius: 100rpx;
-        width: 6px;
-        height: 6px;
-        margin: 0 10rpx;
+        width: 30px;
+        height: 3px;
         opacity: 0.3;
         position: relative;
 
         &.cur {
-          width: 24rpx;
           opacity: 1;
         }
-
-        &.cur::after {
-        }
-      }
-
-      &.line {
-        bottom: 20rpx;
-
-        .line-box {
-          display: inline-block;
-          width: 30px;
-          height: 3px;
-          opacity: 0.3;
-          position: relative;
-
-          &.cur {
-            opacity: 1;
-          }
-        }
-      }
-
-      &.tag {
-        justify-content: flex-end;
-        position: absolute;
-        bottom: 20rpx;
-        right: 20rpx;
       }
     }
 
-    &.card {
-      .swiper-item {
-        width: 610rpx !important;
-        left: 70rpx;
-        box-sizing: border-box;
-        padding: 20rpx 0rpx 60rpx;
-        overflow: initial;
-      }
+    &.tag {
+      justify-content: flex-end;
+      position: absolute;
+      bottom: 20rpx;
+      right: 20rpx;
+    }
+  }
 
-      .swiper-item .ui-swiper-main {
-        width: 100%;
-        display: block;
-        height: 100%;
-        transform: scale(0.9);
-        transition: all 0.2s ease-in 0s;
-        position: relative;
-        background-size: cover;
+  &.card {
+    .swiper-item {
+      width: 100% !important;
+      // left: 70rpx;
+      box-sizing: border-box;
+      // padding: 20rpx 0rpx 60rpx;
+      padding: 0 10rpx;
+      overflow: initial;
+    }
 
-        .swiper-image {
-          height: 100%;
-        }
-      }
+    .swiper-item .ui-swiper-main {
+      width: 100%;
+      display: block;
+      height: 100%;
+      transform: scale(0.9);
+      transition: all 0.2s ease-in 0s;
+      position: relative;
+      background-size: cover;
 
-      .swiper-item .ui-swiper-main::before {
-        content: '';
-        display: block;
-        background: inherit;
-        filter: blur(5px);
-        position: absolute;
-        width: 100%;
+      .swiper-image {
         height: 100%;
-        top: 10rpx;
-        left: 10rpx;
-        z-index: -1;
-        opacity: 0.3;
-        transform-origin: 0 0;
-        transform: scale(1, 1);
       }
+    }
 
-      .swiper-item.cur .ui-swiper-main {
-        transform: scale(1);
-        transition: all 0.2s ease-in 0s;
-      }
+    .swiper-item .ui-swiper-main::before {
+      content: '';
+      display: block;
+      background: inherit;
+      filter: blur(5px);
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      top: 10rpx;
+      left: 10rpx;
+      z-index: -1;
+      opacity: 0.3;
+      transform-origin: 0 0;
+      transform: scale(1, 1);
+    }
 
-      .ui-swiper-dot.tag {
-        position: absolute;
-        bottom: 85rpx;
-        right: 75rpx;
-      }
+    .swiper-item.cur .ui-swiper-main {
+      transform: scale(1);
+      transition: all 0.2s ease-in 0s;
     }
 
-    &.hotelCard {
-      .swiper-item {
-        width: 650rpx !important;
-        left: 30rpx;
-        box-sizing: border-box;
-        padding: 0rpx 0rpx 50rpx;
-        overflow: initial;
-      }
+    .ui-swiper-dot.tag {
+      position: absolute;
+      bottom: 15rpx;
+      right: 15rpx;
+    }
+  }
 
-      .swiper-item .ui-swiper-main {
-        width: 100%;
-        display: block;
-        height: 100%;
-        transform: scale(0.9);
-        opacity: 0.8;
-        transition: all 0.2s ease-in 0s;
-        position: relative;
-        background-size: cover;
+  &.hotelCard {
+    .swiper-item {
+      width: 650rpx !important;
+      left: 30rpx;
+      box-sizing: border-box;
+      padding: 0rpx 0rpx 50rpx;
+      overflow: initial;
+    }
 
-        .swiper-image {
-          width: 100%;
-          height: 400rpx;
-        }
-      }
+    .swiper-item .ui-swiper-main {
+      width: 100%;
+      display: block;
+      height: 100%;
+      transform: scale(0.9);
+      opacity: 0.8;
+      transition: all 0.2s ease-in 0s;
+      position: relative;
+      background-size: cover;
 
-      .swiper-item .ui-swiper-main::before {
-        content: '';
-        display: block;
-        background: inherit;
-        filter: blur(5px);
-        position: absolute;
+      .swiper-image {
         width: 100%;
-        height: 100%;
-        top: 10rpx;
-        left: 10rpx;
-        z-index: -1;
-        opacity: 0.3;
-        transform-origin: 0 0;
-        transform: scale(1, 1);
+        height: 400rpx;
       }
+    }
 
-      .swiper-item.cur .ui-swiper-main {
-        transform: scale(1);
-        transition: all 0.2s ease-in 0s;
-        opacity: 1;
-      }
+    .swiper-item .ui-swiper-main::before {
+      content: '';
+      display: block;
+      background: inherit;
+      filter: blur(5px);
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      top: 10rpx;
+      left: 10rpx;
+      z-index: -1;
+      opacity: 0.3;
+      transform-origin: 0 0;
+      transform: scale(1, 1);
+    }
 
-      .ui-swiper-dot {
-        display: none;
-      }
+    .swiper-item.cur .ui-swiper-main {
+      transform: scale(1);
+      transition: all 0.2s ease-in 0s;
+      opacity: 1;
     }
 
-    &.hotelDetail {
-      .swiper-item {
-        width: 690rpx !important;
-        left: 30rpx;
-        box-sizing: border-box;
-        padding: 20rpx 0rpx;
-        overflow: initial;
-      }
+    .ui-swiper-dot {
+      display: none;
+    }
+  }
 
-      .swiper-item .ui-swiper-main {
-        width: 100%;
-        display: block;
-        height: 100%;
-        transform: scale(0.96);
-        transition: all 0.2s ease-in 0s;
-        position: relative;
-        background-size: cover;
+  &.hotelDetail {
+    .swiper-item {
+      width: 690rpx !important;
+      left: 30rpx;
+      box-sizing: border-box;
+      padding: 20rpx 0rpx;
+      overflow: initial;
+    }
 
-        .swiper-image {
-          height: 100%;
-        }
-      }
+    .swiper-item .ui-swiper-main {
+      width: 100%;
+      display: block;
+      height: 100%;
+      transform: scale(0.96);
+      transition: all 0.2s ease-in 0s;
+      position: relative;
+      background-size: cover;
 
-      .swiper-item.cur .ui-swiper-main {
-        transform: scale(0.96);
-        transition: all 0.2s ease-in 0s;
+      .swiper-image {
+        height: 100%;
       }
     }
+
+    .swiper-item.cur .ui-swiper-main {
+      transform: scale(0.96);
+      transition: all 0.2s ease-in 0s;
+    }
   }
+}
 </style>