tremble 6 years ago
parent
commit
56601cc586
76 changed files with 8088 additions and 513 deletions
  1. 1 1
      build/webpack.dev.conf.js
  2. BIN
      mobile.zip
  3. 1 0
      package.json
  4. 3 10
      src/App.vue
  5. BIN
      src/assets/images/404.png
  6. BIN
      src/assets/images/banner_pro.png
  7. BIN
      src/assets/images/c01.png
  8. BIN
      src/assets/images/icon-huiyuan.png
  9. BIN
      src/assets/images/pro.png
  10. BIN
      src/assets/images/quhao-jiantou.png
  11. 23 16
      src/components/cinvoices/index.vue
  12. 15 8
      src/components/citySelect/index.vue
  13. 4793 0
      src/components/createInvoice/city.js
  14. 332 0
      src/components/createInvoice/index.vue
  15. 218 0
      src/components/createInvoice/style.scss
  16. 11 6
      src/components/invoices/index.vue
  17. 175 0
      src/components/toast/binding.vue
  18. 7 125
      src/components/toast/index.vue
  19. 125 0
      src/components/toast/style.scss
  20. 6 0
      src/components/toast/toast.js
  21. 47 0
      src/pages/404/index.vue
  22. 186 0
      src/pages/account/country.js
  23. 32 1
      src/pages/account/forget/index.vue
  24. 38 1
      src/pages/account/forget/style.scss
  25. 1 1
      src/pages/account/manage/cart/index.vue
  26. 10 7
      src/pages/account/manage/change/index.vue
  27. 3 0
      src/pages/account/manage/change/style.scss
  28. 6 3
      src/pages/account/manage/confirm/index.vue
  29. 4 0
      src/pages/account/manage/confirm/style.scss
  30. 305 0
      src/pages/account/manage/consumption/index.vue
  31. 308 0
      src/pages/account/manage/device/index.vue
  32. 93 2
      src/pages/account/manage/index.vue
  33. 34 35
      src/pages/account/manage/information/index.vue
  34. 18 7
      src/pages/account/manage/myscene/index.vue
  35. 3 3
      src/pages/account/manage/myscene/style.scss
  36. 130 0
      src/pages/account/manage/openInvoice/index.vue
  37. 1 1
      src/pages/account/manage/order/index.vue
  38. 2 2
      src/pages/account/manage/order/style.scss
  39. 64 0
      src/pages/account/manage/style.scss
  40. 5 2
      src/pages/account/manage/submit/index.vue
  41. 38 4
      src/pages/account/register/index.vue
  42. 38 1
      src/pages/account/register/style.scss
  43. 20 12
      src/pages/cases/index.vue
  44. 11 3
      src/pages/cases/style.scss
  45. 1 1
      src/pages/eight/index.vue
  46. 13 0
      src/pages/introduce/index.vue
  47. 0 0
      src/pages/introduce/style.scss
  48. 57 0
      src/pages/introtow/index.vue
  49. 84 0
      src/pages/introtow/style.scss
  50. 11 3
      src/pages/layout/header.vue
  51. 5 7
      src/pages/layout/style.scss
  52. 1 1
      src/pages/location/index.vue
  53. 1 1
      src/pages/location/style.scss
  54. 12 0
      src/pages/privilege/index.vue
  55. 17 64
      src/pages/purchase/index.vue
  56. 1 0
      src/pages/purchase/style.scss
  57. 17 19
      src/pages/purchasetwo/index.vue
  58. 1 0
      src/pages/purchasetwo/style.scss
  59. 39 0
      src/router/index.js
  60. 1 1
      src/store/language/cn/about.js
  61. 2 6
      src/store/language/cn/binocular.js
  62. 3 3
      src/store/language/cn/coreTech.js
  63. 24 26
      src/store/language/cn/eight.js
  64. 1 1
      src/store/language/cn/home.js
  65. 123 0
      src/store/language/cn/purchase.js
  66. 113 0
      src/store/language/cn/purchasetow.js
  67. 19 23
      src/store/language/en/binocular.js
  68. 2 2
      src/store/language/en/coreTech.js
  69. 26 28
      src/store/language/en/eight.js
  70. 1 1
      src/store/language/en/home.js
  71. 123 0
      src/store/language/en/purchase.js
  72. 113 0
      src/store/language/en/purchasetow.js
  73. 29 25
      src/store/language/home_cn.js
  74. 29 40
      src/store/language/home_en.js
  75. 108 6
      src/store/user.js
  76. 4 4
      src/util/http.js

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

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

BIN
mobile.zip


+ 1 - 0
package.json

