tremble před 6 roky
rodič
revize
54f5a030a1

+ 1 - 1
build/webpack.dev.conf.js

@@ -10,7 +10,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
 const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
 const portfinder = require('portfinder')
 
-const HOST = '192.168.0.133'
+const HOST = '192.168.0.28'
 const PORT = process.env.PORT && Number(process.env.PORT)
 
 const devWebpackConfig = merge(baseWebpackConfig, {

+ 5 - 3
src/App.vue

@@ -6,7 +6,7 @@
       </iheader>
     </div>
     <div class="mask" :class="{active: showMask}" :style="{zIndex: maskZIndex}"></div>
-    <iaside :active="showLogin"/>
+    <iaside :active="showLogin" :cp='asideCp'/>
     <ichat />
     <router-view />
     <ifooter v-if="$route.name!=='about'" />
@@ -31,7 +31,8 @@ export default {
     return {
       maskZIndex: -1,
       showMask: false,
-      showLogin: false
+      showLogin: false,
+      asideCp: 'list'
     }
   },
   watch: {
@@ -67,8 +68,9 @@ export default {
       this.showMask = true
     })
 
-    this.$bus.$on('showAside', () => {
+    this.$bus.$on('showAside', data => {
       this.showLogin = true
+      this.asideCp = data || {type: 'list', sku: [], fromList: true}
     })
 
     this.$bus.$on('hideAside', () => {

binární
src/assets/images/icon/error.png


binární
src/assets/images/icon/success.png


binární
src/assets/images/icon/warn.png


binární
src/assets/images/logo-black.png


+ 149 - 0
src/components/toast/index.vue

@@ -0,0 +1,149 @@
+<template>
+  <div class="toast-layout" v-if="visible">
+    <div class="toast-con" :style="{width:toastType==='comfirm'?'704px':'540px'}">
+      <div class="top">
+        <span>{{typeTxt}}</span>
+        <i @click="toastType==='comfirm'?visible=false:emitCallback()" class="iconfont icon-cuowu"></i>
+        <!-- <img src="@/assets/images/" alt=""> -->
+      </div>
+      <div class="t-line"></div>
+      <div class="detail">
+        <img :src="img" alt="">
+        <span>{{message}}</span>
+      </div>
+      <div class="t-line"></div>
+      <div class="bottom" v-if="toastType==='comfirm'">
+        <span class="btn primary" @click="emitCallback">确认</span>
+        <span @click="visible=false" class="btn cancel">取消</span>
+      </div>
+      <div class="bottom mid-bottom" v-else>
+        <span class="btn primary" @click="emitCallback">确认</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+let types = {
+  warn: '提示',
+  error: '错误',
+  success: '成功'
+}
+export default {
+  data () {
+    return {
+      visible: false,
+      message: '',
+      type: 'warn',
+      toastType: 'show',
+      callback: '',
+      img: require('@/assets/images/icon/warn.png')
+    }
+  },
+  computed: {
+    typeTxt () {
+      return types[this.type]
+    }
+  },
+  created () {
+
+  },
+  watch: {
+
+  },
+  mounted () {
+  },
+  methods: {
+    emitCallback () {
+      this.callback()
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+  .btn{
+    width: 88px;
+    color: #2d2d2d;
+    display: inline-block;
+    font-size: 14px;
+    text-align: center;
+    border-radius: 2px;
+    width: 88px;
+    height: 34px;
+    line-height: 34px;
+    cursor: pointer;
+  }
+  .primary{
+    background: $theme-color;
+  }
+  .cancel{
+    background: #e6e6e6;
+    margin-left: 10px;
+  }
+  .toast-layout {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    margin: 0;
+    background: rgba(0, 0, 0, 0.3);
+    z-index: 88888888;
+    .toast-con{
+      position: absolute;
+      padding: 20px 0;
+      top: 40%;
+      left: 50%;
+      transform: translate(-50%,-50%);
+      background: #fff;
+      width: 704px;
+      border-radius: 6px;
+      .t-line{
+        width: 100%;
+        background: #e4e4e4;
+        height: 1px;
+        margin: 20px 0;
+      }
+      .top{
+        padding:0 36px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        color: #969696;
+        span{
+          font-size: 16px;
+        }
+        .iconfont{
+          cursor: pointer;
+        }
+      }
+      .detail{
+        padding:0 36px;
+        img{
+          width: 30px;
+          display: inline-block;
+          vertical-align: middle;
+        }
+        span{
+          margin-left: 10px;
+          font-size: 16px;
+          color: #2d2d2d;
+          display: inline-block;
+          vertical-align: middle;
+        }
+      }
+      .bottom{
+        padding:0 36px;
+        float: right;
+      }
+      .mid-bottom{
+        float: none;
+        text-align: center;
+      }
+    }
+  }
+</style>

+ 45 - 0
src/components/toast/toast.js

@@ -0,0 +1,45 @@
+import ToastComponent from './index.vue'
+const Toast = {}
+// 注册Toast
+Toast.install = function (Vue) {
+  // 生成一个Vue的子类
+  // 同时这个子类也就是组件
+  const ToastConstructor = Vue.extend(ToastComponent)
+  // 生成一个该子类的实例
+  const instance = new ToastConstructor()
+  // 将这个实例挂载在我创建的p上
+  // 并将此p加入全局挂载点内部
+  instance.$mount(document.createElement('p'))
+  document.body.appendChild(instance.$el)
+  // 通过Vue的原型注册一个方法
+  // 让所有实例共享这个方法
+  let imgs = {
+    success: require('@/assets/images/icon/success.png'),
+    warn: require('@/assets/images/icon/warn.png'),
+    error: require('@/assets/images/icon/error.png')
+  }
+  Vue.prototype.$toast = {
+    showConfirm: (type, msg, callback) => {
+      instance.img = imgs[type] || require('@/assets/images/icon/success.png')
+      instance.message = msg
+      instance.type = type
+      instance.visible = true
+      instance.toastType = 'comfirm'
+      instance.callback = callback || function () {
+      }
+    },
+    show: (type, msg, callback) => {
+      instance.img = imgs[type] || require('@/assets/images/icon/success.png')
+      instance.message = msg
+      instance.type = type
+      instance.visible = true
+      instance.toastType = 'show'
+      instance.callback = callback || function () {
+      }
+    },
+    hide: () => {
+      instance.visible = false
+    }
+  }
+}
+export default Toast

+ 3 - 2
src/main.js

@@ -4,16 +4,17 @@ import App from './App'
 import vuex from 'vuex'
 // import axios from './util/http.js'
 // import router from './router'
-
 Vue.prototype.$cdn = 'https://4dscene.4dage.com/new4dkk/'
 
 Vue.use(vuex)
+Vue.prototype.$bus = new Vue()
+
 let axios = require('./util/http.js').default
 let router = require('./router').default
 
 Vue.prototype.$http = axios
+Vue.prototype.$serverName = 'http://192.168.0.10:8080'
 
-Vue.prototype.$bus = new Vue()
 Vue.config.productionTip = false
 
 function dateFtt (fmt) {

+ 2 - 2
src/page/layout/aside/index.vue

@@ -1,7 +1,7 @@
 <template>
 <div class="login-layout">
   <div class="mask" :style="{maxHeight:active?'100%':'0'}"></div>
-  <component :is="login?'cart':'login'" :active='active'></component>
+  <component :is="login?'cart':'login'" :cp="cp" :active='active'></component>
 </div>
 </template>
 
@@ -16,7 +16,7 @@ export default {
       login: state => state.user.token
     })
   },
-  props: ['active'],
+  props: ['active', 'cp'],
   components: {
     login,
     cart

+ 7 - 5
src/page/layout/aside/temp/cart.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="cart-con" :style="{maxHeight:active?'100%':'0'}">
-    <component :is="cp" :sku="sku" @backList="cp='list'" @toPay="handlePay"></component>
+    <component :is="cp.type" :sku="cp.sku" @backList="cp.type='list'" :fromList='cp.fromList' @toPay="handlePay"></component>
   </div>
 </template>
 
@@ -9,19 +9,21 @@ import list from './ctemp/list'
 import detail from './ctemp/detail'
 
 export default {
-  props: ['active'],
+  props: ['active', 'cp'],
   data () {
     return {
-      cp: 'list',
       sku: ''
     }
   },
   methods: {
     handlePay (data) {
-      this.sku = data
-      this.cp = 'detail'
+      this.cp.fromList = true
+      this.cp.sku = data
+      this.cp.type = 'detail'
     }
   },
+  mounted () {
+  },
   components: {
     list,
     detail

+ 5 - 0
src/page/layout/aside/temp/ctemp/detail.scss

@@ -69,6 +69,11 @@ input {
       cursor: pointer;
       transform: translateY(-50%) rotate(-90deg);
     }
+    .right{
+      font-size: 20px;
+      left: unset;
+      right: 30px;
+    }
   }
   .edit-item {
     width: 100%;

+ 26 - 19
src/page/layout/aside/temp/ctemp/detail.vue

@@ -3,7 +3,8 @@
     <div class="detail-layout">
       <div class="detail-header">
         <div class="c-title">确认订单</div>
-        <i @click="backHandle" class="iconfont icon-shang"></i>
+        <i v-if="fromList" @click="backHandle" class="iconfont icon-shang"></i>
+        <i v-else @click="closeHandle" class="iconfont right icon-cuowu"></i>
       </div>
       <edit
         :name="'收货信息'"
@@ -130,7 +131,6 @@
             </div>
           </div>
             <div @click="saveInvoice(invoice)" class="btn parmary">保存</div>
-
         </div>
       </edit>
       <div class="express-type">
@@ -186,7 +186,7 @@ import citySelect from '@/components/citySelect'
 import { mapState } from 'vuex'
 
 export default {
-  props: ['sku'],
+  props: ['sku', 'fromList'],
   data () {
     return {
       agree: -1,
@@ -205,21 +205,17 @@ export default {
     ...mapState({
       invoice2: state => state.user.invoice2 || {},
       invoice3: state => state.user.invoice3 || {},
-      address: state =>
-        state.user.address || {
-          shipAddress: '',
-          shipAreaPath: '',
-          province: '',
-          city: '',
-          shipMobile: '',
-          shipName: ''
-        }
+      token: state => state.user.token,
+      address: state => state.user.address || {}
     })
   },
   methods: {
     backHandle () {
       this.$emit('backList')
     },
+    closeHandle () {
+      this.$bus.$emit('hideAside')
+    },
     handleOper (type) {
       this[type] = !this[type]
     },
@@ -235,20 +231,27 @@ export default {
       })
       return [count, sum]
     },
-    pay () {
+    async pay () {
       if (!this.agree) { return alert('请同意协议') }
+      let invoice = this.invoice === 'normal' ? this.invoice2 : this.invoice === 'zengzhi' ? this.invoice3 : null
       let params = {
-
+        goods: this.sku,
+        receiver: this.address,
+        invoice: invoice,
+        payType: this.paytype
       }
-      this.$http
+      let res = await this.$http
         .post('user/order/placeOrder', params, {
           headers: {
             token: this.token
           }
         })
-        .then(data => {
-          // let res = data.data
-        })
+      this.$bus.$emit('hideAside')
+      this.$router.push({name: 'pay',
+        params: {
+          orderId: res.data.data.id,
+          orderType: 0
+        }})
     },
     saveInvoice (cInvoice) {
       let params = {}
@@ -285,7 +288,11 @@ export default {
     }
   },
   mounted () {
-    console.log(this.sku)
+    if (this.address && Object.keys(this.address).length > 0) return
+    this.$store.dispatch('getInfo', {
+      url: '/user/getReceiverInfo',
+      name: 'address'
+    })
   }
 }
 </script>

+ 2 - 1
src/page/layout/aside/temp/ctemp/list.vue

@@ -87,7 +87,8 @@ export default {
     add (item) {
       let params = {
         goodsId: item.goodsId,
-        goodsCount: 1
+        goodsCount: 1,
+        skuSn: item.skuSn
       }
       this.$store.dispatch('addCart', params)
     },

+ 3 - 3
src/page/layout/aside/temp/ltemp/forget.vue

@@ -33,7 +33,7 @@ export default {
     },
     submit () {
       if (!this.password) {
-        return alert('密码格式不正确')
+        return this.$toast.show('warn', '密码格式不正确')
       }
       let params = {
         password: this.password,
@@ -51,9 +51,9 @@ export default {
       }, res => {
         console.log(res)
         if (res.data.code === 0) {
-          alert('修改密码成功')
+          this.$toast.show('warn', '修改密码成功')
         } else {
-          alert(res.data.msg)
+          this.$toast.show('warn', res.data.msg)
         }
       })
     }

+ 10 - 3
src/page/layout/aside/temp/ltemp/login.vue

@@ -20,7 +20,14 @@
   </div>
 </template>
 <script>
+import {mapState} from 'vuex'
+
 export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token
+    })
+  },
   data () {
     let remember = localStorage.getItem('remember') || ''
     let username = localStorage.getItem('username')
@@ -36,7 +43,7 @@ export default {
 
   },
   methods: {
-    login () {
+    async login () {
       localStorage.setItem('remember', this.rememberMe)
       if (this.rememberMe) {
         localStorage.setItem('username', this.phone)
@@ -51,8 +58,8 @@ export default {
         randomcode: '1234',
         rememberMe: Boolean(this.rememberMe)
       }
-      this.$store.dispatch('login', params)
-      this.$bus.$emit('hideAside')
+      await this.$store.dispatch('login', params)
+      if (this.token) this.$bus.$emit('hideAside')
     }
   }
 }

+ 4 - 2
src/page/layout/aside/temp/ltemp/register.vue

@@ -41,8 +41,10 @@ export default {
         data: params,
         url: '/sso/user/register'
       }, res => {
-        if (res.code !== 200) {
-          alert(res.msg)
+        console.log('asdasdas', res)
+
+        if (res.data.code !== 0) {
+          this.$toast.show('warn', res.data.msg)
         }
       })
     }

+ 5 - 2
src/page/manage/index.vue

@@ -8,7 +8,7 @@
           <p>尚未开通任何会员</p>
           <p>{{info.userName}}</p>
         </div>
-        <div class="open-btn">立即开通</div>
+        <div class="open-btn" @click="open">立即开通</div>
       </div>
       <div class="capacity">
         <div class="c-line">
@@ -103,10 +103,13 @@ export default {
     }
   },
   methods: {
+    open () {
+      this.$toast.showConfirm('success', '开通成功')
+    },
     tabHandle (sub) {
       switch (sub.cp) {
         case 'ilogout':
-          this.$store.commit('logout')
+          this.$store.dispatch('logout')
           this.$router.push({name: 'home'})
           break
 

+ 1 - 1
src/page/manage/temp/change.vue

@@ -57,7 +57,7 @@ export default {
       }, res => {
         let data = res.data
         if (data.code === 0) {
-          alert('请重新登录~')
+          this.$toast.show('success', '请重新登录')
           this.$store.commit('logout')
         }
       })

+ 0 - 1
src/page/manage/temp/infomation.vue

@@ -271,7 +271,6 @@ export default {
   },
   watch: {},
   mounted () {
-    console.log(this.invoice2)
     this.$store.dispatch('getInfo', {
       url: '/user/getReceiverInfo',
       name: 'address'

+ 199 - 50
src/page/manage/temp/order.vue

@@ -1,86 +1,170 @@
 <template>
   <div class="order-layout">
-    <div class="order-item">
-      <div class="o-top">订单号:2018066262629894984984984</div>
+    <div class="order-item" v-for="(item,i) in myorder.list" :key='i'>
+      <div class="o-top">订单号:{{item.orderSn}}</div>
       <div class="o-title">
         <span>商品</span>
         <span>数量</span>
         <span>小计(CNY)</span>
       </div>
-      <div class="o-detail">
+      <div class="o-detail" v-for="(sub,index) in item.orderItems" :key="index">
         <div class="od-name">
-          <img class="thumbnail" src="@/assets/images/banner_pro.png" alt>
+          <img class="thumbnail" :src="sub.pic" alt>
           <div>
-            <p>四维看看 Pro</p>
-            <p>标准套餐</p>
+            <p>{{sub.goodsName}}</p>
+            <p>{{sub.description}}</p>
           </div>
         </div>
-        <div class="count">2</div>
-        <div class="sum">6,798</div>
-      </div>
-      <div class="o-detail">
-        <div class="od-name">
-          <img class="thumbnail" src="@/assets/images/banner_pro.png" alt>
-          <div>
-            <p>四维看看 Pro</p>
-            <p>标准套餐</p>
-          </div>
-        </div>
-        <div class="count">2</div>
-        <div class="sum">6,798</div>
+        <div class="count">{{sub.goodsCount}}</div>
+        <div class="sum">{{sub.goodsPrice*sub.goodsCount}}</div>
       </div>
       <div class="sum-price">
         <div></div>
-        <div>总价:¥6,798</div>
+        <div>总价:{{item.goodsAmount}}</div>
       </div>
       <div class="to-pay">
-        <span class="cancel">取消订单</span>
-        <span class="pay btns">立即付款</span>
+        <template v-if="getStatus(item) === 'unpaid'">
+          <span class="cancel" @click="cancal(item)">取消订单</span>
+          <span class="pay btns" @click="toPay(item)">立即付款</span>
+        </template>
+        <template v-else-if="getStatus(item) === 'shipped'">
+          <span class="expreeNum">物流单号:77110342778758</span>
+        </template>
+        <template v-else-if="getStatus(item) === 'unshipped'">
+          <span class="expreeNum">等待商家发货</span>
+        </template>
+        <template v-else-if="getStatus(item) === 'finish'">
+          <span class="expreeNum">已完成</span>
+        </template>
+         <template v-else>
+          <span class="expreeNum">已取消</span>
+        </template>
       </div>
     </div>
-     <div class="order-item">
-      <div class="o-top">订单号:2018066262629894984984984</div>
-      <div class="o-title">
-        <span>商品</span>
-        <span>数量</span>
-        <span>小计(CNY)</span>
-      </div>
-      <div class="o-detail">
-        <div class="od-name">
-          <img class="thumbnail" src="@/assets/images/banner_pro.png" alt>
-          <div>
-            <p>四维看看 Pro</p>
-            <p>标准套餐</p>
-          </div>
-        </div>
-        <div class="count">2</div>
-        <div class="sum">6,798</div>
-      </div>
-      <div class="sum-price">
-        <div></div>
-        <div>总价:¥6,798</div>
-      </div>
-      <div class="to-pay">
-        <span class="cancel">取消订单</span>
-        <span class="pay btns">立即付款</span>
-      </div>
+    <div class="paging">
+      <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
     </div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+import Paging from '@/components/Paging'
+
 export default {
+  components: {Paging},
+  data () {
+    return {
+      pageSize: 2,
+      currentPage: 1,
+      total: 0
+    }
+  },
+  watch: {
+    currentPage () {
+      this.getList()
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      myorder: state => {
+        if (Object.prototype.toString.call(state.user.myorder) === '[object Object]') {
+          return state.user.myorder
+        }
+        return (state.user.myorder ? JSON.parse(state.user.myorder) : {})
+      }
+    })
+  },
   mounted () {
     this.getList()
   },
   methods: {
+    pageChange (data) {
+      this.currentPage = data
+    },
     getList () {
       let params = {
         type: '',
-        pageNum: 1,
-        pageSize: 10
+        pageNum: this.currentPage,
+        pageSize: this.pageSize
       }
       this.$store.dispatch('getUserOrder', params)
+      this.pageSize = this.myorder.pageSize
+      this.total = this.myorder.total || 0
+    },
+    getStatus (item) {
+      console.log(item)
+      let temp = ''
+      let sPay = function () {
+        switch (item.shippingStatus) {
+          case 'unshipped':
+            temp = 'unshipped'
+            break
+          case 'shipped':
+            temp = 'shipped'
+            break
+          default:
+            break
+        }
+      }
+      let pPay = function () {
+        switch (item.paymentStatus) {
+          case 'unpaid':
+            temp = 'unpaid'
+            break
+          case 'paid':
+            sPay()
+            break
+          default:
+            break
+        }
+      }
+
+      switch (item.orderStatus) {
+        case 'unprocessed':
+          pPay()
+          break
+        case 'completed':
+          temp = 'finish'
+          break
+        case 'processed':
+          sPay()
+          break
+
+        default:
+          break
+      }
+      return temp
+    },
+    toPay (item) {
+      this.$router.push({name: 'pay',
+        params: {
+          orderId: item.id,
+          orderType: 0
+        }})
+    },
+    async cancal (item) {
+      this.$toast.showConfirm('warn', '确定要删除当前订单吗?', async () => {
+        let params = {
+          orderId: item.id
+        }
+        let res = await this.$http({
+          method: 'post',
+          data: params,
+          headers: {
+            token: this.token
+          },
+          url: '/user/order/cancel'
+        })
+        let data = res.data
+        if (data.code === 0) {
+          return this.$toast.show('warn', '删除成功', () => {
+            this.getList()
+          })
+        }
+        return this.$toast.show('error', '删除失败')
+      })
     }
   }
 }
@@ -194,6 +278,71 @@ $border-color: #e7e7e7;
         text-align: center;
         cursor: pointer;
       }
+      .expreeNum{
+        margin-right: 60px;
+        color: #2d2d2d;
+      }
+    }
+  }
+  .paging {
+    // border-left: #e5e5e5 1px solid;
+    height: 100%;
+    margin-bottom: 40px;
+    & /deep/ .layout {
+      text-align: left;
+      margin-top: 40px;
+      margin-left: 15px;
+    }
+    & /deep/ .layout a:not(:last-child) {
+      margin: 10px 8px;
+      font-size: 16px;
+      display: inline-block;
+      font-weight: 500;
+      cursor: pointer;
+      user-select: none;
+      color: #999;
+      position: relative;
+      transition: color 0.3s;
+    }
+    & /deep/ .layout a:last-child {
+      position: relative;
+      top: -5px;
+      display: -ms-inline-flexbox;
+      display: inline-flex;
+      -ms-flex-align: center;
+      align-items: center;
+      height: 22px;
+      padding: 0 9.6px;
+      padding: 0 0.6rem;
+    }
+    & /deep/ .layout a:last-child::before,
+    & /deep/ .layout a:last-child::after {
+      content: "";
+      display: inline-block;
+      will-change: transform;
+      transition: transform 0.3s;
+    }
+
+    & /deep/ .layout a:not(:last-child).active::after,
+    & /deep/ .layout a:not(:last-child).active,
+    & /deep/ .layout a:not(:last-child):hover,
+    & /deep/ .layout a:not(:last-child):hover::after {
+      color: #111111;
+      transform: scaleX(1);
+    }
+
+    & /deep/ .layout a:not(:last-child)::after {
+      content: "";
+      height: 3px;
+      width: 140%;
+      background-color: #111;
+      display: block;
+      margin-left: -20%;
+      margin-top: 3px;
+      transform-origin: 50% 50%;
+      transform: scaleX(0);
+      will-change: transform;
+      transition: transform 0.3s;
     }
   }
 }

+ 304 - 0
src/page/pay/index.vue

@@ -0,0 +1,304 @@
+<template>
+  <div class="pay-layout">
+    <div class="pay-header">
+      <div class="h-left">
+        <img src="@/assets/images/logo-black.png" alt>
+        <span class="h-line"></span>
+        <span>支付中心</span>
+      </div>
+      <div class="h-right">当前账号:{{info.userName}}</div>
+    </div>
+    <div class="pay-con">
+      <!-- <div class="top">
+        <div class="attr">开通选择:</div>
+        <div class="val">
+          <div class="tag" :class="{'tag-active':privilege==='year'}" @click="privilege='year'">
+            <span class="year">1年</span>
+            <span class="price">
+              <i style="font-size:12px">¥</i>1999
+              <span class="per">166元/月</span>
+            </span>
+            <img v-if="privilege==='year'" src="@/assets/images/tag-icon.png" alt>
+          </div>
+          <div class="tag" :class="{'tag-active':privilege==='mouth'}" @click="privilege='mouth'">
+            <span class="year">1个月</span>
+            <span class="price">
+              <i style="font-size:12px">¥</i>199
+            </span>
+            <img v-if="privilege==='mouth'" src="@/assets/images/tag-icon.png" alt>
+          </div>
+        </div>
+      </div> -->
+      <div class="mid">
+        <div class="attr">支付方式:</div>
+        <div class="body">
+          <div class="pay-tag" :class="{'tag-active':paytype==='alipay'}" @click="paytype='alipay'">
+            <img src="@/assets/images/ali-pay.png" class="t-icon" alt>
+            <span>支付宝</span>
+            <img src="@/assets/images/tag-icon.png" class="t-click" alt>
+          </div>
+          <div class="pay-tag" :class="{'tag-active':paytype==='wechatPay'}" @click="paytype='wechatPay'">
+            <img src="@/assets/images/wechat-pay.png" class="t-icon" alt>
+            <span>微信支付</span>
+            <img src="@/assets/images/tag-icon.png" class="t-click" alt>
+          </div>
+          <div class="pay-tag" :class="{'tag-active':paytype==='paypal'}" @click="paytype='paypal'">
+            <img src="@/assets/images/paypal.png" class="t-icon" alt>
+            <span>paypal</span>
+            <img src="@/assets/images/tag-icon.png" class="t-click" alt>
+          </div>
+        </div>
+      </div>
+      <div class="bottom">
+        <div class="attr">应付金额:</div>
+        <div class="price-detail">
+          <dir class="price">¥{{response.price}}</dir>
+          <div class="sao">扫码支付</div>
+          <img :src="`${$serverName}${response.src}`" alt="">
+          <div class="dec">使用<span style="color:#ff0000">{{payZH}}</span>app扫码完成支付</div>
+        </div>
+      </div>
+    </div>
+    <div class="pay-bottom">
+       ©2019 4dkankan移动开放平台
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+let payTypes = {
+  wechatPay: '微信',
+  alipay: '支付宝',
+  paypal: 'paypal'
+}
+export default {
+  data () {
+    return {
+      paytype: 'wechatPay',
+      privilege: 'year',
+      response: ''
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      info: state => state.user.info
+    }),
+    payZH () {
+      return payTypes[this.paytype]
+    }
+  },
+  watch: {
+    paytype (newVal, oldVal) {
+      this.getCode()
+    }
+  },
+  mounted () {
+    this.getCode()
+  },
+  methods: {
+    async getCode () {
+      let {orderId, orderType} = this.$route.params
+      if (!orderId || (!orderType && orderType !== 0)) {
+        return alert('获取订单信息失败')
+      }
+      let params = {
+        orderId: orderId,
+        orderType: orderType
+      }
+      let res = await this.$http
+        .post(`order/pay/${this.paytype}`, params, {
+          headers: {
+            token: this.token
+          }
+        })
+      this.response = res.data.data
+      console.log(this.response)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+
+.pay-layout {
+  width: 1030px;
+  margin: 25px auto;
+  .pay-header {
+    width: 100%;
+    margin-bottom: 50px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .h-left {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .h-line {
+        width: 1px;
+        height: 20px;
+        background: #000;
+        margin: 0 10px;
+        display: inline-block;
+      }
+      span {
+        font-size: 20px;
+        color: #2d2d2d;
+      }
+    }
+    .h-right {
+      font-size: 14px;
+      color: #2d2d2d;
+    }
+  }
+  .pay-con {
+    background: #f4f4f4;
+    padding: 40px;
+    .top,
+    .mid,
+    .bottom {
+      display: flex;
+      margin-bottom: 50px;
+      .attr {
+        font-size: 14px;
+        color: #2d2d2d;
+      }
+
+      .val {
+        display: flex;
+        align-items: center;
+        margin-left: 20px;
+        .tag {
+          height: 100%;
+          font-size: 0;
+          margin-right: 50px;
+          display: flex;
+          align-items: center;
+          border: 1px solid #f4f4f4;
+          position: relative;
+          .year {
+            width: 52px;
+            height: 48px;
+            line-height: 48px;
+            text-align: center;
+            display: inline-block;
+            background: #ededed;
+            color: #777777;
+            font-size: 14px;
+            flex-shrink: 0;
+          }
+          .price {
+            background: #fff;
+            height: 48px;
+            width: 160px;
+            line-height: 48px;
+            display: inline-block;
+            font-size: 18px;
+            color: #ff0000;
+            text-align: center;
+            .per {
+              font-size: 12px;
+              margin-left: 20px;
+              color: #777777;
+            }
+          }
+          img {
+            position: absolute;
+            bottom: 0;
+            right: 0;
+            width: 14px;
+          }
+        }
+        .tag-active {
+          border: 1px solid $theme-color;
+          box-sizing: border-box;
+        }
+      }
+      .body {
+        margin-left: 20px;
+        .pay-tag {
+          cursor: pointer;
+          border: 1px solid #e7e7e7;
+          width: 200px;
+          line-height: 36px;
+          height: 36px;
+          margin-bottom: 20px;
+          position: relative;
+          span {
+            margin-left: 36px;
+            display: inline-block;
+            text-align: center;
+            padding-left: 60px;
+          }
+          img {
+            position: absolute;
+          }
+          .t-icon {
+            width: 36px;
+            height: 36px;
+            padding: 6px;
+            left: 0;
+            border-right: 1px solid #e7e7e7;
+          }
+          .t-click {
+            right: 0;
+            bottom: 0;
+            display: none;
+          }
+        }
+        .tag-active {
+          border: 1px solid $theme-color;
+          span {
+            color: #000;
+          }
+          .t-icon {
+            border-right: 1px solid $theme-color;
+          }
+          .t-click {
+            display: inline-block;
+          }
+        }
+      }
+      .price-detail{
+        margin-left: 6px;
+        text-align: center;
+        position: relative;
+        width: 160px;
+        top: -15px;
+        .price{
+          font-size: 30px;
+          color: #ff0000;
+          margin: 0 0 0 8px;
+          text-align: left;
+          padding: 0;
+          margin-bottom: 40px;
+        }
+        .sao{
+          font-size: 14px;
+          color: #2d2d2d;
+          margin-bottom: 5px;
+        }
+        .dec{
+          color: #2d2d2d;
+          font-size: 12px;
+          margin-top: 10px;
+        }
+        img{
+          width: 130px;
+          height: 130px;
+        }
+      }
+    }
+    .bottom {
+      margin-bottom: 0;
+    }
+  }
+  .pay-bottom{
+    color: #969696;
+    font-size: 12px;
+    text-align: center;
+    margin-top: 20px;
+  }
+}
+</style>

+ 16 - 5
src/page/purchase/index.vue

@@ -46,7 +46,7 @@
                 <span>加入购物车</span>
               </vcenter>
             </div>
-            <div class="button">
+            <div class="button"  @click="pay">
               <vcenter>
                 <!-- <img src="@/assets/images/product_icon_arrow.png" alt> -->
                 <span>{{langPurchase.buy}}</span>
@@ -149,11 +149,23 @@ export default {
     addcart () {
       let params = {
         goodsId: 4,
-        goodsCount: this.count
+        goodsCount: this.count,
+        skuSn: 'U15609161635760015'
       }
       this.$store.dispatch('addCart', params)
-      // cart.push(item)
-      // console.log(this.cart)
+    },
+    pay () {
+      let params = {
+        type: 'detail',
+        sku: [{
+          goodsId: 4,
+          goodsCount: this.count,
+          price: 9800,
+          skuSn: 'U15609161635760015'
+        }],
+        fromList: false
+      }
+      this.$bus.$emit('showAside', params)
     },
     scrollTo (href) {
       this.interval = null
@@ -172,7 +184,6 @@ export default {
   beforeDestroy () {
     clearInterval(this.interval)
   }
-
 }
 </script>
 

+ 5 - 0
src/router/index.js

@@ -17,6 +17,11 @@ let router = new Router({
       component: () => import('@/page/videos')
     },
     {
+      path: '/pay/:orderId/:orderType',
+      name: 'pay',
+      component: () => import('@/page/pay')
+    },
+    {
       path: '/product',
       name: 'product',
       component: () => import('@/page/product')

+ 23 - 1
src/store/user.js

@@ -1,5 +1,11 @@
 import http from '@/util/http'
 import { reg } from '@/util'
+import Vue from 'Vue'
+import Toast from '@/components/toast/toast'
+
+Vue.use(Toast)
+
+let vue = new Vue()
 
 let token = (localStorage && localStorage.getItem('token')) || ''
 let cart = (localStorage && localStorage.getItem('cart')) || []
@@ -106,7 +112,8 @@ export default {
 
       let data = res.data
       if (data.code !== 0) {
-        return alert(data.msg)
+        console.log(vue.$toast)
+        return vue.$toast.show('warn', data.msg)
       }
       let token = data.data.token
       context.commit('saveToken', token)
@@ -115,6 +122,21 @@ export default {
         context.dispatch('getCart')
       }
     },
+    async logout (context, params) {
+      let res = await http({
+        method: 'post',
+        headers: {
+          token: context.state.token
+        },
+        url: '/sso/user/logout'
+      })
+
+      let data = res.data
+      if (data.code !== 0) {
+        return alert(data.msg)
+      }
+      context.commit('logout')
+    },
     async reduceCart (context, params) {
       let res = await http({
         method: 'post',

+ 11 - 11
src/util/http.js

@@ -1,13 +1,14 @@
 import axios from 'axios'
 import store from '@/store'
 import router from '../router'
+import Vue from 'vue'
 
+let vue = new Vue()
 // import qs from 'qs'
+const exceptUrl = '/sso/user/logout'
 
 axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://192.168.0.10:8080/api' : 'http://192.168.0.10:8080/api'
 // axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://www.4dkankan.com' : 'http://www.4dkankan.com'
-
-// axios.defaults.headers['X-Requested-with'] = 'XMLHttpRequest'
 // 拦截请求,做登陆,或head处理
 axios.interceptors.request.use(function (config) {
   if (config.method === 'post') {
@@ -32,17 +33,16 @@ axios.interceptors.request.use(function (config) {
 axios.interceptors.response.use(
   response => {
     let code = Number(response.data.code)
-    console.log(code)
+    let url = response.config.baseURL + exceptUrl
+    if (response.config.url === url) {
+      return response
+    }
     switch (code) {
-      case 3001:
-        alert('请重新登录')
-        store.commit('logout')
-        router.push({name: 'home'})
-        break
       case 3004:
-        alert('请重新登录')
-        store.commit('logout')
-        router.push({name: 'home'})
+        store.state.user.token && vue.$toast.show('warn', '请重新登录', function () {
+          store.dispatch('logout')
+          router.push({name: 'home'})
+        })
         break
       default:
         break