Explorar el Código

feat:中文版本基本通过

xzh hace 4 años
padre
commit
799c5acbf2
Se han modificado 98 ficheros con 2111 adiciones y 748 borrados
  1. 49 48
      common/data/newsData.js
  2. BIN
      mobile/src/assets/images/refactor/home/partners_list.png
  3. 5 0
      mobile/src/pages/home/components/plate6.vue
  4. 12 0
      mobile/src/pages/home/index.vue
  5. 6 7
      pc/build/wepack.dev.server.js
  6. 1 1
      pc/index.html
  7. BIN
      pc/src/assets/images/home/France.jpg
  8. BIN
      pc/src/assets/images/home/France@2x.jpg
  9. BIN
      pc/src/assets/images/home/Germany.jpg
  10. BIN
      pc/src/assets/images/home/Germany@2x.jpg
  11. BIN
      pc/src/assets/images/home/USA.jpg
  12. BIN
      pc/src/assets/images/home/USA@2x.jpg
  13. BIN
      pc/src/assets/images/home/default-avatar.png
  14. BIN
      pc/src/assets/images/refactor/mall/cartNoGoods.jpg
  15. BIN
      pc/src/assets/images/refactor/mall/cartNoGoods@2x.jpg
  16. 33 8
      pc/src/components/Paging/index.vue
  17. 16 19
      pc/src/components/card/index.vue
  18. 10 7
      pc/src/components/common/phoneAddressSelect.vue
  19. 16 20
      pc/src/components/dev/components/Lang.vue
  20. 1 1
      pc/src/components/shared/MessageBox/MessageBox.vue
  21. 16 12
      pc/src/components/shared/MessageBox/plugin.js
  22. 1 0
      pc/src/components/shared/Modal.vue
  23. 2 2
      pc/src/components/toast/index.vue
  24. 9 0
      pc/src/lang/en/index.js
  25. 47 0
      pc/src/lang/en/modules/agent.js
  26. 4 0
      pc/src/lang/en/modules/common.js
  27. 62 0
      pc/src/lang/en/modules/conduct.js
  28. 32 0
      pc/src/lang/en/modules/header.js
  29. 50 0
      pc/src/lang/en/modules/home.js
  30. 14 0
      pc/src/lang/en/modules/kankanSpace.js
  31. 16 0
      pc/src/lang/en/modules/mall.js
  32. 74 0
      pc/src/lang/en/modules/news.js
  33. 7 0
      pc/src/lang/en/modules/service.js
  34. 12 2
      pc/src/lang/index.js
  35. 0 1
      pc/src/lang/zh/index.js
  36. 47 0
      pc/src/lang/zh/modules/agent.js
  37. 3 3
      pc/src/lang/zh/modules/common.js
  38. 62 0
      pc/src/lang/zh/modules/conduct.js
  39. 33 18
      pc/src/lang/zh/modules/header.js
  40. 49 44
      pc/src/lang/zh/modules/home.js
  41. 14 0
      pc/src/lang/zh/modules/kankanSpace.js
  42. 23 0
      pc/src/lang/zh/modules/login.js
  43. 16 0
      pc/src/lang/zh/modules/mall.js
  44. 74 0
      pc/src/lang/zh/modules/news.js
  45. 7 0
      pc/src/lang/zh/modules/service.js
  46. 49 33
      pc/src/page/cases/index.vue
  47. 7 7
      pc/src/page/cases/style.scss
  48. 5 5
      pc/src/page/conduct/conductExhibition/index.vue
  49. 5 5
      pc/src/page/conduct/conductHouse/index.vue
  50. 4 4
      pc/src/page/conduct/conductSecury/index.vue
  51. 5 5
      pc/src/page/conduct/conductShop/index.vue
  52. 5 5
      pc/src/page/conduct/conductSubject/index.vue
  53. 8 8
      pc/src/page/coreProducts/index.vue
  54. 51 50
      pc/src/page/distributor/index.vue
  55. 14 12
      pc/src/page/home2/index.vue
  56. 11 5
      pc/src/page/home2/style.scss
  57. 4 2
      pc/src/page/introtow/index.vue
  58. 4 3
      pc/src/page/layout/aside/index.vue
  59. 31 23
      pc/src/page/layout/footer.vue
  60. 77 15
      pc/src/page/layout/header/index.vue
  61. 67 36
      pc/src/page/layout/header/istyle.scss
  62. 79 24
      pc/src/page/layout/shopHeader/index.vue
  63. 13 13
      pc/src/page/location/index.vue
  64. 12 8
      pc/src/page/login/components/cameraLogin.vue
  65. 23 7
      pc/src/page/login/components/codeLogin.vue
  66. 54 10
      pc/src/page/login/components/forget/emailForm.vue
  67. 10 6
      pc/src/page/login/components/forget/index.vue
  68. 26 1
      pc/src/page/login/components/forget/selectType.vue
  69. 48 18
      pc/src/page/login/components/login.vue
  70. 130 25
      pc/src/page/login/components/register/index.vue
  71. 66 12
      pc/src/page/login/index.vue
  72. 48 2
      pc/src/page/mall/cart/index.vue
  73. 71 31
      pc/src/page/mall/confirm/components/addressModule.vue
  74. 34 32
      pc/src/page/mall/confirm/components/invoiceModule.vue
  75. 6 2
      pc/src/page/mall/confirm/index.vue
  76. 69 46
      pc/src/page/mall/kankanPro/index.vue
  77. 12 13
      pc/src/page/mall/kankanPro/style.scss
  78. 2 2
      pc/src/page/mall/pay/index.vue
  79. 2 1
      pc/src/page/mall/zhijia/index.vue
  80. 0 1
      pc/src/page/mall/zhijia/style.scss
  81. 4 2
      pc/src/page/manage/temp/information.vue
  82. 1 1
      pc/src/page/manage/temp/order.vue
  83. 14 4
      pc/src/page/news/index.vue
  84. 1 1
      pc/src/page/purchasetow/index.vue
  85. 1 1
      pc/src/page/purchasezhijia/index.vue
  86. 4 4
      pc/src/page/service/temp/app.vue
  87. 1 1
      pc/src/page/service/temp/clause.vue
  88. 5 5
      pc/src/page/service/temp/index.vue
  89. 1 1
      pc/src/page/service/temp/use.vue
  90. 95 21
      pc/src/page/service/video.vue
  91. 1 1
      pc/src/page/zhijia/index.vue
  92. 22 18
      pc/src/router/index.js
  93. 2 2
      pc/src/store/language/cn/purchase.js
  94. 2 2
      pc/src/store/language/cn/toast.js
  95. 30 5
      pc/src/store/language/index.js
  96. 11 5
      pc/src/store/user.js
  97. 8 9
      pc/src/util/http.js
  98. 33 0
      pc/src/util/tools.js

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 49 - 48
common/data/newsData.js


BIN
mobile/src/assets/images/refactor/home/partners_list.png


+ 5 - 0
mobile/src/pages/home/components/plate6.vue

@@ -1,11 +1,16 @@
 <template>
   <div class="plate06">
     <h1 class="common-title">合作伙伴</h1>
+    <img src="@/assets/images/refactor/home/partners_list.png" />
   </div>
 </template>
 
 <style lang="scss" scoped>
 .plate06 {
   padding: 56px 0 50px 20px;
+  img {
+    margin-top: 32px;
+    width: 335px;
+  }
 }
 </style>

+ 12 - 0
mobile/src/pages/home/index.vue

@@ -11,6 +11,7 @@
         <div @click="broadcast(language==='en'?`${$cdn}video/banner1.mp4`:`${$cdn}video/4dkkPRO_zh.mp4`)" class="btn-player">
           <img src="@/assets/images/refactor/home/playBtn.png" alt="">
           <span >介绍视频</span>
+          <div class="play-btn"></div>
         </div>
       </div>
     </div>
@@ -110,4 +111,15 @@ export default {
 
 <style lang="scss" scoped>
 @import './style.scss';
+.play-btn {
+  display: inline-block;
+  border: 6px solid #fff;
+  border-top-color: transparent;
+  border-right-color: transparent;
+  border-bottom-color: transparent;
+  border-left-width: 12px;
+  position: absolute;
+  top: 15px;
+  left: 49%;
+}
 </style>

+ 6 - 7
pc/build/wepack.dev.server.js

@@ -12,18 +12,17 @@ module.exports = function(app, server) {
         const files = fs.readdirSync(filePath)
         let data = {}
         files.forEach(item => {
+          delete require.cache[require.resolve(path.join(__dirname, `../src/lang/${req.params.id}/modules/${item}`))]
           data[item.replace(/\.\w+$/, '')] = require(path.join(__dirname, `../src/lang/${req.params.id}/modules/${item}`))
         })
         res.json({ ok: true, data });
     });
