zoukankan      html  css  js  c++  java
  • 仿美团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.在购物车页,点击提交订单按钮,跳转到订单页面

  • 相关阅读:
    不可或缺 Windows Native (15)
    不可或缺 Windows Native (14)
    不可或缺 Windows Native (13)
    不可或缺 Windows Native (12)
    不可或缺 Windows Native (11)
    不可或缺 Windows Native (10)
    不可或缺 Windows Native (9)
    不可或缺 Windows Native (8)
    不可或缺 Windows Native (7)
    不可或缺 Windows Native (6)
  • 原文地址:https://www.cnblogs.com/fsg6/p/14434086.html
Copyright © 2011-2022 走看看