仿美团pc,koa+ssr(六)

一,地点详情页

product.vue组件,点击h3标题,跳转到对应地点的详情detail路径

 

<template>
  <dl class="s-item">
    <dt>
      <img
        :src="meta.img"
        alt="商品图片">
    </dt>
    <dd>
      <h3><nuxt-link :to="{path:'detail',query:{keyword:meta.name,type:meta.module}}">{{ meta.name }}</nuxt-link></h3>
      <el-rate
        v-model="meta.rate"
        :colors="['#ff9900', '#ff9900', '#FF9900']"
        disabled/>
      <span
        v-if="meta.rate>4"
        class="s-item-comment">很好</span><span
          v-else-if="meta.rate>3"
          class="s-item-comment">一般</span><span
            v-else
            class="s-item-comment">很差</span>
      <span class="s-item-value">{{ meta.rate }}分</span>
      <span class="s-item-comment-total">{{ meta.comment }}人评论</span>
      <p>
        <span class="s-item-type">{{ meta.type }}</span>
        <span class="s-item-addr">{{ meta.addr }}</span>
      </p>
      <p>
        <em class="s-item-price">¥{{ meta.price }}起</em>
        <b>{{ meta.status }}</b>
      </p>
      <ul>
        <!-- <li>
          <span class="detail-type">门票</span>{{meta.ticket}}
        </li>
        <li>
          <span class="detail-type">跟团</span>{{meta.group}}
        </li> -->
        <li v-if="meta.scene&&meta.scene.length">
          <span class="detail-type">景酒</span>{{ meta.scene }}
        </li>
        <li v-else>
          <span class="detail-type">景酒</span>暂无描述
        </li>
      </ul>
    </dd>
  </dl>
</template>

<script>
export default {
  props: {
    meta: {
      type:Object,
      default(){
        return {}
      }
    }
  }
}
</script>

pages-->新建detail.vue,引入

crumbs.vue面包屑组件,
summary.vue地点详情,
list.vue,商家团购和优惠
<template>
  <div class="page-detail">
    <el-row>
      <el-col :span="24">
        <crumbs
          :keyword="keyword"
          :type="type"/>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <summa :meta="product"/>
      </el-col>
    </el-row>
    <el-row class="m-title">
      <el-col :span="24">
        <h3>商家团购及优惠</h3>
      </el-col>
    </el-row>
    <el-row v-if="canOrder || !login">
      <el-col :span="24">
        <!-- 登录状态结构 -->
        <list
          v-if="login"
          :list="list"/>
          <!-- 未登录状态结构 -->
        <div
          v-else
          class="deal-need-login">
          <img
            src="//p0.meituan.net/codeman/56a7d5abcb5ce3d90fc91195e5b5856911194.png"
            alt="登录查看">
          <span>请登录后查看详细团购优惠</span>
          <el-button
            type="primary"
            round>
            <a href="/login">立即登录</a>
          </el-button>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import Crumbs from '@/components/detail/crumbs.vue';
import Summa from '@/components/detail/summary.vue'
import List from '@/components/detail/list.vue'
export default {
  components:{
    Crumbs,
    Summa,
    List
  },
  computed:{
    canOrder:function(){
      // 过滤图片数据,有的数据图片为空
      return this.list.filter(item=>item.photos.length).length
    }
  },
  // 通过ssr获取数据
  async asyncData(ctx){
    let {keyword,type}=ctx.query;
    let {status,data:{product,more:list,login}}=await ctx.$axios.get('/search/products',{
      params:{
        keyword,
        type,
        city:ctx.store.state.geo.position.city
      }
    })
    if(status===200){
      return {
        keyword,
        product,
        type,
        list,
        login
      }
    }else{
      return {
        keyword,
        product:{},
        type,
        list:[],
        login:false
      }
    }
  }
}
</script>

<style lang="scss">
  @import "@/assets/css/detail/index.scss";
</style>

crumbs.vue面包屑组件,

<template>
  <div class="m-crumbs">
    <el-breadcrumb separator=">">
      <el-breadcrumb-item :to="{ path: '/' }">{{ $store.state.geo.position.city.replace('','') }}美团</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/' }">{{ $store.state.geo.position.city.replace('','') }}{{ type }}</el-breadcrumb-item>
      <el-breadcrumb-item><a href="/">{{ $store.state.geo.position.city.replace('','') }}{{ decodeURIComponent(keyword) }}</a></el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script>
export default {
  props: {
    keyword: {
      type:String,
      default:''
    },
    type: {
      type:String,
      default:''
    }
  }
}
</script>

summary.vue地点详情,

el-rate评分组件,el-carousel走马灯组件,element-ui

<template>
  <dl class="m-sum-card">
    <dt>
      <h1>{{ meta.name }}</h1>
      <el-rate
        v-model="rate"
        disabled />
      <span>{{ Number(meta.biz_ext.rating)||rate }}分</span>
      <span>人均¥{{ Number(meta.biz_ext.cost) }}</span>
      <ul>
        <li @click="openMap(meta.location)">地址:{{ meta.address }}</li>
        <li>电话:{{ meta.tel }}</li>
      </ul>
    </dt>
    <dd>
      <el-carousel
        height="214px"
        indicator-position="none">
        <el-carousel-item
          v-for="(item,idx) in meta.photos"
          :key="idx">
          <h3><img
            :src="item.url"
            alt="item.title"
            width="100%"
            height="100%"></h3>
        </el-carousel-item>
      </el-carousel>
    </dd>
  </dl>