@@ -16,6 +16,7 @@
   "dependencies": {
   "dependencies": {
     "axios": "^0.18.0",
     "axios": "^0.18.0",
     "gsap": "^2.1.2",
     "gsap": "^2.1.2",
+    "js-cookie": "^2.2.0",
     "luxy.js": "^0.1.0",
     "luxy.js": "^0.1.0",
     "three": "^0.102.1",
     "three": "^0.102.1",
     "vue": "^2.5.2",
     "vue": "^2.5.2",

+ 3 - 10
src/App.vue

@@ -37,6 +37,7 @@ export default {
     if (!this.isMobile) {
     if (!this.isMobile) {
       location.href = '/'
       location.href = '/'
     }
     }
+    this.$store.dispatch('checkToken')
   },
   },
   components: {
   components: {
     iheader: header,
     iheader: header,
@@ -47,15 +48,7 @@ export default {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 #app {
 #app {
-  position: absolute;
   padding-top: 60px;
   padding-top: 60px;
-  width: 100%;
-  height: 100%;
-  overflow: auto;
-  -webkit-overflow-scrolling: touch;
-  &::-webkit-scrollbar {
-    display: none;
-  }
 }
 }
 
 
 .header{
 .header{
@@ -63,7 +56,7 @@ export default {
   top: 0;
   top: 0;
   left: 0;
   left: 0;
   width: 100%;
   width: 100%;
+  transform: translateY(0);
 }
 }
-.layout{
-}
+
 </style>
 </style>

BIN
src/assets/images/404.png


BIN
src/assets/images/banner_pro.png


BIN
src/assets/images/c01.png


BIN
src/assets/images/icon-huiyuan.png


BIN
src/assets/images/pro.png


BIN
src/assets/images/quhao-jiantou.png


+ 23 - 16
src/components/cinvoices/index.vue

@@ -2,16 +2,16 @@
   <div class="invoices-layout">
   <div class="invoices-layout">
     <div class="address-input-con" v-if="selectedId===3">
     <div class="address-input-con" v-if="selectedId===3">
       <template v-if="isShowInvoice3">
       <template v-if="isShowInvoice3">
-        <template v-if="tempInvoice3.title">
+        <template v-if="invoicet.title">
           <div class="bc-item">
           <div class="bc-item">
             <div class="bc-contact">
             <div class="bc-contact">
-              <span>{{tempInvoice3.title}}</span>
+              <span>{{invoicet.title}}</span>
             </div>
             </div>
-            <div>{{tempInvoice3.code}}</div>
-            <div>{{tempInvoice3.organizedAddress}}</div>
-            <div>{{tempInvoice3.registerPhone}}</div>
-            <div>{{tempInvoice3.bankName}}</div>
-            <div>{{tempInvoice3.bankAccount}}</div>
+            <div>{{invoicet.code}}</div>
+            <div>{{invoicet.organizedAddress}}</div>
+            <div>{{invoicet.registerPhone}}</div>
+            <div>{{invoicet.bankName}}</div>
+            <div>{{invoicet.bankAccount}}</div>
             <div class="bc-edit" @click="isShowInvoice3=false">编辑</div>
             <div class="bc-edit" @click="isShowInvoice3=false">编辑</div>
           </div>
           </div>
         </template>
         </template>
@@ -88,12 +88,12 @@
     </div>
     </div>
     <div class="address-input-con" v-else>
     <div class="address-input-con" v-else>
       <template v-if="isShowInvoice2">
       <template v-if="isShowInvoice2">
-        <template v-if="tempInvoice2.title">
+        <template v-if="invoice.title">
           <div class="bc-item">
           <div class="bc-item">
             <div class="bc-contact">
             <div class="bc-contact">
-              <span>{{tempInvoice2.title}}</span>
+              <span>{{invoice.title}}</span>
             </div>
             </div>
-            <div>{{tempInvoice2.code}}</div>
+            <div>{{invoice.code}}</div>
             <div class="bc-edit" @click="isShowInvoice2=false">编辑</div>
             <div class="bc-edit" @click="isShowInvoice2=false">编辑</div>
           </div>
           </div>
         </template>
         </template>
@@ -141,7 +141,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj
@@ -150,7 +150,6 @@ export default {
   props: ['invoice', 'invoicet', 'token', 'selectedId'],
   props: ['invoice', 'invoicet', 'token', 'selectedId'],
   computed: {
   computed: {
     tempInvoice2: function () {
     tempInvoice2: function () {
-      console.log(cloneObj(this.invoice))
       return cloneObj(this.invoice)
       return cloneObj(this.invoice)
     },
     },
     tempInvoice3: function () {
     tempInvoice3: function () {
@@ -165,12 +164,12 @@ export default {
   },
   },
   methods: {
   methods: {
     blurHandle () {
     blurHandle () {
-      document.querySelector('#app').style.height = 'auto'
-      setTimeout(() => {
-        document.querySelector('#app').style.height = '100%'
-      }, 20)
+
     },
     },
     saveInvoice () {
     saveInvoice () {
+      let isObject = function (obj) {
+        return JSON.stringify(obj) === '{}' ? '' : obj
+      }
       let params = {}
       let params = {}
       if (this.selectedId === 2) {
       if (this.selectedId === 2) {
         params = {
         params = {
@@ -197,6 +196,12 @@ export default {
           bankAccount
           bankAccount
         }
         }
       }
       }
+      let test = Object.keys(params)
+      for (let i = 0; i < test.length; i++) {
+        if (!isObject(params[test[i]])) {
+          return this.$toast.show('warn', '信息填写不完整')
+        }
+      }
 
 
       this.$http
       this.$http
         .post('user/invoice/save', params, {
         .post('user/invoice/save', params, {
@@ -208,6 +213,8 @@ export default {
           let res = data.data
           let res = data.data
           if (res.code !== 0) return
           if (res.code !== 0) return
           this.$emit('closeInvoice', true)
           this.$emit('closeInvoice', true)
+          this.isShowInvoice3 = true
+          this.isShowInvoice2 = true
           let type = this.selectedId === 'geren' ? 2 : 3
           let type = this.selectedId === 'geren' ? 2 : 3
           this.$store.dispatch('getInvoice', {
           this.$store.dispatch('getInvoice', {
             type: type,
             type: type,

+ 15 - 8
src/components/citySelect/index.vue

@@ -5,13 +5,13 @@
         <div class="address-sub address-name">
         <div class="address-sub address-name">
           <div class="top-title">姓名</div>
           <div class="top-title">姓名</div>
           <div class="ant-input">
           <div class="ant-input">
-            <input @blur="blurHandle"  v-model="tempAddress.shipName" type="text" placeholder="姓名" />
+            <input v-model="tempAddress.shipName" type="text" placeholder="姓名" />
           </div>
           </div>
         </div>
         </div>
         <div class="address-sub address-phone">
         <div class="address-sub address-phone">
           <div class="top-title">联系电话</div>
           <div class="top-title">联系电话</div>
           <div class="ant-input">
           <div class="ant-input">
-            <input @blur="blurHandle" v-model="tempAddress.shipMobile" type="text" placeholder="联系电话" />
+            <input v-model="tempAddress.shipMobile" type="text" placeholder="联系电话" />
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -45,7 +45,7 @@
             </ul>
             </ul>
           </div>
           </div>
           <div class="ant-input">
           <div class="ant-input">
-            <input @blur="blurHandle" v-model="tempAddress.shipAddress" type="text" placeholder="详细地址" />
+            <input v-model="tempAddress.shipAddress" type="text" placeholder="详细地址" />
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -69,7 +69,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj
@@ -136,10 +136,6 @@ export default {
   },
   },
   methods: {
   methods: {
     blurHandle () {
     blurHandle () {
-      document.querySelector('#app').style.height = 'auto'
-      setTimeout(() => {
-        document.querySelector('#app').style.height = '100%'
-      }, 20)
     },
     },
     uAddress () {
     uAddress () {
       this.tempAddress.province = this.areaPath[0]
       this.tempAddress.province = this.areaPath[0]
@@ -153,6 +149,11 @@ export default {
         shipMobile,
         shipMobile,
         shipName
         shipName
       } = this.tempAddress
       } = this.tempAddress
+
+      let isObject = function (obj) {
+        return JSON.stringify(obj) === '{}' ? '' : obj
+      }
+
       let params = {
       let params = {
         shipAddress,
         shipAddress,
         shipAreaPath,
         shipAreaPath,
@@ -161,6 +162,12 @@ export default {
         shipMobile,
         shipMobile,
         shipName
         shipName
       }
       }
+      let test = Object.keys(params)
+      for (let i = 0; i < test.length; i++) {
+        if (!isObject(params[test[i]])) {
+          return this.$toast.show('warn', '信息填写不完整')
+        }
+      }
       this.$http
       this.$http
         .post('/user/updateAddress', params, {
         .post('/user/updateAddress', params, {
           headers: {
           headers: {

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


+ 332 - 0
src/components/createInvoice/index.vue

@@ -0,0 +1,332 @@
+<template>
+  <div>
+    <div class="select-layout">
+      <p class="sub-title">
+        <span>发票金额</span>
+      </p>
+      <div class="address-input-con">
+        <div class="address-input-item">
+          <div class="address-sub">
+            <div class="top-title">开票金额</div>
+            <div class="ant-input">
+              <input v-model="amount" oninput="value=Math.max(Number(value.replace(/[^\d]/g,'')),1)"  type="text" placeholder="请输入开票金额" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="select-layout">
+      <p class="sub-title">
+        <span>发票信息</span>
+      </p>
+      <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 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 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 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 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 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 v-model="tempInvoice3.bankAccount" type="text" placeholder="银行账户" />
+            </div>
+          </div>
+        </div>
+      </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 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 v-model="tempInvoice2.code" type="text" placeholder="税务登记号" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="select-layout">
+      <p class="sub-title">
+        <span>收货地址</span>
+      </p>
+      <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 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 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 v-model="tempAddress.shipAddress" type="text" placeholder="详细地址" />
+            </div>
+          </div>
+        </div>
+        <p class="p-dec">请务必详细填写相符无误的地址以免耽误收货</p>
+      </div>
+    </div>
+    <div class="invoice-save">
+      <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="$router.back()">
+        <span>取 消</span>
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import { citylist } from './city'
+let sle = ['prov', 'city', 'dist']
+
+export default {
+  data () {
+    let idArr = ['', '', '']
+
+    return {
+      type: 'geren',
+      amount: '',
+      tempInvoice2: {},
+      tempInvoice3: {},
+      tempAddress: {},
+      citylist,
+      prov: false,
+      city: false,
+      dist: false,
+      currentPID: idArr[0] || 18,
+      currentCID: idArr[1] || 3,
+      currentSID: idArr[2] || 2,
+      areaPath: ''
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token
+    }),
+    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: {
+    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]
+      console.log(this.areaPath)
+    },
+    async saveInvoice () {
+      let params = {}
+      let invoiceType = ''
+      if (this.type === 'geren') {
+        invoiceType = 2
+        let { title = '', code = '' } = this.tempInvoice2
+        params = {
+          invoiceType,
+          title,
+          code
+        }
+      } else {
+        let {
+          title = '',
+          code = '',
+          organizedAddress = '',
+          registerPhone = '',
+          bankName = '',
+          bankAccount = ''
+        } = this.tempInvoice3
+        invoiceType = 3
+        params = {
+          invoiceType,
+          title,
+          code,
+          organizedAddress,
+          registerPhone,
+          bankName,
+          bankAccount
+        }
+      }
+      let {
+        shipName = '',
+        shipMobile = '',
+        shipAddress = ''
+      } = this.tempAddress
+
+      this.tempAddress.shipAreaPath = this.areaPath.join(',')
+      this.tempAddress.amount = Number(this.amount)
+      this.tempAddress.shipName = shipName || ''
+      this.tempAddress.shipMobile = shipMobile || ''
+      this.tempAddress.shipAddress = shipAddress || ''
+
+      let temp = Object.keys(this.tempAddress)
+      temp.forEach(item => {
+        params[item] = this.tempAddress[item] || ''
+      })
+      console.log(params)
+      let arr = Object.keys(params)
+      for (let i = 0; i < arr.length; i++) {
+        if (!params[arr[i]]) {
+          return this.$toast.show('warn', '信息填写不能为空')
+        }
+      }
+
+      params['cameraId'] = ''
+
+      let res = await this.$http.post('/user/invoice/add', params, {
+        headers: {
+          token: this.token
+        }
+      })
+      let response = res.data
+
+      if (response.code === 0) {
+        this.$toast.show('success', '开票成功', () => {
+          this.$router.replace({name: 'consumption'})
+        })
+      } else {
+        return this.$toast.show('warn', response.msg, () => {})
+      }
+    }
+  },
+  mounted () {
+    this.handleChange()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+</style>

+ 218 - 0
src/components/createInvoice/style.scss

@@ -0,0 +1,218 @@
+.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);
+  }
+}
+
+.select-layout{
+  margin-top: 10px;
+  background-color: #fff;
+  .sub-title{
+    font-size: 14px;
+    line-height: 21px;
+    font-weight: 700;
+    padding: 13px 16px;
+    border-bottom: 1px solid #e9e9e9;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+}
+
+
+.address-input-con {
+  font-size: 12px;
+  line-height: 1.5;
+  margin-bottom: 10px;
+  color: rgba(0, 0, 0, 0.65);
+  padding: 16px;
+  .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;
+  }
+}
+.cancel{
+  background: #e7e7e7!important;
+  margin-left: 5px;
+}
+
+.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: " ";
+      }
+    }
+  }
+}
+
+.invoice-header{
+  padding: 18px 16px 0;
+}
+
+.invoice-save{
+  padding: 16px;
+  background-color: #fff;
+}

+ 11 - 6
src/components/invoices/index.vue

@@ -104,7 +104,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj
@@ -113,7 +113,6 @@ export default {
   props: ['invoice', 'invoicet', 'token'],
   props: ['invoice', 'invoicet', 'token'],
   computed: {
   computed: {
     tempInvoice2: function () {
     tempInvoice2: function () {
-      console.log(cloneObj(this.invoice))
       return cloneObj(this.invoice)
       return cloneObj(this.invoice)
     },
     },
     tempInvoice3: function () {
     tempInvoice3: function () {
@@ -127,12 +126,11 @@ export default {
   },
   },
   methods: {
   methods: {
     blurHandle () {
     blurHandle () {
-      document.querySelector('#app').style.height = 'auto'
-      setTimeout(() => {
-        document.querySelector('#app').style.height = '100%'
-      }, 20)
     },
     },
     saveInvoice () {
     saveInvoice () {
+      let isObject = function (obj) {
+        return JSON.stringify(obj) === '{}' ? '' : obj
+      }
       let params = {}
       let params = {}
       if (this.type === 'geren') {
       if (this.type === 'geren') {
         params = {
         params = {
@@ -153,6 +151,13 @@ export default {
         }
         }
       }
       }
 
 
+      let test = Object.keys(params)
+      for (let i = 0; i < test.length; i++) {
+        if (!isObject(params[test[i]])) {
+          return this.$toast.show('warn', '信息填写不完整')
+        }
+      }
+
       this.$http
       this.$http
         .post('user/invoice/save', params, {
         .post('user/invoice/save', params, {
           headers: {
           headers: {

+ 175 - 0
src/components/toast/binding.vue

@@ -0,0 +1,175 @@
+<template>
+  <div
+    class="toast-layout"
+    :style="{background:false?'none':'rgba(0, 0, 0, 0.3)'}"
+    :class="{'toast-active':visible}"
+  >
+    <div class="toast-con bind-con" :style="{minWidth:'320px'}">
+      <div class="t-header ">
+        <span>添加新设备</span>
+        <i class="iconfont icon-cuowu" @click="handleClick"></i>
+      </div>
+      <div class="binding-con">
+        <div class="binding-body" v-if="!bindingSuccess">
+          <div class="b-input">
+            <input :class="{notbing:hasBind}" v-model="SN" placeholder="请输入产品包装盒上的S/N码" type="text">
+          </div>
+          <div class="bind-error">{{hasBind?errorMsg:''}}</div>
+          <div class="bind-info">
+           <p v-for="(item,i) in binginfo" :key="i">{{item}}</p>
+          </div>
+        </div>
+        <div class="binding-success" v-else>
+          <img src="@/assets/images/icon/success.png" alt="">
+          <p>绑定成功</p>
+          <p>{{successName}}</p>
+        </div>
+      </div>
+
+      <div class="bind-btn" >
+        <span v-if="!bindingSuccess" @click="binding">绑定设备</span>
+        <span v-else @click="bindingSuccess=false">继续绑定</span>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+
+let binginfo = [
+  '1、绑定设备后,可进行充值、查看消费记录和解绑等保管操作',
+  '2、同一台设备只能被一个账号绑定,已经被绑定的设备需要解绑才可以被再次绑定',
+  '3、设备被绑定后,设备仍可无需登录个人账号完成上传、编辑和删除场景等操作'
+]
+export default {
+  props: ['visible', 'btype'],
+  data () {
+    return {
+      binginfo,
+      SN: '',
+      hasBind: false,
+      errorMsg: '该序列号已被绑定',
+      bindingSuccess: false,
+      successName: ''
+    }
+  },
+  watch: {
+    SN () {
+      this.hasBind = false
+    }
+  },
+  methods: {
+    handleClick () {
+      this.SN = ''
+      this.$emit('closePoint')
+    },
+    async binding () {
+      if (!this.SN) {
+        this.errorMsg = '序列号不能为空'
+        this.hasBind = true
+        return false
+      }
+      let params = {
+        childName: this.SN,
+        cameraType: this.btype
+      }
+
+      let token = localStorage.getItem('token')
+      let result = await this.$http({
+        method: 'post',
+        data: params,
+        headers: {
+          token
+        },
+        url: '/user/camera/add'
+      })
+      let data = result.data
+      if (data.code === 0) {
+        this.successName = this.SN
+        this.SN = ''
+        this.bindingSuccess = true
+      } else if (data.code === 4010) {
+        this.hasBind = true
+        this.errorMsg = '绑定的相机不存在'
+      } else if (data.code === 6010) {
+        this.hasBind = true
+        this.errorMsg = '该序列号已被绑定'
+      } else {
+        this.hasBind = true
+        this.errorMsg = data.msg
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+$theme-color: #1fe4dc;
+
+.bind-con{
+  .t-header{
+    height: 50px;
+    line-height: 50px;
+    text-align: center;
+    .iconfont{
+      position: absolute;
+      right: 10px;
+    }
+  }
+  .binding-con{
+    text-align: center;
+    .binding-body{
+      .b-input{
+        width: 70%;
+        margin: 0 auto;
+        input{
+          width: 100%;
+          text-align: center;
+          color: #969696;
+          height: 30px;
+          padding: 0 20px 0 10px;
+          line-height: 30px;
+          font-size: 12px;
+          border: solid 1px #e7e7e7;
+        }
+        .notbing{
+          border: 1px solid #ff0000;
+        }
+      }
+      .bind-info{
+        width: 90%;
+        margin: 15px auto;
+        color: #2d2d2d;
+        text-align: left;
+        p{
+          line-height: 1.5;
+        }
+      }
+      .bind-error{
+        color: #ff0000;
+        font-size: 12px;
+        text-align: center;
+        margin-top: 5px;
+      }
+    }
+  }
+
+  .bind-btn{
+    text-align: center;
+    background: #f7f7f7;
+    span{
+      display: inline-block;
+      margin:  0 auto;
+      line-height: 30px;
+      font-size: 14px;
+      padding: 0 10px;
+      margin: 10px 0;
+      background-color: $theme-color;
+      color: #2d2d2d;
+      border-radius: 4px;
+    }
+  }
+}
+</style>

+ 7 - 125
src/components/toast/index.vue

@@ -1,5 +1,6 @@
 <template>
 <template>
   <div>
   <div>
+    <binding :btype="bindingType" :visible='bindingVisible' @closePoint="()=>{bindingVisible = false,emitCallback()}"/>
     <div
     <div
       class="toast-layout"
       class="toast-layout"
       :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
       :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
@@ -39,15 +40,20 @@
 </template>
 </template>
 
 
 <script>
 <script>
+import binding from './binding'
+
 let types = {
 let types = {
   warn: '提示',
   warn: '提示',
   error: '错误',
   error: '错误',
   success: '成功'
   success: '成功'
 }
 }
 export default {
 export default {
+  components: {binding},
   data () {
   data () {
     return {
     return {
+      bindingType: 1,
       visible: false,
       visible: false,
+      bindingVisible: false,
       message: '',
       message: '',
       submsg: '',
       submsg: '',
       type: 'warn',
       type: 'warn',
@@ -75,129 +81,5 @@ export default {
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <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;
-}
+@import './style.scss';
 </style>
 </style>

+ 125 - 0
src/components/toast/style.scss

@@ -0,0 +1,125 @@
+$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;
+}

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

@@ -31,6 +31,12 @@ Toast.install = function (Vue) {
     showLoading: () => {
     showLoading: () => {
       instance.isLoaing = true
       instance.isLoaing = true
     },
     },
+    showBinding: (val, callback) => {
+      instance.bindingVisible = true
+      instance.bindingType = val
+      instance.callback = callback || function () {
+      }
+    },
     show: (type, msg, callback) => {
     show: (type, msg, callback) => {
       instance.img = imgs[type] || require('@/assets/images/icon/success.png')
       instance.img = imgs[type] || require('@/assets/images/icon/success.png')
       instance.message = msg
       instance.message = msg

+ 47 - 0
src/pages/404/index.vue

@@ -0,0 +1,47 @@
+<template>
+  <div class="layout-404">
+    <div class="_404">
+      <img :src="`${$cdn}images/404.png`" alt="">
+      <p>抱歉,您访问的页面出现了错误,请重新加载</p>
+      <div @click="$router.push({name:'home'})">返回首页</div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style lang="scss" scoped>
+.layout-404{
+  position: relative;
+  min-height: 80vh;
+  ._404{
+    top: 50%;
+    left: 50%;
+    position: absolute;
+    transform: translate(-50%,-50%);
+    text-align: center;
+    font-size: 16px;
+    color: #2d2d2d;
+    width: 90%;
+    img{
+      width:100%;
+    }
+    p{
+      margin: 30px 0;
+    }
+    div{
+      border: 1px solid #2d2d2d;
+      border-radius: 8px;
+      width: 120px;
+      line-height: 40px;
+      height: 40px;
+      margin: 0 auto;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 186 - 0
src/pages/account/country.js

@@ -0,0 +1,186 @@
+let selectCall = [
+  ['中国', '+86', 'China'],
+  ['美国', '+1', 'USA'],
+  ['日本', '+81', 'Japan'],
+  ['中国香港', '+852', 'Hong Kong China'],
+  ['中国台湾', '+886', 'Taiwan of China'],
+  ['马来西亚', '+60', 'Malaysia'],
+  ['澳大利亚', '+61', 'Australia'],
+  ['加拿大', '+1', 'Canada'],
+  ['英国', '+44', 'UK'],
+  ['新加坡', '+65', 'Singapore'],
+  ['德国', '+49', 'Germany'],
+  ['俄罗斯', '+7', 'Russia'],
+  ['埃及', '+20', 'Egypt'],
+  ['南非', '+27', 'South Africa'],
+  ['希腊', '+30', 'Greece'],
+  ['荷兰', '+31', 'Holland'],
+  ['比利时', '+32', 'Belgium'],
+  ['法国', '+33', 'France'],
+  ['西班牙', '+34', 'Spain'],
+  ['匈牙利', '+36', 'Hungary'],
+  ['意大利', '+39', 'Italy'],
+  ['罗马尼亚', '+40', 'Romania'],
+  ['瑞士', '+41', 'Switzerland'],
+  ['奥地利', '+43', 'Austria'],
+  ['丹麦', '+45', 'Denmark'],
+  ['瑞典', '+46', 'Rachel Canon'],
+  ['挪威', '+47', 'Norway'],
+  ['波兰', '+48', 'Poland'],
+  ['秘鲁', '+51', 'Peru'],
+  ['墨西哥', '+52', 'Mexico'],
+  ['古巴', '+53', 'Cuba'],
+  ['阿根廷', '+54', 'Argentina'],
+  ['巴西', '+55', 'Brazil'],
+  ['智利', '+56', 'Chile'],
+  ['哥伦比亚', '+57', 'Columbia'],
+  ['委内瑞拉', '+58', 'Venezuela'],
+  ['印度尼西亚', '+62', 'Indonesia'],
+  ['菲律宾', '+63', 'Philippines'],
+  ['新西兰', '+64', 'New Zealand'],
+  ['泰国', '+66', 'Thailand'],
+  ['哈萨克斯坦', '+7', 'Kazakhstan'],
+  ['韩国', '+82', 'Korea'],
+  ['越南', '+84', 'Vietnam'],
+  ['土耳其', '+90', 'Turkey'],
+  ['印度', '+91', 'India'],
+  ['巴基斯坦', '+92', 'BaStan'],
+  ['阿富汗', '+93', 'Afghanistan'],
+  ['斯里兰卡', '+94', 'Sri Lanka'],
+  ['缅甸', '+95', 'Burma'],
+  ['伊朗', '+98', 'Iran'],
+  ['摩洛哥', '+212', 'Morocco'],
+  ['阿尔及利亚', '+213', 'Alger'],
+  ['突尼斯', '+216', 'Tunisian'],
+  ['利比亚', '+218', 'Libyan'],
+  ['冈比亚', '+220', 'Gambian'],
+  ['塞内加尔', '+221', 'Senegalese'],
+  ['马里', '+223', 'Mali'],
+  ['几内亚', '+224', 'Guinean'],
+  ['科特迪瓦', '+225', 'Ketediwa'],
+  ['布基纳法索', '+226', 'Burkina Faso'],
+  ['尼日尔', '+227', 'Niger'],
+  ['多哥', '+228', 'Togo'],
+  ['贝宁', '+229', 'Berlin'],
+  ['毛里求斯', '+230', 'Mauritius'],
+  ['利比里亚', '+231', 'Liberian'],
+  ['塞拉利昂', '+232', 'Sierra Leone'],
+  ['加纳', '+233', 'Ghana'],
+  ['尼日利亚', '+234', 'Nigerian'],
+  ['乍得', '+235', 'Chad'],
+  ['中非共和国', '+236', 'Central African Republic'],
+  ['喀麦隆', '+237', 'Cameroon'],
+  ['圣多美和普林西比', '+239', 'Sao Tome and Principe'],
+  ['加蓬', '+241', 'Gabonese'],
+  ['刚果民主共和国', '+243', 'Congo democratic republic'],
+  ['安哥拉', '+244', 'Angolan'],
+  ['阿森松岛', '+247', 'Ascension Island'],
+  ['塞舌尔', '+248', 'seychelles'],
+  ['苏丹', '+249', 'Sudanese'],
+  ['埃塞俄比亚', '+251', 'Ethiopian'],
+  ['索马里', '+252', 'Somalian'],
+  ['吉布提', '+253', 'Djibouti'],
+  ['肯尼亚', '+254', 'Kenyan'],
+  ['坦桑尼亚', '+255', 'Tanzanian'],
+  ['乌干达', '+256', 'Ugandan'],
+  ['布隆迪', '+257', 'Burundi'],
+  ['莫桑比克', '+258', 'Mozambique'],
+  ['赞比亚', '+260', 'Zambian'],
+  ['马达加斯加', '+261', 'Madagascar'],
+  ['津巴布韦', '+263', 'Zimbabwe'],
+  ['纳米比亚', '+264', 'Namibian'],
+  ['马拉维', '+265', 'Malawi'],
+  ['莱索托', '+266', 'Lesotho'],
+  ['博茨瓦纳', '+267', 'Botswana'],
+  ['斯威士兰', '+268', 'Swaziland'],
+  ['直布罗陀', '+350', 'Gibraltar'],
+  ['葡萄牙', '+351', 'Portuguese'],
+  ['卢森堡', '+352', 'Luxembourg'],
+  ['爱尔兰', '+353', 'Irish'],
+  ['冰岛', '+354', 'Icelandic'],
+  ['阿尔巴尼亚', '+355', 'Albanian'],
+  ['马耳他', '+356', 'Malta'],
+  ['塞浦路斯', '+357', 'Cypriot'],
+  ['芬兰', '+358', 'Finnish'],
+  ['保加利亚', '+359', 'Bulgarian'],
+  ['立陶宛', '+370', 'Lithuania'],
+  ['拉脱维亚', '+371', 'Latvian'],
+  ['爱沙尼亚', '+372', 'Estonian'],
+  ['摩尔多瓦', '+373', 'Moldova'],
+  ['亚美尼亚', '+374', 'Armenian'],
+  ['白俄罗斯', '+375', 'Belorussia'],
+  ['安道尔共和国', '+376', 'Republic of Andorra'],
+  ['摩纳哥', '+377', 'Monaco'],
+  ['圣马力诺', '+378', 'san marino'],
+  ['乌克兰', '+380', 'Ukraine'],
+  ['斯洛文尼亚', '+386', 'Slovenia'],
+  ['捷克', '+420', 'Czechoslovakian'],
+  ['斯洛伐克', '+421', 'Slovakian'],
+  ['列支敦士登', '+423', 'Liechtenstein'],
+  ['伯利兹', '+501', 'Belize'],
+  ['瓜地马拉', '+502', 'Guatemala'],
+  ['萨尔瓦多', '+503', 'Salvadoran'],
+  ['洪都拉斯', '+504', 'Honduran'],
+  ['尼加拉瓜', '+505', 'Nicaraguan'],
+  ['哥斯达黎加', '+506', 'Costa Rica'],
+  ['巴拿马', '+507', 'Panamanian'],
+  ['海地', '+509', 'Haiti'],
+  ['玻利维亚', '+591', 'Bolivian'],
+  ['圭亚那', '+592', 'Guyanan'],
+  ['厄瓜多尔', '+593', 'Ecuadoran'],
+  ['法属圭亚那', '+594', 'French Guianan'],
+  ['巴拉圭', '+595', 'Paraguay'],
+  ['马提尼克', '+596', 'Martini gram'],
+  ['苏里南', '+597', 'Surinam'],
+  ['乌拉圭', '+598', 'Uruguayan'],
+  ['文莱', '+673', 'Brunei'],
+  ['巴布亚新几内亚', '+675', 'Papua New Guinean'],
+  ['汤加', '+676', 'Tonga'],
+  ['所罗门群岛', '+677', 'Solomon Islands'],
+  ['斐济', '+679', 'Fijian'],
+  ['库克群岛', '+682', 'Cook Islands'],
+  ['法属波利尼西亚', '+689', 'French Polynesian'],
+  ['中国澳门', '+853', 'Chinese Aomen'],
+  ['柬埔寨', '+855', 'Cambodian'],
+  ['老挝', '+856', 'Laos'],
+  ['孟加拉国', '+880', 'Bangladesh'],
+  ['马尔代夫', '+960', 'Maldives'],
+  ['黎巴嫩', '+961', 'Lebanese'],
+  ['约旦', '+962', 'Jordanian'],
+  ['叙利亚', '+963', 'Syrian'],
+  ['伊拉克', '+964', 'Iraqi'],
+  ['科威特', '+965', 'Kuwaiti'],
+  ['沙特阿拉伯', '+966', 'Saudi Arabian'],
+  ['也门', '+967', 'Yemenese'],
+  ['阿曼', '+968', 'Aman'],
+  ['阿拉伯联合酋长国', '+971', 'United Arab Emirates'],
+  ['以色列', '+972', 'Israeli'],
+  ['巴林', '+973', 'Bahraini'],
+  ['卡塔尔', '+974', 'Qataran'],
+  ['蒙古', '+976', 'Mongolian'],
+  ['尼泊尔', '+977', 'Nepalese'],
+  ['塔吉克斯坦', '+992', 'Tajikistan'],
+  ['土库曼斯坦', '+993', 'Turkmenistan'],
+  ['阿塞拜疆', '+994', 'Azerbaijanian'],
+  ['格鲁吉亚', '+995', 'Georgian'],
+  ['吉尔吉斯斯坦', '+996', 'Kyrgyzstan'],
+  ['乌兹别克斯坦', '+998', 'Uzbekistan'],
+  ['巴哈马', '+1242', 'Bahamian'],
+  ['巴巴多斯', '+1246', 'Barbados'],
+  ['安圭拉岛', '+1264', 'Anguilla island'],
+  ['安提瓜和巴布达', '+1268', 'Antigua and Barbadian'],
+  ['开曼群岛', '+1345', 'cayman islands'],
+  ['百慕大群岛', '+1441', 'Bermuda Islands'],
+  ['格林纳达', '+1473', 'Grenada'],
+  ['蒙特塞拉特岛', '+1664', 'Montserrat'],
+  ['关岛', '+1671', 'Guam'],
+  ['圣卢西亚', '+1758', 'Saint Lucia'],
+  ['波多黎各', '+1787', 'Puerto Rico'],
+  ['多明尼加共和国', '+1809', 'Dominican republic'],
+  ['特立尼达和多巴哥', '+1868', 'Trinidad and Tobago'],
+  ['牙买加', '+1876', 'Jamaica'],
+  ['塞尔维亚共和国', '+381', 'The republic of Serbia'],
+  ['毛里塔尼亚', '+222', 'Mauritania ']
+]
+
+export default selectCall

+ 32 - 1
src/pages/account/forget/index.vue

@@ -8,6 +8,17 @@
     <div class="login-con">
     <div class="login-con">
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
         <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
         <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
+        <div class="phone-select" ref="quhaoMenu">
+          <div @click="showSelect=!showSelect">
+            <span>{{codeActive[1]}}</span>
+            <img :src="`${$cdn}images/quhao-jiantou.png`" >
+          </div>
+          <ul v-show="showSelect" >
+            <li @click="selectItem(item)" v-for="(item,i) in selectCall" :key="i">
+              {{item[0]}}{{item[1]}}
+            </li>
+          </ul>
+        </div>
         <input v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
         <input v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
       </div>
       </div>
       <div class="code-con">
       <div class="code-con">
@@ -33,6 +44,7 @@
 
 
 <script>
 <script>
 import {mapState} from 'vuex'
 import {mapState} from 'vuex'
+import selectCall from '../country.js'
 
 
 export default {
 export default {
   computed: {
   computed: {
@@ -42,6 +54,9 @@ export default {
   },
   },
   data () {
   data () {
     return {
     return {
+      showSelect: false,
+      selectCall,
+      codeActive: ['中国', '+86', 'China'],
       phone: '',
       phone: '',
       authCode: '',
       authCode: '',
       interTime: 60,
       interTime: 60,
@@ -51,7 +66,20 @@ export default {
       inputActive: ''
       inputActive: ''
     }
     }
   },
   },
+  mounted () {
+    document.addEventListener('click', (e) => {
+      if (this.$refs.quhaoMenu) {
+        if (!this.$refs.quhaoMenu.contains(e.target)) {
+          this.showSelect = false
+        }
+      }
+    })
+  },
   methods: {
   methods: {
+    selectItem (item) {
+      this.showSelect = false
+      this.codeActive = item
+    },
     blurHandle () {
     blurHandle () {
       this.inputActive = ''
       this.inputActive = ''
       document.querySelector('#app').style.height = 'auto'
       document.querySelector('#app').style.height = 'auto'
@@ -60,7 +88,10 @@ export default {
       }, 20)
       }, 20)
     },
     },
     async getAuthCode () {
     async getAuthCode () {
-      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      let res = await this.$store.dispatch('getAuthCode', {
+        phone: this.phone,
+        code: Number(this.codeActive[1].substr(1))
+      })
       if (res) {
       if (res) {
         this.interl && clearInterval(this.interl)
         this.interl && clearInterval(this.interl)
         this.interl = null
         this.interl = null

+ 38 - 1
src/pages/account/forget/style.scss

@@ -3,7 +3,6 @@ input[type='password']{
   border: 0;
   border: 0;
   outline: 0;
   outline: 0;
   height: 48px;
   height: 48px;
-  line-height: 48px;
   padding-right: 16px;
   padding-right: 16px;
   padding-left: 12px;
   padding-left: 12px;
   font-size: 14px;
   font-size: 14px;
@@ -26,6 +25,44 @@ input[type='password']{
   font-size: 16px;
   font-size: 16px;
   color: rgba(0, 0, 0, 0.7);
   color: rgba(0, 0, 0, 0.7);
 }
 }
+.phone-select{
+  &>div{
+    height: 18px;
+    border-right: 1px solid #f1f1f1;
+    &>span{
+      display: inline-block;
+      vertical-align: middle;
+    }
+  }
+  img{
+    width: 10px!important;
+    margin: 0 12px!important;
+    vertical-align: middle!important;
+  }
+  ul{
+    position: absolute;
+    top: 0;
+    left: 0;
+    background: #fff;
+    width: 200px;
+    height: 220px;
+    padding: 0 10px;
+    overflow: auto;
+    transition: ease 0.3s all;
+    z-index: 888;
+    box-shadow: 0px 1px 8px #ddd;
+    li{
+      height: 40px;
+      line-height: 50px;
+      color: #999;
+      font-size: 14px;
+      cursor: pointer;
+      &:hover{
+        color: #000;
+      }
+    }
+  }
+}
 .forget-layout{
 .forget-layout{
   width: 100%;
   width: 100%;
   .banner{
   .banner{

+ 1 - 1
src/pages/account/manage/cart/index.vue

@@ -78,7 +78,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj

+ 10 - 7
src/pages/account/manage/change/index.vue

@@ -5,9 +5,7 @@
         <div class="order-input-item">
         <div class="order-input-item">
           <div class="order-sub">
           <div class="order-sub">
             <div class="top-title">手机号码</div>
             <div class="top-title">手机号码</div>
-            <div class="ant-input" >
-              <input @blur="blurHandle" v-model="phone" type="text" placeholder="手机号码" />
-            </div>
+            <div class="top-username">{{info.userName}}</div>
           </div>
           </div>
         </div>
         </div>
         <div class="order-input-item">
         <div class="order-input-item">
@@ -18,7 +16,7 @@
                <input @blur="blurHandle" v-model="code" type="text" placeholder="请输入验证码" />
                <input @blur="blurHandle" v-model="code" type="text" placeholder="请输入验证码" />
               </div>
               </div>
                 <button type="submit" class="ant-btn ant-btn-primary code">
                 <button type="submit" class="ant-btn ant-btn-primary code">
-                    <span v-if="!jishi">获取验证码</span>
+                    <span v-if="!jishi" @click="getAuthCode">获取验证码</span>
                     <span v-else>{{interTime}}s后重新发送</span>
                     <span v-else>{{interTime}}s后重新发送</span>
                 </button>
                 </button>
             </div>
             </div>
@@ -54,7 +52,8 @@ import {mapState} from 'vuex'
 export default {
 export default {
   computed: {
   computed: {
     ...mapState({
     ...mapState({
-      token: state => state.user.token
+      token: state => state.user.token,
+      info: state => state.user.info
     })
     })
   },
   },
   data () {
   data () {
@@ -75,7 +74,11 @@ export default {
       }, 20)
       }, 20)
     },
     },
     async getAuthCode () {
     async getAuthCode () {
-      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      let {userName, country} = this.info
+      let res = await this.$store.dispatch('getAuthCode', {
+        phone: userName,
+        code: country === '中国' ? 86 : country
+      })
       if (res) {
       if (res) {
         this.interl && clearInterval(this.interl)
         this.interl && clearInterval(this.interl)
         this.interl = null
         this.interl = null
@@ -100,7 +103,7 @@ export default {
       }
       }
       let params = {
       let params = {
         password: this.password,
         password: this.password,
-        phoneNum: this.phone,
+        phoneNum: this.info.userName,
         msgAuthCode: this.code
         msgAuthCode: this.code
       }
       }
       this.$http({
       this.$http({

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

@@ -54,6 +54,9 @@
             text-align: left;
             text-align: left;
             line-height: 1.5;
             line-height: 1.5;
           }
           }
+          .top-username{
+            font-size: 16px;
+          }
         }
         }
         .order-name,.prov-name{
         .order-name,.prov-name{
           width: 33.33%;
           width: 33.33%;

+ 6 - 3
src/pages/account/manage/confirm/index.vue

@@ -21,8 +21,8 @@
     </div>
     </div>
     <div class="box-con">
     <div class="box-con">
       <div class="bc-title">收货地址</div>
       <div class="bc-title">收货地址</div>
-      <div class="bc-item address-item" v-if="isShowAddress">
-        <div class="bc-ct">
+      <div class="bc-item " :class="{'address-item':address.shipName}"  v-if="isShowAddress">
+        <div class="bc-ct" v-if="address.shipName">
           <div class="bc-contact">
           <div class="bc-contact">
             {{address.shipName}}
             {{address.shipName}}
             <div>{{address.shipMobile}}</div>
             <div>{{address.shipMobile}}</div>
@@ -31,6 +31,9 @@
             {{`${address.shipAreaPath}${address.shipAddress}`}}
             {{`${address.shipAreaPath}${address.shipAddress}`}}
           </div>
           </div>
         </div>
         </div>
+        <div class="noaddress" v-else>
+          <p>暂无收货地址</p>
+        </div>
         <div class="bc-edit" @click="isShowAddress=false">编辑</div>
         <div class="bc-edit" @click="isShowAddress=false">编辑</div>
       </div>
       </div>
       <div class="address-con" v-else>
       <div class="address-con" v-else>
@@ -71,7 +74,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj

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

@@ -66,9 +66,13 @@
       border: 1px solid #1fe4dc;
       border: 1px solid #1fe4dc;
       position: relative;
       position: relative;
       background-color: #f6f9ff;
       background-color: #f6f9ff;
+      .noaddress{
+        color: rgba(0,0,0,.45);
+      }
       .bc-ct{
       .bc-ct{
         margin-left: 32px;
         margin-left: 32px;
         margin-right: 50px;
         margin-right: 50px;
+        min-height: 55px;
         .bc-contact{
         .bc-contact{
           font-size: 12px;
           font-size: 12px;
           color: rgba(0,0,0,.7);
           color: rgba(0,0,0,.7);

+ 305 - 0
src/pages/account/manage/consumption/index.vue

@@ -0,0 +1,305 @@
+<template>
+  <div class="consumption-layout">
+    <div class="plate">
+      <ul class="re-list">
+        <li v-for="(item,i) in data" :key="i">
+          <template v-if="tabActive===1">
+            <p class="f-title">{{item.childName}}</p>
+            <p>{{item.body}}</p>
+            <div>{{item.fuhao}}{{item.points}}<i class="iconfont icon-shang"></i></div>
+
+          </template>
+           <template v-else-if="tabActive===0">
+            <p class="f-title">{{item.childName}}</p>
+            <p>{{item.channel}}</p>
+            <div>{{item.status}}<i class="iconfont icon-shang"></i></div>
+          </template>
+
+          <template v-else>
+            <p class="f-title">{{item.title||''}}</p>
+            <p>{{item.createTime}}</p>
+            <div>{{item.finish}}<i class="iconfont icon-shang"></i></div>
+          </template>
+        </li>
+      </ul>
+      <div class="scene-nothing" v-if="!total">
+        <img src="@/assets/images/nothing.png">
+        <div>居然还没有新时代空间建模神器<br/>赶紧入手吧</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'
+
+let PAYSSTR = {
+  0: '微信',
+  1: '支付宝',
+  2: 'paypal'
+}
+
+let methodStr = {
+  0: 'getConsumpList',
+  1: 'getChargeList',
+  2: 'getInvoiceList'
+}
+
+let invoceStatusType = {
+  0: '未开票',
+  1: '已开票'
+}
+export default {
+  props: ['tabactive'],
+  components: { Paging },
+  data () {
+    let tabList = [
+      {
+        name: '四维看看Pro',
+        id: 4
+      }, {
+        name: '四维看看Lite',
+        id: 0
+      }
+    ]
+
+    return {
+      tabList,
+      currentPage: 1,
+      total: 0,
+      data: [],
+      tabActive: this.tabactive,
+      searchKey: '',
+      pageSize: 8
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      myexpansion: state => {
+        let type = Object.prototype.toString.call(state.user.myexpansion)
+        if (type === '[object Object]') {
+          return state.user.myexpansion
+        }
+        let condition = state.user.myexpansion && state.user.myexpansion !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.myexpansion) : {})
+      },
+      mycharge: state => {
+        let type = Object.prototype.toString.call(state.user.mycharge)
+        if (type === '[object Object]') {
+          return state.user.mycharge
+        }
+        let condition = state.user.mycharge && state.user.mycharge !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.mycharge) : {})
+      },
+      myinvoicelist: state => {
+        let type = Object.prototype.toString.call(state.user.myinvoicelist)
+        if (type === '[object Object]') {
+          return state.user.myinvoicelist
+        }
+        let condition = state.user.myinvoicelist && state.user.myinvoicelist !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.myinvoicelist) : {})
+      },
+      invoicedevice: state => {
+        let type = Object.prototype.toString.call(state.user.invoicedevice)
+        if (type === '[object Object]') {
+          return state.user.invoicedevice
+        }
+        let condition = state.user.invoicedevice && state.user.invoicedevice !== 'null'
+        return (condition ? state.user.invoicedevice : [])
+      }
+    })
+  },
+  methods: {
+    pageChange (data) {
+      this.currentPage = data
+    },
+    getList (searchKey = '') {
+      let str = methodStr[this.tabActive]
+      this[str](searchKey)
+    },
+    async getChargeList (searchKey = '') {
+      let params = {
+        childName: searchKey,
+        pageNum: searchKey ? 1 : this.currentPage,
+        pageSize: this.pageSize
+      }
+      await this.$store.dispatch('getChargeList', params)
+      if (!this.mycharge.total && searchKey) {
+        return this.$toast.show('warn', '没有找到相应的记录', () => {
+          this.getList()
+        })
+      }
+      this.pageSize = this.mycharge.pageSize
+      this.total = this.mycharge.total || 0
+      this.data = this.mycharge.list
+      this.data.forEach(item => {
+        item['fuhao'] = item['status'] === -1 ? '-' : '+'
+      })
+    },
+    async getInvoiceList () {
+      let params = {
+        cameraId: this.activeId,
+        pageNum: this.currentPage,
+        pageSize: this.pageSize,
+        type: this.activeTypeId
+      }
+      await this.$store.dispatch('getInvoiceList', params)
+      this.pageSize = this.myinvoicelist.pageSize
+      this.total = this.myinvoicelist.total || 0
+      this.data = this.myinvoicelist.list
+      this.data.forEach(item => {
+        item['detail'] = '详细'
+        item['finish'] = invoceStatusType[item['finish']]
+      })
+    },
+    async getConsumpList (searchKey = '') {
+      let params = {
+        childName: searchKey,
+        pageNum: searchKey ? 1 : this.currentPage,
+        pageSize: this.pageSize
+      }
+      await this.$store.dispatch('getUserExpansion', params)
+      if (!this.myexpansion.total && searchKey) {
+        return this.$toast.show('warn', '没有找到相应的记录', () => {
+          this.getList()
+        })
+      }
+      this.pageSize = this.myexpansion.pageSize
+      this.total = this.myexpansion.total || 0
+      this.data = this.myexpansion.list
+      this.data.forEach(item => {
+        item['unitSize'] = item['unitSize'] + item['unit']
+        item['channel'] = '扩充容量购买'
+        item['payType'] = PAYSSTR[item['payType']]
+      })
+    }
+  },
+  mounted () {
+    this.$bus.$on('selectdevice', id => {
+      this.tabActive = id
+    })
+    this.getList()
+  },
+  watch: {
+    currentPage () {
+      this.getList()
+    },
+    tabActive (newVal) {
+      this.getList()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+
+.btn{
+  width: 72px;
+  display: inline-block;
+  border: solid 1px #ddd;
+  line-height: 32px;
+  height: 32px;
+  text-align: center;
+  border-radius: 2px;
+}
+.primary{
+  background-color: $theme-color;
+  border-color: $theme-color;
+}
+.consumption-layout{
+  background: #f6f9fd;
+  .plate{
+    .re-list{
+      margin-top: 20px;
+      li{
+        background-color: #fff;
+        border-bottom: 1px solid #ececec;
+        height: 60px;
+        padding-right: 20%;
+        position: relative;
+        padding: 12px 20% 12px 12px;
+        .f-title{
+          font-weight: bold;
+          color: #2d2d2d;
+          margin-bottom: 8px;
+        }
+        p{
+          color: #777;
+          font-size: 12px;
+        }
+        div{
+          position: absolute;
+          right: 4%;
+          top: 50%;
+          transform: translateY(-50%);
+          font-size: 12px;
+          color: #777;
+          .iconfont{
+            transform: rotate(90deg);
+            display: inline-block;
+          }
+        }
+      }
+    }
+    .scene-nothing{
+      background: #fff;
+      text-align: center;
+      padding:40px 0;
+      img{
+        padding-bottom: 22px;
+      }
+      div{
+        font-size: 14px;
+        color: #969696;
+      }
+    }
+  }
+  .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;
+    }
+  }
+}
+</style>

+ 308 - 0
src/pages/account/manage/device/index.vue

@@ -0,0 +1,308 @@
+<template>
+  <div class="device-layout">
+    <div class="plate">
+      <template v-if="tabActive===4">
+        <div class="d-item" v-for="(item,i) in mydevice.list" :key="i" >
+          <img :src="`${$cdn}images/banner_pro.png`" alt="">
+          <img v-if="item.spaceEndTime" class="king" :src="`${$cdn}images/icon-huiyuan.png`" alt="">
+
+          <div class="eight-right">
+            <p class="i-title">ID:{{item.childName}}</p>
+            <p class="i-dec">云存储空间</p>
+            <div class="capacity">
+              <div class="c-line">
+                <div class="active" :style="{width:getBar(item.usedSpace,item.totalSpace)}"></div>
+              </div>
+            </div>
+            <p class="i-dec">{{item.usedSpaceStr}} / {{item.totalSpaceStr}}</p>
+
+            <div class="btn-con">
+              <span class="btn" @click="unbind(item)">解绑</span>
+              <span class="btn" @click="$router.push({name:'introduce',params:{id:item.childName}})">扩容</span>
+              <span class="btn primary"  v-if="!item.spaceEndTime" @click="$router.push({name:'privilege',params: {
+          cameraId: item.id,
+          childName: item.childName
+        }})">升级</span>
+              <span class="btn" @click="$router.push({name:'introduce',params:{id:item.childName}})" v-else >续期</span>
+            </div>
+          </div>
+        </div>
+      </template>
+
+      <template v-else>
+        <div class="d-item"  v-for="(item,i) in mydevice.list" :key="i">
+          <img :src="`${$cdn}images/t_product.png`" alt="">
+          <div class="item-right">
+            <p class="i-title">ID:{{item.childName}}</p>
+            <p class="i-dec">剩余点数:</p>
+            <div class="btn-con">
+              <span>{{item.balance}}</span>
+              <div>
+                <span class="btn" @click="unbind(item)">解绑</span>
+                <span class="btn primary" @click="$router.push({name:'introtow',params:{id:item.childName}})">充值</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
+
+      <div class="scene-nothing" v-if="!total">
+        <img src="@/assets/images/nothing.png">
+        <div>居然还没有新时代空间建模神器<br/>赶紧入手吧</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 () {
+    let tabList = [
+      {
+        name: '四维看看Pro',
+        id: 4
+      }, {
+        name: '四维看看Lite',
+        id: 0
+      }
+    ]
+    return {
+      tabList,
+      tabActive: 4,
+      currentPage: 1,
+      total: 0,
+      searchKey: '',
+      pageSize: 8
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      mydevice: state => {
+        let type = Object.prototype.toString.call(state.user.mydevice)
+        if (type === '[object Object]') {
+          return state.user.mydevice
+        }
+        let condition = state.user.mydevice && state.user.mydevice !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.mydevice) : {})
+      }
+    })
+  },
+  methods: {
+    getPercent (a, b) {
+      let temp = a / b
+      if (temp < 1) {
+        return '<1'
+      }
+      return Math.round(temp)
+    },
+    getBar (a, b) {
+      let temp = a / b
+      if (temp < 1) {
+        return '1%'
+      }
+      return Math.round(temp) + '%'
+    },
+    async unbind (item) {
+      this.$toast.showConfirm('warn', '确定要解绑当前设备吗?', async () => {
+        let params = {
+          cameraId: item.id
+        }
+        let res = await this.$http({
+          method: 'post',
+          data: params,
+          headers: {
+            token: this.token
+          },
+          url: '/user/camera/unbind'
+        })
+        let data = res.data
+        if (data.code === 0) {
+          return this.$toast.show('warn', '解绑成功', () => {
+            this.getList()
+          })
+        }
+        return this.$toast.show('error', `解绑失败,${data.msg}`)
+      })
+    },
+    pageChange (data) {
+      this.currentPage = data
+    },
+    addDevice () {
+      let val = this.tabActive === 4 ? 1 : 0
+      this.$toast.showBinding(val, () => {
+        this.getList()
+      })
+    },
+    async getList (searchKey = '') {
+      window.scrollTo(0, 0)
+
+      let params = {
+        cameraType: this.tabActive,
+        childName: searchKey,
+        pageNum: searchKey ? 1 : this.currentPage,
+        pageSize: this.pageSize
+      }
+      await this.$store.dispatch('getUserDevice', params)
+
+      if (!this.mydevice.total && searchKey) {
+        return this.$toast.show('warn', '没有找到对应的设备', () => {
+          this.getList()
+        })
+      }
+      this.pageSize = this.mydevice.pageSize
+      this.total = this.mydevice.total || 0
+    }
+  },
+  mounted () {
+    this.getList()
+    this.$bus.$on('selectdevice', id => {
+      this.tabActive = id
+    })
+  },
+  watch: {
+    currentPage () {
+      this.getList()
+    },
+    tabActive (newVal) {
+      this.currentPage === 1 ? this.getList() : this.currentPage = 1
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+
+.btn{
+  width: 72px;
+  display: inline-block;
+  border: solid 1px #ddd;
+  line-height: 32px;
+  height: 32px;
+  text-align: center;
+  border-radius: 2px;
+}
+.primary{
+  background-color: $theme-color;
+  border-color: $theme-color;
+}
+.device-layout{
+  background: #f6f9fd;
+  .plate{
+    .scene-nothing{
+      background: #fff;
+      text-align: center;
+      padding:40px 0;
+      img{
+        padding-bottom: 22px;
+      }
+      div{
+        font-size: 14px;
+        color: #969696;
+      }
+    }
+    .d-item{
+      position: relative;
+      background: #fff;
+      margin: 10px 0;
+      padding: 10px 0;
+      img{
+        position: absolute;
+        width: 30px;
+        top: 50%;
+        left: 15%;
+        transform: translate(-50%, -50%);
+      }
+      .king{
+        top: 21%;
+        left: 19.5%;
+      }
+      .item-right,.eight-right{
+        height: 90px;
+        margin-left: 30%;
+        margin-right: 16px;
+        .i-title{
+          font-size: 16px;
+          color: #2d2d2d;
+          margin-bottom: 10px;
+          font-weight: bold;
+        }
+        .i-dec{
+          margin-bottom: 10px;
+          font-size: 14px;
+          color: #777;
+        }
+        .capacity{
+          margin: 5px 0;
+          .c-line{
+            width: 64%;
+            height: 8px;
+            background-color: #ccc;
+            .active{
+              background-color:$theme-color;
+              height: 100%;
+            }
+          }
+        }
+        .btn-con{
+          display: flex;
+          width: 100%;
+          justify-content: space-between;
+        }
+      }
+      .eight-right{
+        height: 130px;
+      }
+    }
+  }
+  .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;
+    }
+  }
+}
+</style>

+ 93 - 2
src/pages/account/manage/index.vue

@@ -2,29 +2,120 @@
   <div class="manage-layout">
   <div class="manage-layout">
     <div class="m-nav">
     <div class="m-nav">
       <span>{{title}}</span>
       <span>{{title}}</span>
-      <span class="btns"></span>
+      <span v-if="title==='我的设备'" @click="addDevice" class="btns">
+        +添加设备
+      </span>
+      <span v-if="consumpselected.id===2&&title==='消费记录'" @click="openInvoice" class="btns">
+        开具发票
+      </span>
+      <div v-if="title==='我的设备'" class="select" ref="mbMenu1" @click="selectedActive=!selectedActive">
+        {{selected.name}}
+        <div class="s-sub" :class="{'s-active':selectedActive}">
+          <div v-for="(item,i) in selectType" :key="i" :class="{'item-active':selected.name===item.name}" @click="emithandle(item)" class="s-item">{{item.name}}</div>
+        </div>
+      </div>
+      <div v-if="title==='消费记录'" class="select" ref="mbMenu1" @click="selectedActive=!selectedActive">
+        {{consumpselected.name}}
+        <div class="s-sub" :class="{'s-active':selectedActive}">
+          <div v-for="(item,i) in consumpType" :key="i" :class="{'item-active':consumpselected.name===item.name}" @click="emithandlerecord(item)" class="s-item">{{item.name}}</div>
+        </div>
+      </div>
     </div>
     </div>
-    <router-view />
+    <router-view :tabactive='consumpselected.id' />
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
+import {mapState} from 'vuex'
+
 let titleName = {
 let titleName = {
   'information': '个人中心',
   'information': '个人中心',
   'order': '我的订单',
   'order': '我的订单',
   'myscene': '我的场景',
   'myscene': '我的场景',
+  'device': '我的设备',
+  'consumption': '消费记录',
   'change': '修改密码',
   'change': '修改密码',
   'confirm': '确认订单',
   'confirm': '确认订单',
   'submit': '确认订单',
   'submit': '确认订单',
   'paytype': '确认订单',
   'paytype': '确认订单',
+  'openInvoice': '开具发票',
   'payselect': '支付方式',
   'payselect': '支付方式',
   'cart': '购物车'
   'cart': '购物车'
 }
 }
 export default {
 export default {
   computed: {
   computed: {
+    ...mapState({
+      langCases: state => state.language.home.cases,
+      language: state => state.language.current
+    }),
     title: function () {
     title: function () {
       return titleName[this.$route.name]
       return titleName[this.$route.name]
     }
     }
+  },
+  methods: {
+    addDevice () {
+      let val = this.selected.id === 4 ? 1 : 0
+      this.$toast.showBinding(val, () => {
+      })
+    },
+    openInvoice () {
+      this.$router.push({
+        name: 'openInvoice'
+      })
+    },
+    emithandle (item) {
+      this.selected = item
+      this.$bus.$emit('selectdevice', item.id)
+    },
+    emithandlerecord (item) {
+      this.consumpselected = item
+      this.$bus.$emit('selectdevice', item.id)
+    }
+  },
+  data () {
+    let selectType = [
+      {
+        name: 'Pro',
+        id: 4
+      }, {
+        name: 'Lite',
+        id: 0
+      }
+    ]
+    let consumpType = [
+      {
+        name: '扩容记录',
+        id: 0
+      }, {
+        name: '充值记录',
+        id: 1
+      }, {
+        name: '增值发票',
+        id: 2
+      }
+    ]
+    return {
+      selectedActive: false,
+      selectType,
+      consumpType,
+      selected: {
+        name: 'Pro',
+        id: 4
+      },
+      consumpselected: {
+        name: '扩容记录',
+        id: 0
+      }
+    }
+  },
+  mounted () {
+    document.addEventListener('click', (e) => {
+      if (this.$refs.mbMenu1) {
+        if (!this.$refs.mbMenu1.contains(e.target)) {
+          this.selectedActive = false
+        }
+      }
+    })
   }
   }
 }
 }
 </script>
 </script>

+ 34 - 35
src/pages/account/manage/information/index.vue

@@ -65,7 +65,7 @@
           </div>
           </div>
         </template>
         </template>
       </div>
       </div>
-      <invoices :invoice='invoice2' :invoicet="invoice3" :token="token" @closeInvoice="data=>{isShowInvoice=data}" v-else />
+      <invoices :invoice='editInvoice2' :invoicet="editInvoice3" :token="token" @closeInvoice="data=>{isShowInvoice=data}" v-else />
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>
@@ -74,7 +74,17 @@
 import { mapState } from 'vuex'
 import { mapState } from 'vuex'
 import citySelect from '@/components/citySelect'
 import citySelect from '@/components/citySelect'
 import invoices from '@/components/invoices'
 import invoices from '@/components/invoices'
-
+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 {
 export default {
   components: {
   components: {
     citySelect,
     citySelect,
@@ -92,6 +102,14 @@ export default {
         let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
         let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
         return (condition ? JSON.parse(state.user.invoice2) : {})
         return (condition ? JSON.parse(state.user.invoice2) : {})
       },
       },
+      editInvoice2: 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 cloneObj(condition ? JSON.parse(state.user.invoice2) : {})
+      },
       invoice3: state => {
       invoice3: state => {
         let type = Object.prototype.toString.call(state.user.invoice3)
         let type = Object.prototype.toString.call(state.user.invoice3)
         if (type === '[object Object]') {
         if (type === '[object Object]') {
@@ -101,7 +119,16 @@ export default {
 
 
         return (condition ? JSON.parse(state.user.invoice3) : {})
         return (condition ? JSON.parse(state.user.invoice3) : {})
       },
       },
-      address: state => state.user.address || {}
+      editInvoice3: 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 cloneObj(condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      address: state => state.user.address || {},
+      editAdd: state => cloneObj(state.user.address) || {}
     })
     })
   },
   },
   data () {
   data () {
@@ -115,40 +142,12 @@ export default {
     getCurrentStatus (data) {
     getCurrentStatus (data) {
       this.tempSelect = 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) {
     update (e) {
       let file = e.target.files[0]
       let file = e.target.files[0]
+      let type = file.type.toLowerCase()
+      if (type !== 'image/jpeg' && type !== 'image/png') {
+        return this.$toast.show('warn', '上传的图片类型不正确,请重新上传')
+      }
       let token = this.token
       let token = this.token
       let config = {
       let config = {
         headers: {
         headers: {

+ 18 - 7
src/pages/account/manage/myscene/index.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
   <div class="scene-layout">
   <div class="scene-layout">
     <template v-if="total">
     <template v-if="total">
-      <div class="items" @click="goto(item.webSite)" v-for="(item,i) in myscene.list" :key="i">
+      <div class="items" @click="(item.status === 1||item.status===-2) && 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="card-img" :style="{backgroundImage: `url(${item.thumb||`${$cdn}images/default.png`})`}"></div>
         <div class="item-txt">
         <div class="item-txt">
           <!-- <p>{{typeArr[item.sceneType]}}</p> -->
           <!-- <p>{{typeArr[item.sceneType]}}</p> -->
@@ -10,17 +10,17 @@
           <div class="btm-opr">
           <div class="btm-opr">
             <div class="btm-left">
             <div class="btm-left">
               <img :src="`${$cdn}images/eye.png`" alt>
               <img :src="`${$cdn}images/eye.png`" alt>
-              <span>{{item.sceneScheme===4?'Pro':'Lite'}}</span>
+              <span>{{item.sceneScheme>=4?'Pro':'Lite'}}</span>
             </div>
             </div>
-            <div class="btm-right">编辑</div>
+            <div class="btm-right" @click.stop="(item.status === 1||item.status===-2) && gotoEdit(item.webSite)">编辑</div>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
     </template>
     </template>
     <div class="scene-nothing" v-else>
     <div class="scene-nothing" v-else>
-        <img src="@/assets/images/nothing.png" alt="">
-        <div>暂无任何场景,赶紧去拍摄吧。</div>
-      </div>
+      <img src="@/assets/images/nothing.png" alt="">
+      <div>暂无任何场景,赶紧去拍摄吧。</div>
+    </div>
     <div class="paging" v-if="total">
     <div class="paging" v-if="total">
       <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize"/>
       <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize"/>
     </div>
     </div>
@@ -63,7 +63,18 @@ export default {
   },
   },
   methods: {
   methods: {
     goto (url) {
     goto (url) {
-      location.href = url.replace('http://', 'https://')
+      let temp = url.replace('show.html', 'showApp.html')
+      let temp1 = temp.replace('showProPC.html', 'showProMobile.html')
+      location.href = temp1.replace('http://', 'https://')
+    },
+    gotoEdit (url) {
+      if (url.indexOf('www') !== -1) {
+        return
+      }
+      let temp = url.replace('http://', 'https://')
+      let temp1 = temp.replace('showProPC.html', 'showProMobile.html')
+      // console.log(temp1)
+      window.open(temp1.replace('show', 'edit'), '_blank')
     },
     },
     async del (item) {
     async del (item) {
       this.$toast.showConfirm('warn', '确定要删除当前场景吗?', async () => {
       this.$toast.showConfirm('warn', '确定要删除当前场景吗?', async () => {

+ 3 - 3
src/pages/account/manage/myscene/style.scss

@@ -25,9 +25,9 @@
       border-bottom: none;
       border-bottom: none;
     }
     }
     .card-img{
     .card-img{
-      width: 138px;
-      min-width: 138px;
-      height: 121px;
+      width: 165px;
+      min-width: 165px;
+      height: 100px;
       cursor: pointer;
       cursor: pointer;
       background-position: center;
       background-position: center;
       background-size: auto 100%;
       background-size: auto 100%;

+ 130 - 0
src/pages/account/manage/openInvoice/index.vue

@@ -0,0 +1,130 @@
+<template>
+  <div class="i-layout">
+    <div class="address-con">
+      <createInvoice class="address-scon" />
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import invoices from '@/components/invoices'
+import createInvoice from '@/components/createInvoice'
+
+export default {
+  components: {
+    invoices,
+    createInvoice
+  },
+  data () {
+    return {
+
+    }
+  },
+  computed: {
+    ...mapState({
+      address: state => state.user.address || {}
+    })
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.i-layout{
+  margin-top: 10px;
+  .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;
+    }
+  }
+  .address-con{
+    .sub-title{
+      font-size: 14px;
+      line-height: 21px;
+      font-weight: 700;
+      padding: 13px 16px;
+      border-bottom: 1px solid #e9e9e9;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .address-scon{
+    }
+  }
+}
+</style>

+ 1 - 1
src/pages/account/manage/order/index.vue

@@ -30,7 +30,7 @@
               </div>
               </div>
             </template>
             </template>
             <template v-else-if="getStatus(item) === 'shipped'">
             <template v-else-if="getStatus(item) === 'shipped'">
-              <span class="expreeNum">物流单号:77110342778758</span>
+              <span class="expreeNum">物流单号:{{item.orderItems[0].expressNum}}</span>
             </template>
             </template>
             <template v-else-if="getStatus(item) === 'unshipped'">
             <template v-else-if="getStatus(item) === 'unshipped'">
               <span class="expreeNum">等待商家发货</span>
               <span class="expreeNum">等待商家发货</span>

+ 2 - 2
src/pages/account/manage/order/style.scss

@@ -34,7 +34,7 @@
     }
     }
     .o-con{
     .o-con{
       margin: 16px 0;
       margin: 16px 0;
-      padding: 0 24px 0 45px;
+      padding: 0 24px 0 25px;
       display: flex;
       display: flex;
       justify-content: space-between;
       justify-content: space-between;
       align-items: center;
       align-items: center;
@@ -46,7 +46,7 @@
         display: flex;
         display: flex;
         align-items: center;
         align-items: center;
         img{
         img{
-          width: 20px;
+          width: 55px;
           margin-right: 25px;
           margin-right: 25px;
         }
         }
       }
       }

+ 64 - 0
src/pages/account/manage/style.scss

@@ -1,3 +1,4 @@
+$theme-color: #1fe4dc;
 
 
 .manage-layout{
 .manage-layout{
   background: #f6f9fd;
   background: #f6f9fd;
@@ -13,5 +14,68 @@
     display: flex;
     display: flex;
     justify-content: space-between;
     justify-content: space-between;
     align-items: center;
     align-items: center;
+    .btns{
+      font-size: 14px;
+      color: $theme-color;
+      border: 1px solid $theme-color;
+      height: 30px;
+      line-height: 30px;
+      padding: 0 10px;
+      box-sizing: border-box;
+      border-radius: 2px;
+    }
+    .select{
+      position: relative;
+      min-width: 20%;
+      font-size: 14px;
+      font-weight: normal;
+      .s-sub{
+        position: absolute;
+        top: 48px;
+        box-shadow: 1px 1px 5px rgba($color: #000000, $alpha: 0.5);
+        left: -10%;
+        background: #fff;
+        width: 120%;
+        max-height: 0;
+        transition: 0.3s all ease;
+        overflow: hidden;
+        z-index: 999;
+        .s-item{
+          text-align: center;
+          height: 30px;
+          line-height: 30px;
+        }
+        .item-active{
+          background: #f2f2f2;
+        }
+      }
+      .s-active{
+        max-height: 100px;
+      }
+      select{
+        background: #fff;
+        display: inline-block;
+        width:100%;  
+        appearance:none;  
+        -moz-appearance:none;  
+        -webkit-appearance:none;  
+        border: 0;
+        color:#666;  
+        outline:none;
+        padding-right: 20%;
+      }
+      &::after{
+        position: absolute;
+        right: 0;
+        top: 50%;
+        transform: translateY(calc(-50% + 2px));
+        content: '';
+        width: 0;
+        height: 0;
+        border: 4px solid;
+        display: inline-block;
+        border-color: #000 transparent transparent;
+      }
+    }
   }
   }
 }
 }

+ 5 - 2
src/pages/account/manage/submit/index.vue

@@ -111,7 +111,7 @@ var cloneObj = function (obj) {
     newObj = []
     newObj = []
   }
   }
   for (var key in obj) {
   for (var key in obj) {
-    var val = obj[key]
+    var val = obj[key] || ''
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
     newObj[key] = typeof val === 'object' ? cloneObj(val) : val
   }
   }
   return newObj
   return newObj
@@ -125,6 +125,7 @@ export default {
   computed: {
   computed: {
     ...mapState({
     ...mapState({
       token: state => state.user.token || '',
       token: state => state.user.token || '',
+      language: state => state.language.current,
       payinfo: state => {
       payinfo: state => {
         let type = Object.prototype.toString.call(state.user.payinfo)
         let type = Object.prototype.toString.call(state.user.payinfo)
         if (type === '[object Object]') {
         if (type === '[object Object]') {
@@ -150,7 +151,9 @@ export default {
         goods,
         goods,
         receiver,
         receiver,
         invoice,
         invoice,
-        payType
+        payType,
+        abroad: this.language === 'en' ? 1 : 0
+
       }
       }
       let res = await this.$http
       let res = await this.$http
         .post('user/order/placeOrder', params, {
         .post('user/order/placeOrder', params, {

+ 38 - 4
src/pages/account/register/index.vue

@@ -8,11 +8,22 @@
     <div class="login-con">
     <div class="login-con">
       <div class="input-con" :class="{inputActive:inputActive==='nickname'}">
       <div class="input-con" :class="{inputActive:inputActive==='nickname'}">
         <img :src="`${$cdn}images/icon/icon-user@2x.png`" alt="">
         <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="昵称">
+        <input v-model="nickname" @focus="inputActive='nickname'" @blur="blurHandle" type="text" placeholder="昵称">
       </div>
       </div>
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
       <div class="input-con" :class="{inputActive:inputActive==='phone'}">
         <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
         <img :src="`${$cdn}images/icon/icon-phone@2x.png`" alt="">
-        <input v-model="phone" @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
+        <div class="phone-select" ref="quhaoMenu">
+          <div @click="showSelect=!showSelect">
+            <span>{{codeActive[1]}}</span>
+            <img :src="`${$cdn}images/quhao-jiantou.png`" >
+          </div>
+          <ul v-show="showSelect" >
+            <li @click="selectItem(item)" v-for="(item,i) in selectCall" :key="i">
+              {{item[0]}}{{item[1]}}
+            </li>
+          </ul>
+        </div>
+        <input oninput="value=value.replace(/[^\d]/g,'')" v-model="phone" @focus="inputActive='phone'" @blur="blurHandle" type="text" placeholder="手机">
       </div>
       </div>
       <div class="code-con">
       <div class="code-con">
         <div class="input-con" :class="{inputActive:inputActive==='code'}">
         <div class="input-con" :class="{inputActive:inputActive==='code'}">
@@ -46,9 +57,13 @@
 </template>
 </template>
 
 
 <script>
 <script>
+import selectCall from '../country.js'
+
 export default {
 export default {
   data () {
   data () {
     return {
     return {
+      showSelect: false,
+      codeActive: ['中国', '+86', 'China'],
       nickname: '',
       nickname: '',
       phone: '',
       phone: '',
       authCode: '',
       authCode: '',
@@ -58,9 +73,19 @@ export default {
       interTime: 60,
       interTime: 60,
       jishi: false,
       jishi: false,
       interl: null,
       interl: null,
+      selectCall,
       isAgree: true
       isAgree: true
     }
     }
   },
   },
+  mounted () {
+    document.addEventListener('click', (e) => {
+      if (this.$refs.quhaoMenu) {
+        if (!this.$refs.quhaoMenu.contains(e.target)) {
+          this.showSelect = false
+        }
+      }
+    })
+  },
   methods: {
   methods: {
     blurHandle () {
     blurHandle () {
       this.inputActive = ''
       this.inputActive = ''
@@ -69,8 +94,15 @@ export default {
         document.querySelector('#app').style.height = '100%'
         document.querySelector('#app').style.height = '100%'
       }, 20)
       }, 20)
     },
     },
+    selectItem (item) {
+      this.showSelect = false
+      this.codeActive = item
+    },
     async getAuthCode () {
     async getAuthCode () {
-      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      let res = await this.$store.dispatch('getAuthCode', {
+        phone: this.phone,
+        code: Number(this.codeActive[1].substr(1))
+      })
       if (res) {
       if (res) {
         this.interl && clearInterval(this.interl)
         this.interl && clearInterval(this.interl)
         this.interl = null
         this.interl = null
@@ -90,12 +122,14 @@ export default {
       if (!this.isAgree) {
       if (!this.isAgree) {
         return this.$toast.show('warn', '请查阅并同意四维看看条款')
         return this.$toast.show('warn', '请查阅并同意四维看看条款')
       }
       }
+      let country = Number(this.codeActive[1].substr(1))
+
       let params = {
       let params = {
         password: this.password,
         password: this.password,
         phoneNum: this.phone,
         phoneNum: this.phone,
         msgAuthCode: this.authCode,
         msgAuthCode: this.authCode,
         nickName: this.nickname,
         nickName: this.nickname,
-        country: '中国',
+        country,
         confirmPwd: this.confirmPass
         confirmPwd: this.confirmPass
       }
       }
       let res = await this.$http({
       let res = await this.$http({

+ 38 - 1
src/pages/account/register/style.scss

@@ -3,7 +3,6 @@ input[type='password']{
   border: 0;
   border: 0;
   outline: 0;
   outline: 0;
   height: 48px;
   height: 48px;
-  line-height: 48px;
   padding-right: 16px;
   padding-right: 16px;
   padding-left: 12px;
   padding-left: 12px;
   font-size: 14px;
   font-size: 14px;
@@ -26,6 +25,44 @@ input[type='password']{
   font-size: 16px;
   font-size: 16px;
   color: rgba(0, 0, 0, 0.7);
   color: rgba(0, 0, 0, 0.7);
 }
 }
+.phone-select{
+  &>div{
+    height: 18px;
+    border-right: 1px solid #f1f1f1;
+    &>span{
+      display: inline-block;
+      vertical-align: middle;
+    }
+  }
+  img{
+    width: 10px!important;
+    margin: 0 12px!important;
+    vertical-align: middle!important;
+  }
+  ul{
+    position: absolute;
+    top: 0;
+    left: 0;
+    background: #fff;
+    width: 200px;
+    height: 220px;
+    padding: 0 10px;
+    overflow: auto;
+    transition: ease 0.3s all;
+    z-index: 888;
+    box-shadow: 0px 1px 8px #ddd;
+    li{
+      height: 40px;
+      line-height: 50px;
+      color: #999;
+      font-size: 14px;
+      cursor: pointer;
+      &:hover{
+        color: #000;
+      }
+    }
+  }
+}
 .register-layout{
 .register-layout{
   width: 100%;
   width: 100%;
   .banner{
   .banner{

+ 20 - 12
src/pages/cases/index.vue

@@ -24,17 +24,23 @@
       </div>
       </div>
     </div>
     </div>
     <div class="cases">
     <div class="cases">
-      <div class="item" v-for="(item,index) in scene" :key="index" @click="goto(item.webSite)">
-         <img :src="item.thumb||`${$cdn}images/default.png`" alt>
-         <div class="c-title">
-            <span>{{item.sceneName}}</span>
-            <div>
-              <img :src="`${$cdn}images/eye.png`" alt>
-              <span>{{item.sceneScheme===4?'Pro':'Lite'}}</span>
-            </div>
-         </div>
-         <p class="b-text3">作者:{{item.nickName}}</p>
-         <p class="b-text3">查看次数:{{item.viewCount}}</p>
+      <template v-if="scene.length>0">
+        <div class="item" v-for="(item,index) in scene" :key="index" @click="goto(item.webSite)">
+          <img :src="item.thumb||`${$cdn}images/default.png`" alt>
+          <div class="c-title">
+              <span>{{item.sceneName}}</span>
+              <div>
+                <img :src="`${$cdn}images/eye.png`" alt>
+                <span>{{item.sceneScheme>=4?'Pro':'Lite'}}</span>
+              </div>
+          </div>
+          <p class="b-text3">作者:{{item.nickName}}</p>
+          <p class="b-text3">查看次数:{{item.viewCount}}</p>
+        </div>
+      </template>
+      <div class="scene-nothing" v-else>
+        <img src="@/assets/images/nothing.png" alt="">
+        <div>暂无场景</div>
       </div>
       </div>
     </div>
     </div>
     <div class="paging" v-if="total">
     <div class="paging" v-if="total">
@@ -119,7 +125,9 @@ export default {
       this.currentPage = data
       this.currentPage = data
     },
     },
     goto (url) {
     goto (url) {
-      location.href = url.replace('http://', 'https://')
+      let temp = url.replace('show.html', 'showApp.html')
+      let temp1 = temp.replace('showProPC.html', 'showProMobile.html')
+      location.href = temp1.replace('http://', 'https://')
     },
     },
     async getData () {
     async getData () {
       document.querySelector('#app').scrollTo(0, 0)
       document.querySelector('#app').scrollTo(0, 0)

+ 11 - 3
src/pages/cases/style.scss

@@ -1,4 +1,15 @@
 .cases-con{
 .cases-con{
+  .scene-nothing{
+    text-align: center;
+    padding:30px 0;
+    img{
+      padding-bottom: 22px;
+    }
+    div{
+      font-size: 16px;
+      color: #969696;
+    }
+  }
   .nav-hot{
   .nav-hot{
     .list-navs{
     .list-navs{
       width: 90%;
       width: 90%;
@@ -28,9 +39,6 @@
       .select{
       .select{
         position: relative;
         position: relative;
         min-width: 23%;
         min-width: 23%;
-        span{
-
-        }
         .s-sub{
         .s-sub{
           position: absolute;
           position: absolute;
           top: 24px;
           top: 24px;

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

@@ -146,7 +146,7 @@ export default {
       params,
       params,
       params2,
       params2,
       wh,
       wh,
-      runLineCanvas: false,
+      runLineCanvas: true,
       case1: {
       case1: {
         content: require('@/assets/video/8k.mp4'),
         content: require('@/assets/video/8k.mp4'),
         back: require('@/assets/video/4k.mp4'),
         back: require('@/assets/video/4k.mp4'),

+ 13 - 0
src/pages/introduce/index.vue

@@ -0,0 +1,13 @@
+<template>
+ <div></div>
+</template>
+
+<script>
+
+export default {
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 0 - 0
src/pages/introduce/style.scss


+ 57 - 0
src/pages/introtow/index.vue

@@ -0,0 +1,57 @@
+<template>
+ <div class="introtow-layout">
+   <div class="it-header it-txt">
+     <p>ID:asdasd</p>
+     <p>剩余点数:2000</p>
+   </div>
+   <div class="point-list it-txt">
+     <p>限时抢购点数包</p>
+     <p>购买立即生效</p>
+     <div class="card-scroll">
+       <div class="card-item" v-for="(item,i) in 3" :key="i">
+         <div></div>
+         <p>小号点数包</p>
+         <p>¥<span>539</span><i>¥600</i></p>
+         <p class="p-tag">限时活动</p>
+       </div>
+     </div>
+   </div>
+   <div class="point-qa">
+     <div class="qa-item" v-for="(item,i) in qa" :key="i">
+       <p>{{item.q}}</p>
+       <p>{{item.a}}</p>
+     </div>
+   </div>
+ </div>
+</template>
+
+<script>
+
+export default {
+
+  data () {
+    let qa = [
+      {
+        q: '为什么需要点数充值?',
+        a: '当您的基础点数不足99点时,最新拍摄的场景将无法生成,通过购买点数则可以计算存储更多场景。'
+      }, {
+        q: '点数充值之后还可以退款吗?',
+        a: '不可以,因为点数充值之后,相应点数会立即到账生效,所以不接受中途退款,敬请谅解。'
+      }, {
+        q: '删除场景后会返还点数吗?',
+        a: '点数充值没有有效期,所以消费后代表永久记录您的美好空间,删除场景后不会返还。'
+      }, {
+        q: '点数不足还可继续拍摄上传吗?',
+        a: '点数不足时,不影响设备正常的拍摄,但会无法上传计算,这时只能进行删除操作;直到您的点数满足消费,此时您才可以将拍摄的场景上传计算,随之可查看、编辑和分享。'
+      }
+    ]
+    return {
+      qa
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 84 - 0
src/pages/introtow/style.scss

@@ -0,0 +1,84 @@
+.introtow-layout{
+  .it-header{
+    height: 74px;
+    padding: 18px 0 23px;
+  }
+  .it-txt{
+    &>p{
+      margin-bottom: 6px;
+      padding-left: 10px;
+      color: #969696;
+      font-size: 12px;
+      &:first-child{
+        font-weight: bold;
+        font-size: 16px;
+        color: #2d2d2d;
+      }
+    }
+  }
+  .point-list{
+    background-color: #f7f7f7;
+    padding: 15px 0;
+    &>p{
+      &:first-child{
+        font-size: 18px;
+      }
+    }
+    .card-scroll{
+      overflow-y: hidden;
+      overflow-x: scroll;
+      white-space: nowrap;
+      margin-left: 12px;
+      &::-webkit-scrollbar{
+        display: none;
+      }
+      .card-item{
+        width: 135px;
+        display: inline-block;
+        background-color: #fff;
+        margin-right: 8px;
+        padding: 12px;
+        .p-tag{
+          background-color: #ffe8e8;
+          display: inline-block;
+          color: #f04c42;
+          font-size: 10px;
+          padding: 2px 4px;
+          border-radius: 4px;
+          margin-bottom: 0;
+        }
+        p{
+          font-size: 14px;
+          font-weight: bold;
+          margin-bottom: 6px;
+          span{
+            font-size: 20px;
+          }
+          i{
+            color: #ccc;
+            font-size: 10px;
+            text-decoration: line-through;
+            margin-left: 4px;
+          }
+        }
+      }
+    }
+  }
+  .point-qa{
+    padding: 12px;
+    .qa-item{
+      p{
+        font-size: 12px;
+        margin-bottom: 10px;
+        color: #969696;
+        line-height: 1.5;
+        &:first-child{
+          color: #2d2d2d;
+          font-weight: bold;
+          font-size: 14px;
+          margin-bottom: 6px;
+        }
+      }
+    }
+  }
+}

+ 11 - 3
src/pages/layout/header.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
   <div class="header-layout" >
   <div class="header-layout" >
-    <div class="h-left" @touchend="active = !active">
+    <div class="h-left" @click="active = !active">
       <div class="l-con" :class="{active:active}" >
       <div class="l-con" :class="{active:active}" >
         <span class="l1"></span>
         <span class="l1"></span>
         <span class="l2"></span>
         <span class="l2"></span>
@@ -17,7 +17,7 @@
         <i class="iconfont icon-sousuo" @click="()=>{searchActive = true;active = false}"></i>
         <i class="iconfont icon-sousuo" @click="()=>{searchActive = true;active = false}"></i>
       </div>
       </div>
       <div class="h-user" v-else-if="isAccout">
       <div class="h-user" v-else-if="isAccout">
-          <i class="iconfont icon-cart" @click="$router.push({path:'/cart'})"><span>{{count}}</span></i>
+          <i class="iconfont icon-cart" @click="$router.push({path:'/cart'})"><span>{{count>99?'99+':count}}</span></i>
           <img ref="userList" :src="`${$cdn}images/icon/nav_icon.png`" @click="userList=!userList" alt="">
           <img ref="userList" :src="`${$cdn}images/icon/nav_icon.png`" @click="userList=!userList" alt="">
         <ul :class="{'ul-active':userList}" >
         <ul :class="{'ul-active':userList}" >
           <li v-for="(item,i) in manage" :key="i" @click="handleClick(item)">{{item.name}}</li>
           <li v-for="(item,i) in manage" :key="i" @click="handleClick(item)">{{item.name}}</li>
@@ -118,6 +118,14 @@ export default {
         to: {path: '/myscene'}
         to: {path: '/myscene'}
       },
       },
       {
       {
+        name: '我的设备',
+        to: {path: '/device'}
+      },
+      {
+        name: '消费记录',
+        to: {path: '/consumption'}
+      },
+      {
         name: '修改密码',
         name: '修改密码',
         to: {path: '/change'}
         to: {path: '/change'}
       },
       },
@@ -148,7 +156,7 @@ export default {
     },
     },
     searchTxt (newVal) {
     searchTxt (newVal) {
       if (newVal) {
       if (newVal) {
-        this.getData()
+        this.currentPage === 1 ? this.getData() : this.currentPage = 1
       } else {
       } else {
         this.scene = []
         this.scene = []
       }
       }

+ 5 - 7
src/pages/layout/style.scss

@@ -19,8 +19,6 @@ $bannerHeight:60px;
   background-color: #1fe4dc;
   background-color: #1fe4dc;
 }
 }
 .header-layout {
 .header-layout {
-  position: fixed;
-  box-sizing: content-box;
   z-index: 9999;
   z-index: 9999;
   background-color: #101010;
   background-color: #101010;
   display: flex;
   display: flex;
@@ -29,7 +27,6 @@ $bannerHeight:60px;
   align-items: center;
   align-items: center;
   padding: 0 10px;
   padding: 0 10px;
   width: 100%;
   width: 100%;
-  box-sizing: border-box;
   .h-left {
   .h-left {
     width: 40px;
     width: 40px;
     height: $bannerHeight;
     height: $bannerHeight;
@@ -110,7 +107,7 @@ $bannerHeight:60px;
         }
         }
       }
       }
       .ul-active{
       .ul-active{
-        max-height: 150px;
+        max-height: 250px;
       }
       }
       img{
       img{
         width: 50%;
         width: 50%;
@@ -131,9 +128,9 @@ $bannerHeight:60px;
           text-align: center;
           text-align: center;
           li{
           li{
             padding: 0 11px;
             padding: 0 11px;
-            line-height: 30px;
-            height: 30px;
-            font-size: 12px;
+            line-height: 32px;
+            height: 32px;
+            font-size: 14px;
             color: rgba(0, 0, 0, 0.7);
             color: rgba(0, 0, 0, 0.7);
           }
           }
        }
        }
@@ -275,6 +272,7 @@ $bannerHeight:60px;
   }
   }
 
 
   .nav-active {
   .nav-active {
+    z-index: 9999;
     position: absolute;
     position: absolute;
     top: $bannerHeight;
     top: $bannerHeight;
     width: 100%;
     width: 100%;

+ 1 - 1
src/pages/location/index.vue

@@ -2,7 +2,7 @@
   <div class="home-layout">
   <div class="home-layout">
     <div class="plate01">
     <div class="plate01">
       <div class="fdkk-pro">
       <div class="fdkk-pro">
-        <img :style="{marginTop:language==='en'?'136px':'64px'}" :src="`${$cdn}images/hxjs-model.png`" alt="">
+        <img :src="`${$cdn}images/hxjs-model.png`" alt="">
         <div class="pulse" v-for="(item,i) in langCoreTech.kjdw.points" :style="item.posi" :key="i"></div>
         <div class="pulse" v-for="(item,i) in langCoreTech.kjdw.points" :style="item.posi" :key="i"></div>
       </div>
       </div>
       <div class="title">
       <div class="title">

+ 1 - 1
src/pages/location/style.scss

@@ -51,7 +51,7 @@
       position: relative;
       position: relative;
       padding-top: 80px;
       padding-top: 80px;
       img {
       img {
-        margin-top: 136px;
+        margin-top: 64px;
         width: 100%;
         width: 100%;
       }
       }
       .pulse {
       .pulse {

+ 12 - 0
src/pages/privilege/index.vue

@@ -0,0 +1,12 @@
+<template>
+ <div></div>
+</template>
+
+<script>
+
+export default {
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 17 - 64
src/pages/purchase/index.vue

@@ -2,50 +2,47 @@
   <div class="purchase-layout">
   <div class="purchase-layout">
     <div class="plate01">
     <div class="plate01">
       <div class="top">
       <div class="top">
-        <span @touchend="$router.push({name:'eight'})">概览</span>
-        <span @click="scrollTo('jsgg')">技术规格</span>
+        <span @click="$router.push({name:'eight'})">{{langPurchase.top1}}</span>
+        <span @click="scrollTo('jsgg')">{{langPurchase.top2}}</span>
       </div>
       </div>
       <div class="main-layout">
       <div class="main-layout">
         <img class="pro" :src="`${$cdn}images/banner_pro.png`" alt="">
         <img class="pro" :src="`${$cdn}images/banner_pro.png`" alt="">
         <div class="txt-con">
         <div class="txt-con">
           <img class="p-logo" :src="`${$cdn}images/pro-logo-m.png`" alt="">
           <img class="p-logo" :src="`${$cdn}images/pro-logo-m.png`" alt="">
-          <div class="p-label">15分钟快速建模,全自动生成空间模型,实时计算空间尺寸,10K分辨率,支持4倍放大</div>
-          <div class="p-price">RMB 9,800</div>
+          <div class="p-label" v-html="langPurchase.dec"></div>
+          <div class="p-price">{{langPurchase.price}}</div>
         </div>
         </div>
         <div class="attr-con">
         <div class="attr-con">
-          <div class="attr">颜色</div>
+          <div class="attr">{{langPurchase.color.key}}</div>
           <div class="box color">
           <div class="box color">
             <i class="iconfont icon-yuandian"></i>
             <i class="iconfont icon-yuandian"></i>
-            静谧黑</div>
-          <div class="attr">服务</div>
+            {{langPurchase.color.val}}</div>
+          <div class="attr">{{langPurchase.service.key}}</div>
           <div class="box service">
           <div class="box service">
             <ul>
             <ul>
-              <li>数据永久存储</li>
-              <li>高速上传计算队列</li>
-              <li>场景分享、热点编辑隐私</li>
+              <li v-for="(item,i) in langPurchase.service.val1" :key="i" v-html="item"></li>
             </ul>
             </ul>
             <span class="line"></span>
             <span class="line"></span>
             <ul>
             <ul>
-              <li>多种个性化功能</li>
-              <li>附送30G终身容量</li>
+              <li v-for="(item,i) in langPurchase.service.val2" :key="i" v-html="item"></li>
             </ul>
             </ul>
           </div>
           </div>
-          <div class="attr">赠品</div>
+          <div class="attr">{{langPurchase.gift.key}}</div>
           <div class="box zhijia">
           <div class="box zhijia">
             <img :src="`${$cdn}images/zhijia.png`" alt>
             <img :src="`${$cdn}images/zhijia.png`" alt>
-            <span>官方拍摄支架 x 1</span>
+            <span>{{langPurchase.gift.val}}</span>
           </div>
           </div>
-          <div class="attr">数量</div>
+          <div class="attr">{{langPurchase.count.key}}</div>
           <spinner class="count" @count='handleNum' />
           <spinner class="count" @count='handleNum' />
-          <div class="btn" @click="addcart">立即购买</div>
+          <div class="btn" @click="addcart">{{langPurchase.buy}}</div>
           <div class="dec">* 付款成功后5个工作日内发货,默认顺丰快递包邮</div>
           <div class="dec">* 付款成功后5个工作日内发货,默认顺丰快递包邮</div>
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
     <div class="plate02" ref="jsgg">
     <div class="plate02" ref="jsgg">
-      <div class="p2-name">{{parmas.name}}</div>
+      <div class="p2-name">{{langPurchase.parmas.name}}</div>
       <div class="p2-pramas">
       <div class="p2-pramas">
-        <div v-for="(item,i) in parmas.detail" :key="i">
+        <div v-for="(item,i) in langPurchase.parmas.detail" :key="i">
           <p class="title">{{item.label}}</p>
           <p class="title">{{item.label}}</p>
           <div class="name">{{item.name}}</div>
           <div class="name">{{item.name}}</div>
           <div class="detail" >
           <div class="detail" >
@@ -71,56 +68,12 @@ export default {
   },
   },
   computed: {
   computed: {
     ...mapState({
     ...mapState({
-      token: state => state.user.token
+      token: state => state.user.token,
+      langPurchase: state => state.language.home.purchase
     })
     })
   },
   },
   data () {
   data () {
-    let parmas = {
-      name: '技术规格',
-      detail: [
-        {
-          label: '型号',
-          dec: [
-            '高度: 141.5毫米 / ',
-            '宽度: 71.1mm / ',
-            '厚度:17.98mm',
-            '<br/>重量:115g'
-          ]
-        }, {
-          label: '材质',
-          name: '',
-          dec: [
-            '钛金属 / ',
-            '磨砂背']
-        }, {
-          label: '摄像头',
-          name: '',
-          dec: ['f / 2.0 大光圈镜头 / ', '3200万像素SONY sensor / ', '220°双鱼眼镜头 / ', '9片8组光学镜头 / ', '3K视频录制速度为30fps']
-        }, {
-          label: '连接',
-          name: '蓝牙:5.0',
-          dec: ['WiFi / ', 'WiFi:802.11a / b / g / n / ac']
-        }, {
-          label: '电池',
-          name: '',
-          dec: ['3040mAh / ', '通过USB快速充电']
-        }, {
-          label: '存储',
-          name: '',
-          dec: ['支持128G TF卡 / ', '3K视频 录制120分钟']
-        }, {
-          label: '端口',
-          name: '',
-          dec: ['microUSB / ', '三脚架固定孔']
-        }, {
-          label: '防水防尘',
-          name: '',
-          dec: ['IP54']
-        }
-      ]
-    }
     return {
     return {
-      parmas,
       count: 1
       count: 1
     }
     }
   },
   },

+ 1 - 0
src/pages/purchase/style.scss

@@ -88,6 +88,7 @@
           ul{
           ul{
             display: inline-block;
             display: inline-block;
             vertical-align: top;
             vertical-align: top;
+            width: 40%;
             &:last-child{
             &:last-child{
               float: right;
               float: right;
               margin-left: 20px;
               margin-left: 20px;

+ 17 - 19
src/pages/purchasetwo/index.vue

@@ -2,50 +2,47 @@
   <div class="purchase-layout">
   <div class="purchase-layout">
     <div class="plate01">
     <div class="plate01">
       <div class="top">
       <div class="top">
-        <span @touchend="$router.push({name:'eight'})">概览</span>
-        <span @click="scrollTo('jsgg')">技术规格</span>
+        <span @click="$router.push({name:'binocular'})">{{langPurchase.top1}}</span>
+        <span @click="scrollTo('jsgg')">{{langPurchase.top2}}</span>
       </div>
       </div>
       <div class="main-layout">
       <div class="main-layout">
         <img class="pro" :src="`${$cdn}images/t_product.png`" alt="">
         <img class="pro" :src="`${$cdn}images/t_product.png`" alt="">
         <div class="txt-con">
         <div class="txt-con">
           <img class="p-logo" :src="`${$cdn}images/lite-logo-m.png`" alt="">
           <img class="p-logo" :src="`${$cdn}images/lite-logo-m.png`" alt="">
-          <div class="p-label">10分钟复刻空间,时间仅需传统设备的1/20,4K高清画质,实现沉浸式3D实景空间漫游</div>
-          <div class="p-price">RMB 3,999</div>
+          <div class="p-label"  v-html="langPurchase.dec"></div>
+          <div class="p-price">{{langPurchase.price}}</div>
         </div>
         </div>
         <div class="attr-con">
         <div class="attr-con">
-          <div class="attr">颜色</div>
+          <div class="attr">{{langPurchase.color.key}}</div>
           <div class="box color">
           <div class="box color">
             <i class="iconfont icon-yuandian"></i>
             <i class="iconfont icon-yuandian"></i>
-            静谧黑</div>
-          <div class="attr">服务</div>
+            {{langPurchase.color.val}}</div>
+          <div class="attr">{{langPurchase.service.key}}</div>
           <div class="box service">
           <div class="box service">
             <ul>
             <ul>
-              <li>数据永久存储</li>
-              <li>高速上传计算队列</li>
-              <li>场景分享、热点编辑隐私</li>
+              <li v-for="(item,i) in langPurchase.service.val1" :key="i" v-html="item"></li>
             </ul>
             </ul>
             <span class="line"></span>
             <span class="line"></span>
             <ul>
             <ul>
-              <li>多种个性化功能</li>
-              <li>附送30G终身容量</li>
+              <li v-for="(item,i) in langPurchase.service.val2" :key="i" v-html="item"></li>
             </ul>
             </ul>
           </div>
           </div>
-          <div class="attr">赠品</div>
+          <div class="attr">{{langPurchase.gift.key}}</div>
           <div class="box zhijia">
           <div class="box zhijia">
             <img :src="`${$cdn}images/zhijia.png`" alt>
             <img :src="`${$cdn}images/zhijia.png`" alt>
-            <span>官方拍摄支架 x 1</span>
+            <span>{{langPurchase.gift.val}}</span>
           </div>
           </div>
-          <div class="attr">数量</div>
+          <div class="attr">{{langPurchase.count.key}}</div>
           <spinner class="count" @count='handleNum' />
           <spinner class="count" @count='handleNum' />
-          <div class="btn" @click="addcart">立即购买</div>
+          <div class="btn" @click="addcart">{{langPurchase.buy}}</div>
           <div class="dec">* 付款成功后5个工作日内发货,默认顺丰快递包邮</div>
           <div class="dec">* 付款成功后5个工作日内发货,默认顺丰快递包邮</div>
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
     <div class="plate02" ref="jsgg">
     <div class="plate02" ref="jsgg">
-      <div class="p2-name">{{parmas.name}}</div>
+      <div class="p2-name">{{langPurchase.parmas.name}}</div>
       <div class="p2-pramas">
       <div class="p2-pramas">
-        <div v-for="(item,i) in parmas.detail" :key="i">
+        <div v-for="(item,i) in langPurchase.parmas.detail" :key="i">
           <p class="title">{{item.label}}</p>
           <p class="title">{{item.label}}</p>
           <div class="name">{{item.name}}</div>
           <div class="name">{{item.name}}</div>
           <div class="detail" >
           <div class="detail" >
@@ -71,7 +68,8 @@ export default {
   },
   },
   computed: {
   computed: {
     ...mapState({
     ...mapState({
-      token: state => state.user.token
+      token: state => state.user.token,
+      langPurchase: state => state.language.home.purchasetow
     })
     })
   },
   },
   data () {
   data () {

+ 1 - 0
src/pages/purchasetwo/style.scss

@@ -86,6 +86,7 @@
           padding: 13px 12%;
           padding: 13px 12%;
           width: 100%;
           width: 100%;
           ul{
           ul{
+            width: 40%;
             display: inline-block;
             display: inline-block;
             vertical-align: top;
             vertical-align: top;
             &:last-child{
             &:last-child{

+ 39 - 0
src/router/index.js

@@ -12,6 +12,27 @@ let router = new Router({
       component: resolve => require(['@/pages/home'], resolve)
       component: resolve => require(['@/pages/home'], resolve)
     },
     },
     {
     {
+      path: '/404',
+      name: '404',
+      component: resolve => require(['@/pages/404'], resolve)
+    },
+    {
+      path: '/introduce/:id',
+      name: 'introduce',
+      component: resolve => require(['@/pages/introduce'], resolve)
+    },
+    {
+      path: '/introtow/:id',
+      name: 'introtow',
+      component: resolve => require(['@/pages/introtow'], resolve)
+    },
+    {
+      path: '/privilege/:cameraId/:childName',
+      name: 'privilege',
+      component: resolve => require(['@/pages/privilege'], resolve)
+    },
+
+    {
       path: '/binocular',
       path: '/binocular',
       name: 'binocular',
       name: 'binocular',
       component: resolve => require(['@/pages/binocular'], resolve)
       component: resolve => require(['@/pages/binocular'], resolve)
@@ -64,6 +85,24 @@ let router = new Router({
           meta: {requireAuth: true}
           meta: {requireAuth: true}
         },
         },
         {
         {
+          path: '/openInvoice',
+          name: 'openInvoice',
+          component: resolve => require(['@/pages/account/manage/openInvoice'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'device',
+          path: '/device',
+          component: resolve => require(['@/pages/account/manage/device'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'consumption',
+          path: '/consumption',
+          component: resolve => require(['@/pages/account/manage/consumption'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
           name: 'order',
           name: 'order',
           path: '/order',
           path: '/order',
           component: resolve => require(['@/pages/account/manage/order'], resolve),
           component: resolve => require(['@/pages/account/manage/order'], resolve),

+ 1 - 1
src/store/language/cn/about.js

@@ -21,7 +21,7 @@ export default{
       name: '德国人工智能研究中心',
       name: '德国人工智能研究中心',
       txt: [
       txt: [
         '德国人工智能研究中心(DFKI)创立于1988年,是德国顶级的人工智能研究机构,也是目前世界上最大的非营利性人工智能研究机构,研究方向覆盖人工智能的主要产业方向,包括大数据分析、知识管理、画面处理和理解自然语言处理、人机交互、机器人。其股东包括Google、Intel、微软、宝马、SAP、Airbus在内的全球顶级科技企业。',
         '德国人工智能研究中心(DFKI)创立于1988年,是德国顶级的人工智能研究机构,也是目前世界上最大的非营利性人工智能研究机构,研究方向覆盖人工智能的主要产业方向,包括大数据分析、知识管理、画面处理和理解自然语言处理、人机交互、机器人。其股东包括Google、Intel、微软、宝马、SAP、Airbus在内的全球顶级科技企业。',
-        '德国人工智能研究中心CEO沃夫冈·瓦尔斯特尔(Wolfgang Wahlster)教授是德国总理默克尔的科技顾问,也是“工业4 . 0”构想发起者之一。中心旗下大约有900名科学家、研究人员及工程师,其中包括德国国家科学院、欧洲科学院、瑞士皇家科学院、德国自然与文学科学院、德国自然与工程科学院、柏林勃兰登堡自然与人类学科学院等知名科学院的院士。'
+        '德国人工智能研究中心CEO——沃夫冈·瓦尔斯特尔(Wolfgang Wahlster)教授是德国总理默克尔的科技顾问,也是“工业4 . 0”构想发起者之一。中心旗下大约有900名科学家、研究人员及工程师,其中包括德国国家科学院、欧洲科学院、瑞士皇家科学院、德国自然与文学科学院、德国自然与工程科学院、柏林勃兰登堡自然与人类学科学院等知名科学院的院士。'
       ],
       ],
       img: require('@/assets/images/DFKI.png')
       img: require('@/assets/images/DFKI.png')
     }
     }

+ 2 - 6
src/store/language/cn/binocular.js

@@ -97,11 +97,11 @@ export default{
       }, {
       }, {
         label: '连接',
         label: '连接',
         name: '蓝牙:5.0',
         name: '蓝牙:5.0',
-        dec: ['WiFi / ', 'WiFi:802.11a / b / g / n / ac']
+        dec: ['WiFi:802.11a / b / g / n / ac']
       }, {
       }, {
         label: '电池',
         label: '电池',
         name: '',
         name: '',
-        dec: ['3040mAh / ', '通过USB快速充电']
+        dec: ['2000mAh / ', '通过USB快速充电']
       }, {
       }, {
         label: '存储',
         label: '存储',
         name: '',
         name: '',
@@ -110,10 +110,6 @@ export default{
         label: '端口',
         label: '端口',
         name: '',
         name: '',
         dec: ['microUSB / ', '三脚架固定孔']
         dec: ['microUSB / ', '三脚架固定孔']
-      }, {
-        label: '防水防尘',
-        name: '',
-        dec: ['IP54']
       }
       }
     ]
     ]
   }
   }

+ 3 - 3
src/store/language/cn/coreTech.js

@@ -48,7 +48,7 @@ export default{
       }],
       }],
     ability: {
     ability: {
       name: 'AI数字化算法的创新技术能力',
       name: 'AI数字化算法的创新技术能力',
-      sub: '全新算法极大提升了关键帧特征点的匹配准确率<br/>把定位丢失的情况降至最低。另外,基于自适应<br/>分段的集束调整,把长序列分成若干<br/>序列在后端优化,改善了优化效率',
+      sub: '计算相机在拍摄时的空间位置,并提取对应的3D点云,从而获取三维空间的真实情况。',
       app: [
       app: [
         {
         {
           icon: require('@/assets/images/img_core_app01.png'),
           icon: require('@/assets/images/img_core_app01.png'),
@@ -60,14 +60,14 @@ export default{
         },
         },
         {
         {
           icon: require('@/assets/images/img_core_app03.png'),
           icon: require('@/assets/images/img_core_app03.png'),
-          sub: '人工智能算法<br/>与环闭合配合运作<br/>使相机几何校准<br/>加快速稳定'
+          sub: '人工智能算法<br/>使相机几何校准<br/>加快速稳定'
         }
         }
       ]
       ]
     }
     }
   },
   },
   kjjm: {
   kjjm: {
     title: '空间重建',
     title: '空间重建',
-    logon: '自动化高精度三维数字建技术,恢复空间的平面<br/>布局以及三维结构,无需人工干预从上传到生成结果<br/>仅需要5-10分钟。自动化高精度三维数字重建技术<br/>在获取稀疏点云和相机位姿后,计算空间的平面布局<br/>并恢复三维结构,生成3D场景',
+    logon: '自动化高精度三维数字建技术,恢复空间的平面<br/>布局以及三位结构,无需人工干预。',
     dec: ['自动化高精度三维数字建模技术', '恢复空间的平面布局以及三维结构', '无需人工干预,从上传到生成结果仅需要5-10分钟。'],
     dec: ['自动化高精度三维数字建模技术', '恢复空间的平面布局以及三维结构', '无需人工干预,从上传到生成结果仅需要5-10分钟。'],
     chars: [
     chars: [
       {
       {

+ 24 - 26
src/store/language/cn/eight.js

@@ -6,7 +6,7 @@ export default{
   introduce: {
   introduce: {
     title: ['四维看看 Pro', '专业精准建模,高效复刻空间'],
     title: ['四维看看 Pro', '专业精准建模,高效复刻空间'],
     price: 'RMB 9,800',
     price: 'RMB 9,800',
-    dec: '15分钟快速三维重建,全自动生成数字3D空间,实时计算空间尺寸,10K分辨率,支持4倍放大',
+    dec: '15分钟快速三维重建,全自动生成数字3D空间,实时计算空间尺寸,12K分辨率,支持4倍放大',
     btn: '立即购买',
     btn: '立即购买',
     subTitle: '让三维空间获得数字新生',
     subTitle: '让三维空间获得数字新生',
     benefitGroup: [
     benefitGroup: [
@@ -37,10 +37,10 @@ export default{
     sub: ['快速编辑和分享你的互动式视频', '分享你的空间故事']
     sub: ['快速编辑和分享你的互动式视频', '分享你的空间故事']
   },
   },
   definition: {
   definition: {
-    title: '10K高清画质<br/>捕捉空间的每个细节',
+    title: '12K高清画质<br/>捕捉空间的每个细节',
     top: {
     top: {
-      dec: '四维看看Pro全方位记录空间信息,生成实景3D数字空间,让您走进3D场景,如临现场般自由探索。10K清晰度,可4倍放大画面,不错过任何细节。',
-      intro: '拍摄画面分辨率高达10000*5000像素'
+      dec: '四维看看Pro全方位记录空间信息,生成实景3D数字空间,让您走进3D场景,如临现场般自由探索。12K清晰度,可4倍放大画面,不错过任何细节。',
+      intro: '拍摄画面分辨率高达12288*6144像素'
 
 
     },
     },
     bottom: {
     bottom: {
@@ -92,7 +92,7 @@ export default{
         lTxt: '四维看看 Lite',
         lTxt: '四维看看 Lite',
         rTxt: '四维看看 Pro',
         rTxt: '四维看看 Pro',
         lMask: '4K高清',
         lMask: '4K高清',
-        rMask: '10K高清图像,4倍放大'
+        rMask: '12K高清图像,4倍放大'
       }
       }
     },
     },
     ranging: {
     ranging: {
@@ -127,42 +127,40 @@ export default{
     detail: [
     detail: [
       {
       {
         label: '型号',
         label: '型号',
+        name: '四维看看 Pro',
         dec: [
         dec: [
-          '高度: 141.5毫米 / ',
-          '宽度: 71.1mm / ',
-          '厚度:17.98mm',
-          '<br/>重量:115g'
+          '高度: 220.7毫米 / ',
+          '宽度: 78.2毫米 / ',
+          '厚度:78.2毫米'
         ]
         ]
       }, {
       }, {
-        label: '材质',
+        label: '镜头',
         name: '',
         name: '',
         dec: [
         dec: [
-          '钛金属 / ',
-          '磨砂背']
+          '类型:200°鱼眼镜头 /  ',
+          '孔径:f/2.0 /  ',
+          '数量:8个 /  ',
+          '分辨率:4608*3456像素(每个);12288*6144像素(合计)']
       }, {
       }, {
-        label: '摄像头',
+        label: '传感器',
         name: '',
         name: '',
-        dec: ['f / 2.0 大光圈镜头 / ', '3200万像素SONY sensor / ', '220°双鱼眼镜头 / ', '9片8组光学镜头 / ', '3K视频录制速度为30fps']
+        dec: ['范围:1/2.3英寸 / ', '数量:8个']
       }, {
       }, {
-        label: '连接',
-        name: '蓝牙:5.0',
-        dec: ['WiFi / ', 'WiFi:802.11a / b / g / n / ac']
-      }, {
-        label: '电池',
+        label: '存储内存',
         name: '',
         name: '',
-        dec: ['3040mAh / ', '通过USB快速充电']
+        dec: ['16GB']
       }, {
       }, {
-        label: '存储',
+        label: '电池',
         name: '',
         name: '',
-        dec: ['支持128G TF卡 / ', '3K视频 录制120分钟']
+        dec: ['7.4V 4200mAh / ', '可通过USB快速充电']
       }, {
       }, {
-        label: '端口',
+        label: 'WiFi',
         name: '',
         name: '',
-        dec: ['microUSB / ', '三脚架固定孔']
+        dec: ['802.11a/b/g/n网络协议 / ', '支持2.4/5GHz通信']
       }, {
       }, {
-        label: '防水防尘',
+        label: '设备接口',
         name: '',
         name: '',
-        dec: ['IP54']
+        dec: ['TYPE C']
       }
       }
     ]
     ]
   }
   }

+ 1 - 1
src/store/language/cn/home.js

@@ -107,7 +107,7 @@ export default{
       image: baseUrl + 'images/phone_9.jpg',
       image: baseUrl + 'images/phone_9.jpg',
       icon: baseUrl + 'images/phone_icon_9.png',
       icon: baseUrl + 'images/phone_icon_9.png',
       text: '伟星' },
       text: '伟星' },
-    {url: 'https://admin.4dmuseum.cn/showPC.html?m=333&bigScene&novr',
+    {url: 'https://admin.4dmuseum.cn/showApp.html?m=240&bigScene&novr',
       image: baseUrl + 'images/phone_10.jpg',
       image: baseUrl + 'images/phone_10.jpg',
       icon: baseUrl + 'images/phone_icon_10.png',
       icon: baseUrl + 'images/phone_icon_10.png',
       text: '武侯祠' }
       text: '武侯祠' }

+ 123 - 0
src/store/language/cn/purchase.js

@@ -0,0 +1,123 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '15分钟快速三维重建,全自动生成数字3D空间,实时计算空间尺寸,12K分辨率,支持4倍放大',
+  yushou: '【新品预售】',
+  price: 'RMB 9,800',
+  buy: '立即购买',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: '机身尺寸',
+        val: ['高度:220.7毫米', '宽度:78.2毫米', '厚度:78.2毫米']
+      },
+      {
+        name: '镜头',
+        val: [
+          '类型:200°鱼眼镜头',
+          '孔径:f/2.0',
+          '数量:8个',
+          '分辨率:4608*3456像素(每个);12288*6144像素(合计)'
+        ]
+      },
+      {
+        name: '传感器',
+        val: ['范围:1/2.3英寸', '数量:8个']
+      },
+      {
+        name: '存储内存',
+        val: [
+          '16GB'
+        ]
+      },
+      {
+        name: '电池',
+        val: [
+          '7.4V 4200mAh',
+          '可通过USB快速充电'
+        ]
+      },
+      {
+        name: 'WiFi',
+        val: [
+          '802.11a/b/g/n网络协议',
+          '支持2.4/5GHz通信'
+        ]
+      },
+      {
+        name: '设备接口',
+        val: [
+          'TYPE C'
+        ]
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val1: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密'
+    ],
+    val2: [
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  },
+  parmas: {
+    name: '技术规格',
+    detail: [
+      {
+        label: '型号',
+        name: '四维看看 Pro',
+        dec: [
+          '高度: 220.7毫米 / ',
+          '宽度: 78.2毫米 / ',
+          '厚度:78.2毫米'
+        ]
+      }, {
+        label: '镜头',
+        name: '',
+        dec: [
+          '类型:200°鱼眼镜头 /  ',
+          '孔径:f/2.0 /  ',
+          '数量:8个 /  ',
+          '分辨率:4608*3456像素(每个);12288*6144像素(合计)']
+      }, {
+        label: '传感器',
+        name: '',
+        dec: ['范围:1/2.3英寸 / ', '数量:8个']
+      }, {
+        label: '存储内存',
+        name: '',
+        dec: ['16GB']
+      }, {
+        label: '电池',
+        name: '',
+        dec: ['7.4V 4200mAh / ', '可通过USB快速充电']
+      }, {
+        label: 'WiFi',
+        name: '',
+        dec: ['802.11a/b/g/n网络协议 / ', '支持2.4/5GHz通信']
+      }, {
+        label: '设备接口',
+        name: '',
+        dec: ['TYPE C']
+      }
+    ]
+  }
+}

+ 113 - 0
src/store/language/cn/purchasetow.js

@@ -0,0 +1,113 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '10分钟复刻空间,时间仅需传统设备的1/20,4K高清画质,实现沉浸式3D实景空间漫游',
+  yushou: '【新品预售】',
+  price: 'RMB 3,999',
+  buy: '立即购买',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: '机身尺寸',
+        val: ['高度:130mm', '宽度:47mm', '厚度:18mm', '重量:115g']
+      },
+      {
+        name: '材质',
+        val: [
+          '钛金属',
+          '磨砂背'
+        ]
+      },
+      {
+        name: '摄像头',
+        val: ['f / 2.0 大光圈镜头',
+          '3200万像素SONY sensor',
+          '220°双鱼眼镜头',
+          '9片8组光学镜头',
+          '3K视频录制速度为30fps']
+      },
+      {
+        name: '连接',
+        val: ['蓝牙:5.0', 'WiFi:802.11a / b / g / n / ac']
+      },
+      {
+        name: '电池',
+        val: ['2000mAh', '通过USB快速充电']
+      },
+      {
+        name: '存储',
+        val: ['支持128G TF卡', '3K视频 录制120分钟']
+      },
+      {
+        name: '端口',
+        val: ['microUSB', '三脚架固定孔']
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val1: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密'
+    ],
+    val2: [
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  },
+  parmas: {
+    name: '技术规格',
+    detail: [
+      {
+        label: '型号',
+        dec: [
+          '高度: 141.5毫米 / ',
+          '宽度: 71.1毫米 / ',
+          '厚度:17.98毫米',
+          '<br/>重量:115g'
+        ]
+      }, {
+        label: '材质',
+        name: '',
+        dec: [
+          '钛金属 / ',
+          '磨砂背']
+      }, {
+        label: '摄像头',
+        name: '',
+        dec: ['f / 2.0 大光圈镜头 / ', '3200万像素SONY sensor / ', '220°双鱼眼镜头 / ', '9片8组光学镜头 / ', '3K视频录制速度为30fps']
+      }, {
+        label: '连接',
+        name: '蓝牙:5.0',
+        dec: ['WiFi:802.11a / b / g / n / ac']
+      }, {
+        label: '电池',
+        name: '',
+        dec: ['2000mAh / ', '通过USB快速充电']
+      }, {
+        label: '存储',
+        name: '',
+        dec: ['支持128G TF卡 / ', '3K视频 录制120分钟']
+      }, {
+        label: '端口',
+        name: '',
+        dec: ['microUSB / ', '三脚架固定孔']
+      }
+    ]
+  }
+}

+ 19 - 23
src/store/language/en/binocular.js

@@ -77,43 +77,39 @@ export default{
     name: 'Detailed Parameters of 4DKanKan Lite',
     name: 'Detailed Parameters of 4DKanKan Lite',
     detail: [
     detail: [
       {
       {
-        label: '型号',
+        label: 'Model',
         dec: [
         dec: [
-          '高度: 130mm / ',
-          '宽度: 47mm / ',
-          '厚度:18mm',
-          '<br/>重量:115g'
+          'Height: 130mm / ',
+          'Width: 47mm / ',
+          'Depth: 18mm',
+          '<br/>Weight: 115g'
         ]
         ]
       }, {
       }, {
-        label: '材质',
+        label: 'Fabric',
         name: '',
         name: '',
         dec: [
         dec: [
-          '钛金属 / ',
-          '磨砂背']
+          'Titanium / ',
+          'Matte surface']
       }, {
       }, {
-        label: '摄像头',
+        label: 'Camera',
         name: '',
         name: '',
-        dec: ['f / 2.0 大光圈镜头 / ', '3200万像素SONY sensor / ', '220°双鱼眼镜头 / ', '9片8组光学镜头 / ', '3K视频录制速度为30fps']
+        dec: ['f / 2.0 aperture / ', '3200-pixels SONY sensor / ', '220° fisheye lens*2 / ', 'Optical lens*8 / ', '30fps recording speed in 3K']
       }, {
       }, {
-        label: '连接',
-        name: '蓝牙:5.0',
-        dec: ['WiFi / ', 'WiFi:802.11a / b / g / n / ac']
+        label: 'Connection',
+        name: 'Bluetooth: 5.0',
+        dec: ['WiFi:802.11a / b / g / n / ac']
       }, {
       }, {
-        label: '电池',
+        label: 'Battery',
         name: '',
         name: '',
-        dec: ['3040mAh / ', '通过USB快速充电']
+        dec: ['2000mAh / ', 'Quick charge through USB']
       }, {
       }, {
-        label: '存储',
+        label: 'Storage',
         name: '',
         name: '',
-        dec: ['支持128G TF卡 / ', '3K视频 录制120分钟']
+        dec: ['128G Trans-flash Card / ', '120-minutes 3K video']
       }, {
       }, {
-        label: '端口',
+        label: 'Interface',
         name: '',
         name: '',
-        dec: ['microUSB / ', '三脚架固定孔']
-      }, {
-        label: '防水防尘',
-        name: '',
-        dec: ['IP54']
+        dec: ['microUSB / ', 'Tripod attachment hole']
       }
       }
     ]
     ]
   }
   }

+ 2 - 2
src/store/language/en/coreTech.js

@@ -48,7 +48,7 @@ export default{
       }],
       }],
     ability: {
     ability: {
       name: 'The Innovative technology of AI Digitization',
       name: 'The Innovative technology of AI Digitization',
-      sub: 'The new algorithm has significantly enhanced the matches of feature points, thus reducing the localization loss to the lowest level. Further, bundle adjustment based on self-adaptive segmentation divides long sequences into several sequences and optimizes it in the back end, thus improving the optimization efficiency.',
+      sub: 'Calculate camera locations and obtain corresponding 3Dpoint clouds to understand real-life environment.',
       app: [
       app: [
         {
         {
           icon: require('@/assets/images/img_core_app01.png'),
           icon: require('@/assets/images/img_core_app01.png'),
@@ -67,7 +67,7 @@ export default{
   },
   },
   kjjm: {
   kjjm: {
     title: 'Space reconstruction',
     title: 'Space reconstruction',
-    logon: '自动化高精度三维数字重建技术,在获取稀疏点云和相机位姿后,计算空间的平面布局<br/>并恢复三维结构,生成3D场景。',
+    logon: 'Automatic and precise 3D digitization technology that recovers floorplan and 3D structure of space without manual intervention.',
     dec: ['Automatic and precise 3D digitization technology that recovers floorplan and 3D structure of space without manual intervention, which takes only 5 to 10 minutes to generate the result.'],
     dec: ['Automatic and precise 3D digitization technology that recovers floorplan and 3D structure of space without manual intervention, which takes only 5 to 10 minutes to generate the result.'],
     chars: [
     chars: [
       {
       {

+ 26 - 28
src/store/language/en/eight.js

@@ -6,7 +6,7 @@ export default{
   introduce: {
   introduce: {
     title: ['四维看看 Pro', '专业精准建模,高效复刻空间'],
     title: ['四维看看 Pro', '专业精准建模,高效复刻空间'],
     price: 'RMB 9,800',
     price: 'RMB 9,800',
-    dec: '4DKanKan Pro generates 3D digital model of space automatically and takes measurements in real time. Results are displayed in 10K definition, and allow 4x magnification.',
+    dec: '4DKanKan Pro generates 3D digital model of space automatically and takes measurements in real time. Results are displayed in 12K definition, and allow 4x magnification.',
     btn: 'Shop Now',
     btn: 'Shop Now',
     subTitle: 'Bring Space to Life in Digital 3D',
     subTitle: 'Bring Space to Life in Digital 3D',
     benefitGroup: [
     benefitGroup: [
@@ -37,10 +37,10 @@ export default{
     sub: ['快速编辑和分享你的互动式视频', '分享你的空间故事']
     sub: ['快速编辑和分享你的互动式视频', '分享你的空间故事']
   },
   },
   definition: {
   definition: {
-    title: '10K Image Quality That Captures Every Detail in the Space',
+    title: '12K Image Quality That Captures Every Detail in the Space',
     top: {
     top: {
-      dec: '4DKanKan Pro records three-dimensional information of space, andproduces realistic 3D digital spaces, allowing you to enter anytimeand freely explore as you were there. Never miss a detail with 10K definition and 4x magnification.',
-      intro: 'Quality of images shot by 4DKanKan Pro<br/>reaches up to 10000*5000 pixels'
+      dec: '4DKanKan Pro records three-dimensional information of space, andproduces realistic 3D digital spaces, allowing you to enter anytimeand freely explore as you were there. Never miss a detail with 12K definition and 4x magnification.',
+      intro: 'Quality of images shot by 4DKanKan Pro<br/>reaches up to 12288*6144 pixels'
     },
     },
     bottom: {
     bottom: {
       title: '细节之处,纤毫毕现',
       title: '细节之处,纤毫毕现',
@@ -91,7 +91,7 @@ export default{
         lTxt: '4DKanKan Lite',
         lTxt: '4DKanKan Lite',
         rTxt: '4DKanKan Pro',
         rTxt: '4DKanKan Pro',
         lMask: 'High-definition of 4K',
         lMask: 'High-definition of 4K',
-        rMask: '10K HD picture with 4-times magnification'
+        rMask: '12K HD picture with 4-times magnification'
       }
       }
     },
     },
     ranging: {
     ranging: {
@@ -122,46 +122,44 @@ export default{
     dec: 'Powered by the integrated work of hundreds of sophisticated parts, 4DKanKan Pro is light and compact, portable and durable, and can capture space in 3D for you at any time.'
     dec: 'Powered by the integrated work of hundreds of sophisticated parts, 4DKanKan Pro is light and compact, portable and durable, and can capture space in 3D for you at any time.'
   },
   },
   parmas: {
   parmas: {
-    name: 'Detailed Parameters of 4DKanKan Pro',
+    name: '四维看看 Pro 详细参数',
     detail: [
     detail: [
       {
       {
-        label: '型号',
+        label: 'Model',
+        name: '4DKanKan Pro',
         dec: [
         dec: [
-          '高度: 141.5毫米 / ',
-          '宽度: 71.1mm / ',
-          '厚度:17.98mm',
-          '<br/>重量:115g'
+          'Height:220.7mm / ',
+          'Width:78.2mm / ',
+          'Depth:78.2mm'
         ]
         ]
       }, {
       }, {
-        label: '材质',
+        label: 'Lenses',
         name: '',
         name: '',
         dec: [
         dec: [
-          '钛金属 / ',
-          '磨砂背']
+          'Type:200°fisheye lens /  ',
+          'Aperture:f/2.0 /  ',
+          'Number:8 /  ',
+          'Resolution:4608*3456pixels(each); 12288*6144pixels(total)']
       }, {
       }, {
-        label: '摄像头',
+        label: 'Sensors',
         name: '',
         name: '',
-        dec: ['f / 2.0 大光圈镜头 / ', '3200万像素SONY sensor / ', '220°双鱼眼镜头 / ', '9片8组光学镜头 / ', '3K视频录制速度为30fps']
+        dec: ['Dimension:1/2.3" / ', 'Number:8']
       }, {
       }, {
-        label: '连接',
-        name: '蓝牙:5.0',
-        dec: ['WiFi / ', 'WiFi:802.11a / b / g / n / ac']
-      }, {
-        label: '电池',
+        label: 'Storage',
         name: '',
         name: '',
-        dec: ['3040mAh / ', '通过USB快速充电']
+        dec: ['16GB']
       }, {
       }, {
-        label: '存储',
+        label: 'Battery',
         name: '',
         name: '',
-        dec: ['支持128G TF卡 / ', '3K视频 录制120分钟']
+        dec: ['7.4V 4200mAh / ', 'USB charge']
       }, {
       }, {
-        label: '端口',
+        label: 'WiFi',
         name: '',
         name: '',
-        dec: ['microUSB / ', '三脚架固定孔']
+        dec: ['802.11a/b/g/n / ', '2.4/5GHz communication']
       }, {
       }, {
-        label: '防水防尘',
+        label: 'USB',
         name: '',
         name: '',
-        dec: ['IP54']
+        dec: ['TYPE C']
       }
       }
     ]
     ]
   }
   }

+ 1 - 1
src/store/language/en/home.js

@@ -107,7 +107,7 @@ export default{
       image: baseUrl + 'images/phone_9.jpg',
       image: baseUrl + 'images/phone_9.jpg',
       icon: baseUrl + 'images/phone_icon_9.png',
       icon: baseUrl + 'images/phone_icon_9.png',
       text: '伟星' },
       text: '伟星' },
-    {url: 'https://admin.4dmuseum.cn/showPC.html?m=333&bigScene&novr',
+    {url: 'https://admin.4dmuseum.cn/showApp.html?m=240&bigScene&novr',
       image: baseUrl + 'images/phone_10.jpg',
       image: baseUrl + 'images/phone_10.jpg',
       icon: baseUrl + 'images/phone_icon_10.png',
       icon: baseUrl + 'images/phone_icon_10.png',
       text: '武侯祠' }
       text: '武侯祠' }

+ 123 - 0
src/store/language/en/purchase.js

@@ -0,0 +1,123 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '15分钟快速三维重建,全自动生成数字3D空间,实时计算空间尺寸,12K分辨率,支持4倍放大',
+  yushou: '【新品预售】',
+  price: 'RMB 9,800',
+  buy: '立即购买',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: '机身尺寸',
+        val: ['高度:220.7毫米', '宽度:78.2毫米', '厚度:78.2毫米']
+      },
+      {
+        name: '镜头',
+        val: [
+          '类型:200°鱼眼镜头',
+          '孔径:f/2.0',
+          '数量:8个',
+          '分辨率:4608*3456像素(每个);12288*6144像素(合计)'
+        ]
+      },
+      {
+        name: '传感器',
+        val: ['范围:1/2.3英寸', '数量:8个']
+      },
+      {
+        name: '存储内存',
+        val: [
+          '16GB'
+        ]
+      },
+      {
+        name: '电池',
+        val: [
+          '7.4V 4200mAh',
+          '可通过USB快速充电'
+        ]
+      },
+      {
+        name: 'WiFi',
+        val: [
+          '802.11a/b/g/n网络协议',
+          '支持2.4/5GHz通信'
+        ]
+      },
+      {
+        name: '设备接口',
+        val: [
+          'TYPE C'
+        ]
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val1: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密'
+    ],
+    val2: [
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  },
+  parmas: {
+    name: '技术规格',
+    detail: [
+      {
+        label: 'Model',
+        name: '4DKanKan Pro',
+        dec: [
+          'Height:220.7mm / ',
+          'Width:78.2mm / ',
+          'Depth:78.2mm'
+        ]
+      }, {
+        label: 'Lenses',
+        name: '',
+        dec: [
+          'Type:200°fisheye lens /  ',
+          'Aperture:f/2.0 /  ',
+          'Number:8 /  ',
+          'Resolution:4608*3456pixels(each); 12288*6144pixels(total)']
+      }, {
+        label: 'Sensors',
+        name: '',
+        dec: ['Dimension:1/2.3" / ', 'Number:8']
+      }, {
+        label: 'Storage',
+        name: '',
+        dec: ['16GB']
+      }, {
+        label: 'Battery',
+        name: '',
+        dec: ['7.4V 4200mAh / ', 'USB charge']
+      }, {
+        label: 'WiFi',
+        name: '',
+        dec: ['802.11a/b/g/n / ', '2.4/5GHz communication']
+      }, {
+        label: 'USB',
+        name: '',
+        dec: ['TYPE C']
+      }
+    ]
+  }
+}

+ 113 - 0
src/store/language/en/purchasetow.js

@@ -0,0 +1,113 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '10分钟复刻空间,时间仅需传统设备的1/20,4K高清画质,实现沉浸式3D实景空间漫游',
+  yushou: '【新品预售】',
+  price: 'RMB 3,999',
+  buy: '立即购买',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: 'Size',
+        val: ['Height: 130mm', 'Width: 47mm', 'Depth: 18mm', 'Weight: 115g']
+      },
+      {
+        name: 'Fabric',
+        val: [
+          'Titanium',
+          'Matte surface'
+        ]
+      },
+      {
+        name: 'Camera',
+        val: ['f/2.0 aperture',
+          '3200-pixels SONY sensor',
+          '220° fisheye lens*2',
+          'Optical lens*8',
+          '30fps recording speed in 3K']
+      },
+      {
+        name: 'Connection',
+        val: ['Bluetooth: 5.0', 'WiFi:802.11a / b / g / n / ac']
+      },
+      {
+        name: 'Battery',
+        val: ['2000mAh', 'Quick charge through USB']
+      },
+      {
+        name: 'Storage',
+        val: ['128G Trans-flash Card', '120-minutes 3K video']
+      },
+      {
+        name: 'Interface',
+        val: ['microUSB', 'Tripod attachment hole']
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val1: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密'
+    ],
+    val2: [
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  },
+  parmas: {
+    name: '技术规格',
+    detail: [
+      {
+        label: 'Model',
+        dec: [
+          'Height: 130mm / ',
+          'Width: 47mm / ',
+          'Depth: 18mm /',
+          '<br/>Weight: 115g'
+        ]
+      }, {
+        label: 'Fabric',
+        name: '',
+        dec: [
+          'Titanium / ',
+          'Matte surface']
+      }, {
+        label: 'Camera',
+        name: '',
+        dec: ['f/2.0 aperture / ', '3200-pixels SONY sensor / ', '220° fisheye lens*2 / ', 'Optical lens*8 / ', '30fps recording speed in 3K']
+      }, {
+        label: 'Connection',
+        name: 'Bluetooth: 5.0',
+        dec: ['WiFi:802.11a / b / g / n / ac']
+      }, {
+        label: 'Battery',
+        name: '',
+        dec: ['2000mAh / ', 'Quick charge through USB']
+      }, {
+        label: 'Storage',
+        name: '',
+        dec: ['128G Trans-flash Card / ', '120-minutes 3K video']
+      }, {
+        label: 'Interface',
+        name: '',
+        dec: ['microUSB / ', 'Tripod attachment hole']
+      }
+    ]
+  }
+}

+ 29 - 25
src/store/language/home_cn.js

@@ -3,6 +3,8 @@ import binocular from './cn/binocular'
 import eight from './cn/eight'
 import eight from './cn/eight'
 import about from './cn/about'
 import about from './cn/about'
 import coreTech from './cn/coreTech'
 import coreTech from './cn/coreTech'
+import purchase from './cn/purchase'
+import purchasetow from './cn/purchasetow'
 
 
 export default {
 export default {
   title: '中文',
   title: '中文',
@@ -54,30 +56,30 @@ export default {
           }
           }
         ]
         ]
       },
       },
-      {
-        title: '服务支持',
-        url: '',
-        id: 'fwzc',
-        sub: [ {
-          icon: 'icon-tutorial',
-          name: '使用教程',
-          to: {name: 'service', params: {id: 'use'}}
-        },
-        {
-          icon: 'icon-faq',
-          name: '常见问题',
-          to: {name: 'service', params: {id: 'qa'}}
-        }, {
-          icon: 'icon-appdown',
-          name: 'app下载',
-          to: {name: 'service', params: {id: 'app'}}
-        },
-        {
-          icon: 'icon-sysc',
-          name: '产品手册',
-          to: {name: 'service', params: {id: 'product'}}
-        }]
-      },
+      // {
+      //   title: '服务支持',
+      //   url: '',
+      //   id: 'fwzc',
+      //   sub: [ {
+      //     icon: 'icon-tutorial',
+      //     name: '使用教程',
+      //     to: {name: 'service', params: {id: 'use'}}
+      //   },
+      //   {
+      //     icon: 'icon-faq',
+      //     name: '常见问题',
+      //     to: {name: 'service', params: {id: 'qa'}}
+      //   }, {
+      //     icon: 'icon-appdown',
+      //     name: 'app下载',
+      //     to: {name: 'service', params: {id: 'app'}}
+      //   },
+      //   {
+      //     icon: 'icon-sysc',
+      //     name: '产品手册',
+      //     to: {name: 'service', params: {id: 'product'}}
+      //   }]
+      // },
       {
       {
         title: '核心技术',
         title: '核心技术',
         url: '/location',
         url: '/location',
@@ -98,6 +100,8 @@ export default {
       }
       }
     ]
     ]
   },
   },
+  purchase,
+  purchasetow,
   home,
   home,
   eight,
   eight,
   binocular,
   binocular,
@@ -188,7 +192,7 @@ export default {
       },
       },
       {
       {
         name: '联系电话',
         name: '联系电话',
-        content: '400-6698-025'
+        content: '0086 756-6996790-800'
       }
       }
     ],
     ],
     links: [{
     links: [{

+ 29 - 40
src/store/language/home_en.js

@@ -3,6 +3,8 @@ import binocular from './en/binocular'
 import eight from './en/eight'
 import eight from './en/eight'
 import about from './en/about'
 import about from './en/about'
 import coreTech from './en/coreTech'
 import coreTech from './en/coreTech'
+import purchase from './en/purchase'
+import purchasetow from './en/purchasetow'
 
 
 export default {
 export default {
   title: '英文',
   title: '英文',
@@ -54,50 +56,35 @@ export default {
           }
           }
         ]
         ]
       },
       },
-      {
-        title: 'Services',
-        url: '',
-        id: 'fwzc',
-        sub: [ {
-          icon: 'icon-tutorial',
-          name: 'Tutorials',
-          to: {name: 'service', params: {id: 'use'}}
-        },
-        {
-          icon: 'icon-faq',
-          name: 'Q&As',
-          to: {name: 'service', params: {id: 'qa'}}
-        }, {
-          icon: 'icon-appdown',
-          name: 'Download',
-          to: {name: 'service', params: {id: 'app'}}
-        },
-        {
-          icon: 'icon-sysc',
-          name: 'Specifications',
-          to: {name: 'service', params: {id: 'product'}}
-        }]
-      },
+      // {
+      //   title: 'Services',
+      //   url: '',
+      //   id: 'fwzc',
+      //   sub: [ {
+      //     icon: 'icon-tutorial',
+      //     name: 'Tutorials',
+      //     to: {name: 'service', params: {id: 'use'}}
+      //   },
+      //   {
+      //     icon: 'icon-faq',
+      //     name: 'Q&As',
+      //     to: {name: 'service', params: {id: 'qa'}}
+      //   }, {
+      //     icon: 'icon-appdown',
+      //     name: 'Download',
+      //     to: {name: 'service', params: {id: 'app'}}
+      //   },
+      //   {
+      //     icon: 'icon-sysc',
+      //     name: 'Specifications',
+      //     to: {name: 'service', params: {id: 'product'}}
+      //   }]
+      // },
       {
       {
         title: 'Technologies',
         title: 'Technologies',
         url: '/location',
         url: '/location',
         id: '',
         id: '',
         sub: []
         sub: []
-        // sub: [{
-        //   name: '空间定位',
-        //   icon: 'icon-tech_space_location',
-        //   to: {name: 'location', query: {id: 'kjdw'}}
-        // }, {
-        //   name: '空间建模',
-        //   icon: 'icon-tech_space_modeling',
-        //   to: {name: 'location', query: {id: 'kjjm'}}
-
-        // }, {
-        //   name: '空间展示',
-        //   icon: 'icon-tech_space_display',
-        //   to: {name: 'location', query: {id: 'kjzs'}}
-
-        // }]
       },
       },
       {
       {
         title: 'About us',
         title: 'About us',
@@ -115,6 +102,8 @@ export default {
   },
   },
   home,
   home,
   eight,
   eight,
+  purchase,
+  purchasetow,
   binocular,
   binocular,
   coreTech,
   coreTech,
   about,
   about,
@@ -203,7 +192,7 @@ export default {
       },
       },
       {
       {
         name: 'Tel',
         name: 'Tel',
-        content: '400-6698-025'
+        content: '0086 756-6996790-800'
       }
       }
     ],
     ],
     links: [{
     links: [{

+ 108 - 6
src/store/user.js

@@ -1,13 +1,15 @@
 import http from '@/util/http'
 import http from '@/util/http'
-import { reg } from '@/util'
 import Vue from 'Vue'
 import Vue from 'Vue'
 import Toast from '@/components/toast/toast'
 import Toast from '@/components/toast/toast'
+import Cookies from 'js-cookie'
 
 
 Vue.use(Toast)
 Vue.use(Toast)
 
 
 let vue = new Vue()
 let vue = new Vue()
 
 
 let token = (localStorage && localStorage.getItem('token')) || ''
 let token = (localStorage && localStorage.getItem('token')) || ''
+let fdkankantoken = Cookies.get('4dkankantoken') || ''
+
 let cart = (localStorage && localStorage.getItem('cart')) || []
 let cart = (localStorage && localStorage.getItem('cart')) || []
 let payinfo = (localStorage && localStorage.getItem('payinfo')) || {}
 let payinfo = (localStorage && localStorage.getItem('payinfo')) || {}
 let orderinfo = (localStorage && localStorage.getItem('orderinfo')) || {}
 let orderinfo = (localStorage && localStorage.getItem('orderinfo')) || {}
@@ -33,8 +35,13 @@ export default {
     token: token,
     token: token,
     name: null,
     name: null,
     cart: cart,
     cart: cart,
+    fdkankantoken,
     myscene: '',
     myscene: '',
     myorder: '',
     myorder: '',
+    mydevice: '',
+    myexpansion: '',
+    mycharge: '',
+    myinvoicelist: '',
     payinfo,
     payinfo,
     orderinfo,
     orderinfo,
     invoice2: invoice2,
     invoice2: invoice2,
@@ -47,12 +54,14 @@ export default {
       state.token = token
       state.token = token
       try {
       try {
         localStorage.setItem('token', token)
         localStorage.setItem('token', token)
+        Cookies.set('fdkankantoken', token)
       } catch (error) {
       } catch (error) {
 
 
       }
       }
     },
     },
     logout (state) {
     logout (state) {
       try {
       try {
+        Cookies.set('fdkankantoken', '')
         Object.keys(state).forEach(key => {
         Object.keys(state).forEach(key => {
           state[key] = ''
           state[key] = ''
           localStorage.setItem(key, '')
           localStorage.setItem(key, '')
@@ -70,6 +79,10 @@ export default {
       state.myscene = data
       state.myscene = data
       localStorage.setItem('myscene', JSON.stringify(data))
       localStorage.setItem('myscene', JSON.stringify(data))
     },
     },
+    MYDEVICE (state, data) {
+      state.mydevice = data
+      localStorage.setItem('mydevice', JSON.stringify(data))
+    },
 
 
     ORDERINFO (state, data) {
     ORDERINFO (state, data) {
       console.log(data)
       console.log(data)
@@ -92,6 +105,20 @@ export default {
       localStorage.setItem('cart', JSON.stringify(data))
       localStorage.setItem('cart', JSON.stringify(data))
     },
     },
 
 
+    MYEXPANSION (state, data) {
+      state.myexpansion = data
+      localStorage.setItem('myexpansion', JSON.stringify(data))
+    },
+
+    MYCHARGE (state, data) {
+      state.mycharge = data
+      localStorage.setItem('mycharge', JSON.stringify(data))
+    },
+    MYINVOICELIST (state, data) {
+      state.myinvoicelist = data
+      localStorage.setItem('myinvoicelist', JSON.stringify(data))
+    },
+
     myOrder (state, data) {
     myOrder (state, data) {
       state.myorder = data
       state.myorder = data
       localStorage.setItem('myorder', JSON.stringify(data))
       localStorage.setItem('myorder', JSON.stringify(data))
@@ -194,6 +221,21 @@ export default {
       context.commit('CART', info.data.data)
       context.commit('CART', info.data.data)
     },
     },
 
 
+    async getUserDevice (context, params) {
+      let res = await http({
+        method: 'post',
+        data: params,
+        headers: {
+          token: context.state.token
+        },
+        url: '/user/camera/list'
+      })
+
+      let data = res.data
+      if (data.code !== 0) return
+      context.commit('MYDEVICE', data.data)
+    },
+
     async getInvoice (context, data) {
     async getInvoice (context, data) {
       let info = await http({
       let info = await http({
         method: 'post',
         method: 'post',
@@ -235,23 +277,83 @@ export default {
       if (data.code !== 0) return
       if (data.code !== 0) return
       context.commit('myOrder', data.data)
       context.commit('myOrder', data.data)
     },
     },
-    async getAuthCode (context, phone) {
-      if (reg.phone.test(phone)) {
+    async checkToken (context, params) {
+      let res = await http({
+        method: 'post',
+        headers: {
+          token: context.state.token
+        },
+        url: '/user/checkToken'
+      })
+
+      let data = res.data
+      if (data.code !== 0) {
+        context.commit('logout')
+      }
+    },
+    async getAuthCode (context, item) {
+      let {phone, code} = item
+      let areaNum = Number(code) || 86
+      if (phone) {
         let params = {
         let params = {
-          phoneNum: phone,
-          areaNum: '86'
+          phoneNum: Number(phone),
+          areaNum
         }
         }
         http({
         http({
           method: 'post',
           method: 'post',
           data: params,
           data: params,
           url: '/sso/user/getMsgAuthCode'
           url: '/sso/user/getMsgAuthCode'
         }, res => {
         }, res => {
-
         })
         })
         return true
         return true
       } else {
       } else {
         return vue.$toast.show('warn', '手机号码不合法')
         return vue.$toast.show('warn', '手机号码不合法')
       }
       }
+    },
+
+    async getUserExpansion (context, params) {
+      let res = await http({
+        method: 'post',
+        data: params,
+        headers: {
+          token: context.state.token
+        },
+        url: '/user/virtualOrder/expansionList'
+      })
+
+      let data = res.data
+      if (data.code !== 0) return
+      context.commit('MYEXPANSION', data.data)
+    },
+
+    async getChargeList (context, params) {
+      let res = await http({
+        method: 'post',
+        data: params,
+        headers: {
+          token: context.state.token
+        },
+        url: '/user/virtualOrder/chargeList'
+      })
+
+      let data = res.data
+      if (data.code !== 0) return
+      context.commit('MYCHARGE', data.data)
+    },
+
+    async getInvoiceList (context, params) {
+      let res = await http({
+        method: 'post',
+        data: params,
+        headers: {
+          token: context.state.token
+        },
+        url: '/user/invoice/list'
+      })
+
+      let data = res.data
+      if (data.code !== 0) return
+      context.commit('MYINVOICELIST', data.data)
     }
     }
   }
   }
 }
 }

+ 4 - 4
src/util/http.js

@@ -5,15 +5,15 @@ import Vue from 'vue'
 
 
 let vue = new Vue()
 let vue = new Vue()
 // import qs from 'qs'
 // import qs from 'qs'
-const exceptUrls = ['/sso/user/logout', '/sso/user/sendUserInfo']
+const exceptUrls = ['/sso/user/logout', '/sso/user/sendUserInfo', '/user/checkToken']
 
 
 // axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://192.168.0.10:8080/api' : '/api'
 // axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://192.168.0.10:8080/api' : '/api'
 axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'https://pro.4dkankan.com/api' : '/api'
 axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'https://pro.4dkankan.com/api' : '/api'
 
 
-// 请求超时时限 我设置500毫秒
-axios.defaults.timeout = 2000
+// 请求超时时限
+axios.defaults.timeout = 15000
 // 请求次数
 // 请求次数
-axios.defaults.retry = 4
+axios.defaults.retry = 2
 // 请求的间隙
 // 请求的间隙
 axios.defaults.retryDelay = 1000
 axios.defaults.retryDelay = 1000