tremble 6 years ago
parent
commit
533d60e9b7
100 changed files with 7940 additions and 313 deletions
  1. 18 1
      src/App.vue
  2. BIN
      src/assets/images/canvas-left.png
  3. BIN
      src/assets/images/canvas-right.png
  4. BIN
      src/assets/images/ceju-n.gif
  5. BIN
      src/assets/images/ceju.gif
  6. BIN
      src/assets/images/head-default.png
  7. BIN
      src/assets/images/icon/edit.png
  8. BIN
      src/assets/images/icon/error.png
  9. BIN
      src/assets/images/icon/ic_cart@2x.png
  10. BIN
      src/assets/images/icon/success.png
  11. BIN
      src/assets/images/icon/warn.png
  12. BIN
      src/assets/images/item_icon_1.png
  13. BIN
      src/assets/images/item_icon_2.png
  14. BIN
      src/assets/images/item_icon_3.png
  15. BIN
      src/assets/images/item_icon_4.png
  16. BIN
      src/assets/images/item_icon_5.png
  17. BIN
      src/assets/images/item_icon_6.png
  18. BIN
      src/assets/images/item_icon_7.png
  19. BIN
      src/assets/images/item_icon_8.png
  20. BIN
      src/assets/images/lite-logo-m.png
  21. BIN
      src/assets/images/nav-bg.png
  22. BIN
      src/assets/images/nothing.png
  23. BIN
      src/assets/images/payfail.png
  24. BIN
      src/assets/images/paynow.png
  25. BIN
      src/assets/images/paysuccess.png
  26. BIN
      src/assets/images/phone_1.jpg
  27. BIN
      src/assets/images/phone_10.jpg
  28. BIN
      src/assets/images/phone_11.jpg
  29. BIN
      src/assets/images/phone_12.jpg
  30. BIN
      src/assets/images/phone_13.jpg
  31. BIN
      src/assets/images/phone_14.jpg
  32. BIN
      src/assets/images/phone_15.jpg
  33. BIN
      src/assets/images/phone_16.jpg
  34. BIN
      src/assets/images/phone_2.jpg
  35. BIN
      src/assets/images/phone_3.jpg
  36. BIN
      src/assets/images/phone_4.jpg
  37. BIN
      src/assets/images/phone_5.jpg
  38. BIN
      src/assets/images/phone_6.jpg
  39. BIN
      src/assets/images/phone_7.jpg
  40. BIN
      src/assets/images/phone_8.jpg
  41. BIN
      src/assets/images/phone_9.jpg
  42. BIN
      src/assets/images/phone_icon_1.png
  43. BIN
      src/assets/images/phone_icon_10.png
  44. BIN
      src/assets/images/phone_icon_2.png
  45. BIN
      src/assets/images/phone_icon_3.png
  46. BIN
      src/assets/images/phone_icon_4.png
  47. BIN
      src/assets/images/phone_icon_5.png
  48. BIN
      src/assets/images/phone_icon_6.png
  49. BIN
      src/assets/images/phone_icon_7.png
  50. BIN
      src/assets/images/phone_icon_8.png
  51. BIN
      src/assets/images/phone_icon_9.png
  52. BIN
      src/assets/images/weixin-pay.png
  53. 22 0
      src/assets/style/public.scss
  54. BIN
      src/assets/video/4dkkPRO_zh.mp4
  55. BIN
      src/assets/video/4k.mp4
  56. BIN
      src/assets/video/banner1.mp4
  57. BIN
      src/assets/video/item2.mp4
  58. BIN
      src/assets/video/kjdw.mp4
  59. 1 3
      src/components/Paging/index.vue
  60. 226 0
      src/components/cinvoices/index.vue
  61. 194 0
      src/components/cinvoices/style.scss
  62. 4793 0
      src/components/citySelect/city.js
  63. 209 0
      src/components/citySelect/index.vue
  64. 94 0
      src/components/citySelect/style.scss
  65. 181 0
      src/components/invoices/index.vue
  66. 164 0
      src/components/invoices/style.scss
  67. 2 2
      src/components/spinner/index.vue
  68. 203 0
      src/components/toast/index.vue
  69. 48 0
      src/components/toast/toast.js
  70. 13 5
      src/main.js
  71. 2 2
      src/pages/about/index.vue
  72. 75 11
      src/pages/account/forget/index.vue
  73. 35 7
      src/pages/account/login/index.vue
  74. 2 2
      src/pages/account/login/style.scss
  75. 116 24
      src/pages/account/manage/cart/index.vue
  76. 86 8
      src/pages/account/manage/change/index.vue
  77. 12 0
      src/pages/account/manage/change/style.scss
  78. 106 15
      src/pages/account/manage/confirm/index.vue
  79. 4 0
      src/pages/account/manage/confirm/style.scss
  80. 18 3
      src/pages/account/manage/index.vue
  81. 162 73
      src/pages/account/manage/information/index.vue
  82. 65 3
      src/pages/account/manage/information/style.scss
  83. 111 0
      src/pages/account/manage/myscene/index.vue
  84. 121 0
      src/pages/account/manage/myscene/style.scss
  85. 170 19
      src/pages/account/manage/order/index.vue
  86. 60 0
      src/pages/account/manage/order/style.scss
  87. 97 0
      src/pages/account/manage/payselect/index.vue
  88. 58 0
      src/pages/account/manage/payselect/style.scss
  89. 50 13
      src/pages/account/manage/paytype/index.vue
  90. 120 21
      src/pages/account/manage/submit/index.vue
  91. 10 1
      src/pages/account/manage/submit/style.scss
  92. 73 15
      src/pages/account/register/index.vue
  93. 8 8
      src/pages/binocular/index.vue
  94. 49 46
      src/pages/cases/index.vue
  95. 2 2
      src/pages/cases/style.scss
  96. 129 0
      src/pages/check/index.vue
  97. 11 11
      src/pages/eight/index.vue
  98. 13 14
      src/pages/home/index.vue
  99. 7 4
      src/pages/home/style.scss
  100. 0 0
      src/pages/layout/footer.vue

+ 18 - 1
src/App.vue

@@ -3,7 +3,6 @@
     <iheader  class="header" />
     <router-view class="layout"/>
     <ifooter  class="header" />
-
   </div>
 </template>
 
@@ -13,14 +12,32 @@ import '@/assets/style/public.scss'
 import '@/assets/font/iconfont.css'
 import header from '@/pages/layout/header'
 import footer from '@/pages/layout/footer'
