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

  • 相关阅读:
    深拷贝
    属性showoverflowtooltip内容过多时,如何设置tooltip的宽度,让其多行显示
    vue 实现点击全屏和退出全屏
    大数计算 BigInt()
    vue3 添加 vuex
    width:inherit
    Object 方法整理
    Python逆向爬虫之requests
    爬虫及浏览器开发者工具
    Python逆向爬虫之urllib
  • 原文地址:https://www.cnblogs.com/fsg6/p/14434086.html
Copyright © 2020-2023  润新知