徐志豪 5 lat temu
rodzic
commit
d03a6a9bfd
100 zmienionych plików z 3924 dodań i 296 usunięć
  1. 40 8
      mobile/package-lock.json
  2. 2 1
      pc/build/webpack.base.conf.js
  3. 2 1
      pc/build/webpack.prod.conf.js
  4. 1 1
      pc/config/index.js
  5. 1 0
      pc/index.html
  6. 120 0
      pc/package-lock.json
  7. 3 1
      pc/package.json
  8. 4 4
      pc/src/App.vue
  9. 15 1
      pc/src/apis/index.js
  10. BIN
      pc/src/assets/images/home/solutions-sec.png
  11. BIN
      pc/src/assets/images/home/solutions-sec@2x.png
  12. BIN
      pc/src/assets/images/refactor/conductExhibition/banner.png
  13. BIN
      pc/src/assets/images/refactor/coreTech/AI AR SLAM 01(剪辑版2).mp4
  14. BIN
      pc/src/assets/images/refactor/home-video.mp4
  15. BIN
      pc/src/assets/images/refactor/mall/ali-icon.png
  16. BIN
      pc/src/assets/images/refactor/mall/delete-icon.png
  17. BIN
      pc/src/assets/images/refactor/mall/delete-icon@2x.png
  18. BIN
      pc/src/assets/images/refactor/mall/edit-icon.png
  19. BIN
      pc/src/assets/images/refactor/mall/edit-icon@2x.png
  20. BIN
      pc/src/assets/images/refactor/mall/pay-channel.png
  21. BIN
      pc/src/assets/images/refactor/mall/scan-tip.png
  22. BIN
      pc/src/assets/images/refactor/mall/wechat-icon.png
  23. BIN
      pc/src/assets/images/refactor/news/banner.png
  24. BIN
      pc/src/assets/images/refactor/news/banner2.png
  25. BIN
      pc/src/assets/images/refactor/news/banner2@2x.png
  26. BIN
      pc/src/assets/images/refactor/news/banner3.png
  27. BIN
      pc/src/assets/images/refactor/news/banner3@2x.png
  28. BIN
      pc/src/assets/images/refactor/news/banner@2x.png
  29. BIN
      pc/src/assets/images/refactor/news/fade-bg.png
  30. BIN
      pc/src/assets/images/refactor/news/left-arrow.png
  31. BIN
      pc/src/assets/images/refactor/news/new-1.png
  32. BIN
      pc/src/assets/images/refactor/news/new-10.png
  33. BIN
      pc/src/assets/images/refactor/news/new-10@2x.png
  34. BIN
      pc/src/assets/images/refactor/news/new-11.png
  35. BIN
      pc/src/assets/images/refactor/news/new-11@2x.png
  36. BIN
      pc/src/assets/images/refactor/news/new-12.png
  37. BIN
      pc/src/assets/images/refactor/news/new-12@2x.png
  38. BIN
      pc/src/assets/images/refactor/news/new-1@2x.png
  39. BIN
      pc/src/assets/images/refactor/news/new-2.png
  40. BIN
      pc/src/assets/images/refactor/news/new-2@2x.png
  41. BIN
      pc/src/assets/images/refactor/news/new-3.png
  42. BIN
      pc/src/assets/images/refactor/news/new-3@2x.png
  43. BIN
      pc/src/assets/images/refactor/news/new-4.png
  44. BIN
      pc/src/assets/images/refactor/news/new-4@2x.png
  45. BIN
      pc/src/assets/images/refactor/news/new-5.png
  46. BIN
      pc/src/assets/images/refactor/news/new-5@2x.png
  47. BIN
      pc/src/assets/images/refactor/news/new-6.png
  48. BIN
      pc/src/assets/images/refactor/news/new-6@2x.png
  49. BIN
      pc/src/assets/images/refactor/news/new-7.png
  50. BIN
      pc/src/assets/images/refactor/news/new-7@2x.png
  51. BIN
      pc/src/assets/images/refactor/news/new-8.png
  52. BIN
      pc/src/assets/images/refactor/news/new-8@2x.png
  53. BIN
      pc/src/assets/images/refactor/news/new-9.png
  54. BIN
      pc/src/assets/images/refactor/news/new-9@2x.png
  55. BIN
      pc/src/assets/images/refactor/news/right-arrow.png
  56. 3 3
      pc/src/assets/style/public.scss
  57. 1 1
      pc/src/components/browseVideo/index.vue
  58. 18 5
      pc/src/components/mall/number.vue
  59. 4 4
      pc/src/components/priceTable/index.vue
  60. 4 0
      pc/src/components/shared/Icon.vue
  61. 64 15
      pc/src/components/shared/MessageBox/MessageBox.vue
  62. 10 1
      pc/src/components/shared/MessageBox/plugin.js
  63. 2 2
      pc/src/components/shared/Modal.vue
  64. 61 0
      pc/src/config/mall.js
  65. 98 0
      pc/src/config/newsData.js
  66. 30 15
      pc/src/page/cases/index.vue
  67. 1 1
      pc/src/page/conduct/conductExhibition/index.vue
  68. 2 2
      pc/src/page/conduct/conductSecury/index.vue
  69. 1 1
      pc/src/page/conduct/conductShop/index.vue
  70. 51 17
      pc/src/page/distributor/index.vue
  71. 22 42
      pc/src/page/home2/index.vue
  72. 26 2
      pc/src/page/home2/style.scss
  73. 2 2
      pc/src/page/introduce/index.vue
  74. 23 16
      pc/src/page/layout/footer.vue
  75. 12 25
      pc/src/page/layout/header/index.vue
  76. 5 0
      pc/src/page/layout/header/istyle.scss
  77. 0 11
      pc/src/page/layout/normal.vue
  78. 0 11
      pc/src/page/layout/shop.vue
  79. 115 18
      pc/src/page/layout/shopHeader/index.vue
  80. 11 4
      pc/src/page/location/index.vue
  81. 6 3
      pc/src/page/login/components/cameraLogin.vue
  82. 9 2
      pc/src/page/login/components/codeLogin.vue
  83. 16 13
      pc/src/page/login/components/forget/emailForm.vue
  84. 3 3
      pc/src/page/login/components/login.vue
  85. 411 0
      pc/src/page/mall/cart/index.vue
  86. 93 0
      pc/src/page/mall/cloudCapacity/index.vue
  87. 364 0
      pc/src/page/mall/confirm/components/addressModule.vue
  88. 138 0
      pc/src/page/mall/confirm/components/citySelect.vue
  89. 453 0
      pc/src/page/mall/confirm/components/invoiceModule.vue
  90. 424 0
      pc/src/page/mall/confirm/index.vue
  91. 130 29
      pc/src/page/mall/kankanPro/index.vue
  92. 45 13
      pc/src/page/mall/kankanPro/style.scss
  93. 282 0
      pc/src/page/mall/pay/index.vue
  94. 307 0
      pc/src/page/mall/zhijia/index.vue
  95. 461 0
      pc/src/page/mall/zhijia/style.scss
  96. 19 15
      pc/src/page/manage/index.vue
  97. 7 2
      pc/src/page/manage/style.scss
  98. 1 0
      pc/src/page/manage/temp/information.vue
  99. 1 1
      pc/src/page/manage/temp/order.vue
  100. 0 0
      pc/src/page/news/index.vue

+ 40 - 8
mobile/package-lock.json

@@ -6023,7 +6023,8 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -6438,7 +6439,8 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -6494,6 +6496,7 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -6537,12 +6540,14 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         }
       }
     },
@@ -8712,10 +8717,9 @@
       }
     },
     "js-base64": {
-      "version": "2.5.1",
-      "resolved": "http://registry.npm.taobao.org/js-base64/download/js-base64-2.5.1.tgz",
-      "integrity": "sha1-Hvo57yxfeYC7F4St5KivLeMpESE=",
-      "dev": true
+      "version": "2.6.4",
+      "resolved": "https://registry.npm.taobao.org/js-base64/download/js-base64-2.6.4.tgz?cache=0&sync_timestamp=1596920559006&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-base64%2Fdownload%2Fjs-base64-2.6.4.tgz",
+      "integrity": "sha1-9OaGxd4eofhn28rT1G2WlCjfmMQ="
     },
     "js-beautify": {
       "version": "1.10.2",
@@ -8860,6 +8864,24 @@
       "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
       "dev": true
     },
+    "jsonp": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npm.taobao.org/jsonp/download/jsonp-0.2.1.tgz",
+      "integrity": "sha1-pltPoPEL2nGaBUQep7lMVfPhW64=",
+      "requires": {
+        "debug": "^2.1.3"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz",
+          "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz",
@@ -13260,6 +13282,11 @@
       "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
       "dev": true
     },
+    "qqsdk": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npm.taobao.org/qqsdk/download/qqsdk-0.1.5.tgz",
+      "integrity": "sha1-XRuWDWOBbDRdcy9biTzURWVNv2Y="
+    },
     "qs": {
       "version": "6.5.2",
       "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1569207136481&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz",
@@ -17116,6 +17143,11 @@
       "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=",
       "dev": true
     },