+import browser from '@/util/browser'
 
 export default {
   name: 'App',
   data () {
     return {
+      isMobile: browser.mobile
 
     }
   },
+  watch: {
+    '$store.state.user.cart': function (newVal, oldVal) {
+      if (newVal && (newVal !== oldVal)) {
+        let count = 0
+        newVal.forEach(item => {
+          count += item.goodsCount
+        })
+        this.$bus.$emit('updateCart', count)
+      }
+    }
+  },
+  mounted () {
+    if (!this.isMobile) {
+      location.href = '/'
+    }
+  },
   components: {
     iheader: header,
     ifooter: footer

BIN
src/assets/images/canvas-left.png


BIN
src/assets/images/canvas-right.png


BIN
src/assets/images/ceju-n.gif


BIN
src/assets/images/ceju.gif


BIN
src/assets/images/head-default.png


BIN
src/assets/images/icon/edit.png


BIN
src/assets/images/icon/error.png


BIN
src/assets/images/icon/ic_cart@2x.png


BIN
src/assets/images/icon/success.png


BIN
src/assets/images/icon/warn.png


BIN
src/assets/images/item_icon_1.png


BIN
src/assets/images/item_icon_2.png


BIN
src/assets/images/item_icon_3.png


BIN
src/assets/images/item_icon_4.png


BIN
src/assets/images/item_icon_5.png


BIN
src/assets/images/item_icon_6.png


BIN
src/assets/images/item_icon_7.png


BIN
src/assets/images/item_icon_8.png


BIN
src/assets/images/lite-logo-m.png


BIN
src/assets/images/nav-bg.png


BIN
src/assets/images/nothing.png


BIN
src/assets/images/payfail.png


BIN
src/assets/images/paynow.png


BIN
src/assets/images/paysuccess.png


BIN
src/assets/images/phone_1.jpg


BIN
src/assets/images/phone_10.jpg


BIN
src/assets/images/phone_11.jpg


BIN
src/assets/images/phone_12.jpg


BIN
src/assets/images/phone_13.jpg


BIN
src/assets/images/phone_14.jpg


BIN
src/assets/images/phone_15.jpg


BIN
src/assets/images/phone_16.jpg


BIN
src/assets/images/phone_2.jpg


BIN
src/assets/images/phone_3.jpg


BIN
src/assets/images/phone_4.jpg


BIN
src/assets/images/phone_5.jpg


BIN
src/assets/images/phone_6.jpg


BIN
src/assets/images/phone_7.jpg


BIN
src/assets/images/phone_8.jpg


BIN
src/assets/images/phone_9.jpg


BIN
src/assets/images/phone_icon_1.png


BIN
src/assets/images/phone_icon_10.png


BIN
src/assets/images/phone_icon_2.png


BIN
src/assets/images/phone_icon_3.png


BIN
src/assets/images/phone_icon_4.png


BIN
src/assets/images/phone_icon_5.png


BIN
src/assets/images/phone_icon_6.png


BIN
src/assets/images/phone_icon_7.png


BIN
src/assets/images/phone_icon_8.png


BIN
src/assets/images/phone_icon_9.png


BIN
src/assets/images/weixin-pay.png


+ 22 - 0
src/assets/style/public.scss

@@ -123,4 +123,26 @@ body{
   height: 40px;
   line-height: 40px;
   padding: 0 16px;
+}
+
+@keyframes rotateLoader {
+  0% {
+      transform: rotate(0deg)
+  }
+
+  to {
+      transform: rotate(1turn)
+  }
+}
+
+@media screen and (max-width: 330px) {
+  .b-text1 {
+    font-size: 10px;
+  }
+  .b-text2 {
+    font-size: 22px;
+  }
+  .b-text3 {
+    font-size: 12px;
+  }
 }

BIN
src/assets/video/4dkkPRO_zh.mp4


BIN
src/assets/video/4k.mp4


BIN
src/assets/video/banner1.mp4


BIN
src/assets/video/item2.mp4


BIN
src/assets/video/kjdw.mp4


+ 1 - 3
src/components/Paging/index.vue

@@ -8,9 +8,7 @@
       @click="clickHandle(page)"
       :class="{active: index === page}"
       >{{page}}
-    </a>
-    <a class="more" @click="clickHandle(pages[pages.length-1] + 2)" v-if="pages[pages.length-1]+2<=maxPage" >...</a>
-    <a @click="clickHandle(maxPage)" :class="{active: index === maxPage}" >{{maxPage}}</a>
+    </a><a class="more" @click="clickHandle(pages[pages.length-1] + 2)" v-if="pages[pages.length-1]+2<=maxPage" >...</a><a @click="clickHandle(maxPage)" :class="{active: index === maxPage}" >{{maxPage}}</a>
     <i class="iconfont icon-youjiantou" @click="clickHandle(index + 1)" ></i>
   </div>
 </template>

+ 226 - 0
src/components/cinvoices/index.vue

@@ -0,0 +1,226 @@
+<template>
+  <div class="invoices-layout">
+    <div class="address-input-con" v-if="selectedId===3">
+      <template v-if="isShowInvoice3">
+        <template v-if="tempInvoice3.title">
+          <div class="bc-item">
+            <div class="bc-contact">
+              <span>{{tempInvoice3.title}}</span>
+            </div>
+            <div>{{tempInvoice3.code}}</div>
+            <div>{{tempInvoice3.organizedAddress}}</div>
+            <div>{{tempInvoice3.registerPhone}}</div>
+            <div>{{tempInvoice3.bankName}}</div>
+            <div>{{tempInvoice3.bankAccount}}</div>
+            <div class="bc-edit" @click="isShowInvoice3=false">编辑</div>
+          </div>
+        </template>
+        <template v-else>
+          <div class="bc-item">
+            <div class="bc-contact">
+              <span>暂无发票信息</span>
+            </div>
+            <div class="bc-edit" @click="isShowInvoice3=false">编辑</div>
+          </div>
+        </template>
+      </template>
+      <template v-else>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">抬头名称</div>
+            <div class="ant-input">
+              <input @blur="blurHandle"
+                v-model="tempInvoice3.title"
+                class="ant-input"
+                type="text"
+                placeholder="请输入发票抬头"
+              />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">税号</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice3.code" type="text" placeholder="请输入税务登记号" />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">地址</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice3.organizedAddress" type="text" placeholder="公司地址" />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">电话号码</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice3.registerPhone" type="text" placeholder="公司电话号码" />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">开户银行</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice3.bankName" type="text" placeholder="开户银行" />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">银行账户</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice3.bankAccount" type="text" placeholder="银行账户" />
+            </div>
+          </div>
+        </div>
+        <button @click="saveInvoice" type="submit" class="ant-btn ant-btn-primary">
+          <span>保 存</span>
+        </button>
+        <button type="submit" class="ant-btn ant-btn-primary cancel" @click="isShowInvoice3=true">
+          <span>取 消</span>
+        </button>
+      </template>
+    </div>
+    <div class="address-input-con" v-else>
+      <template v-if="isShowInvoice2">
+        <template v-if="tempInvoice2.title">
+          <div class="bc-item">
+            <div class="bc-contact">
+              <span>{{tempInvoice2.title}}</span>
+            </div>
+            <div>{{tempInvoice2.code}}</div>
+            <div class="bc-edit" @click="isShowInvoice2=false">编辑</div>
+          </div>
+        </template>
+        <template v-else>
+          <div class="bc-item">
+            <div class="bc-contact">
+              <span>暂无发票信息</span>
+            </div>
+            <div class="bc-edit" @click="isShowInvoice2=false">编辑</div>
+          </div>
+        </template>
+      </template>
+      <template v-else>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">抬头名称</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice2.title" type="text" placeholder="发票抬头" />
+            </div>
+          </div>
+        </div>
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">税号</div>
+            <div class="ant-input">
+              <input @blur="blurHandle" v-model="tempInvoice2.code" type="text" placeholder="税务登记号" />
+            </div>
+          </div>
+        </div>
+        <button @click="saveInvoice" type="submit" class="ant-btn ant-btn-primary">
+          <span>保 存</span>
+        </button>
+        <button type="submit" class="ant-btn ant-btn-primary cancel" @click="isShowInvoice2=true">
+          <span>取 消</span>
+        </button>
+      </template>
+    </div>
+  </div>
+</template>
+
+<script>
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+export default {
+  props: ['invoice', 'invoicet', 'token', 'selectedId'],
+  computed: {
+    tempInvoice2: function () {
+      console.log(cloneObj(this.invoice))
+      return cloneObj(this.invoice)
+    },
+    tempInvoice3: function () {
+      return cloneObj(this.invoicet)
+    }
+  },
+  data () {
+    return {
+      isShowInvoice3: true,
+      isShowInvoice2: true
+    }
+  },
+  methods: {
+    blurHandle () {
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    saveInvoice () {
+      let params = {}
+      if (this.selectedId === 2) {
+        params = {
+          invoiceType: 2,
+          title: this.tempInvoice2.title,
+          code: this.tempInvoice2.code
+        }
+      } else {
+        let {
+          title,
+          code,
+          organizedAddress,
+          registerPhone,
+          bankName,
+          bankAccount
+        } = this.tempInvoice3
+        params = {
+          invoiceType: 3,
+          title,
+          code,
+          organizedAddress,
+          registerPhone,
+          bankName,
+          bankAccount
+        }
+      }
+
+      this.$http
+        .post('user/invoice/save', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          let res = data.data
+          if (res.code !== 0) return
+          this.$emit('closeInvoice', true)
+          let type = this.selectedId === 'geren' ? 2 : 3
+          this.$store.dispatch('getInvoice', {
+            type: type,
+            params: {
+              invoiceType: type
+            }
+          })
+        })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+</style>

+ 194 - 0
src/components/cinvoices/style.scss

@@ -0,0 +1,194 @@
+.cancel{
+  background: #e7e7e7!important;
+  margin-left: 5px;
+}
+.ant-input{
+  height: auto;
+  input{
+    border: 0;
+    width: 100%;
+    height: 40px;
+    line-height: 40px;
+    padding: 0;
+    font-size: 12px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+.check-con {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+  color: rgba(0, 0, 0, 0.65);
+  font-size: 14px;
+  font-variant: tabular-nums;
+  line-height: 1.5;
+  list-style: none;
+  font-feature-settings: "tnum", "tnum";
+  display: inline-block;
+  line-height: unset;
+  cursor: pointer;
+  color: rgba(0,0,0,.65);
+  font-size: 14px;
+  margin-right: 30px;
+  .check-box {
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    font-variant: tabular-nums;
+    line-height: 1.5;
+    list-style: none;
+    font-feature-settings: "tnum", "tnum";
+    position: relative;
+    top: -0.09em;
+    display: inline-block;
+    line-height: 1;
+    white-space: nowrap;
+    vertical-align: middle;
+    outline: none;
+    cursor: pointer;
+    .checkbox-input {
+      position: absolute;
+      top: 0;
+      right: 0;
+      bottom: 0;
+      left: 0;
+      z-index: 1;
+      width: 100%;
+      height: 100%;
+      cursor: pointer;
+      opacity: 0;
+    }
+    .checkbox-inner {
+      border-radius: 90px;
+      width: 18px;
+      height: 18px;
+      position: relative;
+      top: 0;
+      left: 0;
+      display: block;
+      background-color: #fff;
+      border: 1px solid #d9d9d9;
+      border-collapse: separate;
+      transition: all 0.3s;
+      &::after {
+        position: absolute;
+        top: 50%;
+        left: 21%;
+        display: table;
+        width: 5.71428571px;
+        height: 9.14285714px;
+        border: 2px solid #fff;
+        width: 8px;
+        height: 12px;
+        border-top: 0;
+        border-left: 0;
+        transform: rotate(45deg) scale(0) translate(-50%, -50%);
+        opacity: 0;
+        transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6),
+      }
+    }
+    .checkbox-inner-checked {
+      background-color: #1fe4dc;
+      border-color: #1fe4dc;
+      &::after {
+        position: absolute;
+        display: table;
+        border: 2px solid #fff;
+        border-top: 0;
+        border-left: 0;
+        transform: rotate(45deg) scale(1) translate(-50%, -50%);
+        opacity: 1;
+        transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
+        content: " ";
+      }
+    }
+  }
+}
+.invoices-layout{
+  background: #fff;
+  .invoice-header{
+    padding: 18px 16px 0;
+  }
+  .address-input-con{
+    padding: 16px 0 0;
+    font-size: 12px;
+    line-height: 1.5;
+    color: rgba(0, 0, 0, 0.65);
+    .address-input-item{
+      display: flex;
+      margin-bottom:8px;
+  
+      .address-sub{
+        width: 100%;
+        .top-title{
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          color: rgba(0, 0, 0, 0.85);
+          padding: 0 0 8px;
+          margin: 0;
+          display: block;
+          text-align: left;
+          line-height: 1.5;
+          &::before{
+            display: inline-block;
+            margin-right: 4px;
+            content: "*";
+            font-family: SimSun;
+            line-height: 1;
+            font-size: 12px;
+            color: #f04134;
+          }
+        }
+      }
+      .address-name,.prov-name{
+        width: 33.33%;
+        padding-right:4px;
+        flex-shrink: 0;
+      }
+      .prov-name{
+        width: 50%;
+      }
+      .address-phone,.city-name{
+        flex: auto;
+      }
+      
+    }
+    .bc-item{
+      padding: 16px;
+      margin: 8px 0;
+      background-size: 18px 32px;
+      background-repeat: no-repeat;
+      background-position: left 16px top 16px;
+      border: 1px solid #1fe4dc;
+      position: relative;
+      background-color: #f6f9ff;
+      overflow-wrap: break-word;
+      .bc-contact{
+        font-size: 12px;
+        color: rgba(0,0,0,.7);
+        line-height: 18px;
+        
+      }
+      .bc-locotion{
+        font-size: 10px;
+        color: rgba(0,0,0,.45);
+        line-height: 12px;
+      }
+      .bc-edit{
+        position: absolute;
+        top: 16px;
+        right: 16px;
+        font-size: 12px;
+        color: rgba(0,0,0,.7);
+        line-height: 18px;
+      }
+    }
+    .p-dec{
+      line-height:32px;
+      margin-bottom: 8px;
+    }
+  }
+}

File diff suppressed because it is too large
+ 4793 - 0
src/components/citySelect/city.js


+ 209 - 0
src/components/citySelect/index.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="select-layout">
+    <div class="address-input-con">
+      <div class="address-input-item">
+        <div class="address-sub address-name">
+          <div class="top-title">姓名</div>
+          <div class="ant-input">
+            <input @blur="blurHandle"  v-model="tempAddress.shipName" type="text" placeholder="姓名" />
+          </div>
+        </div>
+        <div class="address-sub address-phone">
+          <div class="top-title">联系电话</div>
+          <div class="ant-input">
+            <input @blur="blurHandle" v-model="tempAddress.shipMobile" type="text" placeholder="联系电话" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub prov-name">
+          <div class="top-title">省份</div>
+          <div class="ant-input prov" @click="handleSelect('prov')">
+            {{citylist[currentPID]['p']||'省份'}}
+            <ul v-if="prov">
+              <li v-for="(item,i) in citylist" :key="i" @click="handleClick('currentPID',i)">{{item.p}}</li>
+            </ul>
+          </div>
+        </div>
+        <div class="address-sub city-phone">
+          <div class="top-title">城市</div>
+          <div class="ant-input city" @click="handleSelect('city')">
+            {{currentProv[currentCID]['n']||'城市'}}
+            <ul v-if="city">
+              <li v-for="(item,i) in currentProv" :key="i" @click="handleClick('currentCID',i)">{{item.n}}</li>
+            </ul>
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">地址</div>
+          <div class="ant-input dist" @click="handleSelect('dist')">
+            {{currentCity[currentSID]['s']||'区/县'}}
+            <ul v-if="dist">
+              <li v-for="(item,i) in currentCity" :key="i" @click="handleClick('currentSID',i)">{{item.s}}</li>
+            </ul>
+          </div>
+          <div class="ant-input">
+            <input @blur="blurHandle" v-model="tempAddress.shipAddress" type="text" placeholder="详细地址" />
+          </div>
+        </div>
+      </div>
+      <p class="p-dec">请务必详细填写相符无误的地址以免耽误收货</p>
+      <button type="submit" class="ant-btn ant-btn-primary" @click="uAddress">
+        <span>保 存</span>
+      </button>
+      <button type="submit" class="ant-btn ant-btn-primary cancel" @click="$emit('closeSelect', true)">
+        <span>取 消</span>
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { citylist } from './city'
+let sle = ['prov', 'city', 'dist']
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+export default {
+  props: ['address', 'token'],
+  data () {
+    let idArr = ['', '', '']
+    if (this.address.shipAreaPath) {
+      let tempArr = this.address.shipAreaPath.split(',')
+      let [p, c, d] = tempArr
+      idArr = (() => {
+        let tmp = []
+        citylist.forEach((item, index) => {
+          if (item.p === p) {
+            tmp.push(index)
+            item.c.forEach((t2, i2) => {
+              if (t2.n === c) {
+                tmp.push(i2)
+                t2.a.forEach((t3, i3) => {
+                  if (t3.s === d) {
+                    tmp.push(i3)
+                  }
+                })
+              }
+            })
+          }
+        })
+        return tmp
+      })()
+    }
+
+    return {
+      citylist,
+      prov: false,
+      city: false,
+      dist: false,
+      currentPID: idArr[0] || 18,
+      currentCID: idArr[1] || 3,
+      currentSID: idArr[2] || 2,
+      areaPath: cloneObj(this.address.areaPath)
+    }
+  },
+  computed: {
+    tempAddress: function () {
+      return cloneObj(this.address)
+    },
+
+    currentProv: function () {
+      let tmp = this.citylist[this.currentPID]
+      return tmp.c
+    },
+    currentCity: function () {
+      let cprov = this.citylist[this.currentPID]
+      let tmp = cprov.c[this.currentCID]
+      return tmp.a
+    }
+  },
+  watch: {
+    currentProv () {
+      this.currentCID = 0
+      this.currentSID = 0
+    }
+  },
+  methods: {
+    blurHandle () {
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    uAddress () {
+      this.tempAddress.province = this.areaPath[0]
+      this.tempAddress.city = this.areaPath[1]
+      this.tempAddress.shipAreaPath = this.areaPath.join(',')
+      let {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      } = this.tempAddress
+      let params = {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      }
+      this.$http
+        .post('/user/updateAddress', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          let res = data.data
+          if (res.code === 0) {
+            this.$emit('closeSelect', true)
+            this.$store.dispatch('getInfo', {
+              url: '/user/getReceiverInfo',
+              name: 'address'
+            })
+          }
+        })
+    },
+    handleSelect (item) {
+      sle.forEach(i => {
+        if (i === item) {
+          this[i] = !this[i]
+        } else {
+          this[i] = false
+        }
+      })
+    },
+    handleClick (id, i) {
+      this[id] = i
+      this.handleChange()
+    },
+    handleChange () {
+      let prov = this.citylist[this.currentPID]
+      let city = prov.c[this.currentCID]
+      let dist = city.a[this.currentSID]
+      this.areaPath = [prov.p, city.n, dist.s]
+    }
+  },
+  mounted () {
+    this.handleChange()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 94 - 0
src/components/citySelect/style.scss

@@ -0,0 +1,94 @@
+.cancel{
+  background: #e7e7e7!important;
+  margin-left: 5px;
+}
+.ant-input{
+  height: auto;
+  input{
+    border: 0;
+    width: 100%;
+    height: 40px;
+    line-height: 40px;
+    padding: 0;
+    font-size: 12px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+.address-input-con {
+  font-size: 12px;
+  line-height: 1.5;
+  margin-bottom: 10px;
+  color: rgba(0, 0, 0, 0.65);
+  .address-input-item {
+    display: flex;
+    margin-bottom: 8px;
+    .address-sub {
+      width: 100%;
+      .prov,
+      .city,
+      .dist {
+        position: relative;
+        ul{
+          position: absolute;
+          top: 48px;
+          left: 0;
+          background: #fff;
+          width: 100%;
+          box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+          border-radius: 4px;
+          z-index: 999;
+          transition: all 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
+          overflow: auto;
+          max-height: 300px;
+          li{
+            padding: 0 11px;
+            line-height: 30px;
+            height: 30px;
+            font-size: 12px;
+            color: rgba(0, 0, 0, 0.7);
+          }
+        }
+      }
+      .dist{
+        margin-bottom:8px;
+      }
+      .top-title {
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        color: rgba(0, 0, 0, 0.85);
+        padding: 0 0 8px;
+        margin: 0;
+        display: block;
+        text-align: left;
+        line-height: 1.5;
+        &::before {
+          display: inline-block;
+          margin-right: 4px;
+          content: "*";
+          font-family: SimSun;
+          line-height: 1;
+          font-size: 12px;
+          color: #f04134;
+        }
+      }
+    }
+    .address-name,
+    .prov-name {
+      width: 33.33%;
+      padding-right: 4px;
+      flex-shrink: 0;
+    }
+    .prov-name {
+      width: 50%;
+    }
+    .address-phone,
+    .city-name {
+      flex: auto;
+    }
+  }
+  .p-dec {
+    line-height: 32px;
+    margin-bottom: 8px;
+  }
+}

+ 181 - 0
src/components/invoices/index.vue

@@ -0,0 +1,181 @@
+<template>
+  <div class="invoices-layout">
+    <div class="invoice-header">
+      <label class="check-con" @click="type='geren'">
+        <span class="check-box">
+          <span class="checkbox-inner" :class="{'checkbox-inner-checked':type==='geren'}"></span>
+        </span>
+        <span>个人</span>
+      </label>
+      <label class="check-con" @click="type='qiye'">
+        <span class="check-box">
+          <span class="checkbox-inner" :class="{'checkbox-inner-checked':type==='qiye'}"></span>
+        </span>
+        <span>企业</span>
+      </label>
+    </div>
+    <div class="address-input-con" v-if="type==='qiye'">
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">抬头名称</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice3.title" type="text" placeholder="请输入发票抬头" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">税号</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice3.code" type="text" placeholder="请输入税务登记号" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">地址</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice3.organizedAddress" type="text" placeholder="公司地址" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">电话号码</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice3.registerPhone" type="text" placeholder="公司电话号码" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">开户银行</div>
+          <div class="ant-input" >
+           <input @blur="blurHandle" v-model="tempInvoice3.bankName" type="text" placeholder="开户银行" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">银行账户</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice3.bankAccount" type="text" placeholder="银行账户" />
+          </div>
+        </div>
+      </div>
+      <button @click="saveInvoice" type="submit" class="ant-btn ant-btn-primary">
+        <span>保 存</span>
+      </button>
+      <button type="submit" class="ant-btn ant-btn-primary cancel" @click="$emit('closeInvoice', true)">
+        <span>取 消</span>
+      </button>
+    </div>
+    <div class="address-input-con" v-else>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">抬头名称</div>
+          <div class="ant-input" >
+           <input @blur="blurHandle" v-model="tempInvoice2.title" type="text" placeholder="发票抬头" />
+          </div>
+        </div>
+      </div>
+      <div class="address-input-item">
+        <div class="address-sub">
+          <div class="top-title">税号</div>
+          <div class="ant-input" >
+            <input @blur="blurHandle" v-model="tempInvoice2.code" type="text" placeholder="税务登记号" />
+          </div>
+        </div>
+      </div>
+      <button @click="saveInvoice" type="submit" class="ant-btn ant-btn-primary">
+        <span>保 存</span>
+      </button>
+      <button type="submit" class="ant-btn ant-btn-primary cancel" @click="$emit('closeInvoice', true)">
+        <span>取 消</span>
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+export default {
+  props: ['invoice', 'invoicet', 'token'],
+  computed: {
+    tempInvoice2: function () {
+      console.log(cloneObj(this.invoice))
+      return cloneObj(this.invoice)
+    },
+    tempInvoice3: function () {
+      return cloneObj(this.invoicet)
+    }
+  },
+  data () {
+    return {
+      type: 'geren'
+    }
+  },
+  methods: {
+    blurHandle () {
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    saveInvoice () {
+      let params = {}
+      if (this.type === 'geren') {
+        params = {
+          invoiceType: 2,
+          title: this.tempInvoice2.title,
+          code: this.tempInvoice2.code
+        }
+      } else {
+        let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.tempInvoice3
+        params = {
+          invoiceType: 3,
+          title,
+          code,
+          organizedAddress,
+          registerPhone,
+          bankName,
+          bankAccount
+        }
+      }
+
+      this.$http
+        .post('user/invoice/save', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          let res = data.data
+          if (res.code !== 0) return
+          this.$emit('closeInvoice', true)
+          let type = this.type === 'geren' ? 2 : 3
+          this.$store.dispatch('getInvoice', {
+            type: type,
+            params: {
+              invoiceType: type
+            }
+          })
+        })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+</style>

+ 164 - 0
src/components/invoices/style.scss

@@ -0,0 +1,164 @@
+.cancel{
+  background: #e7e7e7!important;
+  margin-left: 5px;
+}
+.ant-input{
+  height: auto;
+  input{
+    border: 0;
+    width: 100%;
+    height: 40px;
+    line-height: 40px;
+    padding: 0;
+    font-size: 12px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+.check-con {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+  color: rgba(0, 0, 0, 0.65);
+  font-size: 14px;
+  font-variant: tabular-nums;
+  line-height: 1.5;
+  list-style: none;
+  font-feature-settings: "tnum", "tnum";
+  display: inline-block;
+  line-height: unset;
+  cursor: pointer;
+  color: rgba(0,0,0,.65);
+  font-size: 14px;
+  margin-right: 30px;
+  .check-box {
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    font-variant: tabular-nums;
+    line-height: 1.5;
+    list-style: none;
+    font-feature-settings: "tnum", "tnum";
+    position: relative;
+    top: -0.09em;
+    display: inline-block;
+    line-height: 1;
+    white-space: nowrap;
+    vertical-align: middle;
+    outline: none;
+    cursor: pointer;
+    .checkbox-input {
+      position: absolute;
+      top: 0;
+      right: 0;
+      bottom: 0;
+      left: 0;
+      z-index: 1;
+      width: 100%;
+      height: 100%;
+      cursor: pointer;
+      opacity: 0;
+    }
+    .checkbox-inner {
+      border-radius: 90px;
+      width: 18px;
+      height: 18px;
+      position: relative;
+      top: 0;
+      left: 0;
+      display: block;
+      background-color: #fff;
+      border: 1px solid #d9d9d9;
+      border-collapse: separate;
+      transition: all 0.3s;
+      &::after {
+        position: absolute;
+        top: 50%;
+        left: 21%;
+        display: table;
+        width: 5.71428571px;
+        height: 9.14285714px;
+        border: 2px solid #fff;
+        width: 8px;
+        height: 12px;
+        border-top: 0;
+        border-left: 0;
+        transform: rotate(45deg) scale(0) translate(-50%, -50%);
+        opacity: 0;
+        transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6),
+      }
+    }
+    .checkbox-inner-checked {
+      background-color: #1fe4dc;
+      border-color: #1fe4dc;
+      &::after {
+        position: absolute;
+        display: table;
+        border: 2px solid #fff;
+        border-top: 0;
+        border-left: 0;
+        transform: rotate(45deg) scale(1) translate(-50%, -50%);
+        opacity: 1;
+        transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
+        content: " ";
+      }
+    }
+  }
+}
+.invoices-layout{
+  background: #fff;
+  .invoice-header{
+    padding: 18px 16px 0;
+  }
+  .address-input-con{
+    padding: 16px;
+    font-size: 12px;
+    line-height: 1.5;
+    margin-bottom: 10px;
+    color: rgba(0, 0, 0, 0.65);
+    .address-input-item{
+      display: flex;
+      margin-bottom:8px;
+      .address-sub{
+        width: 100%;
+        .top-title{
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          color: rgba(0, 0, 0, 0.85);
+          padding: 0 0 8px;
+          margin: 0;
+          display: block;
+          text-align: left;
+          line-height: 1.5;
+          &::before{
+            display: inline-block;
+            margin-right: 4px;
+            content: "*";
+            font-family: SimSun;
+            line-height: 1;
+            font-size: 12px;
+            color: #f04134;
+          }
+        }
+      }
+      .address-name,.prov-name{
+        width: 33.33%;
+        padding-right:4px;
+        flex-shrink: 0;
+      }
+      .prov-name{
+        width: 50%;
+      }
+      .address-phone,.city-name{
+        flex: auto;
+      }
+      
+    }
+    .p-dec{
+      line-height:32px;
+      margin-bottom: 8px;
+    }
+  }
+}

+ 2 - 2
src/components/spinner/index.vue

@@ -3,7 +3,7 @@
     <div class="icon" @click="num>1?num--:1" >
       <i  class="iconfont icon-jianhao"></i>
     </div>
-    <input v-model="num" min="1" step="1" type="number">
+    <input oninput="value=Math.max(Math.min(Number(value.replace(/[^\d]/g,'')),99),1)" v-model="num" min="1" step="1" type="number">
     <div @click="num++"  class="icon">
       <i class="iconfont icon-jiahao"></i>
     </div>
@@ -19,7 +19,7 @@ export default {
   },
   watch: {
     num (newVal) {
-      this.$emit('count', newVal)
+      this.$emit('count', Number(String(newVal).replace(/\b(0+)/gi, '')))
     }
   }
 }

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

@@ -0,0 +1,203 @@
+<template>
+  <div>
+    <div
+      class="toast-layout"
+      :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
+      :class="{'toast-active':isLoaing}"
+    >
+      <div class="loading">
+        <svg viewBox="0 0 28 19">
+          <path
+            d="M4 0l3 3C5.151 4.589 4.141 6.938 4 9c.141 2.994 1.18 5.374 3 7l-3 3c-2.512-2.51-4-5.919-4-10 0-3.134 1.446-6.499 4-9zm20 0c2.554 2.501 4 5.866 4 9 0 4.081-1.488 7.49-4 10l-3-3c1.82-1.626 2.859-4.006 3-7-.141-2.062-1.151-4.411-3-6l3-3z"
+          ></path>
+        </svg>
+      </div>
+    </div>
+    <div
+      class="toast-layout"
+      :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
+      :class="{'toast-active':visible}"
+    >
+      <div class="toast-con">
+        <div class="detail">
+          <div>
+            <p class="main-msg" v-html="message"></p>
+            <p class="sub-msg">{{submsg}}</p>
+          </div>
+        </div>
+        <div class="bottom" v-if="toastType==='comfirm'">
+          <span @click="visible=false" class="btn primary">取消</span>
+          <span class="b-line"></span>
+          <span class="btn primary" @click="emitCallback">确认</span>
+        </div>
+        <div class="bottom mid-bottom" v-else>
+          <span class="btn primary" @click="emitCallback">确认</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+let types = {
+  warn: '提示',
+  error: '错误',
+  success: '成功'
+}
+export default {
+  data () {
+    return {
+      visible: false,
+      message: '',
+      submsg: '',
+      type: 'warn',
+      toastType: 'show',
+      callback: '',
+      isLoaing: false,
+      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;
+$anima-time:0.2s;
+$anima-delay:0.15s;
+
+.btn {
+  width: 88px;
+  color: #4a90e2;
+  display: inline-block;
+  font-size: 14px;
+  text-align: center;
+  border-radius: 2px;
+  width: 88px;
+  height: 40px;
+  line-height: 40px;
+  cursor: pointer;
+}
+.primary {
+  background: #fff;
+}
+.cancel {
+  background: #e6e6e6;
+  margin-left: 10px;
+}
+.toast-layout {
+  display: none;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  margin: 0;
+  opacity:0;
+  z-index: 88888888;
+  transition: all $anima-time linear;
+  .loading {
+    svg {
+      position: absolute;
+      top: calc(50% - 14px);
+      left: calc(50% - 14px);
+      height: 28px;
+      width: 28px;
+      max-height: 28px;
+      max-width: 28px;
+      animation: rotateLoader 1s;
+      animation-iteration-count: infinite;
+    }
+  }
+  .toast-con {
+    position: absolute;
+    padding: 0;
+    overflow: hidden;
+    top: 48%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    background: #fff;
+    width: 80%;
+    border-radius: 6px;
+    box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
+    .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 10px;
+      text-align: center;
+      height: 86px;
+      position: relative;
+      &>div{
+        position: absolute;
+        top: 50%;
+        width: 100%;
+        left: 50%;
+        transform: translate(-50%,-50%);
+        .main-msg{
+          font-size: 14px;
+          color: #000000;
+          line-height: 24px;
+        }
+        .sub-msg{
+          font-size: 10px;
+          color: #898A8E;
+          line-height: 15px;
+        }
+      }
+    }
+    .bottom {
+      border-top: 1px solid #ddd;
+      display: flex;
+      justify-content: space-around;
+      .b-line{
+        display: inline-block;
+        width: 1px;
+        height: 40px;
+        background: #ddd;
+      }
+    }
+    .mid-bottom {
+      text-align: center;
+      padding: 0;
+      .primary{
+        flex: 1;
+      }
+    }
+  }
+}
+.toast-active{
+  display: block!important;
+  opacity: 1!important;
+}
+</style>

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

@@ -0,0 +1,48 @@
+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 () {
+      }
+    },
+    showLoading: () => {
+      instance.isLoaing = true
+    },
+    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 () {
+      }
+    },
+    hideLoading: () => {
+      instance.isLoaing = false
+    }
+  }
+}
+export default Toast

+ 13 - 5
src/main.js

@@ -1,16 +1,24 @@
 import 'babel-polyfill'
 import Vue from 'vue'
 import App from './App'
-import router from './router'
 import vuex from 'vuex'
-import axios from './util/http.js'
+import Toast from '@/components/toast/toast'
 
-Vue.prototype.$http = axios
+// import axios from './util/http.js'
+// import router from './router'
+Vue.prototype.$cdn = 'https://4dscene.4dage.com/new4dkk/mobile/'
 
 Vue.use(vuex)
-
+Vue.use(Toast)
 Vue.prototype.$bus = new Vue()
-Vue.prototype.$cdn = 'https://4dscene.4dage.com/new4dkk/'
+
+let axios = require('./util/http.js').default
+let router = require('./router').default
+
+Vue.prototype.$http = axios
+Vue.prototype.$serverName = 'https://pro.4dkankan.com/'
+// Vue.prototype.$serverName = ''
+
 Vue.config.productionTip = false
 
 function dateFtt (fmt) {

+ 2 - 2
src/pages/about/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="about-layout">
-    <img class="about-logo" src="@/assets/images/event.png" alt="">
+    <img class="about-logo" :src="`${$cdn}images/event.png`" alt="">
     <div class="plate01">
       <div class="about-intro">
         <div v-for="(item,i) in langAbout.intro" :key='i'>
@@ -13,7 +13,7 @@
       </div>
     </div>
     <div class="plate02">
-      <img src="@/assets/images/hezhao.png" alt>
+      <img :src="`${$cdn}images/hezhao.png`" alt>
     </div>
     <div class="plate03">
       <div class="e-node">

+ 75 - 11
src/pages/account/forget/index.vue

@@ -1,41 +1,105 @@
 <template>
   <div class="forget-layout">
     <div class="banner">
-      <img  src="@/assets/images/icon/forget.png" alt="">
+      <img :src="`${$cdn}images/icon/forget.png`" alt="">
       <p>帮你找回密码</p>
     </div>
     <div class="r-line"></div>
     <div class="login-con">
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
-        <img src="@/assets/images/icon/icon-phone@2x.png" alt="">
-        <input @focus="inputActive='phone'" @blur="inputActive=''" type="text" placeholder="手机">
+        <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
+        <input v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
       </div>
       <div class="code-con">
         <div class="input-con" :class="{inputActive:inputActive==='code'}">
-          <img src="@/assets/images/icon/icon-code@2x.png" style="width:23px;" alt="">
-          <input @focus="inputActive='code'" @blur="inputActive=''" style="padding-left:6px;" type="text" placeholder="输入验证码">
+          <img :src="`${$cdn}images/icon/icon-code@2x.png`" style="width:23px;" alt="">
+          <input v-model="authCode" @focus="inputActive='code'" @blur="blurHandle" style="padding-left:6px;" type="text" placeholder="输入验证码">
         </div>
-        <div class="btns">获取验证码</div>
+        <div v-if="!jishi" class="btns" @click="getAuthCode">获取验证码</div>
+        <span class="btns" v-else>{{interTime}}s后重新发送</span>
       </div>
       <div class="input-con"  :class="{inputActive:inputActive==='password'}">
-        <img src="@/assets/images/icon/icon-password@2x.png" alt="">
-        <input @focus="inputActive='password'" @blur="inputActive=''" type="password" placeholder="新密码">
+        <img :src="`${$cdn}images/icon/icon-password@2x.png`" alt="">
+        <input v-model="password" @focus="inputActive='password'" @blur="blurHandle" type="password" placeholder="新密码">
       </div>
       <div class="input-con"  :class="{inputActive:inputActive==='confirm'}">
-        <img src="@/assets/images/icon/icon-confirm@2x.png" alt="">
-        <input @focus="inputActive='confirm'" @blur="inputActive=''" type="password" placeholder="再次输入新密码">
+        <img :src="`${$cdn}images/icon/icon-confirm@2x.png`" alt="">
+        <input v-model="confirmpass" @focus="inputActive='confirm'" @blur="blurHandle" type="password" placeholder="再次输入新密码">
       </div>
-      <div class="btns">提交</div>
+      <div class="btns" @click="submit">提交</div>
     </div>
   </div>
 </template>
 
 <script>
+import {mapState} from 'vuex'
+
 export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token
+    })
+  },
   data () {
     return {
+      phone: '',
+      authCode: '',
+      interTime: 60,
+      jishi: false,
+      password: '',
+      confirmpass: '',
       inputActive: ''
     }
+  },
+  methods: {
+    blurHandle () {
+      this.inputActive = ''
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    getAuthCode () {
+      this.$store.dispatch('getAuthCode', this.phone)
+      this.interl && clearInterval(this.interl)
+      this.interl = null
+      this.jishi = true
+      this.interl = setInterval(() => {
+        this.interTime--
+        if (this.interTime <= 0) {
+          this.jishi = false
+          this.interTime = 60
+          clearInterval(this.interl)
+          this.interl = null
+        }
+      }, 1000)
+    },
+    async submit () {
+      if (!this.password) {
+        return this.$toast.show('warn', '密码格式不正确')
+      }
+      let params = {
+        password: this.password,
+        phoneNum: this.phone,
+        confirmPwd: this.confirmpass,
+        msgAuthCode: this.authCode
+      }
+      let res = await this.$http({
+        method: 'post',
+        headers: {
+          token: this.token
+        },
+        data: params,
+        url: 'sso/user/changePassword'
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', response.msg)
+      }
+      this.$toast.show('warn', '密码修改成功', () => {
+        this.$router.push({path: '/login'})
+      })
+    }
   }
 }
 </script>

+ 35 - 7
src/pages/account/login/index.vue

@@ -1,23 +1,23 @@
 <template>
   <div class="account-layout">
     <div class="banner">
-      <img  src="@/assets/images/icon/login.png" alt="">
+      <img :src="`${$cdn}images/icon/login.png`" alt="">
       <p>Hi~ 请登录</p>
     </div>
     <div class="r-line"></div>
     <div class="login-con">
       <div class="input-con" :class="{inputActive:inputActive==='text'}">
-        <img src="@/assets/images/icon/icon-phone@2x.png" alt="">
-        <input @focus="inputActive='text'" @blur="inputActive=''" type="text" placeholder="手机">
+        <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
+        <input v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' @focus="inputActive='text'" @blur="blurHandle" type="text" placeholder="手机">
       </div>
       <div class="input-con"  :class="{inputActive:inputActive==='password'}">
-        <img src="@/assets/images/icon/icon-password@2x.png" alt="">
-        <input @focus="inputActive='password'" @blur="inputActive=''" type="password" placeholder="密码">
+        <img :src="`${$cdn}images/icon/icon-password@2x.png`" alt="">
+        <input v-model="password" @focus="inputActive='password'" @blur="blurHandle" type="password" placeholder="密码">
       </div>
       <div class="forget">
         <router-link :to="{path:'/forget'}">忘记密码?</router-link>
       </div>
-      <div class="btns">登录</div>
+      <div class="btns" @click="login">登录</div>
       <div class="to-register">
         <div class="re-con">
           <router-link :to="{path:'/register'}">尚未注册账号?</router-link>
@@ -28,10 +28,38 @@
 </template>
 
 <script>
+import {mapState} from 'vuex'
+
 export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token
+    })
+  },
   data () {
     return {
-      inputActive: ''
+      inputActive: '',
+      phone: '',
+      password: ''
+    }
+  },
+  methods: {
+    async login () {
+      let params = {
+        phoneNum: this.phone,
+        password: this.password
+      }
+      await this.$store.dispatch('login', params)
+      if (this.token) {
+        this.$router.replace({path: '/information'})
+      }
+    },
+    blurHandle () {
+      this.inputActive = ''
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
     }
   }
 }

+ 2 - 2
src/pages/account/login/style.scss

@@ -1,13 +1,13 @@
 input{
   border: 0;
-  outline: 0;
+  outline: none;
   height: 48px;
-  line-height: 48px;
   padding-right: 16px;
   padding-left: 12px;
   font-size: 14px;
   color: #000;
   flex: auto;
+  appearance: none;
 }
 .btns{
   display: block;

+ 116 - 24
src/pages/account/manage/cart/index.vue

@@ -1,88 +1,180 @@
 <template>
   <div class="cart-layout">
-    <div class="cart-con" v-if="true">
+    <div class="cart-con" v-if="cart.length>0">
       <div class="c-header">
         <label class="check-con">
-          <span class="check-box">
-            <input v-model="checked" @click="checked=!checked" type="checkbox" class="checkbox-input" value="">
+          <span class="check-box" @click="selectAll">
             <span class="checkbox-inner" :class="{'checkbox-inner-checked':checked}"></span>
           </span>
           <span>全选</span>
         </label>
       </div>
-      <div class="cart-item">
+      <div class="cart-item" v-for="(item, index) in cart" :key="index">
         <div class="i-left">
-          <label class="check-con">
+          <label class="check-con" @click="selectItem(item,index)">
             <span class="check-box">
-              <input v-model="checked" @click="checked=!checked" type="checkbox" class="checkbox-input" value="">
-              <span class="checkbox-inner" :class="{'checkbox-inner-checked':checked}"></span>
+              <span class="checkbox-inner" :class="{'checkbox-inner-checked':String(checkedArr[index])}"></span>
             </span>
           </label>
         </div>
         <div class="info-con">
-            <div class="i-info" v-for="(item,i) in 2" :key="i">
+            <div class="i-info">
             <div class="img-product">
-              <img src="@/assets/images/banner_pro.png" alt="">
+              <img :src="item.goodsId===4?`${$cdn}images/banner_pro.png`:`${$cdn}images/t_product.png`" alt="">
             </div>
             <div class="info-detail">
               <div class="detail-top">
-                <img class="img-txt" src="@/assets/images/pro-logo-m.png" alt="">
+                <img class="img-txt" :src="item.goodsId===4?`${$cdn}images/download-pro.png`:`${$cdn}images/download-lite.png`" alt="">
                 <div>标准套餐</div>
-                <img class="i-close" src="@/assets/images/i_close.png" alt="">
+                <img class="i-close" @click="rmItem(item)" :src="`${$cdn}images/i_close.png`" alt="">
               </div>
               <div class="detail-bottom">
                 <div class="btm-price">
-                  CNY ¥ 99888
+                  CNY ¥ {{item.price}}
                 </div>
                 <div class="ipt-number">
-                  <img class="i-close" src="@/assets/images/ic_cart_less_h@2x.png" alt="">
+                  <img class="i-close" @click="reduce(item)" :src="`${$cdn}images/ic_cart_less_h@2x.png`" alt="">
                   <div class="input-num">
-                    <input type="text" value="1" step="1">
+                    <input v-model="item.goodsCount" disabled type="text" step="1">
                   </div>
-                  <img class="i-close" src="@/assets/images/ic_cart_plus_h@2x.png" alt="">
+                  <img class="i-close" @click="add(item)" :src="`${$cdn}images/ic_cart_plus_h@2x.png`" alt="">
                 </div>
               </div>
             </div>
           </div>
         </div>
-
       </div>
       <div class="sum-con">
         <div class="sum-price">
           <div>
             <span>合计:</span>
-            <span class="price-txt">CNY ¥202641</span>
+            <span class="price-txt">CNY ¥{{getSum()[1]}}</span>
           </div>
           <div>
             <span>本订单包邮</span>
           </div>
         </div>
-        <div class="btn-submit">结算</div>
+        <div class="btn-submit" @click="toPay">结算</div>
         <div class="dec">温馨提示:您的订单将有顺丰速运专业配送</div>
       </div>
       <div class="paytype">
         <div>支付方式</div>
-        <img src="@/assets/images/paytypelist.png" alt="">
+        <img :src="`${$cdn}images/paytypelist.png`" alt="">
       </div>
     </div>
     <div class="no-cart-con" v-else>
-      <img src="@/assets/images/nocart.png" alt="">
+      <img :src="`${$cdn}images/nocart.png`" alt="">
       <div class="nocart-txt">您的购物车是空的</div>
-      <div class="btn-submit">结算</div>
+      <div class="btn-submit" @click="$router.push({path:'/eight'})">继续选购</div>
     </div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
 export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      cart: state => {
+        if (Object.prototype.toString.call(state.user.cart) === '[object Array]') {
+          return state.user.cart
+        }
+        let tmp = (state.user.cart && state.user.cart !== 'null' ? JSON.parse(state.user.cart) : [])
+        return cloneObj(tmp)
+      }
+    })
+  },
   data () {
     return {
-      checked: false
+      checked: false,
+      checkedArr: {
+        0: '',
+        1: '',
+        2: '',
+        3: ''
+      }
     }
   },
   methods: {
-    selectItem (e) {
-
+    reduce (item) {
+      if (item.goodsCount > 1) {
+        item.goodsCount--
+        let params = {
+          goodsId: item.goodsId,
+          goodsCount: item.goodsCount
+        }
+        this.$store.dispatch('reduceCart', params)
+      }
+    },
+    selectAll () {
+      this.checked = !this.checked
+      this.cart.forEach((item, i) => {
+        if (this.checked) {
+          this.checkedArr[i] = item
+        } else {
+          this.checkedArr[i] = ''
+        }
+      })
+    },
+    add (item) {
+      let params = {
+        goodsId: item.goodsId,
+        goodsCount: 1,
+        skuSn: item.skuSn
+      }
+      this.$store.dispatch('addCart', params)
+    },
+    rmItem (item) {
+      this.$toast.showConfirm('warn', '确定删除吗?', () => {
+        let params = {
+          goodsId: item.goodsId,
+          goodsCount: 0
+        }
+        this.$store.dispatch('reduceCart', params)
+      })
+    },
+    selectItem (item, index) {
+      if (this.checkedArr[index]) {
+        this.checkedArr[index] = ''
+      } else {
+        this.checkedArr[index] = item
+      }
+    },
+    toPay () {
+      let temp = {}
+      let tmpcart = []
+      Object.keys(this.checkedArr).forEach(item => {
+        if (this.checkedArr[item]) {
+          tmpcart.push(this.checkedArr[item])
+        }
+      })
+      if (tmpcart.length <= 0) {
+        return this.$toast.show('warn', '请勾选您想购买的商品')
+      }
+      temp['goods'] = tmpcart
+      this.$store.commit('PAYINFO', temp)
+      this.$router.push({path: '/confirm'})
+    },
+    getSum () {
+      let sum = 0
+      let count = 0
+      this.cart.forEach(item => {
+        sum += item.goodsCount * item.price
+        count += item.goodsCount
+      })
+      return [count, sum]
     }
   }
 }

+ 86 - 8
src/pages/account/manage/change/index.vue

@@ -5,16 +5,21 @@
         <div class="order-input-item">
           <div class="order-sub">
             <div class="top-title">手机号码</div>
-            <input class="ant-input" type="text" placeholder="手机号码" />
+            <div class="ant-input" >
+              <input @blur="blurHandle" v-model="phone" type="text" placeholder="手机号码" />
+            </div>
           </div>
         </div>
         <div class="order-input-item">
           <div class="order-sub">
             <div class="top-title">验证码</div>
             <div class="code-con">
-              <input class="ant-input" type="text" placeholder="请输入验证码" />
+              <div class="ant-input" >
+               <input @blur="blurHandle" v-model="code" type="text" placeholder="请输入验证码" />
+              </div>
                 <button type="submit" class="ant-btn ant-btn-primary code">
-                    <span>获取验证码</span>
+                    <span v-if="!jishi">获取验证码</span>
+                    <span v-else>{{interTime}}s后重新发送</span>
                 </button>
             </div>
           </div>
@@ -22,16 +27,20 @@
         <div class="order-input-item">
           <div class="order-sub">
             <div class="top-title">密码</div>
-            <input class="ant-input" type="text" placeholder="请输入密码" />
+              <div class="ant-input" >
+                <input @blur="blurHandle" v-model="password" type="password" placeholder="请输入密码" />
+              </div>
           </div>
         </div>
         <div class="order-input-item">
           <div class="order-sub">
             <div class="top-title">确认密码</div>
-            <input class="ant-input" type="text" placeholder="请再次输入密码" />
+              <div class="ant-input" >
+                <input @blur="blurHandle" v-model="confirmpassword" type="password" placeholder="请再次输入密码" />
+              </div>
           </div>
         </div>
-        <button type="submit" class="ant-btn ant-btn-primary">
+        <button @click="submit" type="submit" class="ant-btn ant-btn-primary">
           <span>提 交</span>
         </button>
       </div>
@@ -40,11 +49,80 @@
 </template>
 
 <script>
-export default {
+import {mapState} from 'vuex'
 
+export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token
+    })
+  },
+  data () {
+    return {
+      password: '',
+      confirmpassword: '',
+      phone: '',
+      interTime: 60,
+      jishi: false,
+      code: ''
+    }
+  },
+  methods: {
+    blurHandle () {
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    getAuthCode () {
+      this.$store.dispatch('getAuthCode', this.phone)
+      if (this.phone) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            this.interTime = 60
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
+    },
+    submit () {
+      if (!this.password) {
+        return this.$toast.show('warn', '密码格式不正确')
+      }
+      if (this.password !== this.confirmpassword) {
+        return this.$toast.show('warn', '输入的两次密码不一致')
+      }
+      let params = {
+        password: this.password,
+        phoneNum: this.phone,
+        msgAuthCode: this.code
+      }
+      this.$http({
+        method: 'post',
+        headers: {
+          token: this.token
+        },
+        data: params,
+        url: 'user/changePassword'
+      }, res => {
+        let data = res.data
+        if (data.code === 0) {
+          this.$store.commit('logout')
+          this.$toast.show('success', '密码修改成功,请重新登录', () => {
+            this.$router.push({path: '/login'})
+          })
+        }
+      })
+    }
+  }
 }
 </script>
-
 <style lang="scss" scoped>
 @import './style.scss';
 </style>

+ 12 - 0
src/pages/account/manage/change/style.scss

@@ -1,5 +1,17 @@
 .order-layout{
   margin-top: 20px;
+  .ant-input{
+    height: auto;
+    input{
+      border: 0;
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      padding: 0;
+      font-size: 12px;
+      color: rgba(0, 0, 0, 0.65);
+    }
+  }
   .order-con{
     background: #fff;
     .sub-title{

+ 106 - 15
src/pages/account/manage/confirm/index.vue

@@ -3,35 +3,38 @@
     <div class="time-line">
       <div class="line"></div>
       <div class="auth">
-        <img src="@/assets/images/hasLogin.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/hasLogin.png`" alt="" class="timeline-icon">
         <div class="timeline-text">登录信息</div>
       </div>
       <div class="shipping">
-        <img src="@/assets/images/spot.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/spot.png`" alt="" class="timeline-icon">
         <div class="timeline-text">配送信息</div>
       </div>
       <div class="payment">
-        <img src="@/assets/images/ic_schedule_default_mb@2x.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/ic_schedule_default_mb@2x.png`" alt="" class="timeline-icon">
         <div class="timeline-text">支付信息</div>
         </div>
       <div class="review">
-        <img src="@/assets/images/ic_schedule_default_mb@2x.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/ic_schedule_default_mb@2x.png`" alt="" class="timeline-icon">
         <div class="timeline-text">订单提交</div>
       </div>
     </div>
     <div class="box-con">
       <div class="bc-title">收货地址</div>
-      <div class="bc-item address-item">
+      <div class="bc-item address-item" v-if="isShowAddress">
         <div class="bc-ct">
           <div class="bc-contact">
-            陈志广
-            <div>13211064273</div>
+            {{address.shipName}}
+            <div>{{address.shipMobile}}</div>
           </div>
           <div class="bc-locotion">
-            中国大陆,广西,贵港,广西贵港市农业科学研究所内广西贵港市农业科学研究所内。537100
+            {{`${address.shipAreaPath}${address.shipAddress}`}}
           </div>
         </div>
-        <div class="bc-edit">编辑</div>
+        <div class="bc-edit" @click="isShowAddress=false">编辑</div>
+      </div>
+      <div class="address-con" v-else>
+        <citySelect :address='address' :token="token" @closeSelect="data=>{isShowAddress=data}" />
       </div>
     </div>
     <div class="box-con">
@@ -45,26 +48,114 @@
       <div class="bc-title">发票</div>
       <div class="invoice-con" :class="{'invoice-focus':selected}">
         <div class="invoice-select" @click="selected=!selected">
-          <div class="select-txt">不需要发票</div>
+          <div class="select-txt">{{selectedTxt}}</div>
           <i class="iconfont icon-xia"></i>
         </div>
         <ul class="invoice-item" :class="{'invoice-active':selected}">
-          <li>增值税发票</li>
-          <li>增值税发票</li>
-          <li>增值税发票</li>
+          <li v-for="(item,i) in invoiceType" :key="i" @click="handleItem(item)">{{item.name}}</li>
         </ul>
+        <cinvoices v-if="selectedId!==1" :invoice='invoice2' :selectedId='selectedId' :invoicet="invoice3" :token="token" @closeInvoice="data=>{isShowInvoice=data}"/>
       </div>
     </div>
-    <div class="btn-confirm">下一步</div>
+    <div class="btn-confirm" @click="next()">下一步</div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+import citySelect from '@/components/citySelect'
+import cinvoices from '@/components/cinvoices'
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+
 export default {
+  components: {
+    citySelect,
+    cinvoices
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      invoice2: state => {
+        let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      invoice3: state => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
+        }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+
+        return (condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      payinfo: state => {
+        let type = Object.prototype.toString.call(state.user.payinfo)
+        if (type === '[object Object]') {
+          return state.user.payinfo
+        }
+        let condition = state.user.payinfo && state.user.payinfo !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.payinfo) : {}
+      },
+      address: state => cloneObj(state.user.address) || {}
+    })
+  },
   data () {
+    let invoiceType = [{
+      id: 1,
+      name: '不需要发票'
+    }, {
+      id: 2,
+      name: '增值税普通发票'
+    }, {
+      id: 3,
+      name: '增值税专用发票'
+    }]
     return {
-      selected: false
+      invoiceType,
+      selected: false,
+      selectedTxt: '不需要发票',
+      selectedId: 1,
+      isShowAddress: true
+    }
+  },
+  methods: {
+    handleItem (item) {
+      this.selectedTxt = item.name
+      this.selectedId = item.id
+      this.selected = false
+    },
+    next () {
+      let temp = cloneObj(this.payinfo)
+
+      let invoice = this.selectedId === 2 ? this.invoice2 : this.selectedId === 3 ? this.invoice3 : null
+      console.log(invoice)
+      temp['invoice'] = invoice
+      temp['receiver'] = this.address
+
+      this.$store.commit('PAYINFO', temp)
+      this.$router.push({path: '/paytype'})
     }
+  },
+  mounted () {
+    if (this.address && Object.keys(this.address).length > 0) return
+    this.$store.dispatch('getInfo', {
+      url: '/user/getReceiverInfo',
+      name: 'address'
+    })
   }
 }
 </script>

+ 4 - 0
src/pages/account/manage/confirm/style.scss

@@ -54,6 +54,9 @@
     .address-item{
       background-image: url("https://static.insta360.com/assets/storage/20190615/894e2ec7c04482c8e899c319c5991608/ic_gps@2x.png");
     }
+    .address-con{
+      padding: 16px 0;
+    }
     .bc-item{
       padding: 16px;
       margin: 8px 0;
@@ -125,6 +128,7 @@
         user-select: none;
         height: 48px;
         padding: 0 11px;
+        position: relative;
         .select-txt{
           height: 48px;
           line-height: 48px;

+ 18 - 3
src/pages/account/manage/index.vue

@@ -1,16 +1,31 @@
 <template>
   <div class="manage-layout">
     <div class="m-nav">
-      <span>个人中心</span>
-      <span class="btns">我的优惠</span>
+      <span>{{title}}</span>
+      <span class="btns"></span>
     </div>
     <router-view />
   </div>
 </template>
 
 <script>
+let titleName = {
+  'information': '个人中心',
+  'order': '我的订单',
+  'myscene': '我的场景',
+  'change': '修改密码',
+  'confirm': '确认订单',
+  'submit': '确认订单',
+  'paytype': '确认订单',
+  'payselect': '支付方式',
+  'cart': '购物车'
+}
 export default {
-
+  computed: {
+    title: function () {
+      return titleName[this.$route.name]
+    }
+  }
 }
 </script>
 

+ 162 - 73
src/pages/account/manage/information/index.vue

@@ -2,104 +2,193 @@
   <div class="information-layout">
     <div class="user-con">
       <div class="user-top">
-        <div class="user-img">
-          <img src alt />
+        <div class="user-img" :style="{backgroundImage:`url(${info.head||`${$cdn}images/head-default.png`})`}">
         </div>
         <div class="user-upload">
           <p>上传头像</p>
-          <button type="button" class="ant-btn">
+          <div type="button" class="ant-btn">
+            <input class="el-upload" ref="uploadInput" name="file" type="file" @change="update">
             <span>选择文件</span>
-          </button>
+          </div>
           <p>允许的文件类型为JPG 或 PNG。</p>
         </div>
       </div>
     </div>
     <div class="address-con">
-      <p class="sub-title">我的收货地址</p>
-      <div class="address-input-con">
-        <div class="address-input-item">
-          <div class="address-sub address-name">
-            <div class="top-title">姓名</div>
-            <input class="ant-input" type="text" placeholder="何" />
-          </div>
-          <div class="address-sub address-phone">
-            <div class="top-title">联系电话</div>
-            <input class="ant-input" type="text" placeholder="联系电话" />
+      <p class="sub-title">
+        <span>我的收货地址</span>
+      </p>
+      <div class="address-show" v-if="isShowAddress">
+        <template v-if="address.shipName">
+          <div class="add-info">
+            <div class="show-name">
+              <span>{{address.shipName}}</span>
+              <span>{{address.shipMobile}}</span>
+            </div>
+            <div class="show-address">
+              {{`${address.shipAreaPath}${address.shipAddress}`}}
+            </div>
           </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub prov-name">
-            <div class="top-title">省份</div>
-            <input class="ant-input" type="text" placeholder="省份" />
+          <div class="add-edit" @click="isShowAddress=false">
+            <img :src="`${$cdn}images/icon/edit.png`" alt="">
           </div>
-          <div class="address-sub city-phone">
-            <div class="top-title">城市</div>
-            <input class="ant-input" type="text" placeholder="城市" />
-          </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">地址</div>
-            <input class="ant-input" type="text" style="margin-bottom:8px;" placeholder="区/县" />
-            <input class="ant-input" type="text" placeholder="详细地址" />
+        </template>
+        <template v-else>
+          <div class="add-info">暂无地址信息</div>
+          <div class="add-edit" @click="isShowAddress=false">
+            <img :src="`${$cdn}images/icon/edit.png`" alt="">
           </div>
-        </div>
-        <p class="p-dec">请务必详细填写相符无误的地址以免耽误收货</p>
-        <button type="submit" class="ant-btn ant-btn-primary">
-          <span>保 存</span>
-        </button>
+        </template>
       </div>
+      <citySelect class="address-scon" :address='address' :token="token" @closeSelect="data=>{isShowAddress=data}" v-else/>
     </div>
     <div class="address-con">
       <p class="sub-title">我的发票抬头</p>
-      <div class="address-input-con">
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">抬头名称</div>
-            <input class="ant-input" type="text" placeholder="发票抬头" />
-          </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">税号</div>
-            <input class="ant-input" type="text" placeholder="税务登记号" />
-          </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">地址</div>
-            <input class="ant-input" type="text" placeholder="公司地址" />
+      <div class="invoice-show" v-if="isShowInvoice">
+        <template v-if="invoice2.title||invoice3.title">
+          <div class="add-info">
+            <div class="show-name">
+              <span>{{invoice2.title||invoice3.title}}</span>
+            </div>
+            <div class="show-address">
+              {{invoice2.code}}
+            </div>
           </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">电话号码</div>
-            <input class="ant-input" type="text" placeholder="公司电话号码" />
+          <div class="add-edit" @click="isShowInvoice=false">
+            <img :src="`${$cdn}images/icon/edit.png`" alt="">
           </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">开户银行</div>
-            <input class="ant-input" type="text" placeholder="开户银行" />
-          </div>
-        </div>
-        <div class="address-input-item">
-          <div class="address-sub">
-            <div class="top-title">银行账户</div>
-            <input class="ant-input" type="text" placeholder="银行账户" />
+        </template>
+        <template v-else>
+          <div class="add-info">暂无发票信息</div>
+          <div class="add-edit" @click="isShowInvoice=false">
+            <img :src="`${$cdn}images/icon/edit.png`" alt="">
           </div>
-        </div>
-        <p class="p-dec">如需开具增值税专用发票,需全部填写</p>
-        <button type="submit" class="ant-btn ant-btn-primary">
-          <span>保 存</span>
-        </button>
+        </template>
       </div>
+      <invoices :invoice='invoice2' :invoicet="invoice3" :token="token" @closeInvoice="data=>{isShowInvoice=data}" v-else />
     </div>
   </div>
 </template>
 
 <script>
-export default {}
+import { mapState } from 'vuex'
+import citySelect from '@/components/citySelect'
+import invoices from '@/components/invoices'
+
+export default {
+  components: {
+    citySelect,
+    invoices
+  },
+  computed: {
+    ...mapState({
+      info: state => state.user.info,
+      token: state => state.user.token,
+      invoice2: state => {
+        let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      invoice3: state => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
+        }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+
+        return (condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      address: state => state.user.address || {}
+    })
+  },
+  data () {
+    return {
+      isShowAddress: true,
+      tempSelect: '',
+      isShowInvoice: true
+    }
+  },
+  methods: {
+    getCurrentStatus (data) {
+      this.tempSelect = data
+    },
+    uAddress () {
+      this.address.province = this.tempSelect[0]
+      this.address.city = this.tempSelect[1]
+      this.address.shipAreaPath = this.tempSelect.join(',')
+      let {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      } = this.address
+      let params = {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      }
+      this.$http
+        .post('/user/updateAddress', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          let res = data.data
+          this.addressStatus = true
+          localStorage.setItem('address', JSON.stringify(res.data))
+        })
+    },
+    update (e) {
+      let file = e.target.files[0]
+      let token = this.token
+      let config = {
+        headers: {
+          token
+        }
+      } // 添加请求头
+      var reader = new FileReader()
+      reader.onload = async e => {
+        let imgdata = e.target.result
+        let res = await this.$http.post('/user/uploadHead', { imgdata }, config)
+        if (res.data.code === 0) {
+          this.info.head = res.data.msg
+          localStorage.setItem('info', JSON.stringify(this.info))
+        } else {
+          this.$toast.show('warn', '上传失败,请稍后再试')
+        }
+      }
+      reader.readAsDataURL(file)
+    }
+  },
+  mounted () {
+    this.$store.dispatch('getInfo', {
+      url: '/user/getReceiverInfo',
+      name: 'address'
+    })
+
+    Object.keys(this.invoice2).length === 0 && this.$store.dispatch('getInvoice', {
+      type: 2,
+      params: {
+        invoiceType: 2
+      }
+    })
+    Object.keys(this.invoice3).length === 0 && this.$store.dispatch('getInvoice', {
+      type: 3,
+      params: {
+        invoiceType: 3
+      }
+    })
+  }
+}
 </script>
 
 <style lang="scss" scoped>

+ 65 - 3
src/pages/account/manage/information/style.scss

@@ -1,3 +1,22 @@
+.el-upload {
+  position: absolute;
+  top: 0;
+  left: 0;
+  opacity: 0;
+  line-height: 1;
+  cursor: pointer;
+  height: 100%;
+  z-index: 10;
+  width: 100%;
+  padding: 0;
+  margin: 0;
+  font-size: 0;
+  display: inline-block;
+}
+.cancel{
+  background: #e7e7e7!important;
+  margin-left: 5px;
+}
 .information-layout{
   margin-top: 20px;
   .user-con{
@@ -21,8 +40,8 @@
         height: 100px;
         border-radius: 50px;
         overflow: hidden;
-        background-image: url(https://static.insta360.com/assets/www/project/official/account/avatar_2.png);
-        background-size: 100px;
+        background-size: cover;
+        background-repeat: no-repeat;
         img{
           width: 100%;
           height: 100%;
@@ -41,8 +60,10 @@
         color: #898A8E;
         padding: 8px 0;
       }
-      button{
+      .ant-btn{
         height: 24px;
+        line-height: 24px;
+        position: relative;
         background: #EDEFF2;
         color: #000000;
         letter-spacing: 0.8px;
@@ -61,6 +82,12 @@
       font-weight: 700;
       padding: 13px 16px;
       border-bottom: 1px solid #e9e9e9;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .address-scon{
+      padding: 16px;
     }
     .address-input-con{
       padding: 16px;
@@ -112,5 +139,40 @@
         margin-bottom: 8px;
       }
     }
+    .address-show,.invoice-show{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 18px 16px;
+      margin-bottom: 10px;
+      .add-info{
+        max-width: calc(100% - 40px);
+        .show-name{
+          font-size: 14px;
+          color: #000000;
+          line-height: 20px;
+          margin-bottom: 8px;
+          display: flex;
+          justify-content: space-between;
+          span{
+            overflow-wrap: break-word;
+            width: 100%;
+            flex: 1;
+          }
+        }
+        .show-address{
+          font-size: 10px;
+          color: #898A8E;
+          line-height: 15px;
+          overflow-wrap: break-word;
+          width: 100%;
+        }
+      }
+      .add-edit{
+        img{
+          width: 20px;
+        }
+      }
+    }
   }
 }

+ 111 - 0
src/pages/account/manage/myscene/index.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="scene-layout">
+    <template v-if="total">
+      <div class="items" @click="goto(item.webSite)" v-for="(item,i) in myscene.list" :key="i">
+        <div class="card-img" :style="{backgroundImage: `url(${item.thumb||`${$cdn}images/default.png`})`}"></div>
+        <div class="item-txt">
+          <!-- <p>{{typeArr[item.sceneType]}}</p> -->
+          <p v-html="item.sceneName"></p>
+          <p>拍摄时间:{{item.createTime}}</p>
+          <div class="btm-opr">
+            <div class="btm-left">
+              <img :src="`${$cdn}images/eye.png`" alt>
+              <span>{{item.sceneScheme===4?'Pro':'Lite'}}</span>
+            </div>
+            <div class="btm-right">编辑</div>
+          </div>
+        </div>
+      </div>
+    </template>
+    <div class="scene-nothing" v-else>
+        <img src="@/assets/images/nothing.png" alt="">
+        <div>暂无任何场景,赶紧去拍摄吧。</div>
+      </div>
+    <div class="paging" v-if="total">
+      <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: 10,
+      currentPage: 1,
+      total: 0
+    }
+  },
+  watch: {
+    currentPage () {
+      this.getList()
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      myscene: state => {
+        let type = Object.prototype.toString.call(state.user.myscene)
+        if (type === '[object Object]') {
+          return state.user.myscene
+        }
+        let condition = state.user.myscene && state.user.myscene !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.myscene) : {})
+      }
+    })
+  },
+  mounted () {
+    this.getList()
+  },
+  methods: {
+    goto (url) {
+      location.href = url.replace('http://', 'https://')
+    },
+    async del (item) {
+      this.$toast.showConfirm('warn', '确定要删除当前场景吗?', async () => {
+        let params = {
+          sceneId: item.id
+        }
+        let res = await this.$http({
+          method: 'post',
+          data: params,
+          headers: {
+            token: this.token
+          },
+          url: '/user/scene/delete'
+        })
+        let data = res.data
+        if (data.code === 0) {
+          return this.$toast.show('warn', '删除成功', () => {
+            this.getList()
+          })
+        }
+        return this.$toast.show('error', '删除失败')
+      })
+    },
+    pageChange (data) {
+      this.currentPage = data
+    },
+    async getList () {
+      document.querySelector('#app').scrollTo(0, 0)
+
+      let params = {
+        pageNum: this.currentPage,
+        pageSize: this.pageSize
+      }
+      await this.$store.dispatch('getUserScene', params)
+      console.log()
+      this.pageSize = this.myscene.pageSize
+      this.total = this.myscene.total || 0
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 121 - 0
src/pages/account/manage/myscene/style.scss

@@ -0,0 +1,121 @@
+.expreeNum{
+  text-align: right;
+  display: block;
+  padding: 10px 24px;
+  border-top: 1px solid #e9e9e9;
+}
+.scene-nothing{
+  text-align: center;
+  padding-bottom:30px;
+  img{
+    padding-bottom: 22px;
+  }
+  div{
+    font-size: 16px;
+    color: #969696;
+  }
+}
+.scene-layout{
+  margin-top: 20px;
+  .items{
+    display: flex;
+    background-color: #fff;
+    border-bottom: 1px solid rgba(204, 204, 204, 0.4);
+    &:last-of-type{
+      border-bottom: none;
+    }
+    .card-img{
+      width: 138px;
+      min-width: 138px;
+      height: 121px;
+      cursor: pointer;
+      background-position: center;
+      background-size: auto 100%;
+    }
+    .item-txt{
+      display: flex;
+      flex-direction: column;
+      color: #101010;
+      justify-content: center;
+      width: 100%;
+      padding: 0 10px 0 15px;
+      .btm-opr{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-top: 10px;
+        .btm-left{
+          vertical-align: middle;
+          img{
+            width: 20%;
+            vertical-align: middle;
+          }
+          span{
+            vertical-align: middle;
+            color: #2d2d2d;
+          }
+        }
+        .btm-right{
+          background: #fff;
+          border: 1px solid #777777;
+          border-radius: 6px;
+          padding: 4px 8px;
+        }
+      }
+      p{
+        line-height: 1.5;
+        font-weight: normal;
+        font-size: 14px;
+        color: #777777;
+        &:first-child{
+          font-size: 16px;
+          color: #2d2d2d;
+          font-weight: normal;
+          font-weight: bold;
+        }
+      }
+    }
+  }
+  .paging {
+    // border-left: #e5e5e5 1px solid;
+    height: 100%;
+    padding-bottom: 20px;
+    & /deep/ .layout {
+      text-align: center;
+      margin-top: 20px;
+    }
+    & /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: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;
+    }
+  }
+}

+ 170 - 19
src/pages/account/manage/order/index.vue

@@ -1,37 +1,188 @@
 <template>
   <div class="order-layout">
     <div>
-      <div class="order-item" v-for="(item,i) in 3" :key="i">
-        <div class="o-header">
-          <div class="o-title">INS5CD1906260931C8B</div>
-        </div>
-        <div class="o-con">
-          <div class="oc-left">
-            <img src="@/assets/images/banner_pro.png" alt="">
-            <div class="oc-name">
-              4DKanKan Pro<br/>套餐
+      <template  v-if="total">
+        <div class="order-item" v-for="(item,i) in myorder.list" :key="i">
+          <div class="o-header">
+            <div class="o-title">{{item.orderSn}}</div>
+          </div>
+          <div class="o-con" v-for="(sub,index) in item.orderItems" :key="index">
+            <div class="oc-left">
+              <img :src="sub.pic" alt="">
+              <div class="oc-name">
+                {{sub.goodsName}}<br/>
+                {{sub.description}}
+              </div>
+            </div>
+            <div class="oc-right">
+                <div>CNY ¥{{sub.goodsPrice}}</div>
+                <div>x{{sub.goodsCount}}</div>
             </div>
           </div>
-          <div class="oc-right">
-              <div>CNY ¥69</div>
-              <div>x1</div>
+          <div class="o-price">
+            <span>总价:&nbsp;&nbsp;CNY ¥{{item.goodsAmount}}</span>
+          </div>
+          <div class="to-pay">
+            <template v-if="getStatus(item) === 'unpaid'">
+              <div class="o-button">
+                <span class="cancel"  @click="cancal(item)">取消订单</span>
+                <span class="pay" @click="goPay(item)">立即付款</span>
+              </div>
+            </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="o-price">
-          <span>总价:&nbsp;&nbsp;CNY ¥69</span>
-        </div>
-        <div class="o-button">
-          <span class="cancel">取消订单</span>
-          <span class="pay">立即付款</span>
-        </div>
+      </template>
+      <div class="scene-nothing" v-else>
+        <img src="@/assets/images/nothing.png" alt="">
+        <div>暂无任何订单,赶紧去购买吧。</div>
+      </div>
+      <div class="paging" v-if="total">
+        <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize"/>
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+import Paging from '@/components/Paging'
+
 export default {
+  components: { Paging },
+  data () {
+    return {
+      pageSize: 5,
+      currentPage: 1,
+      total: 0
+    }
+  },
+  watch: {
+    currentPage () {
+      this.getList()
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      myorder: state => {
+        let type = Object.prototype.toString.call(state.user.myorder)
+        if (type === '[object Object]') {
+          return state.user.myorder
+        }
+        let condition = state.user.myorder && state.user.myorder !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.myorder) : {}
+      }
+    })
+  },
+  mounted () {
+    this.getList()
+  },
+  methods: {
+    pageChange (data) {
+      this.currentPage = data
+    },
+    async getList () {
+      document.querySelector('#app').scrollTo(0, 0)
+      let params = {
+        type: '',
+        pageNum: this.currentPage,
+        pageSize: this.pageSize
+      }
+      await this.$store.dispatch('getUserOrder', params)
+      this.pageSize = this.myorder.pageSize
+      this.total = this.myorder.total || 0
+    },
+    getStatus (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
+    },
+    goPay (item) {
+      this.$store.commit('ORDERINFO', {
+        orderSn: item.orderSn,
+        price: item.goodsAmount
+      })
+      this.$router.push({
+        name: 'payselect',
+        params: {
+          orderId: item.id || 1,
+          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', '删除失败')
+      })
+    }
+  }
 }
 </script>
 

+ 60 - 0
src/pages/account/manage/order/style.scss

@@ -1,3 +1,20 @@
+.expreeNum{
+  text-align: right;
+  display: block;
+  padding: 10px 24px;
+  border-top: 1px solid #e9e9e9;
+}
+.scene-nothing{
+  text-align: center;
+  padding-bottom:30px;
+  img{
+    padding-bottom: 22px;
+  }
+  div{
+    font-size: 16px;
+    color: #969696;
+  }
+}
 .order-layout{
   margin-top: 20px;
   .order-item{
@@ -35,6 +52,7 @@
       }
       .oc-right{
         text-align: right;
+        min-width: 85px;
       }
     }
     .o-price{
@@ -70,4 +88,46 @@
       }
     }
   }
