| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 | 
							- <template>
 
-   <view
 
-       class="u-rate"
 
-       :id="elId"
 
-       ref="u-rate"
 
-       :style="[$u.addStyle(customStyle)]"
 
-   >
 
-     <view
 
-         class="u-rate__content"
 
-         @touchmove.stop="touchMove"
 
-         @touchend.stop="touchEnd"
 
-     >
 
-       <view
 
-           class="u-rate__content__item"
 
-           v-for="(item, index) in Number(count)"
 
-           :key="index"
 
-           :class="[elClass]"
 
-       >
 
-         <view
 
-             class="u-rate__content__item__icon-wrap"
 
-             ref="u-rate__content__item__icon-wrap"
 
-             @tap.stop="clickHandler($event, index + 1)"
 
-         >
 
-           <u-icon
 
-               :name="
 
-                             Math.floor(activeIndex) > index
 
-                                 ? activeIcon
 
-                                 : inactiveIcon
 
-                         "
 
-               :color="
 
-                             disabled
 
-                                 ? '#c8c9cc'
 
-                                 : Math.floor(activeIndex) > index
 
-                                 ? activeColor
 
-                                 : inactiveColor
 
-                         "
 
-               :custom-style="{
 
-                             padding: `0 ${$u.addUnit(gutter / 2)}`,
 
-                         }"
 
-               :size="size"
 
-           ></u-icon>
 
-         </view>
 
-         <view
 
-             v-if="allowHalf"
 
-             @tap.stop="clickHandler($event, index + 1)"
 
-             class="u-rate__content__item__icon-wrap u-rate__content__item__icon-wrap--half"
 
-             :style="[{
 
-                         width: $u.addUnit(rateWidth / 2),
 
-                     }]"
 
-             ref="u-rate__content__item__icon-wrap"
 
-         >
 
-           <u-icon
 
-               :name="
 
-                             Math.ceil(activeIndex) > index
 
-                                 ? activeIcon
 
-                                 : inactiveIcon
 
-                         "
 
-               :color="
 
-                             disabled
 
-                                 ? '#c8c9cc'
 
-                                 : Math.ceil(activeIndex) > index
 
-                                 ? activeColor
 
-                                 : inactiveColor
 
-                         "
 
-               :custom-style="{
 
-                             padding: `0 ${$u.addUnit(gutter / 2)}`
 
-                         }"
 
-               :size="size"
 
-           ></u-icon>
 
-         </view>
 
-       </view>
 
-     </view>
 
-   </view>
 
- </template>
 
- <script>
 
- import props from './props.js';
 
- // #ifdef APP-NVUE
 
- const dom = weex.requireModule("dom");
 
- // #endif
 
- /**
 
-  * rate 评分
 
-  * @description 该组件一般用于满意度调查,星型评分的场景
 
-  * @tutorial https://www.uviewui.com/components/rate.html
 
-  * @property {String | Number}  value      用于v-model双向绑定选中的星星数量 (默认 1 )
 
-  * @property {String | Number}  count      最多可选的星星数量 (默认 5 )
 
-  * @property {Boolean}      disabled    是否禁止用户操作 (默认 false )
 
-  * @property {String | Number}  size      星星的大小,单位px (默认 18 )
 
-  * @property {String}      inactiveColor  未选中星星的颜色 (默认 '#b2b2b2' )
 
-  * @property {String}      activeColor    选中的星星颜色 (默认 '#FA3534' )
 
-  * @property {String | Number}  gutter      星星之间的距离 (默认 4 )
 
-  * @property {String | Number}  minCount    最少选中星星的个数 (默认 1 )
 
-  * @property {Boolean}      allowHalf    是否允许半星选择 (默认 false )
 
-  * @property {String}      activeIcon    选中时的图标名,只能为uView的内置图标 (默认 'star-fill' )
 
-  * @property {String}      inactiveIcon  未选中时的图标名,只能为uView的内置图标 (默认 'star' )
 
-  * @property {Boolean}      touchable    是否可以通过滑动手势选择评分 (默认 'true' )
 
-  * @property {Object}      customStyle    组件的样式,对象形式
 
-  * @event {Function} change 选中的星星发生变化时触发
 
-  * @example <u-rate :count="count" :value="2"></u-rate>
 
-  */
 
