Browse Source

搜索页:接口对接

panyong 2 years ago
parent
commit
91d0d502e3

+ 11 - 0
htmldev/cps/src/views/search/api/index.js

@@ -0,0 +1,11 @@
+import request from '@/api/request'
+
+/**
+ * 商品搜索接口
+ * @param obj
+ */
+export const apiGoodsSearch = (obj) => request({
+  method: 'GET',
+  url: '/api/buy/goods/search',
+  params: obj
+})

+ 433 - 0
htmldev/cps/src/views/search/child/main.vue

@@ -0,0 +1,433 @@
+<template>
+  <div
+    class="wrapper"
+    ref="returnWrapper">
+    <ul>
+      <li
+        :class="{'static': isRefresh}"
+        class="pulldown-wrapper">
+        <van-loading
+          v-show="isRefresh"
+          size="24px"
+          type="spinner">加载中...
+        </van-loading>
+        <div
+          v-show="!isRefresh"
+          class="van-loading">
+          <span
+            class="van-loading__text">下拉刷新</span>
+        </div>
+      </li>
+      <li
+        v-for="(item, index) in list"
+        :key="index"
+        class="list-item border-bottom-1px"
+        @click="getOrderDetail(item.goods_id)">
+        <div class="photo">
+          <img
+            :src="item.goods_thumb_url"
+            alt="">
+        </div>
+        <div class="info">
+          <div
+            class="top">
+            <p>{{ item.goods_name }}</p>
+          </div>
+          <div class="middle">
+            <div class="price-wrap">
+              <p class="price">
+                <span>¥</span>
+                <span>{{ item.price && (item.price * 1).toFixed(2) }}</span>
+              </p>
+              <p class="origin">¥{{ item.market_price && (item.market_price * 1).toFixed(2) }}</p>
+            </div>
+            <!--暂时不用这个字段-->
+            <!--<div class="sale-count">-->
+            <!--<span>已售</span>-->
+            <!--<span>0</span>-->
+            <!--</div>-->
+          </div>
+          <div class="card" v-show="item.discount > 0 || item.commission > 0">
+            <p class="coupon" v-show="item.discount > 0">
+              <span>券</span>
+              <span>¥{{ item.discount }}</span>
+            </p>
+            <p class="profit" v-show="item.commission > 0">
+              <span>分享赚</span>
+              <span>¥&nbsp;{{ item.commission }}</span>
+            </p>
+          </div>
+          <!--暂时不用这个字段-->
+          <div class="shop">
+            <van-icon
+              size="20"
+              name="shop-o"/>
+            <p>{{ item.shop_name }}</p>
+          </div>
+        </div>
+      </li>
+      <li class="pullup-wrapper">
+        <van-loading
+          v-show="!finished"
+          size="24px"
+          type="spinner">加载中...
+        </van-loading>
+        <div
+          v-show="finished"
+          class="van-loading">
+          <span
+            class="van-loading__text">没有更多了</span>
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+import BScroll from 'better-scroll'
+import { Toast, Loading, Icon } from 'vant'
+import { apiGoodsSearch } from '../api'
+
+export default {
+  components: {
+    'van-loading': Loading,
+    'van-icon': Icon
+  },
+  props: {
+    keyword: {
+      type: String,
+      default: ''
+    },
+    source: {
+      type: String,
+      default: ''
+    },
+    sort: {
+      type: [String, Number],
+      default: 1
+    }
+  },
+  data () {
+    return {
+      finished: false, // 所有数据是否加载完
+      isRefresh: false, // 是否下拉刷新
+      isFetchLock: false, // 接口调用加锁
+      pagenum: 0,
+      pagesize: 20,
+      list: [],
+      scroll: null
+    }
+  },
+  methods: {
+    init () {
+      this.finished = false
+      this.isRefresh = false
+      this.isFetchLock = false
+      this.pagenum = 0
+      this.pagesize = 20
+      this.list = []
+      if (this.scroll) {
+        this.scroll.scrollTo(0, 0)
+      }
+      this.getList()
+    },
+    onRefresh () {
+      this.pagenum = 0
+      this.pagesize = 20
+      this.finished = false
+      this.isRefresh = true
+      this.getList()
+    },
+    async getList () {
+      if (this.finished) {
+        return
+      }
+      if (this.isFetchLock) {
+        return
+      }
+      this.isFetchLock = true
+      this.pagenum++
+      try {
+        const { status, data, msg } = await apiGoodsSearch({
+          page: this.pagenum,
+          page_size: this.pagesize,
+          source: this.source,
+          keyword: this.keyword,
+          sort: this.sort
+        })
+        if (status) {
+          const { list } = data
+          // 下拉刷新数据清空
+          if (this.isRefresh) {
+            this.isRefresh = false
+            this.list = []
+          }
+
+          // 没有数据返回了
+          if (Array.isArray(list) && !list.length) {
+            this.finished = true
+          }
+
+          if (Array.isArray(list) && list.length) {
+            // 总页数小于等于1页时
+            if (list.length < this.pagesize) {
+              this.finished = true
+            }
+            this.list = this.list.concat(list)
+
+            this.$nextTick(() => {
+              if (!this.scroll) {
+                this.scroll = new BScroll(this.$refs.returnWrapper, {
+                  click: true,
+                  pullDownRefresh: {
+                    threshold: 50, // 顶部下拉的距离
+                    stop: 20 // 回弹停留的距离
+                  },
+                  pullUpLoad: {
+                    threshold: -20
+                  },
+                  scrollbar: true
+                })
+
+                this.scroll.on('pullingDown', () => {
+                  this.onRefresh()
+                })
+
+                this.scroll.on('pullingUp', () => {
+                  this.getList()
+                })
+              } else {
+                this.scroll.finishPullDown()
+                this.scroll.finishPullUp()
+                this.scroll.refresh()
+              }
+            })
+          }
+        } else {
+          Toast(msg)
+        }
+        this.isFetchLock = false
+      } catch (err) {
+        this.isFetchLock = false
+      }
+    },
+    getOrderDetail (id) {
+      this.$router.push({
+        name: 'CategoryDetail',
+        params: {
+          source: this.source,
+          goodsId: id
+        }
+      })
+    }
+  },
+  beforeDestroy () {
+    this.scroll && this.scroll.destroy()
+  }
+}
+</script>
+<style lang="scss" scoped>
+.wrapper {
+  position: absolute;
+  left: 0;
+  top: 136px;
+  right: 0;
+  bottom: 0;
+  width: 100%;
+  overflow: hidden;
+
+  ul {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    width: 100%;
+    padding: 0 0 102px;
+  }
+}
+
+.pulldown-wrapper {
+  position: absolute;
+  left: 0;
+  top: -43px;
+  width: 100%;
+  text-align: center;
+  margin-bottom: 10px;
+
+  &.static {
+    position: static;
+    left: 0;
+    top: 0;
+  }
+}
+
+.pullup-wrapper {
+  width: 100%;
+  text-align: center;
+
+  .van-loading {
+    margin-top: 16px;
+  }
+}
+
+.list-item {
+  display: flex;
+  width: 355px;
+  min-height: 138px;
+  background: #FEFEFE;
+  border-radius: 5px;
+  margin-bottom: 10px;
+  padding: 9px;
+}
+
+.photo {
+  width: 121px;
+  height: 121px;
+  margin-right: 10px;
+  border-radius: 6px;
+  overflow: hidden;
+
+  img {
+    display: block;
+    width: 100%;
+  }
+}
+
+.info {
+  width: 206px;
+  padding-top: 6px;
+}
+
+.top {
+  p {
+    display: -webkit-box;
+    font-size: 14px;
+    font-weight: bold;
+    color: #333333;
+    line-height: 18px;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+  }
+}
+
+.middle {
+  display: flex;
+  align-items: flex-end;
+  justify-content: space-between;
+  margin-top: 8px;
+}
+
+.price-wrap {
+  display: flex;
+  align-items: flex-end;
+}
+
+.price {
+  margin-right: 8px;
+  font-size: 0;
+
+  span {
+    &:nth-of-type(1) {
+      margin-right: 4px;
+      font-size: 12px;
+      font-weight: bold;
+      color: #EA483F;
+      line-height: 18px;
+    }
+
+    &:nth-of-type(2) {
+      font-size: 16px;
+      font-weight: bolder;
+      color: #EA483F;
+      line-height: 18px;
+    }
+  }
+}
+
+.origin {
+  font-size: 10px;
+  text-decoration: line-through;
+  color: #999999;
+  line-height: 18px;
+}
+
+.sale-count {
+  font-size: 0;
+
+  span {
+    font-size: 10px;
+    color: #999999;
+    line-height: 18px;
+
+    &:nth-of-type(1) {
+      margin-right: 4px;
+    }
+  }
+}
+
+.card {
+  display: flex;
+  align-items: center;
+  margin-top: 4px;
+}
+
+.coupon {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-width: 57px;
+  height: 18px;
+  background: url("../image/ic_coupon.png") center center/100% 100% no-repeat;
+  margin-right: 11px;
+
+  span {
+    font-size: 11px;
+    font-weight: bold;
+    color: #FFFFFF;
+    line-height: 18px;
+
+    &:nth-of-type(1) {
+      margin-right: 2px;
+    }
+  }
+}
+
+.profit {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-width: 82px;
+  height: 19px;
+  background: #FBF4F4;
+  padding: 0 8px;
+  border-radius: 3px;
+
+  span {
+    font-size: 10px;
+    font-weight: 500;
+    color: #D64136;
+    line-height: 18px;
+
+    &:nth-of-type(1) {
+      margin-right: 2px;
+    }
+  }
+}
+
+.shop {
+  display: flex;
+  align-items: center;
+  margin-top: 8px;
+
+  p {
+    width: calc(100% - 24px);
+    margin-left: 4px;
+    font-size: 12px;
+    font-weight: 500;
+    color: #999999;
+    line-height: 22px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}
+</style>

BIN
htmldev/cps/src/views/search/image/ic_coupon.png


+ 51 - 14
htmldev/cps/src/views/search/index.vue

@@ -4,7 +4,7 @@
       class="fbt-form"
       action="/">
       <van-search
-        v-model="searchValue"
+        v-model.trim="keyword"
         show-action
         :shape="'round'"
         placeholder="搜索商品标题 领优惠券拿返现"
@@ -21,7 +21,7 @@
     <div
       class="business-list">
       <van-tabs
-        v-model="businessValue"
+        v-model="source"
         :color="'#F09E38'"
         :title-active-color="'#333333'"
         :title-inactive-color="'#515151'"
@@ -36,12 +36,14 @@
         </van-tab>
       </van-tabs>
     </div>
-    <ul class="filter-wrap border-top-1px">
+    <ul
+      class="filter-wrap border-top-1px"
+      v-show="booGoodsWrap">
       <li
-        :class="{'active': condition === item.value}"
+        :class="{'active': sort === item.value}"
         v-for="item in filterList"
         :key="item.value"
-        @click="condition = item.value">选项
+        @click="selectSortType(item)">选项
       </li>
       <li
         @click="showType = showType === 1 ? 2 : 1">
@@ -49,22 +51,31 @@
           :class="['shopfont', showType === 1 ? 'shopfont-liebiao' : 'shopfont-shuangliebiao']"></span>
       </li>
     </ul>
+    <!--商品列表-->
+    <Main
+      :keyword="keyword"
+      :source="source"
+      :sort="sort"
+      ref="myMain"
+      v-show="booGoodsWrap"/>
   </div>
 </template>
 
 <script>
-import { Search, Tabs, Tab } from 'vant'
+import { Search, Tabs, Tab, Toast } from 'vant'
+import Main from './child/main'
 
 export default {
   name: 'index',
   components: {
     'van-search': Search,
     'van-tabs': Tabs,
-    'van-tab': Tab
+    'van-tab': Tab,
+    Main
   },
   data () {
     return {
-      searchValue: '',
+      keyword: '',
       sourceList: [
         {
           name: '京东',
@@ -102,9 +113,10 @@ export default {
           value: 3
         }
       ],
-      businessValue: 'jd',
-      condition: 1,
-      showType: 1 // 列表展示方式
+      source: 'jd',
+      sort: 1,
+      showType: 1, // 列表展示方式
+      booGoodsWrap: false
     }
   },
   activated () {
@@ -116,10 +128,35 @@ export default {
     this.$route.meta.isUseCache = false
   },
   methods: {
-    onSearch (val) {
-      console.log(val)
+    onSearch () {
+      if (!this.keyword) {
+        Toast('搜索内容不能为空')
+        return
+      }
+      if (!this.booGoodsWrap) {
+        this.booGoodsWrap = true
+      }
+      this.$nextTick(() => {
+        this.$refs.myMain.init()
+      })
+    },
+    fetchGoodsList () {
+      if (!this.keyword) {
+        return
+      }
+      this.$nextTick(() => {
+        this.$refs.myMain.init()
+      })
     },
-    fetchGoodsList () {}
+    selectSortType (item) {
+      this.sort = item.value
+      if (!this.keyword) {
+        return
+      }
+      this.$nextTick(() => {
+        this.$refs.myMain.init()
+      })
+    }
   }
 }
 </script>