-    app.post('/dev/lang/:id', function(req, res) {
-      Object.keys(req.body).forEach(item => {
-        fs.writeFile('./src/lang/' + req.params.id + `/modules/${item}.js`, 'module.exports = ' + JSON.stringify(req.body[item], null, 4), err => {
-          if (err) {
-              return res.json({ ok: false });
-          }
-          res.json({ ok: true });
+    app.post('/dev/lang/:id', async function(req, res) {
+      await Object.keys(req.body).forEach(async item => {
+        await fs.writeFile('./src/lang/' + req.params.id + `/modules/${item}.js`, 'module.exports = ' + JSON.stringify(req.body[item], null, 4), err => {
+          
         })
       })
+      res.json({ ok: true });
     });
 }

+ 1 - 1
pc/index.html

@@ -14,7 +14,7 @@
     <meta name="description" content="世界上首款消费级3D相机—四维看看(4DKanKan)。技术核心三要素:易操作;自动化;高精度。主要应用领域为数字文博、数字地产、数字电商、数字餐饮、数字家居等。">
     <link rel="shortcut icon" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon.ico">
     <link rel="icon" type="image/png" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon192.png" sizes="192x192">
-    <link rel="stylesheet" href="//at.alicdn.com/t/font_941679_3nfsz5n7ru8.css">
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_941679_px081tlqkur.css">
     <link rel="apple-touch-icon" sizes="180x180" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon180.png">
     <title>四维看看</title>
     <script>

BIN
pc/src/assets/images/home/France.jpg


BIN
pc/src/assets/images/home/France@2x.jpg


BIN
pc/src/assets/images/home/Germany.jpg


BIN
pc/src/assets/images/home/Germany@2x.jpg


BIN
pc/src/assets/images/home/USA.jpg


BIN
pc/src/assets/images/home/USA@2x.jpg


BIN
pc/src/assets/images/home/default-avatar.png


BIN
pc/src/assets/images/refactor/mall/cartNoGoods.jpg


BIN
pc/src/assets/images/refactor/mall/cartNoGoods@2x.jpg


+ 33 - 8
pc/src/components/Paging/index.vue

@@ -1,14 +1,15 @@
 <template>
   <div class="layout">
-    <a @click="clickHandle(index - 1)" ></a>
-    <a @click="clickHandle(1)" :class="{active: index === 1}" >1</a><a class="more" @click="clickHandle(current - 3)" v-if="current>5" >...</a><a
+    <a class="next-page pre-page" v-if="index>1" @click="clickHandle(index - 1)"></a>
+    <a class="page-item" @click="clickHandle(1)" :class="{active: index === 1}" >1</a><a class="page-item more" @click="clickHandle(current - 3)" v-if="current>5" >...</a><a
       v-if="page!==maxPage && page!==1"
       v-for="page in pages"
       :key="page"
       @click="clickHandle(page)"
+      class="page-item"
       :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)" v-if="maxPage!==1" :class="{active: index === maxPage}" >{{maxPage}}</a>
-      <a @click="clickHandle(index + 1)"></a>
+      >{{page}}</a><a class="more page-item" @click="clickHandle(pages[pages.length-1] + 2)" v-if="pages[pages.length-1]+2<=maxPage" >...</a><a @click="clickHandle(maxPage)" class="page-item" v-if="maxPage!==1" :class="{active: index === maxPage}" >{{maxPage}}</a>
+      <a v-if="index !== maxPage" class="next-page next-page-item" @click="clickHandle(index + 1)"></a>
   </div>
 </template>
 
@@ -100,6 +101,7 @@ export default {
       if (index > 0 && index <= this.maxPage) {
         this.index = index
       }
+      console.log(this.index, 's')
       this.$emit('clickHandle', this.index)
     }
   },
@@ -118,25 +120,48 @@ export default {
     .layout .more:hover::after{
        transform: scaleX(0)!important;
     }
-    .layout a:last-child:hover::before{
+    .layout .next-page-item:hover::before{
       transform: scaleX(2);
     }
-    .layout a:last-child:hover::after{
+    .layout .next-page-item:hover::after{
       transform: translateX(5px);
     }
-    .layout a:last-child::before{
+    .layout .next-page-item::before{
       background-color: #111;
       height: 2px;
       width: 8px;
       transform-origin: 0 0;
     }
-    .layout a:last-child::after{
+    .layout .next-page-item::after{
       width: 0;
       height: 0;
       border-style: solid;
       border-width: 5px 0 5px 8px;
       border-color: transparent transparent transparent #011111;
     }
+    .layout .pre-page::after {
+      transform-origin: 100% 0;
+    }
+    .layout .pre-page:hover::after{
+      transform: scaleX(2);
+      transform-origin: 100% 0;
+    }
+    .layout .pre-page:hover::before{
+      transform: translateX(-5px);
+    }
+    .layout .pre-page::after{
+      background-color: #111;
+      height: 2px;
+      width: 8px;
+    }
+    .layout .pre-page::before{
+      width: 0;
+      height: 0;
+      border-style: solid;
+      border-width: 5px 8px 5px 0;
+      border-color: transparent  #011111 transparent transparent;
+    }
+    
 
 /* .layout {
   text-align: center;

+ 16 - 19
pc/src/components/card/index.vue

@@ -1,21 +1,15 @@
 <template>
 <div class="card-con">
   <!-- <img :src="data.homepic||'https://scene3d.4dage.com/loading/thumb.jpg'"> -->
-  <div class="card-img" :style="{backgroundImage: `url(${data.thumb+'?v='+data.version||`${$cdn}images/default.png`})`}"></div>
-  <div class="item-info" @click="goto(data.webSite)">
-    <div class="text-info">
-      <div>
-        <h3>{{data.sceneName}}</h3>
-      </div>
-    </div>
-  </div>
+  <div class="card-img"  @click="goto(data.webSite)" :style="{backgroundImage: `url(${data.thumb+'?v='+data.version||`${$cdn}images/default.png`})`}"></div>
   <div class="info">
     <!-- <div class="title">{{data.title}}</div> -->
     <div class="username">
       <div class="u-l">
         <p class="sname">{{data.sceneName}}</p>
-        <span class="txt">{{language==='en'?'Created by: ':'作者:'}}{{data.userName}}</span>
-        <span class="txt">{{data.nickName}}</span>
+         <!-- <span class="txt"> </span> -->
+        <!-- <span class="txt">{{language==='en'?'Created by: ':'作者:'}}{{data.userName}}</span> -->
+        <!-- <span class="txt">{{data.nickName}}</span> -->
       </div>
       <div class="u-r">
         <img :style="{width:data.sceneScheme>=4?'20px':'18px',height:data.sceneScheme>=4?'20px':'18px'}" :src="`${$cdn}images/_eye.png`" alt>
@@ -88,7 +82,7 @@ export default {
 .card-con {
   width: 100%;
   position: relative;
-  margin-bottom: 20px;
+  margin-bottom: 33px;
   .card-img{
     width: 100%;
     height: 184px;
@@ -96,7 +90,10 @@ export default {
     background-position: center;
     background-size: auto 100%;
     background-repeat: no-repeat;
-
+    transition: all 0.3s linear;
+    &:hover {
+      background-size: auto 105%;
+    }
   }
   img {
     width: 100%;
@@ -111,9 +108,7 @@ export default {
     bottom: 0;
     top: 0;
     right: 0;
-    background-color: rgba(31, 228, 220, 0.7);
     opacity: 0;
-    transition: opacity .5s cubic-bezier(.39, .03, .41, .98);
     width: 100%;
     height: 184px;
     cursor: pointer;
@@ -155,9 +150,9 @@ export default {
       opacity: 1;
     }
 
-    h3 {
-      transform: matrix(1, 0, 0, 1, 0, 0);
-    }
+    // h3 {
+    //   transform: matrix(1, 0, 0, 1, 0, 0);
+    // }
 
     p {
       opacity: 1;
@@ -190,13 +185,15 @@ export default {
         }
       }
       .u-r{
-        flex: 1;
-        text-align: right;
+        position: absolute;
+        right: 0;
+        bottom: 0;
         img{
           width: 18px;
           height: 18px;
           display: inline-block;
           vertical-align: middle;
+          cursor: initial;
         }
         span{
           display: inline-block;

+ 10 - 7
pc/src/components/common/phoneAddressSelect.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="phone-address">
-    <div class="search-w">
+    <div class="search-w" @click.stop="">
       <input class="search-input" placeholder="搜索" type="text" v-model="keyword">
       <h-icon type="sousuo" class="sousuo-icon" />
     </div>
@@ -31,7 +31,7 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 .phone-address {
   padding: 20px 20px 10px;
   border:1px solid rgba(144,144,144,1);
@@ -43,18 +43,20 @@ export default {
   overflow: auto;
   position: absolute;
   background: #fff;
-  left: 0;
+  left: -1px;
+  z-index: 111;
   .search-w {
     position: relative;
   }
   .search-input {
-    height: 26px;
-    line-height: 24px;
+    height: 26px !important;
+    line-height: 24px !important;
     background:rgba(247,247,247,1);
     border:1px solid rgba(144,144,144,1);
     border-radius:3px;
     width: 100%;
     padding-right: 27px;
+    margin: 0;
     &::placeholder {
       text-align: right;
     }
@@ -62,8 +64,9 @@ export default {
   .sousuo-icon {
     position: absolute;
     right: 8px;
-    top: 8px;
-    line-height: 26px;
+    top: 50%;
+    margin: -8px 0 0 0;
+    line-height: 1;
     color: #909090;
     display: inline;
   }

+ 16 - 20
pc/src/components/dev/components/Lang.vue

@@ -38,8 +38,8 @@
                                 @change="onValueChange($event,root,key)"
                             />
                         </div>
-                        <div v-for="(next) in root" :key="next.__name" v-show="isModule(next)">
-                            <div>{{next.__name}}</div>
+                        <div v-for="(next, name) in root" :key="next.__name" v-show="isModule(next)">
+                            <div>{{name}}</div>
                             <div class="module">
                                 <div
                                     class="input"
@@ -47,7 +47,7 @@
                                     :key="key"
                                     v-show="isChildren(key,subs)"
                                 >
-                                    <div>{{key}}</div>
+                                    <div>{{name + key}}</div>
                                     <input :value="subs" type="text" @change="onValueChange($event,next,key)" />
                                 </div>
                             </div>
@@ -61,6 +61,7 @@
 <script>
 import http from "@/util/http";
 import Layout from "./Layout";
+import { deepExtend } from '@/util/tools'
 export default {
     components: {
         Layout
@@ -85,13 +86,11 @@ export default {
     methods: {
         async load(curr) {
             const result = await http.get("../dev/lang/" + (curr || this.curr));
-            console.log(result)
             if (result.data.ok) {
                 if (this.lang == null) {
                     this.lang = result.data.data;
-                    console.log(this.lang)
                 } else {
-                    $.extend(true, this.lang, result.data.data);
+                    this.lang = deepExtend(this.lang, result.data.data);
                 }
             } else {
                 if (this.curr != "zh") {
@@ -116,21 +115,18 @@ export default {
             }
         },
         onSave() {
-            this.$confirm({
-                content: "是否保存?",
-                ok: () => {
-                    http.post(`dev/lang/${this.curr}`, this.lang)
-                        .then(response => {
-                            if (response.ok) {
-                                this.$tips({ content: "保存成功" });
-                            } else {
-                                this.$tips({ content: "保存失败" });
-                            }
-                        })
-                        .catch(err => {
-                            this.$tips({ content: "保存失败" });
-                        });
+            http.post(`../dev/lang/${this.curr}`, this.lang)
+            .then(response => {
+                if (response.data.ok) {
+                    this.$alert('保存成功', {
+                        icon: 'success'
+                    });
+                } else {
+                    this.$alert('保存失败');
                 }
+            })
+            .catch(err => {
+                this.$alert('保存失败');
             });
         }
     }

+ 1 - 1
pc/src/components/shared/MessageBox/MessageBox.vue

@@ -27,7 +27,7 @@
           <h-icon :type="icon" style="font-size: 40px;line-height: 52px" />
         </div>
         <p class="message">{{ message }}</p>
-        <div class="submit-btn" @click="handleAction('close')">确定</div>
+        <div class="submit-btn" @click="handleAction('confirm')">确定</div>
       </div>
     </template>
     

+ 16 - 12
pc/src/components/shared/MessageBox/plugin.js

@@ -117,7 +117,7 @@ MessageBox.setDefaults = defaults => {
   MessageBox.defaults = defaults
 }
 
-MessageBox.alert = (message, title, options) => {
+MessageBox.alert = (message, title, options={icon: 'warn'}) => {
   let iconMap = {
     warn: 'tanhao',
     success: 'duihao'
@@ -130,17 +130,21 @@ MessageBox.alert = (message, title, options) => {
   } else if (title === undefined) {
     title = defaults.title
   }
-  return MessageBox(Object.assign({
-    title: title,
-    message: message,
-    $type: 'alert',
-    closeOnPressEscape: false,
-    closeOnClickModal: false,
-    hideCancleButton: true,
-    type: 'alert',
-    showClose: false,
-    icon
-  }, options))
+  return new Promise(resolve => {
+    Vue.prototype.$toast.show(options.icon, message, resolve)
+  })
+  
+  // return MessageBox(Object.assign({
+  //   title: title,
+  //   message: message,
+  //   $type: 'alert',
+  //   closeOnPressEscape: false,
+  //   closeOnClickModal: false,
+  //   hideCancleButton: true,
+  //   type: 'alert',
+  //   showClose: false,
+  //   icon
+  // }, options))
 }
 
 MessageBox.confirm = (message, title, options) => {

+ 1 - 0
pc/src/components/shared/Modal.vue

@@ -110,6 +110,7 @@ export default {
     box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
     vertical-align: middle;
     text-align: left;
+    max-height: 80%;
   }
 
   .close {

+ 2 - 2
pc/src/components/toast/index.vue

@@ -25,7 +25,7 @@
       :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="toast-con" :style="{minWidth:toastType==='comfirm'?'403px':'403px'}">
         <div class="top">
           <span>{{typeTxt}}</span>
           <i
@@ -63,7 +63,7 @@ import { mapState } from 'vuex'
 let types = {
   warn: '提示',
   error: '错误',
-  success: '成功'
+  success: '提示'
 }
 
 let typesEn = {

+ 9 - 0
pc/src/lang/en/index.js

@@ -0,0 +1,9 @@
+const requireModules = require.context('./modules', true, /[a-z0-9]+\.js$/i)
+
+let en = {}
+requireModules.keys().forEach(fileName => {
+  let name = fileName.substr(fileName.lastIndexOf('/') + 1).replace(/\.\w+$/, '')
+  en[name] = requireModules(fileName)
+})
+
+module.exports = en

+ 47 - 0
pc/src/lang/en/modules/agent.js

@@ -0,0 +1,47 @@
+module.exports = {
+    "bannerTitle": "Become a distributor of 4D KanKan",
+    "planTitle": "Outline of 4D KanKan Distributor Program",
+    "planDesc1": "The patented AI space reconstruction algorithm technology from 4DAge has won numerous awards and has reconstructed more than 300,000 space models worldwide.",
+    "planDesc2": "This innovative approach of space reconstruction is gradually changing the business model of various industries (real estate, architecture, museum, tourism, jounalist, insurance claims, criminal investigation, etc.).",
+    "planDesc3": "Our 4D KanKan Distributor Program invites professionals from all industries to participate in our “Digital Everything” scheme, open up new market together and share profits.",
+    "planDesc4": "If you are interested in the idea of ​​3D capturing the world and would like to incorporate it into your career plan, this is an excellent opportunity for cooperation.",
+    "advanTitle": "Benefits of Being our Valued Distributor",
+    "advan": {
+        "item1Title": "Share the Profit",
+        "item1Sub": "Large Profit to Share",
+        "item2Title": "Exclusive Customer Service",
+        "item2Sub": "Support from Exclusive and Professional Sales and Technicians",
+        "item3Title": "Promotional Material",
+        "item3Sub": "Regularly Updated Promotional Videos and Cases",
+        "item4Title": "Shop Decoration",
+        "item4Sub": "Offer Necessary Promotional Material for the Shop",
+        "item5Title": "Growth Opportunity",
+        "item5Sub": "Opportunities to Join Exhibitions and Professional Conferences"
+    },
+    "jinxiaoTitle": "Become a distributor of 4D KanKan",
+    "jinxiaoForm": {
+        "companytitle": "Company Information",
+        "companyNameLabel": "Registered Company Name",
+        "companyNamePlaceholder": "Please input the registered company name",
+        "addressLabel": "Company Address",
+        "addressPlaceholder1": "Country",
+        "addressPlaceholder2": "Region",
+        "addressPlaceholder3": "Please input the detailed address of your company",
+        "storeLabel": "Do you have a retail shop or a company website?",
+        "storeType1": "Mainly Offline Sales",
+        "storeType2": "Mainly Online Sales",
+        "storePlaceholder": "Please input the detailed address of your retail shop",
+        "applytitle": "Applicant Information",
+        "applyNameXing": "Last Name",
+        "applyNameMing": "First Name",
+        "applyNamePlaceholder": "Please input the last name",
+        "applyNamePlaceholder1": "Please input the first name",
+        "positionLabel": "Title",
+        "positionPlaceholder": "Please input the title",
+        "phoneLabel": "Phone",
+        "phonePlaceholder": "Please input the phone",
+        "emailLabel": "Email",
+        "emailPlaceholder": "Please input the email",
+        "submit": "Submit"
+    }
+}

+ 4 - 0
pc/src/lang/en/modules/common.js

@@ -0,0 +1,4 @@
+module.exports = {
+    "kankan": "4DKanKan Pro",
+    "more": "more"
+}

+ 62 - 0
pc/src/lang/en/modules/conduct.js

@@ -0,0 +1,62 @@
+module.exports = {
+    "__name": "核心产品",
+    "coreProduct": {
+        "bannerTitle": "Core Product",
+        "itemTitle1": "Autonomous& Accurate Modeling,Automatic Distance Measurement",
+        "itemTitle2": "720° Immersive Roaming with 8K Picture Quality",
+        "itemTitle3": "HDR Mode Balances Light and Dark Area Exposure",
+        "itemTitle4": "Real-time Panoramic Video to Create an Immersive Experience",
+        "itemTitle5": "10 Minutes to Start, Easy to Operation",
+        "itemTitle6": "Autonomous Space Modeling in 10 Minutes, Efficient and Fast(About 100㎡)",
+        "itemTitle7": "Multifunctional Editing Tool, Let Space Tell the Story"
+    },
+    "coreTech": {
+        "bannerTitle": "Core Technology",
+        "itemTitle1": "Space Digitization",
+        "itemText1": "Record and calculate the spatial position of the camera when shooting, and extract the corresponding 3D point cloud, so as to obtain the real situation of 3D space",
+        "itemTitle2": "Space Interaction",
+        "itemText2": "Automatic tour with preset route, panoramic and box videos enhance the interaction, different forms of dynamic hot-spot, let the space tell the story",
+        "item2Name1": "Dynamic Hot-spot",
+        "item2Name2": "Interactive Video",
+        "item2Name3": "Automatic Tour",
+        "itemTitle3": "Space Display",
+        "itemText3": "Offers a 720° immersive roaming experience on mobile phone, tablet, PC and VR glasses device without plug-ins.",
+        "item3Name1": "VR",
+        "item3Name2": "PC",
+        "item3Name3": "Mobile"
+    },
+    "conductHouse": {
+        "bannerTitle": "4DKanKan—Realestate, Mass Reconstruction of the Real Houses",
+        "itemTitle1": "AI Automatic Modeling, Efficient Reconstruct the Real Houses",
+        "itemTitle2": "Display All the Details, More Efficient for Sales and Rental Decisions",
+        "itemTitle3": "Multidimensional Display the Information of Real-estate with Higher Efficiency",
+        "itemTitle4": "Multifunctional Editing Tool, Let Houses Display Better"
+    },
+    "conductExhibition": {
+        "bannerTitle": "4DKanKan—Exhibition, Participate in Exhibitions without Any Limitations",
+        "itemTitle1": "Online Visiting and Negotiation, Exchange Business Cards Freely",
+        "itemTitle2": "No Barries to Communication, Easy to Get All the Information",
+        "itemTitle3": "Reduce the Cost of Exhibitions, Promote Transactions Effectively",
+        "itemTitle4": "Statistic Data Flow, Analyze User Persona"
+    },
+    "conductSubject": {
+        "bannerTitle": "4DKanKan--Culture& Relics, Help to Create Never-ending Museums",
+        "itemTitle1": "Digital Twin of Treasure Relics,Break the Time Limitation",
+        "itemTitle2": "Various Forms of Spatial Interaction, Carrying Rich Historical Heritage",
+        "itemTitle3": "Simultaneous Operation by Multi-user, Listening to Historical Stories",
+        "itemTitle4": "Promote Social Science Education and Help Cultural Communication"
+    },
+    "conductShop": {
+        "bannerTitle": "4DKanKan—E-commerce,Free Shopping without Any Limitations",
+        "itemTitle1": "New Immersive Shopping Experience in 3D Digital Business District",
+        "itemTitle2": "Shopping in the Real 3D Models through Mobile Phones",
+        "itemTitle3": "Gather Online Passenger Flow and Boost Offline Economy",
+        "itemTitle4": "Personal Customer Service,Real-time Communications"
+    },
+    "conductSecury": {
+        "bannerTitle": "Security Survey",
+        "itemTitle1": "Reconstruct Disaster Scenes Efficiently,Create Comprehensive 3D Files",
+        "itemTitle2": "Multifunctional Editing Tool,Improve the Communication Quality",
+        "itemTitle3": "Pre-collection is Available,Reduce the Claims Disputes"
+    }
+}

+ 32 - 0
pc/src/lang/en/modules/header.js

@@ -0,0 +1,32 @@
+module.exports = {
+    "core_product": "Core Product",
+    "solutions": "Solutions",
+    "kankan_space": "4DKanKan--Space",
+    "core_tech": "Core Technology",
+    "service": "Service Support",
+    "about": "About Us",
+    "online_shop": "Online Shopping Mall",
+    "solutionsHouse": "Real-estate Marketing",
+    "solutionsExi": "Online Exhibition",
+    "solutionsSubject": "Smart Culture& Relics",
+    "solutionsShop": "VR Shopping",
+    "solutionsSec": "Security Survey",
+    "serviceApp": "APP Download",
+    "serviceUse": "User Tutorial",
+    "serviceBaoxiu": "Warranty Information",
+    "serviceVideo": "Video Tutorial",
+    "aboutNews": "News",
+    "aboutAgent": "Be Our Distributor",
+    "aboutCompany": "Company Introduction",
+    "footer": {
+        "bannerTitle": "4DKanKan--Let the space tell the story",
+        "find": "Findings",
+        "saleEmail": "Business Collaboration",
+        "meitiEmail": "Media Inquiries",
+        "phone": "Tel",
+        "find4D": "Explore 4Dage",
+        "kankan": "4Dage",
+        "zhongde": "CGAII",
+        "moku": "4DMODEL"
+    }
+}

+ 50 - 0
pc/src/lang/en/modules/home.js

@@ -0,0 +1,50 @@
+module.exports = {
+    "bannerText": "Real-time Accurate Reconstruction, Pass the Valve of Space",
+    "bannerBuyBtnText": "Buy Now",
+    "bannerMoreBtn": "Learn More",
+    "bannerIntroVideo": "Introduction Video",
+    "bannerAgent": "Be A Distributor",
+    "plate1Title": "Solutions",
+    "plate2Title": "4DKanKan--Space",
+    "plate3Title": "Core Technology",
+    "plate4Title": "News",
+    "plate5Title": "Partners",
+    "plate1Item1": "Real-estate Marketing",
+    "plate1Item2": "Online Exhibition",
+    "plate1Item3": "Smart Culture& Relics",
+    "plate1Item4": "VR Shopping",
+    "plate1Item5": "Security Survey",
+    "plate1Item1SubTitle": "Mass Reconstruction of the Real Houses",
+    "plate1Item1Desc1": "AI Automatic Modeling, Efficient Reconstruct the Real Houses",
+    "plate1Item1Desc2": "VR Guidance/ VR Explanation,Display All the Details",
+    "plate1Item1Desc3": ".Easy to Operation, Everyone Can Be A Master",
+    "plate1Item1Desc4": ".Professional Real-estate Marketing System, More Efficient for Sales and Rental Decisions",
+    "plate1Item2SubTitle": "All-round Reconstruction of Exhibition Information, Without Any Limitations",
+    "plate1Item2Desc1": "AI Image Reconstruction Technology, Create the Digital Twin of Offline Exhibition",
+    "plate1Item2Desc2": "Interactive 3D Exhibits, 720° Immersive Roaming",
+    "plate1Item2Desc3": "Online Negotiation on the Same Screen, Directly Connect Supply and Acquisition Information",
+    "plate1Item2Desc4": "Automatically Collect and Analyze Exhibition Data, Reduce Customer Acquisition Costs",
+    "plate1Item3SubTitle": "Assistant to Build A Museum that Never Ends",
+    "plate1Item3Desc1": "3D HD Recording, Easy to Retention and Protection",
+    "plate1Item3Desc2": "Space Interaction, Let the Space to Express More Historical Connotations",
+    "plate1Item3Desc3": "Under the Master’s Explanation, Multi-user Can Participate on the Same Screen",
+    "plate1Item3Desc4": "Promote Social Science Education and Promote Everyone to Participate",
+    "plate1Item4SubTitle": "Mass Reconstruction of the Real Houses",
+    "plate1Item4Desc1": "AI Automatic Modeling, Efficient Reconstruct the Real Houses",
+    "plate1Item4Desc2": "VR Guidance/ VR Explanation,Display All the Details",
+    "plate1Item4Desc3": "Easy to Operation, Everyone Can Be A Master",
+    "plate1Item4Desc4": "Professional Real-estate Marketing System, More Efficient for Sales and Rental Decisions",
+    "plate1Item5SubTitle": "Efficient Reconstruct Disaster Scenes,Create Comprehensive 3D Files",
+    "plate1Item5Desc1": "Efficient Reconstruct Disaster Scenes,Create Comprehensive 3D Files",
+    "plate1Item5Desc2": "Pre-collection is Available,Reduce the Claims Disputes",
+    "plate2Item1": "Yongzheng Palace",
+    "plate2Item2": "Xiaomi",
+    "plate2Item3": "Huafa Mountain Mansion",
+    "plate2Item4": "Marriott",
+    "plate3Item1Title": "Space Digitization",
+    "plate3Item1Text": "Automatically 3D Digital Reconstruction, Restore Spatial Layout and Structure",
+    "plate3Item2Title": "Space Interaction",
+    "plate3Item2Text": "Automatic Tour, Interactive Videos, Different Forms of Dynamic Hot-spot",
+    "plate3Item3Title": "Space Display",
+    "plate3Item3Text": "Offers A 720° Immersive Roaming Experience on Different Devices without Plug-ins"
+}

+ 14 - 0
pc/src/lang/en/modules/kankanSpace.js

@@ -0,0 +1,14 @@
+module.exports = {
+    "title": "4DKanKan--Space",
+    "typeAll": "All",
+    "typeHouse": "Real-estate",
+    "typeExihibition": "Exhibition",
+    "typeSubject": "Museum",
+    "typeShop": "E-commerce",
+    "typeFoot": "Catering",
+    "typeOther": "Others",
+    "recommend": "Recommend",
+    "hot": "Hot",
+    "new": "Newest",
+    "placeholder": "Please Enter the Keywords to Search"
+}

+ 16 - 0
pc/src/lang/en/modules/mall.js

@@ -0,0 +1,16 @@
+module.exports = {
+    "postage": "Freight: SF Express",
+    "baseVolume": "Basic Storage Capacity",
+    "knowMore": "Learn More",
+    "standard": "Standard Package",
+    "addCou": "Value-added Package (including tripod)",
+    "count": "Amount",
+    "couTip": "Whether Need to Add Recommended Accessories (Standard Package Does Not Include the Following Accessories)",
+    "jiaojia": "4DKanKan Pro Tripod Set",
+    "jiaojiaDetail": "Tripod + Pulley + Ball Head",
+    "cart": "Add to the Shop Cart",
+    "fahuo": "Expected to Ship within Three Days",
+    "product": "Product Manual",
+    "techDetail": "Technical Parameters",
+    "widthDetail": "Size Parameters"
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 74 - 0
pc/src/lang/en/modules/news.js


+ 7 - 0
pc/src/lang/en/modules/service.js

@@ -0,0 +1,7 @@
+module.exports = {
+    "title": "Service Support",
+    "mVideo": "Video Tutorial",
+    "use": "User Tutorial",
+    "app": "APP Download",
+    "clause": "Warranty Policy"
+}

+ 12 - 2
pc/src/lang/index.js

@@ -1,12 +1,22 @@
 import Vue from 'vue'
 import VueI18n from 'vue-i18n'
 import zh from './zh'
-import en from './_en'
+import en from './en'
 
 Vue.use(VueI18n)
 
+let current = (localStorage && localStorage.getItem('language')) || '中'
+// if (!lang) {
+//     lang = window.navigator.language || window.navigator.userLanguage || null
+//     if (lang && !/^zh/.test(lang)) {
+//         console.log('自动获取浏览器语言:' + lang)
+//         lang = 'en'
+//     }else{
+//         lang = 'zh'
+//     }
+// }
 const i18n = new VueI18n({
-  locale: 'zh',
+  locale: current,
   messages: {
     zh,
     en

+ 0 - 1
pc/src/lang/zh/index.js

@@ -4,7 +4,6 @@ let zh = {}
 requireModules.keys().forEach(fileName => {
   
   let name = fileName.substr(fileName.lastIndexOf('/') + 1).replace(/\.\w+$/, '')
-  console.log(requireModules(fileName))
   zh[name] = requireModules(fileName)
 })
 

+ 47 - 0
pc/src/lang/zh/modules/agent.js

@@ -0,0 +1,47 @@
+module.exports = {
+    "bannerTitle": "成为四维看看经销商",
+    "planTitle": "四维看看经销商计划概述",
+    "planDesc1": "四维时代独创的AI空间重构算法技术已屡获殊荣,并累计在全球范围采集超过30万个空间模型。",
+    "planDesc2": "这种全新的空间记录方式正在逐步改变各行各业的业务模式(房地产、建筑、文博、旅游、新闻、保险理赔、刑侦记录等等)。",
+    "planDesc3": "四维看看经销商计划诚邀各业界专业人士,参与到未来的“数字万物”的进程中,共同开拓市场,分享利润。",
+    "planDesc4": "如果您对3D捕捉世界的想法很感兴趣,并愿将其纳入到您的事业规划中,这是一个绝佳的合作机会。",
+    "advanTitle": "成为增值经销商的好处",
+    "advan": {
+        "item1Title": "利润分成",
+        "item1Sub": "丰厚的利润分成",
+        "item2Title": "专属客服",
+        "item2Sub": "提供专属的专业的销售与技术人员",
+        "item3Title": "宣传资料",
+        "item3Sub": "定期更新的宣传视频及宣传案例",
+        "item4Title": "店面布置",
+        "item4Sub": "支持店面必要的广告物料",
+        "item5Title": "发展机会",
+        "item5Sub": "参与营销与科技大会的机会"
+    },
+    "jinxiaoTitle": "成为四维看看经销商",
+    "jinxiaoForm": {
+        "companytitle": "公司信息",
+        "companyNameLabel": "公司注册名称",
+        "companyNamePlaceholder": "请输入公司注册名称",
+        "addressLabel": "公司地址",
+        "addressPlaceholder1": "国家",
+        "addressPlaceholder2": "地区",
+        "addressPlaceholder3": "请输入公司地址",
+        "storeLabel": "是否有门店或企业网站",
+        "storeType1": "线下销售为主",
+        "storeType2": "线上销售为主",
+        "storePlaceholder": "请输入门店详细地址",
+        "applytitle": "申请人信息",
+        "applyNameXing": "姓",
+        "applyNameMing": "名",
+        "applyNamePlaceholder": "请输入姓",
+        "applyNamePlaceholder1": "请输入名",
+        "positionLabel": "职位",
+        "positionPlaceholder": "请输入职位",
+        "phoneLabel": "电话",
+        "phonePlaceholder": "请输入电话",
+        "emailLabel": "电子邮箱",
+        "emailPlaceholder": "请输入电子邮箱",
+        "submit": "提交"
+    }
+}

+ 3 - 3
pc/src/lang/zh/modules/common.js

@@ -1,4 +1,4 @@
-module.exports =  {
-  kankan: '四维看看Pro',
-  more: '更多'
+module.exports = {
+    "kankan": "四维看看Pro",
+    "more": "更多"
 }

+ 62 - 0
pc/src/lang/zh/modules/conduct.js

@@ -0,0 +1,62 @@
+module.exports = {
+    "__name": "核心产品",
+    "coreProduct": {
+        "bannerTitle": "核心产品",
+        "itemTitle1": "AI全自动精准建模,智能测距",
+        "itemTitle2": "720度8K画质,身临其境",
+        "itemTitle3": "HDR模式平衡明暗区域曝光",
+        "itemTitle4": "球幕视频真人解说 打造沉浸视听体验",
+        "itemTitle5": "10分钟入门,快速掌握拍摄流程",
+        "itemTitle6": "10分钟全自动出结果,高效快速(约100㎡)",
+        "itemTitle7": "强大编辑后台,让空间延伸表达"
+    },
+    "coreTech": {
+        "bannerTitle": "核心技术",
+        "itemTitle1": "空间数字化",
+        "itemText1": "记录与计算相机在拍摄时的空间位置,并提取对应的3D点云,从而获取三维空间的真实情况。",
+        "itemTitle2": "空间互动",
+        "itemText2": "自动导览 预先设定路线,球幕视频 BOX视频 增强体验的互动效果,多形式动态热点 赋以空间说话的艺术。",
+        "item2Name1": "动态热点",
+        "item2Name2": "互动视频",
+        "item2Name3": "自动导览",
+        "itemTitle3": "空间展示",
+        "itemText3": "无需插件,可在手机、 平板、PC端、VR眼镜,实现720°沉浸式漫游体验。",
+        "item3Name1": "VR端",
+        "item3Name2": "网页端",
+        "item3Name3": "移动端"
+    },
+    "conductHouse": {
+        "bannerTitle": "看房 ‧ 海量复刻真房源",
+        "itemTitle1": "AI自动建模,高效复刻真实房源",
+        "itemTitle2": "房源资讯全方位展示,提高租售决策效率",
+        "itemTitle3": "地产资讯多维展示,提高租售决策效率",
+        "itemTitle4": "强大功能编辑后台,传递更多房源价值"
+    },
+    "conductExhibition": {
+        "bannerTitle": "看展 • 随时随地参展办展",
+        "itemTitle1": "在线逛展洽谈,名片即刻获取",
+        "itemTitle2": "沟通畅通无阻,资讯一览无遗",
+        "itemTitle3": "降低搭展成本,高效促进交易",
+        "itemTitle4": "数据流量统计,用户画像分析"
+    },
+    "conductSubject": {
+        "bannerTitle": "文博·助力打造永不落幕的博物馆",
+        "itemTitle1": "珍贵陈展线上复刻,打破线下时空限制",
+        "itemTitle2": "空间交互形式多样,承载丰富历史底蕴",
+        "itemTitle3": "多人实时同屏互动,听专家讲述文化故事",
+        "itemTitle4": "推动社科教育宣传,助力历史文化传播"
+    },
+    "conductShop": {
+        "bannerTitle": "看店 • 宅家中 云逛街 轻松买",
+        "itemTitle1": "3D数字化商圈沉浸式购物新体验",
+        "itemTitle2": "真实复刻空间手机一点就逛",
+        "itemTitle3": "汇聚线上客流拉动线下经济",
+        "itemTitle4": "私人专属客服 同屏带看实时沟通"
+    },
+    "conductSecury": {
+        "bannerTitle": "安防勘查",
+        "itemTitle1": "高效复刻灾害现场,记录全面三维档案",
+        "itemTitle2": "可将现场说明直接添加至三维空间中,提高沟通质量与工作效率",
+        "itemTitle3": "支持预先采集存档,减少理赔纠纷"
+    }
+}

+ 33 - 18
pc/src/lang/zh/modules/header.js

@@ -1,20 +1,35 @@
 module.exports = {
-  core_product: '核心产品',
-  solutions: '行业解决方案',
-  kankan_space: '看看空间',
-  core_tech: '核心技术',
-  service: '服务支持',
-  about: '关于我们',
-  online_shop: '在线商城',
-  solutionsHouse: '房产营销',
-  solutionsExi: '线上展会',
-  solutionsSubject: '数字文博',
-  solutionsShop: 'VR购物',
-  solutionsSec: '安防勘察',
-  serviceApp: 'APP下载',
-  serviceUse: '使用教程',
-  serviceBaoxiu: '保修条例',
-  serviceVideo: '视频教程',
-  aboutNews: '新闻资讯',
-  aboutAgent: '成为经销商'
+    "core_product": "核心产品",
+    "solutions": "行业解决方案",
+    "kankan_space": "看看空间",
+    "core_tech": "核心技术",
+    "service": "服务支持",
+    "about": "关于我们",
+    "online_shop": "在线商城",
+    "solutionsHouse": "房产营销",
+    "solutionsExi": "线上展会",
+    "solutionsSubject": "数字文博",
+    "solutionsShop": "VR购物",
+    "solutionsSec": "安防勘察",
+    "serviceApp": "APP下载",
+    "serviceUse": "使用教程",
+    "serviceBaoxiu": "保修条例",
+    "serviceVideo": "视频教程",
+    "aboutNews": "新闻资讯",
+    "aboutAgent": "成为经销商",
+    "aboutCompany": "公司介绍",
+    mallPro: '四维看看Pro',
+    mallPeijian: '精选配件',
+    addService: '增值服务',
+    "footer": {
+        "bannerTitle": "四维看看,让空间讲故事",
+        "find": "发现精彩",
+        "saleEmail": "销售合作",
+        "meitiEmail": "媒体采访",
+        "phone": "联系电话",
+        "find4D": "探索四维",
+        "kankan": "四维时代",
+        "zhongde": "中德人工智能研究院",
+        "moku": "四维模库"
+    }
 }

+ 49 - 44
pc/src/lang/zh/modules/home.js

@@ -1,45 +1,50 @@
-const header = require('./header')
-module.exports =  {
-  bannerText: '精准实景复刻 传递空间价值',
-  bannerBuyBtnText: '立即购买',
-  bannerMoreBtn: '了解更多',
-  bannerIntroVideo: '介绍视频',
-  bannerAgent: '成为经销商',
-  plate1Title: '行业解决方案',
-  plate2Title: header.kankan_space,
-  plate3Title: header.core_tech,
-  plate4Title: '新闻动态',
-  plate5Title: '合作伙伴',
-  plate1Item1: header.solutionsHouse,
-  plate1Item2: header.solutionsExi,
-  plate1Item3: header.solutionsSubject,
-  plate1Item4: header.solutionsShop,
-  plate1Item5: header.solutionsSec,
-  plate1Item1SubTitle: '海量复刻真房源',
-  plate1Item1Desc1: 'AI自动建模,高效复刻真实房源',
-  plate1Item1Desc2: '云带看/云讲房,全方位介绍房源信息',
-  plate1Item1Desc3: '易上手操作,人人都能掌握拍摄流程',
-  plate1Item1Desc4: '专业地产营销系统,高效管理租售信息',
-  plate1Item2SubTitle: '全方位复现展会信息,全球买家在线看展',
-  plate1Item2Desc1: 'AI图像重构技术,真实还原线下布展效果',
-  plate1Item2Desc2: '3D展品互动,720°无死角展示',
-  plate1Item2Desc3: '同屏在线洽谈,系统可对接供采信息',
-  plate1Item2Desc4: '自动收集展会数据,数据分析挖掘,降低获客成本',
-  plate1Item3SubTitle: '助力打造永不落幕的博物馆',
-  plate1Item3Desc1: '珍贵陈展3D高清记录,方便留存与保护',
-  plate1Item3Desc2: '空间交互,让空间表达更多历史内涵',
-  plate1Item3Desc3: '大师讲解,一带多同屏讲述文化故事',
-  plate1Item3Desc4: '推动社科教育,促进社会参与',
-  plate1Item4SubTitle: '海量复刻真房源',
-  plate1Item4Desc1: 'AI自动建模,高效复刻真实房源',
-  plate1Item4Desc2: '云带看/云讲房,全方位介绍房源信息',
-  plate1Item4Desc3: '易上手操作,人人都能掌握拍摄流程',
-  plate1Item4Desc4: '专业地产营销系统,高效管理租售信息',
-  plate1Item5SubTitle: '高效复刻灾害现场,记录全面三维档案',
-  plate1Item5Desc1: '高效复刻灾害现场,记录全面三维档案',
-  plate1Item5Desc2: '支持预先采集存档,减少理赔纠纷',
-  plate2Item1: '雍正故宫',
-  plate2Item2: '小米有品',
-  plate2Item3: '华发依山郡',
-  plate2Item4: '万豪酒店',
+module.exports = {
+    "bannerText": "精准实景复刻 传递空间价值",
+    "bannerBuyBtnText": "立即购买",
+    "bannerMoreBtn": "了解更多",
+    "bannerIntroVideo": "介绍视频",
+    "bannerAgent": "成为经销商",
+    "plate1Title": "行业解决方案",
+    "plate2Title": "看看空间",
+    "plate3Title": "核心技术",
+    "plate4Title": "新闻资讯",
+    "plate5Title": "合作伙伴",
+    "plate1Item1": "房产营销",
+    "plate1Item2": "线上展会",
+    "plate1Item3": "数字文博",
+    "plate1Item4": "VR购物",
+    "plate1Item5": "安防勘察",
+    "plate1Item1SubTitle": "海量复刻真房源",
+    "plate1Item1Desc1": "AI自动建模,高效复刻真实房源",
+    "plate1Item1Desc2": "云带看/云讲房,全方位介绍房源信息",
+    "plate1Item1Desc3": "易上手操作,人人都能掌握拍摄流程",
+    "plate1Item1Desc4": "专业地产营销系统,高效管理租售信息",
+    "plate1Item2SubTitle": "全方位复现展会信息,全球买家在线看展",
+    "plate1Item2Desc1": "AI图像重构技术,真实还原线下布展效果",
+    "plate1Item2Desc2": "3D展品互动,720°无死角展示",
+    "plate1Item2Desc3": "同屏在线洽谈,系统可对接供采信息",
+    "plate1Item2Desc4": "自动收集展会数据,数据分析挖掘,降低获客成本",
+    "plate1Item3SubTitle": "助力打造永不落幕的博物馆",
+    "plate1Item3Desc1": "珍贵陈展3D高清记录,方便留存与保护",
+    "plate1Item3Desc2": "空间交互,让空间表达更多历史内涵",
+    "plate1Item3Desc3": "大师讲解,一带多同屏讲述文化故事",
+    "plate1Item3Desc4": "推动社科教育,促进社会参与",
+    "plate1Item4SubTitle": "海量复刻真房源",
+    "plate1Item4Desc1": "AI自动建模,高效复刻真实房源",
+    "plate1Item4Desc2": "云带看/云讲房,全方位介绍房源信息",
+    "plate1Item4Desc3": "易上手操作,人人都能掌握拍摄流程",
+    "plate1Item4Desc4": "专业地产营销系统,高效管理租售信息",
+    "plate1Item5SubTitle": "高效复刻灾害现场,记录全面三维档案",
+    "plate1Item5Desc1": "高效复刻灾害现场,记录全面三维档案",
+    "plate1Item5Desc2": "支持预先采集存档,减少理赔纠纷",
+    "plate2Item1": "雍正故宫",
+    "plate2Item2": "小米有品",
+    "plate2Item3": "华发依山郡",
+    "plate2Item4": "万豪酒店",
+    "plate3Item1Title": "空间数字化",
+    "plate3Item1Text": "自动化三维数字重建 还原空间布局与结构",
+    "plate3Item2Title": "空间互动",
+    "plate3Item2Text": "自动导览 互动视频多形态动态热点",
+    "plate3Item3Title": "空间展示",
+    "plate3Item3Text": "无需插件,多段展示实现720°沉浸体验"
 }

+ 14 - 0
pc/src/lang/zh/modules/kankanSpace.js

@@ -0,0 +1,14 @@
+module.exports = {
+    "title": "看看空间",
+    "typeAll": "全部",
+    "typeHouse": "房地产",
+    "typeExihibition": "会展",
+    "typeSubject": "博物馆",
+    "typeShop": "电商",
+    "typeFoot": "餐饮",
+    "typeOther": "其它",
+    "recommend": "精品推荐",
+    "hot": "热门浏览",
+    "new": "最新发布",
+    "placeholder": "输入搜索关键字"
+}

+ 23 - 0
pc/src/lang/zh/modules/login.js

@@ -0,0 +1,23 @@
+module.exports = {
+  login: '登录',
+  register: '注册',
+  userLogin: '用户登录',
+  cameraLogin: '相机登录',
+  codeLogin: '验证码登录',
+  phonePlaceholder: '请输入手机号码',
+  passwordPlaceholder: '请输入密码',
+  codePlaceholder: '请输入验证码',
+  sendCodeBtnText: '获取验证码',
+  rememberPassword: '记住密码',
+  forgetPassword: '忘记密码',
+  registerAccount: '账号注册',
+  cameraLoginTip: '打开四维看看app扫一扫登录',
+  kankanAccountRegister: '四维账号注册',
+  setPassword: '设置密码',
+  rePassword: '重复密码',
+  cluse: '我已阅读并同意四维看看用户协议',
+  findPassword: '找回密码',
+  emailPlaceholder: '邮箱地址',
+  hasAccount: '已有账号,',
+  zhijieLogin: '直接登录'
+}

+ 16 - 0
pc/src/lang/zh/modules/mall.js

@@ -0,0 +1,16 @@
+module.exports = {
+    "postage": "运费:顺丰包邮",
+    "baseVolume": "包含基础云容量",
+    "knowMore": "了解详情",
+    "standard": "标准套餐",
+    "addCou": "增值套餐(包含三脚架)",
+    "count": "数量",
+    "couTip": "是否需要添加推荐的配件(标准套餐不含以下配件)",
+    "jiaojia": "四维看看Pro三脚架套装",
+    "jiaojiaDetail": "三脚架 + 滑轮 + 云台",
+    "cart": "加入购物车",
+    "fahuo": "预计3日内发货",
+    "product": "产品说明",
+    "techDetail": "技术参数",
+    "widthDetail": "尺寸参数"
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 74 - 0
pc/src/lang/zh/modules/news.js


+ 7 - 0
pc/src/lang/zh/modules/service.js

@@ -0,0 +1,7 @@
+module.exports = {
+    "title": "服务支持",
+    "mVideo": "视频教程",
+    "use": "使用教程",
+    "app": "APP下载",
+    "clause": "保修条款"
+}

+ 49 - 33
pc/src/page/cases/index.vue

@@ -2,9 +2,9 @@
 <div class="case-w">
   <div class="cases-header">
     <div class="container">
-      <h1>看看空间</h1>
+      <h1>{{ $t('kankanSpace.title') }}</h1>
       <ul class="cases-type-list">
-        <li class="cases-type-item" :class="{'is-active': $route.params.id === item.name}" v-for="item in types" :key="item.id" @click="$router.push(`/cases/${item.name}`)">{{ item.name }}</li>
+        <li class="cases-type-item" :class="{'is-active': caseType === item.id}" v-for="item in types" :key="item.id" @click="$router.push(`/cases/${item.name}`)">{{ item.name }}</li>
       </ul>
     </div>
   </div>
@@ -13,20 +13,23 @@
       <ul class="sub-types fl">
         <li class="sub-type-item" :class="{'is-active': sortActive === item.id}" v-for="item in sub_types" :key="item.name" @click="sortActive = item.id"><h-icon class="icon" :type="item.icon" />{{ item.name }}</li>
       </ul>
-      <div class="search fr">
-        <input type="text" placeholder="输入搜索关键字" v-model="searchKey" @keyup.enter="getData">
+      <!-- <div class="search fr">
+        <input type="text" :placeholder="$t('kankanSpace.placeholder')" v-model="searchKey" @keyup.enter="getData">
         <h-icon type="sousuo" class="icon" @click="getData"></h-icon>
-      </div>
+      </div> -->
     </div>
     <h-row :gutter="20">
       <h-col :span="6" v-for="(item,i) in scene" :key="i">
-        <card :data="item" ></card>
+        <div  class="card_active card" :style="{'animation-delay': i*0.1 + 's'}">
+          <card :data="item" ></card>
+        </div>
+        
       </h-col>
     </h-row>
   </div>
-  <div class="paging" :class="{pagingshow:total}">
+  <div class="paging" :class="{pagingshow:total}" v-if="scene.length > 0">
     <vcenter>
-      <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" />
+      <Paging @clickHandle="pageChange" :current="currentPage" :total="total" :equable="pageSize" :value="currentPage" />
     </vcenter>
   </div>
 </div>
@@ -38,7 +41,7 @@ import {mapState} from 'vuex'
 import vcenter from '@/components/vcenter'
 import card from '@/components/card'
 import Paging from '@/components/Paging'
-
+import { i18n } from '@/lang'
 let sceneSTYpe = {
   '全部': null,
   '四维看看 Lite': 1,
@@ -48,48 +51,48 @@ let sceneSTYpe = {
 const types = [
   {
     id: null,
-    name: '全部'
+    name: i18n.t('kankanSpace.typeAll')
   },
   {
     id: 2,
-    name: '房地产'
+    name: i18n.t('kankanSpace.typeHouse')
   },
   {
     id: 1,
-    name: '会展'
+    name: i18n.t('kankanSpace.typeExihibition')
   },
   {
     id: 4,
-    name: '博物馆'
+    name: i18n.t('kankanSpace.typeSubject')
   },
   {
     id: null,
-    name: '电商'
+    name: i18n.t('kankanSpace.typeShop')
   },
   {
     id: null,
-    name: '餐饮'
+    name: i18n.t('kankanSpace.typeFoot')
   },
   {
     id: 0,
-    name: '其它'
+    name: i18n.t('kankanSpace.typeOther')
   },
 ]
 
 const sub_types = [
   {
     icon: 'case_recommend',
-    name: '精品推荐',
+    name: i18n.t('kankanSpace.recommend'),
     id: 1
   },
   {
     icon: 'case_hot',
-    name: '热门浏览',
+    name: i18n.t('kankanSpace.hot'),
     id: 3
   },
   {
     icon: 'case_new',
-    name: '最新发布',
+    name: i18n.t('kankanSpace.new'),
     id: 2
   },
 ]
@@ -109,7 +112,7 @@ export default {
       sub_types,
       selectActive: false,
       total: 0,
-      pageSize: 12,
+      pageSize: 16,
       currentPage: 1,
       sortActive: 1,
       scene: [],
@@ -145,15 +148,14 @@ export default {
       this.getData()
     },
     langCases (newVal) {
-      this.caseType = newVal.typeName[this.$route.params.id] || this.langCases.typeName['房地产']
+      this.caseType = newVal.typeName[i18n.route.params.id] || this.langCases.typeName['房地产']
     },
     '$route.params.id': {
       deep: true,
       immediate: true,
       handler (newVal) {
-        console.log(types.filter(item => item.name === newVal)[0].id)
         this.currentPage = 1
-        this.caseType = types.filter(item => item.name === newVal)[0].id
+        this.caseType = types.filter(item => item.name === newVal)[0] ? types.filter(item => item.name === newVal)[0].id : null
         this.selectActive = false
         this.getData()
       }
@@ -162,6 +164,7 @@ export default {
   // 方法集合
   methods: {
     pageChange (data) {
+      console.log(data)
       this.currentPage = data
     },
     async getData () {
@@ -203,6 +206,18 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.case-w {
+  min-height: 80vh;
+}
+.card {
+  opacity: 0;
+}
+.card_active{
+  animation-fill-mode: forwards;
+  animation-name: bounceIn;
+  animation-duration:0.75s;
+  transition: bounceIn 0.3s;
+}
 .cases-header {
   height: 290px;
   width: 100%;
@@ -274,7 +289,7 @@ export default {
     text-align: center;
     margin-top: 10px;
   }
-  & /deep/ .layout a:not(:last-child) {
+  & /deep/ .layout a.page-item {
     margin: 10px 8px;
     font-size: 16px;
     display: inline-block;
@@ -285,9 +300,9 @@ export default {
     position: relative;
     transition: color 0.3s;
   }
-  & /deep/ .layout a:last-child {
+  & /deep/ .layout .next-page {
     position: relative;
-    top: -5px;
+    // top: -5px;
     display: -ms-inline-flexbox;
     display: inline-flex;
     -ms-flex-align: center;
@@ -295,24 +310,25 @@ export default {
     height: 22px;
     padding: 0 9.6px;
     padding: 0 0.6rem;
+    vertical-align: middle;
   }
-  & /deep/ .layout a:last-child::before,
-  & /deep/ .layout a:last-child::after {
+  & /deep/ .layout .next-page::before,
+  & /deep/ .layout .next-page::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 {
+  & /deep/ .layout a.page-item.active::after,
+  & /deep/ .layout a.page-item.active,
+  & /deep/ .layout a.page-item:hover,
+  & /deep/ .layout a.page-item:hover::after {
     color: #111111;
     transform: scaleX(1);
   }
 
-  & /deep/ .layout a:not(:last-child)::after {
+  & /deep/ .layout a.page-item::after {
     content: "";
     height: 3px;
     width: 140%;

+ 7 - 7
pc/src/page/cases/style.scss

@@ -147,14 +147,14 @@
     display: inline-block;
     opacity: 0;
   }
-  .card_active{
-    animation-fill-mode: forwards;
-    animation-name: bounceIn;
-    animation-duration:0.75s;
-    transition: bounceIn 0.3s;
-  }
+  
+}
+.card_active{
+  animation-fill-mode: forwards;
+  animation-name: bounceIn;
+  animation-duration:0.75s;
+  transition: bounceIn 0.3s;
 }
-
 .pagingshow{
   display: block;
 }

+ 5 - 5
pc/src/page/conduct/conductExhibition/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-display">
     <div class="banner">
-      <div class="container">看展 • 随时随地参展办展</div>
+      <div class="container">{{$t('conduct.conductExhibition.bannerTitle')}}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -24,22 +24,22 @@ export default {
     return {
       sequenceArr: [
         {
-          name: '在线逛展洽谈,名片即刻获取',
+          name: this.$t('conduct.conductExhibition.itemTitle1'),
           img: require('@/assets/images/refactor/conductExhibition/item-1.jpg'),
           runAnimation: true
         },
         {
-          name: '沟通畅通无阻,资讯一览无遗',
+          name: this.$t('conduct.conductExhibition.itemTitle2'),
           img: require('@/assets/images/refactor/conductExhibition/item-2.png'),
           runAnimation: true
         },
         {
-          name: '降低搭展成本,高效促进交易',
+          name: this.$t('conduct.conductExhibition.itemTitle3'),
           img: require('@/assets/images/refactor/conductExhibition/item-3.jpg'),
           runAnimation: true
         },
         {
-          name: '数据流量统计,用户画像分析',
+          name: this.$t('conduct.conductExhibition.itemTitle4'),
           img: require('@/assets/images/refactor/conductExhibition/item-4.jpg'),
           runAnimation: true
         }

+ 5 - 5
pc/src/page/conduct/conductHouse/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-house">
     <div class="banner">
-      <div class="container">看房 ‧ 海量复刻真房源</div>
+      <div class="container">{{ $t('conduct.conductHouse.bannerTitle') }}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -29,17 +29,17 @@ export default {
     return {
       sequenceArr: [
         {
-          name: 'AI自动建模,高效复刻真实房源',
+          name: this.$t('conduct.conductHouse.itemTitle1'),
           img: require('@/assets/images/online/house/item-1.jpg'),
           runAnimation: true
         },
         {
-          name: '房源资讯全方位展示,提高租售决策效率',
+          name: this.$t('conduct.conductHouse.itemTitle2'),
           img: require('@/assets/images/online/house/item-2.png'),
           runAnimation: true
         },
         {
-          name: '地产资讯多维展示,提高租售决策效率',
+          name: this.$t('conduct.conductHouse.itemTitle3'),
           img: [
             require('@/assets/images/online/house/item-3_1.jpg'),
             require('@/assets/images/online/house/item-3_2.jpg')
@@ -47,7 +47,7 @@ export default {
           runAnimation: true
         },
         {
-          name: '强大功能编辑后台,传递更多房源价值',
+          name: this.$t('conduct.conductHouse.itemTitle4'),
           img: require('@/assets/images/online/house/item-3.jpg'),
           runAnimation: true
         },

+ 4 - 4
pc/src/page/conduct/conductSecury/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-secury">
     <div class="banner">
-      <div class="container">安防勘查</div>
+      <div class="container">{{ $t('conduct.conductSecury.bannerTitle') }}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -24,17 +24,17 @@ export default {
     return {
       sequenceArr: [
         {
-          name: '高效复刻灾害现场,记录全面三维档案',
+          name: this.$t('conduct.conductSecury.itemTitle1'),
           img: require('@/assets/images/refactor/conductSecury/item-1.png'),
           runAnimation: true
         },
         {
-          name: '可将现场说明直接添加至三维空间中,提高沟通质量与工作效率',
+          name: this.$t('conduct.conductSecury.itemTitle2'),
           img: require('@/assets/images/refactor/conductSecury/item-2.png'),
           runAnimation: true
         },
         {
-          name: '支持预先采集存档,减少理赔纠纷',
+          name: this.$t('conduct.conductSecury.itemTitle3'),
           img: require('@/assets/images/refactor/conductSecury/item-3.png'),
           runAnimation: true
         }

+ 5 - 5
pc/src/page/conduct/conductShop/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-shop">
     <div class="banner">
-      <div class="container">看店 • 宅家中 云逛街 轻松买</div>
+      <div class="container">{{ $t('conduct.conductShop.bannerTitle') }}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -24,22 +24,22 @@ export default {
     return {
       sequenceArr: [
         {
-          name: '3D数字化商圈沉浸式购物新体验',
+          name: this.$t('conduct.conductShop.itemTitle1'),
           img: require('@/assets/images/refactor/conductShop/item-1.png'),
           runAnimation: true
         },
         {
-          name: '真实复刻空间手机一点就逛',
+          name: this.$t('conduct.conductShop.itemTitle2'),
           img: require('@/assets/images/refactor/conductShop/item-2.png'),
           runAnimation: true
         },
         {
-          name: '汇聚线上客流拉动线下经济',
+          name: this.$t('conduct.conductShop.itemTitle3'),
           img: require('@/assets/images/refactor/conductShop/item-3.png'),
           runAnimation: true
         },
         {
-          name: '私人专属客服 同屏带看实时沟通',
+          name: this.$t('conduct.conductShop.itemTitle4'),
           img: require('@/assets/images/refactor/conductShop/item-4.png'),
           runAnimation: true
         }

+ 5 - 5
pc/src/page/conduct/conductSubject/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-subject">
     <div class="banner">
-      <div class="container">文博·助力打造永不落幕的博物馆</div>
+      <div class="container">{{$t('conduct.conductSubject.bannerTitle')}}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -33,22 +33,22 @@ export default {
     return {
       sequenceArr: [
         {
-          name: '珍贵陈展线上复刻,打破线下时空限制',
+          name: this.$t('conduct.conductSubject.itemTitle1'),
           img: require('@/assets/images/online/subjects/item-1.png'),
           runAnimation: true
         },
         {
-          name: '空间交互形式多样,承载丰富历史底蕴',
+          name: this.$t('conduct.conductSubject.itemTitle2'),
           img: require('@/assets/images/online/subjects/item-2.png'),
           runAnimation: true
         },
         {
-          name: '多人实时同屏互动,听专家讲述文化故事',
+          name: this.$t('conduct.conductSubject.itemTitle3'),
           img: require('@/assets/images/online/subjects/item-3.png'),
           runAnimation: true
         },
         {
-          name: '推动社科教育宣传,助力历史文化传播',
+          name: this.$t('conduct.conductSubject.itemTitle4'),
           img: require('@/assets/images/online/subjects/item-4.png'),
           runAnimation: true
         }

+ 8 - 8
pc/src/page/coreProducts/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="core-products">
     <div class="banner">
-      <div class="container">核心产品</div>
+      <div class="container">{{ $t('conduct.coreProduct.bannerTitle') }}</div>
     </div>
     <div class="" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
@@ -23,37 +23,37 @@ export default {
     return {
       sequenceArr: [
         {
-          name: 'AI全自动精准建模,智能测距',
+          name: this.$t('conduct.coreProduct.itemTitle1'),
           img: 6,
           runAnimation: true
         },
         {
-          name: '720度8K画质,身临其境',
+          name: this.$t('conduct.coreProduct.itemTitle2'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: 'HDR模式平衡明暗区域曝光',
+          name: this.$t('conduct.coreProduct.itemTitle3'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: '球幕视频真人解说 打造沉浸视听体验',
+          name: this.$t('conduct.coreProduct.itemTitle4'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: '10分钟入门,快速掌握拍摄流程',
+          name: this.$t('conduct.coreProduct.itemTitle5'),
           img: 8,
           runAnimation: true
         },
         {
-          name: '10分钟全自动出结果,高效快速(约100㎡)',
+          name: this.$t('conduct.coreProduct.itemTitle6'),
           img: 9,
           runAnimation: true
         },
         {
-          name: '强大编辑后台,让空间延伸表达',
+          name: this.$t('conduct.coreProduct.itemTitle7'),
           img: 10,
           runAnimation: true
         }

+ 51 - 50
pc/src/page/distributor/index.vue

@@ -1,20 +1,20 @@
 <template>
   <div class="distributor-page">
     <div class="banner">
-      <div class="container">成为四维看看经销商</div>
+      <div class="container">{{ $t('agent.bannerTitle') }}</div>
     </div>
     <div class="container">
       <div class="plate">
-        <h1 class="common-title">四维看看经销商计划概述</h1>
+        <h1 class="common-title">{{ $t('agent.planTitle') }}</h1>
         <ul class="plan">
-          <li>四维时代独创的AI空间重构算法技术已屡获殊荣,并累计在全球范围采集超过30万个空间模型。</li>
-          <li>这种全新的空间记录方式正在逐步改变各行各业的业务模式(房地产、建筑、文博、旅游、新闻、保险理赔、刑侦记录等等)。</li>
-          <li>四维看看经销商计划诚邀各业界专业人士,参与到未来的“数字万物”的进程中,共同开拓市场,分享利润。</li>
-          <li>如果您对3D捕捉世界的想法很感兴趣,并愿将其纳入到您的事业规划中,这是一个绝佳的合作机会。</li>
+          <li>{{ $t('agent.planDesc1') }}</li>
+          <li>{{ $t('agent.planDesc2') }}</li>
+          <li>{{ $t('agent.planDesc3') }}</li>
+          <li>{{ $t('agent.planDesc4') }}</li>
         </ul>
       </div>
       <div class="plate">
-        <h1 class="common-title">成为增值经销商的好处</h1>
+        <h1 class="common-title">{{ $t('agent.advanTitle') }}</h1>
         <div class="benefit-w clear">
           <div class="benefit-item" v-for="(item, index) in benefits" :key="index">
             <div class="icon" :style="{backgroundImage: `url(${item.icon})`}"></div>
@@ -27,77 +27,77 @@
 
     <div class="form-plate">
       <div class="container">
-        <h1 class="common-title">成为四维看看经销商</h1>
+        <h1 class="common-title">{{ $t('agent.jinxiaoTitle') }}</h1>
         <h-row :gutter="96">
           <h-col :span="12">
             <div class="form">
-              <p class="form-title">公司信息</p>
+              <p class="form-title">{{ $t('agent.jinxiaoForm.companytitle') }}</p>
               <div class="form-item">
-                <p class="label">*公司注册名称</p>
-                <input type="text" v-model="form.name" placeholder="请输入公司注册名称">
+                <p class="label">*{{ $t('agent.jinxiaoForm.companyNameLabel') }}</p>
+                <input type="text" v-model="form.name" :placeholder="$t('agent.jinxiaoForm.companyNamePlaceholder')">
               </div>
               <div class="form-item">
-                <p class="label">*公司地址</p>
+                <p class="label">*{{ $t('agent.jinxiaoForm.addressLabel') }}</p>
                 <h-row :gutter="10">
                   <h-col :span="12">
-                    <input type="text" v-model="form.country" placeholder="国家">
+                    <input type="text" v-model="form.country" :placeholder="$t('agent.jinxiaoForm.addressPlaceholder1')">
                   </h-col>
                   <h-col :span="12">
-                    <input type="text" v-model="form.region" placeholder="地区">
+                    <input type="text" v-model="form.region" :placeholder="$t('agent.jinxiaoForm.addressPlaceholder2')">
                   </h-col>
                 </h-row>
-                <input type="text"  v-model="form.address" placeholder="请输入公司地址">
+                <input type="text"  v-model="form.address" :placeholder="$t('agent.jinxiaoForm.addressPlaceholder3')">
               </div>
               <div class="form-item">
-                <p class="label">是否有门店或企业网站</p>
+                <p class="label">{{ $t('agent.jinxiaoForm.storeLabel') }}</p>
                 <h-row :gutter="10">
                   <h-col :span="12">
-                    <div :class="`input ${form.type === 1 ? 'active' : ''}`" @click="form.type = 1">线下销售为主</div>
+                    <div :class="`input ${form.type === 1 ? 'active' : ''}`" @click="form.type = 1">{{ $t('agent.jinxiaoForm.storeType1') }}</div>
                   </h-col>
                   <h-col :span="12">
-                    <div  :class="`input ${form.type === 2 ? 'active' : ''}`" @click="form.type = 2">线上销售为主</div>
+                    <div  :class="`input ${form.type === 2 ? 'active' : ''}`" @click="form.type = 2">{{ $t('agent.jinxiaoForm.storeType2') }}</div>
                   </h-col>
                 </h-row>
-                <input type="text" v-model="form.storeAddress" :placeholder="`请输入${form.type === 1 ? '门店详细地址' : '企业网站网址'}`">
+                <input type="text" v-model="form.storeAddress" :placeholder="$t('agent.jinxiaoForm.storePlaceholder')">
               </div>
             </div>
           </h-col>
           <h-col :span="12"><div class="form">
-              <p class="form-title">申请人信息</p>
+              <p class="form-title">{{ $t('agent.jinxiaoForm.applytitle') }}</p>
               <div class="form-item">
                 <h-row :gutter="10">
                   <h-col :span="12">
-                    <p class="label">*</p>
-                    <input type="text"  v-model="form.surName" placeholder="">
+                    <p class="label">*{{ $t('agent.jinxiaoForm.applyNameXing') }}</p>
+                    <input type="text"  v-model="form.surName" :placeholder="$t('agent.jinxiaoForm.applyNamePlaceholder')">
                   </h-col>
                   <h-col :span="12">
-                    <p class="label">*</p>
-                    <input type="text"  v-model="form.userName" placeholder="">
+                    <p class="label">*{{ $t('agent.jinxiaoForm.applyNameMing') }}</p>
+                    <input type="text"  v-model="form.userName" :placeholder="$t('agent.jinxiaoForm.applyNamePlaceholder1')">
                   </h-col>
                 </h-row>
               </div>
               <div class="form-item" style="margin-bottom: 26px">
-                <p class="label">*职位</p>
-                <input type="text"  v-model="form.post" placeholder="">
+                <p class="label">*{{ $t('agent.jinxiaoForm.positionLabel') }}</p>
+                <input type="text"  v-model="form.post" :placeholder="$t('agent.jinxiaoForm.positionPlaceholder')">
               </div>
               <div class="form-item">
-                <p class="label">*电话</p>
+                <p class="label">*{{ $t('agent.jinxiaoForm.phoneLabel') }}</p>
                 <h-row :gutter="10">
                   <h-col :span="8">
                     <input type="text"  v-model="form.areaCode" placeholder="+86" value="+86">
                   </h-col>
                   <h-col :span="16">
-                    <input type="text"  v-model="form.phone" placeholder="请输入电话">
+                    <input type="text"  v-model="form.phone" :placeholder="$t('agent.jinxiaoForm.phonePlaceholder')">
                   </h-col>
                 </h-row>
               </div>
               <div class="form-item">
-                <p class="label">*电子邮箱</p>
-                <input type="text"  v-model="form.email" placeholder="请输入电子邮箱">
+                <p class="label">*{{ $t('agent.jinxiaoForm.emailLabel') }}</p>
+                <input type="text"  v-model="form.email" :placeholder="$t('agent.jinxiaoForm.emailPlaceholder')">
               </div>
             </div></h-col>
         </h-row>
-        <div class="submit-btn" @click="saveAduit">提交</div>
+        <div class="submit-btn" @click="saveAduit">{{ $t('agent.jinxiaoForm.submit') }}</div>
       </div>
     </div>
     
@@ -127,40 +127,40 @@ export default {
         storeAddress: ''
       },
       rules: {
-        name: [ { required: true, message: '请填写公司注册名称' } ],
-        address: [ { required: true, message: '请填写公司地址' } ],
-        country: [ { required: true, message: '请填写公司所在国家' } ],
-        region: [ { required: true, message: '请填写公司所在地区' } ],
-        userName: [ { required: true, message: '请填写姓氏' } ],
-        userName: [ { required: true, message: '请填写名字' } ],
-        post: [ { required: true, message: '请填写职位' } ],
-        phone: [ { required: true, message: '请填写手机号码' } ],
-        email: [ { required: true, message: '请填写联系邮箱' } ],
+        name: [ { required: true, message: this.$t('agent.jinxiaoForm.companyNamePlaceholder') } ],
+        address: [ { required: true, message: this.$t('agent.jinxiaoForm.addressPlaceholder3') } ],
+        country: [ { required: true, message: this.$t('agent.jinxiaoForm.addressPlaceholder1') } ],
+        region: [ { required: true, message: this.$t('agent.jinxiaoForm.addressPlaceholder2') } ],
+        userName: [ { required: true, message: this.$t('agent.jinxiaoForm.applyNamePlaceholder') } ],
+        userName: [ { required: true, message: this.$t('agent.jinxiaoForm.applyNamePlaceholder1') } ],
+        post: [ { required: true, message: this.$t('agent.jinxiaoForm.positionPlaceholder') } ],
+        phone: [ { required: true, message: this.$t('agent.jinxiaoForm.phonePlaceholder') } ],
+        email: [ { required: true, message: this.$t('agent.jinxiaoForm.emailPlaceholder') } ],
       },
       benefits: [
         {
-          name: '利润分成',
-          desc: '丰厚的利润分成',
+          name: this.$t('agent.advan.item1Title'),
+          desc: this.$t('agent.advan.item1Sub'),
           icon: require('@/assets/images/distributor/icon-1.png')
         },
         {
-          name: '专属客服',
-          desc: '提供专属的专业的销售与技术人员',
+          name: this.$t('agent.advan.item2Title'),
+          desc: this.$t('agent.advan.item2Sub'),
           icon: require('@/assets/images/distributor/icon-2.png')
         },
         {
-          name: '宣传资料',
-          desc: '定期更新的宣传视频及宣传案例',
+          name: this.$t('agent.advan.item3Title'),
+          desc: this.$t('agent.advan.item3Sub'),
           icon: require('@/assets/images/distributor/icon-3.png')
         },
         {
-          name: '店面布置',
-          desc: '支持店面必要的广告物料',
+          name: this.$t('agent.advan.item4Title'),
+          desc: this.$t('agent.advan.item4Sub'),
           icon: require('@/assets/images/distributor/icon-4.png')
         },
         {
-          name: '发展机会',
-          desc: '参与营销与科技大会的机会',
+          name: this.$t('agent.advan.item5Title'),
+          desc: this.$t('agent.advan.item5Sub'),
           icon: require('@/assets/images/distributor/icon-5.png')
         },
       ]
@@ -281,6 +281,7 @@ export default {
       color: #909090;
       &.active {
         color: #202020;
+        border-color: #1FE4DC;
       }
     }
   .submit-btn {

+ 14 - 12
pc/src/page/home2/index.vue

@@ -37,7 +37,7 @@
                 <ul>
                   <li v-for="(item, index) in item.list" :key="index">{{ item }}</li>
                 </ul>
-                <a href="javascript:;" class="more" @click="toMore(item)">更多 ></a>
+                <a href="javascript:;" class="more" @click="toMore(item)">{{ $t('common.more') }} ></a>
               </div>
             </div>
           </transition>
@@ -78,10 +78,10 @@
           <li class="news-item" v-for="(item, index) in plate05List" :key="index" @click="toNewsLink(item.link)">
             <div class="news-img" :style="{backgroundImage: `url(${item.img})`}"></div>
             <div class="news-info">
-              <p class="news-time">{{ item.time }}</p>
               <h5 class="news-title">{{ item.title }}</h5>
               <p class="news-content">{{ item.text }}</p>
               <div class="news-tag">{{ item.sub }}</div>
+              <p class="news-time">{{ item.time }}</p>
             </div>
           </li>
         </ul>
@@ -103,7 +103,7 @@ import vcenter from '@/components/vcenter'
 import number from '@/components/number'
 import sequence from '@/components/sequence'
 import {mapState} from 'vuex'
-import { News } from '@/config/newsData'
+import { News } from '@/../../common/data/newsData'
 export default {
   data () {
     return {
@@ -141,13 +141,15 @@ export default {
         desc: this.$t('home.plate1Item4SubTitle'),
         img: require('@/assets/images/home/solutions-shop.png'),
         list: [this.$t('home.plate1Item4Desc1'), this.$t('home.plate1Item4Desc2'), this.$t('home.plate1Item4Desc3'), this.$t('home.plate1Item4Desc4')],
+        link: '/conductShop'
       },
       {
-        title: this.$t('home.plate1Item4'),
-        title_sub: this.$t('home.plate1Item4'),
-        desc: this.$t('home.plate1Item4SubTitle'),
+        title: this.$t('home.plate1Item5'),
+        title_sub: this.$t('home.plate1Item5'),
+        desc: this.$t('home.plate1Item5SubTitle'),
         img: require('@/assets/images/home/solutions-sec.png'),
         list: [this.$t('home.plate1Item5Desc1'), this.$t('home.plate1Item5Desc2')],
+        link: '/conductSecury'
       }],
       space: [
         {
@@ -173,20 +175,20 @@ export default {
       ],
       plate04List: [
         {
-          title: '空间数字化',
-          desc: '自动化三维数字重建还原空间布局与结构',
+          title: this.$t('home.plate3Item1Title'),
+          desc: this.$t('home.plate3Item1Text'),
           imgUrl: require('@/assets/images/home/space_01.png'),
           value: 'type1'
         },
         {
-          title: '空间互动',
-          desc: '自动导览 互动视频多形态动态热点',
+          title: this.$t('home.plate3Item2Title'),
+          desc: this.$t('home.plate3Item2Text'),
           imgUrl: require('@/assets/images/home/space_02.png'),
           value: 'type2'
         },
         {
-          title: '空间展示',
-          desc: '无需插件,多端展示实现720°沉浸体验',
+          title: this.$t('home.plate3Item3Title'),
+          desc: this.$t('home.plate3Item3Text'),
           imgUrl: require('@/assets/images/home/space_03.png'),
           value: 'type3'
         }

+ 11 - 5
pc/src/page/home2/style.scss

@@ -104,7 +104,7 @@
           content: '';
           display: block;
           height: 1px;
-          width: 66px;
+          width: 100%;
           background: #fff;
           position: absolute;
           bottom: -1px;
@@ -180,7 +180,8 @@
     }
     .solution-intro {
       float: left;
-      padding: 43px 0 0 45px;
+      padding: 43px 10px 0 45px;
+      width: 540px;
     }
     h4 {
       font-size: 24px;
@@ -192,7 +193,8 @@
       padding-left: 20px;
     }
     li {
-      line-height:38px;
+      line-height: 20px;
+      margin-bottom: 16px;
       list-style: initial;
     }
     .more {
@@ -295,11 +297,15 @@
     }
   }
   .news-info {
-    padding: 20px 40px 26px;
+    padding: 20px 40px 37px;
     font-size: 14px;
+    position: relative;
   }
   .news-time {
-    color: #E60222;
+    color: #909090;
+    position: absolute;
+    right: 40px;
+    bottom: 37px;
   }
   .news-title {
     margin: 8px 0;

+ 4 - 2
pc/src/page/introtow/index.vue

@@ -1,7 +1,8 @@
 <template>
-  <div class="introduce-layout" v-show="split">
+  <div class="introduce-layout" >
     <div class="introduce-bg">
-      <div class="introduce-con" :style="{marginLeft:(split + 37)+'px'}">
+      <div class="container">
+        <div class="introduce-con" :style="{marginLeft:(split + 37)+'px'}">
         <div class="info">
           <p>设备ID:{{detail.childName}}</p>
         </div>
@@ -12,6 +13,7 @@
           <span>点数构成:{{detail.spaceContent}}</span>
         </div>
       </div>
+      </div>
     </div>
     <div class="plate02">
       <div>

+ 4 - 3
pc/src/page/layout/aside/index.vue

@@ -1,7 +1,7 @@
 <template>
 <div class="login-layout">
-  <div class="mask" :style="{maxHeight:active?'100%':'0'}">
-    <div v-show="openClause" class="user-clause" :class="{'cart-clause':cluseType==='cart'}">
+  <div class="mask" :style="{maxHeight: openClause ? '100%' : '0'}">
+    <div  class="user-clause" :class="{'cart-clause':cluseType==='cart'}">
       <div>
         <div class="clause-img" ref="clause">
           <div ref="clauseImg">
@@ -119,11 +119,12 @@ export default {
     background: rgba($color: #000000, $alpha: 0.8);
     .user-clause{
       z-index: 100000000;
-      width: calc(100% - 450px);
+      width: 70%;
       color: #fff;
       height: 100%;
       position: relative;
       text-align: center;
+      margin: 0 auto;
       >div{
         height: 85%;
         position: absolute;

+ 31 - 23
pc/src/page/layout/footer.vue

@@ -1,8 +1,8 @@
 <template>
   <div>
-    <div class="plate07">
-      <p>四维看看,让空间讲故事</p>
-      <div class="btn" @click="$router.push('/cases/全部')">发现精彩</div>
+    <div class="plate07" v-if="!$route.meta.hideFooterFind">
+      <p>{{ $t('header.footer.bannerTitle') }}</p>
+      <div class="btn" @click="toCase">{{ $t('header.footer.find') }}</div>
     </div>
     <div class="footer" :style="{position: 'relative'}" >
       <div class="layout container">
@@ -10,15 +10,15 @@
             <div class="infos-contact">
               <img src="@/assets/images/home/grey-logo.png" alt="logo" class="logo">
               <ul>
-                <li>销售合作:sales@4dage.com</li>
-                <li>媒体采访:pr@4dage.com</li>
-                <li>联系电话:400-669-8025</li>
+                <li>{{ $t('header.footer.saleEmail') }}:sales@4dage.com</li>
+                <li>{{ $t('header.footer.meitiEmail') }}:pr@4dage.com</li>
+                <li>{{ $t('header.footer.phone') }}:400-669-8025</li>
               </ul>
             </div>
             <div class="infos-list">
               <div class="infos-item" v-for="item in infosList" :key="item.title">
                 <h6>{{ item.title }}</h6>
-                <a v-for="i in item.list" :key="i.text"  target="_blank" :href="`${pathname}#/${i.link}`">{{ i.text }}</a>
+                <a v-for="i in item.list" :key="i.text"  target="_blank" :href="`${i.link.indexOf('http') > -1 ? i.link : `${pathname}#/${i.link}`}`">{{ i.text }}</a>
               </div>
             </div>
             <ul class="contacts-w">
@@ -45,8 +45,8 @@
             <a :href="language==='en'?'https://www.cgaii.com/en':'https://www.cgaii.com'" target="_blank">{{langFooter.cgaii}}</a>
             <a href="http://www.4dmodel.com/" target="_blank">{{langFooter.model}}</a>
           </div> -->
-          <p class="relevant-1">Copyright © 2018 4DAGE Co., Ltd. All rights reserved. </p>
-          <p class="relevant-2"><a class="a_class" href="http://www.beian.miit.gov.cn" target="_blank">粤ICP备14078495号-3</a></p>
+          <p class="relevant-1">Copyright © 2020 4DAGE Co., Ltd. All rights reserved. </p>
+          <p class="relevant-2"><a class="a_class">粤ICP备14078495号-3</a></p>
         </div>
       </div>
     </div>
@@ -64,60 +64,60 @@ export default {
       pathname: window.location.pathname,
       infosList: [
         {
-          title: '行业应用',
+          title: this.$t('header.solutions'),
           list: [
             {
-              text: '房产营销',
+              text: this.$t('header.solutionsHouse'),
               link: 'conductHouse'
             },
             {
-              text: '线上展会',
+              text: this.$t('header.solutionsExi'),
               link: 'conductExhibition'
             },
             {
-              text: '数字文博',
+              text: this.$t('header.solutionsSubject'),
               link: 'conductSubject'
             },
             {
-              text: 'VR购物',
+              text: this.$t('header.solutionsShop'),
               link: 'conductShop'
             },
             {
-              text: '安防勘察',
+              text: this.$t('header.solutionsSec'),
               link: 'conductSecury'
             }
           ]
         },
         {
-          title: '关于我们',
+          title: this.$t('header.about'),
           list: [
             {
-              text: '公司简介',
+              text: this.$t('header.aboutCompany'),
               link: 'about'
             },
             {
-              text: '新闻资讯',
+              text: this.$t('header.aboutNews'),
               link: 'news'
             },
             {
-              text: '成为经销商',
+              text: this.$t('header.aboutAgent'),
               link: 'distributor'
             }
           ]
         },
         {
-          title: '探索四维',
+          title: this.$t('header.footer.find4D'),
           list: [
             {
-              text: '四维时代',
+              text: this.$t('header.footer.kankan'),
               link: 'http://www.4dage.com/cn'
             },
             {
-              text: '中德人工智能研究院',
+              text: this.$t('header.footer.zhongde'),
               link: 'https://www.cgaii.com'
             },
             {
-              text: '四维模库',
+              text: this.$t('header.footer.moku'),
               link: 'http://www.4dmodel.com/'
             }
           ]
@@ -132,6 +132,12 @@ export default {
       langFooter: state => state.language.home.footer,
       language: state => state.language.current
     })
+  },
+  methods: {
+    toCase () {
+      this.$router.push('/cases/全部')
+      window.scrollTo({top: 0})
+    }
   }
 }
 </script>
@@ -140,6 +146,7 @@ export default {
   .a_class,.a_class:hover,.a_class:active{
     color: #fff;
     text-decoration: none;
+    cursor: initial;
   }
   .footer {
     padding-top: 76px 0 26px;
@@ -219,6 +226,7 @@ export default {
     min-width: 138px;
     h6 {
       margin-bottom: 27px;
+      color: #fff;
     }
     a {
       display: block;

+ 77 - 15
pc/src/page/layout/header/index.vue

@@ -1,10 +1,10 @@
 <template>
-  <div class="header-layout">
+  <div class="header-layout" :class="language === 'zh' ? '' : 'isInternational'">
     <div class="container clear">
       <div class="logo-layout">
         <router-link :to="{name: 'home'}" class="logo">
           <vcenter>
-            <img :src="language === 'en' ? `@/assets/images/home/logo-cn.png` : require('@/assets/images/home/logo-cn.png')" alt>
+            <img :src="language === 'en' ? `https://4dscene.oss-cn-shenzhen.aliyuncs.com/new4dkk/v2/img/%E7%BB%84%203802.png` : require('@/assets/images/home/logo-cn.png')" alt>
           </vcenter>
         </router-link>
       </div>
@@ -32,11 +32,23 @@
       <div class="ctrl">
         <div class="shop-btn" @click="$router.push({name: 'mallHome'})">{{ $i18n.t('header.online_shop')}}</div>
         <div class="language-w">
-          <span class="language en" :class="{'is-active': language === 'en'}">EN</span>
-          <span class="language" :class="{'is-active': language !== 'en'}">中</span>
+          <div class="list">
+            <a class="header-item">
+              <p class="guoqi" :style="{'background-image': `url(${languageObj.img})`}">{{ languageObj.name }}</p>
+              <ul class="child-list">
+                <li v-for="item in languageList" :key="item.name" :style="{'background-image': `url(${item.img})`}" @click="changeLanguage(item.value)">{{ item.name }}</li>
+              </ul>
+            </a>
+          </div>
+          <!-- <span class="language en" :class="{'is-active': language === 'en'}" @click="changeLanguage('en')">EN</span>
+          <span class="language" :class="{'is-active': language !== 'en'}" @click="changeLanguage('zh')">中</span> -->
         </div>
         <div class="user" @click="$router.push('/login/login')" v-if="!isLogin"></div>
-        <div class="user" v-else :style="{'background-image': `url(${info.head})`}" @click="$router.push('/information')"></div>
+        <div class="user avatar" v-else :style="{'background-image': `url(${info.head})`}" @click="$router.push('/information')"></div>
+        <div class="cart" @click="$router.push('/mall/cart')">
+          <h-icon type="xingouwuche" class="icon" />
+          <span v-if="cartCount">{{cartCount}}</span>
+        </div>
       </div>
     </div>
   </div>
@@ -108,6 +120,10 @@ export default {
         ]},
         {text: this.$t('header.about'),  items: [
           {
+            text: this.$t('header.aboutCompany'),
+            link: '/about'
+          },
+          {
             text: this.$t('header.aboutNews'),
             link: '/news'
           },
@@ -115,10 +131,7 @@ export default {
             text: this.$t('header.aboutAgent'),
             link: '/distributor'
           },
-          {
-            text: this.$t('header.about'),
-            link: '/about'
-          }
+          
         ]}
       ]
     }
@@ -137,18 +150,39 @@ export default {
       }
       this.$router.push({path: nav.link})
     },
+    changeLanguage (lang) {
+      this.$store.commit('change_language', lang)
+      location.reload()
+    }
   },
   computed: {
     ...mapState({
       language: state => state.language.current,
       isLogin: state => state.user.token,
       info: state => state.user.info,
-      deviceLogin: state => state.user.deviceLogin
-    })
+      deviceLogin: state => state.user.deviceLogin,
+      languageList: state => state.language.languageList,
+      isInternational: state => state.user.isInternational
+    }),
+    languageObj () {
+      return this.languageList.find(item => item.value === this.language)
+    },
+    cartCount () {
+      let cart = this.$store.state.user.cart || []
+      if (typeof cart === 'string') {
+        cart = JSON.parse(cart)
+      }
+      let count = 0
+      cart.forEach(item => {
+        count += item.goodsCount
+      })
+      return count > 99 ? 99 : count
+    }
   },
   mounted () {
-    let lang = ~this.browserLang.indexOf('zh') ? '中' : 'en'
-    this.$store.commit('change_language', lang)
+    // let lang = ~this.browserLang.indexOf('zh') ? 'zh' : 'en'
+    // console.log(lang)
+    // this.$store.commit('change_language', lang)
     if (this.isLogin && !this.deviceLogin) {
       let cart = this.$store.state.user.cart
       if (typeof cart === 'string') {
@@ -175,14 +209,40 @@ export default {
 
 <style lang="scss" scoped>
 @import "./istyle.scss";
+.language-w {
+  .header-item {
+    margin-right: 20px !important;
+    p {
+      color: #202020;
+      font-size: 14px;
+      font-weight: normal;
+      padding-left: 28px;
+      background: url(~@/assets/images/home/China.png) no-repeat left center;
+      background-size: 20px 14px;
+    }
+  }
+  .child-list {
+    background: #fff;
+    li {
+      color: #202020;
+      font-size: 14px;
+      font-weight: normal;
+      padding: 0 13px 0 40px;
+      background: url(~@/assets/images/home/China.png) no-repeat 13px center;
+      background-size: 20px 14px;
+    }
+  }
+}
+
 .header-item:hover {
+  position: relative;
   .child-list {
     display: block;
   }
 }
 .child-list {
   position: absolute;
-  width: 112px;
+  // width: 112px;
   box-shadow: 0px -2px 6px rgba(113,113,113,0.16);
   margin-top: -10px;
   left: 50%;
@@ -216,8 +276,10 @@ export default {
     position: relative;
     background: #fff;
     z-index: 2;
+    padding: 0 25px;
+    white-space: nowrap;
     &:hover {
-      background: #EBEBEB;
+      background-color: #EBEBEB;
     }
   }
 }

+ 67 - 36
pc/src/page/layout/header/istyle.scss

@@ -36,16 +36,23 @@
     height: 100%;
     .logo {
       position: relative;
-      width: 150px;
+      width: 154px;
       height: 100%;
       display: inline-block;
       color: #fff;
+      // img {
+      //   width: 100%;
+      // }
+    }
+  }
+  &.isInternational {
+    .menu {
+      min-width: 740px;
     }
   }
-
   .menu {
     float: left;
-    min-width: 600px;
+    min-width: 650px;
 
     .lang {
       box-sizing: border-box;
@@ -68,47 +75,45 @@
         color: #fff;
       }
     }
+  }
+  .list {
+    justify-content: space-between;
+    height: 100%;
+    display: flex;
+    a {
+      display: inline-block;
+      line-height: 80px;
+      // margin-right: 47px;
+      font-size: 16px;
+      text-decoration: none;
+      font-weight: bold;
+      position: relative;
+      transition: color $mc;
 
-    .list {
-      justify-content: space-between;
-      height: 100%;
-      a {
-        display: inline-block;
-        line-height: 80px;
-        margin-right: 47px;
-        font-size: 16px;
-        text-decoration: none;
-        font-weight: bold;
-        position: relative;
-        transition: color $mc;
-
-        &::before {
-          z-index: 2;
-        }
-
-        &.active {
-          color: #727272;
+      &::before {
+        z-index: 2;
+      }
 
-          &::after {
-            border-top-color: #727272;
-            transform: translateY(-50%) scale(1.3);
-          }
+      &.active {
+        color: #727272;
 
-          &::before {
-            transform: translateY(-50%) scale(0.7);
-            border-top-color: #000;
-          }
+        &::after {
+          border-top-color: #727272;
+          transform: translateY(-50%) scale(1.3);
         }
 
+        &::before {
+          transform: translateY(-50%) scale(0.7);
+          border-top-color: #000;
+        }
       }
+
     }
   }
-
   .ctrl {
     align-items: center;
     font-size: 16px;
     float: right;
-    padding: 20px 0;
     &>div {
       display: inline-block;
       vertical-align: middle;
@@ -120,17 +125,16 @@
       background-color: #1FE4DC;
       text-align: center;
       font-weight: 600;
-      margin-right: 25px;
+      margin-right: 20px;
     }
     .country {
       width: 20px;
       height: 21px;
       display: inline-block;
-      background: url(~@/assets/images/home/CHINA.png) no-repeat center center;
+      background: url(~@/assets/images/home/China.png) no-repeat center center;
       vertical-align: middle;
     }
     .language-w {
-      padding: 0 30px  0 10px;
     }
     .language {
       margin: 0 15px 0 0;
@@ -148,11 +152,38 @@
       height: 20px;
       background: url(~@/assets/images/home/account-icon.png) no-repeat center center;
       cursor: pointer;
-      background-size: contain;
+      background-size: cover;
+      &.avatar {
+        width: 32px;
+        height: 32px;
+        border-radius: 50%;
+      }
     }
   }
 
 }
+.cart {
+  color: #202020;
+  margin-left: 18px;
+  cursor: pointer;
+  position: relative;
+  .icon {
+    font-size: 26px;
+  }
+  span {
+    display: block;
+    position: absolute;
+    right: 0;
+    top: 0;
+    font-size: 12px;
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    text-align: center;
+    background: #1FE4DC;
+    border-radius: 50%;
+  }
+}
 
 @media screen and (max-width: 1600px){
 }

+ 79 - 24
pc/src/page/layout/shopHeader/index.vue

@@ -4,7 +4,7 @@
       <div class="logo-layout">
         <router-link :to="{name: 'home'}" class="logo">
           <vcenter>
-            <img :src="language === 'en' ? `@/assets/images/home/logo-cn.png` : require('@/assets/images/home/logo-cn.png')" alt>
+            <img :src="language === 'en' ? `https://4dscene.oss-cn-shenzhen.aliyuncs.com/new4dkk/v2/img/%E7%BB%84%203802.png` : require('@/assets/images/home/logo-cn.png')" alt>
           </vcenter>
         </router-link>
       </div>
@@ -32,11 +32,17 @@
       <div class="ctrl">
         <div class="shop-btn" @click="$router.push({name: 'mallHome'})">{{ $i18n.t('header.online_shop')}}</div>
         <div class="language-w">
-          <span class="language en" :class="{'is-active': language === 'en'}">EN</span>
-          <span class="language" :class="{'is-active': language !== 'en'}">中</span>
+          <div class="list">
+            <a class="header-item">
+              <p class="guoqi" :style="{'background-image': `url(${languageObj.img})`}">{{ languageObj.name }}</p>
+              <ul class="child-list">
+                <li v-for="item in languageList" :key="item.name" :style="{'background-image': `url(${item.img})`}" @click="changeLanguage(item.value)">{{ item.name }}</li>
+              </ul>
+            </a>
+          </div>
         </div>
         <div class="user" @click="$router.push('/login/login')" v-if="!isLogin"></div>
-        <div class="user" v-else :style="{'background-image': `url(${info.head})`}" @click="$router.push('/information')"></div>
+        <div class="user avatar" v-else :style="{'background-image': `url(${info.head})`}" @click="$router.push('/information')"></div>
         <div class="cart" @click="$router.push('/mall/cart')">
           <h-icon type="xingouwuche" class="icon" />
           <span v-if="cartCount">{{cartCount}}</span>
@@ -65,28 +71,28 @@ export default {
       isWide,
       count: 0,
       navs: [
-        { text: '四维看看Pro', link: '/mall/kankanPro' },
-        { text: '精选配件', link: '/mall/zhijia' },
-        { text: '增值服务', link: '/mall/cloudCapacity' },
-        { text: '行业应用', items: [
+        { text: this.$t('header.mallPro'), link: '/mall/kankanPro' },
+        { text: this.$t('header.mallPeijian'), link: '/mall/zhijia' },
+        { text: this.$t('header.addService'), link: '/mall/cloudCapacity' },
+        { text: this.$t('header.solutions'), items: [
           {
-            text: '房产营销',
+            text: this.$t('header.solutionsHouse'),
             link: '/conductHouse'
           },
           {
-            text: '线上展会',
+            text: this.$t('header.solutionsExi'),
             link: '/conductExhibition'
           },
           {
-            text: '数字文博',
+            text: this.$t('header.solutionsSubject'),
             link: '/conductSubject'
           },
           {
-            text: 'VR购物',
+            text: this.$t('header.solutionsShop'),
             link: '/conductShop'
           },
           {
-            text: '安防勘察',
+            text: this.$t('header.solutionsSec'),
             link: '/conductSecury'
           },
         ]},
@@ -108,6 +114,10 @@ export default {
     },
     toNav (nav) {
       this.$router.push({path: nav.link})
+    },
+    changeLanguage (lang) {
+      this.$store.commit('change_language', lang)
+      location.reload()
     }
   },
   computed: {
@@ -117,8 +127,12 @@ export default {
       split: state => state.ui.navDivision,
       isLogin: state => state.user.token,
       info: state => state.user.info,
-      deviceLogin: state => state.user.deviceLogin
+      deviceLogin: state => state.user.deviceLogin,
+      languageList: state => state.language.languageList,
     }),
+    languageObj () {
+      return this.languageList.find(item => item.value === this.language)
+    },
     cartCount () {
       let cart = this.$store.state.user.cart || []
       if (typeof cart === 'string') {
@@ -132,8 +146,6 @@ export default {
     }
   },
   mounted () {
-    let lang = ~this.browserLang.indexOf('zh') ? '中' : 'en'
-    this.$store.commit('change_language', lang)
     this.$bus.$on('hadload', data => {
       this.$store.commit('change_nav_division', getPosition(this.$refs.list).x)
     })
@@ -153,6 +165,32 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.language-w {
+  .header-item {
+    margin-right: 20px !important;
+    display: inline-block;
+    p {
+      color: #202020;
+      font-size: 14px;
+      font-weight: normal;
+      padding-left: 28px;
+      background: url(~@/assets/images/home/China.png) no-repeat left center;
+      background-size: 20px 14px;
+    }
+  }
+  .child-list {
+    background: #fff;
+    li {
+      color: #202020;
+      font-size: 14px;
+      font-weight: normal;
+      padding: 0 13px 0 40px;
+      background: url(~@/assets/images/home/China.png) no-repeat 13px center;
+      background-size: 20px 14px;
+    }
+  }
+}
+
 .header-layout {
   $mc: .5s cubic-bezier(.77, 0, .175, 1);
   $ts: all $mc;
@@ -224,7 +262,9 @@ export default {
       }
     }
 
-    .list {
+    
+  }
+  .list {
       justify-content: space-between;
       height: 100%;
       a {
@@ -258,13 +298,10 @@ export default {
 
       }
     }
-  }
-
   .ctrl {
     align-items: center;
     font-size: 16px;
     float: right;
-    padding: 20px 0;
     &>div {
       display: inline-block;
       vertical-align: middle;
@@ -283,13 +320,19 @@ export default {
       width: 20px;
       height: 21px;
       display: inline-block;
-      background: url(~@/assets/images/home/CHINA.png) no-repeat center center;
+      background: url(~@/assets/images/home/China.png) no-repeat center center;
       vertical-align: middle;
     }
+    .language-w {
+      // padding: 0 30px  0 10px;
+    }
     .language {
-      margin: 0 18px 0 15px;
+      margin: 0 15px 0 0;
       color: #8F8F8F;
+      cursor: pointer;
       vertical-align: middle;
+      font-size: 16px;
+      font-weight: 600;
       &.is-active {
         color: #202020;
       }
@@ -299,6 +342,12 @@ export default {
       height: 20px;
       background: url(~@/assets/images/home/account-icon.png) no-repeat center center;
       cursor: pointer;
+      background-size: cover;
+      &.avatar {
+        width: 32px;
+        height: 32px;
+        border-radius: 50%;
+      }
     }
     .cart {
       color: #202020;
@@ -326,13 +375,14 @@ export default {
 
 }
 .header-item:hover {
+  position: relative;
   .child-list {
     display: block;
   }
 }
 .child-list {
   position: absolute;
-  width: 112px;
+  // width: 112px;
   box-shadow: 0px -2px 6px rgba(113,113,113,0.16);
   margin-top: -10px;
   left: 50%;
@@ -341,6 +391,9 @@ export default {
   display: none;
   transition: all linear 0.5s;
   padding-top: 6px;
+  white-space: nowrap;
+  
+  background: #fff;
   &::before {
     position: absolute;
     display: block;
@@ -366,8 +419,10 @@ export default {
     position: relative;
     background: #fff;
     z-index: 2;
+    width: 100%;
+    padding: 0 25px;
     &:hover {
-      background: #EBEBEB;
+      background-color: #EBEBEB;
     }
   }
 }

+ 13 - 13
pc/src/page/location/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="conduct-tech" ref="container">
     <div class="banner">
-      <div class="container">核心技术</div>
+      <div class="container">{{ $t('conduct.coreTech.bannerTitle') }}</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i" id="type1">
@@ -14,8 +14,8 @@
       </div>
       <div class="plate item"  id="type2">
         <div class="container">
-          <h2 class="common-title">空间互动</h2>
-          <p class="desc">自动导览 预先设定路线,球幕视频 BOX视频 增强体验的互动效果,多形式动态热点 赋以空间说话的艺术。</p>
+          <h2 class="common-title">{{ $t('conduct.coreTech.itemTitle2') }}</h2>
+          <p class="desc">{{ $t('conduct.coreTech.itemText2') }}</p>
           <div class="plate-content clear">
             <div class="content-left fl">
               <ul>
@@ -32,8 +32,8 @@
       </div>
       <div class="plate item"  id="type3">
         <div class="container">
-          <h2 class="common-title">空间展示</h2>
-          <p class="desc">无需插件,可在手机、 平板、PC端、VR眼镜,实现720°沉浸式漫游体验。</p>
+          <h2 class="common-title">{{ $t('conduct.coreTech.itemTitle3') }}</h2>
+          <p class="desc">{{ $t('conduct.coreTech.itemText3') }}</p>
           <div class="plate-content clear">
             <h-row :gutter="40">
               <h-col :span="8" v-for="(item, index) in items_3" :key="index">
@@ -61,8 +61,8 @@ export default {
       activeIndex: 0,
       sequenceArr: [
         {
-          name: '空间数字化',
-          desc: '记录与计算相机在拍摄时的空间位置,并提取对应的3D点云,从而获取三维空间的真实情况。',
+          name: this.$t('conduct.coreTech.itemTitle1'),
+          desc: this.$t('conduct.coreTech.itemText1'),
           // img: require('@/assets/images/refactor/coreTech/item-1.png'),
           video: require('@/assets/images/refactor/coreTech/AI AR SLAM 01(剪辑版2).mp4'),
           runAnimation: true
@@ -70,29 +70,29 @@ export default {
       ],
       items_2: [
         {
-          name: '动态热点',
+          name: this.$t('conduct.coreTech.item2Name1'),
           img: require('@/assets/images/refactor/coreTech/item-2_1.png')
         },
         {
-          name: '互动视频',
+          name: this.$t('conduct.coreTech.item2Name2'),
           img: ''
         },
         {
-          name: '自动导览',
+          name: this.$t('conduct.coreTech.item2Name3'),
           img: ''
         },
       ],
       items_3: [
         {
-          name: 'VR端',
+          name: this.$t('conduct.coreTech.item3Name1'),
           img: require('@/assets/images/refactor/coreTech/item-3_1.png')
         },
         {
-          name: '网页端',
+          name: this.$t('conduct.coreTech.item3Name2'),
           img: require('@/assets/images/refactor/coreTech/item-3_2.png')
         },
         {
-          name: '移动端',
+          name: this.$t('conduct.coreTech.item3Name3'),
           img: require('@/assets/images/refactor/coreTech/item-3_3.png')
         },
       ]

+ 12 - 8
pc/src/page/login/components/cameraLogin.vue

@@ -45,17 +45,18 @@ export default {
             this.$store.commit('DEVICELOGIN', childName)
             this.$router.replace({name: 'scene'})
           } else {
-            this.$bus.$emit('hasLogin')
             this.$store.commit('DEVICELOGIN', '')
             this.$store.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
             this.$store.dispatch('getCart')
+            this.$bus.$emit('hasLogin')
+            const from = this.$route.query.from
+            if (from) {
+              this.$router.push(from)
+            } else {
+              this.$router.push('/')
+            }
           }
-          const from = this.$route.query.from
-          if (from) {
-            this.$router.push(from)
-          } else {
-            this.$router.push('/')
-          }
+          
           return false
         }
       }, 3000)
@@ -69,7 +70,8 @@ export default {
 </script>
 <style lang="scss" scoped>
 .camera-login {
-  padding: 0 17px 40px;
+  padding: 0 17px 56px;
+  // height: 486px;
   &>div {
     display: inline-block;
     vertical-align: middle;
@@ -85,6 +87,8 @@ export default {
     padding: 6 10px;
     font-weight: bold;
     line-height: 20px;
+    
+    letter-spacing: 2px;
   }
 }
 </style>

+ 23 - 7
pc/src/page/login/components/codeLogin.vue

@@ -1,14 +1,14 @@
 <template>
-  <div class="account-login">
+  <div class="account-login code-login">
     <div class="phone-w">
       <div class="phone-input-w">
         <div class="phone-area" @click.stop="showPhoneArea=!showPhoneArea">{{ `${selectArea[1]}(${selectArea[0]})` }}</div>
-        <input type="text" v-model="loginForm.phone" >
+        <input type="text" v-model="loginForm.phone" placeholder="请输入手机号" >
       </div>
       <phoneAddressSelect v-show="showPhoneArea" @select="changeArea" />
     </div>
     <div class="code-w">
-      <input v-model="loginForm.authCode" class="input password" placeholder="短信验证码">
+      <input v-model="loginForm.authCode" class="input password" placeholder="请输入验证码" @keyup.enter="login">
       <div class="code-btn" :class="{'is-disabled': sendCodeExTime}" @click="sendCode">{{ sendCodeExTime ? `${sendCodeExTime}s后重新发送` : '获取验证码' }}</div>
     </div>
     
@@ -17,15 +17,15 @@
     </div>
     <div class="login-btn" @click="login">登录</div>
     <div class="others">
-      <a class="other-actions" @click="toOtherLogin('camera')">忘记密码</a>
-      <a class="other-actions" href="">账号注册</a>
+      <a class="other-actions" @click="$router.push('/login/forget')">忘记密码</a>
+      <a class="other-actions" @click="$router.push('/login/register')">账号注册</a>
     </div>
   </div>
 </template>
 
 <script>
 import phoneAddressSelect from '@/components/common/phoneAddressSelect'
-
+import { mapState } from 'vuex'
 let timer
 export default {
   data () {
@@ -39,6 +39,11 @@ export default {
   components: {
     phoneAddressSelect
   },
+  computed: {
+    ...mapState({
+      langToast: state => state.language.home.toast
+    }),
+  },
   methods: {
     changeArea (item) {
       this.selectArea = item
@@ -65,7 +70,8 @@ export default {
       let check = value => {
         for (let i = 0, len = value.length; i < len; i++) {
           if (!value[i].val) {
-            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            return
           }
         }
         return true
@@ -175,4 +181,14 @@ export default {
     }
   }
 }
+</style>
+
+<style lang="less">
+.code-login {
+  .phone-address {
+    left: 38px !important;
+    z-index: 1;
+  }
+}
+
 </style>

+ 54 - 10
pc/src/page/login/components/forget/emailForm.vue

@@ -2,18 +2,27 @@
   <div class="email-form">
     <div class="border-box" v-if="type === 'phone'">
       <div class="phone-area" @click="showPhoneArea = !showPhoneArea">
-        {{selectArea[1]}}({{selectArea[0]}})<span class="sanjiao"></span>
+        <p>{{selectArea[1]}}({{selectArea[0]}})</p>
+        <span class="sanjiao"></span>
         <phoneAddressSelect  v-show="showPhoneArea" @select="changeArea" />
       </div>
       <input type="text" placeholder="请输入手机号码" v-model="form.phone">
     </div>
     <input class="border-box"  v-model="form.phone" placeholder="邮箱地址" type="text" v-else>
     <div class="send-code-w border-box">
-      <input type="text" placeholder="验证码"  v-model="form.authCode">
+      <input type="text" placeholder="请输入验证码"  v-model="form.authCode">
       <div class="send-btn" @click="sendCode">{{ time? `${time}s后重试` : '获取验证码'}}</div>
     </div>
-    <input class="border-box" placeholder="设置密码" type="text"  v-model="form.password">
-    <input class="border-box" placeholder="重复密码" type="text"  v-model="form.confirmPass">
+    <div class="password-w border-box" :class="{'show-tip': !form.password && passwordTip}" @mouseleave="passwordTip=false" @click="focusInput('emialInput')" >
+        <input class="" ref="emialInput" :placeholder="passwordTip ? '' : '设置密码'" autocomplete="new-password "  v-model="form.password" type="password" @mouseover="passwordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+      <div class="password-w border-box" :class="{'show-tip': !form.confirmPass && confirmPassWordTip}" @click="focusInput('emialConfirmInput')" @mouseleave="confirmPassWordTip=false">
+        <input class="" :placeholder="confirmPassWordTip ? '' : '重复密码'" ref="emialConfirmInput" autocomplete="new-password" v-model="form.confirmPass" type="password"  @mouseenter="confirmPassWordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+    <!-- <input class="border-box" placeholder="设置密码" type="password"  v-model="form.password">
+    <input class="border-box" placeholder="重复密码" type="password"  v-model="form.confirmPass"> -->
     <p class="login-entry">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
     <div class="submit-btn" @click="submit">提交</div>
   </div>
@@ -38,7 +47,9 @@ export default {
       interEmailTime: 0,
       interTime: 0,
       showPhoneArea: false,
-      selectArea: ['中国', '+86']
+      selectArea: ['中国', '+86'],
+      confirmPassWordTip: false,
+      passwordTip: false
     }
   },
   computed: {
@@ -59,14 +70,16 @@ export default {
     changeArea (item) {
       this.selectArea = item
     },
+    focusInput (input = 'emialInput') {
+      this.$refs[input].focus()
+    },
     async getAuthCode () {
       if (this.interl) {
         return
       }
       let res = await this.$store.dispatch('getAuthCode', {
         phone: this.form.phone,
-        code: Number(this.selectArea[0].substr(1)),
-        type: 'resigter',
+        code: Number(this.selectArea[0].substr(1))
       })
       if (res) {
         this.interl && clearInterval(this.interl)
@@ -88,7 +101,6 @@ export default {
         return
       }
       let res = await this.$store.dispatch('getAuthCode', {
-        type: 'resigter',
         email: this.form.phone,
         qudao: 'email'
       })
@@ -109,7 +121,8 @@ export default {
       let check = value => {
         for (let i = 0, len = value.length; i < len; i++) {
           if (!value[i].val) {
-            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            return
           }
         }
         return true
@@ -219,11 +232,40 @@ export default {
     border-radius: 3px;
     cursor: pointer;
   }
+  .password-w {
+    position: relative;
+    margin: 0 0 20px;
+    input {
+      margin-bottom: 0;
+    }
+    p {
+      font-size: 12px;
+      color: #909090;
+      position: absolute;
+      line-height: 44px;
+      z-index: 1;
+      top: 0;
+      width: 100%;
+      text-align: center;
+      display: none;
+    }
+    &.show-tip {
+      p {
+        display: block;
+      }
+    }
+  }
   .phone-area {
       padding: 0 16px 0 10px;
       position: relative;
       cursor: pointer;
       width: 120px;
+      
+      &>p {
+        overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      }
       &::after {
         content: '';
         display: block;
@@ -241,7 +283,9 @@ export default {
       border-bottom: none;
       border-left-color: transparent;
       border-right-color: transparent;
-      margin-left: 10px;
+      position: absolute;
+      right: 10px;
+      top: 16px;
     }
 }
 </style>

+ 10 - 6
pc/src/page/login/components/forget/index.vue

@@ -1,18 +1,19 @@
 <template>
   <div class="forget">
     <div class="forget-header">{{ title }}</div>
-    <selectType @change="changePage" v-if="page === 'select'" />
-    <emailForm v-else :type="page" />
+    <!-- <selectType @change="changePage" v-if="page === 'select'" /> -->
+    <emailForm  :type="page" />
   </div>
 </template>
 
 <script>
 import selectType from './selectType'
 import emailForm from './emailForm'
+import { mapState } from 'vuex'
 export default {
   data () {
     return {
-      page: 'select'
+      // page: 'select'
     }
   },
   components: {
@@ -20,14 +21,17 @@ export default {
     emailForm
   },
   computed: {
+    ...mapState({
+      isInternational: state => state.user.isInternational
+    }),
     title () {
       return '找回密码'
+    },
+    page () {
+      return this.isInternational === 'zh' ? 'phone' : 'emali'
     }
   },
   methods: {
-    changePage (type) {
-      this.page = type
-    }
   }
 }
 </script>

+ 26 - 1
pc/src/page/login/components/forget/selectType.vue

@@ -3,12 +3,19 @@
     <img src="@/assets/images/refactor/login/forget-img.png" alt="">
     <p class="tips">为确认您是本人操作,<br/>请选择验证方式完成密码重置</p>
     <div class="type-btn" @click="selectType('phone')">使用手机短信验证码</div>
-    <div class="type-btn" @click="selectType('email')">使用E-mail验证码</div>
+    <div class="type-btn" @click="selectType('email')" v-if="isInternational">使用E-mail验证码</div>
+    <p class="login-entry">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
   </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
 export default {
+  computed: {
+    ...mapState({
+      isInternational: state => state.user.isInternational
+    })
+  },
   methods: {
     selectType (type) {
       this.$emit('change', type)
@@ -37,4 +44,22 @@ export default {
   line-height: 60px;
   margin-top: 30px;
 }
+.login-entry {
+    margin: 33px 0 0 0;
+    text-align: center;
+    font-size: 14px;
+    span {
+      font-weight: bold;
+      display: inline-block;
+      position: relative;
+      cursor: pointer;
+      &::after {
+        content: '';
+        display: block;
+        height: 2px;
+        width: 100%;
+        background: #1FE4DC;
+      }
+    }
+  }
 </style>

+ 48 - 18
pc/src/page/login/components/login.vue

@@ -4,13 +4,17 @@
       <div class="login-tab" :class="{'is-active': !type || type === 'codeLogin'}" @click="toOtherLogin('')">用户登录</div><div class="login-tab" :class="{'is-active': type==='camera'}" @click="toOtherLogin('camera')">相机登录</div>
     </div>
     <div class="account-login" v-if="!type">
-      <input type="text" class="input" placeholder="请输入手机号码/邮箱" v-model="form.phone">
-      <input type="password" class="input password" placeholder="请输入密码" v-model="form.password">
+      <input type="text" class="input" :placeholder="`请输入手机号码${isInternational ? '/邮箱' : ''}`" v-model="form.phone">
+      <div class="password-w">
+        <input :type="showPassword ? 'test' : 'password'" class="input password" placeholder="请输入密码" v-model="form.password" @keyup.enter="login">
+        <h-icon :type="showPassword ? 'mimabukejian' : 'mimakejian'" class="password-visible" @click="showPassword=!showPassword" />
+      </div>
+      
       <div class="toCodeLogin tips-tap" >
         <a @click="$router.push({name: 'login', query: {type: 'codeLogin'}})">验证码登录</a>
       </div>
-      <div class="checkbox"><input type="checkbox" v-model="rememberMe" />记住密码</div>
-      <div class="login-btn" @click="login" @keyup.enter="login">登录</div>
+      <div class="checkbox"><input type="checkbox" v-model="rememberMe" id="rember" /><label for="rember">记住密码</label></div>
+      <div class="login-btn"  @click="login" >登录</div>
       <div class="others">
         <a class="other-actions" @click="$router.push('/login/forget')">忘记密码</a>
         <a class="other-actions" @click="$router.push('/login/register')">账号注册</a>
@@ -26,10 +30,11 @@ import cameraLogin from './cameraLogin'
 import codeLogin from './codeLogin'
 import { encodeStr } from '@/util'
 import { Base64 } from 'js-base64'
-
+import { mapState } from 'vuex'
 export default {
   data () {
     return {
+      showPassword: false,
       rememberMe: false,
       form: {
         phone: '',
@@ -38,6 +43,10 @@ export default {
     }
   },
   computed: {
+    ...mapState({
+      langToast: state => state.language.home.toast,
+      isInternational: state => state.user.isInternational
+    }),
     type () {
       return this.$route.query.type
     }
@@ -46,6 +55,9 @@ export default {
     cameraLogin,
     codeLogin
   },
+  mounted () {
+    this.rememberMe = eval(localStorage.getItem('remember')) || ''
+  },
   methods: {
     toOtherLogin (type) {
       this.$router.push({
@@ -59,7 +71,8 @@ export default {
       let check = value => {
           for (let i = 0, len = value.length; i < len; i++) {
             if (!value[i].val) {
-              return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+              this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+              return 
             }
           }
           return true
@@ -94,13 +107,21 @@ export default {
           randomcode: '1234',
           rememberMe: Boolean(this.rememberMe)
         }
-        await this.$store.dispatch('login', params)
-        const from = this.$route.query.from
-        if (from) {
-          this.$router.push(from)
-        } else {
-          this.$router.push('/')
+        try {
+          let res = await this.$store.dispatch('login', params)
+          if (!res) {
+            return
+          }
+          const from = this.$route.query.from
+          if (from) {
+            this.$router.push(from)
+          } else {
+            this.$router.push('/')
+          }
+        } catch (err) {
+
         }
+        
     }
   }  
 }
@@ -138,9 +159,19 @@ export default {
 .account-login {
   padding: 0 38px;
 }
-
-.password {
+.password-w {
+  position: relative;
   margin: 29px 0 13px;
+  .password-visible {
+    position: absolute;
+    right: 20px;
+    font-size: 30px;
+    line-height: 60px;
+    cursor: pointer;
+  }
+}
+.password {
+  
 }
 .toCodeLogin {
   text-align: right;
@@ -154,14 +185,13 @@ export default {
   font-size: 16px;
   color: #202020;
   
-  display: inline-block;
+  display: flex;
+  align-items: center;
+  line-height: 18px;
   input {
     margin-right: 7px;
     cursor: pointer;
   }
-  * {
-    vertical-align: middle;
-  }
 }
 .login-btn {
   margin: 36px 0 18px;

+ 130 - 25
pc/src/page/login/components/register/index.vue

@@ -4,36 +4,52 @@
     <p class="tologin">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
     <!-- 手机注册 -->
     <div class="phone-register" v-if="type === 'phone'">
-      <input placeholder="请输入昵称" type="text" v-model="form.nickname">
+      <!-- <input placeholder="请输入昵称" type="text" v-model="form.nickname" maxlength="10"> -->
       <div class="phone-w">
-        <div class="phone-area" @click.stop="showPhoneArea=!showPhoneArea">{{ `${selectArea[1]}(${selectArea[0]})` }}<span class="sanjiao"></span>
+        <div class="phone-area" @click="showPhoneArea = !showPhoneArea">
+          <p>{{selectArea[1]}}({{selectArea[0]}})</p>
+          <span class="sanjiao"></span>
           <phoneAddressSelect  v-show="showPhoneArea" @select="changeArea" />
         </div>
+        
         <input placeholder="请输入手机号码" class="phone" type="text" v-model="form.phone">
       </div>
       <div class="code-w">
-        <input placeholder="短信验证码" class="phone" type="text" v-model="form.authCode">
+        <input placeholder="请输入验证码" class="phone" type="text" v-model="form.authCode">
         <div class="send-code-btn" :class="{'is-disabled': interTime}" @click="getAuthCode">{{ interTime ? `${interTime}s后重试` : '获取验证码'}}</div>
       </div>
-      <input placeholder="设置密码" autocomplete="new-password" v-model="form.password" type="password">
-      <input placeholder="重复密码" autocomplete="new-password" v-model="form.confirmPass" type="password">
-      <div class="right-tips"><span @click="type = 'email'">邮箱注册</span></div>
+      <div class="password-w" :class="{'show-tip': !form.password && passwordTip}" @mouseleave="passwordTip=false" @click="focusInput('emialInput')" >
+        <input ref="emialInput" :placeholder="passwordTip ? '' : '设置密码'" autocomplete="new-password "  v-model="form.password" type="password" @mouseover="passwordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+      <div class="password-w" :class="{'show-tip': !form.confirmPass && confirmPassWordTip}" @click="focusInput('emialConfirmInput')" @mouseleave="confirmPassWordTip=false">
+        <input :placeholder="confirmPassWordTip ? '' : '重复密码'" ref="emialConfirmInput" autocomplete="new-password" v-model="form.confirmPass" type="password"  @mouseenter="confirmPassWordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+      <div class="right-tips" v-if="isInternational"><span @click="type = 'email'">邮箱注册</span></div>
     </div>
     <!-- 邮箱注册 -->
     <div class="email-register" v-if="type === 'email'">
-      <input placeholder="请输入昵称" type="text" v-model="emailForm.nickname">
+      <!-- <input placeholder="请输入昵称" type="text" v-model="emailForm.nickname"> -->
       <div class="code-w">
         <input placeholder="邮箱地址" class="phone" type="text" v-model="emailForm.phone">
         <div class="send-code-btn" :class="{'is-disabled': interEmailTime}" @click="getEmailAuthCode">{{ interEmailTime ? `${interEmailTime}s后重试` : '获取验证码'}}</div>
       </div>
-      <input placeholder="验证码(6位数)"  type="text" v-model="emailForm.authCode">
-      <input placeholder="设置密码" autocomplete="new-password" v-model="emailForm.password" type="password">
-      <input placeholder="重复密码" autocomplete="new-password" v-model="emailForm.confirmPass" type="password">
+      <input placeholder="请输入验证码"  type="text" v-model="emailForm.authCode">
+      <div class="password-w" :class="{'show-tip': !emailForm.password && passwordTip}" @mouseleave="passwordTip=false" @click="focusInput('emialInput')" >
+        <input ref="emialInput" :placeholder="passwordTip ? '' : '设置密码'" autocomplete="new-password "  v-model="emailForm.password" type="password" @mouseover="passwordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+      <div class="password-w" :class="{'show-tip': !emailForm.confirmPass && confirmPassWordTip}" @click="focusInput('emialConfirmInput')" @mouseleave="confirmPassWordTip=false">
+        <input :placeholder="confirmPassWordTip ? '' : '重复密码'" ref="emialConfirmInput" autocomplete="new-password" v-model="emailForm.confirmPass" type="password"  @mouseenter="confirmPassWordTip=true" >
+        <p>密码必须包含英文大小写、数字、长度8-16个字符</p>
+      </div>
+      
       <div class="right-tips"><span @click="type = 'phone'">手机号码注册</span></div>
     </div>
     <div class="xieyi-w">
-      <input type="checkbox" v-model="showCluse">
-      <span>我已阅读并同意四维看看用户协议</span>
+      <input id="xieyi" type="checkbox" v-model="showCluse">
+      <label  for="xieyi">我已阅读并同意四维看看用户协议</label>
     </div>
     <div class="register-btn" @click="submit">注册</div>
   </div>
@@ -53,7 +69,9 @@ export default {
       selectArea: ['+86', '中国'],
       interTime: 0,
       interEmailTime: 0,
-      showCluse: false,
+      showCluse: true,
+      passwordTip: false,
+      confirmPassWordTip: false,
       form: {
         phone: '',
         authCode: '',
@@ -71,7 +89,9 @@ export default {
   },
   computed : {
     ...mapState({
-      langToast: state => state.language.home.toast
+      langToast: state => state.language.home.toast,
+      isInternational: state => state.user.isInternational,
+      token: state => state.user.token
     })
   },
   watch: {
@@ -89,11 +109,21 @@ export default {
         confirmPass: '',
         msgAuthCode: ''
       }
+    },
+    showCluse (newVal, oldVal) {
+      if (newVal && !oldVal) {
+        this.$bus.$emit('openClause', {show: true, type: 'register'})
+      }
     }
   },
   components: {
     phoneAddressSelect
   },
+  mounted () {
+    this.$bus.$on('isAgree', data => {
+      this.showCluse = data
+    })
+  },
   methods: {
     changeArea (item) {
       this.selectArea = item
@@ -102,11 +132,16 @@ export default {
       if (this.interl) {
         return
       }
+      if (!this.form.phone) {
+        this.$alert('请填写手机号码')
+        return
+      }
       let res = await this.$store.dispatch('getAuthCode', {
         phone: this.form.phone,
         code: Number(this.selectArea[0].substr(1)),
-        type: 'resigter',
+        type: '',
       })
+      console.log(res, 'res')
       if (res) {
         this.interl && clearInterval(this.interl)
         this.interl = null
@@ -126,6 +161,15 @@ export default {
       if (this.emailInterl) {
         return
       }
+      if (!this.emailForm.phone) {
+        this.$alert('请填写邮箱')
+        return
+      }
+      let patt = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
+      if (!patt.test(this.emailForm.phone)) {
+        this.$alert('请填写正确的邮箱')
+        return
+      }
       let res = await this.$store.dispatch('getAuthCode', {
         type: 'resigter',
         email: this.emailForm.phone,
@@ -146,26 +190,28 @@ export default {
     },
     async submit () {
       if (!this.showCluse) {
+        this.$alert('请阅读并同意四维看看用户协议')
         return
       }
       let check = value => {
         for (let i = 0, len = value.length; i < len; i++) {
           if (!value[i].val && value[i].required) {
-            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+            return
           }
         }
         return true
       }
       let form = this.type === 'email' ? this.emailForm : this.form
       let checkStr = [
+        // {
+        //   name: '昵称',
+        //   En: 'User name',
+        //   val: form.nickname,
+        //   required: this.type === 'email' ? false : true
+        // },
         {
-          name: '昵称',
-          En: 'User name',
-          val: form.nickname,
-          required: this.type === 'email' ? false : true
-        },
-        {
-          name: '手机',
+          name: this.type === 'email' ? '邮箱' : '手机',
           En: 'Phone number',
           val: form.phone,
           required: true
@@ -204,7 +250,7 @@ export default {
         password: temp[0],
         phoneNum: form.phone,
         msgAuthCode: form.authCode,
-        nickName: form.nickname,
+        nickName: form.phone,
         country,
         confirmPwd: temp[1],
       }
@@ -220,7 +266,7 @@ export default {
       this.$toast.showConfirm('success', this.langToast['23'], async () => {
         let params1 = {
           phoneNum: form.phone,
-          password: encodeStr(Base64.encode(this.password)),
+          password: encodeStr(Base64.encode(form.password)),
           randomcode: '1234',
           rememberMe: false
         }
@@ -234,6 +280,9 @@ export default {
         this.$bus.$emit('currentActive', 'ilogin')
         this.$bus.$emit('hideAside')
       })
+    },
+    focusInput (input = 'emialInput') {
+      this.$refs[input].focus()
     }
   }
 }
@@ -274,6 +323,7 @@ export default {
     font-size: 16px;
     border: 1px solid #909090;
     border-radius: 3px;
+    position: relative;
   }
   .phone-w, .code-w {
     display: flex;
@@ -353,5 +403,60 @@ export default {
     cursor: pointer;
     border-radius: 3px;
   }
+  .password-w {
+    position: relative;
+    margin-bottom: 20px;
+    input {
+      margin-bottom: 0;
+    }
+    p {
+      font-size: 12px;
+      color: #909090;
+      position: absolute;
+      line-height: 44px;
+      z-index: 1;
+      top: 0;
+      width: 100%;
+      text-align: center;
+      display: none;
+    }
+    &.show-tip {
+      p {
+        display: block;
+      }
+    }
+  }
 }
+.phone-area {
+      padding: 0 16px 0 10px;
+      position: relative;
+      cursor: pointer;
+      width: 120px;
+      z-index: 1000;
+      &>p {
+        overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      }
+      &::after {
+        content: '';
+        display: block;
+        height: 28px;
+        width: 1px;
+        background: #707070;
+        position: absolute;
+        right: 0;
+        top: 6px
+      }
+    }
+    .sanjiao {
+      display: inline-block;
+      border: 7px solid #909090;
+      border-bottom: none;
+      border-left-color: transparent;
+      border-right-color: transparent;
+      position: absolute;
+      right: 10px;
+      top: 16px;
+    }
 </style>

+ 66 - 12
pc/src/page/login/index.vue

@@ -1,43 +1,61 @@
 <template>
   <div class="login-page">
     <div class="login-container">
-      <LoginBox v-if="page==='login'" />
+      <LoginBox v-if="page === 'login'" />
       <registerBox v-else-if="page === 'register'" />
       <forgetBox v-else-if="page === 'forget'" />
     </div>
+    <cluseUser />
   </div>
 </template>
 
 <script>
-import LoginBox from './components/login'
-import registerBox from './components/register'
-import forgetBox from './components/forget'
+import LoginBox from "./components/login";
+import registerBox from "./components/register";
+import forgetBox from "./components/forget";
+import { mapState } from "vuex";
+import cluseUser from '@/page/layout/aside'
 export default {
+  data() {
+    return {
+    };
+  },
   computed: {
-    page () {
-      return this.$route.params.page || 'login'
-    }
+    ...mapState({
+      language: (state) => state.language.current,
+      languagelAside: (state) => state.language.home.home.loginAside,
+    }),
+    page() {
+      return this.$route.params.page || "login";
+    },
   },
   components: {
     LoginBox,
     registerBox,
-    forgetBox
+    forgetBox,
+    cluseUser
+  },
+  mounted () {
+    this.$nextTick(() => {
+      // this.$bus.$emit('openClause', {show: true, type: 'register'})
+    })
   }
-}
+};
 </script>
 
 <style lang="scss">
 .login-page {
   width: 100%;
   height: calc(100vh - 80px);
-  background: url(~@/assets/images/refactor/login/login-bg.jpg) no-repeat center center;
+  background: url(~@/assets/images/refactor/login/login-bg.jpg) no-repeat center
+    center;
   .login-container {
     position: absolute;
     left: 50%;
     top: 50%;
     transform: translate(-50%, -50%);
     transform: translate(-50%, calc(-50% + 40px));
-    box-shadow:0px 2px 6px rgba(0,0,0,0.4);
+    box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.4);
     background-color: #fff;
   }
   .tips-tap {
@@ -53,6 +71,42 @@ export default {
     font-size: 16px;
     color: #111;
   }
+  .showXieyi {
+    .h-modal__content {
+      height: 80%;
+      text-align: center;
+      & > div {
+        height: 100%;
+      }
+    }
+    .clause-img {
+      height: 80%;
+      overflow-y: auto;
+      overflow-x: hidden;
+    }
+    p {
+      margin: 25px 0;
+      color: #2d2d2d;
+      
+    }
+    .cls-btn {
+      span {
+        display: inline-block;
+        background: rgb(226, 226, 226);
+        color: #000;
+        height: 50px;
+        width: 215px;
+        line-height: 50px;
+        text-align: center;
+        cursor: pointer;
+        &:first-of-type {
+          margin-right: 80px;
+        }
+      }
+      .primary {
+        background: #1fe4dc;
+      }
+    }
+  }
 }
-
 </style>

+ 48 - 2
pc/src/page/mall/cart/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="mall-cart">
-    <div class="container">
+    <div class="container" v-if="cart.length > 0">
       <div class="cart-header clear">
         <div class="fl cart-header-left">
           <h3>购物车</h3>
@@ -68,7 +68,7 @@
             <div class="cart-actions clear">
               <img src="@/assets/images/refactor/mall/pay-channel.png" alt="" class="pay-channel">
               <div class="actions-w fr">
-                <div class="btn" @click="$router.back()">继续选购</div>
+                <div class="btn" @click="$router.push('/mall/kankanPro')">继续选购</div>
                 <div class="btn submit-btn" @click="toConfirm">立即结算</div>
               </div>
             </div>
@@ -76,6 +76,19 @@
         </div>
       </div>
     </div>
+    <div class="container" v-else>
+      <div class="cart-header">
+        <div class=" cart-header-left">
+          <h3>购物车</h3>
+        </div>
+        <div class="fr close-btn" @click="$router.push('/')">
+          <h-icon type="vip_false" size="20" />
+        </div>
+      </div>
+      <div class="cart-section noGoods">
+        <div class="btn" @click="$router.push('/mall/kankanPro')">立即购买</div>
+      </div>
+    </div>
   </div>
 </template>
 
@@ -132,7 +145,9 @@ export default {
           goodsCount: 0
         }
         this.$store.dispatch('reduceCart', params)
+        this.selectedGoods = this.selectedGoods.filter(id => id != item.goodsId)
       })
+      
     },
     input (e) {
       console.log(e)
@@ -187,6 +202,7 @@ export default {
       
     },
     toConfirm () {
+      console.log(this.selectedGoods)
       if (this.selectedGoods.length === 0) {
         this.$toast.show('warn', '请选择需要购买的商品')
         return
@@ -406,6 +422,36 @@ export default {
       background: #1FE4DC;
     }
   }
+  .cart-header {
+    position: relative;
+  }
+  .close-btn {
+    position: absolute;
+    top: 45px;
+    right: 48px;
+    font-size: 20px;
+    color: #909090;
+    cursor: pointer;
+  }
+  .noGoods {
+    width: 100%;
+    height: 550px;
+    background: image-set(url(~@/assets/images/refactor/mall/cartNoGoods.jpg) 1x, url(~@/assets/images/refactor/mall/cartNoGoods@2x.jpg) 2x) no-repeat center 22px;
+    position: relative;
+    border-top: 1px solid #E4E4E4;
+    .btn {
+      width: 216px;
+      height: 55px;
+      line-height: 55px;
+      background: #1FE4DC;
+      font-weight: 600;
+      position: absolute;
+      right: 60px;
+      bottom: 47px;
+      text-align: center;
+      cursor: pointer;
+    }
+  }
 }
 
 </style>

+ 71 - 31
pc/src/page/mall/confirm/components/addressModule.vue

@@ -2,31 +2,31 @@
   <div class="address-module">
     <h3 class="module-label">收货地址</h3>
     <ul class="address-list">
-      <li class="address-item" :class="{'is-active': selectAddressId === item.id}" v-for="item in addressList" :key="item.id" @click="selectAddressId=item.id">
-        <div class="default-tag" v-if="item.setDefault === 1">默认地址</div>
+      <li class="address-item is-active" >
+        <!-- <div class="default-tag" v-if="address.setDefault === 1">默认地址</div> -->
         <div class="address-userinfo clear">
-          <div class="user-name fl">{{ item.shipName }}</div>
-          <div class="user-phone fl">{{ item.shipMobile }}</div>
+          <div class="user-name fl">{{ address.shipName }}</div>
+          <div class="user-phone fl">{{ address.shipMobile }}</div>
         </div>
         <div class="address-detail">
-          <p class="address-p1">{{ item.shipAreaPath }} </p>
-          <p class="address-p2">{{ item.shipAddress }}</p>
+          <p class="address-p1">{{ address.shipAreaPath }} </p>
+          <p class="address-p2">{{ address.shipAddress }}</p>
         </div>
         <div class="action-w" >
-          <div class="edit"  @click.stop="showEdit(item)"><span class="icon edit-icon"></span><span>编辑</span></div>
-          <div class="delete" @click.stop="showDeleteId = item.id"><span class="icon delete-icon"></span><span>删除</span></div>
-          <div class="delete-confirm-box" v-if="showDeleteId === item.id">
+          <div class="edit"  @click.stop="showEdit(address)"><span class="icon edit-icon"></span><span>编辑</span></div>
+          <!-- <div class="delete" @click.stop="showDeleteId = address.id"><span class="icon delete-icon"></span><span>删除</span></div>
+          <div class="delete-confirm-box" v-if="showDeleteId === address.id">
             <h4>您确认要删除该地址吗?</h4>
             <div class="confirm-actions">
-              <div class="confirm-button button-submit" @click="deleteAddress(item.id)">是</div>
+              <div class="confirm-button button-submit" @click="deleteAddress(address.id)">是</div>
               <div class="confirm-button" @click="showDeleteId = ''">否</div>
             </div>
-          </div>
+          </div> -->
         </div>
       </li>
-      <li class="address-add" @click="showCreate">
+      <!-- <li class="address-add" @click="showCreate">
         <h-icon type="jiahao"></h-icon>新增收货地址
-      </li>
+      </li> -->
     </ul>
     <h-modal :visible="addressShow" :showClose="false">
       <div class="address-form">
@@ -34,25 +34,28 @@
         <div class="form">
           <div class="form-item">
             <div class="form-label">*收货人</div>
-            <input type="text" v-model="addressForm.shipName">
+            <input type="text" maxlength="10" v-model="addressForm.shipName">
           </div>
           <div class="form-item">
             <div class="form-label">*手机号码</div>
-            <input type="text" v-model="addressForm.shipMobile">
+            <input type="text" oninput="value=value.replace(/[^\d\-]/g,'')" maxlength='11' v-model="addressForm.shipMobile">
           </div>
           <div class="form-item">
-            <div class="form-label">*收货地址</div>
+            <div class="form-label">*所在地区</div>
             <div class="form-content">
               <citySelect :areaPath="addressForm.shipAreaPath" @currentVal="getCurrentSelect" />
-              <div class="address-select-text">
-                <textarea  v-model="addressForm.shipAddress" />
-              </div>
+            </div>
+          </div>
+          <div class="form-item">
+            <div class="form-label">*详细地址</div>
+            <div class="form-content">
+              <textarea  v-model="addressForm.shipAddress" maxlength="50" />
             </div>
           </div>
         </div>
         <div class="actions-w">
           <div class="cancel-btn" @click="addressShow=false">取消</div>
-          <div class="submit-btn" @click="createAddress">保存并使用</div>
+          <div class="submit-btn" @click="uAddress">保存并使用</div>
         </div>
       </div>
     </h-modal>
@@ -69,7 +72,7 @@ export default {
       addressShow: false,
       addressForm: {},
       addressList: [],
-      address: {},
+      // address: {},
       selectAddressId: '',
       showDeleteId: ''
     }
@@ -77,6 +80,9 @@ export default {
   computed: {
     ...mapState({
       token: state => state.user.token,
+      address: state => state.user.address,
+      language: state => state.language.current,
+      langToast: state => state.language.home.toast,
     })
   },
   watch: {
@@ -89,12 +95,12 @@ export default {
       url: '/user/getReceiverInfo',
       name: 'address'
     })
-    await this.getAddressList()
-    this.addressList.forEach(item => {
-      if (item.setDefault) {
-        this.selectAddressId = item.id
-      }
-    })
+    // await this.getAddressList()
+    // this.addressList.forEach(item => {
+    //   if (item.setDefault) {
+    //     this.selectAddressId = item.id
+    //   }
+    // })
   },
   components: {
     citySelect
@@ -115,7 +121,8 @@ export default {
         province,
         city,
         shipMobile,
-        shipName
+        shipName,
+        id
       } = this.addressForm
       let params = {
         shipAddress,
@@ -123,9 +130,39 @@ export default {
         province,
         city,
         shipMobile,
-        shipName
+        shipName,
+        id
+      }
+      let check = value => {
+        for (let i = 0, len = value.length; i < len; i++) {
+          if (!value[i].val) {
+            return this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
+          }
+        }
+        return true
+      }
+      let checkStr = [
+        {
+          name: '详细地址',
+          En: 'Detailed address',
+          val: shipAddress
+        },
+        {
+          name: '手机号',
+          En: 'Phone number',
+          val: shipMobile
+        },
+        {
+          name: '收货人',
+          En: 'Name',
+          val: shipName
+        }
+      ]
+      if (!check(checkStr)) {
+        return
       }
-      params.shipAreaPath = params.shipAreaPath.join()
+      // console.log(params.shipAreaPath)
+      // params.shipAreaPath = params.shipAreaPath.join()
       this.$http
         .post('/user/updateAddress', params, {
           headers: {
@@ -153,6 +190,10 @@ export default {
           this.addressShow = false
           await this.getAddressList()
           this.selectAddressId = res.data.data.id
+        } else if (res.data.code === 3001) {
+          this.$alert('请完善收货信息')
+        } else {
+          this.$alert('添加失败')
         }
       })
     },
@@ -328,7 +369,6 @@ export default {
     textarea {
       height: 84px;
       width: 100%;
-      margin-top: 20px;
       border:1px solid rgba(144,144,144,1);
       border-radius:3px;
       padding: 10px;

+ 34 - 32
pc/src/page/mall/confirm/components/invoiceModule.vue

@@ -2,14 +2,14 @@
   <div class="invoice-modules">
     <h4 class="module-label">发票信息</h4>
     <ul class="invoice-list">
-      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 0}" @click="invoiceType=0;">
-        不需要发票
+      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 0}" @click="visible = false;invoiceStatus=0;">
+        {{langOrders.type1}}
       </li>
-      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 2}" @click="visible = true;invoiceType=2;">
-        增值税普票(电子发票)
+      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 2}" @click="visible = true;invoiceStatus=2;invoiceType=2;">
+        {{langOrders.type2}}
       </li>
-      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 3}"  @click="visible = true;invoiceType=3;">
-        增值税专用发票
+      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 3}"  @click="visible = true;invoiceStatus=3;invoiceType=3;">
+        {{langOrders.type3}}
       </li>
     </ul>
     <h-modal :visible="visible" :showClose="false">
@@ -22,9 +22,9 @@
           <!-- 电子发票 -->
           <div class="form form-1" v-show="invoiceType === 2">
             <div class="form-item">
-              <div class="form-label">*电子发票</div>
+              <div class="form-label">*{{langOrders.email}}</div>
               <div class="form-input">
-                <input type="text" placeholder="接受发票的邮箱地址" v-model="invoiceForm.emailAddress">
+                <input type="text" :placeholder="langOrders.email" v-model="invoiceForm.emailAddress">
               </div>
             </div>
             <div class="form-item">
@@ -35,60 +35,60 @@
               </div>
             </div>
             <div class="form-item" v-show="invoiceSubType === 1">
-              <div class="form-label">*发票抬头</div>
+              <div class="form-label">*{{langOrders.title}}</div>
               <div class="form-input">
-                <input type="text" placeholder="个人" v-model="invoiceForm.title">
+                <input type="text" :placeholder="langOrders.title" v-model="invoiceForm.title">
               </div>
             </div>
             <div class="form-item" v-show="invoiceSubType === 2">
-              <div class="form-label">*发票抬头</div>
+              <div class="form-label">*{{langOrders.title}}</div>
               <div class="form-input">
-                <input type="text" placeholder="请输入单位名称"  v-model="invoiceForm.title">
+                <input type="text" :placeholder="langOrders.title"  v-model="invoiceForm.title">
               </div>
             </div>
             <div class="form-item" v-show="invoiceSubType === 2">
               <div class="form-label">*纳税人识别号</div>
               <div class="form-input">
-                <input type="text" placeholder="请输入18位税务登记号"  v-model="invoiceForm.code">
+                <input type="text" :placeholder="langOrders.code"  v-model="invoiceForm.code">
               </div>
             </div>
           </div>
           <!-- 专用发票 -->
           <div class="form" v-show="invoiceType === 3">
             <div class="form-item">
-              <div class="form-label">*单位名称</div>
+              <div class="form-label">*{{langOrders.title}}</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.title">
+                <input type="text" :placeholder="langOrders.title" v-model="invoiceForm3.title">
               </div>
             </div>
             <div class="form-item">
               <div class="form-label">*纳税人识别号</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.code">
+                <input type="text" :placeholder="langOrders.code" v-model="invoiceForm3.code">
               </div>
             </div>
             <div class="form-item">
-              <div class="form-label">*注册地址</div>
+              <div class="form-label">*{{langOrders.organizedAddress}}</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.organizedAddress">
+                <input type="text" :placeholder="langOrders.organizedAddress" v-model="invoiceForm3.organizedAddress">
               </div>
             </div>
             <div class="form-item">
-              <div class="form-label">*注册电话</div>
+              <div class="form-label">*{{langOrders.registerPhone}}</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.registerPhone">
+                <input type="text" :placeholder="langOrders.registerPhone" v-model="invoiceForm3.registerPhone">
               </div>
             </div>
             <div class="form-item">
-              <div class="form-label">*开户银行</div>
+              <div class="form-label">*{{langOrders.bankName}}</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.bankName" >
+                <input type="text" :placeholder="langOrders.bankName" v-model="invoiceForm3.bankName" >
               </div>
             </div>
             <div class="form-item">
-              <div class="form-label">*银行账户</div>
+              <div class="form-label">*{{langOrders.bankAccount}}</div>
               <div class="form-input">
-                <input type="text" placeholder="" v-model="invoiceForm3.bankAccount">
+                <input type="text" :placeholder="langOrders.bankAccount" v-model="invoiceForm3.bankAccount">
               </div>
             </div>
           </div>
@@ -98,7 +98,7 @@
           <div class="tips-content">专票随商品一并寄出,若因特殊情况会于10天内顺丰寄送给您(如遇节假日稍有延迟)。请注意查收;增值税专用发票收到后请妥善保存,如退货请一同寄回,如退货专票未能寄回,则需扣除相应的税点。</div>
         </div>
         <div class="actions-w">
-          <div class="cancel-btn" @click="visible=false">取消</div>
+          <div class="cancel-btn" @click="visible=false">{{langOrders.cancal1}}</div>
           <div class="submit-btn" @click="saveInvoice">保存并使用</div>
         </div>
       </div>
@@ -147,6 +147,7 @@ export default {
       token: state => state.user.token,
       langToast: state => state.language.home.toast,
       language: state => state.language.current,
+      langOrders: state => state.language.home.manage.myOrders,
       editInvoice2: state => {
       let type = Object.prototype.toString.call(state.user.invoice2)
         if (type === '[object Object]') {
@@ -204,7 +205,7 @@ export default {
       }
 
       if (invoiceType === 2) {
-        let { title, code } = this.invoiceForm
+        let { title, code, emailAddress } = this.invoiceForm
         code = invoiceSubType === 1 ? '' : code
         if (invoiceSubType === 2 && code.length !== 18) {
           return this.$toast.show('warn', this.langToast['21'])
@@ -212,7 +213,8 @@ export default {
         params = {
           invoiceType,
           title,
-          code
+          code,
+          emailAddress
         }
 
         let checkStr = [
@@ -221,11 +223,11 @@ export default {
             En: 'Title',
             val: title
           },
-          // {
-          //   name: '电子邮箱',
-          //   En: 'Email',
-          //   val: emailAddress
-          // }
+          {
+            name: '电子邮箱',
+            En: 'Email',
+            val: emailAddress
+          }
         ]
         if (!check(checkStr)) {
           return

+ 6 - 2
pc/src/page/mall/confirm/index.vue

@@ -99,7 +99,7 @@ export default {
       formatNum: mallConfig.formatNum,
       goodsDetail: mallConfig.goodsMap,
       invoice: {},
-      address: {},
+      // address: '',
       checked: false,
       openClause: false,
       allreadyRead: true
@@ -112,7 +112,7 @@ export default {
   computed: {
     ...mapState({
       langToast: state => state.language.home.toast,
-      // address: state => state.user.address || {},
+      address: state => state.user.address || {},
       language: state => state.language.current,
       token: state => state.user.token,
       languagelAside: state => state.language.home.home.loginAside
@@ -140,6 +140,10 @@ export default {
         this.$alert('请同意四维看看用户协议')
         return
       }
+      if (!this.address) {
+        this.$alert('请添加地址')
+        return
+      }
       let params = {
         goods: this.goods,
         receiver: this.address,

+ 69 - 46
pc/src/page/mall/kankanPro/index.vue

@@ -13,32 +13,32 @@
           <p class="price">
              {{langPurchase.price}}
           </p>
-          <p class="postage">{{ $t('pages.mall.postage') }}</p>
           <template>
-            <div class="capacity">包含基础容量:10G<a :href="`${pathname}#/mall/cloudCapacity`" target="_blank">了解详情</a></div>
-            <h-row class="package-w" :gutter="28">
-              <h-col :span="12">
-                <div :class="`package-item ${package === 'normal' ? 'active' : ''}`" @click="package='normal'">标准套餐</div>
-              </h-col>
-              <h-col :span="12">
-                <div :class="`package-item ${package === 'lot' ? 'active' : ''}`" @click="package='lot';selectParts=true">增值套餐(包含三脚架)</div>
-              </h-col>
-            </h-row>
-            <div class="number-w">数量 <number v-model="count" :max="99" style="margin-left:12px;" /></div>
-            <p class="title ">是否需要添加推荐的配件(标准套餐不含以下配件)</p>
-            <div class="detail-box zhijia" :class="{'no-active':!selectParts}" @click="changeSelectParts">
-              <!-- <img :src="`${$cdn}images/tag-icon.png`" class="t-click" alt> -->
-              <img :src="`${$cdn}images/zhijia.png`" alt>
-              <div class="zhijia-info">
-                <h6>四维看看Pro三脚架套装</h6>
-                <p>三脚架 + 滑轮 + 云台</p>
-                <a :href="`${pathname}#/mall/zhijia`" target="_blank">了解详情</a>
-              </div>
-              <div class="zhijia-actions">
-                <p>¥{{ mallConfig.zhijiaPrice }}</p>
-                <number v-model="zhijiaCount" :max="99" />
+            <div class="intro-item">
+              <h4 class="intro-title">{{langPurchase.service.key}}</h4>
+              <ul>
+                <li>{{langPurchase.service.type}} <a :href="`${pathname}#/mall/cloudCapacity`" target="_blank">{{ $t('mall.knowMore') }}</a></li>
+                <li>{{ langPurchase.service.val[0] }}</li>
+                <li>{{ langPurchase.service.val[1] }}</li>
+                <li>{{ langPurchase.service.val[2] }}</li>
+              </ul>
+            </div>
+            <div class="intro-item">
+              <h4 class="intro-title">{{langPurchase.gift.peijian}}</h4>
+              <div class="detail-box zhijia" :class="{'no-active':!selectParts}" @click="changeSelectParts">
+                <!-- <img :src="`${$cdn}images/tag-icon.png`" class="t-click" alt> -->
+                <img :src="`${$cdn}images/zhijia.png`" alt>
+                <div class="zhijia-info">
+                  <h6>{{ $t('mall.jiaojia') }}<span class="zhijia-price">{{ purchasezhijia.price }}</span></h6>
+                  <p>{{ $t('mall.jiaojiaDetail') }}</p>
+                  <a :href="`${pathname}#/mall/zhijia`" target="_blank">{{ $t('mall.knowMore')}}</a>
+                </div>
+                <div class="zhijia-actions">
+                </div>
               </div>
             </div>
+            
+            <div class="number-w">{{ $t('mall.count') }} <number v-model="count" :max="99" style="margin-left:12px;" /></div>
           </template>
           <template v-if="language!=='en'">
             <div class="totalPrice">¥{{ totalPrice }}</div>
@@ -47,7 +47,7 @@
             <div class="btns">
               <div v-if="language!=='en'" class="button add-cart" @click="addcart" style="margin-right:28px;">
                 <vcenter>
-                  <span>加入购物车</span>
+                  <span>{{ $t('mall.cart') }}</span>
                 </vcenter>
               </div>
               <div class="button"  @click="pay">
@@ -56,7 +56,7 @@
                 </vcenter>
               </div>
             </div>
-            <div class="btn-dec" ><h-icon type="gouwuche" class="shop-cart-icon" />预计3日内发货</div>
+            <div class="btn-dec" ><h-icon type="gouwuche" class="shop-cart-icon" />{{ $t('mall.fahuo')}}</div>
           </div>
         </div>
       </div>
@@ -64,7 +64,7 @@
     <div class="plate02" >
       <div class="tabs ">
         <ul class="container">
-          <li class="tabs-item" :class="{'is-active': detailType === 'product'}" @click="detailType = 'product'">产品说明</li><li class="tabs-item" :class="{'is-active': detailType === 'tech'}"  @click="detailType = 'tech'">技术参数</li>
+          <li class="tabs-item" :class="{'is-active': detailType === 'product'}" @click="detailType = 'product'">{{$t('mall.product')}}</li><li class="tabs-item" :class="{'is-active': detailType === 'tech'}"  @click="detailType = 'tech'">{{$t('mall.techDetail')}}</li>
         </ul>
         
       </div>
@@ -79,7 +79,7 @@
       <div class="tech-detail" v-show="detailType === 'tech'">
         <div class="params-body">
           <div class="container">
-            <h1 class="common-title">技术参数</h1>
+            <h1 class="common-title">{{$t('mall.techDetail')}}</h1>
             <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>
@@ -95,7 +95,7 @@
           
         </div>
         <div class="params-img-con container">
-          <h1 class="common-title">尺寸参数</h1>
+          <h1 class="common-title">{{ $t('mall.widthDetail')}}</h1>
           <img class="params-img" :src="`${$cdn}images/product_img_content_6_w.png`" alt="">
         </div>
       </div>
@@ -129,13 +129,14 @@ export default {
       split: state => state.ui.navDivision,
       isLogin: state => state.user.name,
       langPurchase: state => state.language.home.purchase,
+      purchasezhijia: state => state.language.home.purchasezhijia,
       language: state => state.language.current,
       langToast: state => state.language.home.toast,
       token: state => state.user.token,
       cart: state => JSON.parse(state.user.cart)
     }),
     totalPrice () {
-      return mallConfig.formatNum(mallConfig.price * this.count + (this.selectParts ? mallConfig.zhijiaPrice * this.zhijiaCount : 0))
+      return mallConfig.formatNum(mallConfig.price * this.count + (this.selectParts ? mallConfig.zhijiaPrice * this.count : 0))
     }
   },
   data () {
@@ -204,44 +205,43 @@ export default {
       browdata,
       count: 1,
       selectParts: true,
-      package: 'lot',
       mallConfig,
       zhijiaCount: 1,
       detailType: 'product',
       pathname: window.location.pathname,
       sequenceArr: [
         {
-          name: 'AI全自动精准建模,智能测距',
+          name: this.$t('conduct.coreProduct.itemTitle1'),
           img: 6,
           runAnimation: true
         },
         {
-          name: '720度8K画质,身临其境',
+          name: this.$t('conduct.coreProduct.itemTitle2'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: 'HDR模式平衡明暗区域曝光',
+          name: this.$t('conduct.coreProduct.itemTitle3'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: '球幕视频真人解说 打造沉浸视听体验',
+          name: this.$t('conduct.coreProduct.itemTitle4'),
           img: '7test',
           runAnimation: true
         },
         {
-          name: '10分钟入门,快速掌握拍摄流程',
+          name: this.$t('conduct.coreProduct.itemTitle5'),
           img: 8,
           runAnimation: true
         },
         {
-          name: '10分钟全自动出结果,高效快速(约100㎡)',
+          name: this.$t('conduct.coreProduct.itemTitle6'),
           img: 9,
           runAnimation: true
         },
         {
-          name: '强大编辑后台,让空间延伸表达',
+          name: this.$t('conduct.coreProduct.itemTitle7'),
           img: 10,
           runAnimation: true
         }
@@ -253,12 +253,9 @@ export default {
       this.count = data
     },
     async addcart () {
-      if (!this.token) {
-        return this.$bus.$emit('showAside')
-      }
       let zhijia = {
         goodsId: 7,
-        goodsCount: this.zhijiaCount,
+        goodsCount: this.count,
         skuSn: 'U15604134406280073'
       }
       let params = {
@@ -266,6 +263,10 @@ export default {
         goodsCount: this.count,
         skuSn: 'U15609161635760015'
       }
+      if (!this.token) {
+        this.$router.push('/login/login')
+        return
+      }
       await this.$store.dispatch('addCart', params)
       this.selectParts && await this.$store.dispatch('addCart', zhijia)
       this.$toast.show('success', this.langToast['39'])
@@ -274,6 +275,10 @@ export default {
       if (this.language === 'en') {
         return window.open('https://www.alibaba.com/product-detail/4DKanKan-Pro-3D-camera-3D-space_62183626283.html?spm=a2700.icbuShop.74.1.66b35b10I4miJd')
       }
+      if (!this.token) {
+        this.$router.push('/login/login')
+        return
+      }
       let params = {
         type: 'detail',
         sku: [{
@@ -286,7 +291,7 @@ export default {
       }
       let zhijia = {
         goodsId: 7,
-        goodsCount: this.zhijiaCount,
+        goodsCount: this.count,
         price: mallConfig.zhijiaPrice,
         skuSn: 'U15604134406280073'
       }
@@ -308,10 +313,7 @@ export default {
       })
     },
     changeSelectParts () {
-      if (this.package !== 'lot') {
-        this.selectParts=!this.selectParts
-      }
-      
+      this.selectParts=!this.selectParts
     }
   },
   mounted () {
@@ -347,4 +349,25 @@ export default {
 
 <style lang="scss" scoped>
 @import "./style.scss";
+.intro-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #202020;
+}
+.intro-item {
+  ul {
+    margin: 15px 0 25px;
+    padding-left: 20px;
+  }
+  li {
+    list-style: disc;
+    color: #909090;
+    line-height: 33px;
+    a {
+      font-size: 12px;
+      color: #909090;
+      text-decoration: underline;
+    }
+  }
+}
 </style>

+ 12 - 13
pc/src/page/mall/kankanPro/style.scss

@@ -27,6 +27,7 @@
 
 .number-w {
   color: #909090;
+  margin-bottom: 24px;
 }
 .plate01{
   background: #fff;
@@ -61,8 +62,8 @@
       max-width: 100%;
     }
     .price{
-      margin-top: 20px;
-      font-size: 30px;
+      margin: 20px 0 25px;
+      font-size: 40px;
       line-height: 50px;
       color: rgba(0,0,0,.7);
       font-weight: 700;
@@ -123,13 +124,6 @@
       width: 250px;
       box-sizing: border-box;
       text-align: left;
-      &:first-of-type{
-        padding: 6px 0 11px;
-        height: auto;
-        box-sizing: border-box;
-        font-size: 16px;
-        color: #000;
-      }
       .t-click{
         position: absolute;
         right: 0;
@@ -193,14 +187,15 @@
       }
     }
     .zhijia{
-      padding: 5px 22px;
-      width: 100%;
+      padding: 5px 29px;
+      width: 460px;
       cursor: pointer;
       text-align: center;
       border: 1px solid #70eee9;
       display: flex;
       align-items: center;
-      margin: 20px 0 6px;
+      margin: 20px 0 36px;
+      background: url('https://4dscene.4dage.com/new4dkk/images/tag-icon.png') no-repeat right bottom;
       img{
         vertical-align: middle;
         margin-right: 20px;
@@ -219,12 +214,15 @@
           margin: 14px 0;
         }
         a {
-          display: block;
+          display: inline-block;
           color: #909090;
           font-size: 12px;
           text-decoration: underline;
         }
       }
+      .zhijia-price {
+        margin-left: 28px;
+      }
       .zhijia-actions {
         flex: 1;
         text-align: right;
@@ -255,6 +253,7 @@
     }
     .no-active{
       border: 1px solid #e3e3e3;
+      background: none;
       background-color: #fff;
       .t-click{
         display: none;

+ 2 - 2
pc/src/page/mall/pay/index.vue

@@ -8,7 +8,7 @@
         <p>支付中心</p>
       </div>
       <div class="pay-content">
-        <div class="account"><span class="label">当前账号:</span><span>{{ info.nickName }}</span></div>
+        <div class="account"><span class="label">当前账号:</span><span>{{ info.userName }}</span></div>
         <div class="pay-types">
           <p class="label">支付方式:</p>
           <div class="pay-type ali-pay" @click="selectedPayType = 'alipay'" :class="{'is-active': selectedPayType === 'alipay'}">
@@ -26,7 +26,7 @@
           <p class="price">¥{{response.price}}</p>
           <div class="pay-qrcode">
             <img :src="`${$serverName}${response.src}`" alt="">
-            <p>使用微信app扫码完成支付</p>
+            <p>使用{{ selectedPayType === 'alipay' ? '支付宝' : '微信'}}app扫码完成支付</p>
           </div>
           <div class="pay-scan-tip"></div>
         </div>

+ 2 - 1
pc/src/page/mall/zhijia/index.vue

@@ -46,7 +46,7 @@
                 </vcenter>
               </div>
             </div>
-            <div class="btn-dec"><h-icon type="gouwuche" class="shop-cart-icon" />预计3日内发货</div>
+            <div class="btn-dec"><h-icon type="gouwuche" class="shop-cart-icon" />{{ $t('mall.fahuo')}}</div>
           </div>
         </div>
       </div>
@@ -146,6 +146,7 @@ export default {
       split: state => state.ui.navDivision,
       isLogin: state => state.user.name,
       langPurchase: state => state.language.home.purchasezhijia,
+      langPurchasekankan: state => state.language.home.purchase,
       langToast: state => state.language.home.toast,
       language: state => state.language.current,
       token: state => state.user.token,

+ 0 - 1
pc/src/page/mall/zhijia/style.scss

@@ -17,7 +17,6 @@
   font-weight: bold;
   text-align: center;
   font-size: 16px;
-  width: 216px;
   img{
     vertical-align: middle;
   }

+ 4 - 2
pc/src/page/manage/temp/information.vue

@@ -341,7 +341,8 @@ export default {
         province,
         city,
         shipMobile,
-        shipName
+        shipName,
+        id
       } = this.editAdd
 
       let check = value => {
@@ -379,7 +380,8 @@ export default {
         province,
         city,
         shipMobile,
-        shipName
+        shipName,
+        id
       }
       this.$http
         .post('/user/updateAddress', params, {

+ 1 - 1
pc/src/page/manage/temp/order.vue

@@ -313,7 +313,7 @@ $border-color: #e7e7e7;
   margin-left: 26px;
 }
 .order-layout {
-  width: 75%;
+  width: 90%;
   color: #2d2d2d;
   .order-item {
     margin: 40px;

+ 14 - 4
pc/src/page/news/index.vue

@@ -22,10 +22,10 @@
           <a class="news-item" :href="item.link" target="_blank" >
             <div class="news-img" :style="{'background-image': `url(${item.img})`}"></div>
             <div class="news-info">
-              <p class="news-time">{{ item.time }}</p>
               <h5 class="news-title">{{ item.title }}</h5>
               <p class="news-content">{{ item.text }}</p>
               <div class="news-tag">{{ item.sub }}</div>
+              <p class="news-time">{{ item.time }}</p>
             </div>
           </a>
         </h-col>
@@ -40,7 +40,7 @@
 import 'swiper/css/swiper.css'
 
 import { Swiper, SwiperSlide } from 'vue-awesome-swiper'
-import { News } from '@/config/newsData'
+import { News } from '@/../../common/data/newsData'
 export default {
   data () {
     return {
@@ -189,19 +189,29 @@ export default {
     }
   }
   .news-info {
-    padding: 20px 40px 26px;
+    padding: 20px 40px 37px;
     font-size: 14px;
     background: #fff;
     color: #909090;
+    position: relative;
   }
   .news-time {
-    color: #E60222;
+    color: #909090;
+    position: absolute;
+    right: 40px;
+    bottom: 37px;
   }
   .news-title {
     margin: 8px 0;
     font-size: 16px;
     color: #202020;
     line-height: 24px;
+    height: 48px;
+    overflow: hidden;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    line-clamp: 2;
+    -webkit-box-orient: vertical;
   }
   .news-img {
     width: 100%;

+ 1 - 1
pc/src/page/purchasetow/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="purchase-layout" v-show="split">
+  <div class="purchase-layout">
     <div class="plate01">
       <div class="main-detail">
         <img

+ 1 - 1
pc/src/page/purchasezhijia/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="purchase-layout" v-show="split">
+  <div class="purchase-layout">
     <div class="plate01">
       <div class="main-detail">
         <browse

+ 4 - 4
pc/src/page/service/temp/app.vue

@@ -2,14 +2,14 @@
   <div class="app-download">
     
     <div class="container">
-      <div class="common-title">下载软件</div>
+      <div class="common-title">{{$t('service.app')}}</div>
       <div class="logo">
         <img :src="`${$cdn}images/app-logo.png`"  alt srcset>
       </div>
       <div class="info">
-        <img :src=" language==='en'?`https://eur.4dkankan.com/app-download`:`https://www.4dkankan.com/app-download.html`" alt srcset>
+        <img :src=" language==='en'?`https://4dscene.4dage.com/new4dkk/images/pro-logo-en.png`:`https://4dscene.4dage.com/new4dkk/images/pro-logo.png`" alt srcset>
         <h2></h2>
-        <p>{{langDownload.sub}}</p>
+        <p>{{ $t('service.appDownload.downloadTip')}}</p>
 
         <div>
           <p>
@@ -61,7 +61,7 @@ export default {
     max-width: 100%;
     margin-left: 180px;
     > img{
-      width: 190px;
+      width: 186px;
     }
     > h2 {
       font-size: 24px;

+ 1 - 1
pc/src/page/service/temp/clause.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="container">
-    <div class="common-title">保修条款</div>
+    <div class="common-title">{{$t('service.clause')}}</div>
     <div class="use-layout" :class="language">
     <lselect :options="navs" :selected="navActive" class="select" :class="{oy: navs.length > 15}" @change="handleChange" />
 

+ 5 - 5
pc/src/page/service/temp/index.vue

@@ -2,7 +2,7 @@
   <div class="temp-layout">
     <div class="banner">
       <div class="container">
-        <h1>服务支持</h1>
+        <h1>{{$t('service.title')}}</h1>
         <ul>
           <li :class="{'is-active': $route.path === item.path}" v-for="item in listItem" :key="item.name" @click="$router.push(item.path)">{{ item.name }}</li>
         </ul>
@@ -41,19 +41,19 @@ export default {
       active: '',
       listItem: [
         {
-          name: '视频教程',
+          name: this.$t('service.mVideo'),
           path: '/service/mVideo/all'
         },
         {
-          name: '使用教程',
+          name: this.$t('service.use'),
           path: '/service/use/pro'
         },
         {
-          name: '软件下载',
+          name: this.$t('service.app'),
           path: '/service/app/pro'
         },
         {
-          name: '保修条款',
+          name: this.$t('service.clause'),
           path: '/service/clause/pro'
         },
       ]

+ 1 - 1
pc/src/page/service/temp/use.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="container">
     <div class="common-title">
-      使用教程
+      {{$t('service.use')}}
     </div>
   <div class="use-layout " :class="language">
     

+ 95 - 21
pc/src/page/service/video.vue

@@ -1,17 +1,25 @@
 <template>
-  <div class="container">
+  <div class="video-w">
+    <div class="container">
     <div class="setion" v-for="(item,i) in langVideoCourse" :key="i">
-      <p class="b-title">{{item.name}}</p>
-      <p class="b-label">{{item.sub}}</p>
+      <p class="common-title">{{item.name}}</p>
+      <!-- <p class="b-label">{{item.sub}}</p> -->
       <ul class="i-ul">
-        <li :style="{width:`${90/item.items.length*2}%`}" @click="itemHandle(sub)" v-for="(sub,idx) in item.items" :key="idx">
-          <img class="li-img" :src="`${$cdn}course/img/${sub.code}.jpg`" alt="">
-          <img class="bofang" :src="`${$cdn}course/img/video_play@2x.png`" alt="">
-          <p class="li-p">{{sub.name}}</p>
+        <li :class="{small: item.items.length > 2}" :style="{width:`${90/item.items.length*2}%`}" @click="itemHandle(sub)" v-for="(sub,idx) in item.items" :key="idx">
+          <div class="img-w">
+            <img class="li-img" :src="`${$cdn}course/img/${sub.code}.jpg`" alt="">
+            <div class="hover-item">
+              <img :src="`${$cdn}course/img/video_play@2x.png`" alt="">
+              <p>{{sub.name}}</p>
+            </div>
+          </div>
+          <p class="li-p" >{{sub.name}}<img class="bofang" :src="`${$cdn}course/img/video_play@2x.png`" alt=""></p>
+          
         </li>
       </ul>
     </div>
   </div>
+  </div>
 </template>
 
 <script>
@@ -41,13 +49,18 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.video-w {
+  background: #F7F7F7;
+}
 .container{
-  width: 1200px;
-  margin: 50px auto;
+  // width: 1200px;
+  margin: 0 auto;
+  padding: 0 0 124px;
   .setion{
-    margin: 20px 0;
-    .b-title{
-      font-size: 38px;
+    margin: 0 0 0;
+    padding-top: 86px;
+    .common-title{
+      margin: 0;
     }
     .i-ul{
       display: flex;
@@ -55,27 +68,88 @@ export default {
       align-items: center;
       flex-wrap: wrap;
       width: 100%;
-      margin-top: 20px;
+      margin-top: 64px;
       li{
         position: relative;
         max-width: 49%;
         margin-top: 20px;
+        background: #fff;
         .li-img{
           width: 100%;
           cursor: pointer;
+          vertical-align: middle;
         }
         .bofang{
-          width: 30px;
-          height: 30px;
+          width: 36px;
+          height: 36px;
           position: absolute;
-          left: 20px;
-          bottom: 60px;
+          right: 15px;
+          bottom: 15px;
+          cursor: pointer;
         }
         .li-p{
-          font-size: 16px;
-          color: #2d2d2d;
-          margin-top: 10px;
-          min-height: 40px;
+          font-size: 24px;
+          color: #202020;
+          line-height: 66px;
+          padding: 0 15px;
+          position: relative;
+        }
+        .img-w {
+          position: relative;
+          overflow: hidden;
+        }
+        &:hover {
+          .hover-item {
+            top: 0;
+          }
+          
+        }
+        .hover-item {
+          background: rgba(0,0,0,0.5);
+          position: absolute;
+          top: -100%;
+          left: 0;
+          width: 100%;
+          height: 100%;
+          cursor: pointer;
+          text-align: center;
+          padding-top: 100px;
+          transition: top 0.2s linear;
+          img {
+            width: 70px;
+            height: 70px;
+            margin: 0 auto;
+          }
+          p {
+            font-size: 40px;
+            color: #fff;
+            
+          }
+        }
+        &.small {
+          .li-p{
+            line-height: 50px;
+            font-size: 16px;
+            padding: 0 9px;
+          }
+          .bofang{
+            width: 30px;
+            height: 30px;
+            position: absolute;
+            right: 9px;
+            bottom: 10px;
+            cursor: pointer;
+          }
+          .hover-item {
+            padding-top: 40px;
+            img {
+              width: 50px;
+              height: 50px;
+            }
+            p {
+              font-size: 20px;
+            }
+          }
         }
       }
     }

+ 1 - 1
pc/src/page/zhijia/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="zhijia-layout" v-show="split">
+  <div class="zhijia-layout">
     <div class="plate01 plate">
       <img class="pl01-bg" :src="`${$cdn}images/zhijia-bg1.png`" alt />
 

+ 22 - 18
pc/src/router/index.js

@@ -90,7 +90,10 @@ let router = new Router({
         {
           path: '/cases/:id',
           name: 'cases',
-          component: resolve => require(['@/page/cases'], resolve)
+          component: resolve => require(['@/page/cases'], resolve),
+          meta: {
+            hideFooterFind: true
+          }
         },
         {
           path: '/news',
@@ -175,10 +178,15 @@ let router = new Router({
           ]
         },
         {
-          path: '/introduce/:id',
+          path: 'introduce/:id',
           name: 'introduce',
           component: resolve => require(['@/page/introduce'], resolve)
         },
+        {
+          path: '/introtow/:id',
+          name: 'introtow',
+          component: resolve => require(['@/page/introtow'], resolve)
+        },
       ]
     },
     {
@@ -262,27 +270,23 @@ let router = new Router({
       name: 'pricedetail',
       component: resolve => require(['@/page/pricedetail'], resolve)
     },
-    // {
-    //   path: '/purchasetow',
-    //   name: 'purchasetow',
-    //   component: resolve => require(['@/page/purchasetow'], resolve)
-    // },
-    // {
-    //   path: '/privilege/:cameraId/:childName',
-    //   name: 'privilege',
-    //   component: resolve => require(['@/page/privilege'], resolve)
-    // },
     {
-      path: '/introduce/:id',
-      name: 'introduce',
-      component: resolve => require(['@/page/introduce'], resolve)
+      path: '/purchasetow',
+      name: 'purchasetow',
+      component: resolve => require(['@/page/purchasetow'], resolve)
+    },
+    {
+      path: '/privilege/:cameraId/:childName',
+      name: 'privilege',
+      component: resolve => require(['@/page/privilege'], resolve)
     },
     // {
-    //   path: '/introtow/:id',
-    //   name: 'introtow',
-    //   component: resolve => require(['@/page/introtow'], resolve)
+    //   path: '/introduce/:id',
+    //   name: 'introduce',
+    //   component: resolve => require(['@/page/introduce'], resolve)
     // },
     
+    
     {
       path: '/service/down',
       name: 'service_down',

+ 2 - 2
pc/src/store/language/cn/purchase.js

@@ -9,7 +9,7 @@ export default{
   addzhijia: 'RMB 13,395',
   buy: '立即购买',
   why: '为什么要购买容量?',
-  tiaokuan: '* 付款成功后5个工作日内发货,默认顺丰快递包邮',
+  tiaokuan: '付款成功后5个工作日内发货,默认顺丰快递包邮',
   guige: {
     name: '技术规格',
     dec: '注:本页面所列配置及参数均以实际上市产品为准,如有变更,恕不另行通知。',
@@ -70,7 +70,7 @@ export default{
   gift: {
     peijian: '配件',
     key: '了解配件详情',
-    val: '四维看看 Pro三脚架套装',
+    val: '四维看看Pro三脚架套装',
     price: 'RMB:899'
   },
   count: {

+ 2 - 2
pc/src/store/language/cn/toast.js

@@ -27,7 +27,7 @@ export default{
   '26': '确定要解绑当前相机吗?',
   '27': '上传的图片类型不正确,请重新上传',
   '28': '您的云端容量已用完,请删除其他场景或扩容, 以保证足够的容量。',
-  '29': '手机号码不合法',
+  '29': '账号不合法',
   '30': '请重新登录',
   '31': '密码位数不能少于8位',
   '32': '密码修改成功',
@@ -65,7 +65,7 @@ export default{
   '3005': '验证码已过期',
   '3006': '验证码错误',
   '3007': '昵称已存在',
-  '3008': '该手机已被注册',
+  '3008': '该账号已被注册',
   '3009': '两次输入的密码不一致',
   '3010': '昵称长度在2-11位之间',
   '3011': '密码必须包含英文大小写、数字,长度8-16个字符',

+ 30 - 5
pc/src/store/language/index.js

@@ -9,24 +9,49 @@ const en = {
   home: enLang
 }
 
-let current = (localStorage && localStorage.getItem('language')) || '中'
+let current = (localStorage && localStorage.getItem('language')) || 'zh'
+if (current === '中') {
+  current = 'zh'
+}
 document.title = current === 'en' ? '4DKanKan' : '四维看看'
-
-let languageObj = current === '中' ? cn : en
+let languageMap = {
+  zh: cn,
+  en: en,
+  france: en
+}
+let languageObj = languageMap[current]
 
 export default {
   state: {
     ...languageObj,
-    current: current
+    current: current,
+    languageList: [
+      {
+        name: '简体中文',
+        img: require('@/assets/images/home/China@2x.png'),
+        value: 'zh'
+      },
+      {
+        name: 'ENGLISH',
+        img: require('@/assets/images/home/USA@2x.jpg'),
+        value: 'en'
+      },
+      // {
+      //   name: 'Français',
+      //   img: require('@/assets/images/home/France@2x.jpg'),
+      //   value: 'france'
+      // }
+    ]
   },
   mutations: {
     change_language (state, language) {
-      let languageObj = language === '中' ? cn : en
+      let languageObj = languageMap[language]
       Object.keys(languageObj).forEach(key => {
         state[key] = languageObj[key]
       })
       state.current = language
       localStorage.setItem('language', language)
+      
     }
   }
 }

+ 11 - 5
pc/src/store/user.js

@@ -33,6 +33,7 @@ try {
 
 export default {
   state: {
+    isInternational: process.env.IS_INTERNATIONAL,
     token: token,
     fdkankantoken,
     name: null,
@@ -185,7 +186,8 @@ export default {
 
       let data = res.data
       if (data.code !== 0) {
-        return vue.$toast.show('warn', toastCode[data.code])
+        vue.$toast.show('warn', toastCode[data.code])
+        return 
       }
       let token = data.data.token
       context.commit('saveToken', token)
@@ -194,6 +196,7 @@ export default {
         context.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
         context.dispatch('getCart')
       }
+      return true
     },
     async logout (context, params) {
       let toastCode = localStorage.getItem('language') === 'en' ? toastEN : toastZH
@@ -426,18 +429,20 @@ export default {
 
       if (phone || email) {
         let resp = await http
-          .post('/sso/user/checkUser', {phoneNum: phone, email})
+          .post('/sso/user/checkUser', {phoneNum: phone || email})
 
         switch (type) {
           case 'resigter':
             if (resp.data.code === 0) {
-              return vue.$toast.show('warn', toastCode[3008])
+              vue.$toast.show('warn', toastCode[3008])
+              return
             }
             break
 
           default:
             if (resp.data.code !== 0) {
-              return vue.$toast.show('warn', toastCode[resp.data.code])
+              vue.$toast.show('warn', toastCode[resp.data.code])
+              return
             }
             break
         }
@@ -460,7 +465,8 @@ export default {
         })
         return true
       } else {
-        return vue.$toast.show('warn', toastCode['29'])
+        vue.$toast.show('warn', toastCode['29'])
+        return false
       }
     }
   }

+ 8 - 9
pc/src/util/http.js

@@ -21,8 +21,7 @@ axios.defaults.retryDelay = 1000
 axios.interceptors.request.use(function (config) {
   if (config.method === 'post') {
     config.data = {
-      ...config.data,
-      rnd: Math.random()
+      ...config.data
     }
     // config.data = qs.stringify(config.data)
   } else if (config.method === 'get') {
@@ -64,13 +63,13 @@ axios.interceptors.response.use(
       }
     }
     switch (code) {
-      // case 3004:
-      //   let msg = localStorage.getItem('language') === 'en' ? 'Please re-log in.' : '请重新登录'
-      //   store.state.user.token && vue.$toast.show('warn', msg, async () => {
-      //     await store.dispatch('logout')
-      //     router.push({name: 'home'})
-      //   })
-      //   break
+      case 3004:
+        let msg = localStorage.getItem('language') === 'en' ? 'Please re-log in.' : '请重新登录'
+        store.state.user.token && vue.$toast.show('warn', msg, async () => {
+          await store.dispatch('logout')
+          router.push({name: 'home'})
+        })
+        break
       default:
         break
     }

+ 33 - 0
pc/src/util/tools.js

@@ -0,0 +1,33 @@
+
+export function deepExtend (){
+    var obj1 = arguments[0];
+    var obj2 = arguments[1];
+    //存放结果对象
+    var resObj = {};
+    if(typeof(obj1) != 'object' || typeof(obj2) != 'object'){
+        console.warn('Not object');
+        return
+    }
+    //遍历obj1的所有属性
+    for(var i in obj1){
+        //如果对象2里面有对象1的这个属性则继承过来,否则resObj放obj1[i]
+        if(obj2.hasOwnProperty(i)){
+            if(typeof(obj1[i]) == 'object'){
+                //如果obj1[i]是一个对象,那么递归调用这个方法,并把resObj[i]的属性设置为结果
+                resObj[i] = deepExtend(obj1[i],obj2[i])
+            }else{
+                resObj[i] = obj2[i];
+            }
+        }else{
+            resObj[i] = obj1[i];
+        }
+    }
+
+    for(var j in obj2){
+        //上一步已经把obj1和obj2共有的属性全替换为obj2的属性,所以这里只需把obj1里不具有的obj2的属性复制即可
+        if(!obj1.hasOwnProperty(j)){
+            resObj[j] = obj2[j];
+        }
+    }
+    return resObj
+}