+  .paging {
+    // border-left: #e5e5e5 1px solid;
+    height: 100%;
+    padding-bottom: 20px;
+    & /deep/ .layout {
+      text-align: center;
+      margin-top: 20px;
+    }
+    & /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: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;
+    }
+  }
 }

+ 97 - 0
src/pages/account/manage/payselect/index.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="paytype-layout">
+    <div class="paytype">
+      <div class="pay-item" v-for="(item,i) in data" :key="i" @click="goPay(item)">
+        <span>{{item.name}}</span>
+        <img :src="item.img" alt="">
+        <form v-if="item.name === 'PayPal'" id="formid1" class="form-con" :action="`${$serverName}api/order/pay/paypalH5`" method="post">
+            <input  v-model="$route.params.orderId" type="text" name='orderId'>
+            <input  v-model="$route.params.orderType" type="text" name='orderType'>
+            <input type="submit" value="提交">
+        </form>
+      </div>
+    </div>
+    <div class="btn-back" @click="$router.replace({path:'/order'})">返回</div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import browser from '@/util/browser'
+
+let PAYS = {
+  0: 'wechatMobilePay',
+  1: 'aliMobilePay',
+  2: 'paypal'
+}
+
+export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token || ''
+    })
+  },
+  data () {
+    let data = [{
+      name: '支付宝',
+      img: this.$cdn + `images/ic_alipay_mb@2x.png`,
+      id: 1
+    }, {
+      id: 0,
+      name: '微信支付',
+      img: this.$cdn + `images/ic_weixin@2x.png`
+    }, {
+      id: 2,
+      name: 'PayPal',
+      img: this.$cdn + `images/paypal.png`
+    }]
+    let weichtdata = [{
+      id: 0,
+      name: '微信支付',
+      img: this.$cdn + `images/ic_weixin@2x.png`
+    }, {
+      id: 2,
+      name: 'PayPal',
+      img: this.$cdn + `images/paypal.png`
+    }]
+    return {
+      data: browser.weixin ? weichtdata : data,
+      isWeixin: browser.weixin
+    }
+  },
+  mounted () {
+  },
+  methods: {
+    async goPay (item) {
+      let {orderId, orderType} = this.$route.params
+      let params = {
+        orderId: orderId,
+        orderType: Number(orderType)
+      }
+      if (this.isWeixin) {
+        return location.replace(`https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri=http%3a%2f%2fpro.4dkankan.com%2fapi%2forder%2fpay%2fwechatPreJsPay%3forderId=${orderId}&appid=wx779dbafb46bab697&response_type=code&scope=snsapi_base&state=1&connect_redirect=1#wechat_redirect`)
+      }
+
+      if (PAYS[item.id] !== 'paypal') {
+        let response = await this.$http
+          .post(`/order/pay/${PAYS[item.id]}`, params, {
+            headers: {
+              token: this.token
+            }
+          })
+        if (response.data.code !== 0) {
+          return this.$toast.show('warn', '支付失败,请稍后再试')
+        }
+        let url = item.id === 1 ? response.data.data.form : response.data.data.mweb_url
+        location.replace(url)
+      } else {
+        this.$toast.show('warn', '正在跳转至paypal支付链接,请稍等')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 58 - 0
src/pages/account/manage/payselect/style.scss

@@ -0,0 +1,58 @@
+.paytype-layout{
+  .paytype{
+    background: #fff;
+    padding: 0 16px 24px;
+    margin: 8px 0;
+  }
+  .pay-item{
+    height: 56px;
+    padding: 17px 0;
+    border-bottom: 1px solid #e6e6e6;
+    background-position: 100%;
+    background-repeat: no-repeat;
+    background-image: url("~@/assets/images/ic_right@2x.png");
+    background-size: 16px;
+    position: relative;
+    .form-con{
+      opacity: 0;
+      input[type='text']{
+        width: 1px;
+        height: 1px;
+        position: absolute;
+        top: 0;
+        left: 0;
+      }
+       input[type='submit']{
+         width: 100%;
+         position: absolute;
+         top: 0;
+         left: 0;
+         height: 100%;
+       }
+    }
+    span{
+      font-size: 12px;
+      color: rgba(0,0,0,.7);
+      float: left;
+      font-weight: 600;
+    }
+    img{
+      width: 96px;
+      float: right;
+      margin-right: 32px;
+      margin-top: -7px;
+    }
+  }
+  .btn-back{
+    height: 48px;
+    display: inline-block;
+    line-height: 48px;
+    text-align: center;
+    font-size: 14px;
+    color: #1fe4dc;
+    border-radius: 2px;
+    width: 100%;
+    background-color: #fff;
+    margin: 16px 0 30px;
+  }
+}

+ 50 - 13
src/pages/account/manage/paytype/index.vue

@@ -23,30 +23,67 @@
       <div class="pay-header">
         支付方式
       </div>
-      <div class="pay-item" v-for="(item,i) in data" :key="i">
+      <div class="pay-item" v-for="(item,i) in data" :key="i" @click="goPay(item)">
         <span>{{item.name}}</span>
         <img :src="item.img" alt="">
       </div>
     </div>
-    <div class="btn-back">返回</div>
+    <div class="btn-back" @click="$router.push({path:'/confirm'})">返回</div>
   </div>
 </template>
 
 <script>
-let data = [{
-  name: '支付宝',
-  img: require('@/assets/images/ic_alipay_mb@2x.png')
-}, {
-  name: '微信支付',
-  img: require('@/assets/images/ic_weixin@2x.png')
-}, {
-  name: 'PayPal',
-  img: require('@/assets/images/payPal.png')
-}]
+import { mapState } from 'vuex'
+import browser from '@/util/browser'
+
 export default {
+  computed: {
+    ...mapState({
+      payinfo: state => {
+        let type = Object.prototype.toString.call(state.user.payinfo)
+        if (type === '[object Object]') {
+          return state.user.payinfo
+        }
+        let condition = state.user.payinfo && state.user.payinfo !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.payinfo) : {}
+      }
+    })
+  },
   data () {
+    let data = [{
+      name: '支付宝',
+      img: this.$cdn + `images/ic_alipay_mb@2x.png`,
+      id: 1
+    }, {
+      id: 0,
+      name: '微信支付',
+      img: this.$cdn + `images/ic_weixin@2x.png`
+    }, {
+      id: 2,
+      name: 'PayPal',
+      img: this.$cdn + `images/paypal.png`
+    }]
+    let weichatdata = [{
+      id: 0,
+      name: '微信支付',
+      img: this.$cdn + `images/ic_weixin@2x.png`
+    }, {
+      id: 2,
+      name: 'PayPal',
+      img: this.$cdn + `images/paypal.png`
+    }]
     return {
-      data
+      data: browser.weixin ? weichatdata : data
+    }
+  },
+  methods: {
+    goPay (item) {
+      let temp = this.payinfo
+      temp['payType'] = item.id
+      temp['payTypeName'] = item.name
+
+      this.$store.commit('PAYINFO', temp)
+      this.$router.push({path: '/submit'})
     }
   }
 }

+ 120 - 21
src/pages/account/manage/submit/index.vue

@@ -1,21 +1,26 @@
 <template>
   <div class="submit-layout">
+    <form id="formid" class="form-con" :action="`${$serverName}api/order/pay/paypalH5`" method="post">
+        <input v-model="orderId" type="text" name='orderId'>
+        <input v-model="orderType" type="text" name='orderType'>
+        <input type="submit" value="提交">
+    </form>
     <div class="time-line">
       <div class="line"></div>
       <div class="auth">
-        <img src="@/assets/images/hasLogin.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/hasLogin.png`"  alt="" class="timeline-icon">
         <div class="timeline-text">登录信息</div>
       </div>
       <div class="shipping">
-        <img src="@/assets/images/hasLogin.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/hasLogin.png`" alt="" class="timeline-icon">
         <div class="timeline-text">配送信息</div>
       </div>
       <div class="payment">
-        <img src="@/assets/images/hasLogin.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/hasLogin.png`" alt="" class="timeline-icon">
         <div class="timeline-text">支付信息</div>
         </div>
       <div class="review">
-        <img src="@/assets/images/spot.png" alt="" class="timeline-icon">
+        <img :src="`${$cdn}images/spot.png`" alt="" class="timeline-icon">
         <div class="timeline-text">订单提交</div>
       </div>
     </div>
@@ -24,11 +29,11 @@
       <div class="bc-item">
         <div class="bc-ct">
           <div class="bc-contact">
-            陈志广
-            <div>13211064273</div>
+            {{payinfo.receiver.shipName}}
+            <div>{{payinfo.receiver.shipMobile}}</div>
           </div>
           <div class="bc-locotion">
-            中国大陆,广西,贵港,广西贵港市农业科学研究所内广西贵港市农业科学研究所内。537100
+            {{payinfo.receiver.shipAreaPath}}{{payinfo.receiver.shipAddress}}
           </div>
         </div>
         <div class="bc-express">顺丰速运</div>
@@ -37,39 +42,41 @@
     <div class="box-con">
       <div class="bc-title">
         <span>支付信息</span>
-        <span>修改</span>
+        <span @click="$router.back()">修改</span>
       </div>
       <div class="bc-item pay-item">
-        <div class="item-method">支付宝</div>
+        <div class="item-method">{{payinfo.payTypeName}}</div>
         <div class="item-time">提交订单后,请您在新打开的页面完成支付</div>
       </div>
     </div>
     <div class="box-con">
       <div class="bc-title">订单概览</div>
       <div class="confirm-products">
-        <div class="confirm-products-item" v-for="(item,i) in 2" :key="i">
+        <div class="confirm-products-item" v-for="(item,i) in payinfo.goods" :key="i">
           <div class="product-thumb">
-            <img  src="@/assets/images/banner_pro.png" alt="">
+            <img :src="item.goodsId===4?`${$cdn}images/banner_pro.png`:`${$cdn}images/t_product.png`" alt="">
           </div>
           <div class="product-info">
-            <div class="product-name">Insta360ONEX</div>
-            <div class="product-name">Vlog套餐</div>
+            <div class="product-name">
+                <img class="img-txt" :src="item.goodsId===4?`${$cdn}images/download-pro.png`:`${$cdn}images/download-lite.png`" alt="">
+            </div>
+            <div class="product-name">标准套餐</div>
             <div class="product-count">
-              <span class="product-price">CNY ¥2865 x 1</span>
-              <span class="product-sum">CNY ¥2865</span>
+              <span class="product-price">CNY ¥{{item.price}} x {{item.goodsCount}}</span>
+              <span class="product-sum">CNY ¥{{item.price}}</span>
             </div>
           </div>
         </div>
         <div class="cart-table-count">
           <div class="cart-table-count-item">
             <span class="title">商品总价:</span>
-            <span class="price">CNY ¥102753</span>
+            <span class="price">CNY ¥{{getSum()[1]}}</span>
           </div>
           <div class="cart-table-count-item">
             <span class="title">税费及其他费用:</span>
             <span class="price">
               <span class="free-shipping">
-                <img src="@/assets/images/free@2x.png" alt="" class="free-shipping-img">
+                <img :src="`${$cdn}images/free@2x.png`" alt="" class="free-shipping-img">
                 <span class="free-shipping-text">包含</span>
               </span>
             </span>
@@ -78,27 +85,119 @@
             <span class="title">运费:</span>
             <span class="price">
               <span class="free-shipping">
-                <img src="@/assets/images/free@2x.png" alt="" class="free-shipping-img">
+                <img :src="`${$cdn}images/free@2x.png`" alt="" class="free-shipping-img">
                 <span class="free-shipping-text">免费</span>
               </span>
             </span>
           </div>
          <div class="cart-table-total cart-table-count-item">
            <span class="total-title">合计:</span>
-           <span class="total-price">CNY ¥102753</span>
+           <span class="total-price">CNY ¥{{getSum()[1]}}</span>
           </div>
         </div>
       </div>
     </div>
-    <div class="btn-submit">提交订单</div>
+    <div class="btn-submit" @click="pay">提交订单</div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+import browser from '@/util/browser'
+
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+
+let paytypes = {
+  0: 'wechatMobilePay',
+  1: 'aliMobilePay'
+}
 export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token || '',
+      payinfo: state => {
+        let type = Object.prototype.toString.call(state.user.payinfo)
+        if (type === '[object Object]') {
+          return state.user.payinfo
+        }
+        let condition = state.user.payinfo && state.user.payinfo !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.payinfo) : {}
+      }
+    })
+  },
   data () {
     return {
-      selected: false
+      selected: false,
+      isWeixin: browser.weixin,
+      orderId: '',
+      orderType: 0
+    }
+  },
+  methods: {
+    async pay () {
+      let {invoice, goods, payType, receiver} = this.payinfo
+      let params = {
+        goods,
+        receiver,
+        invoice,
+        payType
+      }
+      let res = await this.$http
+        .post('user/order/placeOrder', params, {
+          headers: {
+            token: this.token
+          }
+        })
+
+      this.$store.commit('ORDERINFO', {
+        orderSn: res.data.data.orderSn,
+        price: res.data.data.goodsAmount
+      })
+      this.$store.dispatch('getCart')
+      let data = {
+        orderId: res.data.data.id,
+        orderType: 0
+      }
+
+      this.orderId = res.data.data.id
+      this.orderType = 0
+
+      if (this.isWeixin) {
+        return location.replace(`https://open.weixin.qq.com/connect/oauth2/authorize?redirect_uri=http%3a%2f%2fpro.4dkankan.com%2fapi%2forder%2fpay%2fwechatPreJsPay%3forderId=${this.orderId}&appid=wx779dbafb46bab697&response_type=code&scope=snsapi_base&state=1&connect_redirect=1#wechat_redirect`)
+      }
+      if (Number(payType) !== 2) {
+        let response = await this.$http
+          .post(`order/pay/${paytypes[payType]}`, data, {
+            headers: {
+              token: this.token
+            }
+          })
+        let url = payType === 1 ? response.data.data.form : response.data.data.mweb_url
+        location.replace(url)
+      } else {
+        document.getElementById('formid').submit()
+        this.$toast.show('warn', '正在跳转至paypal支付链接,请稍等')
+      }
+    },
+
+    getSum () {
+      let sum = 0
+      let count = 0
+      this.payinfo.goods.forEach(item => {
+        sum += item.goodsCount * item.price
+        count += item.goodsCount
+      })
+      return [count, sum]
     }
   }
 }