</template>

<script>
export default {
  props: {
    meta: {
      type:Object,
      default:()=>{
        return {}
      }
    }
  },
  data() {
    return {
      sale: 70 + Math.floor(Math.random() * 300)
    }
  },
  computed: {
    rate: function () {
      return Number(this.meta.biz_ext.rating) || Math.floor(Math.random() * 5)
    }
  },
  methods: {
    openMap: function (location) {

    }
  }
}
</script>

list.vue,商家团购和优惠

<template lang="html">
  <div class="m-detail-list">
    <ul>
      <li>{{ list.filter(item=>item.photos.length).length }}款套餐</li>
      <item
        v-for="(item,idx) in list"
        :key="idx"
        :meta="item" />
    </ul>
  </div>
</template>

<script>
import Item from './item.vue'
export default {
  components: {
    Item
  },
  props: {
    list: {
      type:Array,
      default:()=>{
        return []
      }
    }
  },
}
</script>

item.vue组件

<template>
  <li
    v-if="meta.photos.length"
    class="m-detail-item">
    <dl class="section">
      <dd>
        <img
          :src="meta.photos[0].url"
          :alt="meta.photos[0].title">
      </dd>
      <dd>
        <h4>{{ meta.name }}</h4>
        <p>
          <span v-if="meta.biz_ext&&meta.biz_ext.ticket_ordering">剩余:{{ Number(meta.biz_ext.ticket_ordering) }}</span>
          <span v-if="meta.deadline">截止日期:{{ meta.deadline }}</span>
        </p>
        <p>
          <span class="price">{{ Number(meta.biz_ext.cost) }}</span>
          <sub>门店价{{ Number(meta.biz_ext.cost) }}</sub>
        </p>
      </dd>
      <dd>
        <el-button
          type="warning"
          round
          @click="createCart">立即抢购</el-button>
      </dd>
    </dl>
  </li>
</template>

<script>
export default {
  props: {
    meta: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  methods: {
    createCart: async function () {
      let self = this;
      let {
        status,
        data: {
          code,
          id
        }
      } = await this.$axios.post('/cart/create', {
        params: {
          id: Math.random().toString().slice(3, 9),
          detail: {
            name: self.meta.name,
            price: self.meta.biz_ext.cost,
            imgs: self.meta.photos
          }
        }
      })
      if(status===200&&code===0){
        // 跳转到购物车页面
        window.location.href=`/cart/?id=${id}`
      }else{
        console.log('error')
      }
    }
  }
}
</script>

<style lang="scss">


</style>

二,购物车功能

1.在地点详情页detail中,点击立即请购按钮,跳转到购物车页面

pages-->cart.vue购物车,引入list组件

<template>
  <div class="page-cart">
    <el-row>
      <el-col
        v-if="cart.length"
        :span="24"
        class="m-cart">
        <list :cart-data="cart"/>
        <p>
          应付金额:<em class="money">¥{{ total }}</em>
        </p>
        <div class="post">
          <el-button
            type="primary"
            @click="submit">提交订单</el-button>
        </div>
      </el-col>
      <el-col
        v-else
        class="empty">购物车为空</el-col>
    </el-row>
  </div>
</template>

<script>
import List from '@/components/cart/list.vue'
export default {
  components:{
    List
  },
  data(){
    return {
      cart:[]
    }
  },
  computed:{
    total(){
      let total=0;
      this.cart.forEach(item=>{
        total+=item.price*item.count
      })
      return total
    }
  },
  methods:{
    submit: async function(){
      let {status,data:{code,id}}=await this.$axios.post('/order/createOrder',{
        count:this.cart[0].count,
        price:this.cart[0].price,
        id:this.cartNo
      })
      if(status==200&&code===0){
        this.$alert(`恭喜您,已成功下单,订单号:${id}`,'下单成功',{
          confirmButtonText:'确定',
          callback:action=>{
       //跳转到订单页面 location.href
='/order' } }) } } }, // 通过ssr获取数据 async asyncData(ctx){ let {status,data:{code,data:{name,price}}}=await ctx.$axios.post('/cart/getCart',{ id:ctx.query.id }) if(status===200&&code===0&&name){ return { cart:[{ name, price, count:1 }], cartNo:ctx.query.id } } } } </script> <style lang="scss"> @import "@/assets/css/cart/index.scss"; </style>

list.vue组件,el-input-number,计数器组件

<template>
  <el-table
    :data="cartData"
    style=" 980px">
    <el-table-column
      prop="name"
      label="项目"
      width="532"/>
    <el-table-column
      prop="price"
      label="单价"
      width="132"/>
    <el-table-column
      label="数量"
      width="212">
      <template slot-scope="scope">
        <el-input-number
          v-model="scope.row.count"
          :min="0"/>
      </template>
    </el-table-column>
    <el-table-column
      label="总价">
      <template slot-scope="scope">
        <div class="">
          {{ scope.row.price*scope.row.count }}
        </div>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  props:{
    cartData:{
      type:Array,
      default:()=>{
        return []
      }
    }
  }
}
</script>

三,在订单页面功能

1.在购物车页,点击提交订单按钮,跳转到订单页面

原文地址:https://www.cnblogs.com/fsg6/p/14434086.html