Преглед изворни кода

Merge remote-tracking branch 'origin/feature-yc-201813' into feature-yc-201813

shenjj пре 7 година
родитељ
комит
e647d9a965
82 измењених фајлова са 4346 додато и 672 уклоњено
  1. 503 0
      components/brandCenter/BrandIndex.vue
  2. 224 0
      components/brandCenter/RecommendBrand.vue
  3. 4 0
      components/brandCenter/index.js
  4. 1 1
      components/default/Header.vue
  5. 0 87
      components/home/count/countItem.vue
  6. 63 26
      components/home/displayCard.vue
  7. 1 1
      components/home/index.js
  8. 7 1
      components/main/Header.vue
  9. 5 2
      components/main/Nav.vue
  10. 47 20
      components/main/Search.vue
  11. 6 10
      components/mobile/applyPurchase/SayPrice.vue
  12. 7 0
      components/mobile/applyPurchase/SayPriceInfo.vue
  13. 7 3
      components/mobile/base/SearchHeader.vue
  14. 46 11
      components/mobile/brand/BrandCenter.vue
  15. 85 279
      components/mobile/common/StatisticsMobile.vue
  16. 28 0
      components/pcb/Nav.vue
  17. 208 0
      components/pcb/PcbNavSearch.vue
  18. 267 0
      components/pcb/brand/BrandList.vue
  19. 93 0
      components/pcb/home/Intro.vue
  20. 53 0
      components/pcb/home/Kinds.vue
  21. 86 0
      components/pcb/home/RecommendBrand.vue
  22. 106 0
      components/pcb/home/floors/Floor.vue
  23. 72 0
      components/pcb/home/floors/Floors.vue
  24. 13 0
      components/pcb/index.js
  25. 571 0
      components/pcb/product/Detail.vue
  26. 99 0
      components/pcb/search/DetailBrand.vue
  27. 381 0
      components/pcb/search/GoodList.vue
  28. 309 0
      components/pcb/search/Kind.vue
  29. 52 0
      components/pcb/search/ResultTitle.vue
  30. 139 90
      components/product/brand/BrandDetail.vue
  31. 43 24
      components/product/brand/CategoriesList.vue
  32. 1 1
      components/provider/Carousel.vue
  33. 7 7
      components/provider/RecommendStore.vue
  34. 156 0
      layouts/pcb.vue
  35. 7 2
      nuxt.config.js
  36. 17 2
      pages/mobile/center/user/collect/message.vue
  37. 17 2
      pages/mobile/center/vendor/message.vue
  38. 2 0
      pages/mobile/center/vendor/seek.vue
  39. 8 2
      pages/mobile/product/_batchCode.vue
  40. 46 0
      pages/pcb/brand/_id.vue
  41. 25 0
      pages/pcb/index.vue
  42. 26 0
      pages/pcb/product/_productId/_batchCode.vue
  43. 129 0
      pages/pcb/search/_keyword.vue
  44. 15 21
      pages/product/brand/_code.vue
  45. 0 66
      pages/product/brand/brandList.vue
  46. 53 6
      pages/product/brand/brandList/_initial.vue
  47. 3 0
      plugins/axios.js
  48. 7 0
      plugins/mixin.js
  49. BIN
      static/images/applyPurchase/apply-top-ad.jpg
  50. BIN
      static/images/brandCenter/brand-index-bg.png
  51. BIN
      static/images/brandCenter/brand-index-title.png
  52. BIN
      static/images/brandCenter/brand-index-tree.png
  53. BIN
      static/images/brandCenter/brand-introduce-line.png
  54. BIN
      static/images/brandCenter/detail.jpg
  55. BIN
      static/images/brandCenter/detail.png
  56. BIN
      static/images/brandCenter/logo1.png
  57. BIN
      static/images/brandCenter/logo2.png
  58. BIN
      static/images/brandCenter/logo3.png
  59. BIN
      static/images/brandCenter/logo4.png
  60. BIN
      static/images/brandCenter/recommend-bg.png
  61. BIN
      static/images/brandCenter/recommend-title.png
  62. BIN
      static/images/brandCenter/search-bg.png
  63. BIN
      static/images/brandCenter/search-btn.png
  64. BIN
      static/images/brandCenter/type.png
  65. BIN
      static/images/brandList/empty-cart.jpg
  66. BIN
      static/images/brandList/upload.png
  67. BIN
      static/images/pcb/banner.png
  68. BIN
      static/images/pcb/identified.png
  69. BIN
      static/images/pcb/intro-bg.png
  70. BIN
      static/images/pcb/link.png
  71. BIN
      static/images/pcb/price-bg.png
  72. BIN
      static/images/pcb/recommend-brand.png
  73. BIN
      static/images/pcb/test-logo.png
  74. 14 0
      store/carousel.js
  75. 20 0
      store/index.js
  76. 55 0
      store/pcb.js
  77. 19 0
      store/pcb/kindsData.js
  78. 19 0
      store/pcb/product.js
  79. 47 0
      store/pcb/search.js
  80. 12 8
      store/product.js
  81. 19 0
      store/product/banner.js
  82. 96 0
      utils/baseUtils.js

+ 503 - 0
components/brandCenter/BrandIndex.vue

@@ -0,0 +1,503 @@
+<template>
+  <div class="brand-center-index">
+    <img src="/images/brandCenter/brand-index-title.png" alt="">
+    <div class="brand-index-tab">
+      <div class="brand-index-group" v-for="(indexGroup, index) in indexGroups">
+        <span v-if="index == 5"></span>
+        <a @click="goBrandIndex(group_index)" v-for="group_index in indexGroup" :class="{'active': activeIndex==group_index}">{{group_index}}</a>
+        <span v-if="index == 5"></span>
+      </div>
+    </div>
+    <div class="brand-center-index-list">
+      <div class="brand-list-nav">
+        <div class="filter-area">
+          <input type="text" placeholder="请输入您要搜索的品牌" v-model="keyword" @keyup.13="searchBrands()">
+          <img src="/images/brandCenter/search-btn.png" alt="" @click="searchBrands()">
+          <span v-if="brandList.totalElements > 0">{{nowPage}}/{{brandList.totalPages}}
+            <a href="javascript:void(0)" class="icon-xiangzuo iconfont" @click="changePage('pre')" :class="{'is-border': nowPage==1}"></a>
+            <a href="javascript:void(0)" @click="changePage('next')" class="icon-xiangyou iconfont" :class="{'is-border': nowPage>=brandList.totalPages}"></a>
+          </span>
+        </div>
+      </div>
+      <div class="brand-list-items">
+        <span v-show="!isSearch">
+          以{{activeIndex&&activeIndex.length==1?'字母':''}}
+          <span class="active-index">{{activeIndex}}&nbsp;</span>开头共有
+          <span class="active-number">{{brandList.totalElements || 0}}&nbsp;</span>个品牌
+          <span v-if="brandList.totalElements > 0">,当前是第
+            <span class="active-number">{{nowPage}}&nbsp;</span>页
+          </span>
+        </span>
+        <span v-show="isSearch">
+          搜索
+          <span class="active-index">"{{showKeyword}}"&nbsp;</span>,为您找到
+          <span class="active-number">{{brandList.totalElements || 0}}&nbsp;</span>个相关品牌:
+        </span>
+        <div class="brand-list-item-wrap" v-for="brand in brandList.content">
+          <a :href="'/product/brand/'+brand.uuid" target="_blank">
+            <span v-if="brand.nameEn">{{brand.nameEn}}</span>
+            <span v-if="brand.nameCn != brand.nameEn">{{brand.nameCn}}</span>
+            <div class="brand-intro">
+              <span class="brand-application">应用领域:{{brand.application | applicationFilter}}</span>
+              <span >品牌介绍:{{brand.brief | introduceFilter}}</span>
+            </div>
+          </a>
+        </div>
+        <div v-if="brandList.totalElements <= 0" class="empty-remind">
+          商城暂未收录您想要查找的品牌,可前往<a @click="goBrandApply">“品牌申请”</a>提醒我们完善该品牌信息
+        </div>
+        <div class="search-modal-wrap" v-if="showSearchModal"></div>
+      </div>
+      <page :total="brandList.totalElements" :page-size="pageSize"
+            :current="nowPage" v-on:childEvent="listenPage"></page>
+    </div>
+  </div>
+</template>
+<script>
+    import Page from '~components/common/page/pageComponent.vue'
+    export default {
+      data () {
+        return {
+          indexGroups: [
+            ['A', 'B', 'C', 'D', 'E'],
+            ['F', 'G', 'H', 'I', 'J'],
+            ['K', 'L', 'M', 'N', 'O'],
+            ['P', 'Q', 'R', 'S', 'T'],
+            ['U', 'V', 'W', 'X', 'Y', 'Z'],
+            ['0~9']
+          ],
+          nowPage: 1,
+          pageSize: 60,
+          keyword: '',
+          isSearch: false,
+          brands: {},
+          showKeyword: '',
+          showSearchModal: false
+        }
+      },
+      filters: {
+        applicationFilter: function (str) {
+          return str ? str.split(',').join('|') : '-'
+        },
+        introduceFilter: function (str) {
+          if (!str || str === '') {
+            return '-'
+          }
+          let len = 0
+          let index = 0
+          for (let i = 0; i < str.length; i++) {
+            if (index === 0 && str.charAt(i).charCodeAt(0) > 255) {
+              len = len + 2
+            } else {
+              len++
+            }
+            if (len > 50) {
+              index = i
+              break
+            }
+          }
+          if (index > 0) {
+            return str.substring(0, index) + '...'
+          } else {
+            return str
+          }
+        }
+      },
+      components: {
+        Page
+      },
+      mounted () {
+        if (this.$route.path !== '/product/brand/brandList/A') {
+          this.$router.push('/product/brand/brandList/A')
+        }
+      },
+      computed: {
+        brandList () {
+          let brandsList = !this.isSearch ? this.$store.state.product.brand.brandPagerList.data : this.brands
+          brandsList.content = brandsList.content || []
+          return brandsList
+        },
+        activeIndex () {
+          return !this.isSearch ? this.$route.params.initial : ''
+        },
+        user () {
+          return this.$store.state.option.user
+        }
+      },
+      watch: {
+        $route: function (val, oldVal) {
+          this.initParams()
+        }
+      },
+      methods: {
+        initParams: function () {
+          this.nowPage = 1
+          this.isSearch = false
+          this.keyword = ''
+          this.reloadData()
+        },
+        reloadData: function () {
+          !this.isSearch ? this.$store.dispatch('product/loadBrandsPager', {'initial': this.$route.params.initial, 'page': this.nowPage, 'count': this.pageSize, 'keyword': this.keyword}) : this.searchData()
+        },
+        searchData: function () {
+          this.showSearchModal = true
+          this.$http.get('/api/product/brand/Brand/ByPage', {params: {'page': this.nowPage, 'count': this.pageSize, 'keyword': this.keyword}})
+            .then(response => {
+              this.brands = response.data
+              this.isSearch = true
+              this.showKeyword = this.keyword
+              this.showSearchModal = false
+            })
+        },
+        listenPage: function (page) {
+          this.nowPage = page
+          this.reloadData()
+        },
+        changePage: function (type) {
+          if (type === 'next' && this.nowPage < this.brandList.totalPages) {
+            this.nowPage ++
+          } else if (type === 'pre' && this.nowPage > 1) {
+            this.nowPage --
+          }
+          this.reloadData()
+        },
+        searchBrands: function () {
+          if (this.keyword && this.keyword !== '') {
+            this.nowPage = 1
+            this.searchData()
+          } else {
+            this.initParams()
+            this.reloadData()
+            this.$router.push('/product/brand/brandList/A')
+          }
+        },
+        goBrandIndex: function (index) {
+          if (index === this.$route.params.initial) {
+            this.initParams()
+            this.reloadData()
+          } else {
+            this.$router.push('/product/brand/brandList/' + index)
+          }
+        },
+        goBrandApply: function () {
+          if (!this.user.logged) {
+            this.login()
+          } else {
+            window.open('/vendor#/brand/apply/')
+          }
+        },
+        login: function () {
+          this.$http.get('/login/page', {params: {returnUrl: window.location.href}}).then(response => {
+            if (response.data) {
+              this.$router.push('/auth/login')
+            }
+          })
+        }
+      }
+    }
+</script>
+<style lang="scss" scoped>
+  .brand-center-index {
+    width: 1190px;
+    margin: 0 auto;
+    >img {
+      width: 1190px;
+      height: 70px;
+      margin-top: 28px;
+    }
+    .brand-index-tab {
+      height: 206px;
+      position: relative;
+      background: url(/images/brandCenter/brand-index-tree.png) no-repeat;
+      background-position: 60px 71.7px;
+      background-color: #eef1fd;
+      .brand-index-group {
+        height: 40px;
+        text-align: center;
+        position: absolute;
+        a {
+          width: 40px;
+          height: 40px;
+          text-align: center;
+          display: inline-block;
+          color: #fff;
+          line-height: 40px;
+          font-size: 16px;
+          vertical-align: middle;
+        }
+        span {
+          width: 10px;
+          height: 40px;
+          display: inline-block;
+          background: #898ef3;
+          vertical-align: middle;
+        }
+        &:nth-child(1) {
+          left: 184px;
+          top: 32px;
+          a {
+            background: #fc524a;
+            &.active {
+              font-weight: bold;
+              background-color: #ec190f;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+        &:nth-child(2) {
+          left: 322px;
+          bottom: 22px;
+          a {
+            background: #fdad33;
+            &.active {
+              font-weight: bold;
+              background-color: #ea8f02;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+        &:nth-child(3) {
+          left: 472px;
+          top: 32px;
+          a {
+            background: #12c8b1;
+            &.active {
+              font-weight: bold;
+              background-color: #009b87;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+        &:nth-child(4) {
+          left: 612px;
+          bottom: 22px;
+          a {
+            background: #24b8fe;
+            &.active {
+              font-weight: bold;
+              background-color: #0095db;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+        &:nth-child(5) {
+          left: 745px;
+          top: 32px;
+          a {
+            background: #008cff;
+            &.active {
+              font-weight: bold;
+              background-color: #026dc5;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+        &:nth-child(6) {
+          left: 958px;
+          bottom: 22px;
+          a {
+            background: #898ef3;
+            &.active {
+              font-weight: bold;
+              background-color: #7479eb;
+              position: relative;
+              bottom: 2px;
+            }
+            &:hover {
+              font-weight: bold;
+              position: relative;
+              bottom: 2px;
+            }
+          }
+        }
+      }
+    }
+    .brand-center-index-list {
+      .brand-list-nav {
+        height: 56px;
+        padding-top: 15px;
+        .filter-area {
+          float: right;
+          height: 50px;
+          line-height: 50px;
+          margin-right: 9px;
+          position: relative;
+          input {
+            height: 32px;
+            width: 318px;
+            line-height: 32px;
+            padding-left: 11px;
+            border: 1px solid #c6c6c6;
+            background-color: #fff;
+            padding-right: 32px;
+            position: absolute;
+            right: 150px;
+            top: 9px;
+          }
+          img {
+            position: absolute;
+            top: 15px;
+            right: 154px;
+          }
+          span {
+            margin-left: 47px;
+            color: #666;
+            a {
+              width: 30px;
+              height: 22px;
+              display: inline-block;
+              line-height: 22px;
+              text-align: center;
+              border: 1px solid #d2d2d2;
+              color: #3c7cf5;
+              margin-left: 9px;
+              cursor: pointer;
+              background: #fff;
+              &.is-border {
+                color: #999;
+                cursor: not-allowed;
+              }
+            }
+          }
+        }
+      }
+      .brand-list-items {
+        padding-top: 20px;
+        background: url('/images/brandCenter/brand-index-bg.png')no-repeat;
+        background-size: cover;
+        padding-bottom: 20px;
+        position: relative;
+        .search-modal-wrap {
+          background: rgba(255, 255, 255, 0.3);
+          position: absolute;
+          width: 100%;
+          height: 100%;
+          z-index: 2;
+          left: 0;
+          top: 0;
+        }
+        >span {
+          font-size: 14px;
+          color: #333;
+          display: block;
+          margin-bottom: 20px;
+          .active-index {
+            font-size: 16px;
+            color: #3c7cf5;
+          }
+          .active-number {
+            font-weight: bold;
+            font-size: 16px;
+            color: #fc524a;
+          }
+        }
+        .brand-list-item-wrap {
+          display: inline-block;
+          width: 297.5px;
+          margin-bottom: 29px;
+          position: relative;
+          height: 30px;
+          vertical-align: middle;
+          >a {
+            display: inline-block;
+            width: 90px;
+            >span {
+              max-width: 270px;
+              white-space: nowrap;
+              display: block;
+              line-height: 20px;
+              color: #323232;
+              font-size: 14px;
+              &:nth-child(2) {
+                font-size: 12px;
+              }
+            }
+            .brand-intro {
+              display: none;
+              z-index: 3;
+              position: absolute;
+              width: 177px;
+              height: 96px;
+              overflow: hidden;
+              right: 31px;
+              top:0;
+              border-radius: 4px;
+              background-color: rgb( 102, 102, 102 );
+              box-shadow: 1.5px 2.598px 7px 0px rgba(0, 0, 0,0.58);
+              color: #fff;
+              font-size: 11px;
+              padding: 13px 15px;
+              line-height: 18px;
+              text-align: left;
+              word-break: break-all;
+              span {
+                display: block;
+                &.brand-application {
+                  overflow: hidden;
+                  text-overflow: ellipsis;
+                  white-space: nowrap;
+                }
+              }
+              &:hover {
+                span {
+                  text-decoration: underline;
+                }
+              }
+            }
+            &:hover {
+              >span {
+                color: #54c1fa;
+                font-weight: bold;
+              }
+              .brand-intro {
+                display: block;
+              }
+            }
+            >div {
+              text-align: center;
+            }
+          }
+        }
+        >div.empty-remind{
+          text-align: center;
+          margin: 20px 0;
+        }
+      }
+      .page-wrap {
+        text-align: right;
+        margin: 0 0 62px 0;
+        float: none;
+      }
+    }
+  }
+</style>

+ 224 - 0
components/brandCenter/RecommendBrand.vue

@@ -0,0 +1,224 @@
+<template>
+  <div class="recommend-brand">
+    <div v-swiper:mySwiper="swiperOption">
+      <div class="swiper-wrapper">
+        <div class="swiper-slide" v-for="banner in sliceBanners">
+          <a :href="banner.hrefUrl" target="_blank" v-if="banner.hrefUrl">
+            <img :src="banner.pictureLink"/>
+          </a>
+          <span v-if="!banner.hrefUrl">
+                <img :src="banner.pictureLink"/>
+              </span>
+        </div>
+        <div class="swiper-button-prev"><i class="iconfont icon-swiper-left"></i></div>
+        <div class="swiper-button-next"><i class="iconfont icon-swiper-right"></i></div>
+      </div>
+      <div class="swiper-pagination swiper-pagination-bullets"></div>
+    </div>
+    <div class="recommend-area">
+      <ul class="recommend-items">
+        <li v-for="item in hotBrands.data">
+          <a :href="item.detailsLink" target="_blank">
+            <img :src="item.pictureLink" alt="">
+            <div>
+              <p>{{item.title}}</p>
+              <span class="brand-application" v-if="item.metadatas.contExp_abstract" :title="item.metadatas.contExp_abstract">应用领域:{{item.metadatas.contExp_abstract | applicationFilter}}</span>
+              <span class="brand-introduce" v-if="item.metadatas.contExp_select">品牌介绍:{{item.metadatas.contExp_select | introduceFilter}}</span>
+            </div>
+          </a>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    data () {
+      return {
+        activeSlide: 0,
+        swiperOption: {
+          autoplay: 6000,
+          pagination: '.swiper-pagination',
+          paginationClickable: true,
+          mousewheelControl: false,
+          effect: 'fade',
+          lazyLoading: true,
+          loop: true,
+          prevButton: '.swiper-button-prev',
+          nextButton: '.swiper-button-next',
+          onTransitionStart: (swiper) => {
+            if (this.banners.data && this.banners.data.length && (swiper.activeIndex > this.banners.data.length)) {
+              swiper.activeIndex = 1
+            }
+            if (this.banners.data && this.banners.data.length && swiper.activeIndex <= 0) {
+              swiper.activeIndex = this.banners.data.length
+            }
+          }
+        }
+      }
+    },
+    filters: {
+      applicationFilter: function (str) {
+        return str.split(',').join('|')
+      },
+      introduceFilter: function (title) {
+        if (title === '') {
+          return title
+        }
+        let len = 0
+        let index = 0
+        for (let i = 0; i < title.length; i++) {
+          if (index === 0 && title.charAt(i).charCodeAt(0) > 255) {
+            len = len + 2
+          } else {
+            len++
+          }
+          if (len > 80) {
+            index = i
+            break
+          }
+        }
+        if (index > 0) {
+          return title.substring(0, index) + '...'
+        } else {
+          return title
+        }
+      }
+    },
+    computed: {
+      floors () {
+        return this.$store.state.floor.list.data
+      },
+      hotBrands () {
+        return this.$store.state.product.brand.recommends.data
+      },
+      banners () {
+        return this.$store.state.carousel.brandCarousel.data
+      },
+      sliceBanners () {
+        return this.banners && this.banners.data.length ? this.banners.data.slice(0, 3) : []
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .recommend-brand {
+    width: 1190px;
+    margin: 0 auto;
+    .swiper-container {
+      z-index: 2;
+      .swiper-wrapper {
+        width: 1190px;
+        margin: 0 auto;
+        .swiper-slide {
+          height: 163px;
+          margin: 0 auto;
+          display: flex;
+          img {
+            width: 1190px;
+            height: 163px;
+            border: 1px solid #ccc;
+          }
+        }
+        .swiper-button-prev i, .swiper-button-next i {
+          font-size: 26px;
+        }
+      }
+      .swiper-pagination-bullets {
+        .swiper-pagination-bullet {
+          width: 10px!important;
+          height: 10px!important;
+        }
+      }
+    }
+    .recommend-adv {
+      margin: 0 auto;
+      width: 1190px;
+      height: 163px;
+      display: block;
+      border-radius: 3px;
+    }
+    .recommend-area {
+      margin: 29px auto 0;
+      width: 1190px;
+      height: 362px;
+      background:url("/images/brandCenter/recommend-bg.png") no-repeat;
+      .recommend-items {
+        padding-top: 80px;
+        padding-left: 2px;
+        li {
+          border-radius: 3px;
+          width: 234px;
+          height: 127px;
+          background: #fff;
+          display: inline-block;
+          margin-right: 4px;
+          vertical-align: middle;
+          margin-bottom: 5px;
+          text-align: center;
+          &:nth-child(5n) {
+            margin-right: 0;
+          }
+          a {
+            padding-top: 22px;
+            width: 234px;
+            height: 127px;
+            line-height: 91px;
+            display: block;
+            position: relative;
+            img {
+              max-width: 140px;
+              max-height: 91px;
+            }
+            >div {
+              display: none;
+              position: absolute;
+              bottom: 2px;
+              border-radius: 3px;
+              width: 234px;
+              height: 127px;
+              background-color: #3a78f4;
+              opacity: 0.9;
+              top: 0;
+              text-align: left;
+              padding: 13px 7px;
+              p {
+                font-size: 15px;
+                color: #fff;
+                font-weight: bold;
+                height: 16px;
+                line-height: 16px;
+              }
+              span {
+                color: #fff;
+                display: block;
+                width: 228px;
+                line-height: 18px;
+                font-size: 12px;
+                &.brand-application {
+                  padding-right: 5px;
+                  text-overflow: ellipsis;
+                  white-space: nowrap;
+                  overflow: hidden;
+                }
+                &.brand-introduce {
+                  padding-right: 5px;
+                  word-break: break-all;
+                }
+              }
+            }
+          }
+          &:hover {
+            /*position: relative;
+            bottom: 5px;*/
+            a {
+              div {
+                display: block;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 4 - 0
components/brandCenter/index.js

@@ -0,0 +1,4 @@
+import RecommendBrand from './RecommendBrand.vue'
+import BrandIndex from './BrandIndex.vue'
+
+export { RecommendBrand, BrandIndex }

+ 1 - 1
components/default/Header.vue

@@ -2,7 +2,7 @@
   <header class="header">
     <div class="apply-adv" v-if="isShowApplyAdv">
       <a href="/applyPurchase#opportunities">
-        <img src="/images/applyPurchase/apply-ad.png" alt="">
+        <img src="/images/applyPurchase/apply-top-ad.jpg" alt="">
       </a>
       <i @click="ShowApplyAdv = false"></i>
     </div>

+ 0 - 87
components/home/count/countItem.vue

@@ -1,87 +0,0 @@
-<template>
-  <div class="count-item">
-      <span>{{ nums }}</span>
-      <span v-text="isMore?'万':'个'" v-if="!isShow && logo !== 0"></span>
-      <span v-text="isMore?'万':'家'" v-if="!isShow && logo === 0"></span>
-      <span v-if="isShow">亿</span>
-  </div>
-</template>
-<script>
-  export default {
-    name: 'count-item',
-    props: {
-      value: {
-        default: 0,
-        type: Number
-      },
-      logo: {
-        default: 0,
-        type: Number
-      }
-    },
-    data () {
-      return {
-        isMore: false,
-        isShow: false,
-        len: 0
-      }
-    },
-    methods: {
-      formatNumber (num) {
-//        let re = /(\d+)(\d{3})/
-        if (num > 99999999) {
-          this.isShow = true
-          let str2 = num.toString()
-          num = Math.floor(num / 100000000)
-          if (parseInt(str2.charAt(str2.length - 8)) > 8) {
-            num = num + 1
-          }
-        }
-        if (num > 9999) {
-          this.isMore = true
-          let str = num.toString()
-          num = Math.floor(num / 10000)
-          if (parseInt(str.charAt(str.length - 4)) > 4) {
-            num = num + 1
-          }
-        }
-        let length = String(num).length
-        this.len = length > 3 ? length + 1 : length
-        num = (Array(7 - length).join(0) + num)
-//        while (re.test(num)) {
-//          num = num.replace(re, '$1,$2')
-//        }
-//        num = num.split('')
-//        console.log(num)
-        return num
-      }
-    },
-    computed: {
-      nums () {
-        return this.formatNumber(this.value)
-      }
-    }
-  }
-</script>
-<style lang="scss" scoped>
-  @import '~assets/scss/variables';
-  .count-item {
-    width: 100%;
-    height: 30px;
-      span{
-        &:first-child{
-          position: relative;
-          top: -2px;
-        }
-        &:last-child{
-          font-size: 16px;
-          color: #376ef3;
-          font-weight: bold;
-          padding: 0px 34px 0px 7px;
-          position: relative;
-          top: -5px;
-        }
-      }
-  }
-</style>
-

+ 63 - 26
components/home/count/displayCard.vue → components/home/displayCard.vue

@@ -10,7 +10,7 @@
          </ul>
          <ul class="list-unstyled">
            <li ref="pingdanListWrapper" v-for="(c, index) in counts"  :style="'top: -' + 30 * timerIndex + 'px'" :class="{'top': isTop}">
-             <count-item :value ="c.count" :logo ="c.logo"></count-item>
+             <span v-html="formatScrollNumber(c.count, c.logo)"></span>
            </li>
          </ul>
        </div>
@@ -27,7 +27,6 @@
   </div>
 </template>
 <script>
-  import CountItem from './countItem.vue'
   import {whichTransitionEvent} from '~utils/baseUtils.js'
   export default {
     name: 'display-card',
@@ -40,9 +39,6 @@
         title: [ '品牌', '现货', '规格书', '店铺' ]
       }
     },
-    components: {
-      CountItem
-    },
     mounted () {
       this.$nextTick(() => {
         this.changeInterval(true)
@@ -55,21 +51,22 @@
             this.isTop = false
             let isChange = true
             this.timerIndex++
-            let _transitionEvent = whichTransitionEvent()
-            _transitionEvent && this.$refs.pingdanListWrapper[0].addEventListener(
-                   _transitionEvent, () => {
-                       console.log(isChange)
-                       if (isChange) {
-                         let title = this.title.shift()
-                         let count = this.counts.shift()
-                         this.title.push(title)
-                         this.counts.push(count)
-                         this.timerIndex = 0
-                         isChange = false
-                         this.isTop = true
-                       }
-              })
-          }, 4000)
+            if (this.$refs.pingdanListWrapper[0]) {
+              let _transitionEvent = whichTransitionEvent()
+              _transitionEvent && this.$refs.pingdanListWrapper[0].addEventListener(
+                _transitionEvent, () => {
+                  if (isChange) {
+                    let title = this.title.shift()
+                    let count = this.counts.shift()
+                    this.title.push(title)
+                    this.counts.push(count)
+                    this.timerIndex = 0
+                    isChange = false
+                    this.isTop = true
+                  }
+                })
+            }
+          }, 3000)
         } else {
           clearInterval(this.timer)
         }
@@ -77,6 +74,45 @@
       cardClose () {
         this.cardShow = false
       },
+      formatScrollNumber (num, logo) {
+//        let re = /(\d+)(\d{3})/
+        if (num > 99999999) {
+          let str2 = num.toString()
+          num = Math.floor(num / 100000000)
+          if (parseInt(str2.charAt(str2.length - 8)) > 8) {
+            num = num + 1
+          }
+          let length = String(num).length
+          this.len = length > 3 ? length + 1 : length
+          num = (Array(7 - length).join(0) + num)
+          num += '&nbsp;<span style="color: #376ef3;font-size: 16px;position:relative;top: -3px;">亿</span>'
+        } else if (num > 9999) {
+          let str = num.toString()
+          num = Math.floor(num / 10000)
+          if (parseInt(str.charAt(str.length - 4)) > 4) {
+            num = num + 1
+          }
+          let length = String(num).length
+          this.len = length > 3 ? length + 1 : length
+          num = (Array(7 - length).join(0) + num)
+          num += '&nbsp;<span style="color: #376ef3;font-size: 16px;position:relative;top: -3px;">万</span>'
+        } else {
+          let length = String(num).length
+          this.len = length > 3 ? length + 1 : length
+          num = (Array(7 - length).join(0) + num)
+          if (logo === 0) {
+            num += '&nbsp;<span style="color: #376ef3;font-size: 16px;position:relative;top: -3px;">家</span>'
+          } else {
+            num += '&nbsp;<span style="color: #376ef3;font-size: 16px;position:relative;top: -3px;">个</span>'
+          }
+        }
+//        while (re.test(num)) {
+//          num = num.replace(re, '$1,$2')
+//        }
+//        num = num.split('')
+//        console.log(num)
+        return num
+      },
       formatNumber (num, type) {
         if (num) {
           if (num.toString().indexOf('E') !== -1) {
@@ -232,14 +268,14 @@
                   position: relative;
                   top: 0;
                   transition: top 1s;
-                  /*-moz-transition: top 1s; !* Firefox 4 *!*/
-                  /*-webkit-transition: top 1s; !* Safari and Chrome *!*/
-                  /*-o-transition: top 1s; !* Opera *!*/
+                  -moz-transition: top 1s; /* Firefox 4 */
+                  -webkit-transition: top 1s; /* Safari and Chrome */
+                  -o-transition: top 1s; /* Opera */
                   &.top {
                     transition: top 0s;
-                    /*-moz-transition: top 0s; !* Firefox 4 *!*/
-                    /*-webkit-transition: top 0s; !* Safari and Chrome *!*/
-                    /*-o-transition: top 0s; !* Opera *!*/
+                    -moz-transition: top 0s; /* Firefox 4 */
+                    -webkit-transition: top 0s; /* Safari and Chrome */
+                    -o-transition: top 0s; /* Opera */
                   }
                 }
               }
@@ -258,6 +294,7 @@
                 color: #fff;
                 position: relative;
                 top: 0;
+                left: -28px;
                 transition: top 1s;
                 -moz-transition: top 1s; /* Firefox 4 */
                 -webkit-transition: top 1s; /* Safari and Chrome */

+ 1 - 1
components/home/index.js

@@ -1,5 +1,5 @@
 import KindCategory from './KindCategory.vue'
-import displayCard from './count/displayCard.vue'
+import displayCard from './displayCard.vue'
 import Carousel from './Carousel.vue'
 import Advert from './Advert.vue'
 import FloorList from './floor/FloorList.vue'

+ 7 - 1
components/main/Header.vue

@@ -12,7 +12,7 @@
       </div>
       <!--搜索-->
       <div class="header-search pull-left">
-        <search-box></search-box>
+        <search-box :isPcb="isPcb"></search-box>
       </div>
       <!--统计-->
      <!-- <div class="header-count pull-right">
@@ -30,6 +30,12 @@
     components: {
       SearchBox,
       CountBox
+    },
+    props: {
+      isPcb: {
+        type: Boolean,
+        default: false
+      }
     }
   }
 </script>

+ 5 - 2
components/main/Nav.vue

@@ -36,9 +36,12 @@
           </li>
         </ul>
       </a>
-      <nuxt-link to="/product/brand/brandList/ABC" class="item">
+      <nuxt-link to="/product/brand/brandList/A" class="item">
         <span>品牌墙</span>
       </nuxt-link>
+      <nuxt-link to="/pcb" class="item">
+        <span>pcb专区</span>
+      </nuxt-link>
       <nuxt-link to="/news" class="item">
         <span>优软快讯</span>
       </nuxt-link>
@@ -94,7 +97,7 @@
       display: inline-block;
       height: $nav-height;
       line-height: $nav-height;
-      width: 126px;
+      width: 122px;
       text-align: center;
       margin: 0;
       vertical-align: middle;

+ 47 - 20
components/main/Search.vue

@@ -1,23 +1,39 @@
 <template>
   <div class="search-box" :class="{'search-box2': !SelectItem}">
     <div class="input-group">
-      <select v-model="searchType" class="form-control select-type select-adder" v-if="SelectItem">
-        <option value="product">产品</option>
-        <option value="store">店铺</option>
-      </select>
-      <input v-model="keyword" type="text" class="search-input form-control input-primary"
-             :placeholder="searchType === 'product' ? '品牌/类目/型号' : '店铺名称'"
-             @focus.stop.prevent="onFocus()"
-             @blur.stop.prevent="onBlur()"
-             @keyup.40="onSelectChange(1)"
-             @keyup.38="onSelectChange(-1)"
-             @keyup.13="onSearch()"/>
-      <span class="input-group-btn" @click="onSearch()" style="z-index: 10">
-        <button class="btn btn-primary search-btn" type="button" :class="{'Isblue':!SelectItem}">搜&nbsp;索</button>
-      </span>
+      <template v-if="!isPcb">
+        <select v-model="searchType" class="form-control select-type select-adder" v-if="SelectItem">
+          <option value="product">产品</option>
+          <option value="store">店铺</option>
+        </select>
+        <input v-model="keyword" type="text" class="search-input form-control input-primary"
+               :placeholder="searchType === 'product' ? '品牌/类目/型号' : '店铺名称'"
+               @focus.stop.prevent="onFocus()"
+               @blur.stop.prevent="onBlur()"
+               @keyup.40="onSelectChange(1)"
+               @keyup.38="onSelectChange(-1)"
+               @keyup.13="onSearch()"/>
+        <span class="input-group-btn" @click="onSearch()" style="z-index: 10">
+          <button class="btn btn-primary search-btn" type="button" :class="{'Isblue':!SelectItem}">搜&nbsp;索</button>
+        </span>
+      </template>
+      <template v-if="isPcb">
+        <input v-model="keyword" type="text" class="search-input form-control input-primary"
+               :placeholder="'请输入pcb型号'"
+               @focus.stop.prevent="onFocus()"
+               @blur.stop.prevent="onBlur()"
+               style="width: 441px;"
+               @keyup.13="onSearch()"/>
+        <span class="input-group-btn" @click="onSearch()" style="z-index: 10">
+          <button class="btn btn-primary search-btn" type="button" :class="{'Isblue':!SelectItem}">搜&nbsp;索</button>
+        </span>
+      </template>
     </div>
-    <ul class="association" :class="{'association2': !SelectItem}" v-show="showAssociate && searchType == 'product'"
-        @mouseenter="associate.focus=true" @mouseleave="associate.focus=false">
+    <ul class="association"
+        :class="{'association2': !SelectItem, 'pcb-asso': isPcb}"
+        v-show="showAssociate && searchType == 'product'"
+        @mouseenter="associate.focus=true"
+        @mouseleave="associate.focus=false">
       <li v-if="similarKeywords.data.component && similarKeywords.data.component.length > 0" class="similar-title">型号:</li>
       <li v-for="(k, index) in similarKeywords.data.component" class="item"
           :class="{'active': index==associate.activeIndex}"
@@ -57,6 +73,10 @@
       SelectItem: {
         type: Boolean,
         default: true
+      },
+      isPcb: {
+        type: Boolean,
+        default: false
       }
     },
     data () {
@@ -182,10 +202,14 @@
         if (this.keyword) {
           this.associate.show = false
           this.$store.dispatch('resetSearchKeywords')
-          if (this.searchType === 'product') {
-            this.$router.push({path: '/search?w=' + encodeURIComponent(this.keyword)})
-          } else if (this.searchType === 'store') {
-            this.$router.push({path: '/searchStore?w=' + encodeURIComponent(this.keyword)})
+          if (this.isPcb) {
+            this.$router.push({path: '/pcb/search?w=' + encodeURIComponent(this.keyword)})
+          } else {
+            if (this.searchType === 'product') {
+              this.$router.push({path: '/search?w=' + encodeURIComponent(this.keyword)})
+            } else if (this.searchType === 'store') {
+              this.$router.push({path: '/searchStore?w=' + encodeURIComponent(this.keyword)})
+            }
           }
         }
       },
@@ -292,6 +316,9 @@
       border: $border;
       border-top-width: 0;
       z-index: 21;
+      &.pcb-asso {
+        left: 0;
+      }
 
       .item {
         padding: 0 15px;

+ 6 - 10
components/mobile/applyPurchase/SayPrice.vue

@@ -279,24 +279,20 @@
       checkValid: function () {
         this.validSayPrice.repliesLapQty = true
         this.validSayPrice.repliesPrice = true
-        this.validSayPrice.repliesleadtime = true
+        this.validSayPrice.leadtime = true
         for (let i = 0; i < this.sayPriceObj.replies.length; i++) {
-          console.log(this.sayPriceObj.replies)
-          if (!/^[0-9]+([.]{1}[0-9]+)?$/.test(this.sayPriceObj.replies[i].lapQty) || this.sayPriceObj.replies[i].lapQty === '') {
+          if (!this.sayPriceObj.replies[i].lapQty || !/^[0-9]+([.]{1}[0-9]+)?$/.test(this.sayPriceObj.replies[i].lapQty) || this.sayPriceObj.replies[i].lapQty === '') {
             this.validSayPrice.repliesLapQty = false
             break
-          } else if (!/^[0-9]+([.]{1}[0-9]+)?$/.test(this.sayPriceObj.replies[i].price) || this.sayPriceObj.replies[i].price === '') {
+          } else if (!this.sayPriceObj.replies[i].price || !/^[0-9]+([.]{1}[0-9]+)?$/.test(this.sayPriceObj.replies[i].price) || this.sayPriceObj.replies[i].price === '') {
             this.validSayPrice.repliesPrice = false
             break
           }
         }
-        if (/^\d+$/.test(this.validSayPrice.leadtime) || this.validSayPrice.leadtime === '') {
-          this.validSayPrice.repliesleadtime = false
+        if (!this.sayPriceObj.leadtime || !/^\d+$/.test(this.sayPriceObj.leadtime) || this.sayPriceObj.leadtime === '') {
+          this.validSayPrice.leadtime = false
         }
-        console.log(this.validSayPrice.repliesleadtime)
-        console.log(this.validSayPrice.repliesLapQty)
-        console.log(this.validSayPrice.repliesPrice)
-        return this.validSayPrice.repliesleadtime && this.validSayPrice.repliesLapQty && this.validSayPrice.repliesPrice
+        return this.validSayPrice.leadtime && this.validSayPrice.repliesLapQty && this.validSayPrice.repliesPrice
       },
       onRemind: function (str) {
         this.remindText = str

+ 7 - 0
components/mobile/applyPurchase/SayPriceInfo.vue

@@ -89,6 +89,7 @@
                 </tbody>
               </table>
               </div>
+              <div class="refused-txt" v-if="item.agreed === 0">拒绝理由:<span v-text="item.refusereason"></span></div>
               <!--<div class="price-level">
                 <p>价格梯度:<span>(pcs)</span></p>
                 <ul>
@@ -192,6 +193,7 @@
                   </tbody>
                 </table>
               </div>
+              <div class="refused-txt" v-if="purchaseDetail.agreed === 0">拒绝理由:<span v-text="purchaseDetail.refusereason"></span></div>
               <!--<div class="price-level vendor">
                 <p>价格梯度:<span>(pcs)</span></p>
                 <ul>
@@ -345,6 +347,11 @@
         overflow: hidden;
         max-height: 90%;
         position: relative;
+        .refused-txt {
+          span{
+            color: #ef5042;
+          }
+        }
         .base-info {
           margin: 0 auto;
           /*border-bottom: .18rem solid #f3f3f3;*/

+ 7 - 3
components/mobile/base/SearchHeader.vue

@@ -18,15 +18,15 @@
       </template>
     </ul>
     <ul v-if="emptyStatus && type == 'default' && keyword && keyword !== '' && showSimilarWord">
-      <template v-if="similarList.brand && similarList.brand.length">
+      <template v-if="similarList.brand && similarList.brand.length && (similarType == 'all' || similarType == 'brand')">
         <li class="title text-ellipse">品牌</li>
         <li class="text-ellipse" v-for="brand in similarList.brand.slice(0, 4)" @click="onSearch(brand.nameEn, 'brand', $event)">{{brand.nameEn}}</li>
       </template>
-      <template v-if="similarList.kind && similarList.kind.length">
+      <template v-if="similarList.kind && similarList.kind.length && (similarType == 'all' || similarType == 'kind')">
         <li class="title text-ellipse">类目(产品名称)</li>
         <li class="text-ellipse" v-for="kind in similarList.kind.slice(0, 4)" @click="onSearch(kind.nameCn, 'kind', $event)">{{kind.nameCn}}</li>
       </template>
-      <template v-if="similarList.component && similarList.component.length">
+      <template v-if="similarList.component && similarList.component.length && (similarType == 'all' || similarType == 'code')">
         <li class="title text-ellipse">型号</li>
         <li class="text-ellipse" v-for="code in similarList.component.slice(0, 4)" @click="onSearch(code.code, 'code', $event)">{{code.code}}</li>
       </template>
@@ -56,6 +56,10 @@
       outerKeyword: {
         type: String,
         default: ''
+      },
+      similarType: {
+        type: String,
+        default: 'all'
       }
     },
     data () {

+ 46 - 11
components/mobile/brand/BrandCenter.vue

@@ -1,9 +1,9 @@
 <template>
   <div>
-    <search-header @searchAction="onSearch" :placeholder="'请输入品牌名称'" :showSimilar="false"></search-header>
+    <search-header @searchAction="onSearch" :placeholder="'请输入品牌名称'" :similarType="'brand'"></search-header>
     <div class="mobile-brand-center mobile-content">
-      <div class="mobile-brand-wrap">
-        <div class="mobile-brand-header">
+      <div class="mobile-brand-wrap" :class="{'is-search': isSearch}">
+        <div class="mobile-brand-header" v-if="!isSearch">
           <img src="/images/mobile/@2x/brand/brandWall.png" alt="">
           <div class="mobile-brand-index" :class="{'scrolled': isScrolled, 'is-more': isScrolled && !isMore}">
             <p style="float: left">索引:</p>
@@ -23,10 +23,11 @@
         <div class="mobile-brand-list">
           <div>
             <div class="brand-initial">
-              <p v-text="activeIndex" :style="activeIndex === '0~9' ? 'font-size: .28rem': 'font-size: .32rem'"></p>
-              <span>
+              <p v-if="!isSearch" v-text="activeIndex" :style="activeIndex === '0~9' ? 'font-size: .28rem': 'font-size: .32rem'"></p>
+              <span v-if="!isSearch">
               {{activeIndex}}开头共<span>{{brandList.totalElements || 0}}</span>个品牌
             </span>
+              <span v-if="isSearch">搜索<span>{{showKeyword}}</span>,共有<span>{{brandList.totalElements || 0}}</span>个品牌</span>
             </div>
             <div class="brand-items" v-if="brandListTemplate.length">
               <nuxt-link :to="`/mobile/brand/${brand.uuid}/`" :key="brand.uuid" v-for="brand in brandListTemplate">
@@ -64,7 +65,9 @@
           keyword: ''
         },
         isChange: false,
-        brandListTemplate: []
+        brandListTemplate: [],
+        isSearch: false,
+        showKeyword: ''
       }
     },
     components: {
@@ -115,14 +118,28 @@
           this.isScrolled = scrolled > 200
         }
       },
+//      reloadData: function () {
+//        this.$store.dispatch('product/loadBrandsPager', {'initial': this.activeIndex, page: this.pageParams.page, count: this.pageParams.count, keyword: this.pageParams.keyword})
+//      },
       reloadData: function () {
-        this.$store.dispatch('product/loadBrandsPager', {'initial': this.activeIndex, page: this.pageParams.page, count: this.pageParams.count, keyword: this.pageParams.keyword})
+        !this.isSearch ? this.$store.dispatch('product/loadBrandsPager', {'initial': this.activeIndex, page: this.pageParams.page, count: this.pageParams.count, keyword: this.pageParams.keyword})
+          : this.$store.dispatch('product/loadBrandsPagerWithoutIndex', this.pageParams)
       },
       onSearch: function (keyObj) {
-        this.pageParams.keyword = keyObj.keyword
-        this.pageParams.page = 1
-        this.isChange = true
-        this.reloadData()
+        if (keyObj.keyword && keyObj.keyword !== '') {
+          this.pageParams.keyword = keyObj.keyword
+          this.pageParams.page = 1
+          this.isChange = true
+          this.isSearch = true
+          this.showKeyword = this.pageParams.keyword
+          this.reloadData()
+        } else {
+          this.isSearch = false
+          this.pageParams.page = 1
+          this.isChange = true
+          this.pageParams.keyword = ''
+          this.reloadData()
+        }
       },
       onPullUpAction: function () {
         this.pageParams.page++
@@ -254,6 +271,24 @@
           }
         }
       }
+      &.is-search {
+        width: 100%;
+        padding-top: .5rem;
+        .mobile-brand-header {
+          height: auto;
+        }
+        .mobile-brand-list {
+          .brand-initial {
+            line-height: .5rem;
+            > span {
+              font-size: .26rem;
+             > span {
+               color: red;
+             }
+            }
+          }
+        }
+      }
     }
   }
 

+ 85 - 279
components/mobile/common/StatisticsMobile.vue

@@ -1,228 +1,26 @@
-<!--<template>
+<template>
   <div class="statistics">
-    <ul class="list-inline" :style="{top: widthTop + 'rem'}" :class="{no_tran: widthTop == 2.4}">
-      <li v-for="(item, index) in itemData" :style="index % 2 == 0 ? 'text-align: right;padding-right: .3rem;' : 'text-align: left;padding-left: .3rem;'">
-        <span class="number" v-if="item.type === 2">
-          <img :src="`/images/mobile/@2x/home/count${index + 1}.jpg`" alt="">
-          <span v-html="formatDouble(item.count)" style="vertical-align: middle"></span>
-          <span class="unit">条</span>
-        </span>
-        <span class="number" v-else>
-          <img :src="`/images/mobile/@2x/home/count${index + 1}.jpg`" alt="">
-          <span v-html="formatNumber(item.count, index)" style="vertical-align: middle"></span>
+    <ul class="list-inline pull-left" ref="pingdanListWrapperL" :style="'top: -' + 1 * timerIndexL + 'rem'" :class="{'topL': isTopL}">
+      <li v-for="(item, index) in itemLeft">
+        <span  class="number">
+          <span class="name" v-html="nameLeft[index]"></span>
+          <span class="num" v-html="formatNumber(item.count, item.type)"></span>
           <span class="unit" v-if="item.type === 3">家</span>
         </span>
       </li>
     </ul>
-    <ul class="list-inline" :style="{top: widthTop + 'rem'}" :class="{no_tran: widthTop == 2.4}">
-      <li v-for="(item, index) in itemData" :style="index % 2 == 0 ? 'text-align: right;padding-right: .3rem;' : 'text-align: left;padding-left: .3rem;'">
+    <ul class="list-inline pull-right" ref="pingdanListWrapperR" :style="'top: -' + 1 * timerIndexR + 'rem'" :class="{'topR': isTopR}">
+      <li v-for="(item, index) in itemRight">
         <span class="number" v-if="item.type === 2">
-          <img :src="`/images/mobile/@2x/home/count${index + 1}.jpg`" alt="">
-          <span v-html="formatDouble(item.count)" style="vertical-align: middle"></span>
+          <span class="name" v-html="nameRight[index]"></span>
+          <span class="month" v-if="item.id === '上月询价单'">(上月)</span>
+          <span class="month" v-if="item.id === '本月询价单'">(本月)</span>
+          <span class="num" v-html="formatDouble(item.count)"></span>
           <span class="unit">条</span>
         </span>
         <span class="number" v-else>
-          <img :src="`/images/mobile/@2x/home/count${index + 1}.jpg`" alt="">
-          <span v-html="formatNumber(item.count, index)" style="vertical-align: middle"></span>
-          <span class="unit" v-if="item.type === 3">家</span>
-        </span>
-      </li>
-    </ul>
-  </div>
-</template>
-<script>
-  export default {
-    name: 'StatisticsView',
-    data () {
-      return {
-        step: 1,
-        widthTop: 0,
-        timerIndex: 0,
-        timer: {}, // 定时器实体
-        imgbox: {
-            'src': ''
-        }
-      }
-    },
-    mounted () {
-      this.$nextTick(() => {
-        this.changeInterval()
-      })
-    },
-    methods: {
-      changeInterval () {
-        setInterval(() => {
-          this.widthTop += -0.6
-          if (this.widthTop === -2.4) {
-            this.widthTop = 0
-          }
-        }, 3000)
-      },
-      formatNumber (num, type) {
-        if (num.toString().indexOf('E') !== -1) {
-          let arr = num.toString().split('E')
-          num = arr[0] * Math.pow(10, arr[1])
-        }
-        if (num > 99999999) {
-          let str2 = num.toString()
-          num = Math.floor(num / 100000000)
-          if (parseInt(str2.charAt(str2.length - 8)) > 8) {
-            num = num + 1
-          }
-          num = num + '<span style="color: #333">亿</span>'
-        } else if (num > 9999) {
-          let str = num.toString()
-          num = Math.floor(num / 10000)
-          if (parseInt(str.charAt(str.length - 4)) > 4) {
-            num = num + 1
-          }
-          num += '<span style="color: #333">万</span>'
-        } else {
-          if (type === 6 || type === 7) {
-            num += '<span style="color: #333">元</span>'
-          } else if (type === 0 || type === 1 || type === 2) {
-            num += '<span style="color: #333">个</span>'
-          } else {
-            num += ''
-          }
-        }
-        return num
-      },
-      formatDouble (num) {
-        if (num.toString().indexOf('E') !== -1) {
-          let arr = num.toString().split('E')
-          num = arr[0] * Math.pow(10, arr[1])
-        }
-        if (num > 99999999) {
-          num = (num / 100000000).toFixed(2).slice(num.length - 1, 4) + '<span style="color: #333">亿</span>'
-        } else if (num > 9999) {
-          num = (num / 10000).toFixed(2).slice(num.length - 1, 4) + '<span style="color: #333">万</span>'
-        } else {
-          num += ''
-        }
-        return num
-      }
-    },
-    computed: {
-      allCount () {
-        return this.$store.state.count.allCount.data
-      },
-      inquirySheet () {
-        let sheetNum = this.$store.state.count.inquirySheet.data.count
-        return this.formatDouble(sheetNum)
-      },
-      inquirySheetLast () {
-        let lastSheetNum = this.$store.state.count.inquirySheetLast.data.count
-        return this.formatDouble(lastSheetNum)
-      },
-      all () {
-        let count = this.$store.state.supplier.merchant.merchantAll.data
-        return count.content ? count.totalElements : '0'
-      },
-      counts () {
-        return this.$store.state.product.common.counts
-      },
-      itemData () {
-        let str = []
-        if (this.counts.data) {
-          this.counts.data.forEach((value, key, $data) => {
-            str.push({id: $data[key].item, count: $data[key].count, type: 1})
-          })
-        }
-        str.push({id: '供应商', count: this.all ? this.all : 0, type: 3})
-        str.push({id: '本月询价单', count: this.$store.state.count.inquirySheet.data ? this.$store.state.count.inquirySheet.data.count : 0, type: 2})
-        str.push({id: '上月询价单', count: this.$store.state.count.inquirySheetLast.data ? this.$store.state.count.inquirySheetLast.data.count : 0, type: 2})
-        if (this.allCount) {
-          this.allCount.forEach((value, key, $data) => {
-            str.push({id: $data[key].item, count: $data[key].count, type: 1})
-          })
-        }
-        str = [str[1], str[2], str[0], ...str.slice(3, 6), str[7], str[6]]
-        return str
-      }
-    }
-  }
-</script>
-<style lang="scss" scoped>
-  .statistics{
-    position:relative;
-  /*  height: 0.6rem;*/
-    height: 8rem;
-    border-radius:.3rem;
-    background: #fff;
-    margin:0 .05rem .2rem;
-    /*overflow: hidden;*/
-    background: url('/images/mobile/@2x/home/countbg.png') no-repeat center;
-    ul{
-      float: left;
-      width:50%;
-      position:absolute;
-      transition: .5s all linear;
-      border: 1px solid red;
-      &:no_tran{
-        transition:none;
-      }
-      li{
-        width:100%;
-        height:.6rem;
-        line-height: .6rem;
-        font-size: .28rem;
-        font-weight: bold;
-        white-space: nowrap;
-        overflow: hidden;
-        vertical-align:top;
-        &:nth-child(even){
-          &::before{
-            content: '';
-            display: inline-block;
-            width: 0.02rem;
-            height: 0.3rem;
-            background-color: #9c9c9c;
-            position: relative;
-            top: .1rem;
-            left: -.3rem;
-          }
-        }
-        span{
-          img {
-            height: .3rem;
-          }
-          &.number{
-            display: inline-block;
-            color:red;
-            font-size: 0.32rem;
-            height: .6rem;
-            vertical-align:middle;
-            line-height:.6rem;
-            .unit{
-              color: #333;
-              vertical-align: middle;
-            }
-          }
-        }
-      }
-    }
-  }
-</style>-->
-<template>
-  <div class="statistics">
-    <ul class="list-inline pull-left" ref="pingdanListWrapper" :style="{top: topLeft + 'rem'}" :class="{no_tran: topLeft == 2.4}">
-      <li v-for="(item, index) in itemData" v-if="index <= 4">
-        <span  class="number">
-          <span class="name" v-html="count[index]"></span>
-          <span class="num" v-html="formatNumber(item.count, index)"></span>
-          <span class="unit" v-if="item.type === 3">家</span>
-        </span>
-      </li>
-    </ul>
-    <ul class="list-inline pull-right" ref="pingdanListWrapper" :style="{top: topRight + 'rem'}" :class="{no_tran: topRight == 2.4}">
-      <li v-for="(item, index) in itemData" v-if="index > 4">
-        <span class="number">
-          <span class="name" v-html="count[index]"></span>
-          <span class="month" v-if="index === 5">(上月)</span>
-          <span class="month" v-if="index === 6">(本月)</span>
-          <span class="num" v-html="formatDouble(item.count)"></span>
-          <span class="unit" v-if="item.type === 2">条</span>
+          <span class="name" v-html="nameRight[index]"></span>
+          <span class="num" v-html="formatNumber(item.count, item.type)"></span>
         </span>
       </li>
     </ul>
@@ -235,11 +33,18 @@
     data () {
       return {
         step: 1,
-        count: ['现货', '品牌', '规格书', '供应商', '店铺', '询价求购', '询价求购', '上年交易', '本年交易'],
+        nameLeft: ['现货', '品牌', '规格书', '供应商', '店铺'],
+        nameRight: ['询价求购', '询价求购', '上年交易', '本年交易'],
         topLeft: 0,
         topRight: 0,
-        timerIndex: 0,
-        timer: {}, // 定时器实体
+//        timer: {},
+//        timerIndex: 0,
+        timerIndexL: 0,
+        timerIndexR: 0,
+        isTopL: false,
+        isTopR: false,
+        timerL: {},
+        timerR: {}, // 定时器实体
         imgbox: {
             'src': ''
         }
@@ -247,78 +52,61 @@
     },
     mounted () {
       this.$nextTick(() => {
-        this.changeIntervalL()
-        this.changeIntervalR()
+        this.changeIntervalL(true)
+        this.changeIntervalR(true)
       })
     },
     methods: {
-//      changeIntervalL () {
-//        setInterval(() => {
-//          this.topLeft += -1
-//          let arr1 = this.itemData.slice(0, 5)
-//          let arr2 = arr1.shift()
-//          arr1.push(arr2)
-//          if (this.topLeft === -5) {
-//            this.topLeft = 0
-//          }
-//        }, 2400)
-//      },
-//      changeIntervalR () {
-//        setInterval(() => {
-//          this.topRight += -1
-//          let arr1 = this.itemData.slice(5, 9)
-//          let arr2 = arr1.shift()
-//          arr1.push(arr2)
-//          this.itemDataTemp.push(this.itemData)
-//          if (this.topRight === -4) {
-//            this.topRight = 0
-//          }
-//        }, 3000)
-//      },
       changeIntervalL: function (flag) {
         if (flag) {
-          this.timer = setInterval(() => {
-            this.isTop = false
+          this.timerL = setInterval(() => {
+            this.isTopL = false
             let isChange = true
-            this.timerIndex++
-            let _transitionEvent = whichTransitionEvent()
-            _transitionEvent && this.$refs.pingdanListWrapper[0].addEventListener(
-              _transitionEvent, () => {
-                console.log(isChange)
-                if (isChange) {
-                  let title = this.itemData.slice(0, 5).shift()
-                  this.title.push(title)
-                  this.timerIndex = 0
-                  isChange = false
-                  this.isTop = true
-                }
-              })
+            this.timerIndexL++
+            if (this.$refs.pingdanListWrapperL) {
+              let _transitionEvent = whichTransitionEvent()
+              _transitionEvent && this.$refs.pingdanListWrapperL.addEventListener(
+                _transitionEvent, () => {
+                  if (isChange) {
+                    let title = this.itemLeft.shift()
+                    let name = this.nameLeft.shift()
+                    this.itemLeft.push(title)
+                    this.nameLeft.push(name)
+                    this.timerIndexL = 0
+                    isChange = false
+                    this.isTopL = true
+                  }
+                })
+           }
           }, 2400)
         } else {
-          clearInterval(this.timer)
+          clearInterval(this.timerL)
         }
       },
       changeIntervalR: function (flag) {
         if (flag) {
-          this.timer = setInterval(() => {
-            this.isTop = false
+          this.timerR = setInterval(() => {
+            this.isTopR = false
             let isChange = true
-            this.timerIndex++
-            let _transitionEvent = whichTransitionEvent()
-            _transitionEvent && this.$refs.pingdanListWrapper[0].addEventListener(
-              _transitionEvent, () => {
-                console.log(isChange)
-                if (isChange) {
-                  let title = this.itemData.slice(5, 9).shift()
-                  this.title.push(title)
-                  this.timerIndex = 0
-                  isChange = false
-                  this.isTop = true
-                }
-              })
+            this.timerIndexR++
+            if (this.$refs.pingdanListWrapperR) {
+              let _transitionEvent = whichTransitionEvent()
+              _transitionEvent && this.$refs.pingdanListWrapperR.addEventListener(
+                _transitionEvent, () => {
+                  if (isChange) {
+                    let title = this.itemRight.shift()
+                    let name = this.nameRight.shift()
+                    this.itemRight.push(title)
+                    this.nameRight.push(name)
+                    this.timerIndexR = 0
+                    isChange = false
+                    this.isTopR = true
+                  }
+                })
+            }
           }, 3000)
         } else {
-          clearInterval(this.timer)
+          clearInterval(this.timerR)
         }
       },
       formatNumber (num, type) {
@@ -341,9 +129,9 @@
           }
           num += '万'
         } else {
-          if (type >= 7) {
+          if (type === 4) {
             num += '元'
-          } else if (type <= 2) {
+          } else if (type === 1) {
             num += '个'
           } else {
             num += ''
@@ -402,12 +190,18 @@
         str.push({id: '上月询价单', count: this.$store.state.count.inquirySheetLast.data ? this.$store.state.count.inquirySheetLast.data.count : 0, type: 2})
         if (this.allCount) {
           this.allCount.forEach((value, key, $data) => {
-            str.push({id: $data[key].item, count: $data[key].count, type: 1})
+            str.push({id: $data[key].item, count: $data[key].count, type: 4})
           })
         }
         str.push({id: '店铺', count: this.list ? this.list : 0, type: 3})
         str = [str[1], str[0], str[2], str[3], str[8], str[5], str[4], str[6], str[7]]
         return str
+      },
+      itemLeft () {
+        return this.itemData.slice(0, 5)
+      },
+      itemRight () {
+        return this.itemData.slice(5, 9)
       }
     }
   }
@@ -426,6 +220,18 @@
       width:50%;
       position:relative;
       transition: .5s all linear;
+      &.topL {
+        transition: top 0s;
+        -moz-transition: top 0s; /* Firefox 4 */
+        -webkit-transition: top 0s; /* Safari and Chrome */
+        -o-transition: top 0s; /* Opera */
+      }
+      &.topR {
+        transition: top 0s;
+        -moz-transition: top 0s; /* Firefox 4 */
+        -webkit-transition: top 0s; /* Safari and Chrome */
+        -o-transition: top 0s; /* Opera */
+      }
       &:first-child{
         margin-left: .0rem;
       }

+ 28 - 0
components/pcb/Nav.vue

@@ -0,0 +1,28 @@
+<template>
+  <div class="pcb-nav">
+    <span>
+      <a href="">pcb商城</a>
+    </span>
+    <span>
+      <i class="iconfont icon-arrow-right"></i><a href="">半固化片</a>
+    </span>
+    <span><i class="iconfont icon-arrow-right"></i><span>sdfkljalsfjasld</span></span>
+  </div>
+</template>
+<style lang="scss" scoped>
+  .pcb-nav {
+    width: 1190px;
+    margin: 18px auto 0;
+    height: 30px;
+    line-height: 30px;
+    font-size: 12px;
+    > span {
+      a {
+        color: #418cf6;
+      }
+      span {
+        color: #999;
+      }
+    }
+  }
+</style>

+ 208 - 0
components/pcb/PcbNavSearch.vue

@@ -0,0 +1,208 @@
+<template>
+  <div class="input-group">
+    <input v-model="keyword" type="text" class="search-input form-control"
+           @focus.stop.prevent="onFocus()"
+           @blur.stop.prevent="onBlur()"
+           @keyup.40="onSelectChange(1)"
+           @keyup.38="onSelectChange(-1)"
+           @keyup.13="onSearch()"/>
+    <span @click="onSearch()">
+          <button class="btn search-btn" type="button"><span class="glyphicon glyphicon-search" aria-hidden="true"></span> </button>
+       </span>
+    <div class="angle"></div>
+    <a class="close" @click="close"><img src="/images/search/search-close.png"></a>
+    <ul class="association" v-show="showAssociate">
+      <li v-for="(k, index) in similarKeywords.data" class="item"
+          :class="{'active': index==associate.activeIndex}"
+          @click.stop.prevent="onAssociateClick(k)">{{ k }}
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+  export default {
+    name: 'search',
+    data () {
+      return {
+        keyword: '',
+        inputValue: '',
+        select: 'product',
+        searchType: 'product',
+        associate: {
+          show: false,
+          activeIndex: null
+        }
+      }
+    },
+    computed: {
+      similarKeywords () {
+        return this.$store.state.search.keywords
+      },
+      showAssociate () {
+        return this.associate.show && this.similarKeywords.data && this.similarKeywords.data.length
+      },
+      floors () {
+        return this.$store.state.floor.list.data
+      },
+      bgUrl () {
+        return this.background && this.background !== '' ? this.background : this.floors[1].items[0].pictureUrl
+      }
+    },
+    watch: {
+      'keyword': {
+        handler (val, oldVal) {
+          let keywords = this.similarKeywords.data
+          if (!keywords || !keywords.length || this.associate.activeIndex === null || val !== keywords[this.associate.activeIndex]) {
+            this.onChange()
+          }
+        }
+      }
+    },
+    methods: {
+      close: function () {
+        this.keyword = ''
+      },
+      onFocus () {
+        this.associate.show = true
+      },
+      onBlur () {
+        this.associate.show = false
+      },
+      onSelectChange (count) {
+        let keywords = this.similarKeywords.data
+        if (keywords && keywords.length) {
+          let index = this.associate.activeIndex
+          if (index === null) {
+            index = -1
+          }
+          index += count
+          if (index >= keywords.length) {
+            index = 0
+          } else if (index < 0) {
+            index = keywords.length - 1
+          }
+          this.associate.activeIndex = index
+          this.keyword = keywords[index]
+        }
+      },
+      onChange () {
+        this.associate.activeIndex = null
+        if (!this.keyword) {
+          this.associate.show = false
+          this.$store.dispatch('resetSearchKeywords')
+        } else {
+          this.searchKeywords()
+        }
+      },
+      searchKeywords () {
+        this.associate.show = true
+        this.$store.dispatch('searchKeywords', { keyword: this.keyword })
+      },
+      onSearch () {
+        document.getElementsByClassName('search-input')[0].blur()
+        if (this.keyword) {
+          this.associate.show = false
+          this.$store.dispatch('resetSearchKeywords')
+          this.$router.push({path: '/pcb/search?w=' + encodeURIComponent(this.keyword)})
+        }
+      },
+      onAssociateClick (word) {
+        this.keyword = word
+        this.onSearch()
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  @import '~assets/scss/variables';
+  .input-group {
+    width: 540px;
+    position: relative;
+  }
+  .select {
+    font-size: 16px;
+    color: #333;
+    width: 70px;
+    height: 30px;
+    border-radius: 25px 0 0 25px;
+    border: 1px solid #fff;
+    float: left;
+    padding-left: 2%;
+    line-height: 30px;
+  }
+  .close {
+    position: absolute;
+    top: 3px;
+    right: 55px;
+    z-index: 1000;
+    color: #000;
+  }
+  .angle {
+    position: absolute;
+    top: 13px;
+    left: 52px;
+    width: 0;
+    height: 0;
+    border-left: 5px solid transparent;
+    border-right: 5px solid transparent;
+    border-top: 5px solid #3c7cf5;
+    &:after{
+      content:'';
+      position: relative;
+      display: block;
+      width: 3px;
+      height: 24px;
+      top: -15px;
+      left: 9px;
+      border-right: 2px solid #3c7cf5;
+    }
+  }
+  .search-input {
+    font-size: 16px;
+    height: 30px;
+    border-radius: 25px 0 0 25px;
+    width: 488px !important;
+    border: 1px solid #fff;
+    padding-right: 25px;
+  }
+  .btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus {
+    outline: none;
+    border-color: transparent;
+    box-shadow:none;
+  }
+  .search-btn {
+    height: 30px;
+    font-size: 22px;
+    width: 50px;
+    margin-left: 0;
+    background: #fff;
+    border: 1px solid #fff;
+    border-radius: 0 25px 25px 0;
+  }
+  .glyphicon-search{
+    color: #3c7cf5;
+  }
+  .association {
+    position: absolute;
+    background: $white;
+    border: $border;
+    border-top-width: 0;
+    z-index: 21;
+    width: 606px;
+    top: 214px;
+    left: 2px;
+    .item {
+      padding: 0 15px;
+      line-height: 30px;
+      cursor: pointer;
+      text-align: left;
+
+      &.active {
+        background-color: $dark-bg;
+      }
+      &:hover {
+        background-color: $grey-bg;
+      }
+    }
+  }
+</style>

+ 267 - 0
components/pcb/brand/BrandList.vue

@@ -0,0 +1,267 @@
+<template>
+  <div class="component-list container">
+    <nuxt-link to="/product/brand/_code"><div class="type-list">产品列表</div></nuxt-link>
+    <div class="input-group">
+      <input  type="search" class="input-sm form-control" placeholder="请输入型号" title="code"
+              v-model="searchCode" @search="goodsSearch(searchCode)"/>
+      <span class="input-group-btn">
+					<button class="search btn btn-default" type="button" @click="goodsSearch(searchCode)">搜索</button>
+			</span>
+    </div>
+    <table class="table">
+      <thead>
+      <tr class="bgf7">
+        <th width="330">产品名称</th>
+        <th width="330">价格</th>
+        <th width="330">操作</th>
+      </tr>
+      </thead>
+      <tbody>
+      <tr class="text-center" v-for="item in list.content">
+        <td><nuxt-link :to="`/pcb/product/${item.productid}/${item.batchCode}`"><span>{{item.code}}</span></nuxt-link></td>
+        <td>
+          <div v-if="item.prices" v-text="item.currencyName === 'RMB' ? '¥' + item.prices[0].rMBPrice : '$' + item.prices[0].uSDPrice"></div>
+          <div v-else>-</div>
+        </td>
+        <!--<td><a :href="item.attach" target="_blank"><button class="btn btn-default"  :disabled="!item.attach" :class="{'disabledbtn':!item.attach}">Datasheet手册</button></a></td>-->
+        <td>
+          <button class="btn btn-default applay" @click="addToCar(item)">加入购物车</button>
+        </td>
+      </tr>
+      <tr v-if="!list.content || list.content.length === 0">
+        <td colspan="10" class="text-center">
+          <div class="empty">
+            <div class="empty-img">
+              <img src="/images/brandList/empty-cart.png">
+            </div>
+            <div class="empty-info">
+              <p class="grey f16"> 暂无器件信息 </p>
+              <i class="fa fa-mail-reply fa-xs"></i>&nbsp;<a href="javascript:history.go(-1)">返回上一页</a>
+            </div>
+          </div>
+        </td>
+      </tr>
+      </tbody>
+    </table>
+    <div style="float: right;">
+      <page :total="list.totalElements" :page-size="pageParams.count"
+            :current="pageParams.page" @childEvent="handleCurrentChange"></page>
+    </div>
+  </div>
+</template>
+<script>
+  import Page from '~components/common/page/pageComponent.vue'
+  import { buyOrCar } from '~utils/baseUtils'
+  export default {
+    name: 'BrandComponent',
+    data () {
+      return {
+        pageParams: {
+          page: 1,
+          count: 10,
+          filter: {}
+        },
+        searchCode: ''
+      }
+    },
+    props: ['kindid'],
+    components: {
+      Page
+    },
+    computed: {
+      lists () {
+        return this.$store.state.brandComponent.component
+      },
+      list () {
+        return this.lists.data
+      },
+      brand () {
+        return this.$store.state.brandDetail.detail.data
+      }
+    },
+    methods: {
+      goodsSearch (keyword) {
+        this.pageParams.page = 1
+        this.pageParams.filter.code = keyword
+        this.pageCmpGoods(this.pageParams)
+      },
+      handlerCurrentNode () {
+        this.searchCode = ''
+        this.pageParams.page = 1
+        this.pageCmpGoods(this.pageParams)
+      },
+      async pageCmpGoods (params) {
+//      pageCmpGoods (params) {
+//        params.filter.brandid = this.brand.id
+        let param = {
+          branduuid: this.brand.uuid,
+          count: this.pageParams.count,
+          page: this.pageParams.page,
+          kindid: this.kindid,
+          keyword: this.searchCode || null
+        }
+        let { data } = await this.$http.get('/api/product/goods', {params: param})
+        this.$store.commit('brandComponent/GET_COMPONENT_SUCCESS', data)
+//        this.$http.get('/api/product/component/list', { params }).then(response => {
+//          this.$store.commit('brandComponent/GET_COMPONENT_SUCCESS', response)
+//        })
+      },
+      handleCurrentChange (page) {
+        this.pageParams.page = page
+        this.pageParams.filter.brandid = this.brand.id
+        this.pageCmpGoods(this.pageParams)
+      },
+      toAttach: function (url) {
+        if (url === '1') {
+          this.$http.get('/login/page', {params: {returnUrl: window.location.href}}).then(response => {
+            if (response.data) {
+              window.location.href = response.data.content + '&baseUrl=' + encodeURIComponent(window.location.protocol + '//' + window.location.host + response.data.baseUrl)
+            }
+          })
+        } else {
+          window.open(url)
+        }
+      },
+      addToCar: function (item) {
+        buyOrCar(false, null, this, item)
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .component-list {
+    float: left;
+    margin-left: 20px;
+    width: 970px;
+    .type-list{
+      height: 34px;
+      width: 150px;
+      border: 1px solid #3a75f5;
+      background-color: #3a75f5;
+      float: left;
+      color: #fff;
+      line-height: 34px;
+      text-align: center;
+      font-size: 14px;
+    }
+    .agency {
+      height: 34px;
+      width: 150px;
+      border: 1px solid #3a75f5;
+      background-color: #fff;
+      float: left;
+      color: #3a75f5;
+      line-height: 34px;
+      text-align: center;
+      font-size: 14px;
+    }
+    .input-group {
+      width: 300px;
+      float: right;
+      border-radius: 3px;
+      .form-control{
+        border-radius: 3px;
+        height: 34px;
+      }
+      .input-group-btn .search{
+        background: #3a75f5;
+        color: #fff;
+        height: 34px;
+        border-radius: 3px;
+        padding: 3px 24px;
+      }
+    }
+  }
+
+  .component-list table {
+    margin-top: 10px;
+    width: 970px;
+    border: 1px solid #e8e8e8;
+  }
+  .component-list table>thead {
+    height: 40px;
+  }
+  .component-list table>thead>th {
+    text-align: center;
+  }
+  .component-list table tbody tr{
+    text-align: center;
+    height: 60px;
+  }
+  .component-list table tbody tr:hover{
+    background-color: #f6f9ff;
+  }
+  .component-list .table>tbody>tr>td{
+    vertical-align: middle;
+    border-top: #e8e8e8 1px solid;
+  }
+  .component-list table tbody tr td a{
+    color: #333;
+    font-size: 14px;
+    &:hover{
+      color: #5078cb;
+    }
+  }
+  .component-list .btn-default {
+    color: #214797;
+    font-size: 12px;
+    line-height: 12px;
+    height: 30px;
+  }
+  .component-list .disabledbtn {
+    color: #A0A0A0;
+  }
+  .component-list .applay {
+    color: #3a75f5;
+    font-size: 12px;
+    line-height: 12px;
+    height: 30px;
+    width: 80px;
+    padding: 0;
+    border: 1px solid #3a75f5;
+    border-radius: 0;
+  }
+  .component-list td.text-center{
+    padding: 30px 0;
+    font-size: 20px;
+    line-height: 40px;
+  }
+  .bgf7{
+    height: 40px;
+    th{
+      background: #f7f7f7;
+      border-bottom: none !important;
+      font-size: 14px;
+      text-align: center;
+      color: #333;
+      vertical-align: middle;
+    }
+  }
+  .component-list .empty{
+    overflow: hidden;
+    text-align: center;
+    margin: 0 auto;
+  }
+  .component-list .empty-img{
+    float: left;
+    margin-left: 335px;
+  }
+  .component-list .empty-info{
+    float: left;
+    line-height: 10px;
+    width: 143px;
+    margin-top: 30px;
+  }
+  .empty-info .grey{
+    color: #999;
+    font-size: 14px;
+  }
+  .component-list .empty-info a{
+    font-size: 14px;
+    color: #5078cb;
+  }
+  .component-list .empty-info i{
+    font-size: 14px;
+    color: #5078cb;
+  }
+</style>

+ 93 - 0
components/pcb/home/Intro.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="pcb-intro">
+    <p class="intro-title">PCB商家介绍<span>PCB Business Introduction</span></p>
+    <div class="item name">
+      <a>
+        <img src="/images/pcb/test-logo.png" alt="">
+      </a>
+      <p>深圳市英唐致盈供应链管理有限公司</p>
+    </div>
+    <div class="item intro">
+      深圳市英唐致盈供应链管理有限公司经营范围: 供应链管理及其相关的信息咨询;受托资产管理(不含证券、保险、基金、金融业务及其它限制项目);企业管理咨询(不含人才中介服务);经营电子商务(涉及前置行政许可的,须取得前置性行政许可文件后方可经营);国内贸易、货物及技术进出口。
+    </div>
+  </div>
+</template>
+<style lang="scss" scoped>
+  .pcb-intro {
+    background: url('/images/pcb/intro-bg.png') no-repeat;
+    background-size: cover;
+    margin-top: 58px;
+    height: 274px;
+    text-align: center;
+    .intro-title {
+      height: 68px;
+      line-height: 68px;
+      font-size: 30px;
+      text-align: center;
+      font-weight: bold;
+      span {
+        margin-left: 10px;
+        font-size: 12px;
+      }
+    }
+    .item {
+      display: inline-block;
+      height: 157px;
+      vertical-align: middle;
+    }
+    .name {
+      width: 183px;
+      margin-right: 63px;
+      margin-top: 14px;
+      a {
+        width: 183px;
+        height: 94px;
+        line-height: 88px;
+        background: #fff;
+        border-radius: 3px;
+        border: 2px solid #d8c7b3;
+        display: block;
+        img {
+          max-width: 183px;
+          max-height: 88px;
+        }
+      }
+      p {
+        font-size: 18px;
+        font-weight: bold;
+        margin-top: 26px;
+      }
+    }
+    .intro {
+      position: relative;
+      width: 842px;
+      background: #fff;
+      /*-webkit-box-shadow: 0 0 10px 3px #dacab6;
+      -moz-box-shadow: 0 0 10px 3px #dacab6;
+      box-shadow: 0 0 10px 3px #dacab6;*/
+      padding: 24px 18px 20px 25px;
+      text-align: left;
+      line-height: 25px;
+      &::before {
+        content: '';
+        position: absolute;
+        border: {
+          top: 34px solid #f0e7de;
+          right: 34px solid transparent;
+        };
+        left: 0;
+        top: 0;
+      }
+      &::after {
+        content: '';
+        position: absolute;
+        border: {
+          right: 34px solid #fbf9f7;
+          top: 34px solid transparent;
+        };
+        right: 0;
+        bottom: 0;
+      }
+    }
+  }
+</style>

+ 53 - 0
components/pcb/home/Kinds.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="pcb-kinds">
+    <ul class="pk-list">
+      <li class="pk-item" v-for="kind in kinds">
+        <nuxt-link :to="`/pcb/search/?w=${encodeURIComponent(kind.nameCn)}`">{{kind.nameCn}}<i class="icon-arrow-right iconfont"></i></nuxt-link>
+      </li>
+    </ul>
+    <img class="fr" src="/images/pcb/banner.png" alt="">
+  </div>
+</template>
+<script>
+  export default {
+    computed: {
+      kinds () {
+        return this.$store.state.pcb.kindsData.kinds.data
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  $height: 300px;
+    .pcb-kinds {
+      width: 1184px;
+      margin: 1px auto 0;
+      .pk-list {
+        width: 230px;
+        height: $height;
+        overflow-y: hidden;
+        border-radius: 4px;
+        border: 1px solid #376ff3;
+        margin-right: 2px;
+        display: inline-block;
+        .pk-item {
+          height: 50px;
+          line-height: 50px;
+          border-bottom: 1px solid rgba(153, 153, 153, .32);
+          text-align: center;
+          a {
+            color: #666;
+          }
+          .iconfont {
+            float: right;
+            margin-right: 18px;
+          }
+        }
+      }
+      .fr {
+        width: 952px;
+        height: $height;
+        border-radius: 4px;
+      }
+    }
+</style>

+ 86 - 0
components/pcb/home/RecommendBrand.vue

@@ -0,0 +1,86 @@
+<template>
+  <div class="recommend-brand">
+    <ul>
+      <li>
+        <div>
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p>Panasonic(松下)</p>
+      </li>
+      <li>
+        <div>
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p>Panasonic(松下)</p>
+      </li>
+      <li>
+        <div>
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p>Panasonic(松下)</p>
+      </li>
+      <li>
+        <div>
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p>Panasonic(松下)</p>
+      </li>
+      <li>
+        <div>
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p>Panasonic(松下)</p>
+      </li>
+    </ul>
+  </div>
+</template>
+<style lang="scss" scoped>
+  .recommend-brand {
+    background: url('/images/pcb/recommend-brand.png') no-repeat;
+    width: 1190px;
+    height: 422px;
+    margin: 48px auto 0;
+    padding-top: 100px;
+    ul {
+      width: 1173px;
+      height: 289px;
+      margin: 0 auto;
+      padding: 40px 22px;
+      background: #fff;
+      li {
+        float: left;
+        margin-left: 7px;
+        width: 220px;
+        height: 208px;
+        -webkit-box-shadow: 0 0 5px 0 rgba(0, 0, 0, .1);
+        -moz-box-shadow: 0 0 5px 0 rgba(0, 0, 0, .1);
+        box-shadow: 0 0 5px 0 rgba(0, 0, 0, .1);
+        border-radius: 4px;
+        cursor: pointer;
+        border: 1px solid #fff;
+        &:hover {
+          border-color: #fa524b;
+          p {
+            font-weight: bold;
+          }
+        }
+        &:first-child {
+          margin-left: 0;
+        }
+        div {
+          width: 114px;
+          height: 108px;
+          line-height: 108px;
+          margin: 31px auto 26px;
+          img {
+            max-width: 114px;
+            max-height: 108px;
+          }
+        }
+        p {
+          text-align: center;
+        }
+      }
+    }
+  }
+</style>

+ 106 - 0
components/pcb/home/floors/Floor.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="floor">
+    <ul>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+      <li class="list-item">
+        <div class="img">
+          <img src="/images/pcb/test-logo.png" alt="">
+        </div>
+        <p class="text">HYCO组合式金属喷嘴</p>
+        <span class="text price">¥699</span>
+      </li>
+    </ul>
+  </div>
+</template>
+<style lang="scss" scoped>
+  $img-size: 215px;
+  .floor {
+    .list-item {
+      display: inline-block;
+      margin-right: 10px;
+      width: 290px;
+      height: 350px;
+      border-radius: 2px;
+      -webkit-box-shadow: 2px 3px 9px 0 rgba( 0, 0, 0, .2 );
+      -moz-box-shadow: 2px 3px 9px 0 rgba( 0, 0, 0, .2 );
+      box-shadow: 2px 3px 9px 0 rgba( 0, 0, 0, .2 );
+      text-align: center;
+      border: 1px solid #fff;
+      cursor: pointer;
+      &:nth-child(4n) {
+        margin-right: 0;
+      }
+      &:nth-child(n + 5) {
+        margin-top: 10px;
+      }
+      &:hover {
+        border-color: #366cf3;
+      }
+      .img {
+        height: $img-size;
+        line-height: $img-size;
+        width: $img-size;
+        margin: 11px auto 30px;
+        img {
+          max-width: $img-size;
+          max-height: $img-size;
+        }
+      }
+      .text {
+        height: 20px;
+        font-weight: bold;
+      }
+      .price {
+        color: #f14f4f;
+      }
+    }
+  }
+</style>

+ 72 - 0
components/pcb/home/floors/Floors.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="floors">
+    <div class="floor-line line1">
+      <p>PCB物料<span>PCB material</span>
+        <nuxt-link :to="`/pcb/search/?w=${encodeURIComponent('PCB物料')}`">查看更多</nuxt-link>
+      </p>
+      <floor></floor>
+    </div>
+    <div class="floor-line line2">
+      <p>PCB常用耗材<span>PCB common consumables</span>
+        <nuxt-link :to="`/pcb/search/?w=${encodeURIComponent('PCB常用耗材')}`">查看更多</nuxt-link>
+      </p>
+      <floor></floor>
+    </div>
+    <div class="floor-line line3">
+      <p>PCB设备<span>PCB equipment</span>
+        <nuxt-link :to="`/pcb/search/?w=${encodeURIComponent('PCB设备')}`">查看更多</nuxt-link>
+      </p>
+      <floor></floor>
+    </div>
+  </div>
+</template>
+<script>
+  import Floor from './Floor.vue'
+  export default {
+    components: {
+      Floor
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .floors {
+    width: 1190px;
+    margin: 0 auto 100px;
+    .floor-line {
+      margin-top: 60px;
+      p {
+        position: relative;
+        font-size: 30px;
+        font-weight: bold;
+        text-align: center;
+        line-height: 30px;
+        margin: 0 0 23px 0;
+        span {
+          font-size: 12px;
+          vertical-align: middle;
+          margin-left: 14px;
+        }
+        a {
+          font-size: 14px;
+         position: absolute;
+          right: 0;
+        }
+      }
+      &.line1 {
+        p, a {
+          color: #6fb61a;
+        }
+      }
+      &.line2 {
+        p, a {
+          color: #d83578;
+        }
+      }
+      &.line3 {
+        p, a {
+          color: #e25e44;
+        }
+      }
+    }
+  }
+</style>

+ 13 - 0
components/pcb/index.js

@@ -0,0 +1,13 @@
+import Kinds from './home/Kinds.vue'
+import Intro from './home/Intro.vue'
+import RecommendBrand from './home/RecommendBrand.vue'
+import Floors from './home/floors/Floors.vue'
+import Nav from './Nav.vue'
+import Detail from './product/Detail.vue'
+import BrandList from './brand/BrandList.vue'
+import PcbNavSearch from './PcbNavSearch.vue'
+import DetailBrand from './search/DetailBrand.vue'
+import GoodList from './search/GoodList.vue'
+import Kind from './search/Kind.vue'
+import ResultTitle from './search/ResultTitle.vue'
+export { Kinds, Intro, RecommendBrand, Floors, Nav, Detail, BrandList, PcbNavSearch, DetailBrand, GoodList, Kind, ResultTitle }

+ 571 - 0
components/pcb/product/Detail.vue

@@ -0,0 +1,571 @@
+<template>
+  <div class="detail">
+    <div class="item">
+      <div class="img inline-block">
+        <img :src="commodity.img || '/images/store/common/default.png'" alt=""/>
+      </div>
+      <div class="info inline-block">
+        <p class="name">{{commodity.code}}</p>
+        <p class="remind"><span>官方自营,品质保障</span>厂家直销,品质保证</p>
+        <!--<div class="price-area">-->
+          <!--<span class="left inline-block">价格<span><i>¥</i>1899.00</span></span>-->
+          <!--<span class="right inline-block"><span>6500</span><br/>浏览数</span>-->
+        <!--</div>-->
+        <div class="price-level">
+          <span class="left inline-block">
+              <div>单价&nbsp;¥&nbsp;(含税):</div>
+              起订量:
+          </span>
+          <ul class="inline-block">
+            <li :class="{active: getPriceLevel(fragment.num) == index}" v-for="(price, index) in commodity.prices">
+              <span class="price"><em>{{commodity.currencyName == 'RMB' ? '¥' : '$'}}</em>{{price.rMBPrice}}</span>
+              <div class="level" :title="price.start + '-' + price.end">{{price.start}}-{{price.end}}</div>
+              <i class="arrow"></i>
+            </li>
+          </ul>
+        </div>
+        <div class="input-area">
+          <!--<div class="operate-btn inline-block">-</div>
+          <input type="text" class="form-control">
+          <div class="operate-btn inline-block">+</div>-->
+          <div class="operate-btn inline-block" @click="fragment.canSub ?subNum():''" :style="!fragment.canSub ?'cursor: not-allowed;':''">-</div>
+          <input type="text" class="form-control" placeholder="数量" v-model="fragment.num" @change="inputNum()"style="padding: 0;min-width: 100px;text-align: center;"/>
+          <div class="operate-btn inline-block" @click="fragment.canAdd ?addNum():''" :style="!fragment.canAdd ?'cursor: not-allowed;':''">+</div>
+          <span class="reserve-info">
+            库存:{{commodity.reserve}}&nbsp;{{commodity.unit}}&nbsp;&nbsp;({{commodity.minBuyQty + commodity.unit}}&nbsp;起订)
+          </span>
+        </div>
+        <div class="operate-area">
+          <a class="inline-block operate-buy" @click="buy(true)">立即购买</a>
+          <a class="inline-block" @click="buy(false)">加入购物车</a>
+        </div>
+      </div>
+      <div class="shop inline-block fr">
+      <!--  <div class="search-area">
+          <input type="search" class="form-control" placeholder="产品名称/品牌/类目">
+          <span class="search-btn inline-block">搜索</span>
+        </div>-->
+        <p class="shop-info-title">
+          商家信息
+        </p>
+        <div class="shop-info">
+          <p class="shop-name">{{storeInfo.storeName}}</p>
+          <img class="identify" src="/images/pcb/identified.png">
+          <div class="info-line">
+            <span class="inline-block">电话:</span>
+            <span class="inline-block">{{storeInfo.enterprise.enTel}}</span>
+          </div>
+          <div class="info-line">
+            <span class="inline-block">传真:</span>
+            <span class="inline-block">{{storeInfo.enterprise.enFax}}</span>
+          </div>
+          <div class="info-line">
+            <span class="inline-block">地址:</span>
+            <span class="inline-block">{{storeInfo.enterprise.enAddress}}</span>
+          </div>
+          <div class="link">
+            <span class="link-btn" @click="goLink()"><img src="/images/pcb/link.png" alt="">联系卖家</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    <ul class="kind">
+      <template v-if="properties && properties.length">
+        <li class="inline-block" v-for="prop in properties">
+          {{prop[1].labelCn}}:{{prop[0].value || '-'}}
+        </li>
+      </template>
+      <li class="empty-param" v-else>
+        <img src="/images/all/empty-cart.png" alt="">该产品暂无参数
+      </li>
+    </ul>
+    <link-saler-box
+      :tel="tel"
+      v-if="showLinkBox"
+      @cancelAction="showLinkBox = false">
+    </link-saler-box>
+  </div>
+</template>
+<script>
+  function initFragment (commodity) {
+    if (!commodity) {
+      return {}
+    }
+    let fragment = {}
+    let prices = commodity.prices[0]
+    fragment.num = commodity.minBuyQty
+    fragment.prices = prices
+
+    if (commodity.currencyName !== 'USD') {
+      fragment.currency = 'RMB'
+    } else {
+      fragment.currency = 'USD'
+    }
+
+    if (fragment.currency !== 'USD') {
+      fragment.price = prices.rMBPrice
+    } else {
+      fragment.price = prices.uSDPrice
+    }
+    fragment.canAdd = true
+    fragment.canSub = false
+    return fragment
+  }
+  function getFragment (commodity, fragment) {
+    // 判断是否小于第一分段的起订量
+    if (commodity.prices[0].start > fragment.num) {
+      fragment.num = commodity.prices[0].start
+    }
+    // 获取分段的信息
+    let prices = commodity.prices
+    for (let i = 0; i < prices.length; i++) {
+      if (fragment.num <= prices[i].end) {
+        fragment.prices = prices[i]
+        break
+      }
+    }
+  }
+  import { buyOrCar } from '~utils/baseUtils'
+  import LinkSalerBox from '~components/common/LinkSalerBox.vue'
+  export default {
+    data () {
+      return {
+        fragment: {
+          currency: 'RMB',
+          num: 0,
+          price: 0,
+          canAdd: true,
+          canSub: true
+        },
+        showLinkBox: false,
+        tel: ''
+      }
+    },
+    components: {
+      LinkSalerBox
+    },
+    computed: {
+      properties () {
+        return this.$store.state.pcb.product.detail.data
+      },
+      storeInfo () {
+        return this.$store.state.shop.storeInfo.store.data
+      },
+      commodity () {
+        let commodity = this.$store.state.shop.storeInfo.commodity.data
+        this.fragment = initFragment(commodity)
+        return commodity
+      }
+    },
+    methods: {
+      getPriceLevel: function (num) {
+        let prices = this.commodity.prices
+        if (this.commodity.prices) {
+          for (let i = 0; i < prices.length; i++) {
+            if (num >= prices[i].start && num <= prices[i].end) {
+              return i
+            }
+          }
+        }
+        return -1
+      },
+      changeNum: function (newNum) {
+        let pack = this.commodity.perQty || this.commodity.minPackQty
+        let buy = this.commodity.minBuyQty
+        let reserve = this.commodity.reserve
+        if (newNum < buy) {
+          this.$message.error('该商品最少购买' + buy + '件')
+          this.fragment.num = buy
+          this.fragment.canSub = false
+          if (this.fragment.num > reserve) {
+            this.$message.error('库存不足')
+            this.fragment.num = reserve - (reserve % pack)
+            this.fragment.canAdd = false
+          } else {
+            if (reserve - this.fragment.num - pack < 0) {
+              this.fragment.canAdd = false
+            } else {
+              this.fragment.canAdd = true
+            }
+          }
+        } else {
+          if (newNum - buy - pack < 0) {
+            this.fragment.canSub = false
+          } else {
+            this.fragment.canSub = true
+          }
+          //    console.log(newNum) 2222
+          if (newNum % pack === 0) {
+            this.fragment.num = newNum
+          } else {
+            this.fragment.num = (Math.floor(newNum / pack) + 1) * pack
+          }
+          if (this.fragment.num > reserve) {
+            this.$message.error('库存不足')
+            this.fragment.num = reserve - (reserve % pack)
+            this.fragment.canAdd = false
+          } else {
+            if (reserve - this.fragment.num - pack < 0) {
+              this.fragment.canAdd = false
+            } else {
+              this.fragment.canAdd = true
+            }
+          }
+        }
+      },
+      subNum () {
+        let pack = this.commodity.perQty || this.commodity.minPackQty
+        let newNum = this.fragment.num - pack
+        this.changeNum(newNum)
+        getFragment(this.commodity, this.fragment)
+      },
+      addNum () {
+        let pack = this.commodity.perQty || this.commodity.minPackQty
+        let newNum = this.fragment.num + pack
+        this.changeNum(newNum)
+        getFragment(this.commodity, this.fragment)
+      },
+      inputNum () {
+        if ((/^[\d]*$/).test(this.fragment.num)) {
+          this.changeNum(this.fragment.num)
+          getFragment(this.commodity, this.fragment)
+        } else {
+          this.$message.error('请输入数字')
+          this.fragment.num = this.commodity.minBuyQty
+        }
+      },
+      buy (flag) {
+        buyOrCar(flag, null, this, this.commodity)
+      },
+      goLink: function () {
+        this.baseUtils.goLinkUser(this, this.storeInfo.enUU)
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .detail {
+    .inline-block {
+      display: inline-block;
+      vertical-align: middle;
+    }
+    .item {
+      .img {
+        width: 300px;
+        height: 356px;
+        line-height: 356px;
+        text-align: center;
+        box-shadow: 0 0 7px 0 rgba(199, 200, 200, .35);
+        img {
+          max-width: 300px;
+          max-height: 356px;
+        }
+      }
+      .info {
+        margin-left: 17px;
+        height: 356px;
+        padding-top: 10px;
+        .name {
+          font-size: 24px;
+          font-weight: bold;
+          color: #666;
+          margin-bottom: 17px;
+        }
+        .remind {
+          margin: 17px 0;
+          span {
+            background: #e4393c;
+            color: #fff;
+            padding: 4px 8px;
+            border-radius: 3px;
+            margin-right: 10px;
+          }
+        }
+        /*.price-area {
+          width: 449px;
+          height: 75px;
+          background: url('/images/pcb/price-bg.png') no-repeat;
+          .left {
+            color: #666;
+            margin-left: 13px;
+            line-height: 40px;
+            height: 40px;
+            width: 339px;
+            border-right: 1px solid #c8e5ff;
+            margin-top: 18px;
+            span {
+              margin-left: 17px;
+              font-size: 32px;
+              color: #e4393c;
+              i {
+                font-size: 18px;
+                font-style: normal;
+              }
+            }
+          }
+          .right {
+            margin: 22px 0 0 30px;
+            font-size: 12px;
+            color: #666;
+            span {
+              font-size: 14px;
+              color: #ffa133;
+              margin-bottom: 8px;
+            }
+          }
+        }*/
+        .price-level {
+          width: 570px;
+          height: 87px;
+          padding: 17px 0 0 7px;
+          background: #fffaf1;
+          .left {
+            color: #999;
+            div {
+              margin-bottom: 19px;
+            }
+          }
+          ul {
+            margin-left: 15px;
+            li {
+              width: 83px;
+              margin-right: 4px;
+              float: left;
+              text-align: center;
+              .price {
+                color: #ffb385;
+                font-size: 22px;
+                margin-bottom: 19px;
+                em {
+                  font-style: normal;
+                  font-size: 13px;
+                  margin-right: 4px;
+                }
+              }
+              .level {
+                width: 82px;
+                height: 21px;
+                line-height: 21px;
+                font-size: 12px;
+                color: #999;
+                background: #e4e4e4;
+                margin-top: 9px;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
+              &.active {
+                position: relative;
+                .price {
+                  color: #ff7800;
+                }
+                .level {
+                  background: #ccc;
+                  color: #333;
+                }
+                .arrow {
+                  content: '';
+                  position: absolute;
+                  top: 28px;
+                  left: 37px;
+                  border: {
+                    left: 4px solid transparent;
+                    right: 4px solid transparent;
+                    bottom: 8px solid #ccc;
+                  }
+                }
+              }
+            }
+          }
+        }
+        .input-area {
+          margin-top: 25px;
+          .operate-btn {
+            width: 33px;
+            height: 45px;
+            text-align: center;
+            line-height: 45px;
+            border: 1px solid #d9d9d9;
+            background: #f4f4f4;
+            cursor: pointer;
+            font-size: 20px;
+            user-select: none;
+          }
+          .form-control {
+            border: 1px solid #d9d9d9;
+            background: #fff;
+            width: 77px;
+            height: 45px;
+            border-radius: 0;
+            vertical-align: middle;
+            text-align: center;
+          }
+          .reserve-info {
+            color: #999;
+            margin-left: 10px;
+            vertical-align: bottom;
+          }
+        }
+        .operate-area {
+          margin-top: 12px;
+          .inline-block {
+            width: 126px;
+            height: 45px;
+            line-height: 45px;
+            text-align: center;
+            font-size: 18px;
+            color: #fff;
+            background: #418cf6;
+            border: 1px solid #418cf6;
+            &.operate-buy {
+              color: #418cf6;
+              background: #fff;
+              margin-right: 8px;
+            }
+          }
+        }
+      }
+      $base-color: #ffa133;
+      .shop {
+        height: 356px;
+        width: 259px;
+        text-align: center;
+        .search-area {
+          .form-control {
+            width: 198px;
+            height: 28px;
+            font-size: 12px;
+            padding: 0 14px;
+            border: 1px solid $base-color;
+            vertical-align: middle;
+            border: {
+              bottom-left-radius: 13px;
+              top-left-radius: 13px;
+              top-right-radius: 0;
+              bottom-right-radius: 0;
+            };
+          }
+          .search-btn {
+            width: 60px;
+            height: 28px;
+            line-height: 28px;
+            color: #fff;
+            background: $base-color;
+            border: 1px solid $base-color;
+            border: {
+              bottom-left-radius: 0;
+              top-left-radius: 0;
+              top-right-radius: 13px;
+              bottom-right-radius: 13px;
+            };
+            cursor: pointer;
+          }
+        }
+        .shop-info-title {
+          position: relative;
+          font-size: 16px;
+          color: #ffa133;
+          border: 1px solid #fee9d0;
+          line-height: 35px;
+          margin: 30px 0 0 0;
+          &::before {
+            content: '';
+            background: #fff;
+            width: 24px;
+            height: 24px;
+            position: absolute;
+            left: -12px;
+            top: -12px;
+            border-right: 1px solid #fee9d0;
+            -webkit-transform: rotate(45deg);
+            -moz-transform: rotate(45deg);
+            -ms-transform: rotate(45deg);
+            -o-transform: rotate(45deg);
+            transform: rotate(45deg);
+          }
+          &::after {
+            content: '';
+            position: absolute;
+            left: 1px;
+            top: 1px;
+            border: {
+              top: 15px solid $base-color;
+              right: 15px solid transparent;
+            }
+          }
+        }
+        .shop-info {
+          border: 1px solid #fee9d0;
+          .shop-name {
+            margin: 19px 0 9px;
+            color: #666;
+          }
+          .identify {
+            margin-bottom: 20px;
+          }
+          .info-line {
+            margin-bottom: 21px;
+            padding: 0 16px;
+            text-align: left;
+            .inline-block {
+              vertical-align: top;
+              &:first-child {
+                color: #666;
+              }
+              &:last-child {
+                max-width: 182px;
+              }
+            }
+          }
+          .link {
+            height: 70px;
+            width: 232px;
+            margin: 0 auto;
+            border-top: 1px dashed $base-color;
+            .link-btn {
+              display: block;
+              margin: 23px auto 0;
+              width: 124px;
+              height: 26px;
+              background: $base-color;
+              color: #fff;
+              line-height: 26px;
+              border-radius: 13px;
+              cursor: pointer;
+              img {
+                margin-right: 7px;
+              }
+            }
+          }
+        }
+      }
+    }
+    .kind {
+      background: #f8fbfd;
+      margin: 38px 0 80px;
+      border: 1px solid #d6ebfd;
+      li {
+        width: 25%;
+        color: #666;
+        height: 40px;
+        line-height: 40px;
+        padding-left: 47px;
+        border-bottom: 1px solid #d6ebfd;
+        &:nth-last-child(-n + 4) {
+          border-bottom: none;
+        }
+        a {
+          color: #418cf6;
+        }
+        &.empty-param {
+          width: 100%;
+          height: auto;
+          text-align: center;
+          padding: 20px 0;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 99 - 0
components/pcb/search/DetailBrand.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="brandDetail container" v-if="list_brands && list_brands.uuid">
+    <div id="brand">
+      <nuxt-link :to="`/product/brand/${list_brands.uuid}`" class="brand-logo">
+        <img :src="list.logoUrl || '/images/component/default.png'" :alt="list.nameEn" :title="list.nameEn"/>
+      </nuxt-link>
+      <div class="brand-message">
+        <div class="brand-main" v-show="list.series"><div>主营产品:</div><span>{{list.series}}</span></div>
+        <div class="brand-main" v-show="applications.length>0">
+          <div>应用领域:</div><span v-for="(item, index) in applications"><span>{{item}}</span><span v-show="index+1 < applications.length">|</span></span>
+        </div>
+        <div class="brand-main" v-show="list.brief"><div>品牌介绍:</div><span>{{list.brief}}</span></div>
+        <div class="brand-main" v-show="list.url"><div>官网地址:</div><a class="office-address" :href="list.url" target="_blank">{{list.url}}</a></div>
+      </div>
+    </div>
+    <nuxt-link :to="`/pcb/brand/${list_brands.uuid}`" class="brand-url">进入品牌中心</nuxt-link>
+  </div>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        applications: []
+      }
+    },
+    computed: {
+      list_brands () {
+        return this.$store.state.searchData.searchList.lists.data.brands
+      },
+      list () {
+        let list = this.$store.state.searchData.searchDetail.detail.data
+        if (list.application && list.application !== '') {
+          this.applications = list.application.split(',')
+        }
+        return list
+      }
+    }
+  }
+</script>
+
+<style scoped>
+  #brand{
+    min-height: 160px;
+  }
+  .brandDetail {
+    margin-top: 20px;
+    width: 1190px;
+    overflow: hidden;
+    border-bottom: 1px solid #e5e5e5;
+  }
+  .brand-main{
+    line-height: 20px;
+    margin-left: 223px;
+    margin-bottom: 10px;
+  }
+  .brand-main >span, .brand-main >a {
+    font-weight: 500;
+    font-size: 13px;
+    display: inline-block;
+    max-width: 92%;
+  }
+  .brand-main >div {
+    font-size: 14px;
+    font-weight: 700;
+    width: 8%;
+    display: inline-block;
+    float: left;
+  }
+  .office-address{
+    color: #666;
+  }
+  .office-address:hover{
+    color: #5078cb;
+    cursor: pointer;
+  }
+  .brandDetail .brand-logo{
+    float: left;
+    width: 213px;
+    height: 160px;
+    text-align: center;
+    line-height: 100px;
+  }
+  .brandDetail .brand-logo img {
+    width: 212px;
+    height: 159px;
+    border: 1px solid #ccc;
+    vertical-align: middle;
+  }
+  .brand-url{
+    color: white;
+    background: #2c87d7;
+    position: relative;
+    left: 1088px;
+    padding: 6px 8px;
+    border-radius: 5px;
+    bottom: 20px;
+  }
+</style>

+ 381 - 0
components/pcb/search/GoodList.vue

@@ -0,0 +1,381 @@
+<template>
+  <div>
+    <div class="tab-filter" >
+      <div class="inline-block item" @click="sortBy('normal1')" :class="{'active': activeTag === 'normal1'}">默认排序</div>
+      <div class="inline-block item" @click="sortBy('normal2')" :class="activeTag==='normal2'?'active':''">现货优选<i class="fa fa-long-arrow-down" v-show="reserve_asc"></i><i class="fa fa-long-arrow-up" v-show="!reserve_asc"></i></div>
+      <div class="inline-block item" @click="sortBy('price')" :class="activeTag==='price'?'active':''">价格<i class="fa fa-long-arrow-down" v-show="price_asc"></i><i class="fa fa-long-arrow-up" v-show="!price_asc"></i></div>
+      <div class="inline-block price-filter">
+        <input type="number" min="0" step="0.01" v-model="min_price" class="form-control" placeholder="¥" onfocus="this.placeholder=''" onblur="this.placeholder='¥'" />
+        <span>&nbsp;-&nbsp;</span>
+        <input type="number" :min="min_price === ''?0:min_price" step="0.01" v-model="max_price" class="form-control" placeholder="¥" onfocus="this.placeholder=''" onblur="this.placeholder='¥'" />
+        <a class="fp-btn inline-block" @click="filter_price">确定</a>
+      </div>
+      <div class="fr">
+        <span>共{{good_list.total}}条商品信息</span>
+        <span class="page-info"><span class="active">{{nowPage}}</span>/{{total_page}}</span>
+        <a href="javascript:void(0)" class="icon-xiangzuo iconfont" @click="changePage('pre')"></a>
+        <a href="javascript:void(0)" class="icon-xiangyou iconfont" @click="changePage('next')"></a>
+      </div>
+    </div>
+    <ul class="good-list" v-if="good_list.pcbgoods && good_list.pcbgoods.length">
+      <li v-for="item in good_list.pcbgoods" class="inline-block">
+        <nuxt-link :to="`/pcb/product/${item.productid}/${item.batchCode}`">
+          <div class="img">
+            <img :src="getLogo(item)">
+          </div>
+          <p class="price">{{item.prices ? item.currencyName === 'RMB' ? '¥' + '&nbsp;&nbsp;' + item.prices[0].rMBPrice : '$' +  '&nbsp;&nbsp;' + item.prices[0].uSDPrice : '-'}}</p>
+          <p>{{item.kindNameCn}}</p>
+          <p>销量<span class="sell-count">{{item.saleQty || 0}}</span>件</p>
+        </nuxt-link>
+      </li>
+    </ul>
+    <div class="com-empty" v-if="!good_list.pcbgoods || !good_list.pcbgoods.length">
+      <img class="com-empty-img" src="/images/brandList/empty-cart.png">
+      <span class="com-empty-text">暂无搜索结果</span>
+    </div>
+    <page :total="total_count" :page-size="pageSize"
+          :current="nowPage" @childEvent="listenPage"></page>
+  </div>
+</template>
+
+<script>
+  import Page from '~components/common/page/pageComponent.vue'
+  import Buy from '~components/common/buyOrCar/buyComponent.vue'
+  export default {
+    data () {
+      return {
+        nowPage: 1,
+        pageSize: 20,
+        sorting: {},
+        price_asc: true,
+        reserve_asc: true,
+        min_price: '',
+        max_price: '',
+        filter: {},
+        activeTag: 'normal1'
+      }
+    },
+    components: {
+      Page,
+      Buy
+    },
+    filters: {
+      currency: function (input) {
+        if (typeof input === 'number') {
+          if (input <= 0.000001) {
+            input = 0.000001
+          } else {
+            if (input.toString().indexOf('.') === -1) {
+              input = input + '.00'
+            } else {
+              let inputStr = input.toString()
+              let arr = inputStr.split('.')
+              let floatNum = arr[1]
+              if (floatNum.length > 6) {
+                input = inputStr.substring(0, arr[0].length + 7)
+                if (Number(floatNum.charAt(6)) > 4) {
+                  input = (Number(input) * 1000000 + 1) / 1000000
+                }
+              } else if (floatNum.length === 1) {
+                input = input + '0'
+              }
+            }
+          }
+        }
+        return input
+      }
+    },
+    watch: {
+      $route: function (val, oldVal) {
+        this.filter = {}
+        this.activeTag = 'normal1'
+      }
+    },
+    computed: {
+      good_lists () {
+        return this.$store.state.pcb.search.list
+      },
+      good_list () {
+        return this.good_lists.data
+      },
+      total_count () {
+        return Math.min(this.good_list.total, 100 * this.pageSize)
+      },
+      total_page () {
+        let currentCount = Math.floor(this.good_list.total / this.pageSize) + (this.good_list.total % this.pageSize > 0 ? 1 : 0)
+        return currentCount > 100 ? 100 : currentCount
+      },
+      buy_info () {
+        return this.$store.state.user.buy.buyInfo.data
+      },
+      car_info () {
+        return this.$store.state.user.car.addCarInfo.data
+      },
+      tab () {
+        return this.$store.state.chat.tab.tab.data
+      },
+      user () {
+        return this.$store.state.option.user
+      }
+    },
+    methods: {
+      goWebChat: function () {
+        if (!this.user.logged) {
+          this.$http.get('/login/page').then(response => {
+            if (response.data) {
+              this.$router.push('/auth/login')
+            }
+          })
+        } else {
+          // 获得窗口的垂直位置
+          let iTop = (window.screen.availHeight - 30 - 780) / 2
+          // 获得窗口的水平位置
+          let iLeft = (window.screen.availWidth - 10 - 1030) / 2
+          if (this.tab.close) {
+            this.tab.close()
+          }
+          let newTab = window.open('', '即时对话框', 'height=750, width=1000, top=' + iTop + ', left=' + iLeft + ', toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no')
+          newTab.close()
+          newTab = window.open('', '即时对话框', 'height=750, width=1000, top=' + iTop + ', left=' + iLeft + ', toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no')
+          this.$store.dispatch('chat/setChatTab', {tab: newTab})
+          this.$http.get('/basic/enterprise/' + this.storeInfo.enUU + '/info')
+            .then(response => {
+              let obj = {}
+              obj.userPhone = this.user.data.userTel
+              obj.userType = 'ENTERPRISE'
+              this.user.data.enterprises.forEach(function (item, index) {
+                if (item.current) {
+                  obj.enUU = item.uu
+                  obj.enterprise = {enUU: item.uu, name: item.enName}
+                }
+              })
+              obj.otherEnUU = response.data.uu
+              obj.otherUserType = 'STORE'
+              obj.otherEnterprise = {enUU: response.data.uu, name: response.data.enName}
+              obj.type = 'CHAT'
+              if (!(/^1\d{10}$/).test(response.data.enTel)) {
+                this.$http.get('/basic/enterprise/' + response.data.uu + '/admin').then(response => {
+                  obj.toPhone = response.data.userTel
+                  console.log(obj)
+                  this.openWebChat(newTab, obj)
+                }, err => {
+                  console.log(err)
+                  this.$message.error('暂无卖家管理员手机号!')
+                })
+              } else {
+                obj.toPhone = response.data.enTel
+                this.openWebChat(newTab, obj)
+              }
+            }, err => {
+              console.log(err)
+            })
+        }
+      },
+      openWebChat: function (newTab, obj) {
+        this.$http.post('https://im.ubtob.com/api/chat/infos?condition=chat_info', obj)
+          .then(response => {
+            if (response.data.success) {
+              newTab.location.href = 'https://im.ubtob.com/chat/visit?gid=' + response.data.content
+            }
+          })
+      },
+      listenPage: function (changedPage) {
+        this.nowPage = changedPage
+        this.$emit('pageEvent', this.nowPage)
+      },
+      changePage: function (type) {
+        if (type === 'next' && this.nowPage < this.total_page) {
+          this.listenPage(++this.nowPage)
+        } else if (type === 'pre' && this.nowPage > 1) {
+          this.listenPage(--this.nowPage)
+        }
+      },
+      sortBy: function (param) {
+        if (param === 'normal1') {
+          this.sorting = {}
+          this.activeTag = 'normal1'
+        } else if (param === 'normal2') {
+          if (this.reserve_asc) {
+            this.sorting = {'RESERVE': 'ASC'}
+          } else {
+            this.sorting = {'RESERVE': 'DESC'}
+          }
+          this.activeTag = 'normal2'
+          this.reserve_asc = !this.reserve_asc
+        } else if (param === 'type') {
+          this.sorting = {'RESERVE': 'DESC'}
+          this.activeTag = 'type'
+        } else if (param === 'price') {
+          if (this.price_asc) {
+            this.sorting = {'PRICE': 'ASC'}
+          } else {
+            this.sorting = {'PRICE': 'DESC'}
+          }
+          this.activeTag = 'price'
+          this.price_asc = !this.price_asc
+        }
+        this.$emit('sortEvent', this.sorting)
+        this.nowPage = 1
+      },
+      filter_price: function () {
+        if (this.min_price === '' && this.max_price !== '') {
+          this.filter.goods_maxpricermb = this.max_price
+        } else if (this.min_price !== '' && this.max_price === '') {
+          this.filter.goods_minpricermb = this.min_price
+        } else if (this.min_price !== '' && this.max_price !== '') {
+          if (this.min_price <= this.max_price) {
+            this.filter.goods_minpricermb = this.min_price
+            this.filter.goods_maxpricermb = this.max_price
+          }
+        } else {
+          delete this.filter.goods_minpricermb
+          delete this.filter.goods_maxpricermb
+        }
+        this.$emit('filterPriceEvent', this.filter)
+      },
+      clear_price: function () {
+        this.min_price = ''
+        this.max_price = ''
+        this.$emit('filterPriceEvent', this.filter)
+      },
+      goUnstandardDetail: function (comp) {
+        if (!comp.uuid) {
+          this.$router.push('/store/productDetail/' + comp.batchCode)
+        }
+      },
+      getLogo: function (item) {
+        if (item.batchCode) {
+          if (item.img) {
+            return item.img
+          } else {
+            return '/images/component/default.png'
+          }
+        } else {
+          if (item.brand && item.brand.logoUrl) {
+            return item.brand.logoUrl
+          } else {
+            return '/images/component/default.png'
+          }
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped lang="scss">
+  .tab-filter {
+    height: 34px;
+    background: #f4f4f4;
+    padding: 5px 31px 0 14px;
+    margin-bottom: 20px;
+    .item {
+      width: 74px;
+      height: 24px;
+      text-align: center;
+      color: #999;
+      line-height: 22px;
+      background: #fff;
+      border: 1px solid #d9d9d9;
+      border-right: none;
+      cursor: pointer;
+      font-size: 12px;
+      &:last-child {
+        border-right: 1px solid #d9d9d9;
+      }
+      &.active {
+        border: 1px solid #5078cb;
+        background: #5078cb;
+        color: #fff;
+      }
+    }
+    .price-filter {
+      margin-left: 30px;
+      .form-control {
+        width: 74px;
+        height: 24px;
+        border: 1px solid #d9d9d9;
+        border-radius: 0;
+        padding: 0 6px;
+        font-size: 12px;
+      }
+      .fp-btn {
+        width: 43px;
+        height: 24px;
+        line-height: 24px;
+        background: #5078cb;
+        color: #fff;
+        text-align: center;
+        border-radius: 2px;
+        margin-left: 6px;
+      }
+    }
+    .fr {
+      height: 24px;
+      line-height: 24px;
+      color: #999;
+      .page-info {
+        margin-left: 20px;
+        margin-right: 4px;
+        .active {
+          color: #3f85f6;
+        }
+      }
+      .iconfont {
+        display: inline-block;
+        width: 38px;
+        height: 24px;
+        line-height: 24px;
+        text-align: center;
+        border: 1px solid #d9d9d9;
+        color: #666;
+        background: #fff;
+      }
+    }
+  }
+  .good-list {
+    .inline-block {
+      width: 220px;
+      height: 300px;
+      margin-right: 15px;
+      border: 1px solid #d9d9d9;
+      padding: 0 20px;
+      margin-bottom: 15px;
+      &:nth-child(5n) {
+        margin-right: 0;
+      }
+      p {
+        color: #666;
+      }
+      $img-size: 179px;
+      .img {
+        width: $img-size;
+        height: $img-size;
+        line-height: $img-size;
+        text-align: center;
+        margin: 0 auto;
+        img {
+          max-width: $img-size;
+          max-height: $img-size;
+        }
+      }
+      .price {
+        font-size: 18px;
+        color: #e4393c;
+      }
+      .sell-count {
+        color: #767cf9;
+      }
+    }
+  }
+  .com-empty{
+    text-align: center;
+    height:130px;
+    border: 1px solid #eee;
+    line-height: 130px;
+    margin-bottom: 20px;
+    .com-empty-text {
+      color: #aaa;
+      margin-left: 10px;
+    }
+  }
+</style>

+ 309 - 0
components/pcb/search/Kind.vue

@@ -0,0 +1,309 @@
+<template>
+  <div class="selector" >
+    <a class="show-filter" @click="show_filter = !show_filter">
+      <span v-text="show_filter?'收起筛选 ':'展开筛选 '"></span>
+      <i :class="show_filter?'fa fa-angle-up':'fa fa-angle-down'"></i>
+    </a>
+    <div v-show="show_filter">
+      <div class="sl-wrap" v-if="good_list.total > 0">
+        <div class="sl-key f14">类目:</div>
+        <div class="sl-value">
+          <span v-for="(kind_temp, index) in kind_exp_arr">
+            <div class="sl-filter" @click="click_kind_exp(kind_temp.ki_id, index)">
+              <a class="text-num" v-text="kind_temp.ki_name_cn"></a>
+              <span><i class="fa fa-close"></i></span>
+            </div>
+          </span>
+          <ul :class="show_kind">
+            <li @click="restore('kind')"><a>全部</a></li>
+            <li v-for="(item, index) in list_kind" v-if="item.ki_name_cn" @click="click_kind(item.ki_id, index)" :title="item.ki_name_cn">
+              <a v-text="item.ki_name_cn"></a>
+            </li>
+          </ul>
+        </div>
+        <div class="sl-clear"></div>
+        <div class="sl-ext">
+          <a @click="click_kind_more" v-if="list_kind.length>17">
+            <span v-text="kind_open?'更多':'收起'"></span>
+            <i class="fa fa-angle-down ng-scope" v-if="kind_open"></i>
+            <i class="fa fa-angle-up ng-scope" v-if="!kind_open"></i>
+          </a>
+        </div>
+      </div>
+      <div class="sl-wrap" v-if="good_list.total > 0">
+      <div class="sl-key f14">品牌:</div>
+      <div class="sl-value" >
+         <span v-for="(brand_temp, index) in brand_exp_arr" >
+          <div class="sl-filter" @click="click_brand_exp(brand_temp.br_id, index)">
+            <a class="text-num" v-text="brand_temp.br_name_cn"></a>
+            <span><i class="fa fa-close"></i></span>
+          </div>
+        </span>
+        <ul :class="show_brand">
+          <li @click="restore('brand')"><a>全部</a></li>
+          <li v-for="(item, index) in list_brand" v-if="item.br_name_cn" @click="click_brand(item.br_id, index)" :title="item.br_name_cn">
+            <a v-text="item.br_name_cn"></a>
+          </li>
+        </ul>
+      </div>
+      <div class="sl-clear"></div>
+      <div class="sl-ext" v-if="list_brand.length>17">
+        <a @click="click_brand_more">
+          <span v-text="brand_open?'更多':'收起'"></span>
+          <i class="fa fa-angle-down ng-scope" v-if="brand_open"></i>
+          <i class="fa fa-angle-up ng-scope" v-if="!brand_open"></i>
+        </a>
+      </div>
+    </div>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    data () {
+      return {
+        show_filter: true,
+        kind_open: true,
+        brand_open: true,
+        show_kind: 'list-inline',
+        show_brand: 'list-inline',
+        filter: {},
+        kind_arr: [],
+        brand_arr: [],
+        kind_exp_arr: [],
+        brand_exp_arr: []
+      }
+    },
+    watch: {
+      $route: function (val, oldVal) {
+        this.filter = {}
+        this.kind_arr = []
+        this.brand_arr = []
+        this.kind_exp_arr = []
+        this.brand_exp_arr = []
+      }
+    },
+    computed: {
+      list_kinds () {
+        return this.$store.state.pcb.search.kinds
+      },
+      list_kind () {
+        return this.list_kinds.data
+      },
+      list_brands () {
+        return this.$store.state.pcb.search.brands
+      },
+      list_brand () {
+        return this.list_brands.data
+      },
+      good_lists () {
+        return this.$store.state.pcb.search.list
+      },
+      good_list () {
+        return this.good_lists.data
+      },
+      list_data_brands () {
+        return this.good_list.brands
+      }
+    },
+    methods: {
+      click_kind_more: function (event) {
+        if (this.kind_open) {
+          this.show_kind = 'list-inline2'
+        } else {
+          this.show_kind = 'list-inline'
+        }
+        this.kind_open = !this.kind_open
+      },
+      click_brand_more: function (event) {
+        if (this.brand_open) {
+          this.show_brand = 'list-inline2'
+        } else {
+          this.show_brand = 'list-inline'
+        }
+        this.brand_open = !this.brand_open
+      },
+      click_kind: function (id, index) {
+        this.kind_arr.push(id)
+        this.$emit('kindFilterEvent', this.kind_arr)
+        this.kind_exp_arr.push(this.list_kind[index])
+        this.kind_exp_arr[this.kind_exp_arr.length - 1].index = index
+        this.list_kind[index] = ''
+      },
+      click_brand: function (id, index) {
+        this.brand_arr.push(id)
+        this.$emit('brandFilterEvent', this.brand_arr)
+        this.brand_exp_arr.push(this.list_brand[index])
+        this.brand_exp_arr[this.brand_exp_arr.length - 1].index = index
+        this.list_brand[index] = ''
+      },
+      click_kind_exp: function (id, index) {
+        let idx = this.getIndex(this.kind_arr, id)
+        this.list_kind[this.kind_exp_arr[index].index] = this.kind_exp_arr[index]
+        this.kind_arr.splice(idx, 1)
+        this.$emit('kindFilterEvent', this.kind_arr)
+        this.kind_exp_arr.splice(index, 1)
+      },
+      click_brand_exp: function (id, index) {
+        let idx = this.getIndex(this.brand_arr, id)
+        this.list_brand[this.brand_exp_arr[index].index] = this.brand_exp_arr[index]
+        this.brand_arr.splice(idx, 1)
+        this.$emit('brandFilterEvent', this.brand_arr)
+        this.brand_exp_arr.splice(index, 1)
+      },
+      restore: function (name) {
+        if (name === 'kind') {
+          this.list_kind.concat(this.kind_exp_arr)
+          this.kind_exp_arr = []
+          this.kind_arr = []
+          this.$emit('kindFilterEvent', this.kind_arr)
+        } else if (name === 'brand') {
+          this.list_brand.concat(this.brand_exp_arr)
+          this.brand_exp_arr = []
+          this.brand_arr = []
+          this.$emit('brandFilterEvent', this.brand_arr)
+        }
+      },
+      getIndex: function (arr, obj) {
+        for (let i = 0; i < arr.length; i++) {
+          if (arr[i] === obj) {
+            return i
+          }
+        }
+        return -1
+      }
+    }
+  }
+</script>
+<style scoped>
+  .show-filter{
+    position: relative;
+    left: 1100px;
+    top: -10px;
+    color: #5078cb;
+    border: 1px solid #5078cb;
+    padding: 3px 8px;
+    background: #fff;
+  }
+  #searchResult .selector >div{
+    margin-bottom: 20px;
+    border-top: 2px solid #6493ff;
+  }
+  #searchResult .selector .sl-wrap {
+    position: relative;
+    padding: 10px 15px;
+    font-size: 12px;
+    line-height: 30px;
+    border: 1px solid #d4e1ff;
+    border-top: none;
+    border-bottom: 1px dashed #d4e1ff;
+  }
+  #searchResult .selector .sl-wrap:last-child {
+    border-bottom: 1px solid #d4e1ff;
+  }
+  #searchResult .selector .sl-wrap .sl-key {
+    float: left;
+  }
+  .f14 {
+    font-size: 14px;
+  }
+  #searchResult .selector .sl-wrap .sl-value {
+    margin-left: 78px;
+    margin-right: 50px;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter {
+    display: inline-block;
+    position: relative;
+    line-height: 22px;
+    padding-left: 10px;
+    padding-right: 30px;
+    border: 1px solid #5078cb;
+    color: #5078cb;
+    cursor: pointer;
+    height: 22px;
+    margin-right: 10px;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter a{
+    color: #666;
+    text-decoration: none;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter span{
+    display: inline-block;
+    position: absolute;
+    right: 0;
+    top: -1px;
+    width: 20px;
+    text-align: center;
+    background: #5078cb;
+    color: #fff;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter:hover {
+    border: 1px solid #ea1e23;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter:hover a{
+    color: #ea1e23;
+  }
+  #searchResult .selector .sl-wrap .sl-value span >.sl-filter:hover span{
+    background: #ea1e23;
+  }
+  #searchResult .selector .sl-wrap .sl-clear {
+    clear: both;
+  }
+  #searchResult .selector .sl-wrap .sl-ext {
+    width: 40px;
+    top: 5px;
+    position: absolute;
+    right: 0;
+  }
+
+  .list-inline {
+    max-height: 60px;
+    overflow: hidden;
+    margin-bottom: 0;
+    padding-left: 0;
+    margin-left: -5px;
+    list-style: none;
+  }
+  .list-inline2 {
+    height: 100%;
+    overflow: hidden;
+    margin-bottom: 0;
+    padding-left: 0;
+    margin-left: -5px;
+    list-style: none;
+  }
+
+  #searchResult .selector .sl-wrap .sl-value li {
+    display: inline-block;
+    padding-right: 5px;
+    padding-left: 5px;
+    margin-right: 20px;
+    width: 10%;
+    height: 23px;
+    line-height: 23px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor: pointer;
+    border: 1px solid #fff;
+  }
+  #searchResult .selector .sl-wrap .sl-value ul  a{
+    color: #666;
+  }
+  #searchResult .selector .sl-wrap .sl-value li:hover {
+    border: 1px solid #5078cb;
+    color: #5078cb;
+  }
+  #searchResult .selector .sl-wrap .sl-value li:hover a {
+    color: #5078cb;
+  }
+  .sl-ext a{
+    color: black;
+  }
+  .sl-ext a:hover{
+    color: #5078cb;
+    text-decoration: none;
+  }
+
+</style>
+

+ 52 - 0
components/pcb/search/ResultTitle.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="result-title text-muted">
+    搜索"<span class="text-inverse" >{{keyword}}</span>"<span v-if="status != 1">暂无此型号</span>
+    <span v-if="status != 3">,为您找到
+    <span class="text-num" v-text="good_list.total"></span> 个<span v-if="status == 2">相关</span>产品</span>:
+  </div>
+</template>
+<script>
+  export default{
+    props: ['keyword', 'page'],
+    data () {
+      return {
+        status: 1
+      }
+    },
+    computed: {
+      good_lists () {
+        return this.$store.state.pcb.search.list
+      },
+      good_list () {
+        if (this.page === 1) {
+          if (this.good_lists.data.components && this.good_lists.data.components.length > 0) {
+            if (this.keyword.toUpperCase() === this.good_lists.data.components[0].code.toUpperCase()) {
+              this.status = 1
+            } else {
+              this.status = 2
+            }
+          } else {
+            this.status = 3
+          }
+        }
+        return this.good_lists.data
+      }
+    }
+  }
+</script>
+<style scoped>
+  #searchResult .result-title {
+    margin-top: 5px;
+    padding: 10px 5px;
+    height: 30px;
+    line-height: 30px;
+    font-size: 14px;
+  }
+  .text-inverse {
+    color: #f40!important;
+  }
+  .text-num {
+    font-style: normal;
+    font-family: verdana;
+  }
+</style>

+ 139 - 90
components/product/brand/BrandDetail.vue

@@ -2,20 +2,23 @@
   <div class="brandDetail container">
     <div class="menu-com row">
       <div class="menu-title col-md-12">
-        <a href="/product/brand/brandList/ABC">品牌中心</a> > <span>{{list.nameEn}}</span></div>
+        <a href="/product/brand/brandList/A">品牌中心</a> > <span>{{list.nameEn}}</span></div>
     </div>
     <div id="brand">
-      <div class="brand-logo">
-        <img :src="list.logoUrl || '/images/component/default.png'" :alt="list.nameEn"/>
-      </div>
+      <div class="brand-name"><h5>{{list.nameEn}}</h5><h5 v-if="list.nameCn && list.nameEn!=list.nameCn"><span>{{list.nameCn}}</span></h5></div>
       <div class="brand-message">
-        <div class="brand-name"><span>{{list.nameEn}}</span><span v-if="list.nameCn && list.nameEn!=list.nameCn">(<span>{{list.nameCn}}</span>)</span></div>
-        <div class="brand-main" v-show="list.series">主营产品:<span>{{list.series}}</span></div>
-        <div class="apply-area" v-show="applications.length>0">
-          应用领域:<span v-for="(item, index) in applications"><span>{{item}}</span><span v-show="index+1 < applications.length">|</span></span>
+        <div class="brand-logo">
+          <img src='/images/brandCenter/detail.jpg' :alt="list.nameEn"/>
+          <img :src="list.logoUrl || '/images/component/default.png'" :alt="list.nameEn"/>
         </div>
-        <div class="brand-description" v-show="list.brief">品牌介绍:<div class="txt-description">{{list.brief}}</div></div>
-        <div style="margin-top: 5px;color:#666;" v-show="list.url">官网地址:<a class="office-address" :href="list.url">{{list.url}}</a></div>
+        <ul>
+        <li class="brand-main" v-show="list.series">主打产品:<span>{{list.series}}</span></li>
+        <li class="apply-area" v-show="applications.length>0">
+          应用领域:<span v-for="(item, index) in applications"><span>{{item}}</span><span v-show="index+1 < applications.length">|</span></span>
+        </li>
+        <li class="brand-description" v-if="list.brief"><span>品牌介绍:</span><div class="txt-description">{{list.brief | briefFilter}}</div></li>
+        <li style="margin-top: 10px;color:#eb062b;" v-show="list.url"><span style="color:#666;">官网地址:</span><a class="office-address" :href="list.url">{{list.url}}</a></li>
+        </ul>
       </div>
     </div>
   </div>
@@ -28,9 +31,34 @@
         applications: []
       }
     },
+    filters: {
+      briefFilter: function (title) {
+        if (title === '') {
+          return title
+        }
+        let len = 0
+        let index = 0
+        for (let i = 0; i < title.length; i++) {
+          if (index === 0 && title.charAt(i).charCodeAt(0) > 255) {
+            len = len + 2
+          } else {
+            len++
+          }
+          if (len > 536) {
+            index = i
+            break
+          }
+        }
+        if (index > 0) {
+          return title.substring(0, index) + '...'
+        } else {
+          return title
+        }
+      }
+    },
     computed: {
       list () {
-        let list = this.$store.state.brandDetail.detail.data
+        let list = this.baseUtils.deepCopy(this.$store.state.brandDetail.detail.data)
         if (list.application && list.application !== '') {
           this.applications = list.application.split(',')
         }
@@ -39,89 +67,110 @@
     }
   }
 </script>
-<style scoped>
+<style lang="scss" scoped>
   .brandDetail {
     margin-bottom: 60px;
     width: 1190px;
     padding: 0;
     overflow: hidden;
-  }
-  .menu-com{
-    margin: 0;
-  }
-  .menu-title{
-    line-height: 40px;
-    font-size: 14px;
-  }
-  .menu-title a{
-    color: #5078cb;
-    font-size: 14px;
-  }
-  i{
-    margin-right: 5px;
-  }
-  .menu-title{
-    padding-left: 0;
-  }
-  .brand-main{
-    font-size: 14px;
-    color: #5078cb;
-    line-height: 20px;
-  }
-  .apply-area{
-    font-size: 14px;
-    color: #5078cb;
-    margin-top: 8px;
-  }
-  .apply-area span{
-    margin-right: 5px;
-  }
-  .office-address{
-    margin-top: 10px;
-  }
-  .office-address{
-    color: #666;
-  }
-  .office-address:hover{
-    color: #5078cb;
-    cursor: pointer;
-  }
-  .brand-description{
-    margin-top: 6px;
-    font-size: 14px;
-    color: #666;
-  }
-  .brand-description .txt-description{
-    font-size: 14px;
-    color: #666;
-  }
-  .brandDetail .brand-logo{
-    float: left;
-    width: 200px;
-    height: 108px;
-    text-align: center;
-    line-height: 100px;
-    border: 1px solid #ccc;
-    background-color: #c1c1c1;
-  }
-  .brandDetail .brand-logo img {
-    max-width: 198px;
-    max-height: 106px;
-    vertical-align: middle;
-  }
-  .brandDetail .brand-message {
-    float: left;
-    margin-left: 20px;
-    margin-bottom: 60px;
-    width: 970px;
-  }
-  .brandDetail .brand-message .brand-name {
-    font-size: 18px;
-    font-weight: 700;
-    margin-bottom: 14px;
-  }
-  .brandDetail .brand-message .brand-description {
-    font-size: 14px;
-    line-height: 20px;
+    .menu-com {
+      margin: 0;
+      width: 100%;
+      border-bottom: 2px solid #3975f4;
+      padding-top: 22px;
+      .menu-title {
+        line-height: 40px;
+        font-size: 14px;
+        padding-left: 0;
+        a {
+          color: #5078cb;
+          font-size: 14px;
+        }
+      }
+    }
+    #brand {
+      width: 1190px;
+      .brand-name {
+        width: 100%;
+        padding-left: 30px;
+        h5 {
+          color: #eb062b;
+          font-size: 18px;
+          font-weight: bold;
+          margin-top: -25px;
+          &:first-child {
+            font-size: 24px;
+            margin-top: 26px;
+          }
+        }
+      }
+      .brand-message {
+        min-height: 310px;
+        .brand-logo {
+          float: right;
+          height: 310px;
+          text-align: center;
+          position: relative;
+         /* line-height: 340px;*/
+          img:first-child {
+            height: 310px;
+            vertical-align: middle;
+          }
+          img:last-child{
+            width: 120px;
+            height: 40px;
+            position: absolute;
+            top: 140px;
+            left: 260px;
+          }
+        }
+        ul {
+          width: 100%;
+          min-height: 310px;
+          list-style-type: disc;
+          font-size: 20px;
+          color: #eb062b;
+          padding: 30px 0px 0px 30px;
+          border-left: 2px solid #efefef;
+          border-right: 2px solid #efefef;
+          border-bottom: 3px solid #efefef;
+          li {
+            color: #666;
+            font-size: 14px;
+          }
+         .brand-main,.apply-area{
+           color: #eb062b;
+           font-size: 14px;
+           padding-bottom: 20px;
+          }
+          .apply-area{
+            font-size: 14px;
+            span{
+              margin-right: 5px;
+            }
+          }
+          .brand-description{
+            line-height: 20px;
+            color: #eb062b;
+            font-size: 14px;
+            span{
+              color: #333;
+            }
+            .txt-description{
+              margin-top: 8px;
+              line-height: 20px;
+              color: #666;
+            }
+          }
+          .office-address{
+            color: #333;
+            &:hover{
+              color: #5078cb;
+              cursor: pointer;
+            }
+          }
+        }
+      }
+    }
   }
 </style>

+ 43 - 24
components/product/brand/CategoriesList.vue

@@ -1,36 +1,33 @@
 <template>
   <div class="categories-list container">
-    <div class="categories-list-header">产品分类</div>
-    <div class="categories-list-body" id="kinds">
-      <el-tree :data="list" :props="defaultProps" accordion :highlight-current="true" @current-change="handlerCurrentNode"></el-tree>
-      <!--<ul>-->
-        <!--<li v-for="kind in list[0]">-->
-          <!--{{kind.nameCn}}-->
-        <!--</li>-->
-      <!--</ul>-->
+    <div v-if="isShow == 0">
+      <div class="categories-list-header">产品分类</div>
+      <div class="categories-list-body">
+        <el-tree :data="list" :props="defaultProps" accordion :highlight-current="true" @current-change="handlerCurrentNode"></el-tree>
+        <!--<ul>
+          <li v-for="kind in list[0]">
+            {{kind.nameCn}}
+          </li>
+        </ul>-->
+      </div>
+    </div>
+    <div v-if="isShow == 1">
+      <div class="categories-list-header">代理商分类</div>
+      <div class="categories-list-agency-body">
+        <ul>
+          <li><a>已入驻代理商</a></li>
+          <li><a>未入驻代理商</a></li>
+        </ul>
+      </div>
     </div>
   </div>
 </template>
-
 <script>
-  // 实现深拷贝
-  function deepCopy(target) {
-    if (typeof target !== 'object') return
-    // 判断目标类型,来创建返回值
-    var newObj = target instanceof Array ? [] : {}
-    for (var item in target) {
-      // 只复制元素自身的属性,不复制原型链上的
-      if (target.hasOwnProperty(item)) {
-        newObj[item] = typeof target[item] === 'object' ? deepCopy(target[item]) : target[item]
-        }
-      }
-      return newObj
-  }
   export default {
     name: 'CategoriesList',
     computed: {
       list () {
-        let brands = deepCopy(this.$store.state.brandCategories.categories.data)
+        let brands = this.baseUtils.deepCopy(this.$store.state.brandCategories.categories.data)
         if (!brands || brands.length === 0) {
           return []
         }
@@ -92,6 +89,7 @@
         return this.$store.state.brandDetail.detail.data
       }
     },
+    props: ['isShow'],
     data () {
       return {
         defaultProps: {
@@ -197,7 +195,7 @@
     height: 34px;
     text-align: center;
     color: #fff;
-    background-color: #5078cb;
+    background: url("/images/brandCenter/type.png") no-repeat center #5078cb;
     font-size: 14px;
     padding: 7px;
   }
@@ -221,4 +219,25 @@
     list-style: none;
     padding: 10px;
   }
+  /*.categories-list-header {*/
+    /*height: 34px;*/
+    /*text-align: center;*/
+    /*color: #fff;*/
+    /*background: url("/images/brandCenter/type.png") no-repeat center #5078cb;*/
+    /*font-size: 14px;*/
+    /*padding: 7px;*/
+  /*}*/
+  .categories-list-agency-body ul>li {
+    list-style: none;
+    padding: 12px 0px 10px 20px;
+    color: #5078CB;
+    font-size: 14px;
+  }
+  .categories-list-agency-body ul>li>a {
+    cursor: pointer;
+    color: #323232;
+  }
+  .categories-list-agency-body ul>li>a:hover {
+    color: #5078CB;
+  }
 </style>

+ 1 - 1
components/provider/Carousel.vue

@@ -62,7 +62,7 @@
 <style lang="scss" scoped>
   @import '~assets/scss/variables';
 
-  $carousel_width: 668px;
+  $carousel_width: 908px;
   $carousel_height: 358px;
 
   .carousel {

+ 7 - 7
components/provider/RecommendStore.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="container marketing">
-    <div class="sales-rank">
+    <!--<div class="sales-rank">
       <sales-rank />
-    </div>
+    </div>-->
     <div class="carousel">
       <carousel />
     </div>
@@ -12,14 +12,14 @@
   </div>
 </template>
 <script>
-import SalesRank from './SalesRank.vue'
+// import SalesRank from './SalesRank.vue'
 import NewStore from './NewStore.vue'
 import Carousel from './Carousel.vue'
 
 export default {
   name: 'recommend-store',
   components: {
-    SalesRank,
+//    SalesRank,
     NewStore,
     Carousel
   }
@@ -33,15 +33,15 @@ export default {
     min-height: 360px;
     padding: 0;
 
-    .sales-rank {
+    /*.sales-rank {
       width: 240px;
       min-height: 360px;
       float: left;
       display: inline-block;
-    }
+    }*/
 
     .carousel {
-      width: 670px;
+      width: 910px;
       min-height: 360px;
       display: inline-block;
       float: left;

+ 156 - 0
layouts/pcb.vue

@@ -0,0 +1,156 @@
+<template>
+  <div id="main">
+    <header-view v-if="!isInFrame"></header-view>
+    <main-header :isPcb="true"></main-header>
+    <main-nav></main-nav>
+    <nuxt/>
+    <footer-view></footer-view>
+    <right-bar></right-bar>
+  </div>
+</template>
+<script>
+  import { Header, Footer, RightBar } from '~components/default'
+  import { MainHeader, MainNav } from '~components/main'
+  export default {
+    name: 'pcb',
+    components: {
+      HeaderView: Header,
+      FooterView: Footer,
+      RightBar,
+      MainHeader,
+      MainNav
+    },
+    head () {
+      return {
+        title: this.title || '【优软商城】IC电子元器件现货采购交易平台商城',
+        meta: [
+          {hid: 'description', name: 'description', content: this.description || '优软商城(usoftmall.com)是中国领先的IC电子元器件现货采购交易网上商城,提供上千万种电子元器件现货采购交易,采购电子元器件就上优软商城!'},
+          {hid: 'keywords', name: 'keywords', content: this.keywords || '优软商城'}
+        ]
+      }
+    },
+    computed: {
+      isMobile: function () {
+        return this.$store.state.option.isMobile
+      },
+      title () {
+        let path = this.$route.path
+        if (path === '/product/kind/home') {
+          return '电子元器件器件选型参数型号查询器件类别分类大全-优软商城'
+        } else if (path.startsWith('/product/kind/')) {
+          if (this.kinds[this.kinds.length - 1]) {
+            return this.kinds[this.kinds.length - 1].nameCn + '产品品牌型号大全-优软商城'
+          }
+          return ''
+        } else if (path.startsWith('/product/component/')) {
+          if (this.componentDetail) {
+            return this.componentDetail.brand.nameCn + this.componentDetail.code + '参数|供应商|数据手册中文资料|规格书-优软商城'
+          } else {
+            return ''
+          }
+        } else if (path.startsWith('/product/brand/brandList/')) {
+          return 'IC电子元器件品牌中心品牌大全-优软商城'
+        } else if (path.startsWith('/product/brand/')) {
+          if (this.brandDetail.nameEn) {
+            return this.brandDetail.nameEn + '(' + this.brandDetail.nameCn + ')产品分类及产品型号大全-优软商城'
+          }
+          return '【优软商城】IC电子元器件现货采购交易平台商城'
+        } else if (path === '/provider/factories') {
+          return 'IC电子元器件厂家原厂直销原厂专卖店大全-优软商城'
+        } else if (path === '/provider/home') {
+          return 'IC电子元器件代理商经销商专营店大全-优软商城'
+        } else if (path === '/news') {
+          return 'IC电子元器件行业市场资讯新闻-优软商城'
+        } else if (path.startsWith('/news/')) {
+          return this.newsDetail.title + '-电子元器件行业资讯-优软商城' || 'IC电子元器件行业市场资讯新闻-优软商城'
+        } else if (path === '/search') {
+          return this.$route.query.w + '-产品搜索-优软商城'
+        } else if (path === '/searchStore') {
+          return this.$route.query.w + '-店铺搜索-优软商城'
+        } else {
+          return '【优软商城】IC电子元器件现货采购交易平台商城'
+        }
+      },
+      description () {
+        let path = this.$route.path
+        if (path === '/product/kind/home') {
+          return '优软商城电子元器件器件型号查询器件类别分类大全,优软商城提供元器件智能选型服务,能让您完美的找到热门型号的替代型号产品,一键搜索功能让您快速找到您想要的型号。'
+        } else if (path.startsWith('/product/kind/')) {
+          if (this.kinds[this.kinds.length - 1]) {
+            return '优软商城' + this.kinds[this.kinds.length - 1].nameCn + '产品品牌型号大全,能让您快速的找到' + this.kinds[this.kinds.length - 1].nameCn + '产品品牌型号。'
+          }
+          return ''
+        } else if (path.startsWith('/product/component/')) {
+          if (this.componentDetail) {
+            return '优软商城提供' + this.componentDetail.brand.nameCn + this.componentDetail.code + '数据手册中文资料规格书下载,' + this.componentDetail.code + '供应商及参数报价。'
+          } else {
+            return ''
+          }
+        } else if (path.startsWith('/product/brand/brandList/')) {
+          return 'IC电子元器件品牌中心品牌大全,优软商城品牌中心汇聚国内国际电子元器件品牌,全力打造国家级元器件电商品台。'
+        } else if (path.startsWith('/product/brand/')) {
+          if (this.brandDetail.brief) {
+            return this.brandDetail.brief || '优软商城(usoftmall.com)是中国领先的IC电子元器件现货采购交易网上商城,提供上千万种电子元器件现货采购交易,采购电子元器件就上优软商城!'
+          }
+          return ''
+        } else if (path === '/provider/factories') {
+          return 'IC电子元器件厂家原厂直销原厂专卖店大全,优软商城原厂专区提供IC电子元器件厂家原厂直销原厂专卖店大全。'
+        } else if (path === '/provider/home') {
+          return 'IC电子元器件代理商经销商专营店大全,优软商城代理经销专区提供IC电子元器件代理商经销商专卖店大全。'
+        } else if (path === '/news') {
+          return '优软商城电子元器件采购网提供精准的电子快讯,电子资讯,电子元器件资讯。'
+        } else if (path.startsWith('/news/')) {
+          return this.newsDetail.summary
+        } else {
+          return '优软商城(usoftmall.com)是中国领先的IC电子元器件现货采购交易网上商城,提供上千万种电子元器件现货采购交易,采购电子元器件就上优软商城!'
+        }
+      },
+      keywords () {
+        let path = this.$route.path
+        if (path === '/product/kind/home') {
+          return '电子元器件分类,电子元器件参数,电子元器件型号,电子元器件类别'
+        } else if (path.startsWith('/product/kind/')) {
+          if (this.kinds[this.kinds.length - 1]) {
+            return this.kinds[this.kinds.length - 1].nameCn
+          }
+          return ''
+        } else if (path.startsWith('/product/component/')) {
+          if (this.componentDetail) {
+            return this.componentDetail.code + '供应商,' + this.componentDetail.code + '数据手册,' + this.componentDetail.code + '规格书'
+          } else {
+            return ''
+          }
+        } else if (path.startsWith('/product/brand/brandList/')) {
+          return 'ic,元器件,品牌'
+        } else if (path.startsWith('/product/brand/')) {
+          if (this.brandDetail.nameEn) {
+            return this.brandDetail.nameEn + '(' + this.brandDetail.nameCn
+          }
+          return '优软商城'
+        } else if (path === '/provider/factories') {
+          return '电子元器件原厂,电子元器件厂家'
+        } else if (path === '/provider/home') {
+          return 'ic代理商,ic经销商,电子元器件代理商 , 电子元器件经销商'
+        } else if (path === '/news') {
+          return '元器件新闻,电子资讯,电子元器件资讯'
+        } else if (path.startsWith('/news/')) {
+          return ''
+        } else {
+          return '优软商城'
+        }
+      },
+      kinds () {
+        return this.$store.state.product.kind.kindsParentWithBother.data
+      },
+      componentDetail () {
+        return this.$store.state.componentDetail.detail.data
+      },
+      brandDetail () {
+        return this.$store.state.brandDetail.detail.data
+      },
+      newsDetail () {
+        return this.$store.state.newsData.detailNews.detailNews.data
+      }
+    }
+  }
+</script>

+ 7 - 2
nuxt.config.js

@@ -1,13 +1,16 @@
 const path = require('path')
 const isProdMode = Object.is(process.env.NODE_ENV, 'production')
 // b2c后台
-const baseUrl = process.env.BASE_URL || (isProdMode ? 'http://api.usoftmall.com/' : 'http://192.168.253.121:9090/platform-b2c')
+const baseUrl = process.env.BASE_URL || (isProdMode ? 'http://api.usoftmall.com/' : 'http://10.1.51.124:8080/platform-b2c')
 // 公共询价
 const commonUrl = process.env.COMMON_URL || (isProdMode ? 'https://api-inquiry.usoftmall.com/' : 'http://218.17.158.219:24000/')
 // 公共物料
 const materialUrl = process.env.MATERIAL_URL || (isProdMode ? 'https://api-product.usoftmall.com/' : 'http://218.17.158.219:24000/')
+// 公共cms
+const cmsUrl = process.env.CMS_URL || (isProdMode ? 'https://cms.usoftmall.com' : 'http://10.1.51.123:8080/jpress')
 // 消息
 const messageUrl = process.env.MATERIAL_URL || (isProdMode ? 'https://api-message.ubtob.com/' : 'http://192.168.253.6:24000/message')
+
 module.exports = {
   router: {
     middleware: 'check-auth',
@@ -90,6 +93,7 @@ module.exports = {
     baseUrl,
     commonUrl,
     materialUrl,
+    cmsUrl,
     messageUrl
   },
   plugins: [
@@ -183,6 +187,7 @@ module.exports = {
     '/internalmessage-service/**': baseUrl,
     '/wx/**': baseUrl,
     '/messages**': messageUrl,
-    '/messages/**': messageUrl
+    '/messages/**': messageUrl,
+    '/cmsApi**': cmsUrl
   }
 }

+ 17 - 2
pages/mobile/center/user/collect/message.vue

@@ -14,7 +14,7 @@
           </div>
           <div class="message">
             <p>{{item.createTime | time}}</p>
-            <a :href="item.type === 'MALL跳转卖家待报价页面' ? '/vendor#/seekPurchase?type=1' : item.type === 'MALL公共询价' ? '/user#/seekPurchase' : item.type === '商城公共询价采纳结果' ? '/vendor#/vendorPurchaseOffer' : ''"
+            <a :href="item.type === 'MALL跳转卖家待报价页面' ? '/mobile/center/user/seek?seekType=done' : item.type === 'MALL公共询价' ? '/mobile/center/vendor/seek?seekType=wait' : item.type === '商城公共询价采纳结果' ? '/mobile/center/vendor/seek?seekType=done' : ''"
                v-if="item.type"
                :title="item.content" class="info" target="_blank">{{item.content}}</a>
             <a v-else :title="item.content" class="noLink info">{{item.content}}</a>
@@ -34,7 +34,9 @@
     data () {
       return {
         count: 10,
-        page: 1
+        page: 1,
+        isChange: false,
+        msgList: []
       }
     },
     fetch ({ store }) {
@@ -63,6 +65,19 @@
       PullUp,
       EmptyStatus
     },
+    watch: {
+      'messageList': {
+        handler: function (val) {
+          if (this.isChange) {
+            this.msgList = val.content
+            this.isChange = false
+          } else {
+            this.msgList = [...this.msgList, ...val.content]
+          }
+        },
+        immediate: true
+      }
+    },
     methods: {
       reloadList: function () {
         this.$store.dispatch('messageShow/getAllMessage', { receiverUu: this.user.data.userUU, receiverEnuu: this.user.data.enterprise.uu, consumerApp: 'MALL', page: this.page, count: this.count, sorting: {'createTime': 'DESC'} })

+ 17 - 2
pages/mobile/center/vendor/message.vue

@@ -14,7 +14,7 @@
           </div>
           <div class="message">
             <p>{{item.createTime | time}}</p>
-            <a :href="item.type === 'MALL跳转卖家待报价页面' ? '/vendor#/seekPurchase?type=1' : item.type === 'MALL公共询价' ? '/user#/seekPurchase' : item.type === '商城公共询价采纳结果' ? '/vendor#/vendorPurchaseOffer' : ''"
+            <a :href="item.type === 'MALL跳转卖家待报价页面' ? '/mobile/center/user/seek?seekType=done' : item.type === 'MALL公共询价' ? '/mobile/center/vendor/seek?seekType=wait' : item.type === '商城公共询价采纳结果' ? '/mobile/center/vendor/seek?seekType=done' : ''"
                v-if="item.type"
                :title="item.content" class="info" target="_blank">{{item.content}}</a>
             <a v-else :title="item.content" class="noLink info">{{item.content}}</a>
@@ -34,7 +34,9 @@
     data () {
       return {
         count: 10,
-        page: 1
+        page: 1,
+        isChange: false,
+        msgList: []
       }
     },
     fetch ({ store }) {
@@ -63,6 +65,19 @@
       PullUp,
       EmptyStatus
     },
+    watch: {
+      'messageList': {
+        handler: function (val) {
+          if (this.isChange) {
+            this.msgList = val.content
+            this.isChange = false
+          } else {
+            this.msgList = [...this.msgList, ...val.content]
+          }
+        },
+        immediate: true
+      }
+    },
     methods: {
       reloadList: function () {
         this.$store.dispatch('messageShow/getAllMessage', { receiverUu: this.user.data.userUU, receiverEnuu: this.user.data.enterprise.uu, consumerApp: 'MALL', page: this.page, count: this.count, sorting: {'createTime': 'DESC'} })

+ 2 - 0
pages/mobile/center/vendor/seek.vue

@@ -20,6 +20,7 @@
       if (query.seekType === 'wait') {
         params.enuu = user.enterprise.uu
         params.useruu = user.userUU
+        params.enableOffer = 1
         return Promise.all([
           store.dispatch('applyPurchase/loadVendorEnPushList', params)
         ])
@@ -52,6 +53,7 @@
           params.enuu = user.enterprise.uu
           params.useruu = user.userUU
           params.keyword = keyword
+          params.enableOffer = 1
           return Promise.all([
             store.dispatch(`applyPurchase/${activeType === 'all' ? 'loadVendorEnPushList' : 'loadVendorPushList'}`, params)
           ])

+ 8 - 2
pages/mobile/product/_batchCode.vue

@@ -115,8 +115,11 @@
           <div v-if="checkInfo(storeInfo.enterprise.enAddress)">商家地址:{{storeInfo.enterprise.enAddress}}</div>
 -->
           <!--<div class="content-line link-url">在线咨询</div>-->
-          <div v-if="checkInfo(storeInfo.enterprise.enTel)">致电:<a :href="'tel:' + storeInfo.enterprise.enTel" target="_blank" class="content-line link-url">{{storeInfo.enterprise.enTel}}</a></div>
-          <div v-else>暂无联系方式</div>
+          <div v-if="checkInfo(storeInfo.enterprise.enTel)">电话:<a :href="'tel:' + storeInfo.enterprise.enTel" target="_blank" class="content-line link-url">{{storeInfo.enterprise.enTel}}</a></div>
+          <div v-if="checkInfo(storeInfo.enterprise.enPhone)">手机:<a :href="'tel:' + storeInfo.enterprise.enPhone" target="_blank" class="content-line link-url">{{storeInfo.enterprise.enPhone}}</a></div>
+          <div v-if="checkInfo(storeInfo.enterprise.enWeixin)">微信:<span class="content-line">{{storeInfo.enterprise.enWeixin}}</span></div>
+          <div v-if="checkInfo(storeInfo.enterprise.enQQ)">Q&nbsp;Q:<span class="content-line">{{storeInfo.enterprise.enQQ}}</span></div>
+          <div v-if="!empty">暂无联系方式</div>
           <!--
           <div v-if="checkInfo(storeInfo.enterprise.enEmail)">邮件:<a :href="'mailto:' + storeInfo.enterprise.enEmail" target="_blank" class="content-line link-url">{{storeInfo.enterprise.enEmail}}</a></div>
 -->
@@ -176,6 +179,9 @@
       },
       component () {
         return this.$store.state.shop.storeInfo.component.data
+      },
+      empty () {
+        return this.checkInfo(this.storeInfo.enterprise.enTel) || this.checkInfo(this.storeInfo.enterprise.enPhone) || this.checkInfo(this.storeInfo.enterprise.enWeixin) || this.checkInfo(this.storeInfo.enterprise.enQQ)
       }
     },
     methods: {

+ 46 - 0
pages/pcb/brand/_id.vue

@@ -0,0 +1,46 @@
+<template>
+  <div class="details">
+    <div class="information">
+      <brand-detail :isPcb="true"/>
+      <div class="comm-list">
+        <categories-list :isPcb="true" @kindSelectAction="onKindSelect"/>
+        <brand-list :kindid="kindid"></brand-list>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  import { BrandDetail, CategoriesList } from '~components/product'
+  import { BrandList } from '~components/pcb'
+  export default {
+    layout: 'pcb',
+    data () {
+      return {
+        code: '',
+        kindid: ''
+      }
+    },
+    components: {
+      BrandDetail,
+      CategoriesList,
+      BrandList
+    },
+    fetch ({ store, params }) {
+      return Promise.all([
+        store.dispatch('loadBrandDetail', { id: params.id, isPcb: true })
+      ])
+    },
+    methods: {
+      onKindSelect: function (kindid) {
+        this.kindid = kindid || null
+      }
+    }
+  }
+</script>
+<style scoped>
+  .comm-list{
+    width: 1190px;
+    margin: 0 auto;
+    overflow: hidden;
+  }
+</style>

+ 25 - 0
pages/pcb/index.vue

@@ -0,0 +1,25 @@
+<template>
+  <div>
+    <kinds></kinds>
+    <intro></intro>
+    <recommend-brand></recommend-brand>
+    <floors></floors>
+  </div>
+</template>
+<script>
+  import { Kinds, Intro, RecommendBrand, Floors } from '~components/pcb'
+  export default {
+    layout: 'pcb',
+    components: {
+      Kinds,
+      Intro,
+      RecommendBrand,
+      Floors
+    },
+    fetch ({ store }) {
+      return Promise.all([
+        store.dispatch('pcb/getPcbKinds', {parentId: 3825})
+      ])
+    }
+  }
+</script>

+ 26 - 0
pages/pcb/product/_productId/_batchCode.vue

@@ -0,0 +1,26 @@
+<template>
+  <div class="pcb-product-detail">
+    <detail></detail>
+  </div>
+</template>
+<script>
+  import { Detail } from '~components/pcb'
+  export default {
+    layout: 'pcb',
+    components: {
+      Detail
+    },
+    fetch ({store, params}) {
+      return Promise.all([
+        store.dispatch('pcb/getPcbProduct', {productId: params.productId}),
+        store.dispatch('shop/findCommodityOnBatchInfo', {batchCode: params.batchCode})
+      ])
+    }
+  }
+</script>
+<style scoped>
+    .pcb-product-detail {
+      width: 1190px;
+      margin: 0 auto;
+    }
+</style>

+ 129 - 0
pages/pcb/search/_keyword.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="container" id="searchResult">
+    <detail-brand></detail-brand>
+    <result-title :keyword="key" :page="nowPage"></result-title>
+    <kind @kindFilterEvent="listenKindFilter"
+          @brandFilterEvent="listenBrandFilter"
+    ></kind>
+    <good-list @pageEvent="listenPage"
+               @sortEvent="listenSort"
+               @filterPriceEvent="listenPriceFilter"
+    ></good-list>
+  </div>
+</template>
+<script>
+  import { GoodList, Kind, ResultTitle, DetailBrand } from '~components/pcb'
+  export default{
+    layout: 'pcb',
+    data () {
+      return {
+        key: this.$route.query.w,
+        pageSize: 15,
+        nowPage: 1,
+        sorting: {},
+        filter: {},
+        paramJSON: {}
+      }
+    },
+    fetch ({store, route}) {
+      return Promise.all([
+        store.dispatch('pcb/searchForKinds', {collectedField: 'goods_kind', keyword: route.query.w, filters: {}}),
+        store.dispatch('pcb/searchForBrands', {collectedField: 'goods_brand', keyword: route.query.w, filters: {}}),
+        store.dispatch('pcb/searchForList', {count: 15, filter: {}, keyword: route.query.w, page: 1, sorting: {}})
+      ])
+    },
+    watch: {
+      '$route.query.w': {
+        handler: function (val) {
+          this.key = val
+          this.reloadAll()
+        },
+        immediate: false
+      }
+    },
+    components: {
+      ResultTitle,
+      Kind,
+      GoodList,
+      DetailBrand
+    },
+    methods: {
+      reloadAll: function () {
+        this.filter = {}
+        this.sorting = {}
+        this.paramJSON = {}
+        this.reloadList()
+        this.reloadKind()
+        this.reloadBrand()
+      },
+      reloadList: function () {
+        if (this.sorting === {}) {
+          this.sorting = {}
+        }
+        this.$store.dispatch('pcb/searchForList', {count: this.pageSize, filter: this.filter, keyword: this.$route.query.w, page: this.nowPage, sorting: this.sorting})
+      },
+      reloadKind: function () {
+        if (!this.filter.goods_kindId) {
+          this.$store.dispatch('pcb/searchForKinds', {collectedField: 'goods_kind', keyword: this.$route.query.w, filters: this.paramJSON})
+        }
+      },
+      reloadBrand: function () {
+        if (!this.filter.goods_brandId) {
+          this.$store.dispatch('pcb/searchForBrands', {collectedField: 'goods_brand', keyword: this.$route.query.w, filters: this.paramJSON})
+        }
+      },
+      listenPage: function (nPage) {
+        this.nowPage = nPage
+        this.reloadList()
+      },
+      listenSort: function (sortType) {
+        this.sorting = sortType
+        this.reloadList()
+      },
+      listenPriceFilter: function (filterType) {
+        if (filterType.goods_minpricermb) {
+          this.filter.goods_minpricermb = filterType.goods_minpricermb
+        } else {
+          delete this.filter.goods_minpricermb
+        }
+        if (filterType.goods_maxpricermb) {
+          this.filter.goods_maxpricermb = filterType.goods_maxpricermb
+        } else {
+          delete this.filter.goods_maxpricermb
+        }
+        this.reloadList()
+      },
+      listenKindFilter: function (kindarr) {
+        this.nowPage = 1
+        if (kindarr.length === 0) {
+          delete this.filter.goods_kindId
+          delete this.paramJSON.goods_kindid
+          this.reloadKind()
+          this.reloadBrand()
+          this.reloadList()
+        } else {
+          this.filter.goods_kindId = kindarr
+          this.paramJSON.goods_kindid = kindarr
+          this.reloadBrand()
+          this.reloadList()
+        }
+      },
+      listenBrandFilter: function (brandarr) {
+        this.nowPage = 1
+        if (brandarr.length === 0) {
+          delete this.filter.goods_brandId
+          delete this.paramJSON.goods_brandid
+          this.reloadKind()
+          this.reloadBrand()
+          this.reloadList()
+        } else {
+          this.filter.goods_brandId = brandarr
+          this.paramJSON.goods_brandid = brandarr
+          this.reloadKind()
+          this.reloadList()
+        }
+      }
+    }
+  }
+</script>
+

+ 15 - 21
pages/product/brand/_code.vue

@@ -1,48 +1,42 @@
 <template>
   <div class="details">
-    <div class="information" v-if="list.id">
+    <div class="information">
       <brand-detail/>
-      <div class="comm-list">
-        <categories-list/>
-        <brand-component/>
+      <div class="comm-list" v-if="true">
+        <categories-list :isShow="isShow"></categories-list>
+        <brand-component @showEvent="showList"></brand-component>
       </div>
     </div>
-    <div v-else>
-      <error-page :title="'品牌'"></error-page>
-    </div>
   </div>
 </template>
 <script>
   import { BrandDetail, CategoriesList, BrandComponent } from '~components/product'
-  import { ErrorPage } from '~components/error'
   export default {
     layout: 'main',
     data () {
       return {
-        code: ''
+        code: '',
+        isShow: 0
       }
     },
     components: {
       BrandDetail,
       CategoriesList,
-      BrandComponent,
-      ErrorPage
-    },
-    computed: {
-      list () {
-        let list = this.$store.state.brandDetail.detail.data
-        if (list.application && list.application !== '') {
-          this.applications = list.application.split(',')
-        }
-//        console.log(list)
-        return list
-      }
+      BrandComponent
     },
     fetch ({ store, params }) {
       return Promise.all([
         store.dispatch('loadBrandDetail', { id: params.code }),
         store.dispatch('product/loadSupplierInformation', { uuid: params.code, count: 5, page: 1 })
       ])
+    },
+    methods: {
+      showList: function (status) {
+        this.isShow = status
+      },
+      listenChild: function (brand) {
+        this.$store.dispatch('loadBrandPages', {count: 10, filter: { brandid: brand.id }, page: brand.page})
+      }
     }
   }
 </script>

+ 0 - 66
pages/product/brand/brandList.vue

@@ -1,66 +0,0 @@
-<template>
-  <div>
-    <img class="banner-img" src="/images/all/banner-brandcenter.jpg" alt="">
-    <recommends></recommends>
-    <img class="banner-img" src="/images/all/banner-brandcenter2.jpg" alt="">
-    <div id="brandsList" class="container">
-      <div class="title-icon">品牌索引</div>
-      <div class="hr-blue"></div>
-      <ul class="row initials">
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/ABC'">ABC</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/DEF'">DEF</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/GHI'">GHI</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/JKL'">JKL</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/MNO'">MNO</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/PQR'">PQR</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/STU'">STU</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/VWX'">VWX</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/YZ'">YZ</nuxt-link>
-        </li>
-        <li class="col-xs-1 initial">
-          <nuxt-link :to="'/product/brand/brandList/0~9'">0~9</nuxt-link>
-        </li>
-      </ul>
-    </div>
-    <nuxt-child/>
-  </div>
-</template>
-
-<script>
-  import { Recommends } from '~components/product'
-
-  export default {
-    layout: 'main',
-    fetch ({store}) {
-      return Promise.all([
-        store.dispatch('product/loadRecommends')
-      ])
-    },
-    components: {
-      Recommends
-    }
-  }
-</script>
-<style scoped>
-  .router-link-exact-active{
-    color: #5078CB;
-    font-weight: bold;
-  }
-</style>

+ 53 - 6
pages/product/brand/brandList/_initial.vue

@@ -1,19 +1,66 @@
 <template>
-  <brand-list></brand-list>
+  <div id="brand-center">
+    <!--<new-search :background="bgLink"></new-search>-->
+    <recommend-brand></recommend-brand>
+    <brand-index></brand-index>
+    <!--<type-index :title="title"></type-index>-->
+  </div>
 </template>
 
 <script>
-  import { BrandList } from '~components/product'
-
+//  import { BrandList, Recommends } from '~components/product'
+  import { NewSearch } from '~components/home'
+  import { RecommendBrand, BrandIndex } from '~components/brandCenter'
   export default {
-    name: 'brandListDetail',
+    name: 'brandCenterIndex',
+    layout: 'default',
+    data () {
+      return {
+        background: '/images/brandCenter/search-bg.png',
+        title: '型号索引:'
+      }
+    },
+    computed: {
+      bgLink () {
+        return this.$store.state.product.banner.brandBanner.data.data[0].pictureLink
+      }
+    },
     fetch ({store, route}) {
       return Promise.all([
-        store.dispatch('product/loadBrands', {'keyword': route.params.initial})
+        store.dispatch('loadFloors'),
+        store.dispatch('loadBanners', {type: 'Brand-v3'}),
+        store.dispatch('loadBrandCarousel'),
+        store.dispatch('loadBrandBanner'),
+        store.dispatch('product/loadRecommends'),
+        store.dispatch('product/loadBrandsPager', {'initial': route.params.initial, 'page': 1, 'count': 60, 'keyword': ''})
       ])
     },
     components: {
-      BrandList
+//      BrandList,
+//      Recommends
+      NewSearch,
+      RecommendBrand,
+      BrandIndex
     }
   }
 </script>
+<style lang="scss">
+  /*.router-link-exact-active{*/
+    /*color: #5078CB;*/
+    /*font-weight: bold;*/
+  /*}*/
+  #brand-center {
+    .search-box {
+      background-size: auto!important;
+      background-position: 54% 0!important;
+     /* height: 187px;*/
+      height: 444px;
+      .input-group {
+        padding-top: 300px;
+      }
+      .association {
+        top: 125px;
+      }
+    }
+  }
+</style>

+ 3 - 0
plugins/axios.js

@@ -19,11 +19,14 @@ service.interceptors.request.use(config => {
       config.url = process.env.commonUrl + config.url
     } else if (config.url.indexOf('/productsuer') === 0) {
       config.url = process.env.materialUrl + config.url
+    } else if (config.url.indexOf('/cmsApi') === 0) {
+      config.url = process.env.cmsUrl + config.url
     } else if (config.url.indexOf('/messages') === 0) {
       config.url = process.env.messageUrl + config.url
     } else {
       config.url = process.env.baseUrl + config.url
     }
+    // console.log(config.url)
     // config.headers.cookie = store.state.option.cookies + '; ' + store.state.option.sessionId
     // config.headers['User-Agent']
   } else {

+ 7 - 0
plugins/mixin.js

@@ -4,6 +4,7 @@
 */
 import BScroll from 'better-scroll'
 import Vue from 'vue'
+import {deepCopy, goLinkUser} from '~utils/baseUtils'
 // import { mapState } from 'vuex'
 
 Vue.mixin({
@@ -48,6 +49,12 @@ Vue.mixin({
       } else {
         return {}
       }
+    },
+    baseUtils () {
+      return {
+        deepCopy: deepCopy,
+        goLinkUser: goLinkUser
+      }
     }
   },
   methods: {

BIN
static/images/applyPurchase/apply-top-ad.jpg


BIN
static/images/brandCenter/brand-index-bg.png


BIN
static/images/brandCenter/brand-index-title.png


BIN
static/images/brandCenter/brand-index-tree.png


BIN
static/images/brandCenter/brand-introduce-line.png


BIN
static/images/brandCenter/detail.jpg


BIN
static/images/brandCenter/detail.png


BIN
static/images/brandCenter/logo1.png


BIN
static/images/brandCenter/logo2.png


BIN
static/images/brandCenter/logo3.png


BIN
static/images/brandCenter/logo4.png


BIN
static/images/brandCenter/recommend-bg.png


BIN
static/images/brandCenter/recommend-title.png


BIN
static/images/brandCenter/search-bg.png


BIN
static/images/brandCenter/search-btn.png


BIN
static/images/brandCenter/type.png


BIN
static/images/brandList/empty-cart.jpg


BIN
static/images/brandList/upload.png


BIN
static/images/pcb/banner.png


BIN
static/images/pcb/identified.png


BIN
static/images/pcb/intro-bg.png


BIN
static/images/pcb/link.png


BIN
static/images/pcb/price-bg.png


BIN
static/images/pcb/recommend-brand.png


BIN
static/images/pcb/test-logo.png


+ 14 - 0
store/carousel.js

@@ -2,6 +2,10 @@ export const state = () => ({
   banners: {
     fetching: false,
     data: []
+  },
+  brandCarousel: {
+    fetching: false,
+    data: []
   }
 })
 
@@ -15,5 +19,15 @@ export const mutations = {
   GET_BANNER_SUCCESS (state, result) {
     state.banners.fetching = false
     state.banners.data = result
+  },
+  REQUEST_BRANDCAROUSEL (state) {
+    state.brandCarousel.fetching = true
+  },
+  GET_BRANDCAROUSEL_FAILURE (state) {
+    state.brandCarousel.fetching = false
+  },
+  GET_BRANDCAROUSEL_SUCCESS (state, result) {
+    state.brandCarousel.fetching = false
+    state.brandCarousel.data = result
   }
 }

+ 20 - 0
store/index.js

@@ -476,6 +476,26 @@ export const actions = {
       }, err => {
         commit('option/REQUEST_WECHATINFO_STATUS_FAILURE', err)
       })
+  },
+  // 获取品牌中心轮播图
+  loadBrandCarousel ({ commit }) {
+    commit('carousel/REQUEST_BRANDCAROUSEL')
+    return axios.get('/cmsApi?method=queryContentPage&module=brandCenter_littleSlideshow&orderBy=contExp_sort')
+      .then(response => {
+        commit('carousel/GET_BRANDCAROUSEL_SUCCESS', response.data)
+      }, err => {
+        commit('carousel/GET_BRANDCAROUSEL_FAILURE', err)
+      })
+  },
+  // 获取品牌中心首屏背景图
+  loadBrandBanner ({ commit }) {
+    commit('product/banner/REQUEST_BRANDBANNER')
+    return axios.get('/cmsApi?method=queryContentPage&module=brandCenter_firstScreen&orderBy=contExp_sort')
+      .then(response => {
+        commit('product/banner/GET_BRANDBANNER_SUCCESS', response.data)
+      }, err => {
+        commit('product/banner/GET_BRANDBANNER_FAILURE', err)
+      })
   }
 }
 

+ 55 - 0
store/pcb.js

@@ -0,0 +1,55 @@
+import axios from '~plugins/axios'
+
+export const actions = {
+  // 获取pcb首页类目
+  getPcbKinds ({ commit }, params = {}) {
+    commit('kindsData/REQUEST_PCB_KINDS', params)
+    return axios.get(`/api/product/kind/${params.parentId}/pcbchildren_all`)
+      .then(response => {
+        commit('kindsData/GET_PCB_KINDS_SUCCESS', response.data)
+      }, err => {
+        commit('kindsData/GET_PCB_KINDS_FAILURE', err)
+      })
+  },
+  // 获取pcb产品详情
+  getPcbProduct ({ commit }, params = {}) {
+    commit('product/REQUEST_PCB_PRODUCT', params)
+    return axios.get(`/api/product/kind/pcbproperty/${params.productId}`)
+      .then(response => {
+        commit('product/GET_PCB_PRODUCT_SUCCESS', response.data)
+      }, err => {
+        commit('product/GET_PCB_PRODUCT_FAILURE', err)
+      })
+  },
+  // 获取pcb搜索kind
+  searchForKinds ({ commit }, params = {}) {
+    commit('search/REQUEST_KINDS', params)
+    return axios.get(`/search/PCBGoods/collect`, {params})
+      .then(response => {
+        commit('search/GET_KINDS_SUCCESS', response.data)
+      }, err => {
+        commit('search/GET_KINDS_FAILURE', err)
+      })
+  },
+  // 获取pcb搜索brand
+  searchForBrands ({ commit }, params = {}) {
+    commit('search/REQUEST_BRANDS', params)
+    return axios.get(`/search/PCBGoods/collect`, {params})
+      .then(response => {
+        commit('search/GET_BRANDS_SUCCESS', response.data)
+      }, err => {
+        commit('search/GET_BRANDS_FAILURE', err)
+      })
+  },
+  // 获取pcb搜索list
+  searchForList ({ commit }, params = {}) {
+    commit('search/REQUEST_LIST', params)
+    return axios.get(`/search/pcbgoods/page`, {params})
+      .then(response => {
+        commit('search/GET_LIST_SUCCESS', response.data)
+      }, err => {
+        commit('search/GET_LIST_FAILURE', err)
+      })
+  }
+}
+

+ 19 - 0
store/pcb/kindsData.js

@@ -0,0 +1,19 @@
+export const state = () => ({
+  kinds: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  REQUEST_PCB_KINDS (state) {
+    state.kinds.fetching = true
+  },
+  GET_PCB_KINDS_SUCCESS (state, result) {
+    state.kinds.fetching = false
+    state.kinds.data = result
+  },
+  GET_PCB_KINDS_FAILURE (state) {
+    state.kinds.fetching = false
+  }
+}

+ 19 - 0
store/pcb/product.js

@@ -0,0 +1,19 @@
+export const state = () => ({
+  detail: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  REQUEST_PCB_PRODUCT (state) {
+    state.detail.fetching = true
+  },
+  GET_PCB_PRODUCT_SUCCESS (state, result) {
+    state.detail.fetching = false
+    state.detail.data = result
+  },
+  GET_PCB_PRODUCT_FAILURE (state) {
+    state.detail.fetching = false
+  }
+}

+ 47 - 0
store/pcb/search.js

@@ -0,0 +1,47 @@
+export const state = () => ({
+  kinds: {
+    fetching: false,
+    data: []
+  },
+  brands: {
+    fetching: false,
+    data: []
+  },
+  list: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  REQUEST_KINDS (state) {
+    state.kinds.fetching = true
+  },
+  GET_KINDS_SUCCESS (state, result) {
+    state.kinds.fetching = false
+    state.kinds.data = result
+  },
+  GET_KINDS_FAILURE (state) {
+    state.kinds.fetching = false
+  },
+  REQUEST_BRANDS (state) {
+    state.brands.fetching = true
+  },
+  GET_BRANDS_SUCCESS (state, result) {
+    state.brands.fetching = false
+    state.brands.data = result
+  },
+  GET_BRANDS_FAILURE (state) {
+    state.brands.fetching = false
+  },
+  REQUEST_LIST (state) {
+    state.list.fetching = true
+  },
+  GET_LIST_SUCCESS (state, result) {
+    state.list.fetching = false
+    state.list.data = result
+  },
+  GET_LIST_FAILURE (state) {
+    state.list.fetching = false
+  }
+}

+ 12 - 8
store/product.js

@@ -27,7 +27,7 @@ export const actions = {
   // 品牌列表推荐品牌配置
   loadRecommends ({ commit }) {
     commit('brand/REQUEST_RECOMMENDS')
-    return axios.get(`/api/product/brand/hot/5`)
+    return axios.get('/cmsApi?method=queryContentPage&module=brandCenter_brandReco&orderBy=contExp_sort')
       .then(response => {
         commit('brand/GET_RECOMMENDS_SUCCESS', response.data)
       }, err => {
@@ -45,14 +45,8 @@ export const actions = {
         commit('brand/GET_BRANDS_FAILURE', err)
       })
   },
-  // 品牌列表分页查询
+  // 品牌列表分页查询(索引)
   loadBrandsPager ({ commit }, params = {}) {
-    // let initial = params.initial
-    // let param = {
-    //   page: params.page || 1,
-    //   count: params.count || 30,
-    //   keyword: params.keyword
-    // }
     commit('brand/REQUEST_BRANDS_PAGER', params)
     return axios.get(`/api/product/brand/page/initial`, {params: params})
       .then(response => {
@@ -61,6 +55,16 @@ export const actions = {
         commit('brand/GET_BRANDS_PAGER_FAILURE', err)
       })
   },
+  // 品牌列表分页查询(搜索)
+  loadBrandsPagerWithoutIndex ({ commit }, params = {}) {
+    commit('brand/REQUEST_BRANDS_PAGER', params)
+    return axios.get(`/api/product/brand/Brand/ByPage`, {params: params})
+      .then(response => {
+        commit('brand/GET_BRANDS_PAGER_SUCCESS', response.data)
+      }, err => {
+        commit('brand/GET_BRANDS_PAGER_FAILURE', err)
+      })
+  },
   // 获取全部子器件类目
   loadAllProductKinds ({ commit }, params = {}) {
     let id = params.id

+ 19 - 0
store/product/banner.js

@@ -0,0 +1,19 @@
+export const state = () => ({
+  brandBanner: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  REQUEST_BRANDBANNER (state) {
+    state.brandBanner.fetching = true
+  },
+  GET_BRANDBANNER_SUCCESS (state, result) {
+    state.brandBanner.fetching = false
+    state.brandBanner.data = result
+  },
+  GET_BRANDBANNER_FAILURE (state) {
+    state.brandBanner.fetching = false
+  }
+}

+ 96 - 0
utils/baseUtils.js

@@ -227,3 +227,99 @@ export function whichTransitionEvent() {
     }
   }
 }
+// 立即购买或加入购物车
+/*
+ *  isBuy: 是否是立即购买
+ *  event: 触发事件
+ *  $this: 当前对象
+ *  item: 操作对象
+ * */
+const buyNow = function (isBuy, event, $this, item) {
+  if (event) event.stopPropagation()
+  if (!$this.$store.state.option.user.logged) {
+    $this.$http.get('/login/page', {params: {returnUrl: window.location.href}}).then(response => {
+      if (response.data) {
+        window.location.href = response.data.content + '&baseUrl=' + encodeURIComponent(window.location.protocol + '//' + window.location.host + response.data.baseUrl)
+      }
+    })
+  } else {
+    if (item && !$this.disabledFlag) {
+      if (isBuy) {
+        $this.$http.post('/trade/order/buyNow', [{
+          uuid: item.uuid,
+          batchCode: item.batchCode,
+          number: item.minBuyQty,
+          storeid: item.storeid ? item.storeid : item.storeId,
+          storeUuid: item.storeid ? item.storeid : item.storeId,
+          currencyName: item.currencyName,
+          minPackQty: item.minPackQty
+        }])
+          .then(response => {
+            //        window.location.href = '/user#/order/pay/' + $this.enidfilter(response.data.orderid)
+            if (response.data.success) {
+              if (response.data.message) {
+                $this.$message({
+                  message: response.data.message,
+                  type: 'success'
+                })
+                window.setTimeout(function () {
+                  window.location.href = '/user#/order/pay/' + enidfilter(response.data.data.orderid)
+                }, 1000)
+              } else {
+                window.location.href = '/user#/order/pay/' + enidfilter(response.data.data.orderid)
+              }
+            } else {
+              if (response.data.data && response.data.data.unvailable === 1) {
+                $this.$message.error('产品信息已失效,请刷新页面')
+              } else {
+                $this.$message.error(response.data.message)
+              }
+            }
+          }, err => {
+            console.log(err)
+            if (item.minBuyQty > item.reserve) {
+              $this.$message.error('商品' + item.code + '的库存已经不满足起订量')
+            }
+          })
+      } else {
+        // $this.$store.dispatch('user/addCar', {uuid: item.uuid, batchCode: item.batchCode, number: item.minBuyQty})
+        $this.$http.post('/trade/cart/add', {
+          uuid: item.uuid,
+          batchCode: item.batchCode,
+          number: item.minBuyQty,
+          storeid: item.storeid ? item.storeid : item.storeId,
+          storeUuid: item.storeid ? item.storeid : item.storeId,
+          currencyName: item.currencyName,
+          minPackQty: item.minPackQty
+        })
+          .then(response => {
+            if (response.data.success) {
+              if (response.data.message) {
+                $this.$message({
+                  message: '添加购物车成功,但商品信息有更新',
+                  type: 'success'
+                })
+              } else {
+                $this.$message({
+                  message: '添加购物车成功',
+                  type: 'success'
+                })
+              }
+            } else {
+              // if (response.data.code === 2) {
+              //   $this.$message.error('库存已不满足起订量')
+              // } else
+              if (response.data.message === '该产品已失效') {
+                $this.$message.error(response.data.message + ',请刷新页面')
+              } else {
+                $this.$message.error(response.data.message)
+              }
+            }
+          })
+      }
+    }
+  }
+  // window.location.href = 'user#/order/pay/' + $this.enidfilter($this.buy_info.orderid)
+}
+
+export const buyOrCar = buyNow