• 仿美团pc,koa+ssr(五)


    一,地点详情页功能开发

    1.在searchbar.vue组件,点击热门景点,跳转到景点详情页,keyword中文需要编码下

    <template>
      <div class="search-panel">
        <el-row class="m-header-searchbar">
          <el-col
            :span="3"
            class="left">
            <img
              src="//s0.meituan.net/bs/fe-web-meituan/e5eeaef/img/logo.png"
              alt="美团">
          </el-col>
          <el-col
            :span="15"
            class="center">
            <div class="wrapper">
              <el-input
                v-model="search"
                placeholder="搜索商家或地点"
                @focus="focus"
                @blur="blur"
                @input="input"/>
              <button class="el-button el-button--primary"><i class="el-icon-search"/></button>
              <dl
                v-if="isHotPlace"
                class="hotPlace">
                <dt>热门搜索</dt>
                <dd
                  v-for="(item,idx) in $store.state.home.hotPlace.slice(0,5)"
                  :key="idx">
                  <a :href="'/products?keyword='+encodeURIComponent(item.name)">{{ item.name }}</a>
                </dd>
              </dl>
              <dl
                v-if="isSearchList"
                class="searchList">
                <dd
                  v-for="(item,idx) in searchList"
                  :key="idx">
                  <a :href="'/products?keyword='+encodeURIComponent(item.name)">{{ item.name }}</a>
                </dd>
              </dl>
            </div>
            <p class="suggest">
              <a
                v-for="(item,idx) in $store.state.home.hotPlace.slice(0,5)"
                :key="idx"
                :href="'/products?keyword='+encodeURIComponent(item.name)">{{ item.name }}</a>
            </p>
            <ul class="nav">
              <li><nuxt-link
                to="/"
                class="takeout">美团外卖</nuxt-link></li>
              <li><nuxt-link
                to="/"
                class="movie">猫眼电影</nuxt-link></li>
              <li><nuxt-link
                to="/"
                class="hotel">美团酒店</nuxt-link></li>
              <li><nuxt-link
                to="/"
                class="apartment">民宿/公寓</nuxt-link></li>
              <li><nuxt-link
                to="/"
                class="business">商家入驻</nuxt-link></li>
            </ul>
          </el-col>
          <el-col
            :span="6"
            class="right">
            <ul class="security">
              <li><i class="refund"/><p class="txt">随时退</p></li>
              <li><i class="single"/><p class="txt">不满意免单</p></li>
              <li><i class="overdue"/><p class="txt">过期退</p></li>
            </ul>
          </el-col>
        </el-row>
      </div>
    </template>

    景点详情页

    pages-->新建products.vue组件,

    crumbs.vue面包屑,categroy.vue分类组件,list.vue列表组件(iselect.vue弹层),map.vue组件都在该父组件引入

    <template>
      <el-row class="page-product">
        <el-col :span="19">
          <crumbs :keyword="keyword"/>
          <categroy
            :types="types"
            :areas="areas"/>
          <list :list="list"/>
        </el-col>
        <el-col :span="5">
          <amap
            v-if="point.length"
            :width="230"
            :height="290"
            :point="point"/>
        </el-col>
      </el-row>
    
    </template>
    
    <script>
    import Crumbs from '@/components/products/crumbs.vue'
    import Categroy from '@/components/products/categroy.vue'
    import List from '@/components/products/list.vue'
    import Amap from '@/components/public/map.vue'
    export default {
      components:{
        Crumbs,
        Categroy,
        List,
        Amap
      },
      data(){
        return {
          list:[],
          types:[],
          areas:[],
          keyword:'',
          point:[]
        }
      },
      // 通过ssr获取数据
      async asyncData(ctx){
        // 获取搜索的关键字
        let keyword = ctx.query.keyword
        let city = ctx.store.state.geo.position.city
        let {status,data:{count,pois}} = await ctx.$axios.get('/search/resultsByKeywords',{
          params:{
            keyword,
            city
          }
        })
        let {status:status2,data:{areas,types}} = await ctx.$axios.get('/categroy/crumbs',{
          params:{
            city
          }
        })
        if(status===200&&count>0&&status2===200){
          return {
            list: pois.filter(item=>item.photos.length).map(item=>{
              return {
                type: item.type,
                img: item.photos[0].url,
                name: item.name,
                comment: Math.floor(Math.random()*10000),
                rate: Number(item.biz_ext.rating),
                price: Number(item.biz_ext.cost),
                scene: item.tag,
                tel: item.tel,
                status: '可订明日',
                // 经纬度
                location: item.location,
                module: item.type.split(';')[0]
              }
            }),
            keyword,
            areas: areas.filter(item=>item.type!=='').slice(0,5),
            types: types.filter(item=>item.type!=='').slice(0,5),
            point: (pois.find(item=>item.location).location||'').split(',')
          }
        }
      }
    }
    </script>
    
    <style lang="scss">
      @import "@/assets/css/products/index.scss";
    </style>

    crumbs.vue面包屑,element-ui的面包屑组件,keyword需要解码

    <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><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: ''
        }
      }
    }
    </script>

    categroy.vue分类组件

    <template>
      <div class="m-product-categroy">
        <dl class="classic">
          <dt>分类</dt>
          <dt>全部</dt>
          <dd
            v-for="(item,idx) in types"
            :key="idx">
            <iselect
              :name="item.type"
              :list="item.module"/>
          </dd>
        </dl>
        <dl class="classic">
          <dt>分类</dt>
          <dt>全部</dt>
          <dd
            v-for="(item,idx) in areas"
            :key="idx">
            <iselect
              :name="item.type"
              :list="item.module"/>
          </dd>
        </dl>
      </div>
    </template>
    
    <script>
    import iselect from './iselect.vue'
    export default {
      components: {
        iselect
      },
      props: {
        types: {
          type: Array,
          default(){
            return []
          }
        },
        areas: {
          type:Array,
          default(){
            return []
          }
        }
      },
    }
    </script>
    
    <style lang="scss">
      .m-product-categroy{
        padding: 15px 20px 0;
        background: #FFF;
        border: 1px solid #E5E5E5;
        border-radius: 4px;
        color: #333;
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
      }
      .classic{
        display: flex;
        padding-bottom: 10px;
        >dt{
           80px;
          &:nth-child(2){
            border-radius: 100px;
            background: #13D1BE;
            color: #FFF;
            height: 22px;
            line-height: 22px;
             40px;
            box-sizing: border-box;
            margin-right: 40px;
            text-align: center;
          }
        }
        &:nth-child(1){
          dd{
            border-bottom: 1px solid #ddd;
          }
        }
      }
    </style>

    iselect.vue组件弹层

    <template>
      <div class="m-product-select">
        <dl class="tab">
          <dt>{{ name }}<i class="el-icon-arrow-down el-icon--right"/></dt>
          <dd>
            <h3>{{ name }}</h3>
            <span
              v-for="(item,idx) in list"
              :key="idx">{{ item }}</span>
          </dd>
        </dl>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        name: {
          type:String,
          default:''
        },
        list: {
          type: Array,
          default(){
            return []
          }
        }
      }
    }
    </script>

    list.vue列表

    <template>
      <div class="m-products-list">
        <dl>
          <dd
            v-for="item in nav"
            :key="item.name"
            :class="[item.name,item.acitve?'s-nav-active':'']"
            @click="navSelect"
          >{{ item.txt }}</dd>
        </dl>
        <ul>
          <Item
            v-for="(item,idx) in list"
            :key="idx"
            :meta="item"/>
        </ul>
      </div>
    </template>
    
    <script>
    import Item from './product.vue'
    export default {
      components: {
        Item
      },
      props: {
        list: {
          type:Array,
          default(){
            return []
          }
        }
      },
      data() {
        return {
          nav: [
            {
              name: 's-default',
              txt: '智能排序',
              acitve: true
            }, {
              name: 's-price',
              txt: '价格最低',
              active: false
            }, {
              name: 's-visit',
              txt: '人气最高',
              active: false
            }, {
              name: 's-comment',
              txt: '评价最高',
              active: false
            }
          ]
        }
      },
      async asyncData({app}) {
        let { data } = await app.$axios.get('searchList')
        return { items: data.list }
      },
      methods: {
        navSelect: function () {
          console.log('select')
        }
      }
    }
    </script>

    item.vue组件,element-ui的el-tare评分组件

    <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>

    map.vue地图组件,需要用到高德的第三方平台的API

    <template>
      <div
        :id="id"
        :style="{width+'px',height:height+'px',margin:'34px auto'}"
        class="m-map"/>
    </template>
    
    <script>
    export default {
      props: {
         {
          type:Number,
          default:300
        },
        height: {
          type:Number,
          default:300
        },
        point: {
          type:Array,
          default(){
            return [116.46,39.92]
          }
        }
      },
      data() {
        return {
          id: `map`,
          key: '0dbc0dfd7c775f2a927174493eab8220'
        }
      },
    //监视经纬度的变化 watch: { point: function (val, old) {
    this.map.setCenter(val) this.marker.setPosition(val) } }, mounted() { let self = this // 动态id self.id = `map${Math.random().toString().slice(4, 6)}` // 高德开放平台,调用地图组件 window.onmaploaded = () => { let map = new window.AMap.Map(self.id, { resizeEnable: true, zoom: 11, center: self.point }) self.map = map window.AMap.plugin('AMap.ToolBar', () => { let toolbar = new window.AMap.ToolBar() map.addControl(toolbar) let marker = new window.AMap.Marker({ icon: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png', position: self.point }) self.marker = marker marker.setMap(map) }) } const url = `https://webapi.amap.com/maps?v=1.4.10&key=${self.key}&callback=onmaploaded` let jsapi = document.createElement('script') jsapi.charset = 'utf-8' jsapi.src = url document.head.appendChild(jsapi) }, } </script>
  • 相关阅读:
    Cisco IOS XE 3S–to–Cisco IOS Release Number Mapping
    ORA-01157 误删表空间对应的dbf文件出现的错误的解决办法
    记录-Windows10 cnpm报禁止运行脚本
    记录-html和html5区别
    记录-查询硬盘物理序号
    CRC16 Java 实现
    kaldi解码及特征提取详解
    kaldi GMM模型解码指令 gmm-latgen-faster详解
    kaldi基于GMM的单音素模型 训练部分
    kaldi学习
  • 原文地址:https://www.cnblogs.com/fsg6/p/14429318.html
Copyright © 2020-2023  润新知