+    "weixin-js-sdk": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npm.taobao.org/weixin-js-sdk/download/weixin-js-sdk-1.6.0.tgz",
+      "integrity": "sha1-/1BITYEYzhII8RJIz0ocCDFXdRQ="
+    },
     "whatwg-encoding": {
       "version": "1.0.5",
       "resolved": "http://registry.npm.taobao.org/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz",

+ 2 - 1
pc/build/webpack.base.conf.js

@@ -56,7 +56,8 @@ module.exports = {
         loader: 'url-loader',
         options: {
           limit: 10000,
-          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+          name: utils.assetsPath('img/[name].[hash:7].[ext]'),
+          publicPath: 'https://4dscene.4dage.com/new4dkk/v2'
         }
       },
       {

+ 2 - 1
pc/build/webpack.prod.conf.js

@@ -17,11 +17,12 @@ const env = process.env.NODE_ENV === 'testing'
 
 const webpackConfig = merge(baseWebpackConfig, {
   module: {
-    rules: utils.styleLoaders({
+    rules: [...utils.styleLoaders({
       sourceMap: config.build.productionSourceMap,
       extract: true,
       usePostCSS: true
     })
+  ]
   },
   devtool: config.build.productionSourceMap ? config.build.devtool : false,
   output: {

+ 1 - 1
pc/config/index.js

@@ -48,7 +48,7 @@ module.exports = {
 
     // Paths
     assetsRoot: path.resolve(__dirname, '../../dist/www'),
-    assetsSubDirectory: 'static',
+    assetsSubDirectory: '',
     assetsPublicPath: './www/',
 
     /**

+ 1 - 0
pc/index.html

@@ -14,6 +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="apple-touch-icon" sizes="180x180" href="//4dkk.4dage.com/FDKKIMG/icon/kankan_icon180.png">
     <title>四维看看</title>
     <script>

+ 120 - 0
pc/package-lock.json

@@ -1981,6 +1981,12 @@
       "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=",
       "dev": true
     },
+    "basic-auth": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npm.taobao.org/basic-auth/download/basic-auth-1.1.0.tgz",
+      "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=",
+      "dev": true
+    },
     "batch": {
       "version": "0.6.1",
       "resolved": "http://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz",
@@ -3210,6 +3216,12 @@
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
       "dev": true
     },
+    "corser": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npm.taobao.org/corser/download/corser-2.0.1.tgz",
+      "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
+      "dev": true
+    },
     "cosmiconfig": {
       "version": "5.2.1",
       "resolved": "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz",
@@ -4726,6 +4738,26 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "ecstatic": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npm.taobao.org/ecstatic/download/ecstatic-3.3.2.tgz",
+      "integrity": "sha1-bR3UmBTQBZRoLGUq22YHamnUbEg=",
+      "dev": true,
+      "requires": {
+        "he": "^1.1.1",
+        "mime": "^1.6.0",
+        "minimist": "^1.1.0",
+        "url-join": "^2.0.5"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
+          "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=",
+          "dev": true
+        }
+      }
+    },
     "editorconfig": {
       "version": "0.15.3",
       "resolved": "https://registry.npm.taobao.org/editorconfig/download/editorconfig-0.15.3.tgz",
@@ -7572,6 +7604,73 @@
         }
       }
     },
+    "http-server": {
+      "version": "0.12.3",
+      "resolved": "https://registry.npm.taobao.org/http-server/download/http-server-0.12.3.tgz",
+      "integrity": "sha1-ugRx0OzEJYhmFss1xPryeRQKDTc=",
+      "dev": true,
+      "requires": {
+        "basic-auth": "^1.0.3",
+        "colors": "^1.4.0",
+        "corser": "^2.0.1",
+        "ecstatic": "^3.3.2",
+        "http-proxy": "^1.18.0",
+        "minimist": "^1.2.5",
+        "opener": "^1.5.1",
+        "portfinder": "^1.0.25",
+        "secure-compare": "3.0.1",
+        "union": "~0.5.0"
+      },
+      "dependencies": {
+        "colors": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npm.taobao.org/colors/download/colors-1.4.0.tgz",
+          "integrity": "sha1-xQSRR51MG9rtLJztMs98fcI2D3g=",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz",
+          "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "minimist": {
+          "version": "1.2.5",
+          "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
+          "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=",
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "0.5.5",
+          "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz",
+          "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz",
+          "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=",
+          "dev": true
+        },
+        "portfinder": {
+          "version": "1.0.28",
+          "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.28.tgz?cache=0&sync_timestamp=1596018176291&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fportfinder%2Fdownload%2Fportfinder-1.0.28.tgz",
+          "integrity": "sha1-Z8RiKFK9U3TdHdkA93n1NGL6x3g=",
+          "dev": true,
+          "requires": {
+            "async": "^2.6.2",
+            "debug": "^3.1.1",
+            "mkdirp": "^0.5.5"
+          }
+        }
+      }
+    },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz",
@@ -14807,6 +14906,12 @@
         }
       }
     },
+    "secure-compare": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npm.taobao.org/secure-compare/download/secure-compare-3.0.1.tgz",
+      "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=",
+      "dev": true
+    },
     "select-hose": {
       "version": "2.0.0",
       "resolved": "http://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz",
@@ -16285,6 +16390,15 @@
         }
       }
     },
+    "union": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npm.taobao.org/union/download/union-0.5.0.tgz",
+      "integrity": "sha1-ssEb6E9gU4U3uEbtuboma6AJAHU=",
+      "dev": true,
+      "requires": {
+        "qs": "^6.4.0"
+      }
+    },
     "union-value": {
       "version": "1.0.1",
       "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz?cache=0&sync_timestamp=1561411160492&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funion-value%2Fdownload%2Funion-value-1.0.1.tgz",
@@ -16430,6 +16544,12 @@
         }
       }
     },
+    "url-join": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npm.taobao.org/url-join/download/url-join-2.0.5.tgz",
+      "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
+      "dev": true
+    },
     "url-loader": {
       "version": "0.5.9",
       "resolved": "https://registry.npm.taobao.org/url-loader/download/url-loader-0.5.9.tgz",

+ 3 - 1
pc/package.json

@@ -11,7 +11,8 @@
     "e2e": "node test/e2e/runner.js",
     "test": "npm run unit && npm run e2e",
     "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
-    "build": "node build/build.js"
+    "build": "node build/build.js",
+    "preview": "http-server ../ -p 3030"
   },
   "dependencies": {
     "axios": "^0.18.0",
@@ -62,6 +63,7 @@
     "file-loader": "^1.1.4",
     "friendly-errors-webpack-plugin": "^1.6.1",
     "html-webpack-plugin": "^2.30.1",
+    "http-server": "^0.12.3",
     "jest": "^22.0.4",
     "jest-serializer-vue": "^0.3.0",
     "less": "^3.9.0",

+ 4 - 4
pc/src/App.vue

@@ -7,7 +7,7 @@
 <script>
 import '@/assets/style/reset.scss'
 import '@/assets/style/public.scss'
-import '@/assets/font/iconfont.css'
+
 import browseVideo from '@/components/browseVideo'
 import header from '@/page/layout/header'
 import footer from '@/page/layout/footer'
@@ -114,8 +114,7 @@ export default {
     })
 
     this.$bus.$on('showAside', data => {
-      this.showLogin = true
-      this.asideCp = data || {type: 'list', sku: [], fromList: true}
+      this.$router.push('/login/login')
     })
 
     this.$bus.$on('hideAside', () => {
@@ -138,7 +137,8 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
+
 #app {
   padding-top: 80px;
   overflow-x: hidden;

+ 15 - 1
pc/src/apis/index.js

@@ -2,9 +2,23 @@ import axios from '@/util/http'
 
 export default {
   saveAduit (data) {
-    return axios.post('agentAduit/save')
+    return axios.post('agentAduit/save', data)
   },
   getEmailAuthCode (data) {
     return axios.post('sso/user/getEmailAuthCode', data)
+  },
+  
+  // 地址模块
+  getReceiverList () {
+    return axios.post('user/getReceiverList')
+  },
+  insertAddress (data) {
+    return axios.post('user/insertAddress', data)
+  },
+  updateAddress (data) {
+    return axios.post('user/updateAddress', data)
+  },
+  deleteAddress (id) {
+    return axios.post('user/deleteAddress', {id})
   }
 }

BIN
pc/src/assets/images/home/solutions-sec.png


BIN
pc/src/assets/images/home/solutions-sec@2x.png


BIN
pc/src/assets/images/refactor/conductExhibition/banner.png


BIN
pc/src/assets/images/refactor/coreTech/AI AR SLAM 01(剪辑版2).mp4


BIN
pc/src/assets/images/refactor/home-video.mp4


BIN
pc/src/assets/images/refactor/mall/ali-icon.png


BIN
pc/src/assets/images/refactor/mall/delete-icon.png


BIN
pc/src/assets/images/refactor/mall/delete-icon@2x.png


BIN
pc/src/assets/images/refactor/mall/edit-icon.png


BIN
pc/src/assets/images/refactor/mall/edit-icon@2x.png


BIN
pc/src/assets/images/refactor/mall/pay-channel.png


BIN
pc/src/assets/images/refactor/mall/scan-tip.png


BIN
pc/src/assets/images/refactor/mall/wechat-icon.png


BIN
pc/src/assets/images/refactor/news/banner.png


BIN
pc/src/assets/images/refactor/news/banner2.png


BIN
pc/src/assets/images/refactor/news/banner2@2x.png


BIN
pc/src/assets/images/refactor/news/banner3.png


BIN
pc/src/assets/images/refactor/news/banner3@2x.png


BIN
pc/src/assets/images/refactor/news/banner@2x.png


BIN
pc/src/assets/images/refactor/news/fade-bg.png


BIN
pc/src/assets/images/refactor/news/left-arrow.png


BIN
pc/src/assets/images/refactor/news/new-1.png


BIN
pc/src/assets/images/refactor/news/new-10.png


BIN
pc/src/assets/images/refactor/news/new-10@2x.png


BIN
pc/src/assets/images/refactor/news/new-11.png


BIN
pc/src/assets/images/refactor/news/new-11@2x.png


BIN
pc/src/assets/images/refactor/news/new-12.png


BIN
pc/src/assets/images/refactor/news/new-12@2x.png


BIN
pc/src/assets/images/refactor/news/new-1@2x.png


BIN
pc/src/assets/images/refactor/news/new-2.png


BIN
pc/src/assets/images/refactor/news/new-2@2x.png


BIN
pc/src/assets/images/refactor/news/new-3.png


BIN
pc/src/assets/images/refactor/news/new-3@2x.png


BIN
pc/src/assets/images/refactor/news/new-4.png


BIN
pc/src/assets/images/refactor/news/new-4@2x.png


BIN
pc/src/assets/images/refactor/news/new-5.png


BIN
pc/src/assets/images/refactor/news/new-5@2x.png


BIN
pc/src/assets/images/refactor/news/new-6.png


BIN
pc/src/assets/images/refactor/news/new-6@2x.png


BIN
pc/src/assets/images/refactor/news/new-7.png


BIN
pc/src/assets/images/refactor/news/new-7@2x.png


BIN
pc/src/assets/images/refactor/news/new-8.png


BIN
pc/src/assets/images/refactor/news/new-8@2x.png


BIN
pc/src/assets/images/refactor/news/new-9.png


BIN
pc/src/assets/images/refactor/news/new-9@2x.png


BIN
pc/src/assets/images/refactor/news/right-arrow.png


+ 3 - 3
pc/src/assets/style/public.scss

@@ -15,8 +15,8 @@ $theme-color:#1fe4dc;
 }
 
 .container {
-
-  max-width: 1276px;
+  height: 100%;
+  width: 1276px;
   margin: 0 auto;
 }
 
@@ -516,4 +516,4 @@ $padding:20px;
   100% {
     opacity: 1;
   }
-}
+}

+ 1 - 1
pc/src/components/browseVideo/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="brow-layout" @click="closeVideo">
     <div class="con" @click.stop>
-        <video :src="`${$cdn}course/videos/${url}.mp4`" autoplay controls loop></video>
+        <video :src="url.indexOf('http') === -1 ? `${$cdn}course/videos/${url}.mp4` : url" autoplay controls loop></video>
     </div>
   </div>
 </template>

+ 18 - 5
pc/src/components/mall/number.vue

@@ -1,8 +1,6 @@
 <template>
-  <div class="number-input">
-    <div class="input-btn reduce">-</div>
-    <input  v-model="num" @input="onInput($event)"  />
-    <div class="input-btn add">+</div>
+  <div class="number-input" @click.stop="">
+    <div class="input-btn reduce" @click.stop="odd">-</div><input :disabled="inputDisabled" v-model="num" @input="onInput($event)"  /><div class="input-btn add" @click.stop="add">+</div>
   </div>
 </template>
 
@@ -13,7 +11,8 @@ export default {
       type: [String, Number],
       default: 1
     },
-    max: Number
+    max: Number,
+    inputDisabled: Boolean
   },
   data () {
     return {
@@ -24,6 +23,9 @@ export default {
     prop: 'value',
     event: 'input'
   },
+  mounted () {
+    this.num = this.value || 1
+  },
   methods: {
     onInput ($event) {
       let value = Number($event.target.value.replace(/[^\d]/g,''))
@@ -40,6 +42,14 @@ export default {
       this.num = value
       this.$emit('input', value)
       return false
+    },
+    add () {
+      this.onInput({target: {value: this.num + 1 + ''}})
+      this.$emit('add')
+    },
+    odd () {
+      this.onInput({target: {value: this.num - 1 + ''}})
+      this.$emit('reduce')
     }
   }
 
@@ -68,5 +78,8 @@ input {
   width: 58px;
   text-align: center;
   vertical-align: middle;
+  &:disabled {
+    background: #fff;
+  }
 }
 </style>

+ 4 - 4
pc/src/components/priceTable/index.vue

@@ -69,9 +69,9 @@ export default {
   box-sizing:border-box;
   border-top: 1px solid #e7e7e7;
   border-left: 1px solid #e7e7e7;
-  width: 621px;
+  width: 844px;
   .box{
-    width: 130px;
+    width: 194px;
     height: 100px;
     display: inline-block;
     vertical-align: top;
@@ -119,7 +119,7 @@ export default {
     }
   }
   .long{
-    width: 180px;
+    width: 226px;
     .thin{
       line-height: 50px;
       span{
@@ -133,7 +133,7 @@ export default {
   }
   }
   .price{
-    width: 360px;
+    width: 452px;
     font-size: 16px;
     display: inline-block;
     vertical-align: top;

+ 4 - 0
pc/src/components/shared/Icon.vue

@@ -21,3 +21,7 @@ export default {
   }
 }
 </script>
+
+<style lang="less">
+
+</style>

+ 64 - 15
pc/src/components/shared/MessageBox/MessageBox.vue

@@ -6,20 +6,32 @@
     :close-on-click-mask="closeOnClickMask"
     :close-on-press-escape="closeOnPressEscape"
     @hide="handleAction('close')"
-  >
-    <div class="h-message-box">
-      <header v-if="title" class="h-message-box__header">
-        <HIcon v-if="icon" :type="icon" />
-        {{ title }}
-      </header>
-      <main class="h-message-box__body">
-        <div class="h-message-box__message">{{ message }}</div>
-      </main>
-      <footer class="h-message-box__footer">
-        <div plain :class="cancelButtonClass" v-if="!hideCancleButton" @click="handleAction('cancel')">{{ cancelButtonText }}</div>
-        <div ref="confirm" :class="confirmButtonClass" @click="handleAction('confirm')">{{ confirmButtonText }}</div>
-      </footer>
-    </div>
+  > 
+    <template>
+      
+      <div class="h-message-box" v-if="type !== 'alert'">
+        <header v-if="title" class="h-message-box__header">
+          <HIcon v-if="icon" :type="icon" />
+          {{ title }}
+        </header>
+        <main class="h-message-box__body">
+          <div class="h-message-box__message">{{ message }}</div>
+        </main>
+        <footer class="h-message-box__footer">
+          <div plain :class="cancelButtonClass" v-if="!hideCancleButton" @click="handleAction('cancel')">{{ cancelButtonText }}</div>
+          <div ref="confirm" :class="confirmButtonClass" @click="handleAction('confirm')">{{ confirmButtonText }}</div>
+        </footer>
+      </div>
+      <div class="h-alert-box" v-else>
+        <div class="warn-icon">
+          <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>
+    </template>
+    
+    
   </HModal>
 </template>
 
@@ -43,7 +55,8 @@ export default {
       mask: true,
       closeOnClickMask: true,
       closeOnPressEscape: true,
-      hideCancleButton: false
+      hideCancleButton: false,
+      type: ''
     }
   },
 
@@ -111,4 +124,40 @@ export default {
     margin-left: 10px;
   }
 }
+
+.h-alert-box {
+  width: 335px;
+  height: 256px;
+  padding: 48px 50px 30px;
+  .warn-icon {
+    width: 52px;
+    height: 52px;
+    border: 1px solid #ebebeb;
+    border-radius: 50%;
+    text-align: center;
+    line-height: 52px;
+    color: #1FE4DC;
+    margin: 0 auto 10px;
+    font-weight: bold;
+    font-size: 40px;
+  }
+  .message {
+    color: #909090;
+    font-size: 16px;
+    font-weight: 600;
+    line-height: 20px;
+    width: 194px;
+    text-align: center;
+    margin: 0 auto;
+  }
+  .submit-btn {
+    width: 100%;
+    background: #1FE4DC;
+    line-height: 40px;
+    text-align: center;
+    font-weight: bold;
+    margin-top: 30px;
+    cursor: pointer;
+  }
+}
 </style>

+ 10 - 1
pc/src/components/shared/MessageBox/plugin.js

@@ -118,9 +118,15 @@ MessageBox.setDefaults = defaults => {
 }
 
 MessageBox.alert = (message, title, options) => {
+  let iconMap = {
+    warn: 'tanhao',
+    success: 'duihao'
+  }
+  let icon = iconMap['warn']
   if (typeof title === 'object') {
     options = title
     title = defaults.title
+    options.icon = iconMap[options.icon]
   } else if (title === undefined) {
     title = defaults.title
   }
@@ -130,7 +136,10 @@ MessageBox.alert = (message, title, options) => {
     $type: 'alert',
     closeOnPressEscape: false,
     closeOnClickModal: false,
-    hideCancleButton: true
+    hideCancleButton: true,
+    type: 'alert',
+    showClose: false,
+    icon
   }, options))
 }
 

+ 2 - 2
pc/src/components/shared/Modal.vue

@@ -85,7 +85,7 @@ export default {
   left: 0;
   width: 100%;
   height: 100%;
-  z-index: 100;
+  z-index: 1000;
 }
 .h-modal {
   position: fixed;
@@ -105,7 +105,7 @@ export default {
     position: relative;
     display: inline-block;
     margin: 0 auto;
-    z-index: 101;
+    z-index: 1001;
     background: #fff;
     box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
     vertical-align: middle;

+ 61 - 0
pc/src/config/mall.js

@@ -0,0 +1,61 @@
+function formatNum(num){
+  return (num.toFixed(0) + '').replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,');
+}
+
+let cameraName = {
+  7: `四维看看 三脚架套装`,
+  1: `四维看看 Lite二目相机`,
+  4: `四维看看 Pro八目相机`
+}
+
+let cameraNameEn = {
+  7: `4D KanKan Pro Tripod Set`,
+  1: `四维看看 Lite二目相机`,
+  4: `4DKanKan Pro Camera`
+}
+let detail = {
+  7: ['四维看看 三脚架套装(标准色)'],
+  1: [
+    '四维看看 Lite二目相机(静谧黑)',
+    '容量套餐(5G)',
+    '四维看看 Lite专用三脚架(标准色)'
+  ],
+  4: ['四维看看 Pro八目相机(静谧黑)', '容量套餐(10G)']
+}
+let detailEn = {
+  7: ['4D KanKan Pro Tripod Set (Standard)'],
+  1: [
+    '四维看看 Lite二目相机(静谧黑)',
+    '容量套餐(5G)',
+    '四维看看 Lite专用三脚架(标准色)'
+  ],
+  4: ['4DKanKan Pro Camera (Night Sky Black)', 'Storage Plan (10G)']
+}
+const price = 12800
+const zhijiaPrice = 899
+
+const goodsMap = {
+  4: {
+    name: '四维看看Pro八目相机',
+    img: `${window.$app.$cdn}images/banner_pro.png`,
+    detail: ['四维看看Pro八目相机(静谧黑)', '容量套餐(10G)'],
+    price: price,
+    skuSn: 'U15609161635760015'
+  },
+  7: {
+    name: '四维看看Pro精选三脚架套装',
+    img: `${window.$app.$cdn}images/zhijia.png`,
+    detail:  ['四维看看Pro精选三脚架套装(标准色)'],
+    price: zhijiaPrice,
+    skuSn: 'U15604134406280073'
+  }
+}
+
+
+export default {
+  formatNum,
+  price,
+  zhijiaPrice,
+  showPrice: formatNum(price),
+  goodsMap
+}

Plik diff jest za duży
+ 98 - 0
pc/src/config/newsData.js


+ 30 - 15
pc/src/page/cases/index.vue

@@ -11,10 +11,11 @@
   <div class="case-body container" >
     <div class="body-header clear">
       <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 :type="item.icon" />{{ item.name }}</li>
+        <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="输入搜索关键字">
+        <input type="text" placeholder="输入搜索关键字" v-model="searchKey" @keyup.enter="getData">
+        <h-icon type="sousuo" class="icon" @click="getData"></h-icon>
       </div>
     </div>
     <h-row :gutter="20">
@@ -51,19 +52,27 @@ const types = [
   },
   {
     id: 2,
-    name: '房屋地产'
+    name: '地产'
   },
   {
     id: 1,
-    name: '文博展览'
+    name: '会展'
   },
   {
     id: 4,
-    name: '餐饮家居'
+    name: '文博'
   },
   {
     id: null,
-    name: '消安刑侦'
+    name: '商圈'
+  },
+  {
+    id: null,
+    name: '旅游'
+  },
+  {
+    id: 0,
+    name: '其它'
   },
 ]
 
@@ -107,6 +116,7 @@ export default {
       isWide: window.innerWidth > 1697,
       selected: '四维看看 Pro',
       caseType: null,
+      searchKey: ''
     }
   },
   // 监听属性 类似于data概念
@@ -161,7 +171,8 @@ export default {
         sceneType: this.caseType,
         sceneInterest: this.sortActive,
         pageNum: this.currentPage,
-        sceneScheme: sceneSTYpe[this.selected]
+        sceneScheme: sceneSTYpe[this.selected],
+        searchKey: this.searchKey
       }
       let result = await this.$http({
         method: 'post',
@@ -184,14 +195,6 @@ export default {
   },
   // 生命周期 - 挂载完成(可以访问DOM元素)
   mounted () {
-    document.addEventListener('click', (e) => {
-      console.log(this.$refs.mbMenu.contains)
-      if (this.$refs.mbMenu) {
-        if (!this.$refs.mbMenu.contains(e.target)) {
-          this.selectActive = false
-        }
-      }
-    })
     window.addEventListener('resize', () => {
       this.isWide = window.innerWidth > 1697
     })
@@ -240,6 +243,17 @@ export default {
     &:hover, &.is-active {
       color: #202020;
     }
+    .icon {
+      margin-right: 4px;
+    }
+  }
+  .search {
+    position: relative;
+    .icon {
+    position: absolute;
+    right: 10px;
+    cursor: pointer;
+  }
   }
   input {
     background: #EBEBEB;
@@ -248,6 +262,7 @@ export default {
     width: 256px;
     padding-left: 20px;
   }
+  
 }
 .paging {
   // border-left: #e5e5e5 1px solid;

+ 1 - 1
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">看展 • 随时随地参展办展</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">

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

@@ -1,5 +1,5 @@
 <template>
-  <div class="conduct-display">
+  <div class="conduct-secury">
     <div class="banner">
       <div class="container">安防勘查</div>
     </div>
@@ -51,7 +51,7 @@ export default {
 }
 </script>
 <style lang="scss">
-.conduct-display {
+.conduct-secury {
   .banner {
     width: 100%;
     height: 420px;

+ 1 - 1
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">看店 • 宅家中 轻松买</div>
     </div>
     <div class="plate-w" ref="homeLayout">
       <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">

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

@@ -1,5 +1,5 @@
 <template>
-  <div class="conduct-subject">
+  <div class="distributor-page">
     <div class="banner">
       <div class="container">成为四维看看经销商</div>
     </div>
@@ -23,7 +23,10 @@
           </div>
         </div>
       </div>
-      <div class="form-plate">
+    </div>
+
+    <div class="form-plate">
+      <div class="container">
         <h1 class="common-title">成为四维看看经销商</h1>
         <h-row :gutter="96">
           <h-col :span="12">
@@ -49,13 +52,13 @@
                 <p class="label">是否有门店或企业网站</p>
                 <h-row :gutter="10">
                   <h-col :span="12">
-                    <div :class="`input ${form.type === 1 ? 'active' : ''}`">线下销售为主</div>
+                    <div :class="`input ${form.type === 1 ? 'active' : ''}`" @click="form.type = 1">线下销售为主</div>
                   </h-col>
                   <h-col :span="12">
-                    <div  :class="`input ${form.type === 2 ? 'active' : ''}`">线上销售为主</div>
+                    <div  :class="`input ${form.type === 2 ? 'active' : ''}`" @click="form.type = 2">线上销售为主</div>
                   </h-col>
                 </h-row>
-                <input type="text" v-model="form.storeAddress" placeholder="请输入门店详细地址">
+                <input type="text" v-model="form.storeAddress" :placeholder="`请输入${form.type === 1 ? '门店详细地址' : '企业网站网址'}`">
               </div>
             </div>
           </h-col>
@@ -94,7 +97,7 @@
               </div>
             </div></h-col>
         </h-row>
-        <div class="submit-btn">提交</div>
+        <div class="submit-btn" @click="saveAduit">提交</div>
       </div>
     </div>
     
@@ -104,7 +107,6 @@
 <script>
 import { getPosition } from '@/util'
 import { mapState } from 'vuex'
-import sequence from '@/components/sequence'
 import Api from '@/apis'
 export default {
   data () {
@@ -124,6 +126,17 @@ export default {
         type: 1,
         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: '请填写联系邮箱' } ],
+      },
       benefits: [
         {
           name: '利润分成',
@@ -154,7 +167,6 @@ export default {
     }
   },
   components: {
-    sequence
   },
   mounted () {
   },
@@ -162,19 +174,35 @@ export default {
   },
   methods: {
     saveAduit () {
-      console.log(this.form)
-      return Api.saveAduit(this.form).then(res => {
-        console.log(res)
-      })
+      if (this.validator()) {
+        return Api.saveAduit(this.form).then(res => {
+          if (res.data.code === 0) {
+            this.$alert('提交成功', {
+              icon: 'success',
+            })
+          } else {
+            this.$alert(res.msg)
+          }
+        })
+      }
+      
     },
     validator () {
-
+      let pass = true
+      Object.keys(this.rules).forEach(key => {
+        if (this.rules[key][0].required && !this.form[key]) {
+          pass = false
+          this.$alert(this.rules[key][0].message)
+          return
+        }
+      })
+      return pass
     }
   }
 }
 </script>
-<style lang="scss">
-.conduct-subject {
+<style lang="scss" >
+.distributor-page {
   color: #202020;
   .banner {
     width: 100%;
@@ -215,7 +243,11 @@ export default {
     }
   }
   .form-plate {
-    padding-bottom: 160px;
+    padding: 102px 0 160px;
+    background: #F7F7F7;
+    .common-title {
+      margin-top: 0;
+    }
   }
   .form {
     color: #202020;
@@ -237,14 +269,16 @@ export default {
       height: 40px;
       line-height: 38px;
       margin-top: 10px;
-      color: #909090;
+      
       font-size: 14px;
       padding: 0 10px;
+      background: #fff;
     }
     
   }
   .input {
       cursor: pointer;
+      color: #909090;
       &.active {
         color: #202020;
       }

+ 22 - 42
pc/src/page/home2/index.vue

@@ -2,19 +2,21 @@
   <div class="home-layout">
     <div class="plate01">
       <div class="my-video">
-        <video :src="language==='en'?`${$cdn}video/banner1.mp4`:`${$cdn}video/4dkkPRO_zh.mp4`" autoplay muted loop></video>
-        <div class="video-info">
+        <video :src="language==='en'?`${$cdn}video/banner1.mp4`:require('@/assets/images/refactor/home-video.mp4')" autoplay muted loop></video>
+        <div class="container">
+          <div class="video-info">
           <h1>四维看看Pro</h1>
           <p>精准实景复刻 传递空间价值</p>
           <div class="actions-w">
             <router-link class="buy-btn" to="/mall/kankanPro">立即购买</router-link>
             <router-link class="action-link" to="/about">了解更多</router-link>
-            <span class="watch-btn action-link">观看视频</span>
+            <span class="watch-btn action-link" @click="detailVideo">介绍视频</span>
           </div>
           <div class="distributor">
-            <router-link to="/distributor" class="">成为经销商</router-link>
+            <router-link to="/distributor" class=""><h-icon type="shouyegongzi" class="icon" /><span>成为经销商</span></router-link>
           </div>
         </div>
+        </div>
       </div>
     </div>
     <div class="plate02 container">
@@ -43,7 +45,9 @@
       </ul>
     </div>
     <div class="plate03 container clear">
-      <h1 class="common-title">看看空间</h1>
+      <h1 class="common-title">看看空间
+        <router-link to="/cases/全部" class="more">更多</router-link>
+      </h1>
       <h-row class="space-list" :gutter="20">
         
         <h-col :span="6" class="space-item" v-for="(item,index) in space" :key="index">
@@ -67,15 +71,17 @@
 
     <div class="plate05 " ref="numcount">
       <div class="container">
-        <h1 class="common-title">新闻动态</h1>
+        <h1 class="common-title">新闻动态
+          <router-link to="/news" class="more">更多</router-link>
+        </h1>
         <ul class="news-list">
-          <li class="news-item" v-for="(item, index) in plate05List" :key="index">
-            <div class="news-img" :style="{backgroundImage: `url(${item.imgUrl})`}"></div>
+          <li class="news-item" v-for="(item, index) in plate05List" :key="index" >
+            <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.content }}</p>
-              <div class="news-tag">{{ item.tag }}</div>
+              <p class="news-content">{{ item.text }}</p>
+              <div class="news-tag">{{ item.sub }}</div>
             </div>
           </li>
         </ul>
@@ -96,7 +102,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'
 export default {
   data () {
     return {
@@ -139,7 +145,7 @@ export default {
         title: '安防勘查',
         title_sub: '安防勘查',
         desc: '高效复刻灾害现场,记录全面三维档案',
-        img: require('@/assets/images/home/solutions-house.png'),
+        img: require('@/assets/images/home/solutions-sec.png'),
         list: ['高效复刻灾害现场,记录全面三维档案', '支持预先采集存档,减少理赔纠纷']
       }],
       space: [
@@ -178,36 +184,7 @@ export default {
           imgUrl: require('@/assets/images/home/space_03.png')
         }
       ],
-      plate05List: [
-        {
-          imgUrl: require('@/assets/images/home/news_01@2x.png'),
-          time: '2020年5月9日',
-          title: '四维时代为德国慕尼黑美术馆展览提供独家3D技术支持',
-          content: '展览上,四维看看Pro吸引了现场部分艺术家的目光。其中,慕尼黑美术馆馆长Mr.Robblg则认为:用3D形式来记录展览和博物馆,是一种新颖的记录形式,十分期待本次展览的数字化成果,并且对这款来自"中国造"的3D相机四维看看Pro长生了浓厚的兴',
-          tag: '网易新闻'
-        },
-        {
-          imgUrl: require('@/assets/images/home/news_02@2x.png'),
-          time: '2020年5月9日',
-          title: '四维时代为德国慕尼黑美术馆展览提供独家3D技术支持',
-          content: 'TEFAF是全球规模最大、规格最顶级、欧洲资格最老的艺术博览会之一,一直被公认为全球艺术市场的“风向标”。每年TEFAF开幕,都会吸引欧洲乃至世界各地的顶级藏家、艺术投资大佬、明星名人都会齐聚此地。受TEFAF的特别邀请,四维时代作为特邀宾客到临现场。',
-          tag: '腾讯新闻'
-        },
-        {
-          imgUrl: require('@/assets/images/home/news_03@2x.png'),
-          time: '2020年5月9日',
-          title: '四维时代为德国慕尼黑美术馆展览提供独家3D技术支持',
-          content: 'TEFAF是全球规模最大、规格最顶级、欧洲资格最老的艺术博览会之一,一直被公认为全球艺术市场的“风向标”。每年TEFAF开幕,都会吸引欧洲乃至世界各地的顶级藏家、艺术投资大佬、明星名人都会齐聚此地。受TEFAF的特别邀请,四维时代作为特邀宾客到临现场。',
-          tag: '彭博报道'
-        },
-        {
-          imgUrl: require('@/assets/images/home/news_04@2x.png'),
-          time: '2020年5月9日',
-          title: '四维时代为德国慕尼黑美术馆展览提供独家3D技术支持',
-          content: '11月17日至20日,由新华社、俄罗斯塔斯社、欧新社、葡萄牙卢萨社、西班牙柯尔比撒通讯社、拉美社、今日俄罗斯、西班牙巴斯克电视台、西班牙加泰ARA报、西班牙加泰罗比亚电视台等14家国际主流媒体组成的“国际媒体观察团”赴珠海进行走访交流,',
-          tag: '新华社'
-        }
-      ]
+      plate05List: News.slice(0, 4)
     }
   },
   methods: {
@@ -229,6 +206,9 @@ export default {
     },
     toMore (item) {
       this.$router.push(item.link)
+    },
+    detailVideo() {
+      this.$bus.$emit('toggleVideo', { url: `https://4d-tjw.oss-cn-shenzhen.aliyuncs.com/4dHouse/%E5%9B%9B%E7%BB%B4%E7%9C%8B%E7%9C%8BPro-%202020-7-22%E7%89%88%E6%9C%AC%288K%29.mp4` })
     }
   },
   computed: {

+ 26 - 2
pc/src/page/home2/style.scss

@@ -8,6 +8,13 @@
   font-size: 16px;
   text-decoration: underline;
 }
+.common-title {
+  .more {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+  }
+}
 .btns .button {
   height: 50px;
   padding-top: 0;
@@ -55,13 +62,19 @@
       // height: 684px;
       // object-fit: fill;
     }
+    .container {
+      position: absolute;
+      top: 0;
+      left: 50%;
+      margin-left: -638px;
+    }
     .video-info {
       position: absolute;
       top: 33%;
-      left: 50%;
-      margin-left: -506px;
+      left: 0;
       color: #fff;
       line-height: 1;
+      text-shadow: 0 0 20px rgba(0,0,0,0.4);
       h1 {
         font-size: 42px;
       }
@@ -79,12 +92,14 @@
         display: inline-block;
         padding: 0 37px;
         font-weight: 600;
+        text-shadow: none;
       }
       .action-link {
         font-size: 16px;
         color: #fff;
         margin-left: 25px;
         position: relative;
+        cursor: pointer;
         &::after {
           content: '';
           display: block;
@@ -102,6 +117,15 @@
         margin-top: 26px;
         a {
           color: #fff;
+          vertical-align: bottom;
+        }
+        span {
+          vertical-align: middle;
+        }
+        .icon {
+          font-size: 30px;
+          margin-right: 10px;
+          vertical-align: middle;
         }
       }
     }

+ 2 - 2
pc/src/page/introduce/index.vue

@@ -1,7 +1,7 @@
 <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="introduce-con container">
         <div class="info">
             <div class="member">
               <p>{{detail.nickName||'--'}}</p>

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

@@ -2,7 +2,7 @@
   <div>
     <div class="plate07">
       <p>四维看看,让空间讲故事</p>
-      <div class="btn">发现精彩</div>
+      <div class="btn" @click="$router.push('/cases/全部')">发现精彩</div>
     </div>
     <div class="footer" :style="{position: 'relative'}" >
       <div class="layout container">
@@ -18,7 +18,7 @@
             <div class="infos-list">
               <div class="infos-item" v-for="item in infosList" :key="item.title">
                 <h6>{{ item.title }}</h6>
-                <p v-for="i in item.list" :key="i.text">{{ i.text }}</p>
+                <a v-for="i in item.list" :key="i.text"  target="_blank" :href="`${pathname}#/${i.link}`">{{ i.text }}</a>
               </div>
             </div>
             <ul class="contacts-w">
@@ -61,25 +61,30 @@ export default {
   name: 'Footer',
   data () {
     return {
+      pathname: window.location.pathname,
       infosList: [
         {
           title: '行业应用',
           list: [
             {
               text: '房产营销',
-              link: ''
+              link: 'conductHouse'
             },
             {
-              text: '数字展厅',
-              link: ''
+              text: '线上展会',
+              link: 'conductExhibition'
             },
             {
-              text: '云展会',
-              link: ''
+              text: '数字文博',
+              link: 'conductSubject'
             },
             {
-              text: '场景购物',
-              link: ''
+              text: 'VR购物',
+              link: 'conductShop'
+            },
+            {
+              text: '安防勘察',
+              link: 'conductSecury'
             }
           ]
         },
@@ -88,15 +93,15 @@ export default {
           list: [
             {
               text: '公司简介',
-              link: ''
+              link: 'about'
             },
             {
               text: '新闻资讯',
-              link: ''
+              link: 'news'
             },
             {
               text: '成为经销商',
-              link: ''
+              link: 'distributor'
             }
           ]
         },
@@ -105,15 +110,15 @@ export default {
           list: [
             {
               text: '四维时代',
-              link: ''
+              link: 'http://www.4dage.com/cn'
             },
             {
               text: '中德人工智能研究院',
-              link: ''
+              link: 'https://www.cgaii.com'
             },
             {
               text: '四维模库',
-              link: ''
+              link: 'http://www.4dmodel.com/'
             }
           ]
         }
@@ -215,7 +220,9 @@ export default {
     h6 {
       margin-bottom: 27px;
     }
-    p {
+    a {
+      display: block;
+      color: #909090;
       margin-bottom: 15px;
       cursor: pointer;
       &:hover {

+ 12 - 25
pc/src/page/layout/header/index.vue

@@ -30,12 +30,13 @@
         </div>
       </div>
       <div class="ctrl">
-        <div class="shop-btn">{{ $i18n.t('header.online_shop')}}</div>
+        <div class="shop-btn" @click="$router.push({name: 'mallHome'})">{{ $i18n.t('header.online_shop')}}</div>
         <div class="language-w">
-          <span class="language en">EN</span>
-          <span class="language">中</span>
+          <span class="language en" :class="{'is-active': language === 'en'}">EN</span>
+          <span class="language" :class="{'is-active': language !== 'en'}">中</span>
         </div>
-        <div class="user" @click="$router.push('/login')"></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>
     </div>
   </div>
@@ -84,25 +85,8 @@ export default {
           },
         ]},
         {text: '看看空间', 
-        link: '/cases/全部',
-        items: [
-          {
-            text: '房屋地产',
-            link: '/cases/房屋地产'
-          },
-          {
-            text: '文博展览',
-            link: '/cases/文博展览'
-          },
-          {
-            text: '线下商城',
-            link: '/cases/房屋地产'
-          },
-          {
-            text: '餐饮家居',
-            link: '/cases/餐饮家居'
-          },
-        ]},
+        link: '/cases/全部'
+        },
         {text: '核心技术',  link: '/location'},
         {text: '服务支持',  items: [
           {
@@ -125,7 +109,7 @@ export default {
         {text: '关于我们',  items: [
           {
             text: '新闻资讯',
-            link: ''
+            link: '/news'
           },
           {
             text: '成为经销商',
@@ -166,7 +150,10 @@ export default {
     let lang = ~this.browserLang.indexOf('zh') ? '中' : 'en'
     this.$store.commit('change_language', lang)
     if (this.isLogin && !this.deviceLogin) {
-      let cart = JSON.parse(this.$store.state.user.cart)
+      let cart = this.$store.state.user.cart
+      if (typeof cart === 'string') {
+        cart = JSON.parse(cart)
+      }
       let count = 0
       cart.forEach(item => {
         count += item.goodsCount

+ 5 - 0
pc/src/page/layout/header/istyle.scss

@@ -134,11 +134,16 @@
       color: #8F8F8F;
       cursor: pointer;
       vertical-align: middle;
+      &.is-active {
+        color: #202020;
+      }
     }
     .user {
       width: 20px;
       height: 20px;
       background: url(~@/assets/images/home/account-icon.png) no-repeat center center;
+      cursor: pointer;
+      background-size: contain;
     }
   }
 

+ 0 - 11
pc/src/page/layout/normal.vue

@@ -5,11 +5,9 @@
       <iheader></iheader>
     </div>
     <div class="mask" :class="{active: showMask}" :style="{zIndex: maskZIndex}"></div>
-    <!-- <iaside :active="showLogin" :cp='asideCp'/> -->
     <ichat />
     <router-view />
     <ifooter v-if="!$route.meta.hideFooter"  />
-    <ileft />
   </div>
 </template>
 
@@ -19,8 +17,6 @@ import '@/assets/style/public.scss'
 import browseVideo from '@/components/browseVideo'
 import header from '@/page/layout/header'
 import footer from '@/page/layout/footer'
-import left from '@/page/layout/left'
-import aside from '@/page/layout/aside'
 import chat from '@/page/chat'
 import browser from '@/util/browser'
 import {mapState} from 'vuex'
@@ -66,9 +62,7 @@ export default {
   components: {
     iheader: header,
     ifooter: footer,
-    iaside: aside,
     ichat: chat,
-    ileft: left,
     browseVideo
   },
   computed: {
@@ -105,11 +99,6 @@ export default {
       this.showMask = true
     })
 
-    this.$bus.$on('showAside', data => {
-      this.showLogin = true
-      this.asideCp = data || {type: 'list', sku: [], fromList: true}
-    })
-
     this.$bus.$on('hideAside', () => {
       this.showLogin = false
     })

+ 0 - 11
pc/src/page/layout/shop.vue

@@ -5,11 +5,9 @@
       <iheader></iheader>
     </div>
     <div class="mask" :class="{active: showMask}" :style="{zIndex: maskZIndex}"></div>
-    <iaside :active="showLogin" :cp='asideCp'/>
     <ichat />
     <router-view />
     <ifooter v-if="$route.name!=='about'" />
-    <ileft />
   </div>
 </template>
 
@@ -19,8 +17,6 @@ import '@/assets/style/public.scss'
 import browseVideo from '@/components/browseVideo'
 import header from '@/page/layout/shopHeader'
 import footer from '@/page/layout/footer'
-import left from '@/page/layout/left'
-import aside from '@/page/layout/aside'
 import chat from '@/page/chat'
 import browser from '@/util/browser'
 import {mapState} from 'vuex'
@@ -66,9 +62,7 @@ export default {
   components: {
     iheader: header,
     ifooter: footer,
-    iaside: aside,
     ichat: chat,
-    ileft: left,
     browseVideo
   },
   computed: {
@@ -105,11 +99,6 @@ export default {
       this.showMask = true
     })
 
-    this.$bus.$on('showAside', data => {
-      this.showLogin = true
-      this.asideCp = data || {type: 'list', sku: [], fromList: true}
-    })
-
     this.$bus.$on('hideAside', () => {
       this.showLogin = false
     })

+ 115 - 18
pc/src/page/layout/shopHeader/index.vue

@@ -17,17 +17,29 @@
             v-for="nav in navs"
             :key="nav.text"
             :class="{active: hoverCp === nav.cp}"
+            class="header-item"
             @click="toNav(nav)"
-          >{{nav.text}}</a>
+          >{{nav.text}}
+            <ul class="child-list" v-if="nav.items">
+              <li class="" v-for="(item, index) in nav.items" :key="index" @click.stop="toNav(item)">
+                {{ item.text }}
+              </li>
+            </ul>
+          </a>
+          
         </div>
       </div>
       <div class="ctrl">
-        <div class="shop-btn">{{ $i18n.t('header.online_shop')}}</div>
+        <div class="shop-btn" @click="$router.push({name: 'mallHome'})">{{ $i18n.t('header.online_shop')}}</div>
         <div class="language-w">
-          <span class="country"></span>
-          <span class="language">简体中文</span>
+          <span class="language en" :class="{'is-active': language === 'en'}">EN</span>
+          <span class="language" :class="{'is-active': language !== 'en'}">中</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="cart" @click="$router.push('/mall/cart')">
+          <h-icon type="xingouwuche" class="icon" />
         </div>
-        <div class="user"></div>
       </div>
     </div>
   </div>
@@ -52,10 +64,31 @@ export default {
       isWide,
       count: 0,
       navs: [
-        { text: '四维看看Pro', link: '' },
-        { text: '精选配件', link: '' },
-        { text: '增值服务', link: '' },
-        { text: '行业应用', link: '' },
+        { text: '四维看看Pro', link: '/mall/kankanPro' },
+        { text: '精选配件', link: '/mall/zhijia' },
+        { text: '增值服务', link: '/mall/cloudCapacity' },
+        { text: '行业应用', items: [
+          {
+            text: '房产营销',
+            link: '/conductHouse'
+          },
+          {
+            text: '线上展会',
+            link: '/conductExhibition'
+          },
+          {
+            text: '数字文博',
+            link: '/conductSubject'
+          },
+          {
+            text: 'VR购物',
+            link: '/conductShop'
+          },
+          {
+            text: '安防勘察',
+            link: '/conductSecury'
+          },
+        ]},
       ]
     }
   },
@@ -89,14 +122,17 @@ export default {
   mounted () {
     let lang = ~this.browserLang.indexOf('zh') ? '中' : 'en'
     this.$store.commit('change_language', lang)
-    if (this.isLogin && !this.deviceLogin) {
-      let cart = JSON.parse(this.$store.state.user.cart)
-      let count = 0
-      cart.forEach(item => {
-        count += item.goodsCount
-      })
-      this.count = count
-    }
+    // if (this.isLogin && !this.deviceLogin) {
+    //   let cart = this.$store.state.user.cart
+    //   if (typeof cart === 'string') {
+    //     cart = JSON.parse(cart)
+    //   }
+    //   let count = 0
+    //   cart.forEach(item => {
+    //     count += item.goodsCount
+    //   })
+    //   this.count = count
+    // }
     this.$bus.$on('hadload', data => {
       this.$store.commit('change_nav_division', getPosition(this.$refs.list).x)
     })
@@ -192,7 +228,9 @@ export default {
       height: 100%;
       a {
         display: inline-block;
-        padding: 30px 47px 25px 0;
+        // padding: 30px 47px 25px 0;
+        margin-right: 48px;
+        line-height: 80px;
         font-size: 16px;
         text-decoration: none;
         font-weight: bold;
@@ -238,6 +276,7 @@ export default {
       text-align: center;
       font-weight: 600;
       margin-right: 25px;
+      cursor: pointer;
     }
     .country {
       width: 20px;
@@ -250,15 +289,73 @@ export default {
       margin: 0 18px 0 15px;
       color: #8F8F8F;
       vertical-align: middle;
+      &.is-active {
+        color: #202020;
+      }
     }
     .user {
       width: 20px;
       height: 20px;
       background: url(~@/assets/images/home/account-icon.png) no-repeat center center;
+      cursor: pointer;
+    }
+    .cart {
+      color: #202020;
+      margin-left: 18px;
+      cursor: pointer;
+      .icon {
+        font-size: 26px;
+      }
     }
   }
 
 }
+.header-item:hover {
+  .child-list {
+    display: block;
+  }
+}
+.child-list {
+  position: absolute;
+  width: 112px;
+  box-shadow: 0px -2px 6px rgba(113,113,113,0.16);
+  margin-top: -10px;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 0;
+  display: none;
+  transition: all linear 0.5s;
+  padding-top: 6px;
+  &::before {
+    position: absolute;
+    display: block;
+    top: -5px;
+    left: 50%;
+    margin-left: -2px;
+    width: 0;
+    height: 0px;
+    content: '';
+    background: #fff;
+    border-style: solid;
+    border-width: 4px;
+    border-color: #fff #fff transparent transparent;
+    transform: rotate(-45deg);
+    box-shadow: 1px -1px 0px rgba(113,113,113,0.16);
+    z-index: 1;
+  }
+  li {
+    height: 48px;
+    line-height: 48px;
+    font-size: 16px;
+    text-align: center;
+    position: relative;
+    background: #fff;
+    z-index: 2;
+    &:hover {
+      background: #EBEBEB;
+    }
+  }
+}
 
 @media screen and (max-width: 1600px){
 }

+ 11 - 4
pc/src/page/location/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="conduct-display">
+  <div class="conduct-tech">
     <div class="banner">
       <div class="container">核心技术</div>
     </div>
@@ -8,7 +8,8 @@
         <div class="container">
           <h2 class="common-title">{{item.name}}</h2>
           <p class="desc">{{ item.desc }}</p>
-          <img :src="item.img" />
+          <!-- <img :src="item.img" /> -->
+          <video :src="item.video" autoplay muted loop></video>
         </div>
       </div>
       <div class="plate item" >
@@ -62,7 +63,8 @@ export default {
         {
           name: '空间数字化',
           desc: '记录与计算相机在拍摄时的空间位置,并提取对应的3D点云,从而获取三维空间的真实情况。',
-          img: require('@/assets/images/refactor/coreTech/item-1.png'),
+          // img: require('@/assets/images/refactor/coreTech/item-1.png'),
+          video: require('@/assets/images/refactor/coreTech/AI AR SLAM 01(剪辑版2).mp4'),
           runAnimation: true
         }
       ],
@@ -106,7 +108,7 @@ export default {
 }
 </script>
 <style lang="scss">
-.conduct-display {
+.conduct-tech {
   .banner {
     width: 100%;
     height: 420px;
@@ -123,6 +125,11 @@ export default {
     img {
       
     }
+    video {
+      width: 100%;
+      // display: block;
+      // margin: 0 auto;
+    }
     .desc {
       color: #909090;
       margin-bottom: 50px;

+ 6 - 3
pc/src/page/login/components/cameraLogin.vue

@@ -43,16 +43,19 @@ export default {
 
           if (token && to !== 0) {
             this.$store.commit('DEVICELOGIN', childName)
-            this.$bus.$emit('hideAside')
             this.$router.replace({name: 'scene'})
           } else {
-            this.$bus.$emit('hideAside')
             this.$bus.$emit('hasLogin')
             this.$store.commit('DEVICELOGIN', '')
             this.$store.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
             this.$store.dispatch('getCart')
           }
-          this.$router.push('/')
+          const from = this.$route.query.from
+          if (from) {
+            this.$router.push(from)
+          } else {
+            this.$router.push('/')
+          }
           return false
         }
       }, 3000)

+ 9 - 2
pc/src/page/login/components/codeLogin.vue

@@ -91,8 +91,15 @@ export default {
         msgAuthCode: this.loginForm.authCode
       }
 
-      await this.$store.dispatch('codeLogin', params)
-      this.$router.push('/')
+      let res = await this.$store.dispatch('codeLogin', params)
+      if (res) {
+        const from = this.$route.query.from
+        if (from) {
+          this.$router.push(from)
+        } else {
+          this.$router.push('/')
+        }
+      }
     }
   },
   beforeDestroy () {

+ 16 - 13
pc/src/page/login/components/forget/emailForm.vue

@@ -10,12 +10,12 @@
     <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">
-      <div class="send-btn" @click="sendCode">获取验证码</div>
+      <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">
     <p class="login-entry">已有账号,<span @click="$router.push('/login/login')">直接登录</span></p>
-    <div class="submit-btn">提交</div>
+    <div class="submit-btn" @click="submit">提交</div>
   </div>
 </template>
 
@@ -44,7 +44,10 @@ export default {
   computed: {
     ...mapState({
       langToast: state => state.language.home.toast
-    })
+    }),
+    time () {
+      return this.type === 'email' ? this.interEmailTime : this.interTime
+    }
   },
   components: {
     phoneAddressSelect
@@ -113,39 +116,39 @@ export default {
       }
       let checkStr = [
         {
-          name: '手机',
+          name: this.type === 'email' ? '邮箱' : '手机',
           En: 'Phone number',
-          val: this.phone
+          val: this.form.phone
         },
         {
           name: '验证码',
           En: 'Verification code',
-          val: this.authCode
+          val: this.form.authCode
         },
         {
           name: '密码',
           En: 'Password',
-          val: this.password
+          val: this.form.password
         },
         {
           name: '确认密码',
           En: 'Password',
-          val: this.confirmpass
+          val: this.form.confirmPass
         }
       ]
       if (!check(checkStr)) {
         return
       }
-      if (this.password.length < 8 || this.confirmpass.length < 8) {
+      if (this.form.password.length < 8 || this.form.confirmPass.length < 8) {
         return this.$toast.show('warn', this.langToast['31'])
       }
 
-      let temp = encodeStr(Base64.encode(this.password), Base64.encode(this.confirmpass))
+      let temp = encodeStr(Base64.encode(this.form.password), Base64.encode(this.form.confirmPass))
       let params = {
         password: temp[0],
-        phoneNum: this.phone,
+        phoneNum: this.form.phone,
         confirmPwd: temp[1],
-        msgAuthCode: this.authCode
+        msgAuthCode: this.form.authCode
       }
       let res = await this.$http({
         method: 'post',
@@ -160,7 +163,7 @@ export default {
         return this.$toast.show('warn', this.langToast[response.code])
       }
       this.$toast.show('warn', this.langToast['32'], () => {
-        this.$bus.$emit('currentActive', 'ilogin')
+        this.$router.push('/login/login')
       })
     }
   }

+ 3 - 3
pc/src/page/login/components/login.vue

@@ -95,9 +95,9 @@ export default {
           rememberMe: Boolean(this.rememberMe)
         }
         await this.$store.dispatch('login', params)
-        const frm = this.$route.query.frm
-        if (frm) {
-          window.location = frm
+        const from = this.$route.query.from
+        if (from) {
+          this.$router.push(from)
         } else {
           this.$router.push('/')
         }

+ 411 - 0
pc/src/page/mall/cart/index.vue

@@ -0,0 +1,411 @@
+<template>
+  <div class="mall-cart">
+    <div class="container">
+      <div class="cart-header clear">
+        <div class="fl cart-header-left">
+          <h3>购物车</h3>
+          <p>本订单顺丰包邮</p>
+        </div>
+        <ul class="step fr">
+          <li>
+            <span class="step-num is-active">1</span>
+            <span>加入购物</span>
+            <span class="line"></span>
+          </li>
+          <li>
+            <span class="step-num">2</span>
+            <span>确认订单</span>
+            <span class="line"></span>
+          </li>
+          <li>
+            <span class="step-num">3</span>
+            <span>下单</span>
+            <span class="line"></span>
+          </li>
+        </ul>
+      </div>
+      <div class="cart-table">
+        <div class="table-header">
+          <div class="th1">
+            <div class="select-status" :class="{'is-active': selectedGoods.length === cart.length}" @click="changeAllSelect">
+              <h-icon type="duihao" class="icon" />
+            </div>
+          </div>
+          <div class="th2">商品</div>
+          <div class="th3">价格</div>
+          <div class="th4">数量 </div>
+          <div class="th5">小计</div>
+          <div class="th6"></div>
+        </div>
+        <div class="table-body">
+          <div class="table-item" v-for="item in cart" :key="item.goodsId">
+            <div class="th1">
+              <div class="select-status " :class="{'is-active': selectedGoods.indexOf(item.goodsId) > -1}" @click="changeSelect(item)">
+                <h-icon type="duihao" class="icon" />
+              </div>
+            </div>
+            <div class="th2">
+              <div class="img-w">
+                <img :src="goodsDetail[item.goodsId].img" alt="">
+              </div>
+              <div class="goods-info">
+                <h6 class="goods-name">{{ goodsDetail[item.goodsId].name }}</h6>
+                <p v-for="(p, index) in goodsDetail[item.goodsId].detail" :key="index">{{ `${p} x ${item.goodsCount}` }}</p>
+              </div>
+            </div>
+            <div class="th3">¥{{ formatNum(item.price) }}</div>
+            <div class="th4"><number  inputDisabled v-model="item.goodsCount" :max="99" @add="add(item)" @reduce="reduce(item)" /></div>
+            <div class="th5">¥{{ formatNum(item.price * item.goodsCount) }}</div>
+            <div class="th6">
+              <a href="javascript:;" @click="rmItem(item)"><h-icon type="guanbi" /></a>
+            </div>
+          </div>
+          <div class="cart-footer">
+            <p class="count">
+              <span>总计{{goodsTotalCount}}件商品</span>
+              <span class="price">{{ formatNum(totalPrice) }}</span>
+            </p>
+            <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 submit-btn" @click="toConfirm">立即结算</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import mallConfig from '@/config/mall'
+import number from '@/components/mall/number'
+import { saveConfirmGoods } from '@/util/storage'
+
+export default {
+  data () {
+    return {
+      formatNum: mallConfig.formatNum,
+      goodsDetail: mallConfig.goodsMap,
+      selectedGoods: []
+    }
+  },
+  computed: {
+    ...mapState({
+      langToast: state => state.language.home.toast,
+      cart: state => {
+        let list = []
+        if (Object.prototype.toString.call(state.user.cart) === '[object Array]') {
+          list = state.user.cart
+        } else {
+          list = state.user.cart && state.user.cart !== 'null'
+          ? JSON.parse(state.user.cart)
+          : []
+        }
+        list.forEach(item => {
+          item.isSelect = true
+        })
+        return list
+      }
+    }),
+    goodsTotalCount () {
+      return this.cart.reduce((total, item) => total + (this.selectedGoods.indexOf(item.goodsId) > -1 ? item.goodsCount : 0), 0)
+    },
+    totalPrice () {
+      if (this.cart.length === 1) {
+        return this.cart[0].goodsCount *  this.cart[0].price
+      }
+      return this.cart.reduce((total, item) => total + (this.selectedGoods.indexOf(item.goodsId) > -1 ? item.goodsCount * item.price : 0), 0)
+    }
+  },
+  components: {
+    number
+  },
+  methods: {
+    rmItem (item) {
+      this.$toast.showConfirm('warn', this.langToast['15'], () => {
+        let params = {
+          goodsId: item.goodsId,
+          goodsCount: 0
+        }
+        this.$store.dispatch('reduceCart', params)
+      })
+    },
+    input (e) {
+      console.log(e)
+    },
+    reduce (item) {
+      if (item.goodsCount > 1) {
+        this.cannotdel = {
+          id: '',
+          status: false
+        }
+
+        let params = {
+          goodsId: item.goodsId,
+          goodsCount: item.goodsCount
+        }
+        this.$store.dispatch('reduceCart', params)
+      } else {
+        this.cannotdel = {
+          id: item.goodsId,
+          status: true
+        }
+      }
+    },
+    add (item) {
+      let params = {
+        goodsId: item.goodsId,
+        goodsCount: 1,
+        skuSn: item.skuSn
+      }
+      this.cannotdel = {
+        id: '',
+        status: false
+      }
+      this.$store.dispatch('addCart', params)
+    },
+    changeSelect (item) {
+      if (this.selectedGoods.indexOf(item.goodsId) > -1) {
+        this.selectedGoods = this.selectedGoods.filter(goodsId => goodsId !== item.goodsId)
+      } else 
+      this.selectedGoods.push(item.goodsId)
+    },
+    changeAllSelect () {
+      if (this.selectedGoods.length !== this.cart.length) {
+        this.cart.forEach(item => {
+          if (this.selectedGoods.indexOf(item.goodsId) === -1) {
+            this.selectedGoods.push(item.goodsId)
+          }
+        })
+      } else {
+        this.selectedGoods = []
+      }
+      
+    },
+    toConfirm () {
+      if (this.selectedGoods.length === 0) {
+        this.$toast.show('warn', '请选择需要购买的商品')
+        return
+      }
+      let goods = []
+      this.cart.forEach(item => {
+        if (this.selectedGoods.indexOf(item.goodsId) > -1) {
+          goods.push(item)
+        }
+      })
+
+      saveConfirmGoods(goods)
+      this.$router.push('/mall/confirm')
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.mall-cart {
+  padding: 114px 0 187px;
+  background: #F7F7F7;
+  .container {
+    background: #fff;
+    box-shadow:0px 2px 2px rgba(0,0,0,0.11);
+    padding-bottom: 48px;
+  }
+  .cart-header {
+    padding: 42px 0 30px;
+  }
+  .cart-header-left {
+    padding-left: 92px;
+    h3, p {
+      display: inline-block;
+    }
+    h3 {
+      font-size: 24px;
+      margin-right: 26px;
+      vertical-align: middle;
+    }
+    p {
+      color: #909090;
+      font-size: 14px;
+      vertical-align: middle;
+    }
+  }
+  .step {
+    padding-right: 60px;
+    li {
+      display: inline-block;
+      color: #909090;
+      font-size: 12px;
+      &>* {
+        display: inline-block;
+        vertical-align: middle;
+      }
+      &:last-child {
+        .line {
+          display: none;
+        }
+      }
+    }
+    .step-num {
+      font-size: 14px;
+      background: #EBEBEB;
+      width: 25px;
+      height: 25px;
+      line-height: 25px;
+      text-align: center;
+      display: inline-block;
+      border-radius: 50%;
+      margin-right: 6px;
+      &.is-active {
+        background: #909090;
+        color: #f7f7f7;
+      }
+    }
+    .line {
+      width: 42px;
+      height: 1px;
+      background: #B7B7B7;
+      vertical-align: middle;
+      margin: 0 10px;
+    }
+  }
+
+  .table-header {
+    height: 56px;
+    border: 1px solid #e4e4e4;
+    border-left: none;
+    border-right: none;
+    line-height: 56px;
+    display: flex;
+    padding-left: 93px;
+    padding-right: 59px;
+    color: #202020;
+    font-weight: bold;
+  }
+  .table-body {
+    padding: 0 59px 0 93px;
+  }
+  .table-item {
+    border-bottom: 1px solid #ebebeb;
+    display: flex;
+    padding: 22px 0;
+  }
+  .th1 {
+    width: 60px;
+    display: flex;
+    align-items: center;
+    padding-left: 13px;
+    line-height: 21px;
+    .select-status {
+      width: 21px;
+      height: 21px;
+      border-radius: 50%;
+      border: 1px solid #909090;
+      text-align: center;
+      cursor: pointer;
+      color: #fff;
+      font-size: 14px;
+      &.is-active {
+        
+        background: #1FE4DC;
+        border-color: #1FE4DC;
+      }
+      .icon {
+        font-size: 20px;
+      }
+    }
+  }
+  .th2 {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    
+    .img-w {
+      width: 90px;
+      text-align: center;
+    }
+    img {
+      // width: 90px;
+      height: 90px;
+    }
+    h6 {
+      margin-bottom: 4px;
+    }
+    p {
+      color: #909090;
+      font-size: 12px;
+    }
+  }
+  .th3 {
+    width: 60px;
+    margin-right: 115px;
+    text-align: center;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .th4 {
+    width: 122px;
+    margin-right: 113px;
+    text-align: center;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .th5 {
+    width: 100px;
+    text-align: center;
+    margin-right: 80px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .th6 {
+    width: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    a {
+      color: #909090;
+    }
+  }
+  .count {
+    font-size: 16px;
+    color: #909090;
+    text-align: right;
+    padding-right: 67px;
+    margin: 50px 0 43px;
+    .price {
+      font-size: 24px;
+      color: #202020;
+      margin-left: 30px;
+    }
+  }
+  .cart-actions {
+    img {
+      height: 28px;
+      margin-top: 13px;
+    }
+    .btn {
+      height: 55px;
+      width: 216px;
+      line-height: 55px;
+      background: #ebebeb;
+      text-align: center;
+      display: inline-block;
+      margin-right: 23px;
+      cursor: pointer;
+      font-weight: 600;
+    }
+    .submit-btn {
+      margin-right: 0;
+      background: #1FE4DC;
+    }
+  }
+}
+
+</style>

+ 93 - 0
pc/src/page/mall/cloudCapacity/index.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="pricedetail-layout">
+    <div class="container">
+      <template v-if="language!=='en'">
+        <p class="common-title">{{langPurchase.pricename}}</p>
+        <priceTable  style="margin: 0 auto 40px;"  />
+      </template>
+      <div class="common-title">{{langPurchase.pricename1}}</div>
+      <priceTable :type="'hw'" style="margin: 0 auto 40px;"  />
+    </div>
+    <div class="qa-con">
+      <ul class="container">
+         <h1 class="common-title">关于云容量</h1>
+        <li v-for="(item,i) in langPurchase.qa" :key="i">
+          <p style="text-align:left;">{{item.q}}</p>
+          <p v-html="item.a"></p>
+        </li>
+        <li style="margin-top:70px;">
+          <p></p>
+          <p>{{langPurchase.read1}}</p>
+          <p>{{langPurchase.read2}}</p>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+<script>
+import { mapState } from 'vuex'
+import priceTable from '@/components/priceTable'
+
+export default {
+  components: {
+    priceTable
+  },
+  computed: {
+    ...mapState({
+      language: state => state.language.current,
+      langPurchase: state => state.language.home.purchase
+    })
+  }
+
+}
+</script>
+<style lang="scss" scoped>
+.pricedetail-layout {
+  width: 100%;
+  .container {
+    margin: 0 auto;
+    padding: 60px 0 80px;
+    text-align: center;
+    .common-title {
+      margin: 0 auto 78px;
+      text-align: left;
+    }
+    .price-txt {
+      text-align: justify;
+      font-size: 14px;
+      padding-left: 20px;
+      margin-top: 25px;
+      li {
+        font-size: 14px;
+        color: #666;
+        line-height: 31px;
+        list-style: disc;
+      }
+    }
+
+    
+  }
+  .qa-con {
+      // max-width: 868px;
+      margin: 50px auto 0;
+      background: #F7F7F7;
+      li {
+        margin-bottom: 18px;
+        text-align: justify;
+        font-family: "Microsoft Yahei", "微软雅黑", Tahoma, Arial, Helvetica,
+          STHeiti;
+        p {
+          font-size: 14px;
+          color: #666;
+          line-height: 31px;
+          &:first-of-type {
+            font-size: 18px;
+            color: #333;
+            font-weight: bold;
+            margin-bottom: 11px;
+          }
+        }
+      }
+    }
+}
+</style>

+ 364 - 0
pc/src/page/mall/confirm/components/addressModule.vue

@@ -0,0 +1,364 @@
+<template>
+  <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>
+        <div class="address-userinfo clear">
+          <div class="user-name fl">{{ item.shipName }}</div>
+          <div class="user-phone fl">{{ item.shipMobile }}</div>
+        </div>
+        <div class="address-detail">
+          <p class="address-p1">{{ item.shipAreaPath }} </p>
+          <p class="address-p2">{{ item.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">
+            <h4>您确认要删除该地址吗?</h4>
+            <div class="confirm-actions">
+              <div class="confirm-button button-submit" @click="deleteAddress(item.id)">是</div>
+              <div class="confirm-button" @click="showDeleteId = ''">否</div>
+            </div>
+          </div>
+        </div>
+      </li>
+      <li class="address-add" @click="showCreate">
+        <h-icon type="jiahao"></h-icon>新增收货地址
+      </li>
+    </ul>
+    <h-modal :visible="addressShow" :showClose="false">
+      <div class="address-form">
+        <div class="form-header">添加收货地址</div>
+        <div class="form">
+          <div class="form-item">
+            <div class="form-label">*收货人</div>
+            <input type="text" v-model="addressForm.shipName">
+          </div>
+          <div class="form-item">
+            <div class="form-label">*手机号码</div>
+            <input type="text" v-model="addressForm.shipMobile">
+          </div>
+          <div class="form-item">
+            <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>
+        <div class="actions-w">
+          <div class="cancel-btn" @click="addressShow=false">取消</div>
+          <div class="submit-btn" @click="createAddress">保存并使用</div>
+        </div>
+      </div>
+    </h-modal>
+  </div>
+</template>
+
+<script>
+import citySelect from './citySelect'
+import { mapState } from 'vuex'
+import API from '@/apis'
+export default {
+  data () {
+    return {
+      addressShow: false,
+      addressForm: {},
+      addressList: [],
+      address: {},
+      selectAddressId: '',
+      showDeleteId: ''
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+    })
+  },
+  watch: {
+    selectAddressId (val) {
+      this.$emit('change', this.addressList.find(item => item.id === val))
+    }
+  },
+  async mounted () {
+    this.$store.dispatch('getInfo', {
+      url: '/user/getReceiverInfo',
+      name: 'address'
+    })
+    await this.getAddressList()
+    this.addressList.forEach(item => {
+      if (item.setDefault) {
+        this.selectAddressId = item.id
+      }
+    })
+  },
+  components: {
+    citySelect
+  },
+  methods: {
+    getCurrentSelect (val) {
+      console.log(val, 'val')
+      this.addressForm.province = val[0]
+      this.addressForm.city = val[1]
+      this.addressForm.shipAreaPath = val.join()
+    },
+    uAddress () {
+      this.addressForm.province = this.addressForm.shipAreaPath[0]
+      this.addressForm.city = this.addressForm.shipAreaPath[1]
+      let {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      } = this.addressForm
+      let params = {
+        shipAddress,
+        shipAreaPath,
+        province,
+        city,
+        shipMobile,
+        shipName
+      }
+      params.shipAreaPath = params.shipAreaPath.join()
+      this.$http
+        .post('/user/updateAddress', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(async data => {
+          this.addressStatus = true
+          await this.$store.dispatch('getInfo', {
+            url: '/user/getReceiverInfo',
+            name: 'address'
+          })
+          this.addressShow = false
+        })
+    },
+    getAddressList () {
+      return API.getReceiverList().then(res => {
+        console.log(res, 'getReceiverList')
+        this.addressList = res.data.data
+      })
+    },
+    createAddress () {
+      API.insertAddress(this.addressForm).then(async res => {
+        if (res.data.code === 0) {
+          this.addressShow = false
+          await this.getAddressList()
+          this.selectAddressId = res.data.data.id
+        }
+      })
+    },
+    deleteAddress (id) {
+      API.deleteAddress(id).then(res => {
+        this.getAddressList()
+      })
+    },
+    showEdit (item) {
+      this.addressForm = Object.assign({}, item)
+      this.addressShow = true
+    },
+    showCreate () {
+      this.addressForm = {}
+      this.addressShow = true
+    }
+  }
+}
+</script>
+<style lang="less">
+.address-module {
+  display: flex;
+  align-items: center;
+  padding: 19px 0 ;
+  .address-list {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .address-item {
+    width: 448px;
+    height: 91px;
+    border:  1px solid #ebebeb;
+    cursor: pointer;
+    position: relative;
+    margin-right: 20px;
+    padding: 10px 73px 0 32px;
+    margin-bottom: 10px;
+    &.is-active {
+      border-color: #1FE4DC;
+    }
+  }
+  .default-tag {
+    width: 70px;
+    height: 24px;
+    line-height: 24px;
+    text-align: center;
+    border-radius:0px 0px 5px 0px;
+    background: #ebebeb;
+    color: #909090;
+    font-size: 12px;
+    position: absolute;
+    top: 0;
+    right: 0;
+    border-radius: 0 0 0 5px;
+  }
+  .address-userinfo {
+    font-size: 14px;
+    margin-bottom: 4px;
+    font-weight: 600;
+  }
+  .user-name {
+    font-weight: 600;
+    margin-right: 15px;
+  }
+  .address-detail {
+    font-size: 12px;
+    line-height: 15px;
+    color: #909090;
+  }
+  .address-add {
+    width: 448px;
+    height: 91px;
+    background: #F7F7F7;
+    color: #202020;
+    font-size: 12px;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .action-w {
+    font-size: 12px;
+    margin-top: 2px;
+    position: relative;
+    &>div {
+      display: inline-block;
+      cursor: pointer;
+      margin-right: 13px;
+      span {
+        vertical-align: middle;
+      }
+      .icon {
+        display: inline-block;
+        width: 11px;
+        height: 11px;
+        background: url(~@/assets/images/refactor/mall/edit-icon.png) no-repeat center center;
+        margin-right: 2px;
+        &.delete-icon {
+          background-image: url(~@/assets/images/refactor/mall/delete-icon.png);
+        }
+      }
+    }
+    .delete-confirm-box {
+      position: absolute;
+      top: -145px;
+      left: 50px;
+      width: 343px;
+      background-color: #fff;
+      // box-shadow:0px 2px 6px rgba(0,0,0,0.4);
+      filter: drop-shadow(0px 2px 6px rgba(0,0,0,0.4));
+      padding: 32px 35px 28px;
+      cursor: default;
+      h4 {
+        font-size: 16px;
+        line-height: 20px;
+        margin-bottom: 28px;
+        text-align: center;
+      }
+      .confirm-button {
+        width: 122px;
+        height: 30px;
+        line-height: 30px;
+        text-align: center;
+        display: inline-block;
+        background: #EBEBEB;
+        font-weight: 600;
+        cursor: pointer;
+        &.button-submit {
+          background: #1FE4DC;
+          margin-right: 25px;
+        }
+      }
+      &::after {
+        content: '';
+        display: block;
+        position: absolute;
+        bottom: -4px;
+        left: 25px;
+        border-top: 5px solid #fff;
+        border-left: 5px solid transparent;
+        border-right: 5px solid transparent;
+      }
+    }
+  }
+}
+
+.address-form {
+  width: 533px;
+  padding: 38px;
+  .form-header {
+    font-size: 20px;
+    font-weight: 600;
+    text-align: center;
+    border-bottom: 1px solid #B3B3B3;
+    padding-bottom: 10px;
+  }
+  .form {
+    padding-top: 39px;
+    line-height: 42px;
+  }
+  .form-item {
+    padding-left: 85px;
+    position: relative;
+    margin-bottom: 20px;
+    input {
+      width: 100%;
+      line-height: 42px;
+      border-radius: 3px;
+      border: 1px solid #909090;
+      padding-left: 10px;
+    }
+    
+    textarea {
+      height: 84px;
+      width: 100%;
+      margin-top: 20px;
+      border:1px solid rgba(144,144,144,1);
+      border-radius:3px;
+      padding: 10px;
+    }
+  }
+  .form-label {
+    // width: 80px;
+    position: absolute;
+    left: 0;
+    top: 0;
+    display: inline-block;
+  }
+  .actions-w {
+    display: flex;
+    width: 100%;
+    margin-top: 40px;
+    & > div {
+      flex: 1;
+      height: 55px;
+      line-height: 55px;
+      text-align: center;
+      margin-right: 0;
+      font-weight: bold;
+      cursor: pointer;
+    }
+    .cancel-btn {
+      margin-right: 26px;
+      background: #EBEBEB;
+    }
+  }
+}
+
+</style>

+ 138 - 0
pc/src/page/mall/confirm/components/citySelect.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="address-select-w">
+    <div class="select-w">
+      <select class="prov" v-model="currentPID" @change="handleChange">
+        <option :value="i" v-for="(item, i) in citylist" :key="i">{{
+          item.p
+        }}</option>
+      </select>
+
+      <div class="sanjiao"></div>
+    </div>
+    <div class="select-w">
+      <select class="city" v-model="currentCID" @change="handleChange">
+        <option :value="i" v-for="(item, i) in currentProv" :key="i">{{
+          item.n
+        }}</option>
+      </select>
+      <div class="sanjiao"></div>
+    </div>
+    <div class="select-w">
+      <select class="dist" v-model="currentSID" @change="handleChange">
+        <option :value="i" v-for="(item, i) in currentCity" :key="i">{{
+          item.s
+        }}</option>
+      </select>
+      <div class="sanjiao"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { citylist } from "@/components/citySelect/city";
+export default {
+  props: ["areaPath"],
+  data() {
+    let idArr = ["", "", ""];
+    if (this.areaPath) {
+      let tempArr = this.areaPath.split(",");
+      let [p, c, d] = tempArr;
+      idArr = (() => {
+        let tmp = [];
+        citylist.forEach((item, index) => {
+          if (item.p === p) {
+            tmp.push(index);
+            item.c.forEach((t2, i2) => {
+              if (t2.n === c) {
+                tmp.push(i2);
+                t2.a.forEach((t3, i3) => {
+                  if (t3.s === d) {
+                    tmp.push(i3);
+                  }
+                });
+              }
+            });
+          }
+        });
+        return tmp;
+      })();
+    }
+
+    return {
+      citylist,
+      currentPID: idArr[0] !== "" ? idArr[0] : 18,
+      currentCID: idArr[1] !== "" ? idArr[1] : 3,
+      currentSID: idArr[2] !== "" ? idArr[2] : 2
+    };
+  },
+  computed: {
+    currentProv: function() {
+      let tmp = this.citylist[this.currentPID];
+      return tmp.c;
+    },
+    currentCity: function() {
+      let cprov = this.citylist[this.currentPID];
+      let tmp = cprov.c[this.currentCID];
+      return tmp.a;
+    }
+  },
+  watch: {
+    currentProv() {
+      this.currentCID = 0;
+      this.currentSID = 0;
+    }
+  },
+  methods: {
+    handleChange() {
+      setTimeout(() => {
+        let prov = this.citylist[this.currentPID];
+        let city = prov.c[this.currentCID];
+        let dist = city.a[this.currentSID];
+        console.log([prov.p, city.n, dist.s]);
+        this.$emit("currentVal", [prov.p, city.n, dist.s]);
+      });
+    }
+  },
+  mounted() {
+    this.handleChange();
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.address-select-w {
+  display: flex;
+  width: 100%;
+}
+.select-w {
+  flex: 1;
+  margin-right: 16px;
+  position: relative;
+  &:last-child {
+    margin-right: 0;
+  }
+}
+select {
+  width: 100%;
+  appearance: none;
+  height: 42px;
+  line-height: 42px;
+  border-radius: 3px;
+  border: 1px solid rgba(144, 144, 144, 1);
+  padding-left: 10px;
+}
+.sanjiao {
+  display: inline-block;
+  position: absolute;
+  right: 13px;
+  top: 17px;
+  &::before {
+    content: "";
+    border: 10px solid transparent;
+    border-top-color: #909090;
+    border-left-width: 7px;
+    border-right-width: 7px;
+    z-index: 1;
+  }
+}
+</style>

+ 453 - 0
pc/src/page/mall/confirm/components/invoiceModule.vue

@@ -0,0 +1,453 @@
+<template>
+  <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>
+      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 2}" @click="visible = true;invoiceType=2;">
+        增值税普票(电子发票)
+      </li>
+      <li class="invoice-select-w" :class="{'is-active': invoiceStatus === 3}"  @click="visible = true;invoiceType=3;">
+        增值税专用发票
+      </li>
+    </ul>
+    <h-modal :visible="visible" :showClose="false">
+      <div class="invoice-modal">
+        <h2 class="modal-title">发票信息</h2>
+        <div class="modal-content">
+          <div class="form-tabs">
+            <div class="tab" :class="{'is-active': invoiceType === item.type}" v-for="item in tabs" :key="item.type" @click="invoiceType=item.type">{{item.name}}</div>
+          </div>
+          <!-- 电子发票 -->
+          <div class="form form-1" v-show="invoiceType === 2">
+            <div class="form-item">
+              <div class="form-label">*电子发票</div>
+              <div class="form-input">
+                <input type="text" placeholder="接受发票的邮箱地址" v-model="invoiceForm.emailAddress">
+              </div>
+            </div>
+            <div class="form-item">
+              <div class="form-label"></div>
+              <div class="form-input">
+                <span class="select-label " :class="{'is-active': invoiceSubType === 1}" @click="invoiceSubType = 1">个人</span>
+                <span class="select-label" :class="{'is-active': invoiceSubType === 2}" @click="invoiceSubType = 2">单位</span>
+              </div>
+            </div>
+            <div class="form-item" v-show="invoiceSubType === 1">
+              <div class="form-label">*发票抬头</div>
+              <div class="form-input">
+                <input type="text" placeholder="个人" 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="请输入单位名称"  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">
+              </div>
+            </div>
+          </div>
+          <!-- 专用发票 -->
+          <div class="form" v-show="invoiceType === 3">
+            <div class="form-item">
+              <div class="form-label">*单位名称</div>
+              <div class="form-input">
+                <input type="text" placeholder="" 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">
+              </div>
+            </div>
+            <div class="form-item">
+              <div class="form-label">*注册地址</div>
+              <div class="form-input">
+                <input type="text" placeholder="" v-model="invoiceForm3.organizedAddress">
+              </div>
+            </div>
+            <div class="form-item">
+              <div class="form-label">*注册电话</div>
+              <div class="form-input">
+                <input type="text" placeholder="" v-model="invoiceForm3.registerPhone">
+              </div>
+            </div>
+            <div class="form-item">
+              <div class="form-label">*开户银行</div>
+              <div class="form-input">
+                <input type="text" placeholder="" v-model="invoiceForm3.bankName" >
+              </div>
+            </div>
+            <div class="form-item">
+              <div class="form-label">*银行账户</div>
+              <div class="form-input">
+                <input type="text" placeholder="" v-model="invoiceForm3.bankAccount">
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="modal-tips">
+          <div class="tips-left">温馨提示:</div>
+          <div class="tips-content">专票随商品一并寄出,若因特殊情况会于10天内顺丰寄送给您(如遇节假日稍有延迟)。请注意查收;增值税专用发票收到后请妥善保存,如退货请一同寄回,如退货专票未能寄回,则需扣除相应的税点。</div>
+        </div>
+        <div class="actions-w">
+          <div class="cancel-btn" @click="visible=false">取消</div>
+          <div class="submit-btn" @click="saveInvoice">保存并使用</div>
+        </div>
+      </div>
+    </h-modal>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import { reg } from '@/util'
+
+var cloneObj = function (obj) {
+  var newObj = {}
+  if (obj instanceof Array) {
+    newObj = []
+  }
+  for (var key in obj) {
+    var val = obj[key] || ''
+    newObj[key] = typeof val === 'object' ? cloneObj(val) : val
+  }
+  return newObj
+}
+
+export default {
+  data () {
+    return {
+      visible: false,
+      tabs: [{
+        name: '电子普通发票',
+        type: 2
+      }, {
+        name: '专用发票',
+        type: 3
+      }],
+      invoiceForm: {
+        title: ''
+      },
+      invoiceForm3: {},
+      invoiceType: 2,
+      invoiceSubType: 1,
+      invoiceStatus: 0
+    }
+  },
+  computed: {
+    ...mapState({
+      token: state => state.user.token,
+      langToast: state => state.language.home.toast,
+      language: state => state.language.current,
+      editInvoice2: state => {
+      let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return cloneObj(condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      editInvoice3: state => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
+        }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+        return cloneObj(condition ? JSON.parse(state.user.invoice3) : {})
+      },
+      invoice2: state => {
+        let type = Object.prototype.toString.call(state.user.invoice2)
+        if (type === '[object Object]') {
+          return state.user.invoice2
+        }
+        let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
+        return (condition ? JSON.parse(state.user.invoice2) : {})
+      },
+      invoice3: state => {
+        let type = Object.prototype.toString.call(state.user.invoice3)
+        if (type === '[object Object]') {
+          return state.user.invoice3
+        }
+        let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
+
+        return (condition ? JSON.parse(state.user.invoice3) : {})
+      }
+    }),
+    
+  },
+  mounted () {
+    this.invoiceForm3 = this.editInvoice3
+    this.invoiceForm = this.editInvoice2
+  },
+  methods: {
+    saveInvoice () {
+      let isObject = function (obj) {
+        return JSON.stringify(obj) === '{}' ? '' : obj
+      }
+      let params = {}
+      const { invoiceType, invoiceSubType } = this
+      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
+      }
+
+      if (invoiceType === 2) {
+        let { title, code } = this.invoiceForm
+        code = invoiceSubType === 1 ? '' : code
+        if (invoiceSubType === 2 && code.length !== 18) {
+          return this.$toast.show('warn', this.langToast['21'])
+        }
+        params = {
+          invoiceType,
+          title,
+          code
+        }
+
+        let checkStr = [
+          {
+            name: '发票抬头',
+            En: 'Title',
+            val: title
+          },
+          // {
+          //   name: '电子邮箱',
+          //   En: 'Email',
+          //   val: emailAddress
+          // }
+        ]
+        if (!check(checkStr)) {
+          return
+        }
+      } else {
+        let {title: title1, code: code1, organizedAddress: organizedAddress1, registerPhone: registerPhone1, bankName: bankName1, bankAccount: bankAccount1} = this.invoiceForm3
+        let title = isObject(title1)
+        let code = isObject(code1)
+        let organizedAddress = isObject(organizedAddress1)
+        let registerPhone = isObject(registerPhone1)
+        let bankName = isObject(bankName1)
+        let bankAccount = isObject(bankAccount1)
+
+        params = {
+          invoiceType,
+          title,
+          code,
+          organizedAddress,
+          registerPhone,
+          bankName,
+          bankAccount
+        }
+        let checkStr = [
+          {
+            name: '发票抬头',
+            En: 'Title',
+            val: title
+          },
+          {
+            name: '税务登记号',
+            En: 'Code',
+            val: code
+          },
+          {
+            name: '注册地址',
+            En: 'Organized Address',
+            val: organizedAddress
+          },
+          {
+            name: '注册电话',
+            En: 'Register Phone',
+            val: registerPhone
+          },
+          {
+            name: '开户银行',
+            En: 'Bank Name',
+            val: bankName
+          },
+          {
+            name: '银行账号',
+            En: 'Bank Account',
+            val: bankAccount
+          }
+        ]
+        if (!check(checkStr)) {
+          return
+        }
+        if (!code || code.length !== 18) {
+          return this.$toast.show('warn', this.langToast['21'])
+        }
+
+        if (!reg.guhua.test(registerPhone)) {
+          return this.$toast.show('warn', this.langToast['22'])
+        }
+      }
+
+      this.$http
+        .post('user/invoice/save', params, {
+          headers: {
+            token: this.token
+          }
+        })
+        .then(data => {
+          this.invoiceStatus = true
+          this.$store.dispatch('getInvoice', {
+            type: invoiceType,
+            params: {
+              invoiceType: invoiceType
+            }
+          })
+          this.invoiceStatus = this.invoiceType
+          this.visible = false
+          console.log(this.invoice2)
+          let invoice = this.invoiceType === 2 ? this.invoice2 : this.invoice3
+          invoice['invoiceType'] = invoice['type']
+          this.$emit('change', invoice)
+        })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.invoice-modules {
+  height: 133px;
+  display: flex;
+  align-items: center;
+}
+.invoice-list {
+  display: flex;
+  .invoice-select-w {
+    margin-right: 20px;
+    width: 250px;
+    height: 55px;
+    line-height: 55px;
+    text-align: center;
+    background: #F7F7F7;
+    border: 1px solid #F7F7F7;
+    font-size: 12px;
+    cursor: pointer;
+    &.is-active {
+      border-color: #1FE4DC;
+      background: #fff;
+    }
+  }
+}
+.invoice-modal {
+  width: 533px;
+  text-align: center;
+  padding: 38px;
+  .modal-title {
+    font-size: 20px;
+    line-height: 25px;
+    margin-bottom: 27px;
+  }
+  .form-tabs {
+    
+    
+    margin-bottom: 30px;
+    .tab {
+      display: inline-block;
+      width: 50%;
+      padding-bottom: 12px;
+      border-bottom: 1px solid #707070;
+      cursor: pointer;
+      &.is-active {
+        font-weight: bold;
+        border-bottom: 2px solid #1FE4DC;
+      }
+    }
+  }
+  .form-1 {
+    min-height: 213px;
+  }
+  .form-item {
+    width: 100%;
+    padding-left: 128px;
+    position: relative;
+    margin-bottom: 20px;
+    color: #202020;
+    .form-label {
+      position: absolute;
+      left: 0;
+      line-height: 42px;
+    }
+    input {
+      width: 100%;
+      border:1px solid rgba(144,144,144,1);
+      opacity:1;
+      border-radius:3px;
+      padding-left: 10px;
+      line-height: 42px;
+      font-size: 16px;
+    }
+    .form-input {
+      text-align: left;
+    }
+    .select-label {
+      position: relative;
+      padding-left: 22px;
+      cursor: pointer;
+      margin-right: 70px;
+      &::before {
+        content: '';
+        display: inline-block;
+        width: 12px;
+        height: 12px;
+        border-radius: 50%;
+        border: 1px solid #909090;
+        vertical-align: middle;
+        position: absolute;
+        top: 5px;
+        left: 0;
+        background: #fff;
+      }
+      &.is-active {
+        &::before {
+          background: #1FE4DC;
+        }
+      }
+    }
+  }
+  .modal-tips {
+    background: #F7F7F7;
+    font-size: 10px;
+    padding: 12px 22px;
+    margin-top: 26px;
+    &>* {
+      display: inline-block;
+      vertical-align: middle;
+      text-align: left;
+    }
+    .tips-content {
+      width: 345px;
+    }
+  }
+  .actions-w {
+    display: flex;
+    width: 100%;
+    margin-top: 40px;
+    & > div {
+      flex: 1;
+      height: 55px;
+      line-height: 55px;
+      text-align: center;
+      margin-right: 0;
+      font-weight: bold;
+      cursor: pointer;
+    }
+    .cancel-btn {
+      margin-right: 26px;
+      background: #EBEBEB;
+    }
+  }
+}
+</style>

+ 424 - 0
pc/src/page/mall/confirm/index.vue

@@ -0,0 +1,424 @@
+<template>
+  <div class="mall-confirm">
+    <div class="container clear">
+      <div class="confirm-header clear">
+        <div class="fl confirm-header-left">
+          <h3>确认订单</h3>
+        </div>
+        <ul class="step fr">
+          <li>
+            <span class="step-num ">1</span>
+            <span>加入购物</span>
+            <span class="line"></span>
+          </li>
+          <li>
+            <span class="step-num is-active">2</span>
+            <span>确认订单</span>
+            <span class="line"></span>
+          </li>
+          <li>
+            <span class="step-num">3</span>
+            <span>下单</span>
+            <span class="line"></span>
+          </li>
+        </ul>
+      </div>
+      <div class="confirm-items">
+        <addressModule @change="changeAddress" />
+      </div>
+      <div class="confirm-items">
+        <invoiceModule @change="changeInvoice" />
+      </div>
+      <div class="order-detail-items">
+        <h4 class="module-label">商品信息</h4>
+        <div class="order-detail">
+          <div class="detail-left">
+            <div class="goods-item" v-for="item in goods" :key="item.goodsId">
+              <div class="img-w">
+                <img :src="goodsDetail[item.goodsId].img" alt="">
+              </div>
+              <div class="goods-info">
+                <h6 class="goods-name">{{ goodsDetail[item.goodsId].name }}</h6>
+                <p v-for="(p, index) in goodsDetail[item.goodsId].detail" :key="index">{{ `${p} x ${item.goodsCount}` }}</p>
+              </div>
+            </div>
+          </div>
+          <div class="detail-right">
+            <div class="right-item">
+              <span>商品总价</span>
+              <span>¥{{totalGoodsPrice}}</span>
+            </div>
+            <div class="right-item">
+              <span>税费及其它费用</span>
+              <span>¥0</span>
+            </div>
+            <div class="right-item">
+              <span>运费</span>
+              <span>¥0</span>
+            </div>
+            <div class="total-price">
+              合计:<span>¥{{ totalGoodsPrice }}</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="xieyi">
+        <input type="checkbox" v-model="checked">
+        <span @click="showAgreement">我已阅读并同意四维看看用户协议</span>
+      </div>
+      <div class="submit-btn fr" @click="pay">付款</div>
+    </div>
+    <h-modal :visible.sync="openClause" >
+      <div  class="user-clause cart-clause">
+      <div>
+        <div class="clause-img" ref="clause">
+          <div ref="clauseImg">
+            <img :src="`${$cdn}images/cluse-long1.jpg`" alt>
+          </div>
+        </div>
+        <p> </p>
+        <div class="cls-btn">
+          <span @click="cancel">{{languagelAside.cancel}}</span>
+          <span :class="{primary:allreadyRead}" @click="agree">{{languagelAside.comfirm}}</span>
+        </div>
+      </div>
+    </div>
+    </h-modal>
+  </div>
+</template>
+
+<script>
+import addressModule from './components/addressModule'
+import invoiceModule from './components/invoiceModule'
+import mallConfig from '@/config/mall'
+import { mapState } from 'vuex'
+import { getConfirmGoods } from '@/util/storage'
+export default {
+  data () {
+    return {
+      formatNum: mallConfig.formatNum,
+      goodsDetail: mallConfig.goodsMap,
+      invoice: {},
+      address: {},
+      checked: false,
+      openClause: false,
+      allreadyRead: true
+    }
+  },
+  components: {
+    addressModule,
+    invoiceModule
+  },
+  computed: {
+    ...mapState({
+      langToast: state => state.language.home.toast,
+      // address: state => state.user.address || {},
+      language: state => state.language.current,
+      token: state => state.user.token,
+      languagelAside: state => state.language.home.home.loginAside
+    }),
+    goods () {
+      return getConfirmGoods()
+    },
+    totalGoodsPrice () {
+      return this.goods.reduce((pre, now = {}) => pre + now.price * now.goodsCount, 0)
+    }
+  },
+  mounted () {
+    // this.sizeHandle()
+    console.log(getConfirmGoods())
+    this.$bus.$on('hasLogin', () => {
+      this.notEmit = false
+      setTimeout(() => {
+        this.notEmit = true
+      }, 700)
+    })
+  },
+  methods: {
+    async pay () {
+      if (!this.checked) {
+        this.$alert('请同意四维看看用户协议')
+        return
+      }
+      let params = {
+        goods: this.goods,
+        receiver: this.address,
+        invoice: this.invoice,
+        payType: 0,
+        abroad: this.language === 'en' ? 1 : 0
+      }
+      let res = await this.$http
+        .post('user/order/placeOrder', params, {
+          headers: {
+            token: this.token
+          }
+        })
+      this.$store.dispatch('getCart')
+      this.$router.push({name: 'pay',
+        query: {
+          payType: this.paytype,
+          orderId: res.data.data.id,
+          orderType: 0,
+          orderSn: res.data.data.orderSn
+        }})
+    },
+    changeInvoice (invoice) {
+      this.invoice = invoice
+    },
+    changeAddress (address) {
+      this.address = address
+    },
+    showAgreement () {
+      this.openClause = true
+    },
+    cancel () {
+      this.openClause = false
+      this.checked = false
+    },
+    agree () {
+      if (this.allreadyRead) {
+        this.openClause = false
+        this.checked = true
+      }
+    },
+    sizeHandle: function () {
+      let scrollHanlde = () => {
+        let ny = this.$refs.clauseImg.offsetHeight
+        if (this.$refs.clause.scrollTop > ny - 700) {
+          this.allreadyRead = true
+        }
+      }
+      this.$refs.clause.addEventListener('scroll', scrollHanlde)
+    },
+    logoutHandle () {
+      this.$bus.$emit('hideAside')
+      this.openClause = false
+    }
+  }
+}
+</script>
+
+<style lang="less">
+.mall-confirm {
+  padding: 114px 0 187px;
+  background: #F7F7F7;
+  .container {
+    background: #fff;
+    box-shadow:0px 2px 2px rgba(0,0,0,0.11);
+    padding-bottom: 48px;
+  }
+  .confirm-header {
+    padding: 42px 0 30px;
+    border-bottom: 1px solid #E4E4E4;
+  }
+  .confirm-header-left {
+    padding-left: 92px;
+    h3, p {
+      display: inline-block;
+    }
+    h3 {
+      font-size: 24px;
+      margin-right: 26px;
+      vertical-align: middle;
+    }
+    p {
+      color: #909090;
+      font-size: 14px;
+      vertical-align: middle;
+    }
+  }
+  .step {
+    padding-right: 60px;
+    li {
+      display: inline-block;
+      color: #909090;
+      font-size: 12px;
+      &>* {
+        display: inline-block;
+        vertical-align: middle;
+      }
+      &:last-child {
+        .line {
+          display: none;
+        }
+      }
+    }
+    .step-num {
+      font-size: 14px;
+      background: #EBEBEB;
+      width: 25px;
+      height: 25px;
+      line-height: 25px;
+      text-align: center;
+      display: inline-block;
+      border-radius: 50%;
+      margin-right: 6px;
+      &.is-active {
+        background: #909090;
+        color: #f7f7f7;
+      }
+    }
+    .line {
+      width: 42px;
+      height: 1px;
+      background: #B7B7B7;
+      vertical-align: middle;
+      margin: 0 10px;
+    }
+  }
+  .confirm-items {
+    min-height: 133px;
+    padding: 0 0 0 92px;
+    border-bottom: 1px solid #E4E4E4;
+  }
+  .module-label {
+    font-size: 16px;
+    color: #202020;
+    font-weight: bold;
+    margin-right: 53px;
+    display: inline-block;
+    white-space: nowrap;
+  }
+  .order-detail-items {
+    padding-left: 92px;
+    display: flex;
+    .module-label {
+      padding-top: 55px;
+    }
+  }
+  .order-detail {
+    display: flex;
+    flex: 1;
+    padding-right: 85px;
+    border-bottom: 1px solid #ebebeb;
+  }
+  .detail-left {
+    min-height: 270px;
+    position: relative;
+    &::after {
+      content: '';
+      display: block;
+      height: 156px;
+      width: 1px;
+      background: #E4E4E4;
+      position: absolute;
+      right: -86px;
+      top: 54px;
+    }
+  }
+  .goods-item {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    padding: 20px 0;
+    width: 574px;
+    border-bottom: 1px solid #ebebeb;
+    &:last-child {
+      border-bottom: none;
+    }
+    .img-w {
+      width: 90px;
+      text-align: center;
+    }
+    img {
+      // width: 90px;
+      height: 90px;
+    }
+    h6 {
+      margin-bottom: 4px;
+    }
+    p {
+      color: #909090;
+      font-size: 12px;
+    }
+  }
+  .detail-right {
+    flex: 1;
+    margin-left: 176px;
+    padding-top: 53px;
+    font-size: 14px;
+    
+    .right-item {
+      margin-bottom: 30px;
+      line-height: 1;
+      display: flex;
+      justify-content: space-between;
+    }
+    .total-price {
+      border-top: 1px solid #EBEBEB;
+      text-align: right;
+      padding-top: 15px;
+      margin-top: -10px;
+      span {
+        font-weight: bold;
+      }
+    }
+  }
+  .xieyi {
+    font-size: 12px;
+    color: #909090;
+    padding: 12px 0 0 218px;
+    * {
+      vertical-align: middle;
+    }
+    span {
+      cursor: pointer;
+    }
+  }
+  .submit-btn {
+    width: 216px;
+    height: 55px;
+    line-height: 55px;
+    text-align: center;
+    background: #1fe4dc;
+    margin-right: 60px;
+    cursor: pointer;
+    font-weight: 600;
+  }
+}
+.user-clause{
+      width: calc(100vw - 450px);
+      color: #fff;
+      height: 100%;
+      position: relative;
+      text-align: center;
+      padding-bottom: 40px;
+      >div{
+        height: 85%;
+        padding: 0;
+        .clause-img{
+          height: 70vh;
+          width: 100%;
+          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;
+          }
+        }
+      }
+
+    }
+    .cart-clause{
+      width: calc(100vw - 730px);
+    }
+</style>

+ 130 - 29
pc/src/page/mall/kankanPro/index.vue

@@ -1,6 +1,6 @@
 <template>
-  <div class="purchase-layout container">
-    <div class="plate01">
+  <div class="purchase-layout ">
+    <div class="plate01 container">
       <div class="main-detail">
         <browse
           :idata='browdata'
@@ -15,28 +15,28 @@
           </p>
           <p class="postage">{{ $t('pages.mall.postage') }}</p>
           <template>
-            <div class="capacity">包含基础容量:10G<a>了解详情</a></div>
+            <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'">增值套餐(包含三脚架)</div>
+                <div :class="`package-item ${package === 'lot' ? 'active' : ''}`" @click="package='lot';selectParts=true">增值套餐(包含三脚架)</div>
               </h-col>
             </h-row>
-            <div>数量 <number v-model="count" :max="99" /></div>
+            <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="selectParts=!selectParts">
+            <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="/#/mall/purchasezhijia">了解详情</a>
+                <a :href="`${pathname}#/mall/zhijia`" target="_blank">了解详情</a>
               </div>
               <div class="zhijia-actions">
-                <p>¥899</p>
-                <number v-model="count" :max="99" />
+                <p>¥{{ mallConfig.zhijiaPrice }}</p>
+                <number v-model="zhijiaCount" :max="99" />
               </div>
             </div>
           </template>
@@ -56,28 +56,49 @@
                 </vcenter>
               </div>
             </div>
-            <div class="btn-dec" >预计3日内发货</div>
+            <div class="btn-dec" ><h-icon type="gouwuche" class="shop-cart-icon" />预计3日内发货</div>
           </div>
         </div>
       </div>
     </div>
     <div class="plate02" >
-      <div class="b-title">{{langPurchase.guige.name}}</div>
-      <div class="params-img-con">
-        <img class="params-img" :src="`${$cdn}images/product_img_content_6_w.png`" alt="">
+      <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>
+        </ul>
+        
       </div>
-      <div class="params-body">
-        <div class="params-con">
-          <div class="params-item" v-for="(item,index) in langPurchase.guige.arr" :key="index">
-            <div class="p-l">{{item.name}}</div>
-            <div class="p-r">
-              <div v-html="sub" v-for="(sub,i) in item.val" :key="i"></div>
+      <div class="product-detail container" v-show="detailType === 'product'" ref="homeLayout">
+        <div class="plate item" v-for="(item,i) in sequenceArr" :key="i">
+          <div class="container">
+            <h2 class="common-title">{{item.name}}</h2>
+            <sequence :runAnimation="item.runAnimation" :img="`${$cdn}images/sequence/v${item.img}.jpg`" />
+          </div>
+        </div>
+      </div>
+      <div class="tech-detail" v-show="detailType === 'tech'">
+        <div class="params-body">
+          <div class="container">
+            <h1 class="common-title">技术参数</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>
+                <div class="p-r">
+                  <div v-html="sub" v-for="(sub,i) in item.val" :key="i"></div>
+                </div>
+              </div>
+            </div>
+            <div class="sub">
+              <p>{{langPurchase.guige.dec}}</p>
             </div>
           </div>
+          
         </div>
-        <div class="sub">
-          <p>{{langPurchase.guige.dec}}</p>
+        <div class="params-img-con container">
+          <h1 class="common-title">尺寸参数</h1>
+          <img class="params-img" :src="`${$cdn}images/product_img_content_6_w.png`" alt="">
         </div>
+        
       </div>
     </div>
   </div>
@@ -91,13 +112,18 @@ import browse from '@/components/browse'
 import priceTable from '@/components/priceTable'
 import { getPosition } from '@/util'
 import number from '@/components/mall/number'
+import mallConfig from '@/config/mall'
+import sequence from '@/components/sequence'
+import { saveConfirmGoods } from '@/util/storage'
+
 export default {
   components: {
     spinner,
     vcenter,
     browse,
     priceTable,
-    number
+    number,
+    sequence
   },
   computed: {
     ...mapState({
@@ -108,7 +134,10 @@ export default {
       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))
+    }
   },
   data () {
     let detail = {
@@ -177,7 +206,47 @@ export default {
       count: 1,
       selectParts: true,
       package: 'lot',
-      totalPrice: '10,699'
+      mallConfig,
+      zhijiaCount: 1,
+      detailType: 'product',
+      pathname: window.location.pathname,
+      sequenceArr: [
+        {
+          name: 'AI全自动精准建模,智能测距',
+          img: 6,
+          runAnimation: true
+        },
+        {
+          name: '720度8K画质,身临其境',
+          img: '7test',
+          runAnimation: true
+        },
+        {
+          name: 'HDR模式平衡明暗区域曝光',
+          img: '7test',
+          runAnimation: true
+        },
+        {
+          name: '球幕视频真人解说 打造沉浸视听体验',
+          img: '7test',
+          runAnimation: true
+        },
+        {
+          name: '10分钟入门,快速掌握拍摄流程',
+          img: 8,
+          runAnimation: true
+        },
+        {
+          name: '10分钟全自动出结果,高效快速(约100㎡)',
+          img: 9,
+          runAnimation: true
+        },
+        {
+          name: '强大编辑后台,让空间延伸表达',
+          img: 10,
+          runAnimation: true
+        }
+      ]
     }
   },
   methods: {
@@ -190,7 +259,7 @@ export default {
       }
       let zhijia = {
         goodsId: 7,
-        goodsCount: this.count,
+        goodsCount: this.zhijiaCount,
         skuSn: 'U15604134406280073'
       }
       let params = {
@@ -211,19 +280,20 @@ export default {
         sku: [{
           goodsId: 4,
           goodsCount: this.count,
-          price: 9800,
+          price: 12800,
           skuSn: 'U15609161635760015'
         }],
         fromList: false
       }
       let zhijia = {
         goodsId: 7,
-        goodsCount: this.count,
-        price: 899,
+        goodsCount: this.zhijiaCount,
+        price: mallConfig.zhijiaPrice,
         skuSn: 'U15604134406280073'
       }
       this.selectParts && params.sku.push(zhijia)
-      this.$bus.$emit('showAside', params)
+      saveConfirmGoods(params.sku)
+      this.$router.push('/mall/confirm')
     },
     scrollTo (href) {
       this.interval = null
@@ -237,10 +307,41 @@ export default {
           clearInterval(this.interval)
         }
       })
+    },
+    changeSelectParts () {
+      if (this.package !== 'lot') {
+        this.selectParts=!this.selectParts
+      }
+      
+    }
+  },
+  mounted () {
+    this.sizeHandle = () => {
+      if (this.detailType !== 'product') {
+        return
+      }
+      let height = getPosition(this.$refs.homeLayout).y
+
+      let items = Array.from(this.$refs.homeLayout.querySelectorAll('.plate'))
+
+      if (this.startNumCount && this.slideActive) {
+        window.removeEventListener('scroll', this.sizeHandle)
+      }
+
+      items.forEach((item, index) => {
+        let addHeight = item.offsetParent && (item.offsetParent.nodeName).toLowerCase() === 'body' ? (item.offsetTop + height) : (item.offsetTop + item.offsetParent.offsetTop + height)
+        if (addHeight <= window.innerHeight + (window.scrollY || window.pageYOffset) + 500) {
+          this.sequenceArr[index]['runAnimation'] = false
+        } else {
+          this.sequenceArr[index]['runAnimation'] = true
+        }
+      })
     }
+    window.addEventListener('scroll', this.sizeHandle)
   },
   beforeDestroy () {
     clearInterval(this.interval)
+    window.removeEventListener('scroll', this.sizeHandle)
   }
 }
 </script>

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

@@ -25,6 +25,9 @@
   }
 }
 
+.number-w {
+  color: #909090;
+}
 .plate01{
   background: #fff;
   padding: 0 0 100px;
@@ -80,6 +83,12 @@
       font-weight: bold;
       padding-left: 20px;
       margin-top: 23px;
+      a {
+        color: #909090;
+        font-size: 12px;
+        margin-left: 20px;
+        text-decoration: underline;
+      }
     }
     .package-item {
       height: 55px;
@@ -267,7 +276,11 @@
       margin-top: 12px;
       font-size: 14px;
       color: #909090;
-      line-height: 16px;
+      .shop-cart-icon {
+        font-size: 26px;
+        vertical-align: middle;
+        margin-right: 5px;
+      }
     }
   }
   .totalPrice {
@@ -279,16 +292,35 @@
 .plate02{
   width: 100%;
   margin: 0 auto;
-  padding: 84px 0 0;
-  text-align: center;
-
-  .b-title{
-    font-weight: 700;
-    font-size: 28px;
-    color: rgba(0, 0, 0, 0.7);
-    line-height: 44px;
-    max-width: 300px;
-    margin: 0 auto;
+  padding: 84px 0 110px;
+  text-align: left;
+  .tabs {
+    color: #909090;
+    font-size: 16px;
+    font-weight: 600;
+    text-align: left;
+    padding: 37px 0 90px;
+    background: #F7F7F7;
+  }
+  .tabs-item {
+    display: inline-block;
+    cursor: pointer;
+    padding-right: 14px;
+    &:first-child {
+      border-right: 1px solid #909090;
+      margin-right: 14px;
+    }
+    &.is-active {
+      color: #202020;
+    }
+  }
+  .common-title {
+    margin: 80px 0 43px;
+  }
+  .params-body {
+    .common-title {
+      margin-top: 0;
+    }
   }
   .params-img-con{
     background: #fff;
@@ -300,8 +332,8 @@
 
   .params-body{
     width: 100%;
-    background: #f8f9fc;
-    padding: 84px 0;
+    background: #F7F7F7;
+    padding-bottom: 112px;
     .params-con{
       width: 621px;
       margin: 28px auto 12px;

+ 282 - 0
pc/src/page/mall/pay/index.vue

@@ -0,0 +1,282 @@
+<template>
+  <div class="mall-pay">
+    <div class="container">
+      <div class="pay-header">
+        <div class="logo">
+          <img src="@/assets/images/home/logo-cn.png" alt="">
+        </div>
+        <p>支付中心</p>
+      </div>
+      <div class="pay-content">
+        <div class="account"><span class="label">当前账号:</span><span>{{ info.nickName }}</span></div>
+        <div class="pay-types">
+          <p class="label">支付方式:</p>
+          <div class="pay-type ali-pay" @click="selectedPayType = 'alipay'" :class="{'is-active': selectedPayType === 'alipay'}">
+            <span class="pay-icon ali-icon"></span>
+            <h-icon type="vip_true" class="select-icon"></h-icon>
+            支付宝
+          </div>
+          <div class="pay-type wechat-pay " @click="selectedPayType = 'wechatPay'" :class="{'is-active': selectedPayType === 'wechatPay'}">
+            <span class="pay-icon wechat-icon"></span>
+            <h-icon type="vip_true" class="select-icon"></h-icon>
+            微信支付</div>
+        </div>
+        <div class="pay-info">
+          <p class="label">应付金额:</p>
+          <p class="price">¥{{response.price}}</p>
+          <div class="pay-qrcode">
+            <img :src="`${$serverName}${response.src}`" alt="">
+            <p>使用微信app扫码完成支付</p>
+          </div>
+          <div class="pay-scan-tip"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+let PAYSID = {
+  wechatPay: 0,
+  alipay: 1,
+  paypal: 2
+}
+export default {
+  data () {
+    return {
+      selectedPayType: 'alipay',
+      response: {},
+      t1: null
+    }
+  },
+  computed: {
+    ...mapState({
+      language: state => state.language.current,
+      languagePay: state => state.language.home.paypage,
+      token: state => state.user.token,
+      info: state => state.user.info,
+      langToast: state => state.language.home.toast
+    }),
+    payZH () {
+      return this.language === 'en' ? payTypesEn[this.selectedPayType] : payTypes[this.selectedPayType]
+    }
+  },
+  watch: {
+    selectedPayType (newVal, oldVal) {
+      this.getCode()
+    }
+  },
+  mounted () {
+    this.getCode()
+    console.log(this.info, 'info')
+  },
+  methods: {
+    inverRequest () {
+      clearInterval(this.t1)
+      this.t1 = null
+      this.t1 = setInterval(() => {
+        this.queryOrderStatus()
+      }, 5000)
+    },
+    async queryOrderStatus () {
+      if (this.t1) {
+        let {orderSn, orderType} = this.$route.query
+        if (!orderSn) {
+          return this.$toast.show('error', this.langToast['1'])
+        }
+
+        let params = {
+          orderSn,
+          orderType: Number(orderType),
+          payType: Number(PAYSID[this.selectedPayType])
+        }
+        let res = await this.$http
+          .post('/user/order/queryOrderStatus', params, {
+            headers: {
+              token: this.token
+            }
+          })
+        let response = res.data
+        if (response.code === 0 && response.data) {
+          this.t1 = null
+          this.t1 && clearInterval(this.t1)
+          this.$router.replace({
+            name: 'payresult',
+            params: {
+              isSuccess: 'success'
+            }
+          })
+        }
+      }
+    },
+    async getCode () {
+      let {orderId, orderType} = this.$route.query
+      if (!orderId || (!orderType && orderType !== 0)) {
+        return this.$toast.show('error', this.langToast['1'])
+      }
+      if (this.selectedPayType !== 'paypal') {
+        let params = {
+          orderId: orderId,
+          orderType: Number(orderType)
+        }
+        let res = await this.$http
+          .post(`/order/pay/${this.selectedPayType}`, params, {
+            headers: {
+              token: this.token
+            }
+          })
+        let response = res.data
+        if (response.code !== 0) {
+          return this.$toast.show('error', this.langToast['2'], () => {
+            this.t1 = null
+            this.t1 && clearInterval(this.t1)
+          })
+        }
+        this.response = response.data
+        this.inverRequest()
+      } else {
+        this.t1 = null
+        this.t1 && clearInterval(this.t1)
+        this.$toast.show('warn', this.langToast['3'])
+      }
+    }
+  },
+  beforeDestroy () {
+    clearInterval(this.t1)
+    this.t1 = null
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.mall-pay {
+  padding: 114px 0 188px;
+  background: #F7F7F7;
+  .container {
+    background: #fff;
+  }
+  .pay-header {
+    border-bottom: 1px solid #E4E4E4;
+    padding: 26px 0 21px 92px;
+    font-size: 24px;
+    line-height: 32px;
+    .logo, p {
+      display: inline-block;
+      vertical-align: middle;
+    }
+    .logo {
+      margin-right: 52px;
+      position: relative;
+      &::after {
+        content: '';
+        display: block;
+        width: 1px;
+        height: 34px;
+        background: #C8C8C8;
+        position: absolute;
+        right: -30px;
+        top: 11px;
+      }
+    }
+  }
+  .pay-content {
+    padding: 0 92px 80px;
+  }
+  .account {
+    height: 56px;
+    line-height: 56px;
+    font-weight: bold;
+    border-bottom: 1px solid #E4E4E4;
+  }
+  .label {
+    font-weight: bold;
+    margin-right: 13px;
+  }
+  .pay-types {
+    padding: 50px 0;
+    border-bottom: 1px solid #E4E4E4;
+    &>p, &>div {
+      display: inline-block;
+    }
+    .pay-type {
+      width: 190px;
+      height: 40px;
+      line-height: 40px;
+      margin-right: 30px;
+      border: 1px solid #909090;
+      border-radius: 2px;
+      padding-left: 60px;
+      cursor: pointer;
+      position: relative;
+      &.is-active {
+        border-color: #1FE4DC;
+        &::after {
+          content: '';
+          display: block;
+          position: absolute;
+          right: 0;
+          bottom: 0;
+          border-bottom: 20px solid #1FE4DC;
+          border-left: 22px solid transparent;
+        }
+      }
+      .select-icon {
+        color: #fff;
+        position: absolute;
+        bottom: 0;
+        right: 0;
+        z-index: 1;
+        line-height: 1;
+        font-size: 12px;
+      }
+    }
+    .pay-icon {
+      position: absolute;
+      left: 4px;
+      top: 0;
+      height: 40px;
+      width: 34px;
+      display: inline-block;
+      background: url(~@/assets/images/refactor/mall/ali-icon.png) no-repeat center center;
+      background-size: 34px 34px;
+      &.wechat-icon {
+        background: url(~@/assets/images/refactor/mall/wechat-icon.png) no-repeat center center;
+        background-size: 28px 25px;
+        
+      }
+    }
+  }
+  .pay-info {
+    padding-top: 24px;
+    position: relative;
+    &>p {
+      display: inline-block;
+      vertical-align: middle;
+    }
+    .price {
+      color: #1FE4DC;
+      font-size: 40px;
+      line-height: 50px;
+    }
+  }
+  .pay-qrcode {
+    padding: 60px 0 0 337px;
+    img {
+      width: 190px;
+      height: 190px;
+      margin-bottom: 7px;
+      display: block;
+    }
+  }
+  .pay-scan-tip {
+    width: 186px;
+    height: 165.5px;
+    background: url(~@/assets/images/refactor/mall/scan-tip.png) no-repeat center center;
+    background-size: contain;
+    position: absolute;
+    top: 113px;
+    left: 562px;
+  }
+}
+</style>

+ 307 - 0
pc/src/page/mall/zhijia/index.vue

@@ -0,0 +1,307 @@
+<template>
+  <div class="purchase-layout">
+    <div class="plate01 container">
+      <div class="main-detail">
+        <browse
+          :idata='browdata'
+          :iactive='browactive'
+          :floder="'zhijiabrowse'"
+          class="product-img"
+         />
+        <!-- <video class="product-img" :style="{marginLeft:(split - 500)+ 'px'}" :src="`${$cdn}video/zhijia-video.mp4`" autoplay muted loop></video> -->
+        <div class="layout">
+          <!-- <img class="pro-logo" :src="this.language==='en'?`${$cdn}images/zhijia-logo-en.png`:`${$cdn}images/zhijia-logo-black.png`" alt=""> -->
+          <h1 class="pro-title">四维看看Pro三脚架套装</h1>
+          <p class="sub b-label" v-html="langPurchase.dec"></p>
+          <p class="price">
+             ¥{{mallConfig.zhijiaPrice}}
+            <!-- <span>{{langPurchase.yushou}}</span> -->
+          </p>
+          <p class="postage">运费:顺丰包邮</p>
+          <template>
+            <div class="taozhuang">
+              <p class="taozhuang-title">套装内容</p>
+              <div class="detail-box sceond-box">
+                <ul>
+                  <li v-for="(item, i) in langPurchase.service.val" :key="i">{{item}}</li>
+                </ul>
+              </div>
+            </div>
+          </template>
+          <template v-if="language!=='en'">
+            <span class="num-title" >{{langPurchase.count.key}}</span>
+            <!-- <spinner class="spinner" @count="handleSpinner"/> -->
+            <number v-model="count" :max="99" />
+          </template>
+          <div>
+            <div class="btns">
+              <div v-if="language!=='en'" class="button add-cart" @click="addcart">
+                <vcenter>
+                  <span>{{langPurchase.cart}}</span>
+                </vcenter>
+              </div>
+              <div class="button" @click="pay">
+                <vcenter>
+                  <span>{{langPurchase.buy}}</span>
+                </vcenter>
+              </div>
+            </div>
+            <div class="btn-dec"><h-icon type="gouwuche" class="shop-cart-icon" />预计3日内发货</div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="plate02">
+      <div class="container">
+        <h1 class="common-title">{{langPurchase.zhijia.name}}</h1>
+        <div class="b-label">{{langPurchase.zhijia.sub}}</div>
+      </div>
+      
+      <!-- <div class="b-title">{{langPurchase.zhijia.name}}</div> -->
+      
+      <div class="p2-con">
+        <img class="p2c-img" :src="`${$cdn}images/zhijia-left.png`" alt="">
+        <div class="b-info">
+          <div class="right-title">{{langPurchase.zhijia.detail}}</div>
+          <div class="right-line"></div>
+          <div class="right-con">
+            <div v-for="(item,i) in langPurchase.zhijia.detailArr" :key="i">
+              <img :src="item.img" alt="">
+              <div class="low-title">{{item.name}}</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="plate03 container" >
+      <div class="b-title">{{langPurchase.guige.name}}</div>
+      <h-row class="params-con" :gutter="95">
+        <h-col class="params-item" :span="12"  v-for="(item,index) in langPurchase.guige.arr" :key="index">
+          <div>
+            <div class="p-l" :style="{width:language==='en'?'300px':'100px'}">{{item.name}}</div>
+            <div class="p-r" :style="{width:getRWidth(index)}">
+              <div v-html="sub" v-for="(sub,i) in item.val" :key="i"></div>
+            </div>
+          </div>
+        </h-col>
+      </h-row>
+      <div class="sub">
+        <p v-for="(ites,i) in langPurchase.guige.dec" :key="i">{{ites}}</p>
+      </div>
+    </div>
+
+    <div class="plate04">
+      <div class="container">
+        <h1 class="common-title">{{langPurchase.hualun.name}}</h1>
+        <div class="b-label">{{langPurchase.hualun.sub}}</div>
+      </div>
+      <div class="p4-img">
+        <img :src=" language==='en'?`${$cdn}images/p4zhijia-len.png`:`${$cdn}images/p4zhijia-l.png`"  alt="">
+        <img :src=" language==='en'?`${$cdn}images/p4zhijia-ren.png`:`${$cdn}images/p4zhijia-r.png`"  alt="">
+      </div>
+    </div>
+
+    <div class="plate03 container" >
+      <div class="b-title">{{langPurchase.lunguige.name}}</div>
+      <h-row class="params-con" :gutter="95">
+        <h-col class="params-item" :span="12"  v-for="(item,index) in langPurchase.lunguige.arr" :key="index">
+          <div>
+            <div class="p-l" :style="{width:language==='en'?'300px':'100px'}">{{item.name}}</div>
+            <div class="p-r" :style="{width:getRWidth(index)}">
+              <div v-html="sub" v-for="(sub,i) in item.val" :key="i"></div>
+            </div>
+          </div>
+        </h-col>
+      </h-row>
+
+      <div class="sub">
+        <p>{{langPurchase.lunguige.dec}}</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import spinner from '@/components/spinner'
+import vcenter from '@/components/vcenter'
+import browse from '@/components/browse'
+import priceTable from '@/components/priceTable'
+import mallConfig from '@/config/mall'
+import { saveConfirmGoods } from '@/util/storage'
+import number from '@/components/mall/number'
+
+export default {
+  components: {
+    spinner,
+    vcenter,
+    browse,
+    priceTable,
+    number
+  },
+  computed: {
+    ...mapState({
+      split: state => state.ui.navDivision,
+      isLogin: state => state.user.name,
+      langPurchase: state => state.language.home.purchasezhijia,
+      langToast: state => state.language.home.toast,
+      language: state => state.language.current,
+      token: state => state.user.token,
+      cart: state => JSON.parse(state.user.cart)
+    })
+  },
+  data () {
+    let zhijiadetail = [
+      {
+        name: '专业球形云台',
+        img: `${this.$cdn}images/zhijia-detail01.png`
+      },
+      {
+        name: '脚管三段角度调节按钮',
+        img: `${this.$cdn}images/zhijia-detail02.png`
+      },
+      {
+        name: '安全的中轴升降锁紧按钮',
+        img: `${this.$cdn}images/zhijia-detail03.png`
+      },
+      {
+        name: '防滑保暖致密海绵护手',
+        img: `${this.$cdn}images/zhijia-detail04.png`
+      },
+      {
+        name: '可伸缩中轴挂钩稳定脚架',
+        img: `${this.$cdn}images/zhijia-detail05.png`
+      },
+      {
+        name: '方便快捷的版扣脚管',
+        img: `${this.$cdn}images/zhijia-detail06.png`
+      }
+    ]
+    let detail = {
+      left: [
+        '数据永久存储',
+        '高速上传计算队列',
+        '场景分享、热点编辑、隐私加密'
+      ],
+      right: ['多种个性化功能', '附送30G终身容量']
+    }
+    let guige = [
+      {
+        name: '容量和内存',
+        val: ['LPDDR4X双通道', '6G内存', 'UFS 2.1', '64GB 机身存储']
+      },
+      {
+        name: '机身尺寸和重量',
+        val: ['高度 = 153.3m', '宽度 = 74.5mm', '厚度 = 7.9mm', '重量 = 170g']
+      },
+      {
+        name: '处理器平台',
+        val: [
+          'Qualcomm® 骁龙™ 845 处理器',
+          '10nm 先进制程',
+          '单核主频可达 2.8GHz',
+          'Adreno™ 630 图形处理器,主频可达 700MHz',
+          '配备人工智能引擎(AI Engine)'
+        ]
+      },
+      {
+        name: '网络',
+        val: ['支持 VoLTE 高质量宽带', '支持三载波聚', '支持 LTE B41 4x4 MIMO']
+      },
+      {
+        name: '屏幕',
+        val: [
+          '6.17 英寸 In-Cell 全高清显示屏',
+          '2242 x 1080 分辨率,403 ppi',
+          '康宁®第三代大猩猩®玻璃'
+        ]
+      }
+    ]
+    let browdata = [
+      {
+        small: 'small-0',
+        big: 'big-0',
+        video: true
+      }, {
+        small: 'small-1',
+        big: 'big-1'
+      },
+      {
+        small: 'small-2',
+        big: 'big-2'
+      },
+      {
+        small: 'small-3',
+        big: 'big-3'
+      },
+      {
+        small: 'small-4',
+        big: 'big-4'
+      }]
+    let browactive = browdata[0]
+    return {
+      mallConfig,
+      detail,
+      zhijiadetail,
+      guige,
+      browactive,
+      browdata,
+      count: 1,
+      selectParts: true
+    }
+  },
+  methods: {
+    getWidth (index) {
+      let zhW = index > this.langPurchase.lunguige.arr.length - 5 ? '100%' : index % 2 === 0 ? 'calc(100% - 36.1%)' : '36.1%'
+      return this.language === 'en' ? '100%' : zhW
+    },
+    getRWidth (index) {
+      let zhW = index > this.langPurchase.lunguige.arr.length - 5 ? 'calc(100% - 110px)' : '200px'
+      return this.language === 'en' ? 'calc(100% - 320px)' : zhW
+    },
+    handleSpinner (data) {
+      this.count = data
+    },
+    gobuy () {
+    },
+    async addcart () {
+      if (!this.token) {
+        return this.$bus.$emit('showAside')
+      }
+      let params = {
+        goodsId: 7,
+        goodsCount: this.count,
+        skuSn: 'U15604134406280073'
+      }
+      await this.$store.dispatch('addCart', params)
+      this.$toast.show('success', this.langToast['39'])
+    },
+    pay () {
+      if (this.language === 'en') {
+        return window.open('https://www.alibaba.com/product-detail/4DKanKan-Pro-Tripod-Set_62431649408.html?spm=a2700.icbuShop.41413.11.339877f3TUXWiN')
+      }
+      let params = {
+        type: 'detail',
+        sku: [{
+          goodsId: 7,
+          goodsCount: this.count,
+          price: 899,
+          skuSn: 'U15604134406280073'
+        }],
+        fromList: false
+      }
+      saveConfirmGoods(params.sku)
+      this.$router.push('/mall/confirm')
+    }
+  },
+  beforeDestroy () {
+    clearInterval(this.interval)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "./style.scss";
+</style>

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

@@ -0,0 +1,461 @@
+.purchase-layout {
+  overflow: hidden;
+}
+
+.btns{
+  font-size: 0;
+}
+.btns .button{
+  cursor: pointer;
+  width: 250px;
+  height: 50px;
+  padding-top: 0;
+  padding-bottom: 0;
+  margin-top: 24px;
+  line-height: 50px;
+  color: #202020;
+  font-weight: bold;
+  text-align: center;
+  font-size: 16px;
+  width: 216px;
+  img{
+    vertical-align: middle;
+  }
+  span{
+    vertical-align: middle;
+    padding-left: 2px;
+  }
+}
+
+.plate01{
+  padding: 0 0 100px;
+  .main-detail{
+    padding-top: 20px;
+  }
+  .pro-title {
+    font-size: 40px;
+    line-height: 83px;
+  }
+  .postage {
+    color: #909090;
+    font-size: 16px;
+    line-height: 30px;
+  }
+  .taozhuang {
+    width: 460px;
+    height: 126px;
+    border: 1px solid #1fe4dc;
+    margin: 22px 0;
+    padding: 16px;
+    .taozhuang-title {
+      display: inline-block;
+      font-weight: bold;
+      margin-right: 16px;
+      vertical-align: top;
+    }
+  }
+  .num-title {
+    color: #909090;
+    font-size: 16px;
+    margin-right: 12px;
+  }
+  .p1-banner{
+    background: #fff;
+    height: 65px;
+    text-align: right;
+    padding-right: 120px;
+    span{
+      display: inline-block;
+      margin-left: 50px;
+      padding-top: 40px;
+      cursor: pointer;
+      font-size: 16px;
+    }
+  }
+  .product-img{
+    display: inline-block;
+  }
+  .layout{
+    width: 540px;
+    margin-top: 60px;
+    margin-left: 8%;
+    display: inline-block;
+    vertical-align: top;
+    .pro-logo{
+      margin-bottom: 8px;
+    }
+    .price{
+      margin-top: 14px;
+      font-size: 28px;
+      line-height: 1;
+      color: rgba(0,0,0,.7);
+      font-weight: 700;
+      span{
+        font-size: 14px;
+        color: #1fe4dc;
+        font-weight: bold;
+      }
+    }
+    .title{
+      font-size: 14px;
+      color: rgba(0,0,0,.7);
+      line-height: 18px;
+      font-weight: 600;
+      margin:6px 0 0;
+    }
+    .peijian{
+      vertical-align: middle;
+      margin-bottom: 19px;
+      color: #486ace;
+      cursor: pointer;
+      font-weight: normal;
+      img{
+        vertical-align: middle;
+        width: 16px;
+        height: 16px;
+      }
+      span{
+        display: inline-block;
+        vertical-align: middle;
+      }
+    }
+    .first-title{
+      margin-top: 20px;
+    }
+    .detail-box{
+      position: relative;
+      display: inline-block;
+      color: rgba(0,0,0,.45);
+      padding: 5px 0;
+      line-height: 1.5;
+      width: 250px;
+      box-sizing: border-box;
+      text-align: left;
+      line-height:33px;
+      font-size: 16px;
+      color: #909090;
+      .t-click{
+        position: absolute;
+        right: 0;
+        bottom: 0;
+        margin: 0;
+        width: 16px;
+        height: 16px;
+      }
+      .icon-yuandian::before{
+        margin-right: 6px;
+        font-size: 16px;
+      }
+      .line{
+        display: inline-block;
+        width: 1px;
+        height: 56px;
+        background: #e2e2e2;
+        margin: 5px 39px 0 40px;
+      }
+      ul{
+        display: inline-block;
+        vertical-align: top;
+        &:last-child{
+          margin: 2px 20px 0;
+        }
+        li{
+          font-size: 14px;
+          line-height: 1;
+          position: relative;
+          margin-bottom: 20px;
+          &::before{
+            content: '';
+            width: 3px;
+            height: 3px;
+            border-radius: 50%;
+            display: inline-block;
+            position: absolute;
+            left: -15px;
+            top: 50%;
+            transform: translateY(-50%);
+            background-color: rgba(0,0,0,.45);
+          }
+        }
+      }
+    }
+    .sceond-box{
+      padding-bottom: 2px;
+      
+      .icon-yuandian{
+        padding: 12px 0 16px;
+        height: auto;
+        -webkit-box-sizing: border-box;
+        box-sizing: border-box;
+        font-size: 16px;
+        color: #000;
+      }
+    }
+    .zhijia{
+      padding: 10px 3.5%;
+      cursor: pointer;
+      text-align: center;
+      border: 1px solid #70eee9;
+      display: flex;
+      align-items: center;
+      margin: 8px 0 6px;
+      img{
+        vertical-align: middle;
+        margin-right: 20px;
+        height: 60px;
+      }
+      p{
+        text-align: left;
+        vertical-align: middle;
+        font-size: 14px;
+      }
+    }
+    .no-active{
+      border: 1px solid #e3e3e3;
+      background-color: #fff;
+      .t-click{
+        display: none;
+      }
+    }
+    .spinner{
+      margin-top: 10px;
+    }
+    .btns {
+      img{
+        width: 24px;
+      }
+    }
+    .btns .add-cart{
+      background: #e7e7e7;
+      margin-right: 28px;
+    }
+    .btn-dec{
+      margin-top: 12px;
+      font-size: 14px;
+      color: #909090;
+      line-height: 16px;
+      .shop-cart-icon {
+        font-size: 26px;
+        vertical-align: middle;
+        margin-right: 5px;
+      }
+    }
+  }
+}
+.plate02{
+  padding: 84px 0;
+  background: #F7F7F7;
+  .common-title {
+    margin-top: 0;
+  }
+  .b-title,
+  .b-label {
+    // text-align: center;
+    margin-top: 51px;
+  }
+  .p2-con{
+    text-align: right;
+    position: relative;
+    margin-top: 45px;
+    .p2c-img{
+      width: 700px;
+      position: absolute;
+      top: 0;
+      left: 0;
+    }
+    .b-info {
+      text-align: justify;
+      display: inline-block;
+      max-width: 680px;
+      margin-right: 17%;
+      padding: 80px 0 0;
+      .right-title {
+        font-weight: bold;
+        color: #202020;
+      }
+      .right-line {
+        width: 100%;
+        height: 1px;
+        background: #e2e2e2;
+        margin-top: 15px;
+      }
+      .p-sub {
+        font-size: 14px;
+        color: rgba($color: #fff, $alpha: 0.8);
+      }
+      .right-con {
+        width: 110%;
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: space-between;
+        margin: 20px 0;
+        transform: translateX(-4.5%);
+        > div {
+          text-align: center;
+          width: 30%;
+          margin-bottom: 40px;
+        }
+      }
+      .low-title {
+        margin-top: 18px;
+        line-height: 24px;
+        font-size: 16px;
+        color: #95979B;
+        font-weight: normal;
+      }
+      .b-title,
+      .b-label {
+        text-align: justify;
+      }
+      img {
+        width: 68%;
+      }
+    }
+  }
+
+}
+
+
+.plate03{
+  padding: 84px 0;
+  text-align: center;
+  // background: #f8f9fc;
+  .b-title{
+    font-weight: 600;
+    font-size: 16px;
+    color: #202020;
+    line-height: 21px;
+    padding-bottom: 11px;
+    border-bottom: 1px solid #909090;
+    text-align: left;
+    width: 590px;
+  }
+  .params-con{
+    margin-top: 40px;
+    .params-item{
+      display: inline-block;
+      
+      text-align: left;
+      
+      &:last-of-type,&:nth-of-type(-2){
+        border-bottom: 1px solid #e7e7e7;
+      }
+      &>div{
+        text-align: left;
+        border-bottom: 1px solid #e7e7e7;
+        width: 100%;
+        padding: 28px 0;
+        &>div {
+          display: inline-block;
+        }
+      }
+      .p-l{
+        width: 100px;
+        height: 100%;
+        text-align: left;
+        font-size: 14px;
+        color: #202020;
+        line-height: 1.5;
+        font-weight: 600;
+        margin: 0;
+        vertical-align: top;
+      }
+      .p-r{
+        width: 200px;
+        height: 100%;
+        text-align: left;
+        div{
+          line-height: 1.5;
+          font-size: 14px;
+          color: rgba(0, 0, 0, 0.45);
+          margin-right: 0px;
+        }
+      }
+    }
+  }
+  .sub{
+    width: 845px;
+    text-align: left;
+    padding: 28px 0;
+    font-size: 12px;
+    color: #909090;
+    line-height: 20px;
+  }
+}
+
+.plate04{
+  padding: 84px 0;
+  background: #F7F7F7;
+  .common-title {
+    margin-top: 0;
+  }
+  .b-title,
+  .b-label {
+    // text-align: center;
+    margin-top: 51px;
+  }
+  .p4-img{
+    max-width: 75%;
+    margin: 40px auto;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    img{
+      margin-top: 45px;
+      width: 45%;
+    }
+  }
+}
+
+
+@media screen and (min-width: 2000px) {
+  .plate01 {
+    .main-detail{
+      max-width: 1920px;
+      margin: 0 auto!important;
+    }
+    
+  }
+
+}
+
+
+@media screen and (max-width: 1600px) {
+  .plate01 {
+    .product-img{
+      margin: 0 0 0 3%!important;
+    }
+    .layout{
+      margin-left:3%;
+    }
+    .pro-logo{
+      max-width: 100%;
+    }
+  }
+
+  .plate02{
+    .p2-con {
+      .p2c-img{
+        width: 580px;
+        top: 70px;
+      }
+      .b-info{
+        margin-right: 8%;
+        max-width: 650px;
+      }
+    }
+  } 
+
+}
+
+@media screen and (max-width: 1500px) {
+  .plate02{
+    .p2-con {
+      .b-info{
+        margin-right: 8%;
+        max-width: 550px;
+      }
+    }
+  } 
+
+}

+ 19 - 15
pc/src/page/manage/index.vue

@@ -1,7 +1,7 @@
 <template>
-  <div class="manage-layout" v-show="split">
+  <div class="manage-layout">
     <div class="manage-bg">
-      <div class="manage-con" :style="{marginLeft:(split + 37)+'px'}">
+      <div class="manage-con container">
         <template v-if="!deviceLogin">
           <div class="info">
             <div class="member">
@@ -56,20 +56,24 @@
         </template>
       </div>
     </div>
-    <div class="manage-body">
-      <div class="mc-left" :style="{width:split+'px'}">
-        <div v-for="(item,index) in settings" :key="index">
-          <ul class="list-items">
-            <li v-for="(sub,i) in item.items" :key="i">
-              <span @click="tabHandle(sub)" :class="{active:active.name===sub.name,'logout-span':sub.name === '退出登录'||sub.name === 'Log out'}">{{sub.name}}</span>
-            </li>
-          </ul>
+    <div class="manage-body ">
+      <div class="container">
+
+      
+        <div class="mc-left">
+          <div v-for="(item,index) in settings" :key="index">
+            <ul class="list-items">
+              <li v-for="(sub,i) in item.items" :key="i">
+                <span @click="tabHandle(sub)" :class="{active:active.name===sub.name,'logout-span':sub.name === '退出登录'||sub.name === 'Log out'}">{{sub.name}}</span>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="mc-right">
+          <div class="mc-title">{{active.name}}</div>
+          <router-view />
+          <!-- <component :is="active.cp"/> -->
         </div>
-      </div>
-      <div class="mc-right">
-        <div class="mc-title">{{active.name}}</div>
-        <router-view />
-        <!-- <component :is="active.cp"/> -->
       </div>
     </div>
   </div>

+ 7 - 2
pc/src/page/manage/style.scss

@@ -136,10 +136,14 @@
   }
   .manage-body{
     min-height: 676px;
-    display: flex;
+    
+    background-color: #f4f4f6;
+    .container {
+      display: flex;
+    }
     .mc-left{
       flex-shrink: 0;
-      background-color: #f4f4f6;
+      
       border-right: 1px solid #e7e7e7;
       padding-top: 30px;
       min-height: 550px;
@@ -190,6 +194,7 @@
     }
     .mc-right{
       width: 100%;
+      background: #fff;
       .mc-title{
         margin-left: 40px;
         margin-top: 34px;

+ 1 - 0
pc/src/page/manage/temp/information.vue

@@ -5,6 +5,7 @@
       @clickOper="handleOper('infoStatus')"
       :oper="infoStatus?langAccount.edit:langAccount.show"
       :isActive="infoStatus"
+      class="container"
     >
       <div class="info" :class="{'info-en':language==='en'}" slot="show">
         <div class="s-tx">

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

@@ -261,7 +261,7 @@ export default {
     toPay (item) {
       this.$router.push({
         name: 'pay',
-        params: {
+        query: {
           payType: 0,
           orderId: item.id,
           orderType: 0,

+ 0 - 0
pc/src/page/news/index.vue


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików