Browse Source

Merge branch 'yc-store_share-0207'

# Conflicts:
#	nuxt.config.js
yangc 7 years ago
parent
commit
218eb0f7c8

+ 5 - 0
components/mobile/share/index.js

@@ -0,0 +1,5 @@
+import CommodityList from './store/CommodityList.vue'
+import StoreHeader from './store/StoreHeader.vue'
+import StoreFooter from './store/StoreFooter.vue'
+
+export { CommodityList, StoreHeader, StoreFooter }

+ 138 - 0
components/mobile/share/store/CommodityList.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="share-store-commodity">
+    <div class="title" v-if="commodities.content && commodities.content.length">
+      <img src="/images/mobile/@2x/shareStore/commodity-title@2x.png" alt="">
+      <div class="date">
+        <span>{{date.month}}</span>月<span>{{date.day}}</span>日
+      </div>
+      <div class="fr">真实库存、真实价格</div>
+    </div>
+    <ul>
+      <li v-for="commodity in commodities.content">
+        <div class="fl">
+          <p>{{commodity.code || '-'}}</p>
+          <span v-if="commodity.brandNameEn || commodity.brandEn">{{commodity.brandNameEn || commodity.brandEn || '-'}}</span>
+        </div>
+        <div class="fr">
+          <span>{{commodity.currencyName === 'USD' ? '$' : '¥'}}</span>
+          <span>{{commodity.prices[0].rMBPrice}}</span>
+        </div>
+      </li>
+    </ul>
+    <div v-if="!commodities.content || !commodities.content.length" class="empty">
+      <img src="/images/mobile/@2x/shareStore/empty.png" alt="">
+      <p>抱歉,该店铺暂未上架商品</p>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    filters: {
+      price: function (val) {
+        return val.toFixed(2)
+      }
+    },
+    computed: {
+      commodities () {
+        return this.$store.state.shop.storeInfo.storeCommodity.data
+//        return []
+      },
+      date () {
+        let now = new Date()
+        const monthTemp = now.getMonth() + 1
+        const dayTemp = now.getDate()
+        const month = monthTemp < 10 ? '0' + monthTemp : monthTemp
+        const day = dayTemp < 10 ? '0' + dayTemp : dayTemp
+        return {
+          month: month,
+          day: day
+        }
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .share-store-commodity {
+    padding: .24rem .3rem;
+    .title {
+      margin-bottom: .2rem;
+      img {
+        width: 1.59rem;
+        height: .45rem;
+      }
+      .date {
+        display: inline-block;
+        font-size: .21rem;
+        color: #fa3f46;
+        position: relative;
+        top: .06rem;
+        left: .32rem;
+        span {
+          color: #fff;
+          font-size: .24rem;
+          display: inline-block;
+          width: .32rem;
+          height: .28rem;
+          line-height: .28rem;
+          text-align: center;
+          border-radius: 2px;
+          background: #fa3f46;
+          margin: .04rem;
+        }
+      }
+      .fr {
+        font-size: .24rem;
+        color: #666;
+        position: relative;
+        top: .16rem;
+      }
+    }
+    > ul {
+      li {
+        height: .82rem;
+        border-bottom: .02rem solid rgba(217, 217, 217, .35);
+        > div {
+          height: .82rem;
+          &.fl {
+            line-height: .4rem;
+            p {
+              font-size: .24rem;
+              color: #f1a850;
+            }
+            span {
+              font-size: .21rem;
+              color: #999;
+            }
+          }
+          &.fr {
+            font-size: .24rem;
+            color: #e21616;
+            line-height: .82rem;
+            width: 1.2rem;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            span {
+              &:nth-child(2) {
+                font-size: .26rem;
+              }
+            }
+          }
+        }
+      }
+    }
+    .empty {
+      text-align: center;
+      padding: 1.44rem 0 2.04rem 0;
+      img {
+        width: 1.21rem;
+        height: 1.21rem;
+      }
+      p {
+        font-size: .24rem;
+        color: #ddd;
+        margin-top: .17rem;
+      }
+    }
+  }
+</style>

+ 147 - 0
components/mobile/share/store/StoreFooter.vue

@@ -0,0 +1,147 @@
+<template>
+  <div class="share-store-footer">
+    <div class="more">
+      <div class="hr"></div>
+      <p>如需查看更多器件请登录<nuxt-link to="/">优软商城</nuxt-link></p>
+      <div class="hr"></div>
+    </div>
+    <div class="info">
+      <img src="/images/mobile/@2x/shareStore/store-info.png" alt="">
+      <div class="info-line">
+        <div class="fl">
+          <img src="/images/mobile/@2x/shareStore/phone.png" alt="">
+          <span>联系电话</span>
+        </div>
+        <div class="fr">{{storeInfo.enterprise.enTel || '无'}}</div>
+      </div>
+      <div class="info-line">
+        <div class="fl">
+          <img src="/images/mobile/@2x/shareStore/fax.png" alt="">
+          <span>传真</span>
+        </div>
+        <div class="fr">{{storeInfo.enterprise.enFax || '无'}}</div>
+      </div>
+      <div class="info-line">
+        <div class="fl">
+          <img src="/images/mobile/@2x/shareStore/address.png" alt="">
+          <span>公司地址</span>
+        </div>
+        <div class="fr">{{storeInfo.enterprise.address || storeInfo.enterprise.enAddress}}</div>
+      </div>
+    </div>
+    <div class="company">
+      <div class="hr"></div>
+      <img src="/images/mobile/@2x/shareStore/logo.png" alt="">
+      <div class="hr right"></div>
+      <p>此页面由深圳市优软商城科技有限公司提供</p>
+      <a href="https://www.usoftmall.com">www.usoftmall.com</a>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    computed: {
+      storeInfo () {
+        return this.$store.state.shop.storeInfo.store.data
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+    .share-store-footer {
+      .more {
+        height: .62rem;
+        line-height: .62rem;
+        font-size: .24rem;
+        background: #f4f4f4;
+        text-align: center;
+        position: relative;
+        p {
+          color: #a9a9aa;
+          a {
+            color: #2f50f7;
+          }
+        }
+        .hr {
+          width: 1.09rem;
+          height: .02rem;
+          background: #d9d9d9;
+          position: absolute;
+          left: .77rem;
+          top: .3rem;
+          &:last-child {
+            right: .77rem;
+            left: auto;
+          }
+        }
+      }
+      .info {
+        height: 2.82rem;
+        background: #fff;
+        padding: .19rem .38rem 0 .35rem ;
+        > img {
+          width: 1.38rem;
+          height: .45rem;
+          margin-bottom: .25rem;
+        }
+        .info-line {
+          margin-top: .2rem;
+          height: .28rem;
+          .fl {
+            > img {
+              width: .28rem;
+              height: .28rem;
+            }
+            span {
+              font-size: .24rem;
+              color: #3c3c3c;
+              line-height: .28rem;
+              margin-left: .18rem;
+            }
+          }
+          .fr {
+            font-size: .21rem;
+            color: #ef873a;
+            line-height: .28rem;
+            max-width: 4.2rem;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+          }
+        }
+      }
+      .company {
+        position: relative;
+        height: 1.36rem;
+        background: #f4f4f4;
+        text-align: center;
+        img {
+          width: 1.15rem;
+          height: .23rem;
+          margin-top: .24rem;
+        }
+        p {
+          font-size: .21rem;
+          color: #aaa;
+          margin: .13rem 0 0 0;
+        }
+        a {
+          margin-top: .12rem;
+          font-size: .18rem;
+          color: #bbb;
+        }
+        .hr {
+          width: 1.09rem;
+          height: .02rem;
+          background: #d9d9d9;
+          position: absolute;
+          left: 1.94rem;
+          top: .35rem;
+          &.right {
+            right: 1.94rem;
+            left: auto;
+          }
+        }
+      }
+    }
+</style>

+ 73 - 0
components/mobile/share/store/StoreHeader.vue

@@ -0,0 +1,73 @@
+<template>
+  <div class="store-share-header">
+    <div class="wrap">
+      <div class="img">
+        <img :src="storeInfo.logoUrl" alt="">
+      </div>
+      <div class="title">
+        <h1>{{storeInfo.storeName}}</h1>
+        <p>{{storeInfo.description}}</p>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    computed: {
+      storeInfo () {
+        return this.$store.state.shop.storeInfo.store.data
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .store-share-header {
+    height: 1.9rem;
+    background: #272a32;
+    padding-top: .18rem;
+    .wrap {
+      height: 1.72rem;
+      width: 7.16rem;
+      margin: 0 auto;
+      background: url('/images/mobile/@2x/shareStore/background@2x.png') no-repeat;
+      background-size: cover;
+      padding: .2rem 0 0 .4rem;
+      > div {
+        display: inline-block;
+        vertical-align: middle;
+        &.img {
+          width: 1.24rem;
+          height: 1.24rem;
+          text-align: center;
+          line-height: 1.24rem;
+          border-radius: 2px;
+          background: #fff;
+          img {
+            max-width: 1.24rem;
+            max-height: 1.24rem;
+          }
+        }
+        &.title {
+          margin-left: .44rem;
+          width: 5rem;
+          h1 {
+            font-size: .36rem;
+            color: #662d00;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            width: 4.5rem;
+          }
+          p {
+            font-size: .21rem;
+            color: #9c4500;
+            margin-top: .2rem;
+            line-height: .32rem;
+            overflow: hidden;
+            max-height: .64rem;
+          }
+        }
+      }
+    }
+  }
+</style>

+ 102 - 1
components/store/common/StoreHeader.vue

@@ -25,6 +25,17 @@
                     <img src="/images/all/songguo.png">
 							      <a @click="goWebChat()" class="contact_btn">联系卖家</a>
                   </span>
+                  <div class="share">
+                    <span @click="setShowShare(!showShare, $event)">生成手机版链接</span>
+                    <div v-show="showShare">
+                      <i class="icon-guanbi1 iconfont" @click="setShowShare(false, $event)"></i>
+                      <h1>分享链接</h1>
+                      <p>随时随地使用手机查看店铺现货</p>
+                      <canvas id="qrccode-canvas"></canvas>
+                      <input v-if="showShare" :value="url" readonly>
+                      <span v-if="showShare" id="copyLink"  :data-clipboard-text="url">复制链接</span>
+                    </div>
+                  </div>
                 </div>
               </div>
               <div class="clearfix"></div>
@@ -70,18 +81,40 @@
   </div>
 </template>
 <script>
+import Clipboard from 'clipboard'
 import SearchBox from '~components/main/Search.vue'
+
+let QRCode = require('qrcode')
+
 export default {
   name: 'store-header',
   data () {
     return {
       isOpen: false,
-      dialogVisible: false
+      dialogVisible: false,
+      clipboard: {},
+      showShare: false
     }
   },
   components: {
     SearchBox
   },
+  mounted () {
+    let _this = this
+    _this.url = window.location.href
+    _this.clipboard = new Clipboard('#copyLink')
+    _this.clipboard.on('success', e => {
+      _this.clipboard.destroy()
+      _this.$message.success('已复制到剪切板')
+    })
+    _this.clipboard.on('error', e => {
+      _this.$message.error('浏览器不支持自动复制,请手动复制')
+      _this.clipboard.destroy()
+    })
+    document.addEventListener('click', function () {
+      _this.showShare = false
+    })
+  },
   computed: {
     storeInfo () {
       return this.$store.state.shop.storeInfo.store.data
@@ -94,9 +127,26 @@ export default {
     },
     tab () {
       return this.$store.state.chat.tab.tab.data
+    },
+    url: {
+      get: function () {
+        return window.location.protocol + '//' + window.location.host + '/mobile/share/storeShare/' + this.storeInfo.uuid
+      },
+      set: function () {
+      }
     }
   },
   methods: {
+    loadQRcode: function () {
+      let canvas = document.getElementById('qrccode-canvas')
+      QRCode.toCanvas(canvas, this.url, (error) => {
+        if (error) {
+          console.log(error)
+        } else {
+          console.log('QRcode success')
+        }
+      })
+    },
     closeDropDown () {
       this.isOpen = false
     },
@@ -177,6 +227,11 @@ export default {
             newTab.location.href = 'https://im.ubtob.com/chat/visit?gid=' + response.data.content
           }
         })
+    },
+    setShowShare: function (flag, event) {
+      event.stopPropagation()
+      this.loadQRcode()
+      this.showShare = flag
     }
   }
 }
@@ -475,4 +530,50 @@ export default {
     background: #ef7f03;
     border-radius: 2px;
   }
+  .icon-style .share {
+    display: inline-block;
+    margin-left: 5px;
+    position: relative;
+  }
+  .icon-style .share > span {
+    color: #4290f7;
+    cursor: pointer;
+  }
+  .icon-style .share > div {
+    position: absolute;
+    top: 26px;
+    left: -94px;
+    width: 300px;
+    height: 380px;
+    background: #fff;
+    box-shadow: 1px 1px 4px 0 #ccbebe;
+    z-index: 1;
+    text-align: center;
+  }
+  .icon-style .share > div input {
+    display: inline-block;
+    width: 140px;
+    overflow: hidden;
+    height: 35px;
+    vertical-align: middle;
+  }
+  .icon-style .share > div span {
+    display: inline-block;
+    color: #fff;
+    background: #4290f7;
+    height: 36px;
+    line-height: 36px;
+    width: 70px;
+    font-style: normal;
+    vertical-align: middle;
+    cursor: pointer;
+  }
+  .icon-style .share > div i {
+    position: absolute;
+    right: 10px;
+    top: 5px;
+    cursor: pointer;
+    font-size: 14px;
+    font-weight: bold;
+  }
 </style>

+ 25 - 0
layouts/mobileStore.vue

@@ -0,0 +1,25 @@
+<template>
+  <div id="mobile-store">
+    <nuxt/>
+  </div>
+</template>
+<script>
+  export default {
+    name: 'mobile-store',
+    head () {
+      return {
+        meta: [
+          { name: 'apple-mobile-web-app-capable', content: 'yes' },
+          { name: 'MobileOptimized', content: '320' },
+          { name: 'HandheldFriendly', content: 'true' },
+          { name: 'viewport', content: 'width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no' },
+          { 'http-equiv': 'Cache-Control', content: 'no-siteapp' },
+          { name: 'format-detection', content: 'telephone=no, email=no' }
+        ]
+      }
+    }
+  }
+</script>
+<style lang="scss">
+  @import '~assets/scss/mobileCommon';
+</style>

+ 1 - 0
package.json

@@ -17,6 +17,7 @@
     "http-proxy-middleware": "^0.17.4",
     "jsonp": "^0.2.1",
     "nuxt": "0.10.6",
+    "qrcode": "^1.2.0",
     "vue-awesome-swiper": "^2.5.4",
     "vue2-filters": "^0.1.9"
   },

+ 27 - 0
pages/mobile/share/storeShare/_uuid.vue

@@ -0,0 +1,27 @@
+<template>
+  <div>
+    <store-header></store-header>
+    <commodity-list></commodity-list>
+    <store-footer></store-footer>
+  </div>
+</template>
+<script>
+  import {CommodityList, StoreHeader, StoreFooter} from '~components/mobile/share'
+  export default {
+    layout: 'mobileStore',
+    fetch ({ store, params, redirect }) {
+      if (!params.uuid) {
+        return redirect('/error')
+      }
+      return Promise.all([
+        store.dispatch('shop/findStoreInfoFromUuid', params),
+        store.dispatch('shop/mobilePageCommoditiesOfStore', { storeid: params.uuid, origin: 'store', page: 1, count: 10 })
+      ])
+    },
+    components: {
+      CommodityList,
+      StoreHeader,
+      StoreFooter
+    }
+  }
+</script>

+ 4 - 0
plugins/qart.js

@@ -0,0 +1,4 @@
+import VueQArt from 'vue-qart'
+import Vue from 'vue'
+
+Vue.use(VueQArt)

BIN
static/images/mobile/@2x/shareStore/address.png


BIN
static/images/mobile/@2x/shareStore/background@2x.png


BIN
static/images/mobile/@2x/shareStore/commodity-title@2x.png


BIN
static/images/mobile/@2x/shareStore/empty.png


BIN
static/images/mobile/@2x/shareStore/fax.png


BIN
static/images/mobile/@2x/shareStore/logo.png


BIN
static/images/mobile/@2x/shareStore/phone.png


BIN
static/images/mobile/@2x/shareStore/qq.png


BIN
static/images/mobile/@2x/shareStore/store-info.png


+ 9 - 0
store/shop.js

@@ -80,6 +80,15 @@ export const actions = {
         commit('storeInfo/GET_STORE_COMMODITY_FAILURE', err)
       })
   },
+  mobilePageCommoditiesOfStore ({ commit }, params = {}) {
+    commit('storeInfo/REQUEST_STORE_COMMODITY')
+    return axios.get('/api/commodity/commodities', { params })
+      .then(response => {
+        commit('storeInfo/GET_STORE_COMMODITY_SUCCESS', response.data)
+      }, err => {
+        commit('storeInfo/GET_STORE_COMMODITY_FAILURE', err)
+      })
+  },
   // 获取保存浏览记录
   saveHistory ({ commit }, params = {}) {
     commit('storeInfo/REQUEST_SAVEHISOTRY')