- export default {
 
-   name: "u-rate",
 
-   mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
 
-   data() {
 
-     return {
 
-       // 生成一个唯一id,否则一个页面多个评分组件,会造成冲突
 
-       elId: uni.$u.guid(),
 
-       elClass: uni.$u.guid(),
 
-       rateBoxLeft: 0, // 评分盒子左边到屏幕左边的距离,用于滑动选择时计算距离
 
-       activeIndex: this.value,
 
-       rateWidth: 0, // 每个星星的宽度
 
-       // 标识是否正在滑动,由于iOS事件上touch比click先触发,导致快速滑动结束后,接着触发click,导致事件混乱而出错
 
-       moving: false,
 
-     };
 
-   },
 
-   watch: {
 
-     value(val) {
 
-       this.activeIndex = val;
 
-     },
 
-     activeIndex: 'emitEvent'
 
-   },
 
-   methods: {
 
-     init() {
 
-       uni.$u.sleep().then(() => {
 
-         this.getRateItemRect();
 
-         this.getRateIconWrapRect();
 
-       })
 
-     },
 
-     // 获取评分组件盒子的布局信息
 
-     async getRateItemRect() {
 
-       await uni.$u.sleep();
 
-       // uView封装的获取节点的方法,详见文档
 
-       // #ifndef APP-NVUE
 
-       this.$uGetRect("#" + this.elId).then((res) => {
 
-         this.rateBoxLeft = res.left;
 
-       });
 
-       // #endif
 
-       // #ifdef APP-NVUE
 
-       dom.getComponentRect(this.$refs["u-rate"], (res) => {
 
-         this.rateBoxLeft = res.size.left;
 
-       });
 
-       // #endif
 
-     },
 
-     // 获取单个星星的尺寸
 
-     getRateIconWrapRect() {
 
-       // uView封装的获取节点的方法,详见文档
 
-       // #ifndef APP-NVUE
 
-       this.$uGetRect("." + this.elClass).then((res) => {
 
-         this.rateWidth = res.width;
 
-       });
 
-       // #endif
 
-       // #ifdef APP-NVUE
 
-       dom.getComponentRect(
 
-           this.$refs["u-rate__content__item__icon-wrap"][0],
 
-           (res) => {
 
-             this.rateWidth = res.size.width;
 
-           }
 
-       );
 
-       // #endif
 
-     },
 
-     // 手指滑动
 
-     touchMove(e) {
 
-       // 如果禁止通过手动滑动选择,返回
 
-       if (!this.touchable) {
 
-         return;
 
-       }
 
-       this.preventEvent(e);
 
-       const x = e.changedTouches[0].pageX;
 
-       this.getActiveIndex(x);
 
-     },
 
-     // 停止滑动
 
-     touchEnd(e) {
 
-       // 如果禁止通过手动滑动选择,返回
 
-       if (!this.touchable) {
 
-         return;
 
-       }
 
-       this.preventEvent(e);
 
-       const x = e.changedTouches[0].pageX;
 
-       this.getActiveIndex(x);
 
-     },
 
-     // 通过点击,直接选中
 
-     clickHandler(e, index) {
 
-       // ios上,moving状态取消事件触发
 
-       if (uni.$u.os() === "ios" && this.moving) {
 
-         return;
 
-       }
 
-       this.preventEvent(e);
 
-       let x = 0;
 
-       // 点击时,在nvue上,无法获得点击的坐标,所以无法实现点击半星选择
 
-       // #ifndef APP-NVUE
 
-       x = e.changedTouches[0].pageX;
 
-       // #endif
 
-       // #ifdef APP-NVUE
 
-       // nvue下,无法通过点击获得坐标信息,这里通过元素的位置尺寸值模拟坐标
 
-       x = index * this.rateWidth + this.rateBoxLeft;
 
-       // #endif
 
-       this.getActiveIndex(x, true);
 
-     },
 
-     // 发出事件
 
-     emitEvent() {
 
-       // 发出change事件
 
-       this.$emit("change", this.activeIndex);
 
-       // 同时修改双向绑定的value的值
 
-       this.$emit("input", this.activeIndex);
 
-     },
 
-     // 获取当前激活的评分图标
 
-     getActiveIndex(x, isClick = false) {
 
-       if (this.disabled) {
 
-         return;
 
-       }
 
-       // 判断当前操作的点的x坐标值,是否在允许的边界范围内
 
-       const allRateWidth = this.rateWidth * this.count + this.rateBoxLeft;
 
-       // 如果小于第一个图标的左边界,设置为最小值,如果大于所有图标的宽度,则设置为最大值
 
-       x = uni.$u.range(this.rateBoxLeft, allRateWidth, x) - this.rateBoxLeft
 
-       // 滑动点相对于评分盒子左边的距离
 
-       const distance = x;
 
-       // 滑动的距离,相当于多少颗星星
 
-       let index;
 
-       // 判断是否允许半星
 
-       if (this.allowHalf) {
 
-         index = Math.floor(distance / this.rateWidth);
 
-         // 取余,判断小数的区间范围
 
-         const decimal = distance % this.rateWidth;
 
-         if (decimal <= this.rateWidth / 2 && decimal > 0) {
 
-           index += 0.5;
 
-         } else if (decimal > this.rateWidth / 2) {
 
-           index++;
 
-         }
 
-       } else {
 
-         index = Math.floor(distance / this.rateWidth);
 
-         // 取余,判断小数的区间范围
 
-         const decimal = distance % this.rateWidth;
 
-         // 非半星时,只有超过了图标的一半距离,才认为是选择了这颗星
 
-         if (isClick) {
 
-           if (decimal > 0) index++;
 
-         } else {
 
-           if (decimal > this.rateWidth / 2) index++;
 
-         }
 
-       }
 
-       this.activeIndex = Math.min(index, this.count);
 
-       // 对最少颗星星的限制
 
-       if (this.activeIndex < this.minCount) {
 
-         this.activeIndex = this.minCount;
 
-       }
 
-       // 设置延时为了让click事件在touchmove之前触发
 
-       setTimeout(() => {
 
-         this.moving = true;
 
-       }, 10);
 
-       // 一定时间后,取消标识为移动中状态,是为了让click事件无效
 
-       setTimeout(() => {
 
-         this.moving = false;
 
-       }, 10);
 
-     },
 
-   },
 
-   mounted() {
 
-     this.init();
 
-   },
 
- };
 
- </script>
 
- <style lang="scss" scoped>
 
- @import "../../libs/css/components.scss";
 
- $u-rate-margin: 0 !default;
 
- $u-rate-padding: 0 !default;
 
- $u-rate-item-icon-wrap-half-top: 0 !default;
 
- $u-rate-item-icon-wrap-half-left: 0 !default;
 
- .u-rate {
 
-   @include flex;
 
-   align-items: center;
 
-   margin: $u-rate-margin;
 
-   padding: $u-rate-padding;
 
-   /* #ifndef APP-NVUE */
 
-   touch-action: none;
 
-   /* #endif */
 
-   &__content {
 
-     @include flex;
 
-     &__item {
 
-       position: relative;
 
-       &__icon-wrap {
 
-         &--half {
 
-           position: absolute;
 
-           overflow: hidden;
 
-           top: $u-rate-item-icon-wrap-half-top;
 
-           left: $u-rate-item-icon-wrap-half-left;
 
-         }
 
-       }
 
-     }
 
-   }
 
- }
 
- .u-icon {
 
-   /* #ifndef APP-NVUE */
 
-   box-sizing: border-box;
 
-   /* #endif */
 
- }
 
- </style>
 
 
  |