tremble 6 năm trước cách đây
mục cha
commit
81fd532ca7
82 tập tin đã thay đổi với 3389 bổ sung781 xóa
  1. 1 1
      build/webpack.dev.conf.js
  2. 7 0
      index.html
  3. 80 8
      src/App.vue
  4. BIN
      src/assets/images/3dcase_img_tit.png
  5. BIN
      src/assets/images/lite-logo.png
  6. BIN
      src/assets/images/nothing.png
  7. BIN
      src/assets/images/payfail.png
  8. BIN
      src/assets/images/paysuccess.png
  9. 47 0
      src/assets/style/public.scss
  10. 7 6
      src/components/Paging/index.vue
  11. 1 22
      src/components/aboutBg/index.vue
  12. 3 4
      src/components/card/index.vue
  13. 3 3
      src/components/citySelect/index.vue
  14. 0 1
      src/components/compare/index.vue
  15. 1 1
      src/components/edit/index.vue
  16. 2 2
      src/components/slide/index.vue
  17. 2 2
      src/components/spinner/index.vue
  18. 29 0
      src/components/table/index.vue
  19. 30 0
      src/components/table/style.scss
  20. 0 1
      src/components/tabs/index.vue
  21. 142 101
      src/components/toast/index.vue
  22. 7 1
      src/components/toast/toast.js
  23. 0 1
      src/components/wave/operators-particles.js
  24. 7 1
      src/main.js
  25. 23 3
      src/page/about/index.vue
  26. 2 0
      src/page/about/style.scss
  27. 8 2
      src/page/binocular/index.vue
  28. 4 2
      src/page/binocular/style.scss
  29. 119 0
      src/page/capacity/index.vue
  30. 42 33
      src/page/cases/index.vue
  31. 67 57
      src/page/cases/style.scss
  32. 7 0
      src/page/eight/index.vue
  33. 9 2
      src/page/eight/style.scss
  34. 14 32
      src/page/home2/index.vue
  35. 0 1
      src/page/information/news/index.vue
  36. 8 3
      src/page/layout/aside/temp/ctemp/detail.scss
  37. 143 42
      src/page/layout/aside/temp/ctemp/detail.vue
  38. 9 7
      src/page/layout/aside/temp/ctemp/list.vue
  39. 6 1
      src/page/layout/aside/temp/login.vue
  40. 33 16
      src/page/layout/aside/temp/ltemp/forget.vue
  41. 61 6
      src/page/layout/aside/temp/ltemp/login.vue
  42. 35 16
      src/page/layout/aside/temp/ltemp/register.vue
  43. 15 7
      src/page/layout/header/index.vue
  44. 7 8
      src/page/layout/header/istyle.scss
  45. 3 2
      src/page/location/style.scss
  46. 38 34
      src/page/manage/index.vue
  47. 1 0
      src/page/manage/style.scss
  48. 23 6
      src/page/manage/temp/change.vue
  49. 229 1
      src/page/manage/temp/consumption.vue
  50. 72 0
      src/page/manage/temp/device.vue
  51. 50 0
      src/page/manage/temp/iconsumption.js
  52. 78 38
      src/page/manage/temp/infomation.vue
  53. 98 71
      src/page/manage/temp/order.vue
  54. 1 0
      src/page/manage/temp/privilege.vue
  55. 176 100
      src/page/manage/temp/scene.vue
  56. 3 0
      src/page/navs/index.vue
  57. 27 21
      src/page/navs/search/index.vue
  58. 2 2
      src/page/navs/search/item/index.vue
  59. 2 0
      src/page/navs/search/style.scss
  60. 2 2
      src/page/navs/temp.vue
  61. 108 17
      src/page/pay/index.vue
  62. 125 0
      src/page/payresult/index.vue
  63. 546 0
      src/page/privilege/index.vue
  64. 7 3
      src/page/purchase/index.vue
  65. 1 1
      src/page/purchase/style.scss
  66. 196 0
      src/page/purchasetow/index.vue
  67. 231 0
      src/page/purchasetow/style.scss
  68. 79 30
      src/router/index.js
  69. 0 5
      src/router/information.js
  70. 13 13
      src/store/language/cn/about.js
  71. 1 1
      src/store/language/cn/home.js
  72. 66 0
      src/store/language/cn/purchasetow.js
  73. 13 13
      src/store/language/en/about.js
  74. 3 3
      src/store/language/en/coreTech.js
  75. 1 1
      src/store/language/en/home.js
  76. 66 0
      src/store/language/en/purchasetow.js
  77. 23 1
      src/store/language/home_cn.js
  78. 23 9
      src/store/language/home_en.js
  79. 5 7
      src/store/user.js
  80. 4 0
      src/util/browser.js
  81. 61 7
      src/util/http.js
  82. 31 0
      src/util/index.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 portfinder = require('portfinder')
 
