vuejs2-7评价页面
1 src/components/ratings/ratings.vue
<template> <div class="ratings" ref="ratings"> <div class="rating-content"> <div class="overview"> <div class="overview-left"> <h2 class="scoer">{{seller.score}}</h2> <div class="title">综合评分</div> <div class="rank">高于周边商家{{seller.rankRate}}%</div> </div> <div class="overview-right"> <p class="score-wrapper"> <span class="title">服务态度</span> <star :size="36" :score="seller.serviceScore"></star> <span class="score">{{seller.serviceScore}}</span> </p> <p class="score-wrapper"> <span class="title">商品评分</span> <star :size="36" :score="seller.foodScore"></star> <span class="score">{{seller.foodScore}}</span> </p> <p class="delivery-wrapper"> <span class="title">送达时间</span> <span class="delivery">{{seller.deliveryTime}}</span> <span class="time">分钟</span> </p> </div> </div> <ratingselect @select="selectRating" @toggle="toggleContent" :selectType="selectType" :onlyContent="onlyContent" :desc="desc" :ratings="ratings"></ratingselect> <!--评论列表--> <div class="rating-wrapper"> <ul> <li v-for="rating in ratings" class="rating-item" v-show="needShow(rating.rateType,rating.text)"> <div class="avatar"><img :src="rating.avatar" alt="" width="28" height="28"></div> <div class="content"> <h2 class="name">{{rating.username}}</h2> <div class="star-wrapper"> <star :size="24" :score="rating.score"></star> <span class="delivery" v-show="rating.deliveryTime">{{rating.deliveryTime}}分钟到达</span> </div> <p class="text">{{rating.text}}</p> <div class="recommend" v-show="rating.recommend && rating.recommend.length"> <span class="icon-thumb_up"></span> <span v-for="item in rating.recommend" class="item">{{item}}</span> </div> <div class="time">{{rating.rateTime | formatDate}}</div> </div> </li> </ul> </div> </div> </div> </template> <script type="text/ecmascript-6"> import star from 'components/star/star'; import BScroll from 'better-scroll'; import split from 'components/split/split'; import ratingselect from 'components/ratingselect/ratingselect'; import {formatDate} from 'common/js/date'; const ALL = 2; const ERR_OK = 0; export default{ props: { seller: { // 获取路由组件(app.vue)传递过来的数据 type: Object } }, data() { return { ratings: [], selectType: ALL, onlyContent: true, desc: { all: '全部', positive: '满意', negative: '不满意' } }; }, created() { this.$http.get('/api/ratings').then((res) => { res = res.body; if (res.errno === ERR_OK) { this.ratings = res.data; this.$nextTick(() => { this.scroll = new BScroll(this.$refs.ratings, { click: true }); }); }; }); }, filters: { formatDate(time) { let date = new Date(time); return formatDate(date, 'yyyy-MM-dd hh:mm'); } }, methods: { needShow(type, text) { // 对ratingselect.vue组件的改变做处理 if (this.onlyContent && !text) { // 只有内容没有文本时 return false; }; if (this.selectType === ALL) { return true; } else { return type === this.selectType; } }, selectRating(type) { // this.selectType = type; // ratingselect.vue改变父组件的值 this.$nextTick(() => { this.scroll.refresh(); // 解决去掉勾选后bs可拖动范围问题 }); }, toggleContent() { this.onlyContent = !this.onlyContent; this.$nextTick(() => { this.scroll.refresh(); }); } }, components: { star: star, split: split, ratingselect: ratingselect } }; </script> <style lang="stylus" rel="stylesheet/stylus"> .ratings position:absolute top:174px bottom:0px left:0 width:100% overflow:hidden .overview display:flex padding:18px 0 .overview-left flex:0 0 137px width:137px padding:6px 0 border-right:1px solid rgba(7,17,27,0.1) text-align:center /*@media only screen add ( max-width: 320px ) flex:0 0 120px width:120px*/ .score font-size:24px color:rgb(255,153,0) line-height:28px .title font-size:12px color:rgb(7,17,27) line-height:12px font-weight:700 margin-top:6px margin-bottom:8px .rank font-size:10px color:rgb(147,153,159) line-height:10px .overview-right flex:1 padding:6px 19px 0 /*@media only screen add ( max-width: 320px ) padding-left:6px*/ .score-wrapper margin-bottom:8px font-size:0 .title font-size:12px color:rgb(7,17,27) vertical-align:top line-height:18px .star display:inline-block margin:0 12px vertical-align:top .score display:inline-block font-size:12px vertical-align:top color:rgb(255,153,0) line-height:18px .delivery-wrapper font-size:0 .title font-size:12px color:rgb(7,17,27) line-height:18px .delivery font-size:12px color:rgb(147,153,159) margin-left:12px .time display:inline-block font-size:12px color:rgb(147,153,159) .rating-wrapper .rating-item border-bottom:1px solid rgba(7,17,27,0.1) display:flex font-size:0 margin:0 16px padding:16px 0 .avatar flex:0 0 28px width:28px height:28px margin-right:12px img border-radius:50% .content flex:1 position:relative .name line-height:12px font-size:10px color:rgb(7,17,27) margin-bottom:4px .star-wrapper font-size:0 margin-bottom:6px .star display:inline-block margin-right:6px viertical-align:top .delivery display:inline-block viertical-align:top line-height:12px font-size:10px color:rgb(147,153,159) .text font-size:12px color:rgb(147,153,159) font-weight:200 margin-bottom:8px .recommend font-size:0px line-height:16px .icon-thumb_up display:inline-block margin:0 8px 4px 0 font-size:9px color:rgb(0,160,220) .item display:inline-block font-size:9px padding:0 6px border:1px solid rgba(7,17,27,0.1) border-radius:1px background-color:#fff margin-right:8px .time position:absolute top:0 right:0 font-size:10px font-weight:200 color:rgb(147,153,159) line-height:12px </style>
2 src/components/ratingselect/ratingselect.vue
<template> <div class="ratingselect"> <div class="rating-type border-1px"> <span class="block positive" :class="{active:selectType===2}" @click="select(2,$event)">{{desc.all}}<span class="count">{{ratings.length}}</span></span> <span class="block positive" :class="{active:selectType===0}" @click="select(0,$event)">{{desc.positive}}<span class="count">{{positives.length}}</span></span> <span class="block negative" :class="{active:selectType===1}" @click="select(1,$event)">{{desc.negative}}<span class="count">{{negatives.length}}</span></span> </div> <div class="switch" :class="{on:onlyContent}" @click="toggleContent"> <i class="icon-check_circle"></i> <span class="text">只看有评价的内容</span> </div> </div> </template> <script type="text/ecmascript-6"> const POSITIVE = 0; const NEGATIVE = 1; const ALL = 2; export default { props: { ratings: { type: Array, default() { return []; } }, selectType: { // 接收 ratings.vue传递的 :selectType="selectType" type: Number, default: ALL }, onlyContent: { // 接收 ratings.vue传递的 :onlyContent="onlyContent" type: Boolean, default: false // 默认可以看到所有评论 }, desc: { type: Object, default() { // 默认文字显示 return { all: '全部', positive: '满意', negative: '不满意' }; } } }, methods: { select(type, ev) { // 选择全部 满意 不满意 if (!ev._constructed) { // 使用了BS return; }; this.$emit('select', type); // 将selectType变化的值交给父组件ratings.vue处理(改变selectType的值) }, toggleContent(ev) { // 点击了只看有评价的内容 if (!ev._constructed) { // 使用了BS return; }; this.$emit('toggle'); // } }, computed: { positives() { // 推荐数量 return this.ratings.filter((rating) => { return rating.rateType === POSITIVE; }); }, negatives() { // 不满意数量 return this.ratings.filter((rating) => { return rating.rateType === NEGATIVE; }); } } }; </script> <style lang="stylus" rel="stylesheet/stylus"> @import "../../common/stylus/mixin.styl" .ratingselect .rating-type padding:18px 0 margin:0 18px border-1px(rgba(7,17,27,0.1)) font-size:0px .block display:inline-block padding:8px 12px border-radius:1px margin-right:8px color:rgb(77,85,93) font-size:12px line-height:16px &.active color:#fff .count font-size:8px margin-left:2px &.positive background: rgba(0,160,220,0.2) &.active background:rgb(0,160,220) &.negative background-color:rgba(77,85,93,0.2) &.active background-color:rgb(77,85,93) .switch padding:12px 18px line-height:24px border-bottom:1px solid rgba(7,17,27,0.1) color:rgb(147,153,159) font-size:0 &.on .icon-check_circle color:#00c850 .icon-check_circle display:inline-block; vertical-align:middle font-size:24px margin-right: 4px .text font-size:12px display:inline-block vertical-align:middle </style>
3 简单图解