+ 10 - 1
src/pages/account/manage/submit/style.scss

@@ -1,4 +1,10 @@
 .submit-layout{
+  .form-con{
+    opacity: 0;
+    height: 1px;
+    width: 1px;
+    overflow: hidden;
+  }
   .time-line{
     height: 46px;
     padding-top: 12px;
@@ -57,7 +63,7 @@
       margin: 8px 0;
       position: relative;
       .bc-ct{
-        margin-right: 50px;
+        padding-right: 50px;
         border-bottom: 1px solid #f2f2f2;
         padding-bottom: 8px;
         .bc-contact{
@@ -121,6 +127,9 @@
           line-height: 1.5;
           .product-name{
             font-size: 12px;
+            .img-txt{
+              width: 90px;
+            }
           }
           .product-count{
             display: flex;

+ 73 - 15
src/pages/account/register/index.vue

@@ -1,39 +1,40 @@
 <template>
   <div class="register-layout">
     <div class="banner">
-      <img  src="@/assets/images/icon/register.png" alt="">
+      <img :src="`${$cdn}images/icon/register.png`" alt="">
       <p>立刻注册吧!</p>
     </div>
     <div class="r-line"></div>
     <div class="login-con">
       <div class="input-con" :class="{inputActive:inputActive==='nickname'}">
-        <img src="@/assets/images/icon/icon-user@2x.png" alt="">
-        <input @focus="inputActive='nickname'" @blur="inputActive=''" type="text" placeholder="昵称">
+        <img :src="`${$cdn}images/icon/icon-user@2x.png`" alt="">
+        <input oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' v-model="nickname" @focus="inputActive='nickname'" @blur="blurHandle" type="text" placeholder="昵称">
       </div>
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
-        <img src="@/assets/images/icon/icon-phone@2x.png" alt="">
-        <input @focus="inputActive='phone'" @blur="inputActive=''" type="text" placeholder="手机">
+        <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
+        <input v-model="phone" @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
       </div>
       <div class="code-con">
         <div class="input-con" :class="{inputActive:inputActive==='code'}">
-          <img src="@/assets/images/icon/icon-code@2x.png" style="width:23px;" alt="">
-          <input @focus="inputActive='code'" @blur="inputActive=''" style="padding-left:6px;" type="text" placeholder="输入验证码">
+          <img :src="`${$cdn}images/icon/icon-code@2x.png`" style="width:23px;" alt="">
+          <input v-model="authCode" @focus="inputActive='code'" @blur="blurHandle" style="padding-left:6px;" type="text" placeholder="输入验证码">
         </div>
-        <div class="btns">获取验证码</div>
+        <div v-if="!jishi" class="btns" @click="getAuthCode">获取验证码</div>
+        <span class="btns" v-else>{{interTime}}s后重新发送</span>
       </div>
       <div class="input-con"  :class="{inputActive:inputActive==='password'}">
-        <img src="@/assets/images/icon/icon-password@2x.png" alt="">
-        <input @focus="inputActive='password'" @blur="inputActive=''" type="password" placeholder="密码">
+        <img :src="`${$cdn}images/icon/icon-password@2x.png`" alt="">
+        <input v-model="password" @focus="inputActive='password'" @blur="blurHandle" type="password" placeholder="密码">
       </div>
       <div class="input-con"  :class="{inputActive:inputActive==='confirm'}">
-        <img src="@/assets/images/icon/icon-confirm@2x.png" alt="">
-        <input @focus="inputActive='confirm'" @blur="inputActive=''" type="password" placeholder="再次输入密码">
+        <img :src="`${$cdn}images/icon/icon-confirm@2x.png`" alt="">
+        <input v-model="confirmPass" @focus="inputActive='confirm'" @blur="blurHandle" type="password" placeholder="再次输入密码">
       </div>
       <div class="agree">
-        <input type="checkbox">
+        <input type="checkbox" v-model="isAgree">
         同意四维看看条款
       </div>
-      <div class="btns">注册</div>
+      <div class="btns"  @click="submit">注册</div>
       <div class="to-login">
         <div class="lo-con">
           已经注册账号,
@@ -48,7 +49,64 @@
 export default {
   data () {
     return {
-      inputActive: ''
+      nickname: '',
+      phone: '',
+      authCode: '',
+      password: '',
+      confirmPass: '',
+      interTime: 60,
+      jishi: false,
+      interl: null,
+      isAgree: true
+    }
+  },
+  methods: {
+    blurHandle () {
+      this.inputActive = ''
+      document.querySelector('#app').style.height = 'auto'
+      setTimeout(() => {
+        document.querySelector('#app').style.height = '100%'
+      }, 20)
+    },
+    async getAuthCode () {
+      await this.$store.dispatch('getAuthCode', this.phone)
+      this.interl && clearInterval(this.interl)
+      this.interl = null
+      this.jishi = true
+      this.interl = setInterval(() => {
+        this.interTime--
+        if (this.interTime <= 0) {
+          this.jishi = false
+          this.interTime = 60
+          clearInterval(this.interl)
+          this.interl = null
+        }
+      }, 1000)
+    },
+    async submit () {
+      if (!this.isAgree) {
+        return this.$toast.show('warn', '请查阅并同意四维看看条款')
+      }
+      let params = {
+        password: this.password,
+        phoneNum: this.phone,
+        msgAuthCode: this.authCode,
+        nickName: this.nickname,
+        country: '中国',
+        confirmPwd: this.confirmPass
+      }
+      let res = await this.$http({
+        method: 'post',
+        data: params,
+        url: '/sso/user/register'
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', response.msg)
+      }
+      this.$toast.show('warn', '注册成功', () => {
+        this.$router.push({path: '/login'})
+      })
     }
   }
 }

+ 8 - 8
src/pages/binocular/index.vue

@@ -2,11 +2,11 @@
   <div class="binocular-layout">
     <div class="mobile1">
       <div class="top">
-        <img class="top-bg" src="@/assets/images/mtwo-bg.png" alt>
+        <img class="top-bg" :src="`${$cdn}images/mtwo-bg.png`" alt>
         <div class="m1-con">
-          <img class="pro-logo" :src="language==='en'?require('@/assets/images/lite-logo1-en.png'):require('@/assets/images/lite-logo1.png')" alt="">
+          <img class="pro-logo" :src="language==='en'?`${$cdn}images/lite-logo1-en.png`:`${$cdn}images/lite-logo1.png`" alt="">
           <p class="b-text2">{{langBinocular.introduce.price}}</p>
-          <img class="m1-img" src="@/assets/images/t_product.png" alt>
+          <img class="m1-img" :src="`${$cdn}images/t_product.png`" alt>
         </div>
       </div>
       <div class="bottom">
@@ -23,17 +23,17 @@
       <div class="top">
         <h2 class="b-text2">{{langBinocular.guide[0].title[0]}}</h2>
         <div class="b-text3" v-html="langBinocular.guide[0].title[1]"></div>
-        <img class="f-img" src="@/assets/images/bigscene.gif" alt>
+        <img class="f-img" :src="`${$cdn}images/bigscene.gif`" alt>
       </div>
       <div class="bottom">
         <h2 class="b-text2">{{langBinocular.guide[1].title[0]}}</h2>
         <div class="b-text3" v-html="langBinocular.guide[1].title[1]"></div>
-        <img class="middle-img fk-img" :src="language === 'en'? require('@/assets/images/mtwo-fk-en.png'):require('@/assets/images/mtwo-fk.png')" alt>
+        <img class="middle-img fk-img" :src="language === 'en'? `${$cdn}images/mtwo-fk-en.png`:`${$cdn}images/mtwo-fk.png`" alt>
       </div>
       <div class="top">
         <h2  class="b-text2">{{langBinocular.guide[3].title[0]}}</h2>
         <div class="b-text3" v-html="langBinocular.guide[3].title[1]"></div>
-        <img class="middle-img" src="@/assets/images/mtwo-bj.png" alt>
+        <img class="middle-img" :src="`${$cdn}images/mtwo-bj.png`" alt>
       </div>
     </div>
     <div class="mobile3">
@@ -41,11 +41,11 @@
         <h2 class="b-text2">{{langBinocular.technology.title}}</h2>
         <div class="b-text3" v-html="langBinocular.technology.dec"></div>
       </div>
-      <img class="boom" src="@/assets/images/product_img_content_5.png" alt>
+      <img class="boom" :src="`${$cdn}images/product_img_content_5.png`" alt>
     </div>
     <div class="mobile4">
       <h3 class="b-text2">{{langBinocular.parmas.name}}</h3>
-      <img src="@/assets/images/m-product_img_content_6.png" alt>
+      <img :src="`${$cdn}images/m-product_img_content_6.png`" alt>
       <div class="m4-pramas">
         <div v-for="(item,i) in langBinocular.parmas.detail" :key="i">
           <p class="title">{{item.label}}</p>

+ 49 - 46
src/pages/cases/index.vue

@@ -3,7 +3,7 @@
     <div class="nav-hot">
       <div class="nav-type">
         <ul class="type-ul">
-          <li :class="{active:typesActive===item.name}"  v-for="(item,index) in langCases.sort.types" :key="index"  @click="typesActive = item.name">
+          <li :class="{active:typesActive===item.id}"  v-for="(item,index) in langCases.sort.types" :key="index"  @click="$router.push(item.to)">
            <span>{{item.name}}</span>
           </li>
         </ul>
@@ -15,29 +15,22 @@
           </li>
         </ul>
         <div class="line"></div>
-        <div class="select" @click="selectedActive=!selectedActive">
-          {{selected}}
+        <div class="select" ref="mbMenu" @click="selectedActive=!selectedActive">
+          {{langCases.sceneSelected[selected]}}
           <div class="s-sub" :class="{'s-active':selectedActive}">
-            <div v-for="(item,i) in selectArr" :key="i" :class="{'item-active':selected===item.name}" @click="selected = item.name" class="s-item">{{item.name}}</div>
+            <div v-for="(item,i) in langCases.selectType" :key="i" :class="{'item-active':selected===item.name}" @click="selected= item.id" class="s-item">{{item.name}}</div>
           </div>
-          <!-- <select v-model="selected">
-            <option disabled value="">筛选设备</option>
-            <option>全部</option>
-            <option>Lite</option>
-            <option>Pro</option>
-          </select> -->
         </div>
-
       </div>
     </div>
     <div class="cases">
       <div class="item" v-for="(item,index) in scene" :key="index" @click="goto(item.webSite)">
-         <img :src="item.homepic||'https://scene3d.4dage.com/loading/thumb.jpg'" alt>
+         <img :src="item.thumb||`${$cdn}images/default.png`" alt>
          <div class="c-title">
             <span>{{item.sceneName}}</span>
             <div>
-              <img src="@/assets/images/eye.png" alt>
-              <span>Lite</span>
+              <img :src="`${$cdn}images/eye.png`" alt>
+              <span>{{item.sceneScheme===4?'Pro':'Lite'}}</span>
             </div>
          </div>
          <p class="b-text3">作者:{{item.nickName}}</p>
@@ -58,19 +51,11 @@ import vcenter from '@/components/vcenter'
 import {mapState} from 'vuex'
 
 let typeArr = {
-  '房地产': 2,
-  '博物馆': 1,
-  '家居': 5,
+  '房地产': 1,
+  '博物馆': 2,
+  '家居': 3,
   '餐饮': 4,
-  '其他': 0
-}
-
-let typeTotal = {
-  '房地产': 70,
-  '博物馆': 50,
-  '家居': 40,
-  '餐饮': 30,
-  '其他': 150
+  '其他': 5
 }
 
 let selectArr = [{
@@ -80,11 +65,19 @@ let selectArr = [{
 }, {
   name: 'Pro'
 }]
+
+let sceneSTYpe = {
+  '全部': null,
+  '四维看看 Lite': 1,
+  '四维看看 Pro': 4
+}
+
 export default {
   components: {vcenter, Paging},
   computed: {
     ...mapState({
-      langCases: state => state.language.home.cases
+      langCases: state => state.language.home.cases,
+      language: state => state.language.current
     })
   },
   data () {
@@ -101,26 +94,24 @@ export default {
     }
   },
   watch: {
-    '$route.params.id': {
-      deep: true,
-      immediate: true,
-      handler (newVal) {
-        this.currentPage = 1
-        this.typesActive = newVal
-        this.getData()
-      }
-    },
     currentPage () {
       this.getData()
     },
-    sortActive () {
-      this.currentPage = 1
+    selected () {
       this.getData()
     },
-    typesActive (newVal) {
-      this.total = typeTotal[newVal]
+    sortActive () {
       this.currentPage = 1
       this.getData()
+    },
+    '$route.params.id': {
+      deep: true,
+      immediate: true,
+      handler (newVal) {
+        this.currentPage = 1
+        this.typesActive = typeArr[newVal]
+        this.getData()
+      }
     }
   },
   methods: {
@@ -128,24 +119,36 @@ export default {
       this.currentPage = data
     },
     goto (url) {
-      window.open(url.replace('http://', 'https://'), '_blank')
+      location.href = url.replace('http://', 'https://')
     },
     async getData () {
+      document.querySelector('#app').scrollTo(0, 0)
+
       let params = {
-        sceneType: typeArr[this.typesActive],
-        sceneInterest: this.sortActive > 3 ? this.sortActive - 2 : this.sortActive,
-        page: this.currentPage
+        pageSize: this.pageSize,
+        sceneType: this.typesActive,
+        sceneInterest: this.sortActive,
+        pageNum: this.currentPage,
+        sceneScheme: sceneSTYpe[this.selected]
       }
-      window.scrollTo(0, 0)
       let result = await this.$http({
         method: 'post',
         data: params,
         url: '/scene/loadScene'
       })
-      this.scene = result.data
+      let data = result.data.data
+      this.scene = data.list
+      this.total = data.total
     }
   },
   mounted () {
+    document.addEventListener('click', (e) => {
+      if (this.$refs.mbMenu) {
+        if (!this.$refs.mbMenu.contains(e.target)) {
+          this.selectedActive = false
+        }
+      }
+    })
     this.getData()
   }
 }

+ 2 - 2
src/pages/cases/style.scss

@@ -155,10 +155,10 @@
   .paging {
     // border-left: #e5e5e5 1px solid;
     height: 100%;
-    margin-bottom: 40px;
+    margin-bottom: 20px;
     & /deep/ .layout {
       text-align: center;
-      margin-top: 40px;
+      margin-top: 20px;
     }
     & /deep/ .layout a:not(:last-child) {
       margin: 10px 8px;

+ 129 - 0
src/pages/check/index.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="checkBox">
+    <div class="check-tip">
+      <div class="check-content">
+        <h3 class="b-text2" >支付订单</h3>
+        <img :src="`${$cdn}images/weixin-pay.png`" alt />
+        <div class="check-detail">
+          <p>
+            <span >1. 如果已完成支付,请点击</span>
+            <strong >完成支付</strong>
+          </p>
+          <p>
+            <span >2. 如果未打开微信客户端或未完成支付,请点击</span>
+            <strong>稍后支付</strong>
+            <span>返回我的订单页</span>
+          </p>
+        </div>
+      </div>
+      <div class="check-footer">
+        <div class="btn" @click="$router.replace({path:'/order'})">稍后支付</div>
+        <div class="btn" @click="queryOrderStatus">完成支付</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+
+export default {
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      orderinfo: state => {
+        let type = Object.prototype.toString.call(state.user.orderinfo)
+        if (type === '[object Object]') {
+          return state.user.orderinfo
+        }
+        let condition = state.user.orderinfo && state.user.orderinfo !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.orderinfo) : {}
+      }
+    })
+  },
+  methods: {
+    async queryOrderStatus () {
+      let {orderSn} = this.orderinfo
+      if (!orderSn) {
+        return this.$toast.show('error', '获取订单信息失败')
+      }
+      let params = {
+        orderSn,
+        orderType: 0,
+        payType: 0
+      }
+      let res = await this.$http
+        .post('/user/order/queryOrderStatus', params, {
+          headers: {
+            token: this.token
+          }
+        })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', '查询交易失败,请稍后再试')
+      }
+      response.data ? this.$router.replace({
+        name: 'payresult',
+        params: {
+          isSuccess: 'success'
+        }
+      }) : this.$router.replace({
+        name: 'payresult',
+        params: {
+          isSuccess: 'fail'
+        }
+      })
+    }
+  },
+  mounted () {
+
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.checkBox{
+  width: 100%;
+  margin: 10% 0;
+  .check-tip{
+    text-align: center;
+    .check-content{
+      img{
+        width: 15%;
+        margin: 8% auto;
+      }
+    }
+    .check-detail{
+      border-top: 1px solid #ddd;
+      padding-top: 8%;
+      margin:0 5%;
+      text-align: left;
+      p{
+        margin-bottom: 20px;
+        line-height: 1.5;
+        span{
+          color: #999;
+        }
+        strong{
+          font-weight: normal;
+        }
+      }
+    }
+    .check-footer{
+      margin:0 5%;
+      .btn {
+        width: 100%;
+        background: white;
+        border-radius: 3px;
+        height: 45px;
+        line-height: 45px;
+        border: 1px solid #ccc;
+        margin-bottom: 5%;
+        &:last-child{
+          border: 1px solid #333;
+        }
+      }
+    }
+  }
+}
+</style>

+ 11 - 11
src/pages/eight/index.vue

@@ -2,11 +2,11 @@
   <div class="eight-layout">
     <div class="mobile1">
       <div class="top">
-        <img class="top-bg" src="@/assets/images/meight-bg.png" alt>
+        <img class="top-bg" :src="`${$cdn}images/meight-bg.png`" alt>
         <div class="m1-con">
-          <img class="pro-logo" :src="language==='en'?require('@/assets/images/pro-logo1-en.png'):require('@/assets/images/pro-logo1.png')" alt="">
+          <img class="pro-logo" :src="language==='en'?`${$cdn}images/pro-logo1-en.png`:`${$cdn}images/pro-logo1.png`" alt="">
           <p class="b-text2">{{langEight.introduce.price}}</p>
-          <img class="m1-img" src="@/assets/images/banner_pro.png" alt>
+          <img class="m1-img" :src="`${$cdn}images/banner_pro.png`" alt>
         </div>
       </div>
       <div class="bottom">
@@ -24,7 +24,7 @@
         <h2 class="b-text2" v-html="langEight.definition.title"></h2>
         <p class="b-text3" v-html="langEight.definition.top.dec"></p>
         <!-- <phone class="front-img"/> -->
-        <img class="front-img" src="@/assets/images/1.gif" alt>
+        <img class="front-img" :src="`${$cdn}images/1.gif`" alt>
         <p class="b-text1" v-html="langEight.definition.top.intro"></p>
       </div>
     </div>
@@ -33,13 +33,13 @@
         <h3 class="b-text2">{{langEight.hardware[1].title[0]}}</h3>
         <div class="b-text3">{{langEight.hardware[1].title[1]}}</div>
         <!-- <div class="xinpian"></div> -->
-        <img class="m3-img" src="@/assets/images/gif2.gif" alt>
+        <img class="m3-img" :src="`${$cdn}images/gif2.gif`" alt>
       </div>
       <div class="m3-2">
         <h3 class="b-text2" v-html="langEight.hardware[2].title[0]"></h3>
         <div class="b-text3" v-html="langEight.hardware[2].title[1]"></div>
 
-        <img src="@/assets/images/lens.png" alt>
+        <img :src="`${$cdn}images/lens.png`" alt>
       </div>
       <!-- <div class="m3-4">
         <h3 class="b-text2">{{langEight.hardware[4].title[0]}}</h3>
@@ -50,7 +50,7 @@
     <div class="mobile4">
       <div class="m4-1">
         <div class="b-text2">{{langEight.feature.definition.title}}</div>
-        <img src="@/assets/images/eight-gif1.gif" alt="">
+        <img :src="`${$cdn}images/eight-gif1.gif`" alt="">
         <div class="title b-text1">
           <span>{{langEight.feature.definition.case1.lTxt}}</span>
           <span>{{langEight.feature.definition.case1.rTxt}}</span>
@@ -67,11 +67,11 @@
       </div>
       <div class="m4-3">
         <div class="b-text2">{{langEight.feature.manyou.title}}</div>
-        <img src="@/assets/images/liti.gif" alt="">
+        <img :src="`${$cdn}images/liti.gif`" alt="">
       </div>
       <div class="m4-4">
         <div class="b-text2">{{langEight.feature.model.title}}</div>
-        <img src="@/assets/images/eight-gif2.gif" alt="">
+        <img :src="`${$cdn}images/eight-gif2.gif`" alt="">
          <div class="title b-text1">
           <span>{{langEight.feature.model.case2.lTxt}}</span>
           <span>{{langEight.feature.model.case2.rTxt}}</span>
@@ -83,11 +83,11 @@
         <h2 class="b-text2">{{langEight.technology.title}}</h2>
         <div class="b-text3" v-html="langEight.technology.dec"></div>
       </div>
-      <img class="boom" src="@/assets/images/pro-bang.png" alt>
+      <img class="boom" :src="`${$cdn}images/pro-bang.png`" alt>
     </div>
     <div class="mobile6">
       <div class="b-text2">{{langEight.parmas.name}}</div>
-      <img src="@/assets/images/m-product_img_content_8.png" alt>
+      <img :src="`${$cdn}images/m-product_img_content_8.png`" alt>
       <div class="m5-pramas">
         <div v-for="(item,i) in langEight.parmas.detail" :key="i">
           <p class="title">{{item.label}}</p>

+ 13 - 14
src/pages/home/index.vue

@@ -1,22 +1,22 @@
 <template>
   <div class="home-layout">
     <div class="popup-player" v-show="showVideo">
-      <div class="mask" @click="showVideo=false"></div>
+      <div class="mask" @click="()=>{currenVideo='';showVideo=false}"></div>
       <video autoplay controls :src="currenVideo" class="video-fr"></video>
     </div>
     <div class="plate01">
-      <img class="p1_bg" src="@/assets/images/c01.png" alt="">
-      <img class="p1_bg2" :class="{p1_bg2_active:loop===1}" src="@/assets/images/c02.png" alt="">
-      <img class="p1_bg2" :class="{p1_bg2_active:loop===2}" src="@/assets/images/c03.png" alt="">
-      <img class="p1_bg2" :class="{p1_bg2_active:loop===3}" src="@/assets/images/c04.png" alt="">
+      <img class="p1_bg" :src="`${$cdn}images/c01.png`" alt="">
+      <img class="p1_bg2" :class="{p1_bg2_active:loop===1}" :src="`${$cdn}images/c02.png`" alt="">
+      <img class="p1_bg2" :class="{p1_bg2_active:loop===2}" :src="`${$cdn}images/c03.png`" alt="">
+      <img class="p1_bg2" :class="{p1_bg2_active:loop===3}" :src="`${$cdn}images/c04.png`" alt="">
       <div class="bottom">
-        <button @click="broadcast(`${$cdn}video/4dkkPRO_zh.mp4`)" class="btn-player btn" data-role="video-onex-2">
-          <img src="@/assets/images/icon_play_mob.png" alt="">
+        <div @click="broadcast(language==='en'?`${$cdn}video/banner1.mp4`:`${$cdn}video/4dkkPRO_zh.mp4`)" class="btn-player btn">
+          <img :src="`${$cdn}images/icon_play_mob.png`" alt="">
           <span >{{langHome.watch}}</span>
-        </button>
+        </div>
       </div>
       <div class="fdkk-pro">
-        <img :src="language==='en'?require('@/assets/images/w02.png'):require('@/assets/images/w01.png')" alt="">
+        <img :src="language==='en'?`${$cdn}images/w02.png`:`${$cdn}images/w01.png`" alt="">
       </div>
     </div>
     <div class="plate02">
@@ -31,7 +31,7 @@
         <p class="b-text3" v-for="(item,i) in langHome.tech.dec" :key='i' v-html="item"></p>
         <div class="figure-con">
           <figure v-for="(item,i) in langHome.tech.icon" :key="i">
-            <img :src="require(`@/assets/images/hxjs_${i+1}.png`)" alt="">
+            <img :src="`${$cdn}images/hxjs_${i+1}.png`" alt="">
             <figcaption class="b-text1">{{item}}</figcaption>
           </figure>
           <!-- <figure>
@@ -49,7 +49,7 @@
         <p class="b-text2">{{langHome.tech.location.title}}</p>
         <p class="b-text3" v-html="langHome.tech.location.dec"></p>
         <div class="player">
-          <video class="video" controls="controls" playsinline="playsinline" muted="muted" poster="@/assets/images/p-kjdw.png">
+          <video class="video" controls="controls" playsinline="playsinline" muted="muted" :poster="`${$cdn}images/p-kjdw.png`">
             <source :src="`${$cdn}video/kjdw.mp4`" type="video/mp4">
           </video>
         </div>
@@ -59,7 +59,7 @@
         <p class="b-text2">{{langHome.tech.modeling.title}}</p>
         <p class="b-text3" v-html="langHome.tech.modeling.dec"></p>
         <div class="player">
-          <video class="video" controls="controls" playsinline="playsinline" muted="muted" poster="@/assets/images/p-kjzs.png">
+          <video class="video" controls="controls" playsinline="playsinline" muted="muted" :poster="`${$cdn}images/p-kjzs.png`">
             <source :src="`${$cdn}video/item2.mp4`" type="video/mp4">
           </video>
         </div>
@@ -70,7 +70,7 @@
         <p class="b-text3" v-html="langHome.tech.exhibition.dec"></p>
         <div class="div-view">
           <div class="video-view">
-          <img src="@/assets/images/gif003.gif" alt="">
+          <img :src="`${$cdn}images/gif003.gif`" alt="">
           </div>
         </div>
       </div>
@@ -106,7 +106,6 @@ export default {
     ...mapState({
       langHome: state => state.language.home.home,
       language: state => state.language.current
-
     })
   },
   data () {

+ 7 - 4
src/pages/home/style.scss

@@ -84,19 +84,22 @@ $theme-color: #1fe4dc;
       display: flex;
       flex-direction: column;
       align-items: center;
-
       .btn-player {
-        display: flex;
         margin-bottom: 30px;
         padding: 0 14px;
-        align-items: center;
         line-height: 32px;
+        font-size: 0;
         img {
           width: 12px;
-          vertical-align: middle;
           height: 12px;
           line-height: 32px;
           margin-right: 4px;
+          vertical-align: middle;
+        }
+        span{
+          display: inline-block;
+          vertical-align: middle;
+          font-size: 12px;
         }
       }
     }

+ 0 - 0
src/pages/layout/footer.vue


Some files were not shown because too many files changed in this diff