-const HOST = '192.168.0.28'
+const HOST = '192.168.0.133'
 const PORT = process.env.PORT && Number(process.env.PORT)
 
 const devWebpackConfig = merge(baseWebpackConfig, {

+ 7 - 0
index.html

@@ -12,6 +12,13 @@
     <link rel="icon" type="image/png" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon192.png" sizes="192x192">
     <link rel="apple-touch-icon" sizes="180x180" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon180.png">
     <title>四维看看</title>
+    <script>
+    (function(){
+        if (navigator.userAgent.indexOf('iPhone') > -1 || navigator.userAgent.indexOf('Android') > -1) {
+            window.location.href = '/mobile/index.html';
+        }
+    })();
+    </script>
   </head>
   <body>
     <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"> </script>

+ 80 - 8
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="app">
+  <div id="app" :style="{transform:scale!==1? `scale(${scale})`:'none'}">
     <div class="big-nav">
       <iheader>
         <inavs slot-scope="{cp}" :cp="cp" />
@@ -24,6 +24,9 @@ import left from '@/page/layout/left'
 import aside from '@/page/layout/aside'
 import navs from '@/page/navs'
 import chat from '@/page/chat'
+import browser from '@/util/browser'
+
+// import { detectZoom } from '@/util'
 
 export default {
   name: 'App',
@@ -32,16 +35,13 @@ export default {
       maskZIndex: -1,
       showMask: false,
       showLogin: false,
-      asideCp: 'list'
+      asideCp: 'list',
+      scale: '',
+      isNotChorme: browser.firefox || browser.edge,
+      isIE: browser.trident
     }
   },
   watch: {
-    '$store.state.user.token': function (newVal, oldVal) {
-      if (newVal && (newVal !== oldVal)) {
-        // this.$store.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
-        // this.$store.dispatch('getInfo', {url: '/user/cart/list', name: 'cart'})
-      }
-    },
     '$store.state.user.cart': function (newVal, oldVal) {
       if (newVal && (newVal !== oldVal)) {
         let count = 0
@@ -50,8 +50,31 @@ export default {
         })
         this.$bus.$emit('updateCart', count)
       }
+    },
+    '$route.path': {
+      handler: function (val, oldVal) {
+        if (devicePixelRatio !== 1) {
+          if (this.isNotChorme || this.isIE) {
+            setTimeout(() => {
+              this.fixHeight()
+            }, 1500)
+          } else {
+            this.$nextTick(() => {
+              this.fixHeight()
+            })
+          }
+        }
+      },
+      // 深度观察监听
+      deep: true
     }
 
+    // function (newVal, olVal) {
+    //   this.$nextTick(() => {
+    //     console.log('newDom compele')
+    //     this.fixHeight()
+    //   })
+    // }
   },
   components: {
     iheader: header,
@@ -61,7 +84,53 @@ export default {
     ichat: chat,
     ileft: left
   },
+  computed: {
+    isManage: function () {
+      if (this.$route.matched.length > 0) {
+        return this.$route.matched[0]['name'] === 'manage'
+      }
+      return false
+    }
+  },
+  methods: {
+    fixHeight () {
+      if (this.isManage) return
+      let z = Math.round(devicePixelRatio * 100)
+      this.scale = (100 / z) || 1
+      let appH = document.querySelector('#app').offsetHeight
+      let hpx = z !== 100 ? appH * this.scale + 'px' : 'auto'
+
+      document.querySelector('html').style.height = hpx
+      document.querySelector('body').style.height = hpx
+      if ((this.isNotChorme || this.isIE) && z !== 100) {
+        document.querySelector('body').style.overflow = 'hidden'
+      } else {
+        document.querySelector('body').style.overflow = 'visible'
+      }
+    }
+  },
   mounted () {
+    let reZoom = () => {
+      let zoom = Math.round(devicePixelRatio * 100)
+      let realWidth = document.documentElement.clientWidth || document.body.clientWidth
+      this.scale = (100 / zoom) || 1
+      if (zoom !== 100) {
+        this.$toast.show('warn', `您当前浏览器的缩放比例是${zoom}%,可能会影响某些功能的正常<br/>使用,请尝试调整浏览器比例为100%以获得更佳的浏览体验。`)
+        document.querySelector('html').style.width = realWidth / this.scale + 'px'
+      } else {
+        this.$toast.hideShow()
+        document.querySelector('html').style.width = '100%'
+      }
+      this.fixHeight()
+    }
+
+    window.onload = function () {
+      reZoom()
+    }
+
+    window.addEventListener('resize', () => {
+      reZoom()
+    })
     this.$bus.$on('showMask', (index) => {
       clearTimeout(this.timeout)
       this.maskZIndex = index || 99
@@ -91,6 +160,9 @@ export default {
 <style lang="scss" scoped>
 #app {
   padding-top: 68px;
+  overflow-x: hidden;
+  width: 100%;
+  transform-origin: left top;
 }
 
 .big-nav {

BIN
src/assets/images/3dcase_img_tit.png


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


BIN
src/assets/images/nothing.png


BIN
src/assets/images/payfail.png


BIN
src/assets/images/paysuccess.png


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

@@ -24,9 +24,14 @@ $theme-color:#1fe4dc;
 }
 
 html {
+  overflow-x: hidden;
   -webkit-font-smoothing:antialiased;
   font-family: "Roboto", "BlinkMacSystemFont", "Segoe UI", "Helvetica Neue", Helvetica, Arial, "Noto Sans CJK SC", "PingFang SC", "-apple-system", "Hiragino Sans GB", "Noto Sans", "Microsoft YaHei", "\5FAE\8F6F\96C5\9ED1", "WenQuanYi Micro Hei", "Heiti SC", sans-serif;
 }
+body{
+  padding: 0;
+  margin: 0;
+}
 
 .middle {
   position: absolute;
@@ -281,3 +286,45 @@ $padding:20px;
 		background-position: 0 0;
   }
 }
+
+
+@keyframes bounceIn {
+  0%, 20%, 40%, 60%, 80%, 100% {
+    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+  }
+
+  20% {
+    opacity: 0;
+  }
+
+  40% {
+    opacity: 0;
+  }
+
+  60% {
+    opacity: 1;
+  }
+
+  80% {
+    opacity: 1;
+  }
+
+  100% {
+    opacity: 1;
+
+  }
+}
+
+@keyframes rotateLoader {
+  0% {
+      transform: rotate(0deg)
+  }
+
+  to {
+      transform: rotate(1turn)
+  }
+}

+ 7 - 6
src/components/Paging/index.vue

@@ -7,11 +7,7 @@
       :key="page"
       @click="clickHandle(page)"
       :class="{active: index === page}"
-      >{{page}}
-    </a>
-    <a class="more" @click="clickHandle(pages[pages.length-1] + 2)" v-if="pages[pages.length-1]+2<=maxPage" >...</a>
-    <a @click="clickHandle(maxPage)" :class="{active: index === maxPage}" >{{maxPage}}</a>
-    <a @click="clickHandle(index + 1)" ></a>
+      >{{page}}</a><a class="more" @click="clickHandle(pages[pages.length-1] + 2)" v-if="pages[pages.length-1]+2<=maxPage" >...</a><a @click="clickHandle(maxPage)" :class="{active: index === maxPage}" >{{maxPage}}</a><a @click="clickHandle(index + 1)"></a>
   </div>
 </template>
 
@@ -78,9 +74,14 @@ export default {
   data () {
     return { index: this.value }
   },
+  mounted () {
+    this.$emit('maxPage', this.maxPage)
+  },
   computed: {
     maxPage () {
-      return Math.ceil(this.total / this.equable)
+      let val = Math.ceil(this.total / this.equable)
+      this.$emit('maxPage', val)
+      return val
     },
     pages () {
       return getPageNumArr(this.length, this.index, this.maxPage)

+ 1 - 22
src/components/aboutBg/index.vue

@@ -9,28 +9,10 @@
 
 import * as THREE from 'three'
 import {TweenMax, TweenLite, TimelineMax} from 'gsap'
-const {Cubic} = TweenMax
 
 var windowLoad = (function () {
-  // var loadSuccess = true
-  // var runFn = null
-  // var loadHandle = () => {
-  //   loadSuccess = true
-  //   if (runFn) {
-  //     runFn()
-  //     runFn = null
-  //   }
-  // }
-  // loadHandle()
-  // setTimeout(loadHandle)
-  // window.addEventListener('load', loadHandle)
-
   return function (cb) {
-    // if (loadSuccess) {
     setTimeout(cb)
-    // } else {
-    // runFn = cb
-    // }
   }
 })()
 
@@ -88,11 +70,9 @@ export default {
       init3d()
       makeParticles()
       loop_frame()
-
       setTimeout(function () {
         TweenLite.to(document.querySelector('canvas'), 4.5, {
-          opacity: 0.99,
-          ease: Cubic.easenInOut
+          opacity: 0.99
         })
       }, optime)
     }
@@ -141,7 +121,6 @@ export default {
 
       /*
       if(renderer_gl.indexOf("Intel")){
-        console.log("????")
       }
       */
       renderer.setPixelRatio(1)

+ 3 - 4
src/components/card/index.vue

@@ -1,7 +1,7 @@
 <template>
 <div class="card-con">
   <!-- <img :src="data.homepic||'https://scene3d.4dage.com/loading/thumb.jpg'"> -->
-  <div class="card-img" :style="{backgroundImage: `url(${data.homepic||`${cdn}images/default.png`})`}"></div>
+  <div class="card-img" :style="{backgroundImage: `url(${data.thumb||`${$cdn}images/default.png`})`}"></div>
   <div class="item-info" @click="goto(data.webSite)">
     <div class="text-info">
       <div>
@@ -11,15 +11,14 @@
   </div>
   <div class="info">
     <!-- <div class="title">{{data.title}}</div> -->
-
     <div class="username">
       <div class="u-l">
-        <span class="txt">作者:</span>
+        <span class="txt">作者:{{data.userName}}</span>
         <span >{{data.nickName}}</span>
       </div>
       <div class="u-r">
         <img src="@/assets/images/eye.png" alt>
-        <span>Lite</span>
+        <span>{{data.sceneScheme===4?'Pro':'Lite'}}</span>
       </div>
     </div>
     <div class="viewcount">

+ 3 - 3
src/components/citySelect/index.vue

@@ -44,9 +44,9 @@ export default {
 
     return {
       citylist,
-      currentPID: idArr[0] || 18,
-      currentCID: idArr[1] || 3,
-      currentSID: idArr[2] || 2
+      currentPID: idArr[0] !== '' ? idArr[0] : 18,
+      currentCID: idArr[1] !== '' ? idArr[1] : 3,
+      currentSID: idArr[2] !== '' ? idArr[2] : 2
     }
   },
   computed: {

+ 0 - 1
src/components/compare/index.vue

@@ -105,7 +105,6 @@ export default {
       }
 
       let outHnadle = ev => {
-        console.log('full')
         this.isLeft = 'full'
         // animtion.style.animationPlayState = 'running'
         body.removeEventListener(move, moveHandle)

+ 1 - 1
src/components/edit/index.vue

@@ -27,7 +27,7 @@ export default {
 <style lang="scss" scoped>
 .edit-layout{
   padding: 30px 0 30px 40px;
-  width: 850px;
+  max-width: 850px;
   border-bottom: 1px solid #e7e7e7;
   .edit-bar{
     font-size: 16px;

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

@@ -91,7 +91,7 @@ export default {
         this.prevShow = newVal > 0 && this.showLen < this.items.length
         this.left += (this.itemWidth + this.spacing) * (newVal - oldVal)
 
-        console.log(this.index)
+        // console.log(this.index)
         // if (this.offset - this.left >= this.listWidth) {
         //   this.left += this.calcCompany(this.addAverage)
         // } else if (this.offset - this.left === this.calcCompany(1)) {
@@ -104,7 +104,7 @@ export default {
   },
   methods: {
     calcCompany (index) {
-      return (this.itemWidth + this.spacing) * index
+      return (this.itemWidth + this.spacing) * index + 1
     },
     changeIndex (index) {
       this.index = index

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

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

+ 29 - 0
src/components/table/index.vue

@@ -0,0 +1,29 @@
+<template>
+  <div class="table-layout">
+    <ul class="t-header">
+      <li v-for="(item,i) in header" :key="i">
+        <slot :data='item' name='header'></slot>
+      </li>
+    </ul>
+    <div class="t-con">
+      <ul class="t-item" v-for="(item,i) in data" :key="i">
+        <li v-for="(sub,j) in header" :key='j'>
+          <slot :data='item[sub.key]'  name='item'></slot>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: ['data', 'header'],
+  data () {
+    return {
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>

+ 30 - 0
src/components/table/style.scss

@@ -0,0 +1,30 @@
+.table-layout{
+  width: 100%;
+  .t-header{
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    background: #eee;
+    width: 100%;
+    padding: 10px 0;
+    li{
+      flex: 1;
+      text-align: center;
+      display: inline-block;
+    }
+  }
+  .t-con{
+    .t-item{
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
+      width: 100%;
+      padding: 10px 0;
+      li{
+        flex: 1;
+        text-align: center;
+        display: inline-block;
+      }
+    }
+  }
+}

+ 0 - 1
src/components/tabs/index.vue

@@ -31,7 +31,6 @@ export default {
   },
   watch: {
     checked (newVal) {
-      console.log(newVal)
       this.$emit('change', newVal)
     },
     selected (newVal) {

+ 142 - 101
src/components/toast/index.vue

@@ -1,23 +1,45 @@
 <template>
-  <div class="toast-layout" v-if="visible">
-    <div class="toast-con" :style="{width:toastType==='comfirm'?'704px':'540px'}">
-      <div class="top">
-        <span>{{typeTxt}}</span>
-        <i @click="toastType==='comfirm'?visible=false:emitCallback()" class="iconfont icon-cuowu"></i>
-        <!-- <img src="@/assets/images/" alt=""> -->
+  <div>
+    <div
+      class="toast-layout"
+      :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
+      :class="{'toast-active':isLoaing}"
+    >
+      <div class="loading">
+        <svg viewBox="0 0 28 19">
+          <path
+            d="M4 0l3 3C5.151 4.589 4.141 6.938 4 9c.141 2.994 1.18 5.374 3 7l-3 3c-2.512-2.51-4-5.919-4-10 0-3.134 1.446-6.499 4-9zm20 0c2.554 2.501 4 5.866 4 9 0 4.081-1.488 7.49-4 10l-3-3c1.82-1.626 2.859-4.006 3-7-.141-2.062-1.151-4.411-3-6l3-3z"
+          ></path>
+        </svg>
       </div>
-      <div class="t-line"></div>
-      <div class="detail">
-        <img :src="img" alt="">
-        <span>{{message}}</span>
-      </div>
-      <div class="t-line"></div>
-      <div class="bottom" v-if="toastType==='comfirm'">
-        <span class="btn primary" @click="emitCallback">确认</span>
-        <span @click="visible=false" class="btn cancel">取消</span>
-      </div>
-      <div class="bottom mid-bottom" v-else>
-        <span class="btn primary" @click="emitCallback">确认</span>
+    </div>
+    <div
+      class="toast-layout"
+      :style="{background:isLoaing?'none':'rgba(0, 0, 0, 0.3)'}"
+      :class="{'toast-active':visible}"
+    >
+      <div class="toast-con" :style="{minWidth:toastType==='comfirm'?'704px':'560px'}">
+        <div class="top">
+          <span>{{typeTxt}}</span>
+          <i
+            @click="toastType==='comfirm'?visible=false:emitCallback()"
+            class="iconfont icon-cuowu"
+          ></i>
+          <!-- <img src="@/assets/images/" alt=""> -->
+        </div>
+        <div class="t-line"></div>
+        <div class="detail">
+          <img :src="img" alt>
+          <span v-html="message"></span>
+        </div>
+        <div class="t-line"></div>
+        <div class="bottom" v-if="toastType==='comfirm'">
+          <span class="btn primary" @click="emitCallback">确认</span>
+          <span @click="visible=false" class="btn cancel">取消</span>
+        </div>
+        <div class="bottom mid-bottom" v-else>
+          <span class="btn primary" @click="emitCallback">确认</span>
+        </div>
       </div>
     </div>
   </div>
@@ -37,6 +59,7 @@ export default {
       type: 'warn',
       toastType: 'show',
       callback: '',
+      isLoaing: false,
       img: require('@/assets/images/icon/warn.png')
     }
   },
@@ -45,14 +68,9 @@ export default {
       return types[this.type]
     }
   },
-  created () {
-
-  },
-  watch: {
-
-  },
-  mounted () {
-  },
+  created () {},
+  watch: {},
+  mounted () {},
   methods: {
     emitCallback () {
       this.callback()
@@ -64,86 +82,109 @@ export default {
 
 <style lang="scss" scoped>
 $theme-color: #1fe4dc;
-  .btn{
-    width: 88px;
-    color: #2d2d2d;
-    display: inline-block;
-    font-size: 14px;
-    text-align: center;
-    border-radius: 2px;
-    width: 88px;
-    height: 34px;
-    line-height: 34px;
-    cursor: pointer;
-  }
-  .primary{
-    background: $theme-color;
-  }
-  .cancel{
-    background: #e6e6e6;
-    margin-left: 10px;
-  }
-  .toast-layout {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    overflow: hidden;
-    margin: 0;
-    background: rgba(0, 0, 0, 0.3);
-    z-index: 88888888;
-    .toast-con{
+$anima-time:0.2s;
+$anima-delay:0.15s;
+
+.btn {
+  width: 88px;
+  color: #2d2d2d;
+  display: inline-block;
+  font-size: 14px;
+  text-align: center;
+  border-radius: 2px;
+  width: 88px;
+  height: 34px;
+  line-height: 34px;
+  cursor: pointer;
+}
+.primary {
+  background: $theme-color;
+}
+.cancel {
+  background: #e6e6e6;
+  margin-left: 10px;
+}
+.toast-layout {
+  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;
-      padding: 20px 0;
-      top: 40%;
-      left: 50%;
-      transform: translate(-50%,-50%);
-      background: #fff;
-      width: 704px;
-      border-radius: 6px;
-      .t-line{
-        width: 100%;
-        background: #e4e4e4;
-        height: 1px;
-        margin: 20px 0;
-      }
-      .top{
-        padding:0 36px;
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        color: #969696;
-        span{
-          font-size: 16px;
-        }
-        .iconfont{
-          cursor: pointer;
-        }
+      top: calc(50% - 14px);
+      left: calc(50% - 14px);
+      transform: translate(-50%, -50%);
+      height: 28px;
+      width: 28px;
+      max-height: 28px;
+      max-width: 28px;
+      animation: rotateLoader 1s;
+      animation-iteration-count: infinite;
+    }
+  }
+  .toast-con {
+    position: absolute;
+    padding: 20px 0;
+    top: 40%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    background: #fff;
+    border-radius: 6px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
+    .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;
       }
-      .detail{
-        padding:0 36px;
-        img{
-          width: 30px;
-          display: inline-block;
-          vertical-align: middle;
-        }
-        span{
-          margin-left: 10px;
-          font-size: 16px;
-          color: #2d2d2d;
-          display: inline-block;
-          vertical-align: middle;
-        }
+      .iconfont {
+        cursor: pointer;
       }
-      .bottom{
-        padding:0 36px;
-        float: right;
+    }
+    .detail {
+      padding: 0 36px;
+      img {
+        width: 30px;
+        display: inline-block;
+        vertical-align: middle;
       }
-      .mid-bottom{
-        float: none;
-        text-align: center;
+      span {
+        margin-left: 10px;
+        font-size: 16px;
+        color: #2d2d2d;
+        display: inline-block;
+        vertical-align: middle;
       }
     }
+    .bottom {
+      padding: 0 36px;
+      float: right;
+    }
+    .mid-bottom {
+      float: none;
+      text-align: center;
+    }
   }
+}
+.toast-active{
+  display: block!important;
+  opacity: 1!important;
+}
 </style>

+ 7 - 1
src/components/toast/toast.js

@@ -28,6 +28,9 @@ Toast.install = function (Vue) {
       instance.callback = callback || function () {
       }
     },
+    showLoading: () => {
+      instance.isLoaing = true
+    },
     show: (type, msg, callback) => {
       instance.img = imgs[type] || require('@/assets/images/icon/success.png')
       instance.message = msg
@@ -37,7 +40,10 @@ Toast.install = function (Vue) {
       instance.callback = callback || function () {
       }
     },
-    hide: () => {
+    hideLoading: () => {
+      instance.isLoaing = false
+    },
+    hideShow: () => {
       instance.visible = false
     }
   }

+ 0 - 1
src/components/wave/operators-particles.js

@@ -19,7 +19,6 @@ function init(dom) {
   var windowHalfY = 300;
 
   function init(container) {
-    console.log(container)
 
     // container = $("#operaters .hero");
 

+ 7 - 1
src/main.js

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

+ 23 - 3
src/page/about/index.vue

@@ -1,9 +1,8 @@
 <template>
   <div class="about-layout" ref="aboutLayout">
     <aboutBg class="about-bg"/>
-    <div >
+    <div>
       <div class="plate01 plate">
-        <!-- <img class="about-logo" :src="`${$cdn}images/about_logo.png`" alt> -->
         <div class="introduce">
           <img :src="`${$cdn}images/event.png`" alt>
           <div class="intro-r">
@@ -120,7 +119,13 @@ export default {
         })
       }
       window.addEventListener('scroll', this.scrollHandle)
-      this.scrollHandle()
+      let removeListener = () => {
+        Math.round(devicePixelRatio * 100) !== 100 && window.removeEventListener('scroll', this.scrollHandle)
+      }
+      removeListener()
+      window.addEventListener('resize', () => {
+        removeListener()
+      })
     }, 100)
   },
   destroyed () {
@@ -133,3 +138,18 @@ export default {
 <style lang="scss" scoped>
 @import "./style.scss";
 </style>
+
+<style lang="scss">
+.e-node{
+  p{
+    span{
+      display: inline-block;
+      width: 36px;
+    }
+    i {
+      width: 60px;
+      display: inline-block;
+    }
+  }
+}
+</style>

+ 2 - 0
src/page/about/style.scss

@@ -130,6 +130,7 @@ $txt_delay: 0.2s;
         margin-left: 45px;
         padding-left: 25px;
         border-left: 1px solid rgba($color: #cccccc, $alpha: 0.5);
+
         li {
           margin-bottom: 40px;
           opacity: 0;
@@ -167,6 +168,7 @@ $txt_delay: 0.2s;
           line-height: 24px;
           font-weight: lighter;
         }
+       
       }
     }
     .contact {

+ 8 - 2
src/page/binocular/index.vue

@@ -10,7 +10,7 @@
           <h2 class="b-title">RMB 3,999</h2>
           <div class="lite-line"></div>
           <p class="b-label fix-letter" v-html="langBinocular.introduce.dec"></p>
-          <div class="btns">
+          <div class="btns" @click="$router.push({name:'purchasetow'})">
             <a class="button"><vcenter>
               <img :src="`${$cdn}images/product_icon_arrow.png`"  alt="">
             </vcenter></a>
@@ -275,7 +275,13 @@ export default {
       })
     }
     window.addEventListener('scroll', this.scrollHandle)
-    this.scrollHandle()
+    let removeListener = () => {
+      Math.round(devicePixelRatio * 100) !== 100 && window.removeEventListener('scroll', this.scrollHandle)
+    }
+    removeListener()
+    window.addEventListener('resize', () => {
+      removeListener()
+    })
   },
   destroyed () {
     clearTimeout(this.timeout)

+ 4 - 2
src/page/binocular/style.scss

@@ -22,7 +22,7 @@ $txt_delay: 0.2s;
   vertical-align: middle;
   &:first-child {
     padding: 0 12px;
-    margin-right: 2px;
+    margin-right: 1px;
   }
 
   &:last-child {
@@ -906,7 +906,6 @@ $txt_delay: 0.2s;
   .product-layout {
     .plate01 {
       .info {
-        width: 630px;
       }
       .benefit {
         width: 1200px;
@@ -932,6 +931,9 @@ $txt_delay: 0.2s;
         }
         .hdsp-right{
           left: 12vw;
+          .b-title,.b-label{
+            width: 540px;
+          }
         }
       }
     }

+ 119 - 0
src/page/capacity/index.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="capatity-layout">
+    <div class="capatity-con">
+      <div class="top">
+        <div class="b-title">总容量:3G</div>
+        <div class="capacity">
+          <div class="c-detail">
+            <span>已使用:15G / 36G (32%)</span>
+            <span>我的场景</span>
+          </div>
+          <div class="c-line">
+            <div class="active" :style="{width:'32%'}"></div>
+          </div>
+          <div class="c-detail">
+            <span>
+              容量构成:3072MB[免费体验容量]
+              <router-link :to="{path:'/priviege'}">会员价格对比</router-link>
+            </span>
+            <span>1G=1024MB</span>
+          </div>
+        </div>
+      </div>
+      <div class="top-card">
+        <div class="tc-left">
+          <img src="@/assets/images/default.png" alt="">
+        </div>
+        <div class="tc-right">
+          <div class="b-title">商业会员尊享15G超大容量</div>
+          <div class="b-label">重复开通商业会员,不会重复叠加限期容量</div>
+          <div class="tcr-bottom">
+            <span>166元 / 月</span>
+            <span>开通商业会员</span>
+          </div>
+        </div>
+      </div>
+      <div class="capatity-detail">
+        <div class="b-title">扩充容量,留存您的珍贵空间</div>
+        <div class="b-label">购买后立即生效,拍摄安心存储放心</div>
+        <div class="c-card">
+          <div class="c-item" v-for="(item,i) in 3" :key="i">
+            <div></div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style lang="scss" scoped>
+.capatity-layout{
+    background: url('~@/assets/images/person-bg.png') #eee no-repeat top center;
+    background-size: 100% 400px;
+    .capatity-con{
+      width: 1100px;
+      margin: 0 auto;
+      padding: 1px 0;
+      text-align: center;
+      .top{
+        margin: 40px 0;
+        .b-title{
+          color: #fff;
+        }
+        .capacity{
+          margin: 30px auto 0;
+          width: 680px;
+          .c-line{
+            margin: 20px 0;
+            width: 100%;
+            height: 8px;
+            background-color: #ccc;
+            .active{
+              background-color: #1fe4dc;
+              height: 100%;
+            }
+          }
+          .c-detail{
+            color: #fff;
+            display: flex;
+            justify-content: space-between;
+            span{
+              color: #fff;
+            }
+          }
+        }
+      }
+      .top-card{
+        display: flex;
+        justify-content: space-between;
+        background: #fff;
+        border-radius: 5px;
+        margin: 40px auto;
+        padding: 10px;
+        .tc-left{
+          flex: 1;
+          img{
+            width: 100%;
+          }
+        }
+        .tc-right{
+          flex: 2;
+          text-align: left;
+          padding-left: 140px;
+          .tcr-bottom{
+            margin-top: 60px;
+          }
+        }
+      }
+      .capatity-detail{
+
+      }
+    }
+}
+</style>

+ 42 - 33
src/page/cases/index.vue

@@ -1,14 +1,14 @@
 <template>
-<div>
+<div :style="{minHeight:scene.length>0?'none':'95vh'}">
   <div class="case-con" :style="{paddingLeft:(split-260)+ 'px'}">
     <div class="case-header">
       <img src="@/assets/images/3dcase_img_tit.png" alt="">
       <div class="case-nav">
         <div class="nav-con">
           <vcenter>
-            <div class="list-nav" :style="{width:language==='en'?'680px':'605px'}">
+            <div class="list-nav" :style="{width:language==='en'?'800px':'605px'}">
               <div class="list-txt b-title">{{caseType}}</div>
-              <router-link class="sub-list b-title" :to="item.to" v-for="(item,i) in navs" :key="i">{{item.name}}</router-link>
+              <router-link class="sub-list b-title" :to="item.to" v-for="(item,i) in navs" :key="i">{{langCases.typeName[item.name]}}</router-link>
             </div>
             <div class="lists">
               <ul class="list-navs">
@@ -16,12 +16,10 @@
                   <span class="b-label">{{item.name}}</span>
                 </li>
               </ul>
-              <div class="select">
-                <span @click="selectActive=!selectActive" :class="{active:selectActive}">{{selected}}</span>
+              <div class="select" ref="mbMenu">
+                <span @click="selectActive=!selectActive" :class="{active:selectActive}">{{langCases.sceneSelected[selected]}}</span>
                 <ul :style="{maxHeight:selectActive?'200px':'0',padding:selectActive?'15px 0':'0'}">
-                  <li @click="selected= '全部'">全部</li>
-                  <li @click="selected= '四维看看 Lite'">四维看看 Lite</li>
-                  <li @click="selected= '四维看看 Pro'">四维看看 Pro</li>
+                  <li @click="selected= item.id" v-for="(item,i) in langCases.selectType" :key="i">{{item.name}}</li>
                 </ul>
               </div>
             </div>
@@ -31,15 +29,15 @@
     </div>
   </div>
   <div class="case-body" :style="{marginLeft:(split-(isWide?380:329))+ 'px'}">
-    <div style="display:inline-block" v-for="(item,i) in scene" :key="i">
-      <card class="card" :data="item" :style="{marginRight:(i+1)%(isWide?4:3)===0?'0':'50px'}"></card>
-    </div>
-    <div class="paging">
-      <vcenter>
-          <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
-      </vcenter>
+    <div class="card" :class="{card_active:scene.length>0}" :style="{animationDelay:`${0.1*(i)}s`}" v-for="(item,i) in scene" :key="i">
+      <card  :data="item" :style="{marginRight:(i+1)%(isWide?4:3)===0?'0':'50px'}"></card>
     </div>
   </div>
+  <div class="paging" v-if="total">
+    <vcenter>
+        <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
+    </vcenter>
+  </div>
 </div>
 </template>
 
@@ -59,12 +57,10 @@ let typeArr = {
   '其他': 0
 }
 
-let typeTotal = {
-  '房地产': 70,
-  '博物馆': 50,
-  '家居': 40,
-  '餐饮': 30,
-  '其他': 150
+let sceneSTYpe = {
+  '全部': null,
+  '四维看看 Lite': 1,
+  '四维看看 Pro': 4
 }
 
 let nav = [
@@ -84,19 +80,12 @@ let nav = [
     name: '博物馆',
     to: {name: 'cases', params: {id: '博物馆'}}
   },
-
   {
     name: '房地产',
     to: {name: 'cases', params: {id: '房地产'}}
   }
-
 ]
 
-let wh = {
-  width: window.innerWidth,
-  height: window.innerHeight
-}
-let isWide = wh.width > 1500
 export default {
   // import引入的组件需要注入到对象中才能使用
   components: {
@@ -110,11 +99,11 @@ export default {
     return {
       selectActive: false,
       total: 0,
-      pageSize: 10,
+      pageSize: 12,
       currentPage: 1,
       sortActive: 1,
       scene: [],
-      isWide,
+      isWide: Math.round(devicePixelRatio * 100) === 100 ? window.innerWidth > 1697 : true,
       selected: '筛选设备',
       caseType: null
     }
@@ -141,6 +130,10 @@ export default {
     currentPage () {
       this.getData()
     },
+    selected () {
+      this.selectActive = false
+      this.getData()
+    },
     sortActive () {
       this.currentPage = 1
       this.selectActive = false
@@ -155,7 +148,6 @@ export default {
       handler (newVal) {
         this.currentPage = 1
         this.caseType = this.langCases.typeName[newVal]
-        this.total = typeTotal[newVal]
         this.selectActive = false
         this.getData()
       }
@@ -169,16 +161,23 @@ export default {
     async getData () {
       window.scrollTo(0, 0)
       let params = {
+        pageSize: this.pageSize,
         sceneType: typeArr[this.caseType],
         sceneInterest: this.sortActive,
-        page: this.currentPage
+        pageNum: this.currentPage,
+        sceneScheme: sceneSTYpe[this.selected]
       }
       let result = await this.$http({
         method: 'post',
         data: params,
         url: '/scene/loadScene'
       })
-      this.scene = result.data
+      let data = result.data.data
+      this.scene = []
+      setTimeout(() => {
+        this.scene = data.list
+      }, 0)
+      this.total = data.total
     }
   },
   // 生命周期 - 创建完成(可以访问当前this实例)
@@ -188,6 +187,16 @@ export default {
   // 生命周期 - 挂载完成(可以访问DOM元素)
   mounted () {
     this.getData()
+    document.addEventListener('click', (e) => {
+      if (this.$refs.mbMenu) {
+        if (!this.$refs.mbMenu.contains(e.target)) {
+          this.selectActive = false
+        }
+      }
+    })
+    window.addEventListener('resize', () => {
+      this.isWide = Math.round(devicePixelRatio * 100) === 100 ? window.innerWidth > 1697 : true
+    })
   }
 }
 </script>

+ 67 - 57
src/page/cases/style.scss

@@ -137,67 +137,77 @@
 }
 .case-body {
   max-width: 1470px;
+  min-width: 1200px;
   .card {
+    overflow: hidden;
     margin-bottom: 20px;
+    display: inline-block;
+    opacity: 0;
+  }
+  .card_active{
+    animation-fill-mode: forwards;
+    animation-name: bounceIn;
+    animation-duration:0.75s;
+    transition: bounceIn 0.3s;
+  }
+}
+.paging {
+  // border-left: #e5e5e5 1px solid;
+  height: 100%;
+  margin-bottom: 40px;
+  & /deep/ .layout {
+    text-align: center;
+    margin-top: 10px;
+  }
+  & /deep/ .layout a:not(:last-child) {
+    margin: 10px 8px;
+    font-size: 16px;
+    display: inline-block;
+    font-weight: 500;
+    cursor: pointer;
+    user-select: none;
+    color: #999;
+    position: relative;
+    transition: color 0.3s;
+  }
+  & /deep/ .layout a:last-child {
+    position: relative;
+    top: -5px;
+    display: -ms-inline-flexbox;
+    display: inline-flex;
+    -ms-flex-align: center;
+    align-items: center;
+    height: 22px;
+    padding: 0 9.6px;
+    padding: 0 0.6rem;
+  }
+  & /deep/ .layout a:last-child::before,
+  & /deep/ .layout a:last-child::after {
+    content: "";
+    display: inline-block;
+    will-change: transform;
+    transition: transform 0.3s;
   }
-  .paging {
-    // border-left: #e5e5e5 1px solid;
-    height: 100%;
-    margin-bottom: 40px;
-    & /deep/ .layout {
-      text-align: center;
-      margin-top: 40px;
-    }
-    & /deep/ .layout a:not(:last-child) {
-      margin: 10px 8px;
-      font-size: 16px;
-      display: inline-block;
-      font-weight: 500;
-      cursor: pointer;
-      user-select: none;
-      color: #999;
-      position: relative;
-      transition: color 0.3s;
-    }
-    & /deep/ .layout a:last-child {
-      position: relative;
-      top: -5px;
-      display: -ms-inline-flexbox;
-      display: inline-flex;
-      -ms-flex-align: center;
-      align-items: center;
-      height: 22px;
-      padding: 0 9.6px;
-      padding: 0 0.6rem;
-    }
-    & /deep/ .layout a:last-child::before,
-    & /deep/ .layout a:last-child::after {
-      content: "";
-      display: inline-block;
-      will-change: transform;
-      transition: transform 0.3s;
-    }
 
-    & /deep/ .layout a:not(:last-child).active::after,
-    & /deep/ .layout a:not(:last-child).active,
-    & /deep/ .layout a:not(:last-child):hover,
-    & /deep/ .layout a:not(:last-child):hover::after {
-      color: #111111;
-      transform: scaleX(1);
-    }
+  & /deep/ .layout a:not(:last-child).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;
-    }
+  & /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;
   }
 }

+ 7 - 0
src/page/eight/index.vue

@@ -340,6 +340,13 @@ export default {
       })
     }
     window.addEventListener('scroll', this.scrollHandle)
+    let removeListener = () => {
+      Math.round(devicePixelRatio * 100) !== 100 && window.removeEventListener('scroll', this.scrollHandle)
+    }
+    removeListener()
+    window.addEventListener('resize', () => {
+      removeListener()
+    })
   },
   destroyed () {
     window.removeEventListener('scroll', this.scrollHandle)

+ 9 - 2
src/page/eight/style.scss

@@ -26,7 +26,7 @@ $num_time: 0.6s;
   vertical-align: middle;
   &:first-child {
     padding: 0 12px;
-    margin-right: 2px;
+    margin-right: 1px;
   }
 
   &:last-child {
@@ -991,6 +991,13 @@ $num_time: 0.6s;
 @media screen and (max-width: 1600px) {
   .product-layout{
     .plate01{
+      .layout{
+        .info{
+          .logo-dec{
+            width: 650px;
+          }
+        }
+      }
       .benefit{
         width: 1200px;  
       }
@@ -1000,7 +1007,7 @@ $num_time: 0.6s;
         margin: 0 auto;
       }
       .front,.bottom{
-        margin: 138px auto 175px;
+        margin: 0 auto;
       }
     }
     .plate04{

+ 14 - 32
src/page/home2/index.vue

@@ -1,31 +1,10 @@
 <template>
   <div class="home-layout">
     <div class="plate01">
-      <div class="layout">
-        <div class="info">
-          <!-- <div>
-            <img :src="`${$cdn}images/banner_title.png`"  alt="">
-            <h3>
-              4Dkankan PRO
-              <p>专业精准建模,高效复刻空间</p>
-            </h3>
-            <div class="money">
-              <span>From:</span>
-              <strong>199.00</strong>
-            </div>
-            <div class="btns">
-              <a href="" class="button"><vcenter><img :src="`${$cdn}images/product_icon_arrow.png`" alt=""></vcenter></a>
-              <a href="" class="button">立即购买</a>
-            </div>
-          </div> -->
-        </div>
-        <!-- <img :src="`${$cdn}images/banner_pro.png`" alt=""> -->
-      </div>
-      <div class="my-video">
+      <div class="my-video" :style="{height:isWide?`${innerH - 128}px`:`${innerH - 88}px`}">
         <video :src="language==='en'?`${$cdn}video/banner1.mp4`:`${$cdn}video/4dkkPRO_zh.mp4`" autoplay muted loop></video>
       </div>
     </div>
-
     <div class="plate02">
       <div class="logo"><img :src="`${$cdn}images/plate_icon.png`" ></div>
       <div class="booking">
@@ -112,14 +91,6 @@
         <p class="b-label" v-for="(item,i) in langHome.cases.dec" :key="i">{{item}}</p>
       </div>
       <div class="content-layout">
-        <div class="tabs">
-          <!-- <div>
-            <a href="" class="active"><img :src="`${$cdn}images/icon_01.png`" ></a>
-            <a href=""><img :src="`${$cdn}images/icon_02.png`" ></a>
-            <a href=""><img :src="`${$cdn}images/icon_03.png`" ></a>
-          </div> -->
-          <!-- <a  href="#/videos">更多行业应用</a> -->
-        </div>
         <div class="slide-l" :class="{actice: slideActive}" ref="slide">
           <div class="content">
             <slide :items="langHome.items" class="body">
@@ -185,9 +156,10 @@ export default {
   data () {
     return {
       slideActive: false,
-      // countGroup,
       kjdw: this.$cdn + 'video/kjdw.mp4',
       item2: this.$cdn + 'video/item2.mp4',
+      isWide: window.innerHeight > 1600,
+      innerH: window.innerHeight,
       startNumCount: false
     }
   },
@@ -207,6 +179,7 @@ export default {
   },
   mounted () {
     this.sizeHandle = () => {
+      this.isWide = window.innerHeight > 1600
       let ny = getPosition(this.$refs.numcount).y + this.$refs.numcount.offsetHeight
       let sy = getPosition(this.$refs.slide).y + this.$refs.slide.offsetHeight
 
@@ -222,8 +195,17 @@ export default {
         window.removeEventListener('scroll', this.sizeHandle)
       }
     }
-
     window.addEventListener('scroll', this.sizeHandle)
+    let removeListener = () => {
+      if (Math.round(devicePixelRatio * 100) !== 100) {
+        this.startNumCount = true
+        this.slideActive = true
+      }
+    }
+    removeListener()
+    window.addEventListener('resize', () => {
+      removeListener()
+    })
   },
   destroyed () {
     window.removeEventListener('scroll', this.sizeHandle)

+ 0 - 1
src/page/information/news/index.vue

@@ -36,7 +36,6 @@ export default {
   async mounted () {
     this.testDom = document.createElement('div')
     let result = (await this.$http.get('/news', {params: {page: 0, limit: 100, language: 1}})).data.content
-    console.log(result)
     this.news = result.data
   }
 }

+ 8 - 3
src/page/layout/aside/temp/ctemp/detail.scss

@@ -85,12 +85,16 @@ input {
       margin-top: 20px;
       p {
         line-height: 36px;
+        line-height: 18px;
+        margin-bottom: 8px;
+        overflow-wrap: break-word;
         span {
           padding-right: 10px;
         }
       }
       .p-desc {
         color: #a0a0a0;
+        overflow-wrap: break-word;
         line-height: 24px;
       }
       .avatar {
@@ -336,6 +340,7 @@ input {
           color: #a0a0a0;
           vertical-align: middle;
           &:first-child{
+            margin-right: 4px;
             border: solid 1px $border-color;
             display: inline-block;
             width: 16px;
@@ -345,9 +350,9 @@ input {
             img{
               pointer-events: none;
               position: absolute;
-              top: -6px;
-              left: -4px;
-              width: 24px;
+              top: -8px;
+              left: -6px;
+              width: 26px;
             }
           }
         }

+ 143 - 42
src/page/layout/aside/temp/ctemp/detail.vue

@@ -22,20 +22,20 @@
         </div>
         <div class="address edit-address" slot="edit">
           <div class="input-con">
-            <input type="text" v-model="address.shipName" :placeholder="address.shipName||'姓名'">
-            <input type="text" v-model="address.shipMobile" :placeholder="address.shipMobile||'电话'">
+            <input type="text" v-model="editAdd.shipName" :placeholder="address.shipName||'姓名'">
+            <input type="text" v-model="editAdd.shipMobile" :placeholder="address.shipMobile||'电话'">
           </div>
           <div class="input-con">
-            <citySelect :areaPath="address.shipAreaPath" @currentVal="getCurrentSelect"/>
+            <citySelect :areaPath="editAdd.shipAreaPath" @currentVal="getCurrentSelect"/>
           </div>
           <div class="input-con address-input">
             <input
               type="text"
-              v-model="address.shipAddress"
-              :placeholder="address.shipAddress||'详细地址'"
+              v-model="editAdd.shipAddress"
+              :placeholder="editAdd.shipAddress||'详细地址'"
             >
           </div>
-          <div class="btn parmary">保存</div>
+          <div class="btn parmary" @click="uAddress">保存</div>
         </div>
       </edit>
       <div class="pay-type">
@@ -82,24 +82,30 @@
             </div>
           </div>
           <div class="invoice-detail" v-if="invoice==='normal'">
-            <p>{{invoice2.title}}</p>
-            <p class="p-desc">{{invoice2.code}}</p>
+            <template v-if="!invoice2.title">
+              <p class="p-desc">暂无信息</p>
+            </template>
+            <template v-else>
+              <p>{{invoice2.title}}</p>
+              <p class="p-desc">{{invoice2.code}}</p>
+            </template>
           </div>
           <div class="invoice-detail" v-if="invoice==='zengzhi'">
-            <p>{{invoice3.title}}</p>
-            <p class="p-desc">{{invoice3.code}}</p>
-            <p class="p-desc">{{invoice3.organizedAddress}}</p>
-            <p class="p-desc">{{invoice3.registerPhone}}</p>
-            <p class="p-desc">{{invoice3.bankName}}</p>
-            <p class="p-desc">{{invoice3.bankAccount}}</p>
+            <template v-if="!invoice3.title">
+              <p class="p-desc">暂无信息</p>
+            </template>
+            <template v-else>
+              <p>{{invoice3.title}}</p>
+              <p class="p-desc">{{invoice3.code}}</p>
+              <p class="p-desc">{{invoice3.organizedAddress}}</p>
+              <p class="p-desc">{{invoice3.registerPhone}}</p>
+              <p class="p-desc">{{invoice3.bankName}}</p>
+              <p class="p-desc">{{invoice3.bankAccount}}</p>
+            </template>
           </div>
         </div>
         <div class="invoice edit-invoice" slot="edit">
           <div class="select-con">
-            <div :class="{'tag-active':invoice==='noinvoice'}" @click="invoice='noinvoice'">
-              <span>不需要发票</span>
-              <img src="@/assets/images/tag-icon.png" alt>
-            </div>
             <div :class="{'tag-active':invoice==='normal'}" @click="invoice='normal'">
               <span>增值税普通发票</span>
               <img src="@/assets/images/tag-icon.png" alt>
@@ -112,22 +118,22 @@
           </div>
           <div class="invoice-input" v-if="invoice==='normal'">
             <div class="input-con">
-              <input type="text" placeholder="请输入发票抬头" v-model="invoice2.title">
-              <input type="text" placeholder="请输入税务登记号(个人用户可不填)" v-model="invoice2.code">
+              <input type="text" placeholder="请输入发票抬头" v-model="editInvoice2.title">
+              <input type="text" placeholder="请输入税务登记号(个人用户可不填)" v-model="editInvoice2.code">
             </div>
           </div>
           <div class="invoice-input" v-if="invoice==='zengzhi'">
             <div class="input-con">
-              <input type="text" v-model="invoice3.title" placeholder="请输入发票抬头">
-              <input type="text" v-model="invoice3.code" placeholder="请输入税务登记号(个人用户可不填)">
+              <input type="text" v-model="editInvoice3.title" placeholder="请输入发票抬头">
+              <input type="text" v-model="editInvoice3.code" placeholder="请输入税务登记号(个人用户可不填)">
             </div>
             <div class="input-con">
-              <input type="text" v-model="invoice3.organizedAddress" placeholder="注册地址">
-              <input type="text" v-model="invoice3.registerPhone" placeholder="注册电话">
+              <input type="text" v-model="editInvoice3.organizedAddress" placeholder="注册地址">
+              <input type="text" v-model="editInvoice3.registerPhone" placeholder="注册电话">
             </div>
             <div class="input-con">
-              <input type="text" v-model="invoice3.bankName" placeholder="开户银行">
-              <input type="text" v-model="invoice3.bankAccount" placeholder="银行账户">
+              <input type="text" v-model="editInvoice3.bankName" placeholder="开户银行">
+              <input type="text" v-model="editInvoice3.bankAccount" placeholder="银行账户">
             </div>
           </div>
             <div @click="saveInvoice(invoice)" class="btn parmary">保存</div>
@@ -140,9 +146,9 @@
       <div class="product-type">
         <div class="title">商品信息</div>
         <div class="p-info" v-for="(item,i) in sku" :key="i">
-          <img src="@/assets/images/banner_pro.png" alt>
+          <img :src="item.goodsId===4?`${$cdn}images/banner_pro.png`:`${$cdn}images/t_product.png`" alt>
           <div class="p-params">
-            <h3>四维看看 Pro</h3>
+            <h3>{{item.goodsId === 4?'四维看看 Pro':'四维看看 Lite'}}</h3>
             <p>本机主体 x {{item.goodsCount}}, 拍摄支架 x {{item.goodsCount}}</p>
           </div>
           <div class="p-price">¥ {{item.price}}</div>
@@ -184,13 +190,24 @@ import vcenter from '@/components/vcenter'
 import edit from '@/components/edit'
 import citySelect from '@/components/citySelect'
 import { mapState } from 'vuex'
-
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
 export default {
   props: ['sku', 'fromList'],
   data () {
     return {
       agree: -1,
       addressStatus: true,
+      tempSelect: '',
       invoiceStatus: true,
       invoice: 'noinvoice',
       paytype: 0
@@ -203,10 +220,43 @@ export default {
   },
   computed: {
     ...mapState({
-      invoice2: state => state.user.invoice2 || {},
-      invoice3: state => state.user.invoice3 || {},
+      invoice2: state => {
+        let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      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 => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
+        }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+
+        return (condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      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) : {})
+      },
       token: state => state.user.token,
-      address: state => state.user.address || {}
+      address: state => state.user.address || {},
+      editAdd: state => cloneObj(state.user.address) || {}
+
     })
   },
   methods: {
@@ -217,7 +267,45 @@ export default {
       this.$bus.$emit('hideAside')
     },
     handleOper (type) {
-      this[type] = !this[type]
+      if (type === 'invoiceStatus') {
+        this.invoice === 'noinvoice' ? this[type] = true : this[type] = !this[type]
+      } else {
+        this[type] = !this[type]
+      }
+    },
+    uAddress () {
+      this.editAdd.province = this.tempSelect[0]
+      this.editAdd.city = this.tempSelect[1]
+      this.editAdd.shipAreaPath = this.tempSelect.join(',')
+      let {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      } = this.editAdd
+      let params = {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      }
+      this.$http
+        .post('/user/updateAddress', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          this.addressStatus = true
+          this.$store.dispatch('getInfo', {
+            url: '/user/getReceiverInfo',
+            name: 'address'
+          })
+        })
     },
     getCurrentSelect (data) {
       this.tempSelect = data
@@ -232,7 +320,9 @@ export default {
       return [count, sum]
     },
     async pay () {
-      if (!this.agree) { return alert('请同意协议') }
+      if (!this.agree) {
+        return this.$toast.show('warn', '请同意条款')
+      }
       let invoice = this.invoice === 'normal' ? this.invoice2 : this.invoice === 'zengzhi' ? this.invoice3 : null
       let params = {
         goods: this.sku,
@@ -247,24 +337,31 @@ export default {
           }
         })
       this.$bus.$emit('hideAside')
+      this.$store.dispatch('getCart')
       this.$router.push({name: 'pay',
         params: {
+          payType: this.paytype,
           orderId: res.data.data.id,
-          orderType: 0
+          orderType: 0,
+          orderSn: res.data.data.orderSn
         }})
     },
     saveInvoice (cInvoice) {
       let params = {}
+      let invoiceType = ''
+
       if (cInvoice === 'normal') {
+        invoiceType = 2
         params = {
-          invoiceType: 2,
-          title: this.invoice2.title,
-          code: this.invoice2.code
+          invoiceType,
+          title: this.editInvoice2.title,
+          code: this.editInvoice2.code
         }
       } else {
-        let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.invoice3
+        let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.editInvoice3
+        invoiceType = 3
         params = {
-          invoiceType: 3,
+          invoiceType,
           title,
           code,
           organizedAddress,
@@ -281,9 +378,13 @@ export default {
           }
         })
         .then(data => {
-          let res = data.data
           this.invoiceStatus = true
-          localStorage.setItem('invoice', JSON.stringify(res.data))
+          this.$store.dispatch('getInvoice', {
+            type: invoiceType,
+            params: {
+              invoiceType: invoiceType
+            }
+          })
         })
     }
   },

+ 9 - 7
src/page/layout/aside/temp/ctemp/list.vue

@@ -7,7 +7,7 @@
     <div class="items">
       <div class="item" v-for="(item, index) in cart" :key="index">
         <div>
-          <img class="product-img" :src="`${$cdn}images/t_product.png`" alt>
+          <img class="product-img" :src="item.goodsId===4?`${$cdn}images/banner_pro.png`:`${$cdn}images/t_product.png`" alt>
           <i @click="cartHandle" class="iconfont icon-plus"></i>
           <img class="product-img" src="@/assets/images/zhijia.png" alt>
         </div>
@@ -59,7 +59,7 @@ export default {
         if (Object.prototype.toString.call(state.user.cart) === '[object Array]') {
           return state.user.cart
         }
-        return (state.user.cart ? JSON.parse(state.user.cart) : [])
+        return (state.user.cart && state.user.cart !== 'null' ? JSON.parse(state.user.cart) : [])
       }
     })
   },
@@ -93,11 +93,13 @@ export default {
       this.$store.dispatch('addCart', params)
     },
     rmItem (item) {
-      let params = {
-        goodsId: item.goodsId,
-        goodsCount: 0
-      }
-      this.$store.dispatch('reduceCart', params)
+      this.$toast.showConfirm('warn', '确定删除吗?', () => {
+        let params = {
+          goodsId: item.goodsId,
+          goodsCount: 0
+        }
+        this.$store.dispatch('reduceCart', params)
+      })
     },
     toPay () {
       let skus = this.cart

+ 6 - 1
src/page/layout/aside/temp/login.vue

@@ -17,7 +17,7 @@
           :key="i"
         >{{item.name}}</li>
       </ul>
-      <component :is="tabActive"></component>
+      <component :is="tabActive" :active='active' :current='tabActive'></component>
     </div>
   </div>
 </template>
@@ -60,6 +60,11 @@ export default {
     logoutHandle () {
       this.$bus.$emit('hideAside')
     }
+  },
+  mounted () {
+    this.$bus.$on('currentActive', data => {
+      this.tabActive = data || 'ilogin'
+    })
   }
 }
 </script>

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

@@ -1,12 +1,13 @@
 <template>
   <div class="iforget-layout">
-    <div class="input"><input placeholder="输入手机号码" v-model="phone" type="text"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" placeholder="输入手机号码" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' v-model="phone" type="text"></div>
     <div class="verification input">
-      <input placeholder="验证码" v-model="authCode" type="text">
-      <span @click="getAuthCode">获取验证码</span>
+      <input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" placeholder="验证码" v-model="authCode" type="text">
+      <span v-if="!jishi" @click="getAuthCode">获取验证码</span>
+      <span v-else>{{interTime}}s后重新发送</span>
     </div>
-    <div class="input"><input v-model="password" placeholder="新密码" type="password"></div>
-    <div class="input"><input v-model="confirmpass" placeholder="再次输入新密码" type="password"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')" maxlength='12' autocomplete="off" v-model="password" placeholder="新密码" type="password"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')" maxlength='12' autocomplete="off" v-model="confirmpass" placeholder="再次输入新密码" type="password"></div>
     <div class="temp-btn submit" @click="submit">提交</div>
   </div>
 </template>
@@ -23,15 +24,31 @@ export default {
     return {
       phone: '',
       authCode: '',
+      interTime: 60,
+      jishi: false,
       password: '',
       confirmpass: ''
     }
   },
   methods: {
-    getAuthCode () {
-      this.$store.dispatch('getAuthCode', this.phone)
+    async getAuthCode () {
+      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      if (res) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            this.interTime = 60
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
     },
-    submit () {
+    async submit () {
       if (!this.password) {
         return this.$toast.show('warn', '密码格式不正确')
       }
@@ -41,20 +58,20 @@ export default {
         confirmPwd: this.confirmpass,
         msgAuthCode: this.authCode
       }
-      this.$http({
+      let res = await this.$http({
         method: 'post',
         headers: {
           token: this.token
         },
         data: params,
         url: 'sso/user/changePassword'
-      }, res => {
-        console.log(res)
-        if (res.data.code === 0) {
-          this.$toast.show('warn', '修改密码成功')
-        } else {
-          this.$toast.show('warn', res.data.msg)
-        }
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', response.msg)
+      }
+      this.$toast.show('warn', '密码修改成功', () => {
+        this.$emit('currentActive', 'ilogin')
       })
     }
   }

+ 61 - 6
src/page/layout/aside/temp/ltemp/login.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="ilogin-layout">
     <div class="input-con">
-    <div class="input"><input v-model="phone" placeholder="请输入手机号码" type="text"></div>
-    <div class="input"><input v-model="password" placeholder="输入密码" type="password"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' placeholder="请输入手机号码" type="text"></div>
+    <div class="input"><input  readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off"  @keyup.enter="login" v-model="password" placeholder="输入密码" maxlength='12' type="password"></div>
       <div class="remember" @click="rememberMe=~rememberMe">
         <span>
           <img v-if="rememberMe"  src="@/assets/images/icon-click.png" alt="">
@@ -13,7 +13,7 @@
       <div class="login-dec">不支持通过第三方账号授权登录</div>
     </div>
     <div class="qrcode">
-      <img src="@/assets/images/index_img_ecode.png" alt="">
+      <img v-if="codeImg" :src="`${$serverName}${codeImg}`" alt="">
       <img src="@/assets/images/icon-qrcode.png" alt="">
       <div class="login-dec">打开四维看看app扫一扫登录</div>
     </div>
@@ -21,8 +21,8 @@
 </template>
 <script>
 import {mapState} from 'vuex'
-
 export default {
+  props: ['active', 'current'],
   computed: {
     ...mapState({
       token: state => state.user.token
@@ -36,11 +36,36 @@ export default {
     return {
       phone: username,
       password: password,
-      rememberMe: remember
+      rememberMe: remember,
+      codeImg: '',
+      isFirst: true,
+      t1: null
     }
   },
   mounted () {
-
+    if (this.current === 'ilogin' && this.active) {
+      this.getQrCode()
+    }
+  },
+  watch: {
+    active (newVal) {
+      // (newVal && this.isFirst && !this.token) && this.getQrCode()
+      if (newVal) {
+        this.getQrCode()
+      } else {
+        clearInterval(this.t1)
+        this.t1 = null
+      }
+    }
+    // (newVal) {
+    //   console.log(newVal)
+    //   newVal && this.getQrCode()
+    //   // (newVal && this.isFirst && !this.token) && this.getQrCode()
+    // }
+  },
+  beforeDestroy () {
+    clearInterval(this.t1)
+    this.t1 = null
   },
   methods: {
     async login () {
@@ -59,7 +84,37 @@ export default {
         rememberMe: Boolean(this.rememberMe)
       }
       await this.$store.dispatch('login', params)
+      clearInterval(this.t1)
+      this.t1 = null
       if (this.token) this.$bus.$emit('hideAside')
+    },
+    async getQrCode () {
+      let res = await this.$http({
+        method: 'get',
+        url: '/sso/user/createLoginQrCode'
+      })
+      this.codeImg = res.data.data.url
+      this.isFirst = false
+      let params = {
+        uuid: res.data.data.uuid
+      }
+      this.t1 = setInterval(async () => {
+        let data = await this.$http({
+          method: 'post',
+          data: params,
+          url: '/sso/user/sendUserInfo'
+        })
+        let response = data.data
+        if (response.code === 0) {
+          this.$store.commit('saveToken', response.data.token)
+          if (response.data.token) {
+            this.$bus.$emit('hideAside')
+            this.$store.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
+            this.$store.dispatch('getCart')
+          }
+          return false
+        }
+      }, 3000)
     }
   }
 }

+ 35 - 16
src/page/layout/aside/temp/ltemp/register.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="iregister-layout">
-    <div class="input"><input v-model="nickname" placeholder="昵称" type="text"></div>
-    <div class="input"><input v-model="phone" placeholder="输入手机号码" type="text"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" v-model="nickname" placeholder="昵称" type="text"></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" v-model="phone" oninput="value=value.replace(/[^\d]/g,'')" maxlength='11' placeholder="输入手机号码" type="text"></div>
     <div class="verification input">
       <input v-model="authCode" placeholder="输入验证码" type="text">
-      <span @click="getAuthCode">获取验证码</span>
+      <span v-if="!jishi" @click="getAuthCode">获取验证码</span>
+      <span v-else>{{interTime}}s后重新发送</span>
     </div>
-    <div class="input"><input v-model="password" type="password" placeholder="密码" ></div>
-    <div class="input"><input v-model="confirmPass" type="password" placeholder="再次输入密码" ></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" v-model="password" maxlength='12' type="password" placeholder="密码" ></div>
+    <div class="input"><input readonly onfocus="this.removeAttribute('readonly')"  autocomplete="off" v-model="confirmPass" maxlength='12' type="password" placeholder="再次输入密码" ></div>
     <div class="temp-btn submit" @click="submit">提交</div>
   </div>
 </template>
@@ -20,14 +21,31 @@ export default {
       phone: '',
       authCode: '',
       password: '',
-      confirmPass: ''
+      confirmPass: '',
+      interTime: 60,
+      jishi: false,
+      interl: null
     }
   },
   methods: {
-    getAuthCode () {
-      this.$store.dispatch('getAuthCode', this.phone)
+    async getAuthCode () {
+      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      if (res) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            this.interTime = 60
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
     },
-    submit () {
+    async submit () {
       let params = {
         password: this.password,
         phoneNum: this.phone,
@@ -36,16 +54,17 @@ export default {
         country: '中国',
         confirmPwd: this.confirmPass
       }
-      this.$http({
+      let res = await this.$http({
         method: 'post',
         data: params,
         url: '/sso/user/register'
-      }, res => {
-        console.log('asdasdas', res)
-
-        if (res.data.code !== 0) {
-          this.$toast.show('warn', res.data.msg)
-        }
+      })
+      let response = res.data
+      if (response.code !== 0) {
+        return this.$toast.show('warn', response.msg)
+      }
+      this.$toast.show('warn', '注册成功', () => {
+        this.$emit('currentActive', 'ilogin')
       })
     }
   }

+ 15 - 7
src/page/layout/header/index.vue

@@ -8,7 +8,7 @@
       </router-link>
     </div>
     <div class="menu">
-      <div class="lang">
+      <div class="lang" :style="{maxWidth:isWide?'300px':'150px'}">
         <vcenter>
           <a :class="{active: language === 'en'}" @click="$store.commit('change_language', 'en')">En</a>
           <a :class="{active: language === '中'}" @click="$store.commit('change_language', '中')">中</a>
@@ -34,13 +34,12 @@
       </div>
     </div>
     <div class="ctrl">
-      <a class="search" @click="searchHandle" :class="{active: hoverCp === 'isearch'}">
+      <a class="search" ref='isearchref' @click="searchHandle" :class="{active: hoverCp === 'isearch'}">
         <vcenter>
           <i class="iconfont icon-sousuo open"></i>
           <i class="iconfont icon-cuowu hide"></i>
         </vcenter>
       </a>
-      <!-- <img class="avatar" src="@/assets/images/product_img_content_3.jpg" alt> -->
       <a class="user" v-if="!isLogin" @click="loginHandle">
         <vcenter>
           <i class="iconfont icon-geren"></i>
@@ -48,12 +47,12 @@
         </vcenter>
       </a>
       <a class="user cart" v-else>
-        <div class="cart-user" @click="$router.push({name:'manage'})">
+        <div class="cart-user" @click="$router.push({name:'information'})">
           <div class="user-img" :style="{background:`url(${info.head}) 50% 50%/cover no-repeat `,}"></div>
         </div>
         <div class="cart-icon" @click="loginHandle">
           <i class="iconfont icon-cart"></i>
-          <sup>{{count}}</sup>
+          <sup>{{count>99?'99+':count}}</sup>
           <span>{{langHeader.cart}}</span>
         </div>
       </a>
@@ -64,7 +63,8 @@
 <script>
 import { mapState } from 'vuex'
 import vcenter from '@/components/vcenter'
-import { getPosition } from '@/util'
+import { getPosition, isWide } from '@/util'
+
 import browser from '@/util/browser'
 
 export default {
@@ -75,12 +75,12 @@ export default {
       overb: false,
       active: true,
       ismobile: browser.mobile,
+      isWide,
       count: 0
     }
   },
   methods: {
     clickHandle (nav) {
-      console.log(nav)
       if (nav.cp === 'case_overview') {
         this.$router.push({name: 'cases', params: {id: '房地产'}})
       } else if (nav.cp === 'service_overview') {
@@ -137,7 +137,15 @@ export default {
     this.$bus.$on('updateCart', data => {
       this.count = data
     })
+    this.$bus.$on('hideSearch', target => {
+      if (this.$refs.isearchref) {
+        if (!this.$refs.isearchref.contains(target)) {
+          this.hideCp()
+        }
+      }
+    })
     this.sizeHandle = () => {
+      this.isWide = Math.round(devicePixelRatio * 100) === 100 ? window.innerWidth > 1600 : true
       this.$store.commit('change_nav_division', getPosition(this.$refs.list).x)
     }
     window.addEventListener('resize', this.sizeHandle)

+ 7 - 8
src/page/layout/header/istyle.scss

@@ -1,5 +1,5 @@
 .header-layout {
-  $mc: .7s cubic-bezier(.77, 0, .175, 1);
+  $mc: .5s cubic-bezier(.77, 0, .175, 1);
   $ts: all $mc;
   $split: #7f7f7f;
   background-color: #101010;
@@ -47,7 +47,6 @@
       box-sizing: border-box;
       text-align: center;
       padding-right: 10px;
-      max-width: 300px;
       flex: 1;
 
       a {
@@ -195,13 +194,14 @@
           display: inline-block;
           position: relative;
           sup{
-            width: 14px;
-            height: 14px;
+            min-width: 14px;
+            min-height: 14px;
             font-size: 12px;
             border-radius: 50%;
             line-height: 14px;
-            top: -4px;
-            left: 32px;
+            padding: 0 2px;
+            top: -8px;
+            left: 30px;
             display: inline-block;
             position: absolute;
             background-color: #ff0000;
@@ -251,11 +251,10 @@
 
 }
 
-@media screen and (max-width:1600px){
+@media screen and (max-width:1600px) and (device-pixel-ratio: 1){
   .header-layout{
     .menu {
       .lang {
-        max-width: 150px;
       }
     }
   }

+ 3 - 2
src/page/location/style.scss

@@ -9,7 +9,8 @@ $loca-ani:0.5s;
 .location-layout{
   overflow: hidden;
   .plate01{
-    background: url("~@/assets/images/hxjs-bg.jpg") center no-repeat;
+    background: url("~@/assets/images/hxjs-bg.jpg") no-repeat;
+    background-size: cover;
     .layout{
       max-width: 1280px;
       margin: 0 0 0 425px;
@@ -46,7 +47,7 @@ $loca-ani:0.5s;
               display: inline-block;
               vertical-align: middle;
               margin-top: 20px;
-              text-align: justify;
+              text-align: left;
               width: 100%;
             }
           }

+ 38 - 34
src/page/manage/index.vue

@@ -1,14 +1,15 @@
 <template>
   <div class="manage-layout">
     <div class="manage-bg">
-      <div class="manage-con" :style="{marginLeft:(split+37)+'px'}">
-        <div class="info" >
+      <div class="manage-con" :style="{marginLeft:(split + 37)+'px'}">
+        <div class="info">
         <img class="avatar" :src="info.head" alt>
         <div class="member">
           <p>尚未开通任何会员</p>
           <p>{{info.userName}}</p>
         </div>
-        <div class="open-btn" @click="open">立即开通</div>
+        <div class="open-btn">立即开通</div>
+        <!-- <router-link :to="{path:'/capacity'}">去扩容</router-link> -->
       </div>
       <div class="capacity">
         <div class="c-line">
@@ -26,49 +27,56 @@
         <div v-for="(item,index) in settings" :key="index">
           <ul class="list-items">
             <li v-for="(sub,i) in item.items" :key="i">
-              <span @click="tabHandle(sub)" :class='{active:active.cp===sub.cp}'>{{sub.name}}</span>
+              <span @click="tabHandle(sub)" :class='{active:active.name===sub.name}'>{{sub.name}}</span>
             </li>
           </ul>
         </div>
       </div>
       <div class="mc-right">
         <div class="mc-title">{{active.name}}</div>
-        <component :is="active.cp"/>
+        <router-view />
+        <!-- <component :is="active.cp"/> -->
       </div>
     </div>
   </div>
 </template>
 <script>
 import {mapState} from 'vuex'
-import iinfomation from './temp/infomation'
-import ichange from './temp/change'
-import iconsumption from './temp/consumption'
-import iinvoice from './temp/invoice'
-import ilogout from './temp/logout'
-import iorder from './temp/order'
-import iprivilege from './temp/privilege'
-import iscene from './temp/scene'
 
 export default {
-  components: {iinfomation, ichange, iconsumption, iinvoice, ilogout, iorder, iscene, iprivilege},
 
   data () {
+    let nameArr = {
+      information: '账号信息',
+      scene: '我的场景',
+      order: '我的订单',
+      device: '我的设备',
+      consumption: '消费记录',
+      change: '修改密码',
+      logout: '退出登录'
+    }
+
     let settings = [
       {
         name: 'info',
         items: [{
           name: '账号信息',
-          cp: 'iinfomation'
+          to: {name: 'information'}
         }, {
           name: '我的场景',
-          cp: 'iscene'
+          to: {name: 'scene'}
         }, {
           name: '我的订单',
-          cp: 'iorder'
-        }, {
-          name: '特权介绍',
-          cp: 'iprivilege'
-        }]
+          to: {name: 'order'}
+        }
+        // {
+        //   name: '我的设备',
+        //   to: {name: 'device'}
+        // }, {
+        //   name: '消费记录',
+        //   to: {name: 'consumption'}
+        // }
+        ]
       },
       // {
       //   name: 'member',
@@ -76,9 +84,6 @@ export default {
       //     name: '特权介绍',
       //     cp: 'iprivilege'
       //   }, {
-      //     name: '消费记录',
-      //     cp: 'iconsumption'
-      //   }, {
       //     name: '增值发票',
       //     cp: 'iinvoice'
       //   }]
@@ -87,37 +92,36 @@ export default {
         name: 'security',
         items: [{
           name: '修改密码',
-          cp: 'ichange'
+          to: {name: 'change'}
         }, {
           name: '退出登录',
-          cp: 'ilogout'
+          to: 'logout'
         }]
       }
     ]
     return {
       settings,
       active: {
-        cp: 'iinfomation',
-        name: '账号信息'
+        name: nameArr[this.$route.name],
+        to: {name: this.$route.name}
       }
     }
   },
+  mounted () {
+  },
   methods: {
-    open () {
-      this.$toast.showConfirm('success', '开通成功')
-    },
     tabHandle (sub) {
-      switch (sub.cp) {
-        case 'ilogout':
+      switch (sub.to) {
+        case 'logout':
           this.$store.dispatch('logout')
           this.$router.push({name: 'home'})
           break
 
         default:
           this.active = sub
+          this.$router.push(sub.to)
           break
       }
-      // sub.cp !== 'ilogout' ? this.active = sub.cp : this.$store.commit('logout')&&t
     }
   },
   computed: {

+ 1 - 0
src/page/manage/style.scss

@@ -108,6 +108,7 @@
       }
     }
     .mc-right{
+      width: 100%;
       .mc-title{
         margin-left: 40px;
         margin-top: 34px;

+ 23 - 6
src/page/manage/temp/change.vue

@@ -6,10 +6,11 @@
       </div>
       <div class="input yanzhengma">
         <input class="" v-model="code" type="text" placeholder="验证码">
-        <div @click="getAuthCode" class="code btn parmary">获取验证码</div>
+        <div v-if="!jishi" @click="getAuthCode" class="code btn parmary">获取验证码</div>
+        <div v-else class="code btn parmary">{{interTime}}s后重新发送</div>
       </div>
       <div class="input">
-        <input class="" v-model="password" type="password" placeholder="新密码">
+        <input class="" maxlength="12" v-model="password" type="password" placeholder="新密码">
       </div>
       <div @click="submit" class="btn parmary">
         提交
@@ -31,16 +32,32 @@ export default {
     return {
       password: '',
       phone: '',
+      interTime: 60,
+      jishi: false,
       code: ''
     }
   },
   methods: {
-    getAuthCode () {
-      this.$store.dispatch('getAuthCode', this.phone)
+    async getAuthCode () {
+      let res = await this.$store.dispatch('getAuthCode', this.phone)
+      if (res) {
+        this.interl && clearInterval(this.interl)
+        this.interl = null
+        this.jishi = true
+        this.interl = setInterval(() => {
+          this.interTime--
+          if (this.interTime <= 0) {
+            this.jishi = false
+            this.interTime = 60
+            clearInterval(this.interl)
+            this.interl = null
+          }
+        }, 1000)
+      }
     },
     submit () {
       if (!this.password) {
-        return alert('密码格式不正确')
+        return this.$toast.show('warn', '密码格式不正确')
       }
       let params = {
         password: this.password,
@@ -57,7 +74,7 @@ export default {
       }, res => {
         let data = res.data
         if (data.code === 0) {
-          this.$toast.show('success', '请重新登录')
+          this.$toast.show('success', '密码修改成功,请重新登录')
           this.$store.commit('logout')
         }
       })

+ 229 - 1
src/page/manage/temp/consumption.vue

@@ -1,13 +1,241 @@
 <template>
-  <div>information</div>
+  <div class="consump-layout">
+    <div class="c-header">
+      <ul class="tab-list">
+        <li :class="{active:i===0}" v-for="(item,i) in tabList" :key="i">
+          {{item.name}}
+        </li>
+      </ul>
+      <div class="tab-select">
+        全部
+        <ul>
+          <li>全部</li>
+          <li>子选项</li>
+        </ul>
+      </div>
+    </div>
+    <tableList :header='capacity' :data='data' class="table-list" >
+      <div slot-scope="{data}" slot="header">
+        {{data.name}}
+      </div>
+      <div slot-scope="{data}" slot="item">
+        {{data}}
+      </div>
+    </tableList>
+    <div class="paging" v-if="total">
+      <vcenter>
+          <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
+      </vcenter>
+    </div>
+  </div>
 </template>
 
 <script>
+import tableList from '@/components/table'
+import {capacity} from './iconsumption'
+import Paging from '@/components/Paging'
+import vcenter from '@/components/vcenter'
+
 export default {
+  components: {
+    tableList,
+    Paging,
+    vcenter
+  },
+  data () {
+    let tabList = [
+      {
+        name: '扩容记录'
+      }, {
+        name: '充值记录'
+      }, {
+        name: '增值发票'
+      }
+    ]
+    let data = [{
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    }, {
+      orderSn: 'KR180928ac',
+      channel: '官方预售活动赠送',
+      size: '100G',
+      paytype: '支付宝',
+      bill: '9800元',
+      validity: '终生有效',
+      status: '使用中',
+      date: '2018-09-28 16:14:23'
+    } ]
 
+    return {
+      data,
+      tabList,
+      capacity,
+      total: 10,
+      pageSize: 10,
+      currentPage: 1
+    }
+  },
+  methods: {
+    pageChange (data) {
+      this.currentPage = data
+    }
+  }
 }
 </script>
 
 <style lang="scss" scoped>
+$theme-color: #1fe4dc;
+.consump-layout{
+  margin: 30px 0 30px 40px;
+  width: 90%;
+  .c-header{
+    .tab-list{
+      display: inline-block;
+      li{
+        display: inline-block;
+        margin-right: 40px;
+        cursor: pointer;
+      }
+      .active{
+        color: $theme-color;
+        border-bottom: 2px solid $theme-color;
+        font-weight: bold;
+      }
+    }
+    .tab-select{
+      float: right;
+      position: relative;
+      width: 200px;
+      padding-left: 10px;
+      border: 1px solid #ccc;
+      border-radius: 5px;
+      ul{
+        position: absolute;
+        // max-height: 0;
+        left: 0;
+        top: 24px;
+        padding-left: 10px;
+        background: #fff;
+        overflow: hidden;
+        width: 100%;
+        box-shadow: 0 0 10px rgba($color: #000000, $alpha: 0.5);
+      }
+    }
+  }
+  .table-list{
+    margin-top: 40px;
+  }
+  .paging {
+  // border-left: #e5e5e5 1px solid;
+    height: 100%;
+    margin-bottom: 40px;
+    & /deep/ .layout {
+      text-align: center;
+      margin-top: 10px;
+    }
+    & /deep/ .layout a:not(:last-child) {
+      margin: 10px 8px;
+      font-size: 16px;
+      display: inline-block;
+      font-weight: 500;
+      cursor: pointer;
+      user-select: none;
+      color: #999;
+      position: relative;
+      transition: color 0.3s;
+    }
+    & /deep/ .layout a:last-child {
+      position: relative;
+      top: -5px;
+      display: -ms-inline-flexbox;
+      display: inline-flex;
+      -ms-flex-align: center;
+      align-items: center;
+      height: 22px;
+      padding: 0 9.6px;
+      padding: 0 0.6rem;
+    }
+    & /deep/ .layout a:last-child::before,
+    & /deep/ .layout a:last-child::after {
+      content: "";
+      display: inline-block;
+      will-change: transform;
+      transition: transform 0.3s;
+    }
+
+    & /deep/ .layout a:not(:last-child).active::after,
+    & /deep/ .layout a:not(:last-child).active,
+    & /deep/ .layout a:not(:last-child):hover,
+    & /deep/ .layout a:not(:last-child):hover::after {
+      color: #111111;
+      transform: scaleX(1);
+    }
+
+    & /deep/ .layout a:not(:last-child)::after {
+      content: "";
+      height: 3px;
+      width: 140%;
+      background-color: #111;
+      display: block;
+      margin-left: -20%;
+      margin-top: 3px;
+      transform-origin: 50% 50%;
+      transform: scaleX(0);
+      will-change: transform;
+      transition: transform 0.3s;
+    }
+  }
+}
 
 </style>

+ 72 - 0
src/page/manage/temp/device.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="device-layout">
+    <div class="d-header">
+      <ul class="tab-list">
+        <li :class="{active:i===0}" v-for="(item,i) in tabList" :key="i">
+          {{item.name}}
+        </li>
+      </ul>
+      <div class="tab-search">
+        <input type="text">
+      </div>
+    </div>
+    <div class="d-con">
+
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    let tabList = [
+      {
+        name: '四维看看Pro'
+      }, {
+        name: '四维看看Lite'
+      }
+    ]
+    return {
+      tabList
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+
+.device-layout{
+  margin: 30px 0 30px 40px;
+  width: 90%;
+  .d-header{
+    .tab-list{
+      display: inline-block;
+      li{
+        display: inline-block;
+        margin-right: 40px;
+        cursor: pointer;
+      }
+      .active{
+        color: $theme-color;
+        border-bottom: 2px solid $theme-color;
+        font-weight: bold;
+      }
+    }
+    .tab-search{
+      float: right;
+      position: relative;
+      width: 200px;
+      padding-left: 10px;
+      border: 1px solid #ccc;
+      border-radius: 5px;
+      input{
+        appearance: none;
+        line-height: 24px;
+        height: 24px;
+        border: 0;
+      }
+    }
+  }
+}
+</style>

+ 50 - 0
src/page/manage/temp/iconsumption.js

@@ -0,0 +1,50 @@
+let capacity = [
+  {
+    key: 'orderSn',
+    name: '扩容单号'
+  }, {
+    key: 'channel',
+    name: '获得渠道'
+  }, {
+    key: 'size',
+    name: '容量大小'
+  }, {
+    key: 'paytype',
+    name: '支付类型'
+  }, {
+    key: 'bill',
+    name: '实付金额'
+  }, {
+    key: 'validity',
+    name: '有效期'
+  }, {
+    key: 'status',
+    name: '状态'
+  }, {
+    key: 'date',
+    name: '消费时间'
+  }
+]
+
+let recharge = [
+  {
+    key: 'rechargeType',
+    name: '充值类型'
+  }, {
+    key: 'name',
+    name: '充值名称'
+  }, {
+    key: 'point',
+    name: '点数'
+  }, {
+    key: 'device',
+    name: '设备'
+  }, {
+    key: 'date',
+    name: '消费时间'
+  }
+]
+export {
+  capacity,
+  recharge
+}

+ 78 - 38
src/page/manage/temp/infomation.vue

@@ -58,17 +58,17 @@
       </div>
       <div class="address edit-address" slot="edit">
         <div class="input-con">
-          <input type="text" v-model="address.shipName" :placeholder="address.shipName||'姓名'">
-          <input type="text" v-model="address.shipMobile" :placeholder="address.shipMobile||'电话'">
+          <input type="text" v-model="editAdd.shipName" :placeholder="address.shipName||'姓名'">
+          <input type="text" v-model="editAdd.shipMobile" :placeholder="address.shipMobile||'电话'">
         </div>
         <div class="input-con">
-          <citySelect :areaPath="address.shipAreaPath" @currentVal="getCurrentSelect"/>
+          <citySelect :areaPath="editAdd.shipAreaPath" @currentVal="getCurrentSelect"/>
         </div>
         <div class="input-con address-input">
           <input
             type="text"
-            v-model="address.shipAddress"
-            :placeholder="address.shipAddress||'详细地址'"
+            v-model="editAdd.shipAddress"
+            :placeholder="editAdd.shipAddress||'详细地址'"
           >
         </div>
         <div class="btn parmary" @click="uAddress">保存</div>
@@ -82,7 +82,7 @@
       :isActive="invoiceStatus"
     >
       <div class="invoice" slot="show">
-        <p class="p-desc">{{invoice2.title||'暂无信息'}}</p>
+        <p class="p-desc">{{invoice2.title||invoice3.title||'暂无信息'}}</p>
       </div>
       <div class="invoice edit-invoice" slot="edit">
         <div class="select-con">
@@ -98,8 +98,8 @@
         </div>
         <div v-if="cInvoice==='normal'">
           <div class="input-con">
-            <input type="text" placeholder="请输入发票抬头" v-model="invoice2.title">
-            <input type="text" placeholder="请输入税务登记号(个人用户可不填)" v-model="invoice2.code">
+            <input type="text" placeholder="请输入发票抬头" v-model="editInvoice2.title">
+            <input type="text" placeholder="请输入税务登记号(个人用户可不填)" v-model="editInvoice2.code">
           </div>
         </div>
         <div v-else>
@@ -126,24 +126,57 @@
 import { mapState } from 'vuex'
 import edit from '@/components/edit'
 import citySelect from '@/components/citySelect'
-
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key]
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
 export default {
   components: { edit, citySelect },
   computed: {
     ...mapState({
       info: state => state.user.info,
       token: state => state.user.token,
-      invoice2: state => state.user.invoice2 || {},
-      invoice3: state => state.user.invoice3 || {},
-      address: state =>
-        state.user.address || {
-          shipAddress: '',
-          shipAreaPath: '',
-          province: '',
-          city: '',
-          shipMobile: '',
-          shipName: ''
+      invoice2: state => {
+        let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      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 => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
         }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      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 () {
@@ -182,21 +215,22 @@ export default {
           localStorage.setItem('info', JSON.stringify(this.info))
         })
     },
-    getVal (val) {
-      return val.split(',')
-    },
+
     saveInvoice (cInvoice) {
       let params = {}
+      let invoiceType = ''
       if (cInvoice === 'normal') {
+        invoiceType = 2
         params = {
-          invoiceType: 2,
-          title: this.invoice2.title,
-          code: this.invoice2.code
+          invoiceType,
+          title: this.editInvoice2.title,
+          code: this.editInvoice2.code
         }
       } else {
-        let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.invoice3
+        let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.editInvoice3
+        invoiceType = 3
         params = {
-          invoiceType: 3,
+          invoiceType,
           title,
           code,
           organizedAddress,
@@ -205,7 +239,6 @@ export default {
           bankAccount
         }
       }
-
       this.$http
         .post('user/invoice/save', params, {
           headers: {
@@ -213,15 +246,19 @@ export default {
           }
         })
         .then(data => {
-          let res = data.data
           this.invoiceStatus = true
-          localStorage.setItem('invoice', JSON.stringify(res.data))
+          this.$store.dispatch('getInvoice', {
+            type: invoiceType,
+            params: {
+              invoiceType: invoiceType
+            }
+          })
         })
     },
     uAddress () {
-      this.address.province = this.tempSelect[0]
-      this.address.city = this.tempSelect[1]
-      this.address.shipAreaPath = this.tempSelect.join(',')
+      this.editAdd.province = this.tempSelect[0]
+      this.editAdd.city = this.tempSelect[1]
+      this.editAdd.shipAreaPath = this.tempSelect.join(',')
       let {
         shipAddress,
         shipAreaPath,
@@ -229,7 +266,7 @@ export default {
         city,
         shipMobile,
         shipName
-      } = this.address
+      } = this.editAdd
       let params = {
         shipAddress,
         shipAreaPath,
@@ -245,9 +282,11 @@ export default {
           }
         })
         .then(data => {
-          let res = data.data
           this.addressStatus = true
-          localStorage.setItem('address', JSON.stringify(res.data))
+          this.$store.dispatch('getInfo', {
+            url: '/user/getReceiverInfo',
+            name: 'address'
+          })
         })
     },
     update (e) {
@@ -275,13 +314,13 @@ export default {
       url: '/user/getReceiverInfo',
       name: 'address'
     })
-    this.$store.dispatch('getInvoice', {
+    Object.keys(this.invoice2).length === 0 && this.$store.dispatch('getInvoice', {
       type: 2,
       params: {
         invoiceType: 2
       }
     })
-    this.$store.dispatch('getInvoice', {
+    Object.keys(this.invoice3).length === 0 && this.$store.dispatch('getInvoice', {
       type: 3,
       params: {
         invoiceType: 3
@@ -295,6 +334,7 @@ export default {
 .info-layout {
   $theme-color: #1fe4dc;
   $border-color: #e7e7e7;
+  width: 90%;
   input {
     appearance: none;
     line-height: 36px;

+ 98 - 71
src/page/manage/temp/order.vue

@@ -1,48 +1,54 @@
 <template>
   <div class="order-layout">
-    <div class="order-item" v-for="(item,i) in myorder.list" :key='i'>
-      <div class="o-top">订单号:{{item.orderSn}}</div>
-      <div class="o-title">
-        <span>商品</span>
-        <span>数量</span>
-        <span>小计(CNY)</span>
-      </div>
-      <div class="o-detail" v-for="(sub,index) in item.orderItems" :key="index">
-        <div class="od-name">
-          <img class="thumbnail" :src="sub.pic" alt>
-          <div>
-            <p>{{sub.goodsName}}</p>
-            <p>{{sub.description}}</p>
+    <div v-if="total">
+      <div class="order-item" v-for="(item,i) in myorder.list" :key="i">
+        <div class="o-top">订单号:{{item.orderSn}}</div>
+        <div class="o-title">
+          <span>商品</span>
+          <span>数量</span>
+          <span>小计(CNY)</span>
+        </div>
+        <div class="o-detail" v-for="(sub,index) in item.orderItems" :key="index">
+          <div class="od-name">
+            <img class="thumbnail" :src="sub.pic" alt>
+            <div>
+              <p>{{sub.goodsName}}</p>
+              <p>{{sub.description}}</p>
+            </div>
           </div>
+          <div class="count">{{sub.goodsCount}}</div>
+          <div class="sum">{{sub.goodsPrice*sub.goodsCount}}</div>
+        </div>
+        <div class="sum-price">
+          <div></div>
+          <div>总价:¥{{item.goodsAmount}}</div>
+        </div>
+        <div class="to-pay">
+          <template v-if="getStatus(item) === 'unpaid'">
+            <span class="cancel" @click="cancal(item)">取消订单</span>
+            <span class="pay btns" @click="toPay(item)">立即付款</span>
+          </template>
+          <template v-else-if="getStatus(item) === 'shipped'">
+            <span class="expreeNum">物流单号:77110342778758</span>
+          </template>
+          <template v-else-if="getStatus(item) === 'unshipped'">
+            <span class="expreeNum">等待商家发货</span>
+          </template>
+          <template v-else-if="getStatus(item) === 'finish'">
+            <span class="expreeNum">已完成</span>
+          </template>
+          <template v-else>
+            <span class="expreeNum">已取消</span>
+          </template>
         </div>
-        <div class="count">{{sub.goodsCount}}</div>
-        <div class="sum">{{sub.goodsPrice*sub.goodsCount}}</div>
-      </div>
-      <div class="sum-price">
-        <div></div>
-        <div>总价:{{item.goodsAmount}}</div>
-      </div>
-      <div class="to-pay">
-        <template v-if="getStatus(item) === 'unpaid'">
-          <span class="cancel" @click="cancal(item)">取消订单</span>
-          <span class="pay btns" @click="toPay(item)">立即付款</span>
-        </template>
-        <template v-else-if="getStatus(item) === 'shipped'">
-          <span class="expreeNum">物流单号:77110342778758</span>
-        </template>
-        <template v-else-if="getStatus(item) === 'unshipped'">
-          <span class="expreeNum">等待商家发货</span>
-        </template>
-        <template v-else-if="getStatus(item) === 'finish'">
-          <span class="expreeNum">已完成</span>
-        </template>
-         <template v-else>
-          <span class="expreeNum">已取消</span>
-        </template>
       </div>
     </div>
-    <div class="paging">
-      <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
+    <div class="scene-nothing" v-else>
+      <img src="@/assets/images/nothing.png" alt>
+      <div>暂无任何订单,赶紧去购买吧。</div>
+    </div>
+    <div class="paging" v-if="total">
+      <Paging @clickHandle="pageChange" @maxPage="data=>maxPage=data" :current="currentPage" :total="total" :equable="pageSize"/>
     </div>
   </div>
 </template>
@@ -52,12 +58,13 @@ import { mapState } from 'vuex'
 import Paging from '@/components/Paging'
 
 export default {
-  components: {Paging},
+  components: { Paging },
   data () {
     return {
       pageSize: 2,
       currentPage: 1,
-      total: 0
+      total: 0,
+      maxPage: 0
     }
   },
   watch: {
@@ -69,10 +76,12 @@ export default {
     ...mapState({
       token: state => state.user.token,
       myorder: state => {
-        if (Object.prototype.toString.call(state.user.myorder) === '[object Object]') {
+        let type = Object.prototype.toString.call(state.user.myorder)
+        if (type === '[object Object]') {
           return state.user.myorder
         }
-        return (state.user.myorder ? JSON.parse(state.user.myorder) : {})
+        let condition = state.user.myorder && state.user.myorder !== 'null' && type !== '[object Array]'
+        return condition ? JSON.parse(state.user.myorder) : {}
       }
     })
   },
@@ -83,18 +92,18 @@ export default {
     pageChange (data) {
       this.currentPage = data
     },
-    getList () {
+    async getList () {
+      window.scrollTo(0, 0)
       let params = {
         type: '',
         pageNum: this.currentPage,
         pageSize: this.pageSize
       }
-      this.$store.dispatch('getUserOrder', params)
+      await this.$store.dispatch('getUserOrder', params)
       this.pageSize = this.myorder.pageSize
       this.total = this.myorder.total || 0
     },
     getStatus (item) {
-      console.log(item)
       let temp = ''
       let sPay = function () {
         switch (item.shippingStatus) {
@@ -138,11 +147,15 @@ export default {
       return temp
     },
     toPay (item) {
-      this.$router.push({name: 'pay',
+      this.$router.push({
+        name: 'pay',
         params: {
+          payType: 0,
           orderId: item.id,
-          orderType: 0
-        }})
+          orderType: 0,
+          orderSn: item.orderSn
+        }
+      })
     },
     async cancal (item) {
       this.$toast.showConfirm('warn', '确定要删除当前订单吗?', async () => {
@@ -160,6 +173,7 @@ export default {
         let data = res.data
         if (data.code === 0) {
           return this.$toast.show('warn', '删除成功', () => {
+            this.currentPage = this.currentPage >= this.maxPage ? this.maxPage : this.currentPage
             this.getList()
           })
         }
@@ -173,7 +187,7 @@ export default {
 <style lang="scss" scoped>
 $theme-color: #1fe4dc;
 $border-color: #e7e7e7;
-.btns{
+.btns {
   cursor: pointer;
   width: 180px;
   display: inline-block;
@@ -184,14 +198,13 @@ $border-color: #e7e7e7;
   font-size: 16px;
   background: $theme-color;
 }
-.order-layout{
-  width: 930px;
+.order-layout {
+  width: 75%;
   color: #2d2d2d;
-  .order-item{
-    width: 100%;
+  .order-item {
     margin: 40px;
     border: 1px solid $border-color;
-    .o-top{
+    .o-top {
       color: #68b8f1;
       line-height: 60px;
       height: 60px;
@@ -199,7 +212,7 @@ $border-color: #e7e7e7;
       padding: 0 20px;
       border-bottom: 1px solid $border-color;
     }
-    .o-title{
+    .o-title {
       display: flex;
       height: 50px;
       padding: 0 85px;
@@ -207,17 +220,17 @@ $border-color: #e7e7e7;
       line-height: 50px;
       border-bottom: 1px solid $border-color;
       background: #fafafa;
-      span{
+      span {
         font-size: 14px;
         flex: 1;
         text-align: center;
-        &:first-child{
+        &:first-child {
           flex: 5;
           text-align: left;
         }
       }
     }
-    .o-detail{
+    .o-detail {
       display: flex;
       align-items: center;
       height: 100px;
@@ -225,52 +238,51 @@ $border-color: #e7e7e7;
       padding: 0 85px;
       color: #4a4a4a;
       font-size: 14px;
-      .od-name{
+      .od-name {
         display: flex;
         align-items: center;
         flex: 5;
-        .thumbnail{
+        .thumbnail {
           width: 20px;
           margin-left: 3px;
           margin-right: 60px;
         }
-        p{
+        p {
           line-height: 1.5;
-
         }
       }
-      .count{
+      .count {
         flex: 1;
         text-align: center;
       }
-      .sum{
+      .sum {
         flex: 1;
         text-align: right;
       }
     }
-    .sum-price{
+    .sum-price {
       display: flex;
       height: 50px;
       line-height: 50px;
       padding: 0 85px;
       border-bottom: 1px solid $border-color;
       border-top: 1px solid $border-color;
-      div{
+      div {
         flex: 6;
         color: #4a4a4a;
         font-size: 14px;
-        &:last-child{
+        &:last-child {
           flex: 1;
           text-align: right;
         }
       }
     }
-    .to-pay{
+    .to-pay {
       text-align: right;
       height: 90px;
       line-height: 90px;
       padding: 0 25px;
-      .cancel{
+      .cancel {
         font-size: 16px;
         color: #a0a0a0;
         display: inline-block;
@@ -278,12 +290,22 @@ $border-color: #e7e7e7;
         text-align: center;
         cursor: pointer;
       }
-      .expreeNum{
+      .expreeNum {
         margin-right: 60px;
         color: #2d2d2d;
       }
     }
   }
+  .scene-nothing{
+    padding: 42px 0 0 40px;
+    img{
+      padding-bottom: 22px;
+    }
+    div{
+      font-size: 16px;
+      color: #969696;
+    }
+  }
   .paging {
     // border-left: #e5e5e5 1px solid;
     height: 100%;
@@ -346,5 +368,10 @@ $border-color: #e7e7e7;
     }
   }
 }
+@media screen and (max-width: 1700px){
+  .order-layout {
+    width: 95%;
+  }
+}
 
 </style>

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

@@ -346,6 +346,7 @@ $theme-color: #1fe4dc;
 
 .privilege-layout {
   color: #2d2d2d;
+  width: 90;
   .p-container {
     margin-left: 80px;
     margin-top: 20px;

+ 176 - 100
src/page/manage/temp/scene.vue

@@ -1,120 +1,97 @@
 <template>
   <div class="scene-layout">
-    <ul>
-      <li v-for="(item,index) in scene" :key="index">
-        <img :src="item.img" alt="">
+    <ul v-if="total">
+      <li v-for="(item,index) in myscene.list" :key="index">
+        <a :href="item.webSite" target="_blank">
+          <img :src="item.thumb" alt="">
+        </a>
         <div class="name">
-          <div class="title">{{item.title}}</div>
+          <div class="title">{{item.sceneName}}</div>
           <div class="oper">
-            <span>编辑</span> / <span>删除</span>
+            <span>编辑</span> / <span @click="del(item)">删除</span>
           </div>
         </div>
-        <div><span>拍摄日期:</span><span>2018-07-09</span></div>
+        <div><span>拍摄日期:</span><span>{{item.createTime}}</span></div>
       </li>
     </ul>
+    <div class="scene-nothing" v-else>
+      <img src="@/assets/images/nothing.png" alt="">
+      <div>暂无任何场景,赶紧去拍摄吧。</div>
+    </div>
+    <div class="paging" v-if="total">
+      <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
+    </div>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
+import Paging from '@/components/Paging'
 export default {
+  components: {Paging},
   data () {
-    let scene = [
-      {
-        title: 'Oin Bar 前台',
-        username: 'VannyShen',
-        img: require('@/assets/images/cases/case_01.png'),
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_02.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_03.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_04.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_05.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_06.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_07.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_08.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_09.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_10.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_11.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_12.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_13.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_14.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_15.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }, {
-        title: 'Oin Bar 前台',
-        img: require('@/assets/images/cases/case_16.png'),
-        username: 'VannyShen',
-        viewcount: '2564'
-      }]
-
     return {
-      scene
+      pageSize: 12,
+      currentPage: 1,
+      total: 0
+    }
+  },
+  watch: {
+    currentPage () {
+      this.getList()
     }
   },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      myscene: state => {
+        let type = Object.prototype.toString.call(state.user.myscene)
+        if (type === '[object Object]') {
+          return state.user.myscene
+        }
+        let condition = state.user.myscene && state.user.myscene !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.myscene) : {})
+      }
+    })
+  },
   mounted () {
     this.getList()
   },
   methods: {
-    getList () {
+    async del (item) {
+      this.$toast.showConfirm('warn', '确定要删除当前场景吗?', async () => {
+        let params = {
+          sceneId: item.id
+        }
+        let res = await this.$http({
+          method: 'post',
+          data: params,
+          headers: {
+            token: this.token
+          },
+          url: '/user/scene/delete'
+        })
+        let data = res.data
+        if (data.code === 0) {
+          return this.$toast.show('warn', '删除成功', () => {
+            this.getList()
+          })
+        }
+        return this.$toast.show('error', '删除失败')
+      })
+    },
+    pageChange (data) {
+      this.currentPage = data
+    },
+    async getList () {
+      window.scrollTo(0, 0)
       let params = {
-        pageNum: 1,
-        pageSize: 10
+        pageNum: this.currentPage,
+        pageSize: this.pageSize
       }
-      this.$store.dispatch('getUserScene', params)
+      await this.$store.dispatch('getUserScene', params)
+      this.pageSize = this.myscene.pageSize
+      this.total = this.myscene.total || 0
     }
   }
 }
@@ -122,30 +99,42 @@ export default {
 
 <style lang="scss" scoped>
 .scene-layout{
-  padding: 30px 0 30px 40px;
+  width: 90%;
   ul{
-    display: flex;
-    flex-wrap: wrap;
+    padding: 30px 0 0 40px;
     li{
-      width: 30%;
+      width: 270px;
       display: inline-block;
       position: relative;
       margin-right: 25px;
       margin-bottom: 35px;
       color: #a0a0a0;
       max-width: 330px;
-      img{
+      font-size: 14px;
+      a{
         width: 100%;
+        height: 160px;
+        display: inline-block;
+        img{
+          width: 100%;
+          height: 100%;
+        }
       }
       .name{
         display: flex;
         justify-content: space-between;
-        line-height: 32px;
+        line-height: 22px;
         .title{
           font-weight: bold;
+          overflow: hidden;
+          text-overflow:ellipsis;
+          white-space: nowrap;
           color: #000;
+          flex: 2;
         }
         .oper{
+          flex: 1;
+          text-align: right;
           span{
             cursor: pointer;
           }
@@ -153,5 +142,92 @@ export default {
       }
     }
   }
+  .scene-nothing{
+    padding: 42px 0 0 40px;
+    img{
+      padding-bottom: 22px;
+    }
+    div{
+      font-size: 16px;
+      color: #969696;
+    }
+  }
+  .paging {
+    // border-left: #e5e5e5 1px solid;
+    height: 100%;
+    margin-bottom: 40px;
+    & /deep/ .layout {
+      text-align: left;
+      margin-top: 0;
+      margin-left: 15px;
+    }
+    & /deep/ .layout a:not(:last-child) {
+      margin: 10px 8px;
+      font-size: 16px;
+      display: inline-block;
+      font-weight: 500;
+      cursor: pointer;
+      user-select: none;
+      color: #999;
+      position: relative;
+      transition: color 0.3s;
+    }
+    & /deep/ .layout a:last-child {
+      position: relative;
+      top: -5px;
+      display: -ms-inline-flexbox;
+      display: inline-flex;
+      -ms-flex-align: center;
+      align-items: center;
+      height: 22px;
+      padding: 0 9.6px;
+      padding: 0 0.6rem;
+    }
+    & /deep/ .layout a:last-child::before,
+    & /deep/ .layout a:last-child::after {
+      content: "";
+      display: inline-block;
+      will-change: transform;
+      transition: transform 0.3s;
+    }
+
+    & /deep/ .layout a:not(:last-child).active::after,
+    & /deep/ .layout a:not(:last-child).active,
+    & /deep/ .layout a:not(:last-child):hover,
+    & /deep/ .layout a:not(:last-child):hover::after {
+      color: #111111;
+      transform: scaleX(1);
+    }
+
+    & /deep/ .layout a:not(:last-child)::after {
+      content: "";
+      height: 3px;
+      width: 140%;
+      background-color: #111;
+      display: block;
+      margin-left: -20%;
+      margin-top: 3px;
+      transform-origin: 50% 50%;
+      transform: scaleX(0);
+      will-change: transform;
+      transition: transform 0.3s;
+    }
+  }
+
+}
+
+@media screen and (max-width:1600px){
+  .scene-layout{
+    width: 100%;
+    ul{
+      li{
+        width: 240px;
+        margin-right: 20px;
+        a{
+          height: 142px;
+        }
+      }
+    }
+  }
 }
 </style>

+ 3 - 0
src/page/navs/index.vue

@@ -28,6 +28,9 @@ export default {
       let cpmap = Object.keys(modulMap).find(key => {
         return ~modulMap[key].indexOf(this.cp)
       })
+      if ((this.cp === 'location' || this.cp === 'about') && !cpmap) {
+        return null
+      }
       return cpmap || this.cp
     }
   },

+ 27 - 21
src/page/navs/search/index.vue

@@ -1,34 +1,29 @@
 <template>
-<div class="search-body">
+<div class="search-body" ref="searchcon">
   <div class="search-con">
     <div class="search-ban" :style="{marginLeft:(split-260)+ 'px'}">
       <div class="search-txt" v-if="scene.length">
         <vcenter>
-          <span >{{scene.length}}</span>
+          <span >{{total}}</span>
           <div></div>
         </vcenter>
       </div>
       <div class="search-input">
         <div class="input">
           <vcenter>
-            <input autofocus @focus="true" @keyup.enter="currentPage=1&&getData()" v-model="searchTxt" :placeholder="langSearch.placeholder" type="text">
+            <input autofocus @keyup.enter="enter" v-model="searchTxt" :placeholder="langSearch.placeholder" type="text">
           </vcenter>
         </div>
       </div>
     </div>
     <div class="search-btn">
-      <div class="img-con" @click="currentPage=1&&getData()">
+      <div class="img-con" @click="enter">
         <img :src="require('@/assets/images/search.png')" alt="">
       </div>
     </div>
     </div>
     <Item :searchTxt='searchTxt' :data='scene' :split='split'/>
-    <!-- <div class="more" v-if="scene.length>0">
-      <div class="result">
-        <div class="result-btn" @click="currentPage++">查看所有结果</div>
-      </div>
-    </div> -->
-    <div class="page-con" v-if="scene.length" :style="{paddingLeft:(split-260)+ 'px'}">
+    <div class="page-con" v-if="total" :style="{paddingLeft:(split-260)+ 'px'}">
       <div class="page-body">
         <!-- <div class="page-title">页码</div> -->
           <div class="paging">
@@ -89,7 +84,7 @@ export default {
   data () {
     return {
       items,
-      total: 90,
+      total: 0,
       searchTxt: '',
       pageSize: 10,
       scene: [],
@@ -110,35 +105,46 @@ export default {
         this.getData()
       } else {
         this.scene = []
+        this.total = 0
       }
     }
   },
   // 方法集合
   methods: {
-    pageChange () {
-
+    pageChange (data) {
+      this.currentPage = data
+    },
+    enter () {
+      this.currentPage = 1
+      this.getData()
     },
     async getData () {
       let params = {
-        sceneType: -1,
-        sceneInterest: 1,
-        page: this.currentPage,
-        key: this.searchTxt
+        pageSize: this.pageSize,
+        pageNum: this.currentPage,
+        searchKey: this.searchTxt
       }
       let result = await this.$http({
         method: 'post',
         data: params,
-        url: '/scene/loadScene'
+        url: '/scene/search'
       })
-      this.scene = result.data
-      console.log(this.scene)
+      let data = result.data.data
+      this.scene = data.list
+      this.total = data.total
     }
   },
   created () {
 
   },
   mounted () {
-    // this.getData()
+    document.addEventListener('click', (e) => {
+      if (this.$refs.searchcon) {
+        if (!this.$refs.searchcon.contains(e.target)) {
+          this.$bus.$emit('hideSearch', e.target)
+        }
+      }
+    })
   }
 }
 </script>

+ 2 - 2
src/page/navs/search/item/index.vue

@@ -9,7 +9,7 @@
         </vcenter>
       </div>
       <div class="title">
-        <img :src="item.homepic" alt="">
+        <img :src="item.thumb" alt="">
         <div class="title-txt">
         <vcenter>
           <div v-html="maskTitle(item.sceneName)"></div>
@@ -19,7 +19,7 @@
       </div>
       <div class="date">
         <vcenter>
-           <div>{{format(item.createTime.time)}}</div>
+           <div>{{item.createTime}}</div>
         </vcenter>
       </div>
     </div>

+ 2 - 0
src/page/navs/search/style.scss

@@ -36,12 +36,14 @@ $lHeight: 145px;
     .search-input{
       padding-left: 260px;
       display: inline-block;
+      width: 60%;
       .input{
         border-left: #646464 1px solid;
         padding-left: 30px;
         input{
           $inputHeight:40px;
           background: none;
+          width: 100%;
           border: 0;
           outline: none;
           color: #fff;

+ 2 - 2
src/page/navs/temp.vue

@@ -44,7 +44,7 @@ export default {
           this.active = false
           setTimeout(() => {
             this.showNav()
-          }, 400 + 50 * this.langNavs.setting[oldVal].length)
+          }, 50 * this.langNavs.setting[oldVal].length)
         } else {
           this.active = false
           this.showNav()
@@ -86,7 +86,7 @@ $lHeight: 145px;
     color: #b6b6b6;
     cursor: pointer;
     height: 100%;
-    transition: all .7s cubic-bezier(.77, 0, .175, 1);
+    transition: all .1s cubic-bezier(.77, 0, .175, 1);
     transform: translateX(100px);
     opacity: 0;
 

+ 108 - 17
src/page/pay/index.vue

@@ -42,19 +42,24 @@
             <span>微信支付</span>
             <img src="@/assets/images/tag-icon.png" class="t-click" alt>
           </div>
-          <div class="pay-tag" :class="{'tag-active':paytype==='paypal'}" @click="paytype='paypal'">
+          <div class="pay-tag paypal-con" :class="{'tag-active':paytype==='paypal'}" @click="paytype='paypal'">
             <img src="@/assets/images/paypal.png" class="t-icon" alt>
             <span>paypal</span>
             <img src="@/assets/images/tag-icon.png" class="t-click" alt>
+            <form id="formid" class="form-con" :action="`${$serverName}api/order/pay/paypal`" method="post">
+                <input  v-model="$route.params.orderId" type="text" name='orderId'>
+                <input  v-model="$route.params.orderType" type="text" name='orderType'>
+                <input type="submit" value="提交">
+            </form>
           </div>
         </div>
       </div>
-      <div class="bottom">
+      <div class="bottom" v-if="paytype !== 'paypal'">
         <div class="attr">应付金额:</div>
         <div class="price-detail">
           <dir class="price">¥{{response.price}}</dir>
           <div class="sao">扫码支付</div>
-          <img :src="`${$serverName}${response.src}`" alt="">
+          <img v-if="response.src" :src="`${$serverName}${response.src}`" alt="">
           <div class="dec">使用<span style="color:#ff0000">{{payZH}}</span>app扫码完成支付</div>
         </div>
       </div>
@@ -72,12 +77,23 @@ let payTypes = {
   alipay: '支付宝',
   paypal: 'paypal'
 }
+let PAYS = {
+  0: 'wechatPay',
+  1: 'alipay',
+  2: 'paypal'
+}
+let PAYSID = {
+  wechatPay: 0,
+  alipay: 1,
+  paypal: 2
+}
 export default {
   data () {
     return {
-      paytype: 'wechatPay',
       privilege: 'year',
-      response: ''
+      response: '',
+      t1: null,
+      paytype: PAYS[this.$route.params.payType]
     }
   },
   computed: {
@@ -98,24 +114,78 @@ export default {
     this.getCode()
   },
   methods: {
+    inverRequest () {
+      clearInterval(this.t1)
+      this.t1 = null
+      this.t1 = setInterval(() => {
+        this.queryOrderStatus()
+      }, 5000)
+    },
+    async queryOrderStatus () {
+      if (this.t1) {
+        let {orderSn, orderType} = this.$route.params
+        if (!orderSn) {
+          return this.$toast.show('error', '获取订单信息失败')
+        }
+
+        let params = {
+          orderSn,
+          orderType: Number(orderType),
+          payType: Number(PAYSID[this.paytype])
+        }
+        let res = await this.$http
+          .post('/user/order/queryOrderStatus', params, {
+            headers: {
+              token: this.token
+            }
+          })
+        let response = res.data
+        if (response.code === 0 && response.data) {
+          this.t1 = null
+          this.t1 && clearInterval(this.t1)
+          this.$router.replace({
+            name: 'payresult',
+            params: {
+              isSuccess: 'success'
+            }
+          })
+        }
+      }
+    },
     async getCode () {
       let {orderId, orderType} = this.$route.params
       if (!orderId || (!orderType && orderType !== 0)) {
-        return alert('获取订单信息失败')
+        return this.$toast.show('error', '获取订单信息失败')
       }
-      let params = {
-        orderId: orderId,
-        orderType: orderType
+      if (this.paytype !== 'paypal') {
+        let params = {
+          orderId: orderId,
+          orderType: Number(orderType)
+        }
+        let res = await this.$http
+          .post(`/order/pay/${this.paytype}`, params, {
+            headers: {
+              token: this.token
+            }
+          })
+        let response = res.data
+        if (response.code !== 0) {
+          return this.$toast.show('error', '获取支付二维码失败', () => {
+            this.t1 = null
+            this.t1 && clearInterval(this.t1)
+          })
+        }
+        this.response = response.data
+        this.inverRequest()
+      } else {
+        document.getElementById('formid').submit()
+        this.$toast.show('warn', '正在跳转至paypal支付链接,请稍等')
       }
-      let res = await this.$http
-        .post(`order/pay/${this.paytype}`, params, {
-          headers: {
-            token: this.token
-          }
-        })
-      this.response = res.data.data
-      console.log(this.response)
     }
+  },
+  beforeDestroy () {
+    clearInterval(this.t1)
+    this.t1 = null
   }
 }
 </script>
@@ -124,6 +194,7 @@ $theme-color: #1fe4dc;
 
 .pay-layout {
   width: 1030px;
+  min-height: 74vh;
   margin: 25px auto;
   .pay-header {
     width: 100%;
@@ -247,6 +318,26 @@ $theme-color: #1fe4dc;
             display: none;
           }
         }
+        .paypal-con{
+          position: relative;
+          .form-con{
+            opacity: 0;
+            input[type='text']{
+              width: 1px;
+              height: 1px;
+              position: absolute;
+              top: 0;
+              left: 0;
+            }
+             input[type='submit']{
+               width: 100%;
+               position: absolute;
+               top: 0;
+               left: 0;
+               height: 100%;
+             }
+          }
+        }
         .tag-active {
           border: 1px solid $theme-color;
           span {

+ 125 - 0
src/page/payresult/index.vue

@@ -0,0 +1,125 @@
+<template>
+  <div class="pay-layout">
+    <div class="pay-header">
+      <div class="h-left">
+        <img src="@/assets/images/logo-black.png" alt>
+        <span class="h-line"></span>
+        <span>支付中心</span>
+      </div>
+      <div class="h-right">当前账号:{{info.userName}}</div>
+    </div>
+    <div class="pay-con">
+      <div class="pay-result">
+        <img :src="result==='success'?require('@/assets/images/paysuccess.png'):require('@/assets/images/payfail.png')" alt>
+        <div class="pay-txt">
+          <div class="main-title" :style="{color:result==='success'?'#13d533':'#ea0b0b'}">{{result==='success'?'恭喜您,支付成功!':'支付失败!请重新支付'}}</div>
+          <div class="sub-title">{{result==='success'?'我们将尽快安排为您发货!':'请检查网络情况后重试'}}</div>
+        </div>
+      </div>
+    </div>
+    <div class="pay-bottom">
+       ©2019 4dkankan移动开放平台
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+
+export default {
+  data () {
+    return {
+      paytype: 'wechatPay',
+      privilege: 'year',
+      response: '',
+      result: this.$route.params.isSuccess || 'success'
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      info: state => state.user.info
+    })
+  },
+  mounted () {
+
+  },
+  methods: {
+
+  }
+}
+</script>
+<style lang="scss" scoped>
+$theme-color: #1fe4dc;
+
+.pay-layout {
+  width: 1030px;
+  min-height: 74vh;
+  margin: 25px auto;
+  .pay-header {
+    width: 100%;
+    margin-bottom: 50px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .h-left {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .h-line {
+        width: 1px;
+        height: 20px;
+        background: #000;
+        margin: 0 10px;
+        display: inline-block;
+      }
+      span {
+        font-size: 20px;
+        color: #2d2d2d;
+      }
+    }
+    .h-right {
+      font-size: 14px;
+      color: #2d2d2d;
+    }
+  }
+  .pay-con {
+    background: #f4f4f4;
+    padding: 40px;
+    position: relative;
+    min-height: 50vh;
+    width: 100%;
+   .pay-result{
+     display: flex;
+     align-items: flex-end;
+     top: 50%;
+     left: 47%;
+     transform: translate(-50%,-50%);
+     position: absolute;
+     .pay-txt{
+       text-align: center;
+      .main-title{
+        font-size: 30px;
+        margin-bottom: 10px;
+        color: #13d533;
+      }
+      .sub-title{
+        font-size: 14px;
+        color: #2d2d2d;
+      }
+     }
+     img{
+       width: 120px;
+       margin-right: 40px;
+       flex-shrink: 0;
+     }
+   }
+  }
+  .pay-bottom{
+    color: #969696;
+    font-size: 12px;
+    text-align: center;
+    margin-top: 20px;
+  }
+}
+</style>

+ 546 - 0
src/page/privilege/index.vue

@@ -0,0 +1,546 @@
+<template>
+  <div class="privilege-layout">
+    <div class="p-container">
+      <div class="p-top">
+        <div class="p-title">
+          <div class="b-title">记录当下世界,开启未来模式</div>
+          <div class="b-label">从个人到企业,我们全心实现空间数字化,满足不同场景的展示需求,为你和你的团队创造更多价值</div>
+        </div>
+        <div class="p-table">
+          <div class="p-rtitle">
+            <div v-for="(item,i) in pTitle" :key="i">{{item}}</div>
+          </div>
+          <div class="p-item">
+            <div :class="{recomment:item.recomment}" v-for="(item,i) in privilege" :key="i">
+              <img class="icon" v-if="item.recomment" src="@/assets/images/good.png" alt>
+              <div class="item-name">
+                <p class="type">{{item.name.title}}</p>
+                <p :class="item.name.price.class" v-html="item.name.price.name"></p>
+                <p :class="item.name.authority.class" v-html="item.name.authority.name"></p>
+              </div>
+              <div>
+                <span v-if="!item.identity.img" v-html="item.identity.url"></span>
+                <div v-else class="vip-icon">
+                  <img
+                    :class="{buss:item.identity.url.length>1}"
+                    :src="sub"
+                    v-for="(sub,index) in item.identity.url"
+                    :key="index"
+                    alt
+                  >
+                </div>
+              </div>
+              <div>
+                <span v-html="item.count"></span>
+              </div>
+              <div>
+                <span v-html="item.bCapacity"></span>
+              </div>
+              <div>
+                <span v-html="item.xCapacity"></span>
+              </div>
+              <div>
+                <span v-html="item.per"></span>
+              </div>
+              <div>
+                <span v-html="item.basic"></span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.loading.icon?item.loading.name:'']"
+                >{{!item.loading.icon?item.loading.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.updateModel.icon?item.updateModel.name:'']"
+                >{{!item.updateModel.icon?item.updateModel.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.measure.icon?item.measure.name:'']"
+                >{{!item.measure.icon?item.measure.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.video.icon?item.video.name:'']"
+                >{{!item.video.icon?item.video.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.coordination.icon?item.coordination.name:'']"
+                >{{!item.coordination.icon?item.coordination.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.customer.icon?item.customer.name:'']"
+                >{{!item.customer.icon?item.customer.name:''}}</span>
+              </div>
+              <div>
+                <span
+                  class="iconfont"
+                  :class="[item.scene.icon?item.scene.name:'']"
+                >{{!item.scene.icon?item.scene.name:''}}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="qa">
+        <div class="qa-item" v-for="(item,i) in qa" :key="i">
+          <div class="title">
+            <img src="@/assets/images/Q.png" alt>
+            <span>{{item.q}}</span>
+          </div>
+          <div class="dec">
+            <span>{{item.a}}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    let pTitle = [
+      '身份标识',
+      '场景数量',
+      '基础容量',
+      '限期容量',
+      '扩容单价',
+      '基础功能',
+      '加载界面替换',
+      '修改模型',
+      '墙面测距',
+      '交互式视频',
+      '协同功能',
+      '客服支持',
+      '场景数量'
+    ]
+    let privilege = [
+      {
+        name: {
+          title: '普通会员',
+          price: {
+            name: '免费',
+            class: 'price'
+          },
+          authority: {
+            class: 'free',
+            name: '可长期免费使用'
+          }
+        },
+        identity: {
+          img: false,
+          url: '无'
+        },
+        count: '不限',
+        bCapacity: '3G<br/>(免费体验容量)',
+        xCapacity: '无',
+        per: '1G=¥69/年<br/>1T=¥639/年',
+        basic: '8项',
+        loading: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        updateModel: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        measure: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        video: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        coordination: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        customer: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        scene: {
+          icon: true,
+          name: 'icon-vip_false'
+        }
+      },
+      {
+        name: {
+          title: '专业会员',
+          price: {
+            name: `买设备就<span style='font-size:20px;margin-left:4px;'>送</span>`,
+            class: 'give'
+          },
+          authority: {
+            class: 'btns default',
+            name: '再次购买'
+          }
+        },
+        identity: {
+          img: true,
+          url: [require('@/assets/images/nianhuiyuan-03.png')]
+        },
+        count: '不限',
+        bCapacity: '30G',
+        xCapacity: '无',
+        per: '1G=¥59/年<br/>1T=¥539/年',
+        basic: '18项',
+        loading: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        updateModel: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        measure: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        video: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        coordination: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        customer: {
+          icon: false,
+          name: '5X8小时在线服务'
+        },
+        scene: {
+          icon: false,
+          name: '快速队列'
+        }
+      },
+      {
+        recomment: true,
+        name: {
+          title: '商业会员',
+          price: {
+            name: `低至<span style='font-size:20px;margin:0 5px;'>¥199</span>/月`,
+            class: 'give'
+          },
+          authority: {
+            class: 'btns primary',
+            name: '立即开通'
+          }
+        },
+        identity: {
+          img: true,
+          url: [
+            require('@/assets/images/nianhuiyuan-04.png'),
+            require('@/assets/images/nianhuiyuan-05.png')
+          ]
+        },
+        count: '不限',
+        bCapacity: '附赠限期容量',
+        xCapacity: '+300M/月<br/>+6G/年',
+        per: '1G=¥49/年<br/>1T=¥¥439/年',
+        basic: '18项',
+        loading: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        updateModel: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        measure: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        video: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        coordination: {
+          icon: true,
+          name: 'icon-vip_false'
+        },
+        customer: {
+          icon: false,
+          name: '5X8小时在线服务'
+        },
+        scene: {
+          icon: false,
+          name: '高速队列'
+        }
+      },
+      {
+        name: {
+          title: '企业套餐',
+          price: {
+            name: `量身定制的贴合服务`,
+            class: 'price'
+          },
+          authority: {
+            class: 'btns default',
+            name: '提供咨询'
+          }
+        },
+        identity: {
+          img: true,
+          url: [require('@/assets/images/nianhuiyuan-02.png')]
+        },
+        count: '不限',
+        bCapacity: '至少200G',
+        xCapacity: '至少+50G/年',
+        per: '1G=¥39/年<br/>1T=¥339/年',
+        basic: '18项',
+        loading: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        updateModel: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        measure: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        video: {
+          icon: true,
+          name: 'icon-vip_true'
+        },
+        coordination: {
+          icon: false,
+          name: '7项'
+        },
+        customer: {
+          icon: false,
+          name: '专属客户经理'
+        },
+        scene: {
+          icon: false,
+          name: '优先通道'
+        }
+      }
+    ]
+    let qa = [
+      {
+        q: '什么是专业会员?',
+        a:
+          '专业会员即为购买或赋予设备的会员,针对专业会员,我们专门附赠提供包含18项实用专业的后台功能,会员可根据这些功能编辑场景,打造朋友圈最新颖的分享方式。'
+      },
+      {
+        q: '专业会员和商业会员的区别是什么?',
+        a:
+          '商业会员是在专业会员基础上的增值服务,相比专业会员拥有更多的容量空间、更便宜的扩容和下载价格,商业会员也享有最新的功能特权机会。'
+      },
+      {
+        q: '专业会员如何升级成商业会员?',
+        a:
+          '如果您已经是专业会员,只需选择商业月会员或商业年会员购买,即可升级成为商业会员。'
+      },
+      {
+        q: '普通会员可以直接升级成商业会员吗?',
+        a:
+          '可以,购买设备的基础上再选购商业月会员或商业年会员购买,即可直接升级成为商业会员。'
+      },
+      {
+        q: '商业会员到期以后还能继续使用吗?',
+        a:
+          '当您购买的商业会员到期后,您可以选择续费,继续正常使用相应的会员功能。如果您暂时不希望付费,您将会自动降为专业会员,并且将无法使用商业会员的功能。'
+      },
+      {
+        q: '我购买商业会员之后还可以退款吗?',
+        a:
+          '不可以,因为购买商业会员之后,相应会员权益都会即刻开放,所以不接受中途退款,敬请谅解。'
+      }
+    ]
+
+    return {
+      privilege,
+      pTitle,
+      qa
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+$border-color: #e7e7e7;
+$theme-color: #1fe4dc;
+.free {
+  line-height: 35px;
+}
+.btns {
+  width: 120px;
+  text-align: center;
+  margin: 0 auto;
+  border: 2px solid $theme-color;
+  line-height: 35px;
+  border-radius: 4px;
+  font-size: 14px;
+  cursor: pointer;
+}
+.default {
+  color: $theme-color;
+}
+
+.primary {
+  background: $theme-color;
+  color: #fff;
+}
+
+.privilege-layout {
+  color: #2d2d2d;
+  margin: 40px;
+  .p-container {
+    margin: 0 auto;
+    width: 1300px;
+    .p-top{
+      text-align: center;
+      .p-title{
+        margin-bottom: 40px;
+        .p-title{
+
+        }
+        .p-label{
+
+        }
+      }
+      .p-table {
+        display: flex;
+        justify-content: center;
+        position: relative;
+        left: -60px;
+        .p-rtitle {
+          width: 120px;
+          margin-top: 180px;
+          & > div {
+            font-size: 16px;
+            color: #969696;
+            line-height: 60px;
+            height: 60px;
+            text-align: center;
+          }
+        }
+
+        .p-item {
+          border: 1px solid $border-color;
+          .recomment {
+            background: #f4f4f4;
+            position: relative;
+            .icon {
+              position: absolute;
+              top: 0;
+              left: 0;
+              width: 40px;
+            }
+          }
+          & > div {
+            width: 180px;
+            text-align: center;
+            display: inline-block;
+            .item-name {
+              height: 180px;
+              padding: 30px 0;
+              line-height: 1.5;
+              .type {
+                font-size: 24px;
+                font-weight: bold;
+                color: #2d2d2d;
+              }
+              .price {
+                color: #969696;
+                margin: 16px 0;
+                font-weight: bold;
+              }
+              .give {
+                color: $theme-color;
+                font-weight: bold;
+                margin: 13px 0;
+                font-size: 16px;
+              }
+            }
+            & > div {
+              border-right: 1px solid $border-color;
+              border-bottom: 1px solid $border-color;
+              height: 60px;
+              line-height: 60px;
+              span {
+                display: inline-block;
+                vertical-align: middle;
+                line-height: 1.2;
+              }
+              .vip-icon {
+                display: inline-block;
+                vertical-align: middle;
+                img {
+                  width: 30px;
+                  display: block;
+                }
+                .buss {
+                  width: 50px;
+                }
+              }
+              .icon-vip_true {
+                color: $theme-color;
+              }
+              .icon-vip_false {
+                color: #2d2d2d;
+              }
+            }
+            &:last-of-type {
+              & > div {
+                border-right: none;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .qa {
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    margin: 80px 0 0 0;
+    .qa-item {
+      width: 38%;
+      .title {
+        img {
+          width: 25px;
+          margin-right: 2px;
+          vertical-align: middle;
+        }
+        span {
+          font-size: 24px;
+          vertical-align: middle;
+          font-weight: bold;
+        }
+      }
+      .dec {
+        position: relative;
+        height: 115px;
+        width: 100%;
+        span {
+          position: absolute;
+          top: 50%;
+          left: 0;
+          transform: translateY(-50%);
+          font-size: 14px;
+          color: #95979b;
+          vertical-align: middle;
+          display: inline-block;
+        }
+      }
+    }
+  }
+}
+</style>

+ 7 - 3
src/page/purchase/index.vue

@@ -146,13 +146,17 @@ export default {
     handleSpinner (data) {
       this.count = data
     },
-    addcart () {
+    async addcart () {
+      if (!this.token) {
+        return this.$bus.$emit('showAside')
+      }
       let params = {
         goodsId: 4,
         goodsCount: this.count,
         skuSn: 'U15609161635760015'
       }
-      this.$store.dispatch('addCart', params)
+      await this.$store.dispatch('addCart', params)
+      this.$toast.show('success', '商品加入购物车成功')
     },
     pay () {
       let params = {
@@ -173,8 +177,8 @@ export default {
       let tag = getPosition(this.$refs[href]).y + 20
       let speed = Math.ceil(tag / 40)
       this.interval = setInterval(() => {
+        window.scrollTo(0, inter)
         inter += speed
-        window.scrollTo(0, Math.min(inter, tag))
         if ((window.scrollY || window.pageYOffset) >= tag) {
           clearInterval(this.interval)
         }

+ 1 - 1
src/page/purchase/style.scss

@@ -48,7 +48,7 @@
   .layout{
     width: 540px;
     margin-top: 20px;
-    margin-left: 300px;
+    margin-left: 16%;
     display: inline-block;
     vertical-align: top;
     .pro-logo{

+ 196 - 0
src/page/purchasetow/index.vue

@@ -0,0 +1,196 @@
+<template>
+  <div class="purchase-layout">
+    <div class="plate01">
+      <div class="p1-banner">
+        <span @click="$router.push({name:'eight'})">{{langPurchase.top1}}</span>
+        <span @click="scrollTo('jsgg')">{{langPurchase.top2}}</span>
+      </div>
+      <img
+        class="product-img"
+        :style="{marginLeft:(split - 170)+ 'px'}"
+        src="@/assets/images/t_product.png"
+        alt
+      >
+      <div class="layout">
+        <img class="pro-logo" src="@/assets/images/lite-logo.png" alt="">
+        <p class="sub b-label" v-html="langPurchase.dec"></p>
+        <p class="price">
+          {{langPurchase.price}}
+          <span>{{langPurchase.yushou}}</span>
+        </p>
+        <template>
+          <p class="title first-title">{{langPurchase.color.key}}</p>
+          <div class="detail-box">
+            <i class="iconfont icon-yuandian"></i>
+            {{langPurchase.color.val}}
+          </div>
+          <p class="title">{{langPurchase.service.key}}</p>
+          <div class="detail-box">
+            <ul>
+              <li v-for="(item, i) in langPurchase.service.val" :key="i">{{item}}</li>
+            </ul>
+          </div>
+          <p class="title">{{langPurchase.gift.key}}</p>
+          <div class="detail-box zhijia">
+            <img src="@/assets/images/zhijia.png" alt>
+            <span>{{langPurchase.gift.val}}</span>
+          </div>
+        </template>
+        <p class="title">{{langPurchase.count.key}}</p>
+        <spinner @count="handleSpinner"/>
+        <div>
+          <div class="btns">
+            <div class="button add-cart" @click="addcart">
+              <vcenter>
+                <!-- <img src="@/assets/images/product_icon_arrow_l.png" alt> -->
+                <span>加入购物车</span>
+              </vcenter>
+            </div>
+            <div class="button"  @click="pay">
+              <vcenter>
+                <!-- <img src="@/assets/images/product_icon_arrow.png" alt> -->
+                <span>{{langPurchase.buy}}</span>
+              </vcenter>
+            </div>
+          </div>
+          <div class="btn-dec">{{langPurchase.tiaokuan}}</div>
+        </div>
+      </div>
+    </div>
+    <div class="plate02" ref="jsgg" :style="{marginLeft:split + 'px'}">
+      <div class="b-title">{{langPurchase.guige.name}}</div>
+      <div class="params-con">
+        <div class="params-item" v-for="(item,index) in langPurchase.guige.arr" :key="index">
+          <div class="p-l">{{item.name}}</div>
+          <div class="p-r">
+            <div v-html="sub" v-for="(sub,i) in item.val" :key="i"></div>
+          </div>
+        </div>
+      </div>
+      <div class="sub">
+        <p>{{langPurchase.guige.dec}}</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import spinner from '@/components/spinner'
+import vcenter from '@/components/vcenter'
+import { getPosition } from '@/util'
+
+export default {
+  components: {
+    spinner,
+    vcenter
+  },
+  computed: {
+    ...mapState({
+      split: state => state.ui.navDivision,
+      isLogin: state => state.user.name,
+      langPurchase: state => state.language.home.purchasetow,
+      language: state => state.language.current,
+      token: state => state.user.token,
+      cart: state => JSON.parse(state.user.cart)
+    })
+  },
+  data () {
+    let detail = {
+      left: [
+        '数据永久存储',
+        '高速上传计算队列',
+        '场景分享、热点编辑、隐私加密'
+      ],
+      right: ['多种个性化功能', '附送30G终身容量']
+    }
+    let guige = [
+      {
+        name: '容量和内存',
+        val: ['LPDDR4X双通道', '6G内存', 'UFS 2.1', '64GB 机身存储']
+      },
+      {
+        name: '机身尺寸和重量',
+        val: ['高度 = 153.3m', '宽度 = 74.5mm', '厚度 = 7.9mm', '重量 = 170g']
+      },
+      {
+        name: '处理器平台',
+        val: [
+          'Qualcomm® 骁龙™ 845 处理器',
+          '10nm 先进制程',
+          '单核主频可达 2.8GHz',
+          'Adreno™ 630 图形处理器,主频可达 700MHz',
+          '配备人工智能引擎(AI Engine)'
+        ]
+      },
+      {
+        name: '网络',
+        val: ['支持 VoLTE 高质量宽带', '支持三载波聚', '支持 LTE B41 4x4 MIMO']
+      },
+      {
+        name: '屏幕',
+        val: [
+          '6.17 英寸 In-Cell 全高清显示屏',
+          '2242 x 1080 分辨率,403 ppi',
+          '康宁®第三代大猩猩®玻璃'
+        ]
+      }
+    ]
+    return {
+      detail,
+      guige,
+      count: 1
+    }
+  },
+  methods: {
+    handleSpinner (data) {
+      this.count = data
+    },
+    async addcart () {
+      if (!this.token) {
+        return this.$bus.$emit('showAside')
+      }
+      let params = {
+        goodsId: 1,
+        goodsCount: this.count,
+        skuSn: 'U15609161635760014'
+      }
+      await this.$store.dispatch('addCart', params)
+      this.$toast.show('success', '商品加入购物车成功')
+    },
+    pay () {
+      let params = {
+        type: 'detail',
+        sku: [{
+          goodsId: 1,
+          goodsCount: this.count,
+          price: 3999,
+          skuSn: 'U15609161635760014'
+        }],
+        fromList: false
+      }
+      this.$bus.$emit('showAside', params)
+    },
+    scrollTo (href) {
+      this.interval = null
+      let inter = 0
+      let tag = getPosition(this.$refs[href]).y + 20
+      let speed = Math.ceil(tag / 40)
+      this.interval = setInterval(() => {
+        inter += speed
+        window.scrollTo(0, inter)
+        if ((window.scrollY || window.pageYOffset) >= tag) {
+          clearInterval(this.interval)
+        }
+      })
+    }
+  },
+  beforeDestroy () {
+    clearInterval(this.interval)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+</style>

+ 231 - 0
src/page/purchasetow/style.scss

@@ -0,0 +1,231 @@
+.purchase-layout {
+  overflow: hidden;
+}
+
+.btns{
+  font-size: 0;
+}
+.btns .button{
+  cursor: pointer;
+  width: 250px;
+  height: 50px;
+  padding-top: 0;
+  padding-bottom: 0;
+  margin-top: 33px;
+  line-height: 50px;
+  color: #414141;
+  text-align: center;
+  font-size: 14px;
+  img{
+    vertical-align: middle;
+  }
+  span{
+    vertical-align: middle;
+    padding-left: 2px;
+  }
+}
+
+.plate01{
+  background: url("~@/assets/images/purchase_bg.png") #f8f9fc top center no-repeat;
+  padding: 0 0 155px;
+  .p1-banner{
+    background: #fff;
+    height: 65px;
+    text-align: right;
+    padding-right: 120px;
+    span{
+      display: inline-block;
+      margin-left: 50px;
+      padding-top: 40px;
+      cursor: pointer;
+      font-size: 16px;
+    }
+  }
+  .product-img{
+    width: 170px;
+    margin-top: 75px;
+  }
+  .layout{
+    width: 540px;
+    margin-top: 20px;
+    margin-left: 16%;
+    display: inline-block;
+    vertical-align: top;
+    .pro-logo{
+      margin-bottom: 8px;
+    }
+    .price{
+      margin-top: 20px;
+      font-size: 28px;
+      line-height: 1;
+      color: rgba(0,0,0,.7);
+      font-weight: 700;
+      border-bottom: 1px #e2e2e2 solid;
+      padding-bottom: 20px;
+      span{
+        font-size: 14px;
+        color: #1fe4dc;
+        font-weight: bold;
+      }
+    }
+    .title{
+      font-size: 14px;
+      color: rgba(0,0,0,.7);
+      line-height: 18px;
+      font-weight: 600;
+      margin:6px 0 8px;
+    }
+    .first-title{
+      margin-top: 20px;
+    }
+    .detail-box{
+      display: inline-block;
+      border: 1px solid #70eee9;
+      background: #f8fefe;
+      color: rgba(0,0,0,.45);
+      padding: 5px 63px;
+      line-height: 1.5;
+      width: 344px;
+      box-sizing: border-box;
+      &:first-of-type{
+        padding: 12px 0;
+        text-align: center;
+        height: auto;
+        box-sizing: border-box;
+        font-size: 16px;
+        color: #000;
+      }
+      .icon-yuandian::before{
+        margin-right: 6px;
+        font-size: 16px;
+      }
+      .line{
+        display: inline-block;
+        width: 1px;
+        height: 56px;
+        background: #e2e2e2;
+        margin: 5px 39px 0 40px;
+      }
+      ul{
+        display: inline-block;
+        vertical-align: top;
+        &:last-child{
+          float: right;
+          margin-left: 20px;
+        }
+        li{
+          font-size: 14px;
+          line-height: 1.5;
+          position: relative;
+          &::before{
+            content: '';
+            width: 3px;
+            height: 3px;
+            border-radius: 50%;
+            display: inline-block;
+            position: absolute;
+            left: -15px;
+            top: 50%;
+            transform: translateY(-50%);
+            background-color: rgba(0,0,0,.45);
+          }
+        }
+      }
+    }
+    .zhijia{
+      padding: 10px 0;
+      text-align: center;
+      img{
+        vertical-align: middle;
+        margin-right: 20px;
+        height: 60px;
+      }
+      span{
+        vertical-align: middle;
+        font-size: 14px;
+      }
+    }
+    .btns {
+      img{
+        width: 24px;
+      }
+    }
+    .btns .add-cart{
+      background: #e7e7e7;
+      margin-right: 40px;
+    }
+    .btn-dec{
+      margin-top: 12px;
+      font-size: 14px;
+      color: rgba(0,0,0,.7);
+      font-weight: bolder;
+      line-height: 16px;
+    }
+  }
+}
+
+.plate02{
+  width: 845px;
+  margin-left: 600px;
+  padding: 155px 0;
+  text-align: center;
+  .b-title{
+    font-weight: 700;
+    font-size: 28px;
+    color: rgba(0, 0, 0, 0.7);
+    line-height: 44px;
+    max-width: 300px;
+    margin-left: 209px;
+  }
+  .params-con{
+    width: 100%;
+    margin: 28px 0 12px;
+    .params-item{
+      width: 100%;
+      border-top: 1px solid #e7e7e7;
+      text-align: left;
+      padding: 28px 0;
+      &:last-of-type{
+       border-bottom: 1px solid #e7e7e7;
+      }
+      &>div{
+        display: inline-block;
+        text-align: left;
+      }
+      .p-l{
+        width: 300px;
+        height: 100%;
+        text-align: left;
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.7);
+        line-height: 1.5;
+        font-weight: 600;
+        margin: 0;
+        vertical-align: top;
+      }
+      .p-r{
+        width: calc(100% - 320px);
+        height: 100%;
+        text-align: left;
+        div{
+          line-height: 1.5;
+          font-size: 14px;
+          color: rgba(0, 0, 0, 0.45);
+          margin-right: 50px;
+        }
+      }
+    }
+  }
+  .sub{
+    text-indent: 28px;
+    text-align: left;
+    margin-top: 12px;
+    font-size: 14px;
+    color: rgba(0, 0, 0, 0.7);
+    font-weight: bolder;
+    line-height: 16px;
+    p:first-of-type{
+      text-indent: 0px;
+    }
+  }
+}

+ 79 - 30
src/router/index.js

@@ -1,6 +1,5 @@
 import Vue from 'vue'
 import Router from 'vue-router'
-import information from './information'
 import store from '../store'
 Vue.use(Router)
 
@@ -9,60 +8,112 @@ let router = new Router({
     {
       path: '/',
       name: 'home',
-      component: () => import('@/page/home2')
+      component: resolve => require(['@/page/home2'], resolve)
     },
     {
       path: '/videos',
       name: 'videos',
-      component: () => import('@/page/videos')
+      component: resolve => require(['@/page/videos'], resolve)
     },
     {
-      path: '/pay/:orderId/:orderType',
+      path: '/capacity',
+      name: 'capacity',
+      component: resolve => require(['@/page/capacity'], resolve)
+    },
+    {
+      path: '/pay/:orderId/:orderType/:orderSn/:payType',
       name: 'pay',
-      component: () => import('@/page/pay')
+      component: resolve => require(['@/page/pay'], resolve)
+    },
+    {
+      path: '/payresult/:isSuccess',
+      name: 'payresult',
+      component: resolve => require(['@/page/payresult'], resolve)
     },
     {
       path: '/product',
       name: 'product',
-      component: () => import('@/page/product')
+      component: resolve => require(['@/page/product'], resolve)
     },
     {
       path: '/binocular',
       name: 'binocular',
-      component: () => import('@/page/binocular')
+      component: resolve => require(['@/page/binocular'], resolve)
     },
     {
       path: '/about',
       name: 'about',
-      component: () => import('@/page/about')
+      component: resolve => require(['@/page/about'], resolve)
     },
     {
       path: '/location',
       name: 'location',
-      component: () => import('@/page/location')
-    },
-    {
-      path: '/m-about',
-      name: 'm-about',
-      component: () => import('@/page/about/mobile.vue')
+      component: resolve => require(['@/page/location'], resolve)
     },
     {
       path: '/eight',
       name: 'eight',
-      component: () => import('@/page/eight')
+      component: resolve => require(['@/page/eight'], resolve)
     },
     {
       path: '/purchase',
       name: 'purchase',
-      component: () => import('@/page/purchase')
+      component: resolve => require(['@/page/purchase'], resolve)
     },
     {
-      path: '/manage',
+      path: '/purchasetow',
+      name: 'purchasetow',
+      component: resolve => require(['@/page/purchasetow'], resolve)
+    },
+    {
+      path: '/privilege',
+      name: 'privilege',
+      component: resolve => require(['@/page/privilege'], resolve)
+    },
+    {
+      path: '/',
       name: 'manage',
-      component: () => import('@/page/manage'),
-      meta: {
-        requireAuth: true
-      }
+      component: resolve => require(['@/page/manage'], resolve),
+      children: [
+        {
+          name: 'information',
+          path: '/information',
+          component: resolve => require(['@/page/manage/temp/information'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'scene',
+          path: '/scene',
+          component: resolve => require(['@/page/manage/temp/scene'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'order',
+          path: '/order',
+          component: resolve => require(['@/page/manage/temp/order'], resolve),
+          meta: {requireAuth: true}
+
+        },
+        {
+          name: 'consumption',
+          path: '/consumption',
+          component: resolve => require(['@/page/manage/temp/consumption'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'device',
+          path: '/device',
+          component: resolve => require(['@/page/manage/temp/device'], resolve),
+          meta: {requireAuth: true}
+        },
+        {
+          name: 'change',
+          path: '/change',
+          component: resolve => require(['@/page/manage/temp/change'], resolve),
+          meta: {requireAuth: true}
+        }
+      ]
+
     },
     // {
     //   path: '/service/down',
@@ -72,12 +123,12 @@ let router = new Router({
     {
       path: '/service/overview',
       name: 'service_overview',
-      component: () => import('@/page/service/overview')
+      component: resolve => require(['@/page/service/overview'], resolve)
     },
     {
       path: '/cases/overview',
       name: 'case_overview',
-      component: () => import('@/page/cases/overview')
+      component: resolve => require(['@/page/cases/overview'], resolve)
     },
     // {
     //   path: '/service/:id',
@@ -91,22 +142,21 @@ let router = new Router({
         {
           path: ':id/:active',
           name: 'service_list',
-          component: () => import('@/page/service/temp')
+          component: resolve => require(['@/page/service/temp'], resolve)
         }
       ],
-      component: () => import('@/page/service')
+      component: resolve => require(['@/page/service'], resolve)
     },
     {
       path: '/cases/:id',
       name: 'cases',
-      component: () => import('@/page/cases')
+      component: resolve => require(['@/page/cases'], resolve)
     },
     {
       path: '/cases/app',
       name: 'cases_app',
-      component: () => import('@/page/cases/app')
-    },
-    information
+      component: resolve => require(['@/page/cases/app'], resolve)
+    }
   ],
   scrollBehavior (to, from, savedPosition) {
     if (to.hash === '') {
@@ -123,7 +173,6 @@ router.beforeEach((to, from, next) => {
     if (token) {
       next()
     } else {
-      alert('请登录')
       next({
         name: 'home'
       })

+ 0 - 5
src/router/information.js

@@ -12,10 +12,5 @@ export default {
     name: 'information_news_detil',
     component: () => import('@/page/information/news/details')
   }
-  // , {
-  //   path: 'media',
-  //   name: 'information_media',
-  //   component: () => import('@/page/information/media')
-  // }
   ]
 }

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

@@ -37,44 +37,44 @@ export default{
       {
         year: '2014年',
         txt: [
-          '10月 四维时代创立,成员在人工智能三维数字化重建及数字化虚拟展示技术方面具有世界领先的科研实力。',
-          '12月 建模精度达微米级的一种基于光栅扫描的物体数字化三维重建装置,获专利授权。'
+          '<span>10月</span>四维时代创立,成员在人工智能三维数字化重建及数字化虚拟展示技术方面具有世界领先的科研实力。',
+          '<span>12月</span>建模精度达微米级的一种基于光栅扫描的物体数字化三维重建装置,获专利授权。'
         ]
       },
       {
         year: '2015年',
         txt: [
-          '8月 “高精度一键式三维数字化重建及其展示”获“中国创翼”青年创业创新大赛三等奖。',
-          '10月 四维时代CEO作为全国双创代表获得李克强总理接见,并向总理汇报工作。',
-          '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;相继成为故宫博物院、广东省博物馆等文物保护机构的合作伙伴。'
+          '<span>8月</span>“高精度一键式三维数字化重建及其展示”获“中国创翼”青年创业创新大赛三等奖。',
+          '<span>10月</span>四维时代CEO作为全国双创代表获得李克强总理接见,并向总理汇报工作。',
+          '<span></span>相继成为故宫博物院、广东省博物馆等文物保护机构的合作伙伴。'
         ]
       },
       {
         year: '2016年',
         txt: [
-          '5月 为中国十大考古发现之一—南昌汉代海昏侯国遗址博物馆打造的线上数字博物馆上线。'
+          '<span>5月</span>为中国十大考古发现之一—南昌汉代海昏侯国遗址博物馆打造的线上数字博物馆上线。'
         ]
       },
       {
         year: '2017年',
         txt: [
-          '4月 成为阿斯塔纳世博会中国馆虚拟现实技术唯一指定供应商。',
-          '6月 在中德两国总理见证下与德国人工智能研究中心签约《中德人工智能研究院项目》,为中德科技交流建立有力纽带。'
+          '<span>4月</span>成为阿斯塔纳世博会中国馆虚拟现实技术唯一指定供应商。',
+          '<span>6月</span>在中德两国总理见证下与德国人工智能研究中心签约《中德人工智能研究院项目》,为中德科技交流建立有力纽带。'
         ]
       },
       {
         year: '2018年',
         txt: [
-          '5月 推出全球首款消费级3D相机四维看看,10分钟即可复刻100平米空间。',
-          '11月 中国高科技产业化研究会授予四维看看“科学技术成果”称号。',
-          '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;中国国际高新技术成果交易会授予四维看看“优秀产品奖”。'
+          '<span>5月</span>推出全球首款消费级3D相机四维看看,10分钟即可复刻100平米空间。',
+          '<span>11月</span>中国高科技产业化研究会授予四维看看“科学技术成果”称号。',
+          '<span></span>中国国际高新技术成果交易会授予四维看看“优秀产品奖”。'
         ]
       },
       {
         year: '2019年',
         txt: [
-          '4月 为黑提恩斯-德国国立陶瓷博物馆展馆及馆藏进行三维数字化重建,并开发数字博物馆App,该案例作为一带一路文化输出的杰出代表入选第二届一带一路峰会案例集。',
-          '5月 四维看看Pro在德国柏林人工智能大会上亮相。'
+          '<span>4月</span>为黑提恩斯-德国国立陶瓷博物馆展馆及馆藏进行三维数字化重建,并开发数字博物馆App,该案例作为一带一路文化输出的杰出代表入选第二届一带一路峰会案例集。',
+          '<span>5月</span>四维看看Pro在德国柏林人工智能大会上亮相。'
         ]
       }
     ]

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

@@ -93,7 +93,7 @@ export default{
       image: baseUrl + 'images/phone_6.jpg',
       icon: baseUrl + 'images/phone_icon_6.png',
       text: '融信' },
-    {url: 'https://www.cgaii.com/museum/cultural/index.html',
+    {url: 'https://www.4dkankan.com/showPC.html?m=X99yIvTq',
       image: baseUrl + 'images/phone_1.jpg',
       icon: baseUrl + 'images/phone_icon_1.png',
       text: '德国陶瓷博物馆' },

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

@@ -0,0 +1,66 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '10分钟复刻空间,时间仅需传统设备的1/20,4K高清画质,实现沉浸式3D实景空间漫游',
+  yushou: '【新品预售】',
+  price: 'RMB 3,999',
+  buy: '立即购买',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: '容量和内存',
+        val: ['LPDDR4X双通道', '6G内存', 'UFS 2.1', '64GB 机身存储']
+      },
+      {
+        name: '机身尺寸和重量',
+        val: ['高度 = 153.3m', '宽度 = 74.5mm', '厚度 = 7.9mm', '重量 = 170g']
+      },
+      {
+        name: '处理器平台',
+        val: [
+          'Qualcomm® 骁龙™ 845 处理器',
+          '10nm 先进制程',
+          '单核主频可达 2.8GHz',
+          'Adreno™ 630 图形处理器,主频可达 700MHz',
+          '配备人工智能引擎(AI Engine)'
+        ]
+      },
+      {
+        name: '网络',
+        val: ['支持 VoLTE 高质量宽带', '支持三载波聚', '支持 LTE B41 4x4 MIMO']
+      },
+      {
+        name: '屏幕',
+        val: [
+          '6.17 英寸 In-Cell 全高清显示屏',
+          '2242 x 1080 分辨率,403 ppi',
+          '康宁®第三代大猩猩®玻璃'
+        ]
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密',
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  }
+}

+ 13 - 13
src/store/language/en/about.js

@@ -39,44 +39,44 @@ export default{
       {
         year: '2014',
         txt: [
-          '2014.10 4DAGE was founded in October 2014. The founder and senior management are returnees with European doctor\'s or master\'s degrees. They are world leaders in scientific research on AI digital 3D reconstruction and digital virtual display technology.',
-          '2014.12 4DAGE was granted a patent for a raster scanning digital 3D object reconstruction device with micron-level modeling accuracy.'
+          '<i>2014.10</i>4DAGE was founded in October 2014. The founder and senior management are returnees with European doctor\'s or master\'s degrees. They are world leaders in scientific research on AI digital 3D reconstruction and digital virtual display technology.',
+          '<i>2014.12</i>4DAGE was granted a patent for a raster scanning digital 3D object reconstruction device with micron-level modeling accuracy.'
         ]
       },
       {
         year: '2015',
         txt: [
-          '2015.08 4DAGE, in competition with over 27,000 enterprises, won the China Innovation and Entrepreneurship Competition\'s Outstanding Enterprise Award.',
-          '2015.10 Dr. Cui Yan, founder of 4DAGE, was received by Premier Li Keqiang and commended to him for his work as a representative of the national "Mass Entrepreneurship and Innovation" initiative.',
-          '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Became partner of organizations that preserves cultural heritage, including the Palace Museum and Guangdong Provincial Museum.'
+          '<i>2015.08</i>4DAGE, in competition with over 27,000 enterprises, won the China Innovation and Entrepreneurship Competition\'s Outstanding Enterprise Award.',
+          '<i>2015.10</i>Dr. Cui Yan, founder of 4DAGE, was received by Premier Li Keqiang and commended to him for his work as a representative of the national "Mass Entrepreneurship and Innovation" initiative.',
+          '<i></i>Became partner of organizations that preserves cultural heritage, including the Palace Museum and Guangdong Provincial Museum.'
         ]
       },
       {
         year: '2016',
         txt: [
-          '2016.05 Nanchang Han Dynasty Haihunhou Historic Site Museum\'s online digital museum was officially launched. The Han Dynasty Haihunhou Historic Site is one of the top ten national archaeological discoveries.'
+          '<i>2016.05</i>Nanchang Han Dynasty Haihunhou Historic Site Museum\'s online digital museum was officially launched. The Han Dynasty Haihunhou Historic Site is one of the top ten national archaeological discoveries.'
         ]
       },
       {
         year: '2017',
         txt: [
-          '2017.04 4DAGE became sole virtual reality technology supplier to the China Pavilion at Kazakhstan\'s Astana World Expo.',
-          '2017.06 4DAGE and German Research Center for Artificial Intelligence signed an Agreement on the China-Germany Artificial Intelligence Institute Project witnessed by the Chinese Premier and Chancellor of Germany, creating a platform for China-Germany cooperation and exchange and establishing a strong foundation for Sino-German scientific and technological exchange.'
+          '<i>2017.04</i>4DAGE became sole virtual reality technology supplier to the China Pavilion at Kazakhstan\'s Astana World Expo.',
+          '<i>2017.06</i>4DAGE and German Research Center for Artificial Intelligence signed an Agreement on the China-Germany Artificial Intelligence Institute Project witnessed by the Chinese Premier and Chancellor of Germany, creating a platform for China-Germany cooperation and exchange and establishing a strong foundation for Sino-German scientific and technological exchange.'
         ]
       },
       {
         year: '2018',
         txt: [
-          '2018.05 4DKanKan, the world\'s first consumer 3D camera was launched, capable of reconstructing 100㎡ of space in five minutes – one twentieth of the time required for image acquisition by existing machines – and costing one-tenth the price of traditional 3D modeling equipment.',
-          '2018.11 4DKanKan was recognized as “Scientific and Technological Achievement” by China High-tech Industrialization Association',
-          '&ensp;&ensp;&ensp;&ensp;&ensp;&nbsp;&nbsp;4DKanKan was evaluated as “Excellent Product” by China Hi-Tech Fair.'
+          '<i>2018.05</i>4DKanKan, the world\'s first consumer 3D camera was launched, capable of reconstructing 100㎡ of space in five minutes – one twentieth of the time required for image acquisition by existing machines – and costing one-tenth the price of traditional 3D modeling equipment.',
+          '<i>2018.11</i>4DKanKan was recognized as “Scientific and Technological Achievement” by China High-tech Industrialization Association',
+          '<i></i>4DKanKan was evaluated as “Excellent Product” by China Hi-Tech Fair.'
         ]
       },
       {
         year: '2019',
         txt: [
-          '2019.04 4DAGE cooperated with Hetjens German Museum of Ceramics in 3D digitization, and developed a digital museum application. As an outstanding case of the Belt and Road Initiative\'s cultural output, the project was included in the case collection of the 2019 Belt and Road Forum.',
-          '2019.05 4DKanKan Pro was unveiled at Rise of AI Conference in Berlin, Germany.'
+          '<i>2019.04</i>4DAGE cooperated with Hetjens German Museum of Ceramics in 3D digitization, and developed a digital museum application. As an outstanding case of the Belt and Road Initiative\'s cultural output, the project was included in the case collection of the 2019 Belt and Road Forum.',
+          '<i>2019.05</i>4DKanKan Pro was unveiled at Rise of AI Conference in Berlin, Germany.'
         ]
       }
     ]

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

@@ -55,19 +55,19 @@ export default{
           icon: {
             backgroundImage: `url(${require('@/assets/images/img_core_app01.png')})`
           },
-          sub: 'The brand new indoor reconstruction<br/>system captures data using AI algorithm.'
+          sub: 'The brand new indoor reconstruction system captures data using AI algorithm.'
         },
         {
           icon: {
             backgroundImage: `url(${require('@/assets/images/img_core_app02.png')})`
           },
-          sub: 'The algorithm works out accurate camera position<br/>to capture all color information and partial depth information.'
+          sub: 'The algorithm works out accurate camera position to capture all color information and partial depth information.'
         },
         {
           icon: {
             backgroundImage: `url(${require('@/assets/images/img_core_app03.png')})`
           },
-          sub: 'The AI algorithm works in conjunction with Loop-Closing, which <br/>makes the camera’s geometric calibration faster and more stable.'
+          sub: 'The AI algorithm works in conjunction with Loop-Closing, which makes the camera’s geometric calibration faster and more stable.'
         }
       ]
     }

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

@@ -88,7 +88,7 @@ export default{
       image: baseUrl + 'images/phone_6.jpg',
       icon: baseUrl + 'images/phone_icon_6.png',
       text: '融信' },
-    {url: 'https://www.cgaii.com/museum/cultural/index.html',
+    {url: 'https://www.4dkankan.com/showPC.html?m=X99yIvTq',
       image: baseUrl + 'images/phone_1.jpg',
       icon: baseUrl + 'images/phone_icon_1.png',
       text: '德国陶瓷博物馆' },

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

@@ -0,0 +1,66 @@
+export default{
+  top1: '概览',
+  top2: '技术规格',
+  dec: '15分钟快速建模,全自动生成空间模型,实时计算空间尺寸,10K分辨率支持4倍放大',
+  yushou: '【新品预售】',
+  price: 'RMB 9,800',
+  buy: 'Shop Now',
+  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  guige: {
+    name: '技术规格',
+    dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知;',
+    arr: [
+      {
+        name: '容量和内存',
+        val: ['LPDDR4X双通道', '6G内存', 'UFS 2.1', '64GB 机身存储']
+      },
+      {
+        name: '机身尺寸和重量',
+        val: ['高度 = 153.3m', '宽度 = 74.5mm', '厚度 = 7.9mm', '重量 = 170g']
+      },
+      {
+        name: '处理器平台',
+        val: [
+          'Qualcomm® 骁龙™ 845 处理器',
+          '10nm 先进制程',
+          '单核主频可达 2.8GHz',
+          'Adreno™ 630 图形处理器,主频可达 700MHz',
+          '配备人工智能引擎(AI Engine)'
+        ]
+      },
+      {
+        name: '网络',
+        val: ['支持 VoLTE 高质量宽带', '支持三载波聚', '支持 LTE B41 4x4 MIMO']
+      },
+      {
+        name: '屏幕',
+        val: [
+          '6.17 英寸 In-Cell 全高清显示屏',
+          '2242 x 1080 分辨率,403 ppi',
+          '康宁®第三代大猩猩®玻璃'
+        ]
+      }
+    ]
+  },
+  color: {
+    key: '颜色',
+    val: ' 静谧黑'
+  },
+  service: {
+    key: '服务',
+    val: [
+      '数据永久存储',
+      '高速上传计算队列',
+      '场景分享、热点编辑、隐私加密',
+      '多种个性化功能',
+      '附送30G终身容量'
+    ]
+  },
+  gift: {
+    key: '赠品',
+    val: ' 官方拍摄支架 x 1'
+  },
+  count: {
+    key: '数量'
+  }
+}

+ 23 - 1
src/store/language/home_cn.js

@@ -4,6 +4,7 @@ import eight from './cn/eight'
 import about from './cn/about'
 import coreTech from './cn/coreTech'
 import purchase from './cn/purchase'
+import purchasetow from './cn/purchasetow'
 
 export default {
   title: '中文',
@@ -131,6 +132,26 @@ export default {
     cart: '购物车'
   },
   cases: {
+    sceneSelected: {
+      '筛选设备': '筛选设备',
+      '全部': '全部',
+      '四维看看 Lite': '四维看看 Lite',
+      '四维看看 Pro': '四维看看 Pro'
+    },
+    selectType: [
+      {
+        id: '全部',
+        name: '全部'
+      },
+      {
+        id: '四维看看 Lite',
+        name: '四维看看 Lite'
+      },
+      {
+        id: '四维看看 Pro',
+        name: '四维看看 Pro'
+      }
+    ],
     sort: {
       name: '排序',
       items: [
@@ -199,5 +220,6 @@ export default {
   eight,
   about,
   coreTech,
-  purchase
+  purchase,
+  purchasetow
 }

+ 23 - 9
src/store/language/home_en.js

@@ -4,6 +4,7 @@ import eight from './en/eight'
 import about from './en/about'
 import coreTech from './en/coreTech'
 import purchase from './en/purchase'
+import purchasetow from './en/purchasetow'
 
 export default {
   title: 'English',
@@ -131,6 +132,26 @@ export default {
     cart: 'cart'
   },
   cases: {
+    sceneSelected: {
+      '筛选设备': 'Select',
+      '全部': 'All',
+      '四维看看 Lite': '4DKanKan Lite',
+      '四维看看 Pro': '4DKanKan Pro'
+    },
+    selectType: [
+      {
+        id: '全部',
+        name: 'All'
+      },
+      {
+        id: '四维看看 Lite',
+        name: '4DKanKan Lite'
+      },
+      {
+        id: '四维看看 Pro',
+        name: '4DKanKan Pro'
+      }
+    ],
     sort: {
       name: 'sequence',
       items: [
@@ -145,14 +166,6 @@ export default {
         {
           id: 3,
           name: 'hot'
-        },
-        {
-          id: 4,
-          name: 'Lite'
-        },
-        {
-          id: 5,
-          name: 'Pro'
         }
       ]
     },
@@ -207,5 +220,6 @@ export default {
   eight,
   about,
   purchase,
-  coreTech
+  coreTech,
+  purchasetow
 }

+ 5 - 7
src/store/user.js

@@ -22,7 +22,6 @@ try {
     dataObj[key] = localStorage && JSON.parse(localStorage.getItem(key))
   })
 } catch (error) {
-
 }
 
 export default {
@@ -112,7 +111,6 @@ export default {
 
       let data = res.data
       if (data.code !== 0) {
-        console.log(vue.$toast)
         return vue.$toast.show('warn', data.msg)
       }
       let token = data.data.token
@@ -133,7 +131,7 @@ export default {
 
       let data = res.data
       if (data.code !== 0) {
-        return alert(data.msg)
+        return vue.$toast.show('warn', data.msg)
       }
       context.commit('logout')
     },
@@ -148,7 +146,7 @@ export default {
       })
       let data = res.data
       if (data.code !== 0) {
-        return alert(data.msg)
+        return vue.$toast.show('warn', data.msg)
       }
       context.dispatch('getCart')
     },
@@ -163,7 +161,7 @@ export default {
       })
       let data = res.data
       if (data.code !== 0) {
-        return alert(data.msg)
+        return vue.$toast.show('warn', data.msg)
       }
       context.dispatch('getCart')
     },
@@ -231,10 +229,10 @@ export default {
           data: params,
           url: '/sso/user/getMsgAuthCode'
         }, res => {
-
         })
+        return true
       } else {
-        alert('手机号码不合法')
+        return vue.$toast.show('warn', '手机号码不合法')
       }
     }
   }

+ 4 - 0
src/util/browser.js

@@ -3,6 +3,10 @@ function versions () {
   return {
     // IE内核
     trident: u.indexOf('Trident') > -1,
+    // Firefox
+    firefox: u.indexOf('Firefox') > -1,
+    // edge
+    edge: u.indexOf('Edge') > -1,
     // opera内核
     presto: u.indexOf('Presto') > -1,
     // 苹果、谷歌内核

+ 61 - 7
src/util/http.js

@@ -5,10 +5,17 @@ import Vue from 'vue'
 
 let vue = new Vue()
 // import qs from 'qs'
-const exceptUrl = '/sso/user/logout'
+const exceptUrls = ['/sso/user/logout', '/sso/user/sendUserInfo', '/user/order/queryOrderStatus']
+axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://pro.4dkankan.com/api' : '/api'
+
+// axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://192.168.0.10:8080/api' : '/api'
+// 请求超时时限
+axios.defaults.timeout = 2000
+// 请求次数
+axios.defaults.retry = 2
+// 请求的间隙
+axios.defaults.retryDelay = 1000
 
-axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://192.168.0.10:8080/api' : 'http://192.168.0.10:8080/api'
-// axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'http://www.4dkankan.com' : 'http://www.4dkankan.com'
 // 拦截请求,做登陆,或head处理
 axios.interceptors.request.use(function (config) {
   if (config.method === 'post') {
@@ -24,6 +31,15 @@ axios.interceptors.request.use(function (config) {
     }
     // config.params = qs.stringify(config.params)
   }
+
+  for (let i = 0; i < exceptUrls.length; i++) {
+    let url = exceptUrls[i]
+
+    if (config.url === url) {
+      return config
+    }
+  }
+  vue.$toast.showLoading()
   return config
 }, function (error) {
   // 对请求错误做些什么
@@ -32,11 +48,15 @@ axios.interceptors.request.use(function (config) {
 // // 拦截返回,做错误统一处理
 axios.interceptors.response.use(
   response => {
+    vue.$toast.hideLoading()
     let code = Number(response.data.code)
-    let url = response.config.baseURL + exceptUrl
-    if (response.config.url === url) {
-      return response
+    for (let i = 0; i < exceptUrls.length; i++) {
+      let url = response.config.baseURL + exceptUrls[i]
+      if (response.config.url === url) {
+        return response
+      }
     }
+
     switch (code) {
       case 3004:
         store.state.user.token && vue.$toast.show('warn', '请重新登录', function () {
@@ -50,7 +70,41 @@ axios.interceptors.response.use(
     return response
   },
   error => {
-    return Promise.reject(error)
+  // 请求超时的之后,抛出 error.code = ECONNABORTED的错误..错误信息是 timeout of  xxx ms exceeded
+    let err = '网络请求失败'
+    if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
+      var config = error.config
+      config.__retryCount = config.__retryCount || 0
+
+      if (config.__retryCount >= config.retry) {
+        // Reject with the error
+        // window.location.reload();
+        vue.$toast.show('error', err, function () {
+          vue.$toast.hideLoading()
+        })
+        return Promise.reject(error)
+      }
+
+      // Increase the retry count
+      config.__retryCount += 1
+
+      // Create new promise to handle exponential backoff
+      var backoff = new Promise(function (resolve) {
+        setTimeout(function () {
+          // console.log('resolve');
+          resolve()
+        }, config.retryDelay || 1)
+      })
+
+      return backoff.then(function () {
+        return axios(config)
+      })
+    } else {
+      vue.$toast.show('error', err, function () {
+        vue.$toast.hideLoading()
+      })
+      return Promise.reject(error)
+    }
   }
 )
 

+ 31 - 0
src/util/index.js

@@ -21,5 +21,36 @@ module.exports = {
       return false
     };
     return true
+  },
+  detectZoom: function () {
+    let ratio = 0
+    let screen = window.screen
+    let ua = navigator.userAgent.toLowerCase()
+
+    if (~ua.indexOf('firefox')) {
+      if (window.devicePixelRatio !== undefined) {
+        ratio = window.devicePixelRatio
+      }
+    } else if (~ua.indexOf('msie')) {
+      if (screen.deviceXDPI && screen.logicalXDPI) {
+        ratio = screen.deviceXDPI / screen.logicalXDPI
+      }
+    } else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
+      ratio = window.outerWidth / window.innerWidth
+    }
+
+    if (ratio) {
+      ratio = Math.round(ratio * 100)
+    }
+
+    // 360安全浏览器下浏览器最大化时诡异的outerWidth和innerWidth不相等
+    if (ratio === 99 || ratio === 101) {
+      ratio = 100
+    }
+
+    return ratio
+  },
+  isWide: function () {
+    return Math.round(devicePixelRatio * 100) === 100 ? window.innerWidth > 1600 : true
   }
 }