Procházet zdrojové kódy

Merge branch 'master' of guanli/ngfrontend into develop

Tyler před 9 měsíci
rodič
revize
1ddd152e5d
77 změnil soubory, kde provedl 10164 přidání a 7474 odebrání
  1. 22 9
      .env.development
  2. 3 2
      .env.production
  3. 10 4
      .env.staging
  4. 3 0
      .gitignore
  5. 116 115
      package.json
  6. 19 15
      public/index.html
  7. 98 13
      src/App.vue
  8. 9 0
      src/api/config.js
  9. 8 0
      src/api/finance.js
  10. 15 1
      src/api/setting.js
  11. 37 1
      src/api/shop.js
  12. 32 4
      src/api/user.js
  13. 9 3
      src/components/Breadcrumb/index.vue
  14. 155 155
      src/components/Charts/Keyboard.vue
  15. 227 227
      src/components/Charts/LineMarker.vue
  16. 271 271
      src/components/Charts/MixChart.vue
  17. 55 42
      src/components/LangSelect/index.vue
  18. 0 31
      src/components/MarkdownEditor/default-options.js
  19. 0 118
      src/components/MarkdownEditor/index.vue
  20. 1 1
      src/components/Pagination/index.vue
  21. 487 0
      src/components/TreeChart/index.vue
  22. 571 509
      src/lang/en.js
  23. 2 2
      src/lang/index.js
  24. 566 505
      src/lang/zh.js
  25. 212 184
      src/layout/components/Navbar.vue
  26. 3 3
      src/layout/components/Sidebar/SidebarItem.vue
  27. 1 1
      src/layout/components/Sidebar/index.vue
  28. 105 105
      src/layout/index.vue
  29. 58 58
      src/main.js
  30. 7 9
      src/permission.js
  31. 11 11
      src/router/index.js
  32. 15 3
      src/router/modules/atlas.js
  33. 0 6
      src/router/modules/components.js
  34. 7 1
      src/router/modules/config.js
  35. 18 6
      src/router/modules/shop.js
  36. 12 6
      src/router/modules/user.js
  37. 2 0
      src/store/getters.js
  38. 10 2
      src/store/modules/app.js
  39. 21 2
      src/store/modules/settings.js
  40. 17 5
      src/store/modules/user.js
  41. 163 147
      src/utils/request.js
  42. 44 0
      src/utils/tool.js
  43. 7 2
      src/views/article/article-list.vue
  44. 218 0
      src/views/atlas/placement-network-ex.vue
  45. 134 134
      src/views/atlas/placement-network.vue
  46. 215 0
      src/views/atlas/sponsor-network-ex.vue
  47. 131 131
      src/views/atlas/sponsor-network.vue
  48. 214 154
      src/views/bonus/account-list.vue
  49. 82 100
      src/views/bonus/bonus-list.vue
  50. 44 96
      src/views/bonus/historical-cumulative-bonus.vue
  51. 85 85
      src/views/bonus/team-inquiry.vue
  52. 0 101
      src/views/components-demo/markdown.vue
  53. 9 4
      src/views/config/shipping-address-list.vue
  54. 102 102
      src/views/dashboard/admin/components/BarChart.vue
  55. 135 135
      src/views/dashboard/admin/components/LineChart.vue
  56. 4 6
      src/views/dashboard/admin/components/PanelGroup.vue
  57. 79 79
      src/views/dashboard/admin/components/PieChart.vue
  58. 116 116
      src/views/dashboard/admin/components/RaddarChart.vue
  59. 10 5
      src/views/dashboard/admin/index.vue
  60. 313 248
      src/views/finance/recharge-list.vue
  61. 11 11
      src/views/finance/transfer-list.vue
  62. 15 0
      src/views/login/index.vue
  63. 91 60
      src/views/profile/components/Account.vue
  64. 26 4
      src/views/profile/components/UserCard.vue
  65. 37 30
      src/views/profile/index.vue
  66. 4 4
      src/views/shop/ba-dec-order-list.vue
  67. 541 531
      src/views/shop/car-fund-products.vue
  68. 4 4
      src/views/shop/dec-order-list.vue
  69. 24 10
      src/views/shop/order-list.vue
  70. 921 0
      src/views/shop/reconsume.vue
  71. 789 730
      src/views/shop/standard-products.vue
  72. 541 531
      src/views/shop/villa-fund-products.vue
  73. 12 12
      src/views/user/brand-ambassador.vue
  74. 214 0
      src/views/user/member-order.vue
  75. 630 592
      src/views/user/member-upgrade.vue
  76. 838 747
      src/views/user/welcome-pack.vue
  77. 146 133
      vue.config.js

+ 22 - 9
.env.development

@@ -1,9 +1,22 @@
-# just a flag
-ENV='development'
-
-# base api
-VUE_APP_BASE_API=''
-VUE_APP_CDN_API='http://16.163.228.151:8041'
-VUE_APP_BASE_WEBSITE='http://local.ng.frontend.ele.com:8080'
-VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
-VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '
+# just a flag
+ENV='development'
+
+# base api
+#VUE_APP_BASE_API=''
+#VUE_APP_BASE_DO_API='http://local.ng.frontend.api.com'
+#VUE_APP_CDN_API='http://16.163.228.151:8041'
+#VUE_APP_BASE_WEBSITE='http://local.ng.frontend.ele.com'
+#VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
+#VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '
+
+# test
+# # api请求地址
+ VUE_APP_BASE_API='http://16.163.228.151:8018'
+ # 文件下载地址
+ VUE_APP_BASE_DO_API='http://16.163.228.151:8018'
+ # CDN文件地址
+ VUE_APP_CDN_API='http://16.163.228.151:8021'
+ # 会员页面地址
+ VUE_APP_BASE_WEBSITE='http://16.163.228.151:8017'
+ VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
+ VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '

+ 3 - 2
.env.production

@@ -2,8 +2,9 @@
 ENV='production'
 
 # base api
-VUE_APP_BASE_API='https://ng-frontend-api.elken.com'
-VUE_APP_CDN_API='http://ng-upload.elken.com'
+VUE_APP_BASE_API=''
+VUE_APP_BASE_DO_API='https://ng-frontend-api.elken.com'
+VUE_APP_CDN_API='https://ng-upload.elken.com'
 VUE_APP_BASE_WEBSITE='https://ngds.elken.com'
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_live_fae524f9d073d877beeb661fd825a37a9bc91f0a'
 VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '

+ 10 - 4
.env.staging

@@ -3,9 +3,15 @@ NODE_ENV=production
 # just a flag
 ENV='staging'
 
-# base api
-VUE_APP_BASE_API='http://16.163.228.151:8039'
-VUE_APP_CDN_API='http://16.163.228.151:8041'
-VUE_APP_BASE_WEBSITE='http://16.163.228.151:8035'
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
 VUE_APP_ACCESS_TOKEN_PREFIX='Bearer '
+
+# test
+# # api请求地址
+ VUE_APP_BASE_API='http://16.163.228.151:8018'
+ # 文件下载地址
+ VUE_APP_BASE_DO_API='http://16.163.228.151:8018'
+ # CDN文件地址
+ VUE_APP_CDN_API='http://16.163.228.151:8021'
+ # 会员页面地址
+ VUE_APP_BASE_WEBSITE='http://16.163.228.151:8017'

+ 3 - 0
.gitignore

@@ -1,6 +1,7 @@
 .DS_Store
 node_modules/
 dist/
+dist.zip
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
@@ -23,3 +24,5 @@ package-lock.json
 yarn.lock
 
 .env.development
+
+.prettieirc.json

+ 116 - 115
package.json

@@ -1,115 +1,116 @@
-{
-  "name": "vue-element-admin",
-  "version": "4.3.1",
-  "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
-  "author": "Pan <panfree23@gmail.com>",
-  "scripts": {
-    "dev": "vue-cli-service serve",
-    "lint": "eslint --ext .js,.vue src",
-    "build:prod": "vue-cli-service build",
-    "build:stage": "vue-cli-service build --mode staging",
-    "preview": "node build/index.js --preview",
-    "new": "plop",
-    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
-    "test:unit": "jest --clearCache && vue-cli-service test:unit",
-    "test:ci": "npm run lint && npm run test:unit"
-  },
-  "dependencies": {
-    "axios": "0.18.1",
-    "clipboard": "2.0.4",
-    "codemirror": "5.45.0",
-    "core-js": "3.6.5",
-    "driver.js": "0.9.5",
-    "dropzone": "5.5.1",
-    "echarts": "4.2.1",
-    "element-ui": "^2.15.12",
-    "file-saver": "2.0.1",
-    "fuse.js": "3.4.4",
-    "js-cookie": "2.2.0",
-    "jsonlint": "1.6.3",
-    "jszip": "3.2.1",
-    "moment": "^2.29.4",
-    "normalize.css": "7.0.0",
-    "nprogress": "0.2.0",
-    "path-to-regexp": "2.4.0",
-    "pinyin": "2.9.0",
-    "screenfull": "4.2.0",
-    "script-loader": "0.7.2",
-    "sortablejs": "1.8.4",
-    "tui-editor": "1.3.3",
-    "vue": "^2.6.10",
-    "vue-count-to": "1.0.13",
-    "vue-i18n": "7.3.2",
-    "vue-paystack": "^2.0.4",
-    "vue-router": "3.0.2",
-    "vue-splitpane": "1.0.4",
-    "vuedraggable": "2.20.0",
-    "vuex": "3.1.0",
-    "xlsx": "0.14.1"
-  },
-  "devDependencies": {
-    "@vue/cli-plugin-babel": "4.4.4",
-    "@vue/cli-plugin-eslint": "4.4.4",
-    "@vue/cli-plugin-unit-jest": "4.4.4",
-    "@vue/cli-service": "4.4.4",
-    "@vue/test-utils": "1.0.0-beta.29",
-    "autoprefixer": "9.5.1",
-    "babel-eslint": "10.1.0",
-    "babel-jest": "23.6.0",
-    "babel-plugin-dynamic-import-node": "2.3.3",
-    "chalk": "2.4.2",
-    "chokidar": "2.1.5",
-    "connect": "3.6.6",
-    "eslint": "6.7.2",
-    "eslint-plugin-vue": "6.2.2",
-    "html-webpack-plugin": "3.2.0",
-    "husky": "1.3.1",
-    "lint-staged": "8.1.5",
-    "mockjs": "1.0.1-beta3",
-    "plop": "2.3.0",
-    "runjs": "4.3.2",
-    "sass": "1.26.2",
-    "sass-loader": "8.0.2",
-    "script-ext-html-webpack-plugin": "2.1.3",
-    "serve-static": "1.13.2",
-    "svg-sprite-loader": "4.1.3",
-    "svgo": "1.2.0",
-    "vue-template-compiler": "2.6.10"
-  },
-  "browserslist": [
-    "> 1%",
-    "last 2 versions"
-  ],
-  "bugs": {
-    "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
-  },
-  "engines": {
-    "node": ">=8.9",
-    "npm": ">= 3.0.0"
-  },
-  "keywords": [
-    "vue",
-    "admin",
-    "dashboard",
-    "element-ui",
-    "boilerplate",
-    "admin-template",
-    "management-system"
-  ],
-  "license": "MIT",
-  "lint-staged": {
-    "src/**/*.{js,vue}": [
-      "eslint --fix",
-      "git add"
-    ]
-  },
-  "husky": {
-    "hooks": {
-      "pre-commit": "lint-staged"
-    }
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
-  }
-}
+{
+  "name": "vue-element-admin",
+  "version": "4.3.1",
+  "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
+  "author": "Pan <panfree23@gmail.com>",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "lint": "eslint --ext .js,.vue src",
+    "build:prod": "vue-cli-service build",
+    "build:dev": "vue-cli-service build --mode development",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "new": "plop",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
+    "test:ci": "npm run lint && npm run test:unit"
+  },
+  "dependencies": {
+    "axios": "0.18.1",
+    "clipboard": "2.0.4",
+    "codemirror": "5.45.0",
+    "core-js": "3.6.5",
+    "driver.js": "0.9.5",
+    "dropzone": "5.5.1",
+    "element-ui": "^2.15.12",
+    "file-saver": "2.0.1",
+    "fuse.js": "3.4.4",
+    "js-cookie": "2.2.0",
+    "jsonlint": "1.6.3",
+    "jszip": "3.2.1",
+    "moment": "^2.29.4",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "path-to-regexp": "2.4.0",
+    "pinyin": "2.9.0",
+    "screenfull": "4.2.0",
+    "script-loader": "0.7.2",
+    "sortablejs": "1.8.4",
+    "vue": "^2.6.10",
+    "vue-count-to": "1.0.13",
+    "vue-i18n": "7.3.2",
+    "vue-paystack": "^2.0.4",
+    "vue-router": "3.0.2",
+    "vue-splitpane": "1.0.4",
+    "vuedraggable": "2.20.0",
+    "vuex": "3.1.0",
+    "xlsx": "0.14.1"
+  },
+  "devDependencies": {
+    "@plugin-web-update-notification/webpack": "^1.6.4",
+    "@vue/cli-plugin-babel": "4.4.4",
+    "@vue/cli-plugin-eslint": "4.4.4",
+    "@vue/cli-plugin-unit-jest": "4.4.4",
+    "@vue/cli-service": "4.4.4",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "9.5.1",
+    "babel-eslint": "10.1.0",
+    "babel-jest": "23.6.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
+    "chalk": "2.4.2",
+    "chokidar": "2.1.5",
+    "connect": "3.6.6",
+    "echarts": "^5.4.3",
+    "eslint": "6.7.2",
+    "eslint-plugin-vue": "6.2.2",
+    "html-webpack-plugin": "3.2.0",
+    "husky": "1.3.1",
+    "lint-staged": "8.1.5",
+    "mockjs": "1.0.1-beta3",
+    "plop": "2.3.0",
+    "runjs": "4.3.2",
+    "sass": "1.26.2",
+    "sass-loader": "8.0.2",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "serve-static": "1.13.2",
+    "svg-sprite-loader": "4.1.3",
+    "svgo": "1.2.0",
+    "vue-template-compiler": "2.6.10"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ],
+  "bugs": {
+    "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
+  },
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "keywords": [
+    "vue",
+    "admin",
+    "dashboard",
+    "element-ui",
+    "boilerplate",
+    "admin-template",
+    "management-system"
+  ],
+  "license": "MIT",
+  "lint-staged": {
+    "src/**/*.{js,vue}": [
+      "eslint --fix",
+      "git add"
+    ]
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
+  }
+}

+ 19 - 15
public/index.html

@@ -1,15 +1,19 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-    <meta name="renderer" content="webkit">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-<!--    <link rel="icon" href="<%= BASE_URL %>favicon.ico">-->
-    <title><%= webpackConfig.name %></title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
-</html>
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="renderer" content="webkit">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+    <meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+
+    <!--    <link rel="icon" href="<%= BASE_URL %>favicon.ico">-->
+    <title><%= webpackConfig.name %></title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 98 - 13
src/App.vue

@@ -1,13 +1,98 @@
-<template>
-  <div id="app">
-    <router-view />
-  </div>
-</template>
-
-<script>
-import store from './store'
-
-export default {
-  name: 'App'
-}
-</script>
+<template>
+  <div id="app">
+    <router-view />
+    <el-dialog
+      v-if="dialogVisible"
+      :title="$t('notificationProps.title')"
+      :visible.sync="dialogVisible"
+      width="320px"
+      custom-class="message_refresh"
+      :close-on-click-modal="false"
+      top="0vh"
+    >
+      <span>{{ $t('notificationProps.description') }}</span>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">{{ $t('notificationProps.cancelButtonText') }}</el-button>
+        <el-button type="primary" @click="notificationRefresh">{{ $t('notificationProps.confirmButtonText') }}</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import store from './store'
+
+export default {
+  name: 'App',
+  data() {
+    return {
+      dialogVisible: false
+    }
+  },
+  mounted() {
+    this.init()
+  },
+  methods: {
+    init() {
+      const self = this
+      const language = store.state.app.language
+      document.body.addEventListener('plugin_web_update_notice', (e) => {
+        const { version, options } = e.detail
+        console.log(version, options)
+        self.dialogVisible = true
+        // if (language === 'en') {
+        //   self.$confirm('System update detected, please refresh the page?', '📢 System update', {
+        //     distinguishCancelAndClose: true,
+        //     closeOnClickModal: false,
+        //     customClass: 'message_refresh',
+        //     confirmButtonText: 'refresh',
+        //     cancelButtonText: 'dismiss'
+        //   })
+        //     .then(() => {
+        //       location.reload()
+        //     })
+        //     .catch(action => {
+        //       self.$message({
+        //         type: 'info',
+        //         message: action === 'cancel'
+        //           ? 'Abandon'
+        //           : 'Stay on the current page'
+        //       })
+        //     })
+        // } else {
+        //   self.$confirm('检测到系统更新,请刷新页面?', '📢 系统更新', {
+        //     distinguishCancelAndClose: true,
+        //     closeOnClickModal: false,
+        //     customClass: 'message_refresh',
+        //     confirmButtonText: '刷新',
+        //     cancelButtonText: '放弃'
+        //   })
+        //     .then(() => {
+        //       location.reload()
+        //     })
+        //     .catch(action => {
+        //       self.$message({
+        //         type: 'info',
+        //         message: action === 'cancel'
+        //           ? '放弃'
+        //           : '停留在当前页面'
+        //       })
+        //     })
+        // }
+      })
+    },
+    notificationRefresh() {
+      location.reload()
+      this.dialogVisible = false
+    }
+  }
+}
+</script>
+
+<style lang="scss" >
+ .message_refresh{
+   width: 320px;
+   top: 50%;
+   transform: translateY(-50%);
+ }
+</style>

+ 9 - 0
src/api/config.js

@@ -35,3 +35,12 @@ export function deleteAddress(data) {
     data
   })
 }
+
+export function getRegionList(query) {
+  return request({
+    url: '/v1/config/region-list',
+    method: 'get',
+    params: query
+  })
+}
+

+ 8 - 0
src/api/finance.js

@@ -72,4 +72,12 @@ export function fetchApplyRecharge(data) {
   })
 }
 
+export function editApplyRecharge(data) {
+  return request({
+    url: '/v1/finance/recharge-update',
+    method: 'post',
+    data
+  })
+}
+
 

+ 15 - 1
src/api/setting.js

@@ -14,4 +14,18 @@ export function getPageId(data) {
     method: 'get',
     data
   })
-}
+}
+
+export function getLanguages() {
+    return request({
+        url: '/v1/site/languages',
+        method: 'get'
+    })
+}
+
+export function getCountries() {
+    return request({
+        url: '/v1/site/countries',
+        method: 'get'
+    })
+}

+ 37 - 1
src/api/shop.js

@@ -39,7 +39,7 @@ export function downloadDecOrder(orderSn) {
 // 订单列表
 export function fetchOrderList(query) {
   return request({
-    url: '/v1/shop/order-list',
+    url: '/v1/shop/own-order',
     method: 'get',
     params: query
   })
@@ -107,3 +107,39 @@ export function deleteApproachOrder(data) {
     data
   })
 }
+
+// 复消商品列表
+export function fetchReconsumeProductList(query) {
+  return request({
+    url: '/v1/shop/reconsume',
+    method: 'get',
+    params: query
+  })
+}
+
+// 支付订单 复消
+export function createReconsumeOrder(data) {
+  return request({
+    url: '/v1/shop/reconsume-sure-order',
+    method: 'post',
+    data
+  })
+}
+
+// Paystack支付订单 复消
+export function createApproachReconsumeOrder(data) {
+  return request({
+    url: '/v1/shop/sure-approach-reconsume-order',
+    method: 'post',
+    data
+  })
+}
+
+// 删除订单中间表
+export function deleteApproachReconsumeOrder(data) {
+  return request({
+    url: '/v1/shop/delete-approach-reconsume-order',
+    method: 'post',
+    data
+  })
+}

+ 32 - 4
src/api/user.js

@@ -7,7 +7,7 @@ import request from '@/utils/request'
  * @returns {*}
  */
 export function login(data, pageId = '') {
-  let url = pageId ? '/v1/oauth/login?page_id='+pageId : '/v1/oauth/login'
+  const url = pageId ? '/v1/oauth/login?page_id=' + pageId : '/v1/oauth/login'
   return request({
     url,
     method: 'post',
@@ -21,7 +21,7 @@ export function login(data, pageId = '') {
  * @returns {*}
  */
 export function backendQuickLogin(params) {
-  let url = '/v1/oauth/login-by-backend'
+  const url = '/v1/oauth/login-by-backend'
   return request({
     url,
     method: 'post',
@@ -126,7 +126,7 @@ export function updatePaymentPassword(data) {
 export function fetchBrandAmbassador() {
   return request({
     url: '/v1/user/ba-dec',
-    method: 'get',
+    method: 'get'
   })
 }
 
@@ -151,11 +151,20 @@ export function fetchFullInfo(data) {
   })
 }
 
+export function fetchInspectNetwork(data) {
+  return request({
+    url: '/v1/user/inspect-network',
+    method: 'get',
+    params: data
+  })
+}
+
 // 用户升级查询
-export function fetchUpgrade() {
+export function fetchUpgrade(data) {
   return request({
     url: '/v1/user/upgrade',
     method: 'get',
+    params: data
   })
 }
 
@@ -212,3 +221,22 @@ export function createWelcomePack(data) {
     data
   })
 }
+
+// 订单列表
+export function fetchOrderList(query) {
+  return request({
+    url: '/v1/shop/member-order',
+    method: 'get',
+    params: query
+  })
+}
+
+// 下载订单PDF
+export function downloadOrder(orderSn) {
+  return request({
+    url: `/v1/shop/order-export/${orderSn}`,
+    method: 'get',
+    params: {}
+  })
+}
+

+ 9 - 3
src/components/Breadcrumb/index.vue

@@ -44,7 +44,8 @@ export default {
         matched = [{ path: '/dashboard/index', meta: { title: 'dashboard' }}].concat(matched)
       }
 
-      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
+      const levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
+      this.levelList = levelList.slice(-1)
     },
     isDashboard(route) {
       const name = route && route.name
@@ -76,11 +77,16 @@ export default {
   display: inline-block;
   font-size: 14px;
   line-height: 50px;
-  margin-left: 8px;
-
+  margin-left: 5px;
+  max-width: 50%;
   .no-redirect {
     color: #97a8be;
     cursor: text;
+    width:220px;
+    overflow:hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow:ellipsis;
   }
 }
 </style>

+ 155 - 155
src/components/Charts/Keyboard.vue

@@ -1,155 +1,155 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-
-      const xAxisData = []
-      const data = []
-      const data2 = []
-      for (let i = 0; i < 50; i++) {
-        xAxisData.push(i)
-        data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
-        data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
-      }
-      this.chart.setOption({
-        backgroundColor: '#08263a',
-        grid: {
-          left: '5%',
-          right: '5%'
-        },
-        xAxis: [{
-          show: false,
-          data: xAxisData
-        }, {
-          show: false,
-          data: xAxisData
-        }],
-        visualMap: {
-          show: false,
-          min: 0,
-          max: 50,
-          dimension: 0,
-          inRange: {
-            color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
-          }
-        },
-        yAxis: {
-          axisLine: {
-            show: false
-          },
-          axisLabel: {
-            textStyle: {
-              color: '#4a657a'
-            }
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: '#08263f'
-            }
-          },
-          axisTick: {
-            show: false
-          }
-        },
-        series: [{
-          name: 'back',
-          type: 'bar',
-          data: data2,
-          z: 1,
-          itemStyle: {
-            normal: {
-              opacity: 0.4,
-              barBorderRadius: 5,
-              shadowBlur: 3,
-              shadowColor: '#111'
-            }
-          }
-        }, {
-          name: 'Simulate Shadow',
-          type: 'line',
-          data,
-          z: 2,
-          showSymbol: false,
-          animationDelay: 0,
-          animationEasing: 'linear',
-          animationDuration: 1200,
-          lineStyle: {
-            normal: {
-              color: 'transparent'
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: '#08263a',
-              shadowBlur: 50,
-              shadowColor: '#000'
-            }
-          }
-        }, {
-          name: 'front',
-          type: 'bar',
-          data,
-          xAxisIndex: 1,
-          z: 3,
-          itemStyle: {
-            normal: {
-              barBorderRadius: 5
-            }
-          }
-        }],
-        animationEasing: 'elasticOut',
-        animationEasingUpdate: 'elasticOut',
-        animationDelay(idx) {
-          return idx * 20
-        },
-        animationDelayUpdate(idx) {
-          return idx * 20
-        }
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :id="id" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts/core'
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    id: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '200px'
+    },
+    height: {
+      type: String,
+      default: '200px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.initChart()
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(document.getElementById(this.id))
+
+      const xAxisData = []
+      const data = []
+      const data2 = []
+      for (let i = 0; i < 50; i++) {
+        xAxisData.push(i)
+        data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
+        data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
+      }
+      this.chart.setOption({
+        backgroundColor: '#08263a',
+        grid: {
+          left: '5%',
+          right: '5%'
+        },
+        xAxis: [{
+          show: false,
+          data: xAxisData
+        }, {
+          show: false,
+          data: xAxisData
+        }],
+        visualMap: {
+          show: false,
+          min: 0,
+          max: 50,
+          dimension: 0,
+          inRange: {
+            color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
+          }
+        },
+        yAxis: {
+          axisLine: {
+            show: false
+          },
+          axisLabel: {
+            textStyle: {
+              color: '#4a657a'
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#08263f'
+            }
+          },
+          axisTick: {
+            show: false
+          }
+        },
+        series: [{
+          name: 'back',
+          type: 'bar',
+          data: data2,
+          z: 1,
+          itemStyle: {
+            normal: {
+              opacity: 0.4,
+              barBorderRadius: 5,
+              shadowBlur: 3,
+              shadowColor: '#111'
+            }
+          }
+        }, {
+          name: 'Simulate Shadow',
+          type: 'line',
+          data,
+          z: 2,
+          showSymbol: false,
+          animationDelay: 0,
+          animationEasing: 'linear',
+          animationDuration: 1200,
+          lineStyle: {
+            normal: {
+              color: 'transparent'
+            }
+          },
+          areaStyle: {
+            normal: {
+              color: '#08263a',
+              shadowBlur: 50,
+              shadowColor: '#000'
+            }
+          }
+        }, {
+          name: 'front',
+          type: 'bar',
+          data,
+          xAxisIndex: 1,
+          z: 3,
+          itemStyle: {
+            normal: {
+              barBorderRadius: 5
+            }
+          }
+        }],
+        animationEasing: 'elasticOut',
+        animationEasingUpdate: 'elasticOut',
+        animationDelay(idx) {
+          return idx * 20
+        },
+        animationDelayUpdate(idx) {
+          return idx * 20
+        }
+      })
+    }
+  }
+}
+</script>

+ 227 - 227
src/components/Charts/LineMarker.vue

@@ -1,227 +1,227 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-
-      this.chart.setOption({
-        backgroundColor: '#394056',
-        title: {
-          top: 20,
-          text: 'Requests',
-          textStyle: {
-            fontWeight: 'normal',
-            fontSize: 16,
-            color: '#F1F1F3'
-          },
-          left: '1%'
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          }
-        },
-        legend: {
-          top: 20,
-          icon: 'rect',
-          itemWidth: 14,
-          itemHeight: 5,
-          itemGap: 13,
-          data: ['CMCC', 'CTCC', 'CUCC'],
-          right: '4%',
-          textStyle: {
-            fontSize: 12,
-            color: '#F1F1F3'
-          }
-        },
-        grid: {
-          top: 100,
-          left: '2%',
-          right: '2%',
-          bottom: '2%',
-          containLabel: true
-        },
-        xAxis: [{
-          type: 'category',
-          boundaryGap: false,
-          axisLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          },
-          data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
-        }],
-        yAxis: [{
-          type: 'value',
-          name: '(%)',
-          axisTick: {
-            show: false
-          },
-          axisLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          },
-          axisLabel: {
-            margin: 10,
-            textStyle: {
-              fontSize: 14
-            }
-          },
-          splitLine: {
-            lineStyle: {
-              color: '#57617B'
-            }
-          }
-        }],
-        series: [{
-          name: 'CMCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(137, 189, 27, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(137, 189, 27, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(137,189,27)',
-              borderColor: 'rgba(137,189,2,0.27)',
-              borderWidth: 12
-
-            }
-          },
-          data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
-        }, {
-          name: 'CTCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(0, 136, 212, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(0, 136, 212, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(0,136,212)',
-              borderColor: 'rgba(0,136,212,0.2)',
-              borderWidth: 12
-
-            }
-          },
-          data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
-        }, {
-          name: 'CUCC',
-          type: 'line',
-          smooth: true,
-          symbol: 'circle',
-          symbolSize: 5,
-          showSymbol: false,
-          lineStyle: {
-            normal: {
-              width: 1
-            }
-          },
-          areaStyle: {
-            normal: {
-              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                offset: 0,
-                color: 'rgba(219, 50, 51, 0.3)'
-              }, {
-                offset: 0.8,
-                color: 'rgba(219, 50, 51, 0)'
-              }], false),
-              shadowColor: 'rgba(0, 0, 0, 0.1)',
-              shadowBlur: 10
-            }
-          },
-          itemStyle: {
-            normal: {
-              color: 'rgb(219,50,51)',
-              borderColor: 'rgba(219,50,51,0.2)',
-              borderWidth: 12
-            }
-          },
-          data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
-        }]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :id="id" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts/core'
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    id: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '200px'
+    },
+    height: {
+      type: String,
+      default: '200px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.initChart()
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(document.getElementById(this.id))
+
+      this.chart.setOption({
+        backgroundColor: '#394056',
+        title: {
+          top: 20,
+          text: 'Requests',
+          textStyle: {
+            fontWeight: 'normal',
+            fontSize: 16,
+            color: '#F1F1F3'
+          },
+          left: '1%'
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          }
+        },
+        legend: {
+          top: 20,
+          icon: 'rect',
+          itemWidth: 14,
+          itemHeight: 5,
+          itemGap: 13,
+          data: ['CMCC', 'CTCC', 'CUCC'],
+          right: '4%',
+          textStyle: {
+            fontSize: 12,
+            color: '#F1F1F3'
+          }
+        },
+        grid: {
+          top: 100,
+          left: '2%',
+          right: '2%',
+          bottom: '2%',
+          containLabel: true
+        },
+        xAxis: [{
+          type: 'category',
+          boundaryGap: false,
+          axisLine: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          },
+          data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
+        }],
+        yAxis: [{
+          type: 'value',
+          name: '(%)',
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          },
+          axisLabel: {
+            margin: 10,
+            textStyle: {
+              fontSize: 14
+            }
+          },
+          splitLine: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          }
+        }],
+        series: [{
+          name: 'CMCC',
+          type: 'line',
+          smooth: true,
+          symbol: 'circle',
+          symbolSize: 5,
+          showSymbol: false,
+          lineStyle: {
+            normal: {
+              width: 1
+            }
+          },
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(137, 189, 27, 0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(137, 189, 27, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: 'rgb(137,189,27)',
+              borderColor: 'rgba(137,189,2,0.27)',
+              borderWidth: 12
+
+            }
+          },
+          data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
+        }, {
+          name: 'CTCC',
+          type: 'line',
+          smooth: true,
+          symbol: 'circle',
+          symbolSize: 5,
+          showSymbol: false,
+          lineStyle: {
+            normal: {
+              width: 1
+            }
+          },
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(0, 136, 212, 0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(0, 136, 212, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: 'rgb(0,136,212)',
+              borderColor: 'rgba(0,136,212,0.2)',
+              borderWidth: 12
+
+            }
+          },
+          data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
+        }, {
+          name: 'CUCC',
+          type: 'line',
+          smooth: true,
+          symbol: 'circle',
+          symbolSize: 5,
+          showSymbol: false,
+          lineStyle: {
+            normal: {
+              width: 1
+            }
+          },
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(219, 50, 51, 0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: 'rgb(219,50,51)',
+              borderColor: 'rgba(219,50,51,0.2)',
+              borderWidth: 12
+            }
+          },
+          data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
+        }]
+      })
+    }
+  }
+}
+</script>

+ 271 - 271
src/components/Charts/MixChart.vue

@@ -1,271 +1,271 @@
-<template>
-  <div :id="id" :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    id: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '200px'
-    },
-    height: {
-      type: String,
-      default: '200px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.initChart()
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(document.getElementById(this.id))
-      const xData = (function() {
-        const data = []
-        for (let i = 1; i < 13; i++) {
-          data.push(i + 'month')
-        }
-        return data
-      }())
-      this.chart.setOption({
-        backgroundColor: '#344b58',
-        title: {
-          text: 'statistics',
-          x: '20',
-          top: '20',
-          textStyle: {
-            color: '#fff',
-            fontSize: '22'
-          },
-          subtextStyle: {
-            color: '#90979c',
-            fontSize: '16'
-          }
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            textStyle: {
-              color: '#fff'
-            }
-          }
-        },
-        grid: {
-          left: '5%',
-          right: '5%',
-          borderWidth: 0,
-          top: 150,
-          bottom: 95,
-          textStyle: {
-            color: '#fff'
-          }
-        },
-        legend: {
-          x: '5%',
-          top: '10%',
-          textStyle: {
-            color: '#90979c'
-          },
-          data: ['female', 'male', 'average']
-        },
-        calculable: true,
-        xAxis: [{
-          type: 'category',
-          axisLine: {
-            lineStyle: {
-              color: '#90979c'
-            }
-          },
-          splitLine: {
-            show: false
-          },
-          axisTick: {
-            show: false
-          },
-          splitArea: {
-            show: false
-          },
-          axisLabel: {
-            interval: 0
-
-          },
-          data: xData
-        }],
-        yAxis: [{
-          type: 'value',
-          splitLine: {
-            show: false
-          },
-          axisLine: {
-            lineStyle: {
-              color: '#90979c'
-            }
-          },
-          axisTick: {
-            show: false
-          },
-          axisLabel: {
-            interval: 0
-          },
-          splitArea: {
-            show: false
-          }
-        }],
-        dataZoom: [{
-          show: true,
-          height: 30,
-          xAxisIndex: [
-            0
-          ],
-          bottom: 30,
-          start: 10,
-          end: 80,
-          handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
-          handleSize: '110%',
-          handleStyle: {
-            color: '#d3dee5'
-
-          },
-          textStyle: {
-            color: '#fff' },
-          borderColor: '#90979c'
-
-        }, {
-          type: 'inside',
-          show: true,
-          height: 15,
-          start: 1,
-          end: 35
-        }],
-        series: [{
-          name: 'female',
-          type: 'bar',
-          stack: 'total',
-          barMaxWidth: 35,
-          barGap: '10%',
-          itemStyle: {
-            normal: {
-              color: 'rgba(255,144,128,1)',
-              label: {
-                show: true,
-                textStyle: {
-                  color: '#fff'
-                },
-                position: 'insideTop',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            709,
-            1917,
-            2455,
-            2610,
-            1719,
-            1433,
-            1544,
-            3285,
-            5208,
-            3372,
-            2484,
-            4078
-          ]
-        },
-
-        {
-          name: 'male',
-          type: 'bar',
-          stack: 'total',
-          itemStyle: {
-            normal: {
-              color: 'rgba(0,191,183,1)',
-              barBorderRadius: 0,
-              label: {
-                show: true,
-                position: 'top',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            327,
-            1776,
-            507,
-            1200,
-            800,
-            482,
-            204,
-            1390,
-            1001,
-            951,
-            381,
-            220
-          ]
-        }, {
-          name: 'average',
-          type: 'line',
-          stack: 'total',
-          symbolSize: 10,
-          symbol: 'circle',
-          itemStyle: {
-            normal: {
-              color: 'rgba(252,230,48,1)',
-              barBorderRadius: 0,
-              label: {
-                show: true,
-                position: 'top',
-                formatter(p) {
-                  return p.value > 0 ? p.value : ''
-                }
-              }
-            }
-          },
-          data: [
-            1036,
-            3693,
-            2962,
-            3810,
-            2519,
-            1915,
-            1748,
-            4675,
-            6209,
-            4323,
-            2865,
-            4298
-          ]
-        }
-        ]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :id="id" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts/core'
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    id: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '200px'
+    },
+    height: {
+      type: String,
+      default: '200px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.initChart()
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(document.getElementById(this.id))
+      const xData = (function() {
+        const data = []
+        for (let i = 1; i < 13; i++) {
+          data.push(i + 'month')
+        }
+        return data
+      }())
+      this.chart.setOption({
+        backgroundColor: '#344b58',
+        title: {
+          text: 'statistics',
+          x: '20',
+          top: '20',
+          textStyle: {
+            color: '#fff',
+            fontSize: '22'
+          },
+          subtextStyle: {
+            color: '#90979c',
+            fontSize: '16'
+          }
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            textStyle: {
+              color: '#fff'
+            }
+          }
+        },
+        grid: {
+          left: '5%',
+          right: '5%',
+          borderWidth: 0,
+          top: 150,
+          bottom: 95,
+          textStyle: {
+            color: '#fff'
+          }
+        },
+        legend: {
+          x: '5%',
+          top: '10%',
+          textStyle: {
+            color: '#90979c'
+          },
+          data: ['female', 'male', 'average']
+        },
+        calculable: true,
+        xAxis: [{
+          type: 'category',
+          axisLine: {
+            lineStyle: {
+              color: '#90979c'
+            }
+          },
+          splitLine: {
+            show: false
+          },
+          axisTick: {
+            show: false
+          },
+          splitArea: {
+            show: false
+          },
+          axisLabel: {
+            interval: 0
+
+          },
+          data: xData
+        }],
+        yAxis: [{
+          type: 'value',
+          splitLine: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#90979c'
+            }
+          },
+          axisTick: {
+            show: false
+          },
+          axisLabel: {
+            interval: 0
+          },
+          splitArea: {
+            show: false
+          }
+        }],
+        dataZoom: [{
+          show: true,
+          height: 30,
+          xAxisIndex: [
+            0
+          ],
+          bottom: 30,
+          start: 10,
+          end: 80,
+          handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
+          handleSize: '110%',
+          handleStyle: {
+            color: '#d3dee5'
+
+          },
+          textStyle: {
+            color: '#fff' },
+          borderColor: '#90979c'
+
+        }, {
+          type: 'inside',
+          show: true,
+          height: 15,
+          start: 1,
+          end: 35
+        }],
+        series: [{
+          name: 'female',
+          type: 'bar',
+          stack: 'total',
+          barMaxWidth: 35,
+          barGap: '10%',
+          itemStyle: {
+            normal: {
+              color: 'rgba(255,144,128,1)',
+              label: {
+                show: true,
+                textStyle: {
+                  color: '#fff'
+                },
+                position: 'insideTop',
+                formatter(p) {
+                  return p.value > 0 ? p.value : ''
+                }
+              }
+            }
+          },
+          data: [
+            709,
+            1917,
+            2455,
+            2610,
+            1719,
+            1433,
+            1544,
+            3285,
+            5208,
+            3372,
+            2484,
+            4078
+          ]
+        },
+
+        {
+          name: 'male',
+          type: 'bar',
+          stack: 'total',
+          itemStyle: {
+            normal: {
+              color: 'rgba(0,191,183,1)',
+              barBorderRadius: 0,
+              label: {
+                show: true,
+                position: 'top',
+                formatter(p) {
+                  return p.value > 0 ? p.value : ''
+                }
+              }
+            }
+          },
+          data: [
+            327,
+            1776,
+            507,
+            1200,
+            800,
+            482,
+            204,
+            1390,
+            1001,
+            951,
+            381,
+            220
+          ]
+        }, {
+          name: 'average',
+          type: 'line',
+          stack: 'total',
+          symbolSize: 10,
+          symbol: 'circle',
+          itemStyle: {
+            normal: {
+              color: 'rgba(252,230,48,1)',
+              barBorderRadius: 0,
+              label: {
+                show: true,
+                position: 'top',
+                formatter(p) {
+                  return p.value > 0 ? p.value : ''
+                }
+              }
+            }
+          },
+          data: [
+            1036,
+            3693,
+            2962,
+            3810,
+            2519,
+            1915,
+            1748,
+            4675,
+            6209,
+            4323,
+            2865,
+            4298
+          ]
+        }
+        ]
+      })
+    }
+  }
+}
+</script>

+ 55 - 42
src/components/LangSelect/index.vue

@@ -1,42 +1,55 @@
-<template>
-  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
-    <div>
-      <svg-icon class-name="international-icon" icon-class="language" />
-    </div>
-    <el-dropdown-menu slot="dropdown">
-      <el-dropdown-item :disabled="language==='zh'" command="zh">
-        中文
-      </el-dropdown-item>
-      <el-dropdown-item :disabled="language==='en'" command="en">
-        English
-      </el-dropdown-item>
-<!--      <el-dropdown-item :disabled="language==='es'" command="es">-->
-<!--        Español-->
-<!--      </el-dropdown-item>-->
-<!--      <el-dropdown-item :disabled="language==='ja'" command="ja">-->
-<!--        日本語-->
-<!--      </el-dropdown-item>-->
-    </el-dropdown-menu>
-  </el-dropdown>
-</template>
-
-<script>
-export default {
-  computed: {
-    language() {
-      return this.$store.getters.language
-    }
-  },
-  methods: {
-    handleSetLanguage(lang) {
-      this.$i18n.locale = lang
-			// 调用setLanguage方法,设置语言,存储到cookie
-      this.$store.dispatch('app/setLanguage', lang)
-      this.$message({
-        message: this.$t('common.switchLanguageHints'),
-        type: 'success'
-      })
-    }
-  }
-}
-</script>
+<template>
+  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
+    <div>
+      <svg-icon class-name="international-icon" icon-class="language" />
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item v-for="(item,index) in languageList" :key="index" :disabled="language===item.KEY" :command="item.KEY">
+          {{ item.NAME }}
+      </el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+import { getLanguages } from '@/api/setting'
+
+export default {
+  data(){
+      return {
+      }
+  },
+  computed: {
+    language() {
+      return this.$store.getters.language
+    },
+    languageList() {
+      return this.$store.getters.languageList
+    },
+  },
+  mounted() {
+      this.getLanguageList()
+  },
+  methods: {
+    getLanguageList(){
+        getLanguages().then(response => {
+            let obj = response
+            let list = []
+            Object.keys(obj).forEach(function(key) {
+                list.push(obj[key])
+            });
+            // this.languageList = list
+            this.$store.dispatch('app/setLanguageList', list)
+        })
+    },
+    handleSetLanguage(lang) {
+      this.$i18n.locale = lang
+      this.$store.dispatch('app/setLanguage', lang)
+      this.$message({
+        message: this.$t('common.switchLanguageHints'),
+        type: 'success'
+      })
+    }
+  }
+}
+</script>

+ 0 - 31
src/components/MarkdownEditor/default-options.js

@@ -1,31 +0,0 @@
-// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
-export default {
-  minHeight: '200px',
-  previewStyle: 'vertical',
-  useCommandShortcut: true,
-  useDefaultHTMLSanitizer: true,
-  usageStatistics: false,
-  hideModeSwitch: false,
-  toolbarItems: [
-    'heading',
-    'bold',
-    'italic',
-    'strike',
-    'divider',
-    'hr',
-    'quote',
-    'divider',
-    'ul',
-    'ol',
-    'task',
-    'indent',
-    'outdent',
-    'divider',
-    'table',
-    'image',
-    'link',
-    'divider',
-    'code',
-    'codeblock'
-  ]
-}

+ 0 - 118
src/components/MarkdownEditor/index.vue

@@ -1,118 +0,0 @@
-<template>
-  <div :id="id" />
-</template>
-
-<script>
-// deps for editor
-import 'codemirror/lib/codemirror.css' // codemirror
-import 'tui-editor/dist/tui-editor.css' // editor ui
-import 'tui-editor/dist/tui-editor-contents.css' // editor content
-
-import Editor from 'tui-editor'
-import defaultOptions from './default-options'
-
-export default {
-  name: 'MarkdownEditor',
-  props: {
-    value: {
-      type: String,
-      default: ''
-    },
-    id: {
-      type: String,
-      required: false,
-      default() {
-        return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
-      }
-    },
-    options: {
-      type: Object,
-      default() {
-        return defaultOptions
-      }
-    },
-    mode: {
-      type: String,
-      default: 'markdown'
-    },
-    height: {
-      type: String,
-      required: false,
-      default: '300px'
-    },
-    language: {
-      type: String,
-      required: false,
-      default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
-    }
-  },
-  data() {
-    return {
-      editor: null
-    }
-  },
-  computed: {
-    editorOptions() {
-      const options = Object.assign({}, defaultOptions, this.options)
-      options.initialEditType = this.mode
-      options.height = this.height
-      options.language = this.language
-      return options
-    }
-  },
-  watch: {
-    value(newValue, preValue) {
-      if (newValue !== preValue && newValue !== this.editor.getValue()) {
-        this.editor.setValue(newValue)
-      }
-    },
-    language(val) {
-      this.destroyEditor()
-      this.initEditor()
-    },
-    height(newValue) {
-      this.editor.height(newValue)
-    },
-    mode(newValue) {
-      this.editor.changeMode(newValue)
-    }
-  },
-  mounted() {
-    this.initEditor()
-  },
-  destroyed() {
-    this.destroyEditor()
-  },
-  methods: {
-    initEditor() {
-      this.editor = new Editor({
-        el: document.getElementById(this.id),
-        ...this.editorOptions
-      })
-      if (this.value) {
-        this.editor.setValue(this.value)
-      }
-      this.editor.on('change', () => {
-        this.$emit('input', this.editor.getValue())
-      })
-    },
-    destroyEditor() {
-      if (!this.editor) return
-      this.editor.off('change')
-      this.editor.remove()
-    },
-    setValue(value) {
-      this.editor.setValue(value)
-    },
-    getValue() {
-      return this.editor.getValue()
-    },
-    setHtml(value) {
-      this.editor.setHtml(value)
-    },
-    getHtml() {
-      return this.editor.getHtml()
-    }
-  }
-}
-</script>

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

@@ -36,7 +36,7 @@ export default {
     pageSizes: {
       type: Array,
       default() {
-        return [10, 20, 30, 50]
+        return [5, 10, 20, 30, 50]
       }
     },
     layout: {

+ 487 - 0
src/components/TreeChart/index.vue

@@ -0,0 +1,487 @@
+<template>
+  <div id="main" class="echarts-container" />
+</template>
+<script>
+import { TreeChart } from "echarts/charts";
+import { TooltipComponent } from "echarts/components";
+import * as echarts from "echarts/core";
+import { CanvasRenderer } from "echarts/renderers";
+
+echarts.use([TooltipComponent, TreeChart, CanvasRenderer]);
+// let this.myChart;
+let option;
+
+var treeNodePadding = 50; //节点间最小间隔
+
+var treeTopPadding = 120; //tree距顶端的距离
+
+var rightNode; //最右侧节点,用于计算偏移量
+export default {
+  name: "TreeChart",
+  data() {
+    return {
+      myChart: null,
+      centerLoca: [],
+      fontSize: 6,
+      chartWidth: 0,
+      chartHeight: 0,
+      center: [this.chartWidth, "50%"],
+    };
+  },
+  props: {
+    treeData: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+    topDeep: Number,
+    type: String,
+    clickNodeList: Array,
+  },
+  watch: {
+    clickNodeList: {
+      handler(newValue, old) {
+        if (newValue) {
+          this.init();
+        }
+      },
+    },
+    treeData: {
+      handler(newValue, old) {
+        console.log(newValue);
+        if (newValue) {
+          this.init();
+        }
+      },
+    },
+    chartWidth: {
+      handler(newValue, old) {
+        console.log(newValue);
+        if (newValue) {
+          this.init();
+        }
+      },
+    },
+  },
+  mounted() {
+    this.init();
+    // 监听树图节点的点击事件
+    this.myChart.on("click", (e) => {
+      console.log("e:", e);
+      this.$emit("clickNode", e);
+    });
+  },
+  methods: {
+    init() {
+      const that = this;
+      // console.log('$el:', this.$el)
+      that.myChart = echarts.init(this.$el);
+      that.myChart.clear();
+      option = {
+        tooltip: {
+          // 提示框浮层设置
+          trigger: "item",
+          triggerOn: "mousemove", // 提示框触发条件
+          enterable: true, // 鼠标是否可进入提示框浮层中,默认false
+          confine: true, // 是否将tooltip框限制在图表的区域内
+          padding: [5, 10],
+          formatter: function (params) {
+            // 提示框浮层内容格式器,支持字符串模板和回调函数两种形式
+            const relationStr =
+              "<div style='display: flex;flex-direction: column;'>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.numberLayers") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              (Number(params.data.TOP_NETWORK_DEEP) - Number(that.topDeep)) +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.memberCode") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.USER_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.name") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.REAL_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.level") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.DEC_LV_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.highest") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.EMP_LV_NAME +
+              "," +
+              params.data.CROWN_LV_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.periodNumber") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.PERIOD_AT +
+              "</span>" +
+              "</div>" +
+              "</div>";
+            const networkStr =
+              "<div style='display: flex;flex-direction: column;'>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.memberCode") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.USER_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.name") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.REAL_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.level") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.DEC_LV_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.highest") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.EMP_LV_NAME +
+              "</span>" +
+              "</div>" +
+              "<div>" +
+              '<span style="color: #606266;">' +
+              that.$t("atlas.periodNumber") +
+              ": " +
+              "</span>" +
+              '<span style="color: #000000;">' +
+              params.data.PERIOD_AT +
+              "</span>" +
+              "</div>" +
+              "</div>";
+
+            return that.type === "placement" ? relationStr : networkStr;
+          },
+          // valueFormatter: function (value) { // tooltip 中数值显示部分的格式化回调函数
+          //   return '$' + value.toFixed(2)
+          // },
+          backgroundColor: "rgba(250,250,250,0.99)", // 提示框浮层的背景颜色
+          borderColor: "#1890FF", // 提示框浮层的边框颜色
+          borderWidth: 0.5, // 提示框浮层的边框宽
+          borderRadius: 8, // 提示框浮层圆角
+          textStyle: {
+            // 提示框浮层的文本样式
+            color: "#333", // 文字颜色
+            // fontWeight: 400, // 字体粗细
+            // fontSize: that.fontSize, // 字体大小
+            // lineHeight: 20, // 行高
+            // width: 60, // 文本显示宽度
+            // 文字超出宽度是否截断或者换行;只有配置width时有效
+            overflow: "breakAll", // truncate截断,并在末尾显示ellipsis配置的文本,默认为...;break换行;breakAll换行,并强制单词内换行
+            ellipsis: "...",
+          },
+          extraCssText:
+            "min-height:100px;box-shadow: 0 0 9px rgba(0, 0, 0, 0.3);text-align: left;", // 额外添加到浮层的css样式
+          axisPointer: {
+            type: "shadow",
+            shadowStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: "rgba(255, 255, 255, 0)" },
+                { offset: 1, color: "rgba(37, 107, 230, 0.18)" },
+              ]),
+            },
+          },
+        },
+        series: [
+          {
+            width: that.chartWidth + "px",
+            height: "100%",
+            type: "tree",
+            data: [this.treeData],
+            name: "树图",
+            top: "1%", // 组件离容器上侧的距离,像素值20,或相对容器的百分比
+            left: "1%", // 组件离容器左侧的距离
+            bottom: "1%", // 组件离容器下侧的距离
+            right: "1%", // 组件离容器右侧的距离
+            layout: "orthogonal", // 树图的布局,正交orthogonal和径向radial两种
+            orient: "TB", // 树图中正交布局的方向,'LR','RL','TB','BT',只有布局是正交时才生效
+            edgeShape: "polyline", // 树图边的形状,有曲线curve和折线polyline两种,只有正交布局下生效
+            // edgeForkPosition:"10%",
+            roam: true, // 是否开启鼠标缩放或平移,默认false
+            zoom: 0.5,
+            scaleLimit: {
+              min: 0.5,
+              max: 10,
+            },
+            center: that.center || null,
+            // center: [5, 5],
+            initialTreeDepth: -1, // 树图初始的展开层级(深度),根节点是0,不设置时全部展开
+            // symbol: 'emptyCircle', // 标记的图形,默认是emptyCircle;circle,rect,roundRect,triangle,diamond,pin,arrow,none
+            symbol: function (value, params) {
+              // params.data节点的所有数据
+              if (params.data.leaf == true) {
+                return "emptyCircle";
+              } else if (params.data.leaf == false) {
+                return "circle";
+              }
+            },
+            // symbolRotate: 270, // 配合arrow图形使用效果较好
+            symbolSize: 10, // 大于0时是圆圈,等于0时不展示,标记的大小
+            itemStyle: {
+              // 树图中每个节点的样式
+              color: "#1890FF", // 节点未展开时的填充色
+              borderColor: "rgba(255, 144, 0, 1)", // 图形的描边颜色
+              borderWidth: 0.5, // 描边线宽,为0时无描边
+              borderType: "dotted", // 描边类型
+              borderCap: "square", // 指定线段末端的绘制方式butt方形结束,round圆形结束,square
+              shadowColor: "rgba(0,121,221,0.3)", // 阴影颜色
+              shadowBlur: 12, // 图形阴影的模糊大小
+              opacity: 1, // 图形透明度
+            },
+            label: {
+              // 每个节点对应的文本标签样式
+              show: true, // 是否显示标签
+              // distance: 22, // 文本距离图形元素的距离
+              position: "bottom", // 标签位置
+              verticalAlign: "middle", // 文字垂直对齐方式,默认自动,top,middle,bottom
+              align: "center", // 文字水平对齐方式,默认自动,left,right,center
+              fontSize: that.fontSize, // 字体大小
+              color: "#333", // 字体颜色
+              backgroundColor: "#F0F5FA", // 文字块的背景颜色
+              borderColor: "#1890FF", // 文字块边框颜色
+              borderWidth: 0.5, // 文字块边框宽度
+              borderType: "solid", // 文字块边框描边类型 solid dashed dotted
+              borderRadius: 6, // 文字块的圆角
+              padding: [5, 6], // 文字块内边距
+              shadowColor: "rgba(0,121,221,0.6)", // 文字块的背景阴影颜色
+              shadowBlur: 6, // 文字块的背景阴影长度
+              width: 80,
+              // 文字超出宽度是否截断或者换行;只有配置width时有效
+              overflow: "truncate", // truncate截断,并在末尾显示ellipsis配置的文本,默认为...;break换行;breakAll换行,并强制单词内换行
+              ellipsis: "...",
+              formatter: function (params) {
+                return (
+                  params.data.USER_NAME + "\n" + "\n" + params.data.REAL_NAME
+                );
+                // return params.data.REAL_NAME
+              },
+            },
+
+            lineStyle: {
+              // 树图边的样式
+              color: "rgba(0,0,0,.35)", // 树图边的颜色
+              width: 1, // 树图边的宽度
+              curveness: 0.5, // 树图边的曲度
+              shadowColor: "rgba(0, 0, 0, 0.5)", // 阴影颜色
+              shadowBlur: 10, // 图形阴影的模糊大小
+            },
+            emphasis: {
+              // 树图中图形和标签高亮的样式
+              disabled: false, // 是否关闭高亮状态,默认false
+              // 在高亮图形时,是否淡出其它数据的图形已达到聚焦的效果
+              focus: "relative", // none不淡出其他图形(默认);self只聚焦当前高亮的数据图形;series聚焦当前高亮的数据所在系列的所有图形;ancestor聚焦所有祖先节点;descendant聚焦所有子孙节点;relative聚焦所有子孙和祖先节点
+              blurScope: "coordinateSystem", // 开启focus时,配置淡出的范围,coordinateSystem淡出范围为坐标系(默认);series淡出范围为系列;global淡出范围为全局
+              itemStyle: {
+                // 该节点的样式
+                color: "#1890FF", // 图形的颜色
+                // borderColor: 'rgba(255, 144, 0, 1)', // 图形的描边颜色
+                // borderWidth: 1, // 描边线宽,为0时无描边
+                borderType: "solid", // 描边类型 solid dashed dotted
+                borderCap: "square", // 指定线段末端的绘制方式butt方形结束,round圆形结束,square
+                shadowColor: "rgba(0,121,221,0.3)", // 阴影颜色
+                shadowBlur: 12, // 图形阴影的模糊大小
+                opacity: 1, // 图形透明度
+              },
+              lineStyle: {
+                // 树图边的样式
+                color: "rgba(0,0,0,.45)", // 树图边的颜色
+                width: 2, // 树图边的宽度
+                curveness: 0.5, // 树图边的曲度
+                shadowColor: "rgba(0, 0, 0, 0.5)", // 阴影颜色
+                shadowBlur: 6, // 图形阴影的模糊大小
+              },
+              label: {
+                // 高亮标签的文本样式
+                color: "#333",
+                fontWeight: 600,
+              },
+            },
+            blur: {
+              // 淡出状态的相关配置,开启emphasis.focus后有效
+              itemStyle: {}, // 节点的样式
+              lineStyle: {}, // 树图边的样式
+              label: {}, // 淡出标签的文本样式
+            },
+            leaves: {
+              // 叶子节点的特殊配置
+              label: {
+                // 叶子节点的文本标签样式
+                // distance: 22,
+                // color: '#1890FF',
+                position: "bottom",
+                verticalAlign: "middle",
+                align: "center",
+              },
+              itemStyle: {}, // 叶子节点的样式
+              emphasis: {}, // 叶子节点高亮状态的配置
+              blur: {}, // 叶子节点淡出状态的配置
+              select: {}, // 叶子节点选中状态的配置
+            },
+            animation: true, // 是否开启动画
+            expandAndCollapse: true, // 子树折叠和展开的交互,默认打开
+            animationDuration: 500, // 初始动画的时长
+            animationEasing: "linear", // 初始动画的缓动效果
+            animationDelay: 0, // 初始动画的延迟
+            animationDurationUpdate: 500, // 数据更新动画的时长
+            animationEasingUpdate: "cubicInOut", // 数据更新动画的缓动效果
+            animationDelayUpdate: 0, // 数据更新动画的延迟
+          },
+        ],
+      };
+
+      option && that.myChart.setOption(option, true);
+      that.resize();
+
+      // that.adjustTreeView();
+      that.myChart.getZr().off("mousewheel");
+      that.myChart.getZr().on("mousewheel", (param) => {
+        let currentOption = that.myChart.getOption();
+        // console.log(currentOption);
+        if (currentOption.series[0]) {
+          let zoom = currentOption.series[0].zoom;
+          // that.fontSize = 10 * zoom
+          currentOption.textStyle.fontSize = 10 * zoom;
+          currentOption.series[0].label.fontSize = 8 * zoom;
+          currentOption.series[0].label.width = 110 * zoom;
+          currentOption.series[0].label.distance = 18 * zoom;
+          currentOption.series[0].leaves.distance = 18 * zoom;
+          option && that.myChart.setOption(currentOption);
+        }
+      });
+    },
+
+    resize() {
+      let elesArr = Array.from(
+        new Set(this.myChart._chartsViews[0]._data._graphicEls)
+      );
+      console.log(elesArr.length)
+      let dep = this.myChart._chartsViews[0]._data.tree.root.height; //获取树高
+      console.log(dep);
+      let layer_height = 90; //层级之间的高度
+      let currentHeight = layer_height * (dep + 1) || layer_height;
+      let newHeight = Math.max(currentHeight, layer_height);
+      this.chartHeight = newHeight + "px";
+      let layer_width = 90; // 兄弟节点之间的距离
+      let currentWidth = layer_width * (elesArr.length - 1) || layer_width;
+      let newWidth = Math.max(currentWidth, layer_width);
+      console.log(newWidth);
+      if (newWidth < 200) {
+        this.center[0] = '-70%';
+        this.center[1] = (dep * 2) + '0%';
+
+      }else if (newWidth > 200 && newWidth < 500) {
+        this.center[0] = '-56%';
+        this.center[1] = (dep * 1.5) + '0%';
+
+      }else if (newWidth > 500 && newWidth < 1000) {
+        this.center[0] = '-30%';
+        this.center[1] = (dep) + '0%';
+
+      } else if (newWidth > 1000){
+        this.center[0] = elesArr.length > 60 ? newWidth * 1.5 : newWidth * 1.2;
+        this.center[1] = (dep ) + '0%';
+      }
+      this.chartWidth = newWidth;
+
+      window.addEventListener("resize", () => {
+        this.myChart.resize();
+      });
+    },
+
+    doGlobalTreeChart(ec, data) {
+      // this.myChart.setOption(getGlobalTreeOption());
+      //生成图表后做调整
+      this.adjustTreeView();
+    },
+
+    //调整tree显示
+    adjustTreeView() {
+      var zr = this.myChart.getZr();
+      var domWidth = zr.painter.getWidth();
+      var treeWidth = this.getTreeWidth(zr);
+      if (treeWidth <= domWidth) return;
+    },
+
+    //计算最左边节点和最右边节点(symbol为image或icon)的间隔即为树图宽度
+
+    getTreeWidth(zr) {
+      var nodes = zr.storage._roots;
+      console.log(nodes);
+      let max = 0;
+      let min = 0;
+      for (var i = 0; i < nodes.length; i++) {
+        if (nodes[i].type == "image" || nodes[i].type == "icon") {
+          var nodeX = nodes[i].style.x;
+
+          if (nodeX > max) {
+            max = nodeX;
+
+            rightNode = nodes[i];
+
+            continue;
+          }
+
+          if (nodeX < min) {
+            min = nodeX;
+          }
+        }
+      }
+
+      return max - min;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.echarts-container {
+  width: 100%;
+  height: calc(100vh - 105px);
+}
+</style>
+

+ 571 - 509
src/lang/en.js

@@ -1,509 +1,571 @@
-export default {
-  route: {
-    dashboard: 'Dashboard',
-    shop: 'Mall management',
-    indexShop: 'Products list',
-    shopReconsume: 'Reconsume List',
-    memberManagement: 'Member management',
-    personalInfo: 'Personal Info',
-    documentation: 'Documentation',
-    guide: 'Guide',
-    permission: 'Permission',
-    pagePermission: 'Page Permission',
-    rolePermission: 'Role Permission',
-    directivePermission: 'Directive Permission',
-    icons: 'Icons',
-    components: 'Components',
-    tinymce: 'Tinymce',
-    markdown: 'Markdown',
-    jsonEditor: 'JSON Editor',
-    dndList: 'Dnd List',
-    splitPane: 'SplitPane',
-    avatarUpload: 'Avatar Upload',
-    dropzone: 'Dropzone',
-    sticky: 'Sticky',
-    countTo: 'Count To',
-    componentMixin: 'Mixin',
-    backToTop: 'Back To Top',
-    dragDialog: 'Drag Dialog',
-    dragSelect: 'Drag Select',
-    dragKanban: 'Drag Kanban',
-    charts: 'Charts',
-    keyboardChart: 'Keyboard Chart',
-    lineChart: 'Line Chart',
-    mixChart: 'Mix Chart',
-    example: 'Example',
-    nested: 'Nested Routes',
-    menu1: 'Menu 1',
-    'menu1-1': 'Menu 1-1',
-    'menu1-2': 'Menu 1-2',
-    'menu1-2-1': 'Menu 1-2-1',
-    'menu1-2-2': 'Menu 1-2-2',
-    'menu1-3': 'Menu 1-3',
-    menu2: 'Menu 2',
-    Table: 'Table',
-    dynamicTable: 'Dynamic Table',
-    dragTable: 'Drag Table',
-    inlineEditTable: 'Inline Edit',
-    complexTable: 'Complex Table',
-    tab: 'Tab',
-    form: 'Form',
-    createArticle: 'Create Article',
-    editArticle: 'Edit Article',
-    articleList: 'Article List',
-    errorPages: 'Error Pages',
-    page401: '401',
-    page404: '404',
-    errorLog: 'Error Log',
-    excel: 'Excel',
-    exportExcel: 'Export Excel',
-    selectExcel: 'Export Selected',
-    mergeHeader: 'Merge Header',
-    uploadExcel: 'Upload Excel',
-    zip: 'Zip',
-    pdf: 'PDF',
-    exportZip: 'Export Zip',
-    theme: 'Theme',
-    clipboardDemo: 'Clipboard',
-    i18n: 'I18n',
-    externalLink: 'External Link',
-    profile: 'Profile'
-  },
-  navbar: {
-    dashboard: 'Dashboard',
-    shippingAddress: 'Shipping Address',
-    logOut: 'Log Out',
-    profile: 'Profile',
-    theme: 'Theme',
-    size: 'Global Size',
-    visitPreviousVersion: 'Visit Previous Version',
-  },
-  menu: {
-    // 一级菜单
-    dashboard: 'Dashboard',
-    shoppingMall: 'Shopping Mall',
-    memberManagement: 'Member Management',
-    networkChart: 'Network Chart',
-    bonusManagement: 'Bonus Management',
-    articleManagement: 'Article Management',
-    setting: 'Setting',
-    // 二级菜单/接口-dashboard
-    monthBonus: 'Month Bonus',
-    // 二级菜单/接口-shoppingMall
-    standardProducts: 'Standard Products',
-    carFundProducts: 'Car Fund Products',
-    villaFundProducts: 'Villa Fund Products',
-    welcomePack: 'Welcome Pack',
-    welcomePackList: 'Welcome Pack Listing',
-    memberUpgrade: 'Upgrade Management',
-    orderList: 'Order List',
-    brandAmbassador: 'Brand Ambassador',
-    BAOrderList: 'Brand Ambassador Order',
-    // 二级菜单/接口-memberManagement
-    personalInfo: 'Personal Info',
-    resetPassword: 'Reset Password',
-    // 二级菜单/接口-networkChart
-    placementNetwork: 'Placement Network',
-    sponsorNetwork: 'Sponsor Network',
-    brandAmbassadorList: 'Brand Ambassador List',
-    // 二级菜单/接口-bonusManagement
-    myAccount: 'My Account',
-    myBonus: 'My Bonus',
-    teamInquiry: 'Team Inquiry',
-    historicalCumulativeBonus: 'Historical Cumulative Bonus',
-    withdrawalDetails: 'Withdrawal Details',
-    applyWithdraw: 'Apply For Withdraw',
-    rechargeDetails: 'Recharge Details',
-    applyRecharge: 'Apply For Recharge',
-    transferDetails: 'Transfer Details',
-    applyTransfer: 'Apply For Transfer',
-    // 二级菜单/接口-articleManagement
-    systemNotification: 'System Notification',
-    // 二级菜单/接口-setting
-    shippingAddress: 'Shipping Address',
-  },
-  login: {
-    title: 'Welcome',
-    logIn: 'Login',
-    username: 'Username',
-    password: 'Password',
-    any: 'any',
-    thirdparty: 'Or connect with',
-    thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !',
-    verifyCode: 'Verification Code'
-  },
-  documentation: {
-    documentation: 'Documentation',
-    github: 'Github Repository'
-  },
-  permission: {
-    addRole: 'New Role',
-    editPermission: 'Edit',
-    roles: 'Your roles',
-    switchRoles: 'Switch roles',
-    tips: 'In some cases, using v-permission will have no effect. For example: Element-UI  el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.',
-    delete: 'Delete',
-    confirm: 'Confirm',
-    cancel: 'Cancel'
-  },
-  guide: {
-    description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',
-    button: 'Show Guide'
-  },
-  components: {
-    documentation: 'Documentation',
-    tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.',
-    dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
-    stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
-    backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
-    backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally',
-    imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.'
-  },
-  table: {
-    dynamicTips1: 'Fixed header, sorted by header order',
-    dynamicTips2: 'Not fixed header, sorted by click order',
-    dragTips1: 'The default order',
-    dragTips2: 'The after dragging order',
-    title: 'Title',
-    importance: 'Imp',
-    type: 'Type',
-    remark: 'Remark',
-    search: 'Search',
-    add: 'Add',
-    export: 'Export',
-    reviewer: 'reviewer',
-    id: 'ID',
-    date: 'Date',
-    author: 'Author',
-    readings: 'Readings',
-    status: 'Status',
-    actions: 'Actions',
-    edit: 'Edit',
-    publish: 'Publish',
-    draft: 'Draft',
-    delete: 'Delete',
-    cancel: 'Cancel',
-    confirm: 'Confirm'
-  },
-  example: {
-    warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details'
-  },
-  errorLog: {
-    tips: 'Please click the bug icon in the upper right corner',
-    description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.',
-    documentation: 'Document introduction'
-  },
-  excel: {
-    export: 'Export',
-    selectedExport: 'Export Selected Items',
-    placeholder: 'Please enter the file name (default excel-list)'
-  },
-  zip: {
-    export: 'Export',
-    placeholder: 'Please enter the file name (default file)'
-  },
-  pdf: {
-    tips: 'Here we use window.print() to implement the feature of downloading PDF.'
-  },
-  theme: {
-    change: 'Change Theme',
-    documentation: 'Theme documentation',
-    tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.'
-  },
-  tagsView: {
-    refresh: 'Refresh',
-    close: 'Close',
-    closeOthers: 'Close Others',
-    closeAll: 'Close All'
-  },
-  settings: {
-    title: 'Page style setting',
-    theme: 'Theme Color',
-    tagsView: 'Open Tags-View',
-    fixedHeader: 'Fixed Header',
-    sidebarLogo: 'Sidebar Logo'
-  },
-  empLevels: {
-    // 级别配置
-    '67BE1C6C21F81B32E055736AECE8644D':  'No Rank',
-    'E121497617216708615': '1-Star Director',
-    '67BE5FE7857C216AE055736AECE8644D': '2-Star Director',
-    'E121497617216708616': '3-Star Director',
-    '67BE6A4D03C52288E055736AECE8644D': '4-Star Director',
-    '67BE6EA2070D22EBE055736AECE8644D': '5-Star Director',
-    '67BE742A336F2370E055736AECE8644D': '6-Star Director',
-    '67BE805032C22492E055736AECE8644D': '7-Star Director'
-  },
-  crownLevels: {
-    // 级别配置
-    'DCBEDD8E0EAD3DF59D81CCC0C2ACAEFF': '0-Star Crown',
-    'E0B75B89C94F35EF8EE0054FA34B759C': '1-Star Crown',
-    '7FEBE5DE95D530578915F4072E7CD842': '2-Star Crown',
-    '391691E01CD5373F8D23F01FAD750222': '3-Star Crown',
-    '8ACAEA736F5331B79283C895F36084E5': '4-Star Crown',
-    'CE46B39D07633217AA5711438649D1D6': '5-Star Crown',
-    '24396B85E74A3005947F1F90EBA5F5CF': '6-Star Crown',
-    '8C253968EB6F3F3FA5BE84F63136FFFA': '7-Star Crown',
-  },
-  decLvs: {
-    // 等级配置
-    '67ABCB8C1F7D5519E055736AECE8644D': 'Elite',
-    '67ABCCE20A9F5553E055736AECE8644D': 'Pro',
-    '67ABCE0ECE705575E055736AECE8644D': 'VIP'
-  },
-  dashboard: {
-    highestDirector: 'Highest Director',
-    highestCrown: 'Highest Crown',
-    memberLevel: 'Member Level',
-    payCycle: 'Current Pay Cycle',
-    remainBv: 'Remain BV',
-    activeDeadline: 'Active Deadline Date',
-    more: 'more',
-    articleNotification: 'System Notification'
-  },
-  currency: {
-    unit: 'Naira',
-    sign: '₦',
-    naira: 'NGN',
-  },
-
-  common: {
-    save: 'Save',
-    modify: 'Modify',
-    submit: 'Submit',
-    delete: 'Delete',
-    edit: 'Edit',
-    action: 'Action',
-    yes: 'YES',
-    no: 'NO',
-    view: 'View',
-    select: 'Select',
-    reset: 'Reset',
-    startDate: 'Start Date',
-    endDate: 'End Date',
-    deleteTips: 'Are you sure you want to delete the selected data?',
-    hint: 'Hint',
-    cancel: 'Cancel',
-    confirm: 'Confirm',
-    successfully: 'Successfully',
-    close: 'Close',
-    note: 'Note',
-    awaitData: 'Retrieving data, please wait.',
-    switchLanguageHints: 'Switch Language Success',
-    websiteTitle: 'Member Management System',
-    uploadHints: 'Uploading, please hold on. Do not close the window!',
-  },
-
-  shop: {
-    product: 'Product',
-    productCode: 'Product Code',
-    productName: 'Product',
-    productPicture: 'Picture',
-    productPrice: 'Price',
-    productBV: 'BV',
-    qty: 'Qty',
-    taxRate: 'Tax Rate',
-    taxAmount: 'Tax',
-    totalTaxAmount: 'Total Tax',
-    totalPrice: 'Total Price',
-    totalBV: 'Total BV',
-    orderCode: 'Order Code',
-    orderType: 'Order Type',
-    amount: 'Amount',
-    decCode: 'Code',
-    memberCode: 'Member Code',
-    memberName: 'Member Name',
-    recipientName: 'Recipient Name',
-    phoneNumber: 'Phone Number',
-    shippingAddress: 'Shipping Address',
-    shipping: 'Shipping',
-    payment: 'Payment',
-    createdTime: 'Created Time',
-    payTime: 'Pay Time',
-    payStatus: 'Pay Status',
-    action: 'Action',
-    download: 'Download',
-    sponsorCode: 'Sponsor Code',
-    inventory: 'Inventory',
-    checkOut: 'Check Out',
-    unPaid: 'Unpaid',
-    paid: 'Paid',
-    goBack: 'Go Back',
-    goPay: 'Pay',
-    orderDetail: 'Order Detail',
-    chooseTips: 'Please choose the products.',
-    confirmClose: 'Confirm to close?',
-    inputPasswordTips: 'Please enter your payment password',
-    selfPickUp: 'Self Pick-up',
-    delivery: 'Delivery',
-    selectAddress: 'Shipping Address',
-    selectPayment: 'Payment Method',
-    freight: 'Freight',
-    paidAmount: 'Amount Paid',
-    productsSettlement: 'Products Settlement',
-    total: 'Total',
-    totalOrders: 'Total Orders',
-    accountBalance: 'Account Balance',
-    balanceNotAllow: 'insufficient, unable to buy products',
-    paymentError: 'Payment or Account Balance error',
-    successOrderTips: 'The order is successful',
-    paymentMethod: 'Payment Method',
-  },
-
-  user: {
-    email: 'Email',
-    accountInformation: 'Account Information',
-    newMemberCode: 'New Member Code',
-    selectWelcomePack: 'Select Welcome Pack',
-    sponsorCode: 'Sponsor Code',
-    payInfo: 'Pay Info',
-    memberInformation: 'Member Information',
-    enterMemberCode: 'Please enter member code.',
-    welcomePackWay: 'Welcome Pack Way',
-    normal: 'Normal',
-    BAUpgrade: 'BA Upgrade',
-    entryLevel: 'Entry Level',
-    selectEntryLevel: 'Select entry level',
-    stockistCode: 'Stockist Code',
-  },
-
-  atlas: {
-    networkInformation: 'Network Information',
-    placementCode: 'Placement Code',
-    placementTree: 'Placement Tree',
-    left: 'Left',
-    right: 'Right',
-    placementAutoLeft: 'Placement Auto Location: L',
-    placementAutoRight: 'Placement Auto Location: R',
-    topMember: 'Top Member',
-    spreadDepth: 'Spread Depth',
-    periodNumber: 'Period number',
-    numberLayers: 'Number of Layers',
-    highest: 'Highest',
-    memberCode: 'Member Code',
-    name: 'Name',
-    level: 'Level',
-    location: 'Location',
-  },
-
-  config: {
-    consignee: 'Consignee',
-    detailedAddress: 'Detailed Address',
-    city: 'City',
-    localGovernmentArea: 'Local Government Area',
-    state: 'State',
-    default: 'Default Address',
-    createAddress: 'Add Shipping Address',
-    editAddress: 'Edit Shipping Address',
-  },
-
-  profile: {
-    personalInformation: 'Personal Information',
-    account: 'Account',
-    loginPassword: 'Login Password',
-    paymentPassword: 'Payment Password',
-    originalPassword: 'Original Password',
-    newPassword: 'New Password',
-    confirmPassword: 'Confirm Password',
-    memberLevel: 'Member Level',
-    highestDirector: 'Highest Director',
-    highestCrown: 'Highest Crown',
-    latestDirector: 'Latest Director',
-    latestCrown: 'Latest Crown',
-    currentPayCycle: 'Current Pay Cycle',
-    currentSystemTime: 'Current System Time',
-    memberJoinTime: 'Member Join Time',
-    joiningPeriod: 'Joining Period',
-    joiningDate: 'Joining Date',
-    whetherUpgrade: 'Whether Upgrade',
-    upgradeWay: 'Upgrade Way',
-    toUpgradeLevel: 'To Upgrade Level',
-    selectLevel: 'Please select a level',
-    topUpBV: 'Top Up(BV)',
-    upgradePurchaseProduct: 'Upgrade purchase product',
-    loginPasswordSuccessTips: 'User login password has been updated successfully.',
-    paymentPasswordSuccessTips: 'User payment password has been updated successfully.',
-    enterLoginPassword: 'Enter Login Password',
-    enterPaymentPassword: 'Enter Payment Password',
-  },
-  article: {
-    title: 'Title',
-    category: 'Category',
-    createTime: 'Create Time',
-    systemNotification: 'System Notification',
-  },
-  bonus: {
-    payCycle: 'Pay Cycle',
-    welcomeBonus: 'Welcome Bonus',
-    teamBonus: 'Team Bonus',
-    directorBonus: 'Director Bonus',
-    quarterlyBonus: 'Quarterly Bonus',
-    stockistCommission: 'Stockist Commission',
-    actualBonus: 'Actual Bonus',
-    totalBonus: 'Total Bonus',
-    leftNewlyIncreasedPerformance: 'Left Newly Increased Performance',
-    rightNewlyIncreasedPerformance: 'Right Newly Increased Performance',
-    leftSurplusPerformance: 'Left Surplus Performance',
-    rightSurplusPerformance: 'Right Surplus Performance',
-    periodBonus: 'Period %s Bonus',
-    viewRecord: 'View Record',
-    bonusFlowTitle: '%s Trading Record',
-    transTime: 'Trans Date',
-    transType: 'Trans Type',
-    preTransactionBalance: 'Pre Trans Balance',
-    transAmount: 'Trans Amount',
-    postTransactionBalance: 'Post Trans Balance',
-    remark: 'Remark',
-    whetherActive: 'Whether Active',
-    directorPGSPerformance: 'Director PGS Performance',
-    personalDetails: 'Personal Details',
-    status: 'Status',
-    personalBV: 'Personal BV',
-    PGS: 'PGS',
-    teamDetails: 'Team Details',
-    latestCalculationTime: 'Latest calculation time',
-    totalBV: 'Total BV',
-  },
-  finance: {
-    applyTransfer: 'Apply For Transfer',
-    transferOutAccountHint: 'Select transfer out of account',
-    transferInAccountHint: 'Select transfer in account',
-    receiveMemberCodeHint: 'Enter your receiving member code',
-    receiveMemberNameHint: 'Enter the name of receiving member',
-    transferAccounts: 'Transfer Accounts',
-    receivingMemberCode: 'Receiving Member Code',
-    receivingMemberName: 'Receiving Member Name',
-    transferIntoAccount: 'Transfer Into Account',
-    transferAmount: 'Amount',
-    serviceCharge: 'Service Charge',
-    actualAmountTransferredInto: 'Actual Amount Transferred Into',
-    transferTime: 'Transfer Time',
-    remark: 'Remark',
-    messageApplyTransfer: 'Are you sure you want to apply transfer?',
-    selectTransferType: 'Select transfer type',
-    transferType: 'Transfer Type',
-    currentAvailableBonus: 'Available Bonus',
-    currentAvailableEcoin: 'Available Ecoin',
-    currentTransferRatio: 'Transfer Ratio',
-    maximumTransferAmount: 'Maximum transfer amount',
-    memberCode: 'Member Code',
-    memberName: 'Member Name',
-    lessTransferHint: 'Each transfer shall not be less than %s',
-    transferNotAllow: 'Not allowed to transfer to yourself',
-    successTips: 'Successfully.',
-    enterPasswordTips: 'Please enter your payment password',
-    executing: 'executing...',
-    recharge: 'Recharge',
-    createdTime: 'Created Time',
-    rechargeAmount: 'Recharge Amount',
-    rechargeStatus: 'Recharge Status',
-    bankName: 'Bank Name',
-    bankAccount: 'Bank Account',
-    printVoucher: 'Recharge Voucher',
-    uploadVoucher: 'Upload',
-    viewVoucher: 'View',
-    bankInformation: 'Bank Info',
-    selectBank: 'Select Bank',
-    accountName: 'Account Name',
-  },
-}
+export default {
+  route: {
+    dashboard: 'Dashboard',
+    shop: 'Mall Management',
+    user: 'Mall Management',
+    bonus: 'Bonus Management',
+    atlas: 'Network Chart',
+    article: 'Article Management',
+    config: 'Personal Center',
+
+    indexShop: 'Products list',
+    shopReconsume: 'Reconsume List',
+    memberManagement: 'Member management',
+    personalInfo: 'Personal Info',
+    documentation: 'Documentation',
+    guide: 'Guide',
+    permission: 'Permission',
+    pagePermission: 'Page Permission',
+    rolePermission: 'Role Permission',
+    directivePermission: 'Directive Permission',
+    icons: 'Icons',
+    components: 'Components',
+    tinymce: 'Tinymce',
+    markdown: 'Markdown',
+    jsonEditor: 'JSON Editor',
+    dndList: 'Dnd List',
+    splitPane: 'SplitPane',
+    avatarUpload: 'Avatar Upload',
+    dropzone: 'Dropzone',
+    sticky: 'Sticky',
+    countTo: 'Count To',
+    componentMixin: 'Mixin',
+    backToTop: 'Back To Top',
+    dragDialog: 'Drag Dialog',
+    dragSelect: 'Drag Select',
+    dragKanban: 'Drag Kanban',
+    charts: 'Charts',
+    keyboardChart: 'Keyboard Chart',
+    lineChart: 'Line Chart',
+    mixChart: 'Mix Chart',
+    example: 'Example',
+    nested: 'Nested Routes',
+    menu1: 'Menu 1',
+    'menu1-1': 'Menu 1-1',
+    'menu1-2': 'Menu 1-2',
+    'menu1-2-1': 'Menu 1-2-1',
+    'menu1-2-2': 'Menu 1-2-2',
+    'menu1-3': 'Menu 1-3',
+    menu2: 'Menu 2',
+    Table: 'Table',
+    dynamicTable: 'Dynamic Table',
+    dragTable: 'Drag Table',
+    inlineEditTable: 'Inline Edit',
+    complexTable: 'Complex Table',
+    tab: 'Tab',
+    form: 'Form',
+    createArticle: 'Create Article',
+    editArticle: 'Edit Article',
+    articleList: 'Article List',
+    errorPages: 'Error Pages',
+    page401: '401',
+    page404: '404',
+    errorLog: 'Error Log',
+    excel: 'Excel',
+    exportExcel: 'Export Excel',
+    selectExcel: 'Export Selected',
+    mergeHeader: 'Merge Header',
+    uploadExcel: 'Upload Excel',
+    zip: 'Zip',
+    pdf: 'PDF',
+    exportZip: 'Export Zip',
+    theme: 'Theme',
+    clipboardDemo: 'Clipboard',
+    i18n: 'I18n',
+    externalLink: 'External Link',
+    profile: 'Profile'
+  },
+  navbar: {
+    dashboard: 'Dashboard',
+    shippingAddress: 'Shipping Address',
+    logOut: 'Log Out',
+    profile: 'Profile',
+    theme: 'Theme',
+    size: 'Global Size',
+    visitPreviousVersion: 'Visit Previous Version'
+  },
+  menu: {
+    // 一级菜单
+    dashboard: 'Dashboard',
+    shoppingMall: 'Shopping Mall',
+    memberManagement: 'Member Management',
+    networkChart: 'Network Chart',
+    bonusManagement: 'Bonus Management',
+    articleManagement: 'Article Management',
+    setting: 'Personal Center',
+    // 二级菜单/接口-dashboard
+    monthBonus: 'Month Bonus',
+    // 二级菜单/接口-shoppingMall
+    repeatPurchase: 'Repeat Purchase',
+    ownOrder: 'My Order',
+    carFundProducts: 'Car Fund Products',
+    villaFundProducts: 'Villa Fund Products',
+    welcomePack: 'Member Welcome Pack',
+    memberRepeatPurchase: 'Member Repeat Purchase',
+    welcomePackList: 'Welcome Pack Listing',
+    memberUpgrade: 'Member Upgrade',
+    memberOrder: 'Member Order',
+    reconsume: 'Reconsume',
+    orderList: 'Order List',
+    brandAmbassador: 'Brand Ambassador',
+    BAOrderList: 'Brand Ambassador Order',
+    // 二级菜单/接口-memberManagement
+    personalInfo: 'Personal Info',
+    resetPassword: 'Reset Password',
+    // 二级菜单/接口-networkChart
+    placementNetwork: 'Placement Network',
+    placementNetworkEx: 'Placement Network Ex',
+    sponsorNetwork: 'Sponsor Network',
+    sponsorNetworkEx: 'Sponsor Network Ex',
+    brandAmbassadorList: 'Brand Ambassador List',
+    // 二级菜单/接口-bonusManagement
+    myAccount: 'My Account',
+    myBonus: 'My Bonus',
+    teamInquiry: 'Team Inquiry',
+    historicalCumulativeBonus: 'Historical Cumulative Bonus',
+    withdrawalDetails: 'Withdrawal Details',
+    applyWithdraw: 'Apply For Withdraw',
+    rechargeDetails: 'Recharge Details',
+    applyRecharge: 'Apply For Recharge',
+    transferDetails: 'Transfer Details',
+    applyTransfer: 'Apply For Transfer',
+    // 二级菜单/接口-articleManagement
+    systemNotification: 'System Notification',
+    // 二级菜单/接口-setting
+    shippingAddress: 'Shipping Address'
+  },
+  login: {
+    title: 'Welcome',
+    logIn: 'Login',
+    username: 'Username',
+    password: 'Password',
+    any: 'any',
+    thirdparty: 'Or connect with',
+    thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !',
+    verifyCode: 'Verification Code'
+  },
+  documentation: {
+    documentation: 'Documentation',
+    github: 'Github Repository'
+  },
+  permission: {
+    addRole: 'New Role',
+    editPermission: 'Edit',
+    roles: 'Your roles',
+    switchRoles: 'Switch roles',
+    tips: 'In some cases, using v-permission will have no effect. For example: Element-UI  el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.',
+    delete: 'Delete',
+    confirm: 'Confirm',
+    cancel: 'Cancel'
+  },
+  guide: {
+    description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',
+    button: 'Show Guide'
+  },
+  components: {
+    documentation: 'Documentation',
+    tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.',
+    dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
+    stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
+    backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
+    backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally',
+    imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.'
+  },
+  table: {
+    dynamicTips1: 'Fixed header, sorted by header order',
+    dynamicTips2: 'Not fixed header, sorted by click order',
+    dragTips1: 'The default order',
+    dragTips2: 'The after dragging order',
+    title: 'Title',
+    importance: 'Imp',
+    type: 'Type',
+    remark: 'Remark',
+    search: 'Search',
+    add: 'Add',
+    export: 'Export',
+    reviewer: 'reviewer',
+    id: 'ID',
+    date: 'Date',
+    author: 'Author',
+    readings: 'Readings',
+    status: 'Status',
+    actions: 'Actions',
+    edit: 'Edit',
+    publish: 'Publish',
+    draft: 'Draft',
+    delete: 'Delete',
+    cancel: 'Cancel',
+    confirm: 'Confirm'
+  },
+  example: {
+    warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details'
+  },
+  errorLog: {
+    tips: 'Please click the bug icon in the upper right corner',
+    description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.',
+    documentation: 'Document introduction'
+  },
+  excel: {
+    export: 'Export',
+    selectedExport: 'Export Selected Items',
+    placeholder: 'Please enter the file name (default excel-list)'
+  },
+  zip: {
+    export: 'Export',
+    placeholder: 'Please enter the file name (default file)'
+  },
+  pdf: {
+    tips: 'Here we use window.print() to implement the feature of downloading PDF.'
+  },
+  theme: {
+    change: 'Change Theme',
+    documentation: 'Theme documentation',
+    tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.'
+  },
+  tagsView: {
+    refresh: 'Refresh',
+    close: 'Close',
+    closeOthers: 'Close Others',
+    closeAll: 'Close All'
+  },
+  settings: {
+    title: 'Page style setting',
+    theme: 'Theme Color',
+    tagsView: 'Open Tags-View',
+    fixedHeader: 'Fixed Header',
+    sidebarLogo: 'Sidebar Logo'
+  },
+  empLevels: {
+    // 级别配置
+    '67BE1C6C21F81B32E055736AECE8644D': "No Rank",
+    '67BE6A4D03C52288E055736AECE8644D': '1 Star Director',
+    '67BE6EA2070D22EBE055736AECE8644D': '2 Star Director',
+    '67BE742A336F2370E055736AECE8644D': '3 Star Director',
+    '67BE805032C22492E055736AECE8644D': 'Diamond',
+    '67BE805032C22492E066736AECE8644D': '2 Star Diamond',
+    '67BE805032C22492E077736AECE8644D': '3 Star Diamond'
+  },
+  crownLevels: {
+    // 级别配置
+    'DCBEDD8E0EAD3DF59D81CCC0C2ACAEFF': '0-Star Crown',
+    'E0B75B89C94F35EF8EE0054FA34B759C': '1-Star Crown',
+    '7FEBE5DE95D530578915F4072E7CD842': '2-Star Crown',
+    '391691E01CD5373F8D23F01FAD750222': '3-Star Crown',
+    '8ACAEA736F5331B79283C895F36084E5': '4-Star Crown',
+    'CE46B39D07633217AA5711438649D1D6': '5-Star Crown',
+    '24396B85E74A3005947F1F90EBA5F5CF': '6-Star Crown',
+    '8C253968EB6F3F3FA5BE84F63136FFFA': '7-Star Crown'
+  },
+  decLvs: {
+    // 等级配置
+    '67ABC6AO8YTK2LN0E055736AECE8644D': 'NA',
+    '67ABCCE20A9F5553E055736AECE8677A': 'Silver',
+    '67ABCE0ECE705575E055736AECE8677C': 'Gold'
+  },
+  eliteLevels: {
+    // 等级配置
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF7C': 'Super Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF7V': 'Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF8V': 'Pro Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8NA7V': 'NA',
+  },
+  dashboard: {
+    highestDirector: 'Highest Director',
+    highestCrown: 'Highest Crown',
+    eliteLevel: 'Elite Level',
+    memberLevel: 'Member Level',
+    payCycle: 'Current Pay Cycle',
+    remainBv: 'Remain BV',
+    activeDeadline: 'Active Deadline Date',
+    more: 'more',
+    articleNotification: 'System Notification'
+  },
+  currency: {
+    unit: 'Naira',
+    sign: '₦',
+    naira: 'NGN'
+  },
+
+  common: {
+    save: 'Save',
+    modify: 'Modify',
+    submit: 'Submit',
+    delete: 'Delete',
+    edit: 'Edit',
+    action: 'Action',
+    yes: 'YES',
+    no: 'NO',
+    view: 'View',
+    select: 'Select',
+    reset: 'Reset',
+    startDate: 'Start Date',
+    endDate: 'End Date',
+    deleteTips: 'Are you sure you want to delete the selected data?',
+    hint: 'Hint',
+    cancel: 'Cancel',
+    confirm: 'Confirm',
+    successfully: 'Successfully',
+    close: 'Close',
+    note: 'Note',
+    awaitData: 'Retrieving data, please wait.',
+    switchLanguageHints: 'Switch Language Success',
+    websiteTitle: 'Member Management System',
+    uploadHints: 'Uploading, please hold on. Do not close the window!',
+    canNotBeBlank: ' cannot be blank',
+    require: 'is required',
+    language: "Language",
+    noData: 'No Data'
+  },
+
+  shop: {
+    product: 'Product',
+    productCode: 'Product Code',
+    productName: 'Product',
+    productPicture: 'Picture',
+    productPrice: 'Price',
+    productBV: 'BV',
+    qty: 'Qty',
+    taxRate: 'Tax Rate',
+    taxAmount: 'Tax',
+    totalTaxAmount: 'Total Tax',
+    totalPrice: 'Total Price',
+    totalBV: 'Total BV',
+    orderCode: 'Order Code',
+    orderType: 'Order Type',
+    amount: 'Amount',
+    decCode: 'Code',
+    memberCode: 'Member Code',
+    memberName: 'Member Name',
+    recipientName: 'Recipient Name',
+    phoneNumber: 'Phone Number',
+    shippingAddress: 'Shipping Address',
+    shipping: 'Shipping',
+    payment: 'Payment',
+    createdTime: 'Created Time',
+    payTime: 'Pay Time',
+    payStatus: 'Pay Status',
+    action: 'Action',
+    download: 'Download',
+    sponsorCode: 'Sponsor Code',
+    inventory: 'Inventory',
+    checkOut: 'Check Out',
+    unPaid: 'Unpaid',
+    paid: 'Paid',
+    goBack: 'Go Back',
+    goPay: 'Pay',
+    orderDetail: 'Order Detail',
+    chooseTips: 'Please choose the products.',
+    confirmClose: 'Confirm to close?',
+    inputPasswordTips: 'Please enter your payment password',
+    selfPickUp: 'Self Pick-up',
+    delivery: 'Delivery',
+    selectAddress: 'Shipping Address',
+    selectPayment: 'Payment Method',
+    freight: 'Freight',
+    paidAmount: 'Amount Paid',
+    productsSettlement: 'Products Settlement',
+    total: 'Total',
+    totalOrders: 'Total Orders',
+    accountBalance: 'Account Balance',
+    balanceNotAllow: 'insufficient, unable to buy products',
+    paymentError: 'Payment or Account Balance error',
+    successOrderTips: 'The order is successful',
+    paymentMethod: 'Payment Method',
+    customerInfo: 'Customer Info',
+    reconsumeUserCode: 'Reconsume User Code',
+    mobile: 'Mobile',
+    province: 'State',
+    lgaName: 'Local Government Area',
+    cityName: 'City',
+    address: 'Detailed Address',
+    memberNotFound: 'Member Not Found',
+    declarationCenterNumber:'Stockist Code',
+    country: 'Country',
+    paymentCurrency: 'Payment Currency',
+    salesPrice: 'DP',
+    marketPrice: 'RP',
+      declarationCenterNumberTips: 'Please enter stockist code'
+  },
+
+  user: {
+    email: 'Email',
+    accountInformation: 'Account Information',
+    newMemberCode: 'New Member Code',
+    selectWelcomePack: 'Select Welcome Pack',
+    sponsorCode: 'Sponsor Code',
+    payInfo: 'Pay Info',
+    memberInformation: 'Member Information',
+    enterMemberCode: 'Please enter member code.',
+    welcomePackWay: 'Welcome Pack Way',
+    normal: 'Normal',
+    BAUpgrade: 'BA Upgrade',
+    entryLevel: 'Entry Level',
+    selectEntryLevel: 'Select entry level',
+    stockistCode: 'Stockist Code',
+    selectCountry: 'Select Country',
+    selectLanguage: 'Select Language',
+    recommenderName: 'Sponsor ID',
+    recommenderActualName: 'Placement Sponsor ID',
+
+  },
+
+  atlas: {
+    networkInformation: 'Network Information',
+    placementCode: 'Placement Code',
+    placementTree: 'Placement Tree',
+    left: 'Left',
+    right: 'Right',
+    placementAutoLeft: 'Placement Auto Location: L',
+    placementAutoRight: 'Placement Auto Location: R',
+    topMember: 'Top Member',
+    spreadDepth: 'Spread Depth',
+    periodNumber: 'Period number',
+    numberLayers: 'Number of Layers',
+    highest: 'Highest',
+    memberCode: 'Member Code',
+    name: 'Name',
+    level: 'Level',
+    location: 'Location'
+  },
+
+  config: {
+    consignee: 'Consignee',
+    detailedAddress: 'Detailed Address',
+    city: 'City',
+    localGovernmentArea: 'Local Government Area',
+    state: 'State',
+    default: 'Default Address',
+    createAddress: 'Add Shipping Address',
+    editAddress: 'Edit Shipping Address'
+  },
+
+  profile: {
+    personalInformation: 'Personal Information',
+    account: 'Account',
+    loginPassword: 'Login Password',
+    paymentPassword: 'Payment Password',
+    originalPassword: 'Original Password',
+    newPassword: 'New Password',
+    confirmPassword: 'Confirm Password',
+    memberLevel: 'Member Level',
+    highestDirector: 'Highest Director',
+    highestCrown: 'Highest Crown',
+    eliteLevel: 'Elite Level',
+    latestDirector: 'Latest Director',
+    latestCrown: 'Latest Crown',
+    currentPayCycle: 'Current Pay Cycle',
+    currentSystemTime: 'Current System Time',
+    memberJoinTime: 'Member Join Time',
+    joiningPeriod: 'Joining Period',
+    joiningDate: 'Joining Date',
+    whetherUpgrade: 'Whether Upgrade',
+    upgradeWay: 'Upgrade Way',
+    toUpgradeLevel: 'To Upgrade Level',
+    selectLevel: 'Please select a level',
+    topUpBV: 'Top Up(BV)',
+    upgradePurchaseProduct: 'Upgrade purchase product',
+    loginPasswordSuccessTips: 'User login password has been updated successfully.',
+    paymentPasswordSuccessTips: 'User payment password has been updated successfully.',
+    enterLoginPassword: 'Enter Login Password',
+    enterPaymentPassword: 'Enter Payment Password'
+  },
+  article: {
+    title: 'Title',
+    category: 'Category',
+    createTime: 'Create Time',
+    systemNotification: 'System Notification'
+  },
+  bonus: {
+    payCycle: 'Pay Cycle',
+    welcomeBonus: 'Welcome Bonus',
+    teamBonus: 'Team Bonus',
+    directorBonus: 'Director Bonus',
+    quarterlyBonus: 'Quarterly Bonus',
+    stockistCommission: 'Stockist Commission',
+    actualBonus: 'Actual Bonus',
+    totalBonus: 'Total Bonus',
+    leftNewlyIncreasedPerformance: 'Left Newly Increased Performance',
+    rightNewlyIncreasedPerformance: 'Right Newly Increased Performance',
+    leftSurplusPerformance: 'Left Surplus Performance',
+    rightSurplusPerformance: 'Right Surplus Performance',
+    periodBonus: 'Period %s Bonus',
+    viewRecord: 'View Record',
+    bonusFlowTitle: '%s Trading Record',
+    transTime: 'Trans Date',
+    expiredTime: 'Expired Date',
+    transType: 'Trans Type',
+    preTransactionBalance: 'Pre Trans Balance',
+    transAmount: 'Trans Amount',
+    postTransactionBalance: 'Post Trans Balance',
+    remark: 'Remark',
+    whetherActive: 'Whether Active',
+    directorPGSPerformance: 'Director PGS Performance',
+    personalDetails: 'Personal Details',
+    status: 'Status',
+    personalBV: 'Personal BV',
+    PGS: 'PGS',
+    teamDetails: 'Team Details',
+    latestCalculationTime: 'Latest calculation time',
+    totalBV: 'Total BV',
+    eliteBonus: 'Elite Bonus',
+    proEliteBonus: 'Pro Elite Bonus',
+    superEliteBonus: 'Super Elite Bonus',
+    stockistBonus: 'Stockist Bonus',
+    leaderShipBonus: 'LeaderShip Bonus',
+    carBonus: 'Car Bonus',
+    userPerformanceBonus: 'Performance Bonus',
+    No:'No.',
+    amount: 'Amount',
+    originalAmount: 'Original Amount'
+  },
+  finance: {
+    applyTransfer: 'Apply For Transfer',
+    transferOutAccountHint: 'Select transfer out of account',
+    transferInAccountHint: 'Select transfer in account',
+    receiveMemberCodeHint: 'Enter your receiving member code',
+    receiveMemberNameHint: 'Enter the name of receiving member',
+    transferAccounts: 'Transfer Accounts',
+    receivingMemberCode: 'Receiving Member Code',
+    receivingMemberName: 'Receiving Member Name',
+    transferIntoAccount: 'Transfer Into Account',
+    transferAmount: 'Amount',
+    serviceCharge: 'Service Charge',
+    actualAmountTransferredInto: 'Actual Amount Transferred Into',
+    transferTime: 'Transfer Time',
+    remark: 'Remark',
+    messageApplyTransfer: 'Are you sure you want to apply transfer?',
+    selectTransferType: 'Select transfer type',
+    transferType: 'Transfer Type',
+    currentAvailableBonus: 'Available Bonus',
+    currentAvailableEcoin: 'Available Ecoin',
+    currentTransferRatio: 'Transfer Ratio',
+    maximumTransferAmount: 'Maximum transfer amount',
+    memberCode: 'Member Code',
+    memberName: 'Member Name',
+    lessTransferHint: 'Each transfer shall not be less than %s',
+    transferNotAllow: 'Not allowed to transfer to yourself',
+    successTips: 'Successfully.',
+    enterPasswordTips: 'Please enter your payment password',
+    executing: 'executing...',
+    recharge: 'Recharge',
+    createdTime: 'Created Time',
+    rechargeAmount: 'Recharge Amount',
+    rechargeStatus: 'Recharge Status',
+    bankName: 'Bank Name',
+    bankAccount: 'Bank Account',
+    printVoucher: 'Recharge Voucher',
+    uploadVoucher: 'Upload',
+    viewVoucher: 'View',
+    bankInformation: 'Bank Info',
+    selectBank: 'Select Bank',
+    accountName: 'Account Name',
+    uploadEdit: 'Edit',
+    paymentReference: 'Payment Reference',
+  },
+  notificationProps: {
+    title: '📢 system update',
+    description: 'System update detected, please refresh the page',
+    confirmButtonText: 'refresh',
+    cancelButtonText: 'dismiss'
+  }
+}

+ 2 - 2
src/lang/index.js

@@ -31,7 +31,7 @@ const messages = {
   }
 }
 export function getLanguage() {
-  const chooseLanguage = Cookies.get('language')
+  const chooseLanguage = Cookies.get('language') || 'en'
   if (chooseLanguage) return chooseLanguage
 
   // if has not choose language
@@ -49,7 +49,7 @@ const i18n = new VueI18n({
   // options: en | zh | es
   locale: getLanguage(),
   // 默认语言设置,当其他语言没有的情况下,使用en作为默认语言
-  fallbackLocale: 'zh',
+  fallbackLocale: 'en',
   // set locale messages
   messages
 })

+ 566 - 505
src/lang/zh.js

@@ -1,505 +1,566 @@
-export default {
-  route: {
-    dashboard: '首页',
-    shop: '商城管理',
-    indexShop: '商品管理',
-    shopReconsume: '复消商品',
-    memberManagement: '会员管理',
-    personalInfo: '个人资料',
-    documentation: '文档',
-    guide: '引导页',
-    permission: '权限测试页',
-    rolePermission: '角色权限',
-    pagePermission: '页面权限',
-    directivePermission: '指令权限',
-    icons: '图标',
-    components: '组件',
-    tinymce: '富文本编辑器',
-    markdown: 'Markdown',
-    jsonEditor: 'JSON 编辑器',
-    dndList: '列表拖拽',
-    splitPane: 'Splitpane',
-    avatarUpload: '头像上传',
-    dropzone: 'Dropzone',
-    sticky: 'Sticky',
-    countTo: 'Count To',
-    componentMixin: '小组件',
-    backToTop: '返回顶部',
-    dragDialog: '拖拽 Dialog',
-    dragSelect: '拖拽 Select',
-    dragKanban: '可拖拽看板',
-    charts: '图表',
-    keyboardChart: '键盘图表',
-    lineChart: '折线图',
-    mixChart: '混合图表',
-    example: '综合实例',
-    nested: '路由嵌套',
-    menu1: '菜单1',
-    'menu1-1': '菜单 1-1',
-    'menu1-2': '菜单 1-2',
-    'menu1-2-1': '菜单 1-2-1',
-    'menu1-2-2': '菜单 1-2-2',
-    'menu1-3': '菜单 1-3',
-    menu2: '菜单 2',
-    Table: 'Table',
-    dynamicTable: '动态 Table',
-    dragTable: '拖拽 Table',
-    inlineEditTable: 'Table 内编辑',
-    complexTable: '综合 Table',
-    tab: 'Tab',
-    form: '表单',
-    createArticle: '创建文章',
-    editArticle: '编辑文章',
-    articleList: '文章列表',
-    errorPages: '错误页面',
-    page401: '401',
-    page404: '404',
-    errorLog: '错误日志',
-    excel: 'Excel',
-    exportExcel: '导出 Excel',
-    selectExcel: '导出 已选择项',
-    mergeHeader: '导出 多级表头',
-    uploadExcel: '上传 Excel',
-    zip: 'Zip',
-    pdf: 'PDF',
-    exportZip: 'Export Zip',
-    theme: '换肤',
-    clipboardDemo: 'Clipboard',
-    i18n: '国际化',
-    externalLink: '外链',
-    profile: '个人中心'
-  },
-  navbar: {
-    dashboard: '首页',
-    shippingAddress: '收货地址',
-    logOut: '退出登录',
-    profile: '个人中心',
-    theme: '换肤',
-    size: '布局大小',
-    visitPreviousVersion: '进入旧版',
-  },
-  menu: {
-    // 一级菜单
-    dashboard: '首页',
-    shoppingMall: '商城管理',
-    memberManagement: '会员管理',
-    networkChart: '会员网络',
-    bonusManagement: '奖金管理',
-    articleManagement: '文章管理',
-    setting: '设置',
-    // 二级菜单/接口-dashboard
-    monthBonus: '月奖',
-    // 二级菜单/接口-shoppingMall
-    standardProducts: '普通商品',
-    carFundProducts: '车奖商品',
-    villaFundProducts: '房奖商品',
-    welcomePack: '报单管理',
-    welcomePackList: '报单列表',
-    memberUpgrade: '升级管理',
-    orderList: '订单列表',
-    brandAmbassador: 'BA会员',
-    BAOrderList: 'BA订单',
-    // 二级菜单/接口-memberManagement
-    personalInfo: '个人资料',
-    resetPassword: '重设密码',
-    // 二级菜单/接口-networkChart
-    placementNetwork: '安置网络',
-    sponsorNetwork: '推荐网路',
-    brandAmbassadorList: 'BA会员',
-    // 二级菜单/接口-bonusManagement
-    myAccount: '我的账户',
-    myBonus: '我的奖金',
-    teamInquiry: '团队查询',
-    historicalCumulativeBonus: '历史累积奖金',
-    withdrawalDetails: '提现明细',
-    applyWithdraw: '申请提现',
-    rechargeDetails: '充值明细',
-    applyRecharge: '申请充值',
-    transferDetails: '转账明细',
-    applyTransfer: '申请转账',
-    // 二级菜单/接口-articleManagement
-    systemNotification: '系统通知',
-    // 二级菜单/接口-setting
-    shippingAddress: '收货地址',
-  },
-  login: {
-    title: '欢迎',
-    logIn: '登录',
-    username: '账号',
-    password: '密码',
-    any: '随便填',
-    thirdparty: '第三方登录',
-    thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!',
-    verifyCode: '验证码'
-  },
-  documentation: {
-    documentation: '文档',
-    github: 'Github 地址'
-  },
-  permission: {
-    addRole: '新增角色',
-    editPermission: '编辑权限',
-    roles: '你的权限',
-    switchRoles: '切换权限',
-    tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
-    delete: '删除',
-    confirm: '确定',
-    cancel: '取消'
-  },
-  guide: {
-    description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于',
-    button: '打开引导'
-  },
-  components: {
-    documentation: '文档',
-    tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见',
-    dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone',
-    stickyTips: '当页面滚动到预设的位置会吸附在顶部',
-    backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮',
-    backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素',
-    imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。'
-  },
-  table: {
-    dynamicTips1: '固定表头, 按照表头顺序排序',
-    dynamicTips2: '不固定表头, 按照点击顺序排序',
-    dragTips1: '默认顺序',
-    dragTips2: '拖拽后顺序',
-    title: '标题',
-    importance: '重要性',
-    type: '类型',
-    remark: '点评',
-    search: '搜索',
-    add: '添加',
-    export: '导出',
-    reviewer: '审核人',
-    id: '序号',
-    date: '时间',
-    author: '作者',
-    readings: '阅读数',
-    status: '状态',
-    actions: '操作',
-    edit: '编辑',
-    publish: '发布',
-    draft: '草稿',
-    delete: '删除',
-    cancel: '取 消',
-    confirm: '确 定'
-  },
-  example: {
-    warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见'
-  },
-  errorLog: {
-    tips: '请点击右上角bug小图标',
-    description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。',
-    documentation: '文档介绍'
-  },
-  excel: {
-    export: '导出',
-    selectedExport: '导出已选择项',
-    placeholder: '请输入文件名(默认excel-list)'
-  },
-  zip: {
-    export: '导出',
-    placeholder: '请输入文件名(默认file)'
-  },
-  pdf: {
-    tips: '这里使用   window.print() 来实现下载pdf的功能'
-  },
-  theme: {
-    change: '换肤',
-    documentation: '换肤文档',
-    tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。'
-  },
-  tagsView: {
-    refresh: '刷新',
-    close: '关闭',
-    closeOthers: '关闭其它',
-    closeAll: '关闭所有'
-  },
-  settings: {
-    title: '系统布局配置',
-    theme: '主题色',
-    tagsView: '开启 Tags-View',
-    fixedHeader: '固定 Header',
-    sidebarLogo: '侧边栏 Logo'
-  },
-  empLevels: {
-    // 级别配置
-    '67BE1C6C21F81B32E055736AECE8644D':  '无级别',
-    'E121497617216708615': '1星经理',
-    '67BE5FE7857C216AE055736AECE8644D': '2星经理',
-    'E121497617216708616': '3星经理',
-    '67BE6A4D03C52288E055736AECE8644D': '4星经理',
-    '67BE6EA2070D22EBE055736AECE8644D': '5星经理',
-    '67BE742A336F2370E055736AECE8644D': '6星经理',
-    '67BE805032C22492E055736AECE8644D': '7星经理'
-  },
-  crownLevels: {
-    // 级别配置
-    'DCBEDD8E0EAD3DF59D81CCC0C2ACAEFF': '无星级',
-    'E0B75B89C94F35EF8EE0054FA34B759C': '1星皇冠',
-    '7FEBE5DE95D530578915F4072E7CD842': '2星皇冠',
-    '391691E01CD5373F8D23F01FAD750222': '3星皇冠',
-    '8ACAEA736F5331B79283C895F36084E5': '4星皇冠',
-    'CE46B39D07633217AA5711438649D1D6': '5星皇冠',
-    '24396B85E74A3005947F1F90EBA5F5CF': '6星皇冠',
-    '8C253968EB6F3F3FA5BE84F63136FFFA': '7星皇冠',
-  },
-  decLvs: {
-    // 等级配置
-    '67ABCB8C1F7D5519E055736AECE8644D': '银卡',
-    '67ABCCE20A9F5553E055736AECE8644D': '金卡',
-    '67ABCE0ECE705575E055736AECE8644D': '钻卡'
-  },
-  dashboard: {
-    highestDirector: '最高管理星级',
-    highestCrown: '最高皇冠星级',
-    memberLevel: '会员级别',
-    payCycle: '当前业绩期',
-    remainBv: '剩余PV',
-    activeDeadline: '活跃日期截止',
-    more: '更多',
-    articleNotification: '系统通知'
-  },
-  currency: {
-    unit: '奈拉',
-    sign: '₦',
-    naira: 'NGN',
-  },
-  common: {
-    save: '保存',
-    modify: '修改',
-    submit: '提交',
-    delete: '删除',
-    edit: '编辑',
-    action: '操作',
-    yes: '是',
-    no: '否',
-    view: '查看',
-    select: '查询',
-    reset: '清空',
-    startDate: '开始时间',
-    endDate: '结束时间',
-    deleteTips: '确认删除所选数据?',
-    hint: '提示',
-    confirm: '确定',
-    cancel: '取消',
-    successfully: '成功',
-    close: '关闭',
-    note: '备注',
-    awaitData: '正在获取数据,请稍后',
-    switchLanguageHints: '语言切换成功',
-    websiteTitle: '会员管理系统',
-    uploadHints: '正在上传,请稍后。请勿关闭窗口!',
-  },
-  shop: {
-    product: '商品',
-    productCode: '编号',
-    productName: '名称',
-    productPrice: '单价',
-    productPicture: '图片',
-    productBV: 'BV',
-    qty: '数量',
-    taxRate: '税率',
-    taxAmount: '税额',
-    totalTaxAmount: '合计税额',
-    totalPrice: '总价',
-    totalBV: '合计BV',
-    orderCode: '订单编号',
-    orderType: '订单类型',
-    amount: '金额',
-    decCode: '报单编号',
-    memberCode: '会员编号',
-    memberName: '会员姓名',
-    recipientName: '收货人',
-    phoneNumber: '收货电话',
-    shippingAddress: '收货地址',
-    shipping: '收货方式',
-    payment: '支付方式',
-    createdTime: '下单时间',
-    payTime: '支付时间',
-    payStatus: '支付状态',
-    action: '操作',
-    download: '下载',
-    sponsorCode: '接点人编号',
-    inventory: '库存',
-    checkOut: '结算',
-    unPaid: '待支付',
-    paid: '已支付',
-    goBack: '返回',
-    goPay: '支付',
-    orderDetail: '订单详情',
-    chooseTips: '请选择商品',
-    confirmClose: '确定要关闭页面吗?',
-    inputPasswordTips: '请输入支付密码',
-    selfPickUp: '自提',
-    delivery: '收货地址',
-    selectAddress: '收货地址',
-    selectPayment: '支付方式',
-    freight: '运费',
-    paidAmount: '实付金额',
-    productsSettlement: '商品结算',
-    total: '合计',
-    totalOrders: '订单合计',
-    accountBalance: '账户余额',
-    balanceNotAllow: '不足,无法购买商品',
-    paymentError: '支付方式或账户类型错误',
-    successOrderTips: '订单支付成功',
-    paymentMethod: '支付方式',
-  },
-  user: {
-    email: '电子邮箱',
-    accountInformation: '账号信息',
-    newMemberCode: '会员编号',
-    selectWelcomePack: '报单方式',
-    sponsorCode: '报单中心编号',
-    payInfo: '支付信息',
-    memberInformation: '会员信息',
-    enterMemberCode: '请输入会员编号',
-    welcomePackWay: '报单方式',
-    normal: '会员报单',
-    BAUpgrade: 'BA会员升级',
-    entryLevel: '报单级别',
-    selectEntryLevel: '请选择报单级别',
-    stockistCode: '报单中心编号',
-  },
-
-  atlas: {
-    networkInformation: '网络信息',
-    placementCode: '安置人编号',
-    placementTree: '安置区位',
-    left: '左区',
-    right: '右区',
-    placementAutoLeft: '自动安置在左侧',
-    placementAutoRight: '自动安置在右侧',
-    topMember: '顶级会员',
-    spreadDepth: '展开深度',
-    periodNumber: '期数',
-    numberLayers: '层数',
-    highest: '最高',
-    memberCode: '会员编号',
-    name: '姓名',
-    level: '级别',
-    location: '区位',
-  },
-
-  config: {
-    consignee: '收货人',
-    detailedAddress: '详细地址',
-    city: '城市',
-    localGovernmentArea: '区域',
-    state: '地区',
-    default: '默认地址',
-    createAddress: '添加地址',
-    editAddress: '修改地址',
-  },
-  profile: {
-    personalInformation: '个人资料',
-    account: '账户',
-    loginPassword: '登录密码',
-    paymentPassword: '支付密码',
-    originalPassword: '原密码',
-    newPassword: '新密码',
-    confirmPassword: '重复新密码',
-    currentPayCycle: '结算周期',
-    currentSystemTime: '系统时间',
-    memberJoinTime: '加入时间',
-    memberLevel: '会员等级',
-    highestDirector: '最高管理聘级',
-    highestCrown: '最高皇冠星级',
-    latestDirector: '最新管理星级',
-    latestCrown: '最新皇冠星级',
-    joiningPeriod: '加入期数',
-    joiningDate: '加入时间',
-    whetherUpgrade: '是否已升级',
-    upgradeWay: '升级方式',
-    toUpgradeLevel: '升级级别',
-    selectLevel: '请选择级别',
-    topUpBV: '升级补差业绩',
-    upgradePurchaseProduct: '升级购买商品',
-    loginPasswordSuccessTips: '登录密码已修改成功',
-    paymentPasswordSuccessTips: '支付密码已修改成功',
-    enterLoginPassword: '请输入登录密码',
-    enterPaymentPassword: '请支付登录密码',
-  },
-  article: {
-    title: '标题',
-    createTime: '发布时间',
-    category: '类型',
-    systemNotification: '系统通知',
-  },
-  bonus: {
-    payCycle: '期数',
-    welcomeBonus: '销售奖金',
-    teamBonus: '绩效奖',
-    directorBonus: '管理奖',
-    quarterlyBonus: '季度分红',
-    stockistCommission: '服务中心',
-    actualBonus: '实发奖金',
-    totalBonus: '奖金合计',
-    leftNewlyIncreasedPerformance: '左市场新增',
-    rightNewlyIncreasedPerformance: '右市场新增',
-    leftSurplusPerformance: '左市场结余',
-    rightSurplusPerformance: '右市场结余',
-    periodBonus: '第 %s 期奖金',
-    viewRecord: '查看流水',
-    bonusFlowTitle: '%s交易记录',
-    transTime: '交易时间',
-    transType: '交易类型',
-    preTransactionBalance: '交易前余额',
-    transAmount: '交易额',
-    postTransactionBalance: '交易后余额',
-    remark: '备注',
-    whetherActive: '是否活跃',
-    directorPGSPerformance: '管理奖个人小组业绩',
-    personalDetails: '个人情况',
-    status: '状态',
-    personalBV: '个人业绩',
-    PGS: '累计业绩',
-    teamDetails: '团队情况',
-    latestCalculationTime: '最新计算时间',
-    totalBV: '合计',
-  },
-  finance: {
-    applyTransfer: '转账',
-    transferOutAccountHint: '请选择转出账户',
-    transferInAccountHint: '请选择转入账户',
-    receiveMemberCodeHint: '请输入接收会员编号',
-    receiveMemberNameHint: '请输入接收会员姓名',
-    transferAccounts: '转出账户',
-    receivingMemberCode: '接收会员编号',
-    receivingMemberName: '接收会员姓名',
-    transferIntoAccount: '转入账户',
-    transferAmount: '转账金额',
-    serviceCharge: '手续费',
-    actualAmountTransferredInto: '实际入账金额',
-    transferTime: '转账时间',
-    remark: '备注',
-    messageApplyTransfer: '确定要发起转账吗?',
-    selectTransferType: '请选择转账类型',
-    transferType: '转账类型',
-    currentAvailableBonus: '当前可用奖金',
-    currentAvailableEcoin: '当前可用余额',
-    currentTransferRatio: '当前转账比例',
-    maximumTransferAmount: '最大转账金额',
-    lessTransferHint: '每次转账不得少于 %s',
-    transferNotAllow: '不允许向自己转账',
-    memberCode: '转入会员编号',
-    memberName: '会员姓名',
-    successTips: '转账成功',
-    enterPasswordTips: '请输入支付密码',
-    executing: '执行中...',
-    recharge: '充值',
-    createdTime: '转账时间',
-    rechargeAmount: '充值金额',
-    rechargeStatus: '充值状态',
-    bankName: '汇款银行',
-    bankAccount: '汇款账号',
-    printVoucher: '充值凭证',
-    uploadVoucher: '上传',
-    viewVoucher: '查看',
-    bankInformation: '银行信息',
-    selectBank: '请选择开户行',
-    accountName: '开户支行',
-  },
-}
+export default {
+  route: {
+    dashboard: '首页',
+    shop: '商城管理',
+    user: '商城管理',
+    bonus: '奖金管理',
+    atlas: '网络图谱',
+    article: '文章管理',
+    config: '个人中心',
+
+    indexShop: '商品管理',
+    shopReconsume: '复消商品',
+    memberManagement: '会员管理',
+    personalInfo: '个人信息',
+    documentation: '文档',
+    guide: '引导页',
+    permission: '权限测试页',
+    rolePermission: '角色权限',
+    pagePermission: '页面权限',
+    directivePermission: '指令权限',
+    icons: '图标',
+    components: '组件',
+    tinymce: '富文本编辑器',
+    markdown: 'Markdown',
+    jsonEditor: 'JSON 编辑器',
+    dndList: '列表拖拽',
+    splitPane: 'Splitpane',
+    avatarUpload: '头像上传',
+    dropzone: 'Dropzone',
+    sticky: 'Sticky',
+    countTo: 'Count To',
+    componentMixin: '小组件',
+    backToTop: '返回顶部',
+    dragDialog: '拖拽 Dialog',
+    dragSelect: '拖拽 Select',
+    dragKanban: '可拖拽看板',
+    charts: '图表',
+    keyboardChart: '键盘图表',
+    lineChart: '折线图',
+    mixChart: '混合图表',
+    example: '综合实例',
+    nested: '路由嵌套',
+    menu1: '菜单1',
+    'menu1-1': '菜单 1-1',
+    'menu1-2': '菜单 1-2',
+    'menu1-2-1': '菜单 1-2-1',
+    'menu1-2-2': '菜单 1-2-2',
+    'menu1-3': '菜单 1-3',
+    menu2: '菜单 2',
+    Table: 'Table',
+    dynamicTable: '动态 Table',
+    dragTable: '拖拽 Table',
+    inlineEditTable: 'Table 内编辑',
+    complexTable: '综合 Table',
+    tab: 'Tab',
+    form: '表单',
+    createArticle: '创建文章',
+    editArticle: '编辑文章',
+    articleList: '文章列表',
+    errorPages: '错误页面',
+    page401: '401',
+    page404: '404',
+    errorLog: '错误日志',
+    excel: 'Excel',
+    exportExcel: '导出 Excel',
+    selectExcel: '导出 已选择项',
+    mergeHeader: '导出 多级表头',
+    uploadExcel: '上传 Excel',
+    zip: 'Zip',
+    pdf: 'PDF',
+    exportZip: 'Export Zip',
+    theme: '换肤',
+    clipboardDemo: 'Clipboard',
+    i18n: '国际化',
+    externalLink: '外链',
+    profile: '个人中心'
+  },
+  navbar: {
+    dashboard: '首页',
+    shippingAddress: '收货地址',
+    logOut: '退出登录',
+    profile: '个人中心',
+    theme: '换肤',
+    size: '布局大小',
+    visitPreviousVersion: '进入旧版'
+  },
+  menu: {
+    // 一级菜单
+    dashboard: '首页',
+    shoppingMall: '商城管理',
+    memberManagement: '会员管理',
+    networkChart: '会员网络',
+    bonusManagement: '奖金管理',
+    articleManagement: '文章管理',
+    setting: '个人中心',
+    // 二级菜单/接口-dashboard
+    monthBonus: '月奖',
+    // 二级菜单/接口-shoppingMall
+    repeatPurchase: '复消',
+    ownOrder: '我的订单',
+    carFundProducts: '车奖商品',
+    villaFundProducts: '房奖商品',
+    welcomePack: '会员报单',
+    memberRepeatPurchase: '会员复消',
+    welcomePackList: '报单列表',
+    memberUpgrade: '会员升级',
+    memberOrder: '会员订单',
+    reconsume: '复消商品',
+    orderList: '订单列表',
+    brandAmbassador: 'BA会员',
+    BAOrderList: 'BA订单',
+    // 二级菜单/接口-memberManagement
+    personalInfo: '个人信息',
+    resetPassword: '重设密码',
+    // 二级菜单/接口-networkChart
+    placementNetwork: '安置网络',
+    placementNetworkEx: '安置网络Ex',
+    sponsorNetwork: '推荐网络',
+    sponsorNetworkEx: '推荐网络Ex',
+    brandAmbassadorList: 'BA会员',
+    // 二级菜单/接口-bonusManagement
+    myAccount: '我的账户',
+    myBonus: '我的奖金',
+    teamInquiry: '团队查询',
+    historicalCumulativeBonus: '历史累积奖金',
+    withdrawalDetails: '提现明细',
+    applyWithdraw: '申请提现',
+    rechargeDetails: '充值明细',
+    applyRecharge: '申请充值',
+    transferDetails: '转账明细',
+    applyTransfer: '申请转账',
+    // 二级菜单/接口-articleManagement
+    systemNotification: '系统通知',
+    // 二级菜单/接口-setting
+    shippingAddress: '收货地址'
+  },
+  login: {
+    title: '欢迎',
+    logIn: '登录',
+    username: '账号',
+    password: '密码',
+    any: '随便填',
+    thirdparty: '第三方登录',
+    thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!',
+    verifyCode: '验证码'
+  },
+  documentation: {
+    documentation: '文档',
+    github: 'Github 地址'
+  },
+  permission: {
+    addRole: '新增角色',
+    editPermission: '编辑权限',
+    roles: '你的权限',
+    switchRoles: '切换权限',
+    tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
+    delete: '删除',
+    confirm: '确定',
+    cancel: '取消'
+  },
+  guide: {
+    description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于',
+    button: '打开引导'
+  },
+  components: {
+    documentation: '文档',
+    tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见',
+    dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone',
+    stickyTips: '当页面滚动到预设的位置会吸附在顶部',
+    backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮',
+    backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素',
+    imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。'
+  },
+  table: {
+    dynamicTips1: '固定表头, 按照表头顺序排序',
+    dynamicTips2: '不固定表头, 按照点击顺序排序',
+    dragTips1: '默认顺序',
+    dragTips2: '拖拽后顺序',
+    title: '标题',
+    importance: '重要性',
+    type: '类型',
+    remark: '点评',
+    search: '搜索',
+    add: '添加',
+    export: '导出',
+    reviewer: '审核人',
+    id: '序号',
+    date: '时间',
+    author: '作者',
+    readings: '阅读数',
+    status: '状态',
+    actions: '操作',
+    edit: '编辑',
+    publish: '发布',
+    draft: '草稿',
+    delete: '删除',
+    cancel: '取 消',
+    confirm: '确 定'
+  },
+  example: {
+    warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见'
+  },
+  errorLog: {
+    tips: '请点击右上角bug小图标',
+    description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。',
+    documentation: '文档介绍'
+  },
+  excel: {
+    export: '导出',
+    selectedExport: '导出已选择项',
+    placeholder: '请输入文件名(默认excel-list)'
+  },
+  zip: {
+    export: '导出',
+    placeholder: '请输入文件名(默认file)'
+  },
+  pdf: {
+    tips: '这里使用   window.print() 来实现下载pdf的功能'
+  },
+  theme: {
+    change: '换肤',
+    documentation: '换肤文档',
+    tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。'
+  },
+  tagsView: {
+    refresh: '刷新',
+    close: '关闭',
+    closeOthers: '关闭其它',
+    closeAll: '关闭所有'
+  },
+  settings: {
+    title: '系统布局配置',
+    theme: '主题色',
+    tagsView: '开启 Tags-View',
+    fixedHeader: '固定 Header',
+    sidebarLogo: '侧边栏 Logo'
+  },
+  empLevels: {
+    // 级别配置
+    '67BE1C6C21F81B32E055736AECE8644D': "No Rank",
+    '67BE6A4D03C52288E055736AECE8644D': '1 Star Director',
+    '67BE6EA2070D22EBE055736AECE8644D': '2 Star Director',
+    '67BE742A336F2370E055736AECE8644D': '3 Star Director',
+    '67BE805032C22492E055736AECE8644D': 'Diamond',
+    '67BE805032C22492E066736AECE8644D': '2 Star Diamond',
+    '67BE805032C22492E077736AECE8644D': '3 Star Diamond'
+  },
+  crownLevels: {
+    // 级别配置
+    'DCBEDD8E0EAD3DF59D81CCC0C2ACAEFF': '无星级',
+    'E0B75B89C94F35EF8EE0054FA34B759C': '1星皇冠',
+    '7FEBE5DE95D530578915F4072E7CD842': '2星皇冠',
+    '391691E01CD5373F8D23F01FAD750222': '3星皇冠',
+    '8ACAEA736F5331B79283C895F36084E5': '4星皇冠',
+    'CE46B39D07633217AA5711438649D1D6': '5星皇冠',
+    '24396B85E74A3005947F1F90EBA5F5CF': '6星皇冠',
+    '8C253968EB6F3F3FA5BE84F63136FFFA': '7星皇冠'
+  },
+  decLvs: {
+    // 等级配置
+    '67ABC6AO8YTK2LN0E055736AECE8644D': '无级别',
+    '67ABCCE20A9F5553E055736AECE8677A': '银卡',
+    '67ABCE0ECE705575E055736AECE8677C': '金卡'
+  },
+  eliteLevels: {
+    // 等级配置
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF7C': 'Super Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF7V': 'Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8MF8V': 'Pro Elite',
+    'N0RI23JKCP4OBLZ6GAXYWH9D1QS8NA7V': 'NA',
+  },
+  dashboard: {
+    highestDirector: '最高荣衔级别',
+    highestCrown: '最高皇冠星级',
+    memberLevel: '会员级别',
+    payCycle: '当前业绩期',
+    eliteLevel: 'Elite 级别',
+    remainBv: '剩余PV',
+    activeDeadline: '活跃日期截止',
+    more: '更多',
+    articleNotification: '系统通知'
+  },
+  currency: {
+    unit: '奈拉',
+    sign: '₦',
+    naira: 'NGN'
+  },
+  common: {
+    save: '保存',
+    modify: '修改',
+    submit: '提交',
+    delete: '删除',
+    edit: '编辑',
+    action: '操作',
+    yes: '是',
+    no: '否',
+    view: '查看',
+    select: '查询',
+    reset: '清空',
+    startDate: '开始时间',
+    endDate: '结束时间',
+    deleteTips: '确认删除所选数据?',
+    hint: '提示',
+    confirm: '确定',
+    cancel: '取消',
+    successfully: '成功',
+    close: '关闭',
+    note: '备注',
+    awaitData: '正在获取数据,请稍后',
+    switchLanguageHints: '语言切换成功',
+    websiteTitle: '会员管理系统',
+    uploadHints: '正在上传,请稍后。请勿关闭窗口!',
+    canNotBeBlank: '不能为空',
+    require: '必须填写',
+    language: '语言',
+    noData: '暂无数据'
+  },
+  shop: {
+    product: '商品',
+    productCode: '编号',
+    productName: '名称',
+    productPrice: '单价',
+    productPicture: '图片',
+    productBV: 'BV',
+    qty: '数量',
+    taxRate: '税率',
+    taxAmount: '税额',
+    totalTaxAmount: '合计税额',
+    totalPrice: '总价',
+    totalBV: '合计BV',
+    orderCode: '订单编号',
+    orderType: '订单类型',
+    amount: '金额',
+    decCode: '报单编号',
+    memberCode: '会员编号',
+    memberName: '会员姓名',
+    recipientName: '收货人',
+    phoneNumber: '电话',
+    shippingAddress: '收货地址',
+    shipping: '收货方式',
+    payment: '支付方式',
+    createdTime: '下单时间',
+    payTime: '支付时间',
+    payStatus: '支付状态',
+    action: '操作',
+    download: '下载',
+    sponsorCode: '接点人编号',
+    inventory: '库存',
+    checkOut: '结算',
+    unPaid: '待支付',
+    paid: '已支付',
+    goBack: '返回',
+    goPay: '支付',
+    orderDetail: '订单详情',
+    chooseTips: '请选择商品',
+    confirmClose: '确定要关闭页面吗?',
+    inputPasswordTips: '请输入支付密码',
+    selfPickUp: '自提',
+    delivery: '收货地址',
+    selectAddress: '收货地址',
+    selectPayment: '支付方式',
+    freight: '运费',
+    paidAmount: '实付金额',
+    productsSettlement: '商品结算',
+    total: '合计',
+    totalOrders: '订单合计',
+    accountBalance: '账户余额',
+    balanceNotAllow: '不足,无法购买商品',
+    paymentError: '支付方式或账户类型错误',
+    successOrderTips: '订单支付成功',
+    paymentMethod: '支付方式',
+    customerInfo: '会员信息',
+    reconsumeUserCode: '复消用户编号',
+    mobile: '手机号',
+    province: '收货地址',
+    lgaName: '行政区',
+    cityName: '城市',
+    address: '详细地址',
+    memberNotFound: '找不到这个用户',
+    declarationCenterNumber: '报单中心编号',
+    country: '国家',
+    paymentCurrency: '支付币种',
+    salesPrice: 'DP',
+    marketPrice: 'RP',
+      declarationCenterNumberTips: '请输入报单中心编号'
+  },
+  user: {
+    email: '电子邮箱',
+    accountInformation: '账号信息',
+    newMemberCode: '会员编号',
+    selectWelcomePack: '报单方式',
+    sponsorCode: '报单中心编号',
+    payInfo: '支付信息',
+    memberInformation: '会员信息',
+    enterMemberCode: '请输入会员编号',
+    welcomePackWay: '报单方式',
+    normal: '会员报单',
+    BAUpgrade: 'BA会员升级',
+    entryLevel: '报单级别',
+    selectEntryLevel: '请选择报单级别',
+    stockistCode: '报单中心编号',
+    selectCountry: '请选择国家',
+    selectLanguage: '请选择语言',
+    recommenderName: '推荐人编号',
+    recommenderActualName: '实际推荐人编号',
+  },
+
+  atlas: {
+    networkInformation: '网络信息',
+    placementCode: '安置人编号',
+    placementTree: '安置区位',
+    left: '左区',
+    right: '右区',
+    placementAutoLeft: '自动安置在左侧',
+    placementAutoRight: '自动安置在右侧',
+    topMember: '顶级会员',
+    spreadDepth: '展开深度',
+    periodNumber: '期数',
+    numberLayers: '层数',
+    highest: '最高',
+    memberCode: '会员编号',
+    name: '姓名',
+    level: '级别',
+    location: '区位'
+  },
+
+  config: {
+    consignee: '收货人',
+    detailedAddress: '详细地址',
+    city: '城市',
+    localGovernmentArea: '区域',
+    state: '地区',
+    default: '默认地址',
+    createAddress: '添加地址',
+    editAddress: '修改地址'
+  },
+  profile: {
+    personalInformation: '个人资料',
+    account: '账户',
+    loginPassword: '登录密码',
+    paymentPassword: '支付密码',
+    originalPassword: '原密码',
+    newPassword: '新密码',
+    confirmPassword: '重复新密码',
+    currentPayCycle: '结算周期',
+    currentSystemTime: '系统时间',
+    memberJoinTime: '加入时间',
+    memberLevel: '会员等级',
+    highestDirector: '最高荣耀等级',
+    highestCrown: '最高皇冠星级',
+    eliteLevel: 'Elite 级别',
+    latestDirector: '最新管理星级',
+    latestCrown: '最新皇冠星级',
+    joiningPeriod: '加入期数',
+    joiningDate: '加入时间',
+    whetherUpgrade: '是否已升级',
+    upgradeWay: '升级方式',
+    toUpgradeLevel: '升级级别',
+    selectLevel: '请选择级别',
+    topUpBV: '升级补差业绩',
+    upgradePurchaseProduct: '升级购买商品',
+    loginPasswordSuccessTips: '登录密码已修改成功',
+    paymentPasswordSuccessTips: '支付密码已修改成功',
+    enterLoginPassword: '请输入登录密码',
+    enterPaymentPassword: '请支付登录密码'
+  },
+  article: {
+    title: '标题',
+    createTime: '发布时间',
+    category: '类型',
+    systemNotification: '系统通知'
+  },
+  bonus: {
+    payCycle: '期数',
+    welcomeBonus: '迎新奖',
+    teamBonus: '绩效奖',
+    directorBonus: '管理奖',
+    quarterlyBonus: '季度分红',
+    stockistCommission: '服务中心',
+    actualBonus: '实发奖金',
+    totalBonus: '奖金合计',
+    leftNewlyIncreasedPerformance: '左市场新增',
+    rightNewlyIncreasedPerformance: '右市场新增',
+    leftSurplusPerformance: '左市场结余',
+    rightSurplusPerformance: '右市场结余',
+    periodBonus: '第 %s 期奖金',
+    viewRecord: '查看流水',
+    bonusFlowTitle: '%s交易记录',
+    transTime: '交易时间',
+    expiredTime: '过期时间',
+    transType: '交易类型',
+    preTransactionBalance: '交易前余额',
+    transAmount: '交易额',
+    postTransactionBalance: '交易后余额',
+    remark: '备注',
+    whetherActive: '是否活跃',
+    directorPGSPerformance: '管理奖个人小组业绩',
+    personalDetails: '个人情况',
+    status: '状态',
+    personalBV: '个人业绩',
+    PGS: '累计业绩',
+    teamDetails: '团队情况',
+    latestCalculationTime: '最新计算时间',
+    totalBV: '合计',
+    eliteBonus: 'Elite奖金',
+    proEliteBonus: 'Pro Elite奖金',
+    superEliteBonus: 'Super Elite奖金',
+    stockistBonus: '店铺奖',
+    leaderShipBonus: 'LeaderShip奖金',
+    carBonus: '车奖',
+    userPerformanceBonus: '绩效奖金',
+    No:'编号',
+    amount: '金额',
+    originalAmount: '原始金额'
+  },
+  finance: {
+    applyTransfer: '转账',
+    transferOutAccountHint: '请选择转出账户',
+    transferInAccountHint: '请选择转入账户',
+    receiveMemberCodeHint: '请输入接收会员编号',
+    receiveMemberNameHint: '请输入接收会员姓名',
+    transferAccounts: '转出账户',
+    receivingMemberCode: '接收会员编号',
+    receivingMemberName: '接收会员姓名',
+    transferIntoAccount: '转入账户',
+    transferAmount: '转账金额',
+    serviceCharge: '手续费',
+    actualAmountTransferredInto: '实际入账金额',
+    transferTime: '转账时间',
+    remark: '备注',
+    messageApplyTransfer: '确定要发起转账吗?',
+    selectTransferType: '请选择转账类型',
+    transferType: '转账类型',
+    currentAvailableBonus: '当前可用奖金',
+    currentAvailableEcoin: '当前可用余额',
+    currentTransferRatio: '当前转账比例',
+    maximumTransferAmount: '最大转账金额',
+    lessTransferHint: '每次转账不得少于 %s',
+    transferNotAllow: '不允许向自己转账',
+    memberCode: '转入会员编号',
+    memberName: '会员姓名',
+    successTips: '转账成功',
+    enterPasswordTips: '请输入支付密码',
+    executing: '执行中...',
+    recharge: '充值',
+    createdTime: '转账时间',
+    rechargeAmount: '充值金额',
+    rechargeStatus: '充值状态',
+    bankName: '汇款银行',
+    bankAccount: '汇款账号',
+    printVoucher: '充值凭证',
+    uploadVoucher: '上传',
+    viewVoucher: '查看',
+    bankInformation: '银行信息',
+    selectBank: '请选择开户行',
+    accountName: '开户支行',
+    uploadEdit: '编辑',
+    paymentReference: '汇款账号',
+  },
+  notificationProps: {
+    title: '📢 系统更新',
+    description: '检测到系统更新,请刷新页面',
+    confirmButtonText: '刷新',
+    cancelButtonText: '放弃'
+  }
+}

+ 212 - 184
src/layout/components/Navbar.vue

@@ -1,184 +1,212 @@
-<template>
-  <div class="navbar">
-    <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
-
-    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
-
-    <div class="right-menu">
-      <template v-if="device!=='mobile'">
-<!--        <search id="header-search" class="right-menu-item" />-->
-
-<!--        <error-log class="errLog-container right-menu-item hover-effect" />-->
-
-        <screenfull id="screenfull" class="right-menu-item hover-effect" />
-
-        <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
-          <size-select id="size-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <lang-select class="right-menu-item hover-effect" />
-
-      </template>
-
-      <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
-        <div class="avatar-wrapper">
-          <img src="@/assets/user_images/avatar.png" class="user-avatar" alt="">
-          <i class="el-icon-caret-bottom" />
-        </div>
-        <el-dropdown-menu slot="dropdown">
-					<router-link to="/">
-						<el-dropdown-item>
-							{{ $t('navbar.dashboard') }}
-						</el-dropdown-item>
-					</router-link>
-          <router-link to="/profile/index">
-            <el-dropdown-item>
-              {{ $t('navbar.profile') }}
-            </el-dropdown-item>
-          </router-link>
-					<router-link to="/config/receive-address-list">
-						<el-dropdown-item>
-							{{ $t('navbar.shippingAddress') }}
-						</el-dropdown-item>
-					</router-link>
-					<el-dropdown-item>
-						<a target="_blank" :href="visitWebsite">{{ $t('navbar.visitPreviousVersion') }}</a>
-					</el-dropdown-item>
-          <el-dropdown-item divided @click.native="logout">
-            <span style="display:block;">{{ $t('navbar.logOut') }}</span>
-          </el-dropdown-item>
-        </el-dropdown-menu>
-      </el-dropdown>
-    </div>
-  </div>
-</template>
-
-<script>
-import { mapGetters } from 'vuex'
-import Breadcrumb from '@/components/Breadcrumb'
-import Hamburger from '@/components/Hamburger'
-import ErrorLog from '@/components/ErrorLog'
-import Screenfull from '@/components/Screenfull'
-import SizeSelect from '@/components/SizeSelect'
-import LangSelect from '@/components/LangSelect'
-import Search from '@/components/HeaderSearch'
-import tool from "@/utils/tool";
-import usersInfo from "@/utils/usersInfo";
-import {getScreenWidth} from "@/utils";
-
-export default {
-  components: {
-    Breadcrumb,
-    Hamburger,
-    ErrorLog,
-    Screenfull,
-    SizeSelect,
-    LangSelect,
-    Search
-  },
-	data() {
-		return {
-			visitWebsite: process.env.NODE_ENV === 'production' ? 'https://ngds.elken.com' : 'http://16.163.228.151:8035',
-		}
-	},
-  computed: {
-    ...mapGetters([
-      'sidebar',
-      'device'
-    ])
-  },
-  methods: {
-    toggleSideBar() {
-      this.$store.dispatch('app/toggleSideBar')
-    },
-    async logout() {
-      await this.$store.dispatch('user/logout')
-      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
-    },
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.navbar {
-  height: 50px;
-  overflow: hidden;
-  position: relative;
-  background: #fff;
-  box-shadow: 0 1px 4px rgba(0,21,41,.08);
-
-  .hamburger-container {
-    line-height: 46px;
-    height: 100%;
-    float: left;
-    cursor: pointer;
-    transition: background .3s;
-    -webkit-tap-highlight-color:transparent;
-
-    &:hover {
-      background: rgba(0, 0, 0, .025)
-    }
-  }
-
-  .breadcrumb-container {
-    float: left;
-  }
-
-  .errLog-container {
-    display: inline-block;
-    vertical-align: top;
-  }
-
-  .right-menu {
-    float: right;
-    height: 100%;
-    line-height: 50px;
-
-    &:focus {
-      outline: none;
-    }
-
-    .right-menu-item {
-      display: inline-block;
-      padding: 0 8px;
-      height: 100%;
-      font-size: 18px;
-      color: #5a5e66;
-      vertical-align: text-bottom;
-
-      &.hover-effect {
-        cursor: pointer;
-        transition: background .3s;
-
-        &:hover {
-          background: rgba(0, 0, 0, .025)
-        }
-      }
-    }
-
-    .avatar-container {
-      margin-right: 30px;
-
-      .avatar-wrapper {
-        margin-top: 5px;
-        position: relative;
-
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
-        }
-
-        .el-icon-caret-bottom {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
-          font-size: 12px;
-        }
-      }
-    }
-  }
-}
-</style>
+<template>
+  <div class="navbar">
+    <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
+
+    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
+
+    <div class="right-menu">
+      <template v-if="device!=='mobile'">
+        <!--        <search id="header-search" class="right-menu-item" />-->
+
+        <!--        <error-log class="errLog-container right-menu-item hover-effect" />-->
+
+        <screenfull id="screenfull" class="right-menu-item hover-effect" />
+
+        <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
+          <size-select id="size-select" class="right-menu-item hover-effect" />
+        </el-tooltip>
+
+      </template>
+      <lang-select class="right-menu-item hover-effect" />
+
+      <el-dropdown :class="device == 'mobile'? 'avatar-container_m' :'avatar-container'" class=" right-menu-item hover-effect" trigger="click">
+        <div class="avatar-wrapper">
+          <img src="@/assets/user_images/avatar.png" class="user-avatar" alt="">
+          <i v-if="device!=='mobile'" class="el-icon-caret-bottom" />
+        </div>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item>
+            {{ userName }}
+          </el-dropdown-item>
+          <!-- <router-link to="/">
+						<el-dropdown-item>
+							{{ $t('navbar.dashboard') }}
+						</el-dropdown-item>
+					</router-link> -->
+          <!-- <router-link to="/profile/index">
+            <el-dropdown-item>
+              {{ $t('navbar.profile') }}
+            </el-dropdown-item>
+          </router-link>
+					<router-link to="/config/receive-address-list">
+						<el-dropdown-item>
+							{{ $t('navbar.shippingAddress') }}
+						</el-dropdown-item>
+					</router-link> -->
+          <!-- <el-dropdown-item>
+						<a target="_blank" :href="visitWebsite">{{ $t('navbar.visitPreviousVersion') }}</a>
+					</el-dropdown-item> -->
+          <el-dropdown-item divided @click.native="logout">
+            <span style="display:block;">{{ $t('navbar.logOut') }}</span>
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+  </div>
+</template>
+
+<script>
+import Breadcrumb from '@/components/Breadcrumb'
+import ErrorLog from '@/components/ErrorLog'
+import Hamburger from '@/components/Hamburger'
+import Search from '@/components/HeaderSearch'
+import LangSelect from '@/components/LangSelect'
+import Screenfull from '@/components/Screenfull'
+import SizeSelect from '@/components/SizeSelect'
+import { mapGetters } from 'vuex'
+
+export default {
+  components: {
+    Breadcrumb,
+    Hamburger,
+    ErrorLog,
+    Screenfull,
+    SizeSelect,
+    LangSelect,
+    Search
+  },
+  data() {
+    return {
+      visitWebsite: process.env.NODE_ENV === 'production' ? 'http://ngds.elken.com:8010/' : 'http://16.163.228.151:8035',
+      userName: ''
+    }
+  },
+  computed: {
+    ...mapGetters([
+      'sidebar',
+      'device'
+    ])
+  },
+  mounted() {
+    this.getUserInfo()
+  },
+  methods: {
+    toggleSideBar() {
+      this.$store.dispatch('app/toggleSideBar')
+    },
+    async logout() {
+      await this.$store.dispatch('user/logout')
+      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
+    },
+    getUserInfo() {
+      this.userName = window.localStorage.getItem('userName')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.navbar {
+  height: 50px;
+  overflow: hidden;
+  position: relative;
+  background: #fff;
+  box-shadow: 0 1px 4px rgba(0,21,41,.08);
+
+  .hamburger-container {
+    line-height: 46px;
+    height: 100%;
+    float: left;
+    cursor: pointer;
+    transition: background .3s;
+    -webkit-tap-highlight-color:transparent;
+
+    &:hover {
+      background: rgba(0, 0, 0, .025)
+    }
+  }
+
+  .breadcrumb-container {
+    float: left;
+  }
+
+  .errLog-container {
+    display: inline-block;
+    vertical-align: top;
+  }
+
+  .right-menu {
+    float: right;
+    height: 100%;
+    line-height: 50px;
+
+    &:focus {
+      outline: none;
+    }
+
+    .right-menu-item {
+      display: inline-block;
+      padding: 0 8px;
+      height: 100%;
+      font-size: 18px;
+      color: #5a5e66;
+      vertical-align: text-bottom;
+
+      &.hover-effect {
+        cursor: pointer;
+        transition: background .3s;
+
+        &:hover {
+          background: rgba(0, 0, 0, .025)
+        }
+      }
+    }
+
+    .avatar-container_m{
+      margin-right: 3px;
+      .avatar-wrapper {
+        margin-top: 5px;
+        position: relative;
+
+        .user-avatar {
+          cursor: pointer;
+          width: 40px;
+          height: 40px;
+          border-radius: 10px;
+        }
+
+        .el-icon-caret-bottom {
+          cursor: pointer;
+          position: absolute;
+          right: -20px;
+          top: 25px;
+          font-size: 12px;
+        }
+      }
+    }
+    .avatar-container {
+      margin-right: 30px;
+
+      .avatar-wrapper {
+        margin-top: 5px;
+        position: relative;
+
+        .user-avatar {
+          cursor: pointer;
+          width: 40px;
+          height: 40px;
+          border-radius: 10px;
+        }
+
+        .el-icon-caret-bottom {
+          cursor: pointer;
+          position: absolute;
+          right: -20px;
+          top: 25px;
+          font-size: 12px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 3 - 3
src/layout/components/Sidebar/SidebarItem.vue

@@ -25,12 +25,12 @@
 </template>
 
 <script>
-import path from 'path'
-import { generateTitle,generateTitleWiki } from '@/utils/i18n'
+import { generateTitle, generateTitleWiki } from '@/utils/i18n'
 import { isExternal } from '@/utils/validate'
+import path from 'path'
+import FixiOSBug from './FixiOSBug'
 import Item from './Item'
 import AppLink from './Link'
-import FixiOSBug from './FixiOSBug'
 
 export default {
   name: 'SidebarItem',

+ 1 - 1
src/layout/components/Sidebar/index.vue

@@ -30,7 +30,7 @@ export default {
   components: { SidebarItem, Logo },
   data() {
     return {
-     
+
     }
   },
   created(){

+ 105 - 105
src/layout/index.vue

@@ -1,105 +1,105 @@
-<template>
-  <div :class="classObj" class="app-wrapper">
-    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
-    <sidebar class="sidebar-container" />
-    <div :class="{hasTagsView:needTagsView}" class="main-container">
-      <div :class="{'fixed-header':fixedHeader}">
-        <navbar />
-      </div>
-      <app-main />
-      <right-panel v-if="showSettings">
-        <settings />
-      </right-panel>
-    </div>
-  </div>
-</template>
-
-<script>
-import RightPanel from '@/components/RightPanel'
-import { AppMain, Navbar, Settings, Sidebar } from './components'
-import ResizeMixin from './mixin/ResizeHandler'
-import { mapState } from 'vuex'
-import initRegion from "@/utils/region"
-
-export default {
-  name: 'Layout',
-	beforeCreate() {
-		// 获取地区信息
-		initRegion(this)
-	},
-  components: {
-    AppMain,
-    Navbar,
-    RightPanel,
-    Settings,
-    Sidebar,
-  },
-  mixins: [ResizeMixin],
-  computed: {
-    ...mapState({
-      sidebar: state => state.app.sidebar,
-      device: state => state.app.device,
-      showSettings: state => state.settings.showSettings,
-      needTagsView: state => state.settings.tagsView,
-      fixedHeader: state => state.settings.fixedHeader
-    }),
-    classObj() {
-      return {
-        hideSidebar: !this.sidebar.opened,
-        openSidebar: this.sidebar.opened,
-        withoutAnimation: this.sidebar.withoutAnimation,
-        mobile: this.device === 'mobile'
-      }
-    }
-  },
-  methods: {
-    handleClickOutside() {
-      this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-  @import "~@/styles/mixin.scss";
-  @import "~@/styles/variables.scss";
-
-  .app-wrapper {
-    @include clearfix;
-    position: relative;
-    height: 100%;
-    width: 100%;
-
-    &.mobile.openSidebar {
-      position: fixed;
-      top: 0;
-    }
-  }
-
-  .drawer-bg {
-    background: #000;
-    opacity: 0.3;
-    width: 100%;
-    top: 0;
-    height: 100%;
-    position: absolute;
-    z-index: 999;
-  }
-
-  .fixed-header {
-    position: fixed;
-    top: 0;
-    right: 0;
-    z-index: 9;
-    width: calc(100% - #{$sideBarWidth});
-    transition: width 0.28s;
-  }
-
-  .hideSidebar .fixed-header {
-    width: calc(100% - 54px)
-  }
-
-  .mobile .fixed-header {
-    width: 100%;
-  }
-</style>
+<template>
+  <div :class="classObj" class="app-wrapper">
+    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
+    <sidebar class="sidebar-container" />
+    <div :class="{hasTagsView:needTagsView}" class="main-container">
+      <div :class="{'fixed-header':fixedHeader}">
+        <navbar />
+      </div>
+      <app-main />
+      <right-panel v-if="showSettings">
+        <settings />
+      </right-panel>
+    </div>
+  </div>
+</template>
+
+<script>
+import RightPanel from '@/components/RightPanel'
+import { AppMain, Navbar, Settings, Sidebar } from './components'
+import ResizeMixin from './mixin/ResizeHandler'
+import { mapState } from 'vuex'
+import initRegion from '@/utils/region'
+
+export default {
+  name: 'Layout',
+  components: {
+    AppMain,
+    Navbar,
+    RightPanel,
+    Settings,
+    Sidebar
+  },
+  mixins: [ResizeMixin],
+  computed: {
+    ...mapState({
+      sidebar: state => state.app.sidebar,
+      device: state => state.app.device,
+      showSettings: state => state.settings.showSettings,
+      needTagsView: state => state.settings.tagsView,
+      fixedHeader: state => state.settings.fixedHeader
+    }),
+    classObj() {
+      return {
+        hideSidebar: !this.sidebar.opened,
+        openSidebar: this.sidebar.opened,
+        withoutAnimation: this.sidebar.withoutAnimation,
+        mobile: this.device === 'mobile'
+      }
+    }
+  },
+  beforeCreate() {
+    // 获取地区信息
+    initRegion(this)
+  },
+  methods: {
+    handleClickOutside() {
+      this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  @import "~@/styles/mixin.scss";
+  @import "~@/styles/variables.scss";
+
+  .app-wrapper {
+    @include clearfix;
+    position: relative;
+    height: 100%;
+    width: 100%;
+
+    &.mobile.openSidebar {
+      position: fixed;
+      top: 0;
+    }
+  }
+
+  .drawer-bg {
+    background: #000;
+    opacity: 0.3;
+    width: 100%;
+    top: 0;
+    height: 100%;
+    position: absolute;
+    z-index: 999;
+  }
+
+  .fixed-header {
+    position: fixed;
+    top: 0;
+    right: 0;
+    z-index: 9;
+    width: calc(100% - #{$sideBarWidth});
+    transition: width 0.28s;
+  }
+
+  .hideSidebar .fixed-header {
+    width: calc(100% - 54px)
+  }
+
+  .mobile .fixed-header {
+    width: 100%;
+  }
+</style>

+ 58 - 58
src/main.js

@@ -1,58 +1,58 @@
-import Vue from 'vue'
-
-import Cookies from 'js-cookie'
-
-import 'normalize.css/normalize.css' // a modern alternative to CSS resets
-
-import Element from 'element-ui'
-import './styles/element-variables.scss'
-
-import moment from 'moment'
-
-import '@/styles/index.scss' // global css
-
-import App from './App'
-import store from './store'
-import router from './router'
-
-import i18n from './lang' // internationalization
-import './icons' // icon
-import './permission' // permission control
-import './utils/error-log' // error log
-
-import * as filters from './filters' // global filters
-
-/**
- * If you don't want to use mock-server
- * you want to use MockJs for mock api
- * you can execute: mockXHR()
- *
- * Currently MockJs will be used in the production environment,
- * please remove it before going online ! ! !
-
-if (process.env.NODE_ENV === 'production') {
-  const { mockXHR } = require('../mock')
-  mockXHR()
-}
-*/
-
-Vue.use(Element, {
-  size: Cookies.get('size') || 'medium', // set element-ui default size
-  i18n: (key, value) => i18n.t(key, value)
-})
-
-// register global utility filters
-Object.keys(filters).forEach(key => {
-  Vue.filter(key, filters[key])
-})
-
-Vue.config.productionTip = false
-Vue.prototype.$moment = moment
-
-new Vue({
-  el: '#app',
-  router,
-  store,
-  i18n,
-  render: h => h(App)
-})
+import Vue from 'vue'
+
+import Cookies from 'js-cookie'
+
+import 'normalize.css/normalize.css' // a modern alternative to CSS resets
+
+import Element from 'element-ui'
+import './styles/element-variables.scss'
+
+import moment from 'moment'
+
+import '@/styles/index.scss' // global css
+
+import App from './App'
+import store from './store'
+import router from './router'
+
+import i18n from './lang' // internationalization
+import './icons' // icon
+import './permission' // permission control
+import './utils/error-log' // error log
+
+import * as filters from './filters' // global filters
+
+/**
+ * If you don't want to use mock-server
+ * you want to use MockJs for mock api
+ * you can execute: mockXHR()
+ *
+ * Currently MockJs will be used in the production environment,
+ * please remove it before going online ! ! !
+
+if (process.env.NODE_ENV === 'production') {
+  const { mockXHR } = require('../mock')
+  mockXHR()
+}
+*/
+
+Vue.use(Element, {
+  size: Cookies.get('size') || 'medium', // set element-ui default size
+  i18n: (key, value) => i18n.t(key, value)
+})
+
+// register global utility filters
+Object.keys(filters).forEach(key => {
+  Vue.filter(key, filters[key])
+})
+
+Vue.config.productionTip = false
+Vue.prototype.$moment = moment
+
+new Vue({
+  el: '#app',
+  router,
+  store,
+  i18n,
+  render: h => h(App)
+})

+ 7 - 9
src/permission.js

@@ -1,12 +1,10 @@
-import router, { selfAddRoutes, resetRouter } from './router'
-import store from './store'
-import { Message } from 'element-ui'
-import NProgress from 'nprogress' // progress bar
-import 'nprogress/nprogress.css' // progress bar style
-import { getToken } from '@/utils/auth' // get token from cookie
 import getPageTitle from '@/utils/get-page-title'
 import usersInfo from '@/utils/usersInfo'
- 
+import NProgress from 'nprogress' // progress bar
+import 'nprogress/nprogress.css' // progress bar style
+import router, { resetRouter } from './router'
+import store from './store'
+
 NProgress.configure({ showSpinner: false }) // NProgress Configuration
 
 const whiteList = ['/login', '/auth-redirect', '/login-by-backend'] // no redirect whitelist
@@ -19,7 +17,7 @@ router.beforeEach(async(to, from, next) => {
   document.title = getPageTitle(to.meta.title)
 
   // determine whether the user has logged in
-  const hasToken = usersInfo.hasLogin() //getToken()
+  const hasToken = usersInfo.hasLogin() // getToken()
   if (hasToken) {
     if (to.path === '/login') {
       // if is logged in, redirect to the home page
@@ -35,7 +33,7 @@ router.beforeEach(async(to, from, next) => {
           // get user info
           // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
           // const { roles } = await store.dispatch('user/getInfo')
-          const { roles } = ['admin'];
+          const { roles } = ['admin']
           resetRouter()
           // generate accessible routes map based on roles
           const accessRoutes = await store.dispatch('permission/generateRoutes', roles)

+ 11 - 11
src/router/index.js

@@ -1,24 +1,24 @@
-import Vue from 'vue'
-import Router from 'vue-router'
+import Vue from 'vue';
+import Router from 'vue-router';
 
 Vue.use(Router)
 
 /* Layout */
-import Layout from '@/layout'
+import Layout from '@/layout';
 
 /* Router Modules */
-import componentsRouter from './modules/components';
-import chartsRouter from './modules/charts';
-import tableRouter from './modules/table';
-import nestedRouter from './modules/nested';
-import shopRouter from '@/router/modules/shop';
-import profileRouter from "@/router/modules/profile";
-import configRouter from "@/router/modules/config";
-import atlasRouter from "@/router/modules/atlas";
 import articleRouter from "@/router/modules/article";
+import atlasRouter from "@/router/modules/atlas";
 import bonusRouter from "@/router/modules/bonus";
+import configRouter from "@/router/modules/config";
 import financeRouter from "@/router/modules/finance";
+import profileRouter from "@/router/modules/profile";
+import shopRouter from '@/router/modules/shop';
 import userRouter from "@/router/modules/user";
+import chartsRouter from './modules/charts';
+import componentsRouter from './modules/components';
+import nestedRouter from './modules/nested';
+import tableRouter from './modules/table';
 
 /**
  * Note: sub-menu only appear when route children.length >= 1

+ 15 - 3
src/router/modules/atlas.js

@@ -7,19 +7,31 @@ const atlasRouter = {
   hidden: true,
   children: [
     {
-      path: 'network',  // 安置网络
+      path: 'network', // 安置网络
       component: () => import('@/views/atlas/placement-network'),
       name: 'placementNetwork',
       meta: { title: 'Placement Network', icon: 'user', noCache: true }
     },
     {
-      path: 'relation',  // 推荐网络
+      path: 'relation', // 推荐网络
       component: () => import('@/views/atlas/sponsor-network'),
       name: 'sponsorNetwork',
       meta: { title: 'Sponsor Network', icon: 'user', noCache: true }
     },
     {
-      path: 'brand-ambassador-list',  // BA会员列表
+      path: 'network-ex', // 安置网络Ex
+      component: () => import('@/views/atlas/placement-network-ex'),
+      name: 'placementNetworkEx',
+      meta: { title: 'Placement Network Ex', icon: 'user', noCache: true }
+    },
+    {
+      path: 'relation-ex', // 推荐网络Ex
+      component: () => import('@/views/atlas/sponsor-network-ex'),
+      name: 'sponsorNetworkEx',
+      meta: { title: 'Sponsor Network Ex', icon: 'user', noCache: true }
+    },
+    {
+      path: 'brand-ambassador-list', // BA会员列表
       component: () => import('@/views/atlas/brand-ambassador-list'),
       name: 'BrandAmbassadorList',
       meta: { title: 'Brand Ambassador List', icon: 'user', noCache: true }

+ 0 - 6
src/router/modules/components.js

@@ -18,12 +18,6 @@ const componentsRouter = {
       name: 'TinymceDemo',
       meta: { title: 'tinymce' }
     },
-    {
-      path: 'markdown',
-      component: () => import('@/views/components-demo/markdown'),
-      name: 'MarkdownDemo',
-      meta: { title: 'markdown' }
-    },
     {
       path: 'json-editor',
       component: () => import('@/views/components-demo/json-editor'),

+ 7 - 1
src/router/modules/config.js

@@ -11,11 +11,17 @@ const configRouter = {
   },
   children: [
     {
-      path: 'receive-address-list',  // 收货地址列表
+      path: 'receive-address-list', // 收货地址列表
       component: () => import('@/views/config/shipping-address-list'),
       name: 'ShippingAddressList',
       meta: { title: 'Shipping Address', icon: 'el-icon-location' }
     },
+    {
+      path: 'profile', // 用户中心
+      component: () => import('@/views/profile/index'),
+      name: 'Profile',
+      meta: { title: 'Personal Info', icon: 'user', noCache: true }
+    }
   ]
 }
 export default configRouter

+ 18 - 6
src/router/modules/shop.js

@@ -13,17 +13,17 @@ const shopRouter = {
     {
       path: 'standard-products', // 普通商品列表
       component: () => import('@/views/shop/standard-products'),
-      name: 'StandardProducts',
-      meta: { title: 'Standard Products', icon: 'el-icon-goods' }
+      name: 'repeatPurchase',
+      meta: { title: 'Repeat Purchase', icon: 'el-icon-goods' }
     },
     {
-      path: 'car-fund-products',  // 车奖商品列表
+      path: 'car-fund-products', // 车奖商品列表
       component: () => import('@/views/shop/car-fund-products'),
       name: 'CarFundProducts',
       meta: { title: 'Car Fund Products', icon: 'el-icon-goods' }
     },
     {
-      path: 'villa-fund-products',  // 房奖商品列表
+      path: 'villa-fund-products', // 房奖商品列表
       component: () => import('@/views/shop/villa-fund-products'),
       name: 'VillaFundProducts',
       meta: { title: 'Villa Fund Products', icon: 'el-icon-goods' }
@@ -35,16 +35,28 @@ const shopRouter = {
       meta: { title: 'Welcome Pack Listing', icon: 'el-icon-goods' }
     },
     {
-      path: 'order-list', // 订单列表
+      path: 'reconsume', // 复消
+      component: () => import('@/views/shop/reconsume'),
+      name: 'memberRepeatPurchase',
+      meta: { title: 'Member Repeat Purchase', icon: 'el-icon-goods' }
+    },
+    {
+      path: 'own-order', // 订单列表
       component: () => import('@/views/shop/order-list'),
       name: 'OrderList',
-      meta: { title: 'Order List', icon: 'el-icon-goods' }
+      meta: { title: 'My Order', icon: 'el-icon-goods' }
     },
     {
       path: 'ba-dec-order-list', // BA报单列表
       component: () => import('@/views/shop/ba-dec-order-list'),
       name: 'BaDecOrderList',
       meta: { title: 'Welcome Listing', icon: 'el-icon-goods' }
+    },
+    {
+      path: 'member-order', // 会员订单
+      component: () => import('@/views/user/member-order'),
+      name: 'memberOrder',
+      meta: { title: 'Member Order', icon: 'user', noCache: true }
     }
   ]
 }

+ 12 - 6
src/router/modules/user.js

@@ -7,23 +7,29 @@ const userRouter = {
   hidden: true,
   children: [
     {
-      path: 'ba-dec',  // 新建BA会员
+      path: 'ba-dec', // 新建BA会员
       component: () => import('@/views/user/brand-ambassador'),
       name: 'brandAmbassador',
       meta: { title: 'Welcome Brand Ambassador', icon: 'user', noCache: true }
     },
     {
-      path: 'upgrade',  // 会员升级
+      path: 'upgrade', // 会员升级
       component: () => import('@/views/user/member-upgrade'),
-      name: 'upgradeManagement',
-      meta: { title: 'Upgrade Management', icon: 'user', noCache: true }
+      name: 'memberUpgrade',
+      meta: { title: 'Member Upgrade', icon: 'user', noCache: true }
     },
     {
-      path: 'dec',  // 会员报单/BA升级
+      path: 'dec', // 会员报单/BA升级
       component: () => import('@/views/user/welcome-pack'),
       name: 'welcomePack',
-      meta: { title: 'Welcome Pack Management', icon: 'user', noCache: true }
+      meta: { title: 'Member Welcome Pack', icon: 'user', noCache: true }
     },
+    {
+      path: 'index', // 用户中心
+      component: () => import('@/views/profile/index'),
+      name: 'Profile',
+      meta: { title: 'Personal Info', icon: 'user', noCache: true }
+    }
   ]
 }
 export default userRouter

+ 2 - 0
src/store/getters.js

@@ -17,5 +17,7 @@ const getters = {
   decLv: state => state.user.decLv,
   empLv: state => state.user.empLv,
   crownLv: state => state.user.crownLv,
+  languageList: state => state.app.languageList,
+  getCountriesList: state => state.settings.countriesList
 }
 export default getters

+ 10 - 2
src/store/modules/app.js

@@ -8,7 +8,8 @@ const state = {
   },
   device: 'desktop',
   language: getLanguage(),
-  size: Cookies.get('size') || 'medium'
+  size: Cookies.get('size') || 'medium',
+  languageList: []
 }
 
 const mutations = {
@@ -36,6 +37,9 @@ const mutations = {
   SET_SIZE: (state, size) => {
     state.size = size
     Cookies.set('size', size)
+  },
+  SET_LANGUAGE_LIST: (state, languageList) => {
+    state.languageList = languageList
   }
 }
 
@@ -54,7 +58,11 @@ const actions = {
   },
   setSize({ commit }, size) {
     commit('SET_SIZE', size)
-  }
+  },
+  setLanguageList({ commit }, languageList) {
+    commit('SET_LANGUAGE_LIST', languageList)
+  },
+
 }
 
 export default {

+ 21 - 2
src/store/modules/settings.js

@@ -1,6 +1,6 @@
 import variables from '@/styles/element-variables.scss'
 import defaultSettings from '@/settings'
-import { getWebSetting, getPageId } from '@/api/setting'
+import { getWebSetting, getPageId, getCountries } from '@/api/setting'
 
 const { showSettings, tagsView, fixedHeader, sidebarLogo, supportPinyinSearch } = defaultSettings
 
@@ -11,7 +11,8 @@ const state = {
   fixedHeader,
   sidebarLogo,
   supportPinyinSearch,
-  title:'默认网站头'
+  title:'默认网站头',
+  countriesList: []
 }
 
 const mutations = {
@@ -23,6 +24,9 @@ const mutations = {
   },
   SET_WEBTITLE: (state , title) => {
     state.title = title
+  },
+  SET_COUNTRIES_LIST: (state, countriesList) => {
+    state.countriesList = countriesList
   }
 }
 
@@ -47,6 +51,21 @@ const actions = {
       })
     })
   },
+  getCountries({ commit }) {
+    return new Promise((resolve, reject) => {
+      getCountries().then(response => {
+        let obj = response
+        let list = []
+        Object.keys(obj).forEach(function(key) {
+          list.push(obj[key])
+        });
+        commit('SET_COUNTRIES_LIST', list)
+        resolve(list)
+      }).catch(error => {
+        reject(error)
+      })
+    })
+  },
 }
 
 export default {

+ 17 - 5
src/store/modules/user.js

@@ -1,7 +1,8 @@
-import {backendQuickLogin, getBaseInfo, getMessageData, getUserInfo, isLoginVerify, login} from '@/api/user'
-import {getToken, removeToken, setToken} from '@/utils/auth'
-import router, {resetRouter} from '@/router'
-import usersInfo from '@/utils/usersInfo'
+import { backendQuickLogin, getBaseInfo, getMessageData, getUserInfo, isLoginVerify, login } from '@/api/user';
+import router, { resetRouter } from '@/router';
+import { getToken, removeToken, setToken } from '@/utils/auth';
+import usersInfo from '@/utils/usersInfo';
+import { Message } from "element-ui";
 
 const state = {
   token: getToken(),
@@ -56,6 +57,12 @@ const actions = {
         commit('SET_INTRODUCTION', 'introduction')
         resolve()
       }).catch(error => {
+        Message({
+          message: error.message,
+          type: 'error',
+          duration: 5 * 1000
+        })
+
         usersInfo.clear()
         reject(error)
       })
@@ -109,7 +116,10 @@ const actions = {
           BANK_NO: ret.BANK_NO,
           MOBILE: ret.MOBILE,
           CREATED_AT: ret.CREATED_AT,
-          REAL_NAME: ret.REAL_NAME
+          REAL_NAME: ret.REAL_NAME,
+          COUNTRY_ID: ret.COUNTRY_ID,
+          ELITE_LV: ret.ELITE_LV,
+          IS_DEC: ret.IS_DEC,
         })
         resolve(response)
       }).catch(error => {
@@ -121,6 +131,8 @@ const actions = {
     return new Promise((resolve, reject) => {
       getBaseInfo({version: 'v2'}).then(response => {
         let ret = response.data
+        // ret.menu[3].child[2].routePath = 'atlas/network-ex'
+        ret.menu[3].child[1].routePath = 'atlas/relation-ex'
         usersInfo.clearBaseInfo()
         usersInfo.setBaseInfo(ret)
         resolve(response)

+ 163 - 147
src/utils/request.js

@@ -1,147 +1,163 @@
-import axios from 'axios'
-import { MessageBox, Message } from 'element-ui'
-import store from '@/store'
-import usersInfo from './usersInfo'
-import tool from './tool'
-
-// create an axios instance
-const service = axios.create({
-  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
-
-  // withCredentials: true, // send cookies when cross-domain requests
-  timeout: 12000 // request timeout
-})
-// request interceptor
-service.interceptors.request.use(
-  config => {
-    // do something before request is sent
-
-    // if (store.getters.token) {
-    //   // let each request carry token
-    //   // ['X-Token'] is a custom headers key
-    //   // please modify it according to the actual situation
-    //   config.headers['X-Token'] = getToken()
-    // }
-    if (usersInfo.accessToken()) {
-      config.headers['Authorization'] = process.env.VUE_APP_ACCESS_TOKEN_PREFIX + usersInfo.accessToken()
-    }
-    if (usersInfo.accessToken() && usersInfo.accessTokenExpiresIn()
-    && parseInt(usersInfo.accessTokenExpiresIn()) + parseInt(usersInfo.accessTokenUpdateAt()) - 30 > parseInt(tool.getTimestamp())) {
-    } else if(usersInfo.accessToken()) {
-      // 需要先刷新token
-      let refreshToken = usersInfo.refreshToken()
-      let refreshTokenExpiresIn = usersInfo.refreshTokenExpiresIn()
-      let refreshTokenUpdateAt = usersInfo.refreshTokenUpdateAt()
-      if (refreshToken && refreshTokenExpiresIn
-        && parseInt(refreshTokenExpiresIn) - 30 + parseInt(refreshTokenUpdateAt) > parseInt(tool.getTimestamp())) {
-        // 有效,去更新
-        axios.get(`${process.env.VUE_APP_BASE_API}/v1/oauth/refresh-token?refresh-token=${refreshToken}`).then(response => {
-          // 更新本地accessToken
-          usersInfo.accessToken(response.data.accessToken)
-          usersInfo.accessTokenExpiresIn(response.data.accessTokenExpiresIn)
-          usersInfo.accessTokenUpdateAt(response.data.accessTokenUpdateAt)
-          usersInfo.refreshToken(response.data.refreshToken)
-          usersInfo.refreshTokenExpiresIn(response.data.refreshTokenExpiresIn)
-          usersInfo.refreshTokenUpdateAt(response.data.refreshTokenUpdateAt)
-          usersInfo.accessToken()
-
-        }).catch(error => {
-          Message({
-            message: 'accessToken Failed',
-            type: 'error',
-            duration: 5 * 1000
-          })
-          return
-        })
-      } else {
-        //console.log('refreshToken已失效');
-        usersInfo.clear()
-        Message({
-          message: 'refreshToken Invalid',
-          type: 'error',
-          duration: 5 * 1000
-        })
-        return
-      }
-    }
-
-    return config
-  },
-  error => {
-    // do something with request error
-    console.log('请求报错----->',error) // for debug
-    return Promise.reject(error)
-  }
-)
-
-// response interceptor
-service.interceptors.response.use(
-  response => {
-    const responseData = response.data
-    const data = responseData.data
-    if ((responseData.success === false) || (responseData.code && responseData.code !== 200)) {
-      // Message({
-      //   message: responseData.message || 'Error',
-      //   type: 'error',
-      //   duration: 5 * 1000
-      // })
-      return Promise.reject(responseData.message)
-    } else {
-      if (!data) {
-        return { data: responseData }
-      }
-      return data
-    }
-  },
-  err => {
-    if (err && err.response && err.response.data && err.response.data.message) {
-      err.message = err.response.data.message
-    } else if (err && err.response) {
-      switch (err.response.data.status) {
-        case 400:
-          err.message = '请求错误'
-          break
-        case 401:
-          err.message = '未授权,请登录'
-          break
-        case 403:
-          err.message = '拒绝访问'
-          break
-        case 404:
-          err.message = `请求地址出错: ${err.response.data.config.url}`
-          break
-        case 408:
-          err.message = '请求超时'
-          break
-        case 500:
-          err.message = '服务器内部错误'
-          break
-        case 501:
-          err.message = '服务未实现'
-          break
-        case 502:
-          err.message = '网关错误'
-          break
-        case 503:
-          err.message = '服务不可用'
-          break
-        case 504:
-          err.message = '网关超时'
-          break
-        case 505:
-          err.message = 'HTTP版本不受支持'
-          break
-        default:
-      }
-    }
-    // Message({
-    //   message: err.message || 'Error',
-    //   type: 'error',
-    //   duration: 5 * 1000
-    // })
-
-    return Promise.reject(err)
-  }
-)
-
-export default service
+import router from '@/router'
+import axios from 'axios'
+import { Message } from 'element-ui'
+import Cookies from 'js-cookie'
+import tool from './tool'
+import usersInfo from './usersInfo'
+// create an axios instance
+const service = axios.create({
+  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
+
+  // withCredentials: true, // send cookies when cross-domain requests
+  timeout: 12000 // request timeout
+})
+// request interceptor
+service.interceptors.request.use(
+  config => {
+    // do something before request is sent
+
+    // if (store.getters.token) {
+    //   // let each request carry token
+    //   // ['X-Token'] is a custom headers key
+    //   // please modify it according to the actual situation
+    //   config.headers['X-Token'] = getToken()
+    // }
+    if (usersInfo.accessToken()) {
+      config.headers['Authorization'] = process.env.VUE_APP_ACCESS_TOKEN_PREFIX + usersInfo.accessToken()
+    }
+    // 设置语言
+    config.headers['language'] = Cookies.get('language')
+
+    if (usersInfo.accessToken() && usersInfo.accessTokenExpiresIn() &&
+    parseInt(usersInfo.accessTokenExpiresIn()) + parseInt(usersInfo.accessTokenUpdateAt()) - 30 > parseInt(tool.getTimestamp())) {
+    } else if (usersInfo.accessToken()) {
+      // 需要先刷新token
+      const refreshToken = usersInfo.refreshToken()
+      const refreshTokenExpiresIn = usersInfo.refreshTokenExpiresIn()
+      const refreshTokenUpdateAt = usersInfo.refreshTokenUpdateAt()
+      if (refreshToken && refreshTokenExpiresIn &&
+        parseInt(refreshTokenExpiresIn) - 30 + parseInt(refreshTokenUpdateAt) > parseInt(tool.getTimestamp())) {
+        // 有效,去更新
+        axios.get(`${process.env.VUE_APP_BASE_API}/v1/oauth/refresh-token?refresh-token=${refreshToken}`).then(response => {
+          // 更新本地accessToken
+          usersInfo.accessToken(response.data.accessToken)
+          usersInfo.accessTokenExpiresIn(response.data.accessTokenExpiresIn)
+          usersInfo.accessTokenUpdateAt(response.data.accessTokenUpdateAt)
+          usersInfo.refreshToken(response.data.refreshToken)
+          usersInfo.refreshTokenExpiresIn(response.data.refreshTokenExpiresIn)
+          usersInfo.refreshTokenUpdateAt(response.data.refreshTokenUpdateAt)
+          usersInfo.accessToken()
+        }).catch(error => {
+          Message({
+            message: 'accessToken Failed',
+            type: 'error',
+            duration: 5 * 1000
+          })
+          return
+        })
+      } else {
+        // console.log('refreshToken已失效');
+        usersInfo.clear()
+        Message({
+          message: 'refreshToken Invalid',
+          type: 'error',
+          duration: 5 * 1000
+        })
+        return
+      }
+    }
+
+    return config
+  },
+  error => {
+    // do something with request error
+    console.log('请求报错----->', error) // for debug
+    return Promise.reject(error)
+  }
+)
+
+// response interceptor
+service.interceptors.response.use(
+  response => {
+    const responseData = response.data
+    const data = responseData.data
+    if ((responseData.success === false) || (responseData.code && responseData.code !== 200)) {
+      // Message({
+      //   message: responseData.message || 'Error',
+      //   type: 'error',
+      //   duration: 5 * 1000
+      // })
+      return Promise.reject(responseData.message)
+    } else {
+      if (!data) {
+        return { data: responseData }
+      }
+      return data
+    }
+  },
+  err => {
+    if (err && err.response && err.response.data && err.response.data.message) {
+      err.message = err.response.data.message
+    } else if (err && err.response) {
+      switch (err.response.data.status) {
+        case 400:
+          err.message = '请求错误'
+          break
+        case 401:
+          err.message = '未授权,请登录'
+          break
+        case 403:
+          err.message = '拒绝访问'
+          break
+        case 404:
+          err.message = `请求地址出错: ${err.response.data.config.url}`
+          break
+        case 408:
+          err.message = '请求超时'
+          break
+        case 500:
+          err.message = '服务器内部错误'
+          break
+        case 501:
+          err.message = '服务未实现'
+          break
+        case 502:
+          err.message = '网关错误'
+          break
+        case 503:
+          err.message = '服务不可用'
+          break
+        case 504:
+          err.message = '网关超时'
+          break
+        case 505:
+          err.message = 'HTTP版本不受支持'
+          break
+        default:
+      }
+    }
+    if (err.response.data.status == 401) {
+      localStorage.clear()
+      router.replace({
+        path: '/login',
+        query: { redirect: router.currentRoute.fullPath }
+      })
+    }
+    if (err.response.data.status == 403 || err.response.data.status == 400) {
+      Message({
+        message: err.message || 'Error',
+        type: 'error',
+        duration: 3 * 1000
+      })
+    }
+    // Message({
+    //   message: err.message || 'Error',
+    //   type: 'error',
+    //   duration: 5 * 1000
+    // })
+
+    return Promise.reject(err)
+  }
+)
+
+export default service

+ 44 - 0
src/utils/tool.js

@@ -59,6 +59,50 @@ const tool = {
     if (withTime) return Y + M + D + h + m + s
     return Y + M + D
   },
+  convertToNigeriaTime(timestamp) {
+    timestamp = this.normalizeTimestamp(timestamp)
+    const options = {
+      timeZone: 'Africa/Lagos',
+      year: 'numeric',
+      month: '2-digit',
+      day: '2-digit',
+      hour: '2-digit',
+      minute: '2-digit',
+      second: '2-digit',
+      hour12: false // 24-hour format
+    };
+    const formatter = new Intl.DateTimeFormat('en-GB', options);
+    const formattedDate = formatter.format(new Date(timestamp));
+
+    // Reformatting to YYYY-MM-DD HH:mm:ss
+    const [date, time] = formattedDate.split(', ');
+    const [day, month, year] = date.split('/');
+    return `${year}-${month}-${day} ${time}`;
+  },
+  convertToNigeriaDayTime(timestamp) {
+    timestamp = this.normalizeTimestamp(timestamp)
+    const options = {
+      timeZone: 'Africa/Lagos',
+      year: 'numeric',
+      month: '2-digit',
+      day: '2-digit',
+      hour: '2-digit',
+      minute: '2-digit',
+      second: '2-digit',
+      hour12: false // 24-hour format
+    };
+    const formatter = new Intl.DateTimeFormat('en-GB', options);
+    const formattedDate = formatter.format(new Date(timestamp));
+
+    // Reformatting to YYYY-MM-DD HH:mm:ss
+    const [date, time] = formattedDate.split(', ');
+    const [day, month, year] = date.split('/');
+    return `${year}-${month}-${day}`;
+  },
+  normalizeTimestamp(timestamp) {
+    // 如果小于毫秒级最小值,认为是秒级时间戳
+    return timestamp < 1000000000000 ? timestamp * 1000 : timestamp;
+  },
   /**
    * 处理错误结果
    * @param error

+ 7 - 2
src/views/article/article-list.vue

@@ -21,7 +21,7 @@
 			</el-table-column>
       <el-table-column align="center" :label="$t('article.createTime')" prop="CREATED_AT">
         <template slot-scope="{row}">
-          <span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d}') }}</span>
+          <span>{{ tool.convertToNigeriaDayTime(row.CREATED_AT) }}</span>
         </template>
       </el-table-column>
     </el-table>
@@ -32,7 +32,7 @@
 			<div class="white-box" style="margin-top: -20px; padding: 0;">
 				<div class="white-box-title" style="text-align: center">
 					<h1>{{ article.TITLE }}</h1>
-					<span>{{ article.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+					<span>{{ tool.convertToNigeriaTime(article.CREATED_AT) }}</span>
 				</div>
 				<div v-html="article.CONTENT" class="white-box-content">
 				</div>
@@ -50,6 +50,11 @@ import tool from "@/utils/tool";
 
 export default {
   name: 'ArticleList',
+  computed: {
+    tool() {
+      return tool
+    }
+  },
   components: { Pagination },
   directives: { waves },
   data() {

+ 218 - 0
src/views/atlas/placement-network-ex.vue

@@ -0,0 +1,218 @@
+
+<template>
+  <div v-loading="loading" class="treeCharBody">
+    <div class="filter-user" style="margin: 5px 0" @keyup.enter="getMainData()">
+      <el-input
+        v-model="mainUserName"
+        size="small"
+        class="top-member"
+        style="width: 300px; margin-top: 10px"
+      >
+        <template slot="prepend">{{ $t("atlas.topMember") }}</template>
+      </el-input>
+      <el-input
+        v-model="expandDeep"
+        size="small"
+        style="width: 200px; margin-top: 10px"
+        class="spread-depth"
+      >
+        <template slot="prepend">{{ $t("atlas.spreadDepth") }}</template>
+      </el-input>
+      <el-input
+        v-show="false"
+        v-model="periodNum"
+        size="small"
+        style="width: 150px"
+      >
+        <template slot="prepend">{{ $t("atlas.periodNumber") }}</template>
+      </el-input>
+      <el-button
+        type="primary"
+        size="small"
+        style="margin-top: 10px"
+        @click="getMainData()"
+      >{{ $t("common.confirm") }}</el-button>
+    </div>
+    <div v-if="treeChartShow" class="tree-chart">
+      <tree-chart :tree-data="treeData" :top-deep="topDeep" type="placement" :click-node-list="clickNodeList" @clickNode="getNodeData" />
+    </div>
+  </div>
+</template>
+<script>
+import { fetchMainUserInfo, fetchPlacementNetwork, fetchPlacementNetworkList } from '@/api/atlas'
+import treeChart from '@/components/TreeChart/index.vue'
+import tool from '@/utils/tool'
+
+export default {
+  name: 'PlacementNetworkEx',
+  components: {
+    treeChart
+  },
+  data() {
+    return {
+      treeChartShow: false,
+      treeData: {
+        name: null,
+        children: null
+      },
+      tool: tool,
+      expandDeep: 5,
+      topDeep: 0,
+      mainUserName: '',
+      periodNum: null,
+      listPeriodNum: null,
+      filterForm: {
+        userName: null,
+        deep: 5,
+        periodNum: null,
+        page: 1,
+        pageSize: 20
+      },
+      listTopDeep: 0,
+      loading: false,
+      clickNodeList: [],
+      clickNodeUserId: null
+    }
+  },
+  created() {
+    this.getMainData(null, true)
+  },
+  mounted() {},
+  methods: {
+    getNodeData(e) {
+      // console.log(e)
+      if (e.collapsed === false && e.data.children == null) {
+        console.log(e.name + '---节点展开')
+      }
+      if (e.data.children == null) {
+        this.clickNodeUserId = e.data.USER_ID
+        this.getChildData(e.data, 'clickNode')
+      }
+    },
+    getList() {
+      this.treeData = {
+        name: null,
+        children: []
+      }
+    },
+    getMainData(userName = null, getList = false) {
+      const that = this
+      this.$message({
+        message: that.$t('common.awaitData')
+      })
+      let params = {
+        periodNum: that.periodNum
+      }
+      if (that.mainUserName !== null) {
+        params = { userName: that.mainUserName, periodNum: that.periodNum }
+      }
+      this.loading = true
+      fetchMainUserInfo(params).then((response) => {
+        const treeData = Object.assign(response.data[0])
+        console.log(treeData)
+        that.treeData = {
+          ...treeData
+        }
+        that.topDeep = Number(treeData.TOP_NETWORK_DEEP)
+        that.listPeriodNum = treeData.listPeriodNum
+        if (getList) {
+          // that.getListData()
+        }
+        this.getChildData(treeData)
+      })
+    },
+    getChildData(data, type) {
+      const that = this
+      const userId = data.USER_ID
+      if (data.leaf) {
+        return ''
+      }
+      if (data.isExpanded) {
+        return ''
+      }
+      if (data.children !== null && data.children.length > 0) {
+        return ''
+      }
+      that.loading = true
+      that.treeChartShow = false
+      fetchPlacementNetwork({
+        id: userId,
+        deep: this.expandDeep,
+        periodNum: this.periodNum
+      }).then((response) => {
+        that.listPeriodNum = response.data.periodNum
+        that.isExpanded = true
+        const resAllData = response.data.allData
+
+        if (type === 'clickNode') {
+          this.clickNodeList = resAllData
+          that.treeData.children = that.treeAddNode(that.treeData.children)
+        } else {
+          that.treeData.children = that.traversalTree(resAllData, that)
+        }
+
+        that.treeChartShow = true
+        this.loading = false
+      })
+    },
+    traversalTree(tree) {
+      const that = this
+      tree.forEach((item) => {
+        item.name = item.USER_NAME
+        if (item.children && item.children.length > 0) {
+          that.traversalTree(item.children)
+        }
+      })
+      return tree
+    },
+    treeAddNode(tree) {
+      const that = this
+      tree.forEach((item) => {
+        if (item.USER_ID == that.clickNodeUserId) {
+          item.children = this.clickNodeList
+        }
+        if (item.children && item.children.length > 0) {
+          that.treeAddNode(item.children)
+        }
+      })
+      return tree
+    },
+    getListData(page, pageSize) {
+      this.filterForm.page = page
+      this.filterForm.pageSize = pageSize
+      fetchPlacementNetworkList(this.filterForm).then((response) => {
+        this.allData = response.data
+        this.listTopDeep = response.data.listTopDeep
+        this.treeData.children = response.data.list
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.treeCharBody {
+  min-height: calc(100vh - 100px);
+}
+.filter-user {
+  font-size: 14px;
+  margin-bottom: 20px;
+  padding: 0px 20px;
+
+}
+.filter-user:after {
+  content: "";
+  display: table;
+  clear: both;
+}
+.filter-user .el-input-group {
+  float: left;
+  margin-right: 15px;
+}
+.tree-chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 134 - 134
src/views/atlas/placement-network.vue

@@ -1,163 +1,163 @@
 <template>
   <div class="app-container">
-		<div class="filter-user" @keyup.enter="getMainData()" style="margin: 5px 0">
-			<el-input v-model="mainUserName" size="small" class="top-member" style="width: 300px; margin-top: 10px;">
-				<template slot="prepend">{{ $t('atlas.topMember') }}</template>
-			</el-input>
-			<el-input v-model="expandDeep" size="small" style="width: 200px; margin-top: 10px;" class="spread-depth">
-				<template slot="prepend">{{ $t('atlas.spreadDepth') }}</template>
-			</el-input>
-			<el-input v-model="periodNum" size="small" style="width: 150px;" v-show="false">
-				<template slot="prepend">{{ $t('atlas.periodNumber') }}</template>
-			</el-input>
-			<el-button type="primary" size="small" @click="getMainData()" style=" margin-top: 10px;">{{ $t('common.confirm') }}</el-button>
-		</div>
-
-		<el-tree :props="props" :data="treeData" node-key="USER_ID" @node-click="getChildData" ref="tree" :indent="0" default-expand-all :height="tool.getTableHeight(true)" style="margin-top: 15px;">
-			<span :id="'node_'+data.USER_ID" :class="'custom-tree-node '+data.className" slot-scope="{ node, data }">
-				<span :class="'el-icon-loading '+ data.displayNone"></span>
-				<span :class="data.icon"></span>
-				<span>
-					<el-tag type="danger">{{countTopDeep(data.TOP_NETWORK_DEEP, topDeep)}}</el-tag>
-					<el-tag>{{ node.label }}</el-tag>
-					<el-tag>{{data.REAL_NAME}}</el-tag>
-					<el-tag type="danger">{{ $t('atlas.location') }}: {{ data.RELATIVE_LOCATION }}</el-tag>
-					<el-tag type="success">{{ data.DEC_LV_NAME }}</el-tag>
-					<el-tag type="warning">{{ $t('atlas.highest') }}: {{ data.EMP_LV_NAME }}, {{ data.CROWN_LV_NAME }}</el-tag>
-					<el-tag>{{ data.PERIOD_AT }}</el-tag>
-				</span>
-			</span>
-		</el-tree>
+    <div class="filter-user" style="margin: 5px 0" @keyup.enter="getMainData()">
+      <el-input v-model="mainUserName" size="small" class="top-member" style="width: 300px; margin-top: 10px;">
+        <template slot="prepend">{{ $t('atlas.topMember') }}</template>
+      </el-input>
+      <el-input v-model="expandDeep" size="small" style="width: 200px; margin-top: 10px;" class="spread-depth">
+        <template slot="prepend">{{ $t('atlas.spreadDepth') }}</template>
+      </el-input>
+      <el-input v-show="false" v-model="periodNum" size="small" style="width: 150px;">
+        <template slot="prepend">{{ $t('atlas.periodNumber') }}</template>
+      </el-input>
+      <el-button type="primary" size="small" style=" margin-top: 10px;" @click="getMainData()">{{ $t('common.confirm') }}</el-button>
+    </div>
+
+    <el-tree ref="tree" :props="props" :data="treeData" node-key="USER_ID" :indent="0" default-expand-all :height="tool.getTableHeight(true)" style="margin-top: 15px;" @node-click="getChildData">
+      <span :id="'node_'+data.USER_ID" slot-scope="{ node, data }" :class="'custom-tree-node '+data.className">
+        <span :class="'el-icon-loading '+ data.displayNone" />
+        <span :class="data.icon" />
+        <span>
+          <el-tag type="danger">{{ countTopDeep(data.TOP_NETWORK_DEEP, topDeep) }}</el-tag>
+          <el-tag>{{ node.label }}</el-tag>
+          <el-tag>{{ data.REAL_NAME }}</el-tag>
+          <el-tag type="danger">{{ $t('atlas.location') }}: {{ data.RELATIVE_LOCATION }}</el-tag>
+          <el-tag type="success">{{ data.DEC_LV_NAME }}</el-tag>
+          <el-tag type="warning">{{ $t('atlas.highest') }}: {{ data.EMP_LV_NAME }}, {{ data.CROWN_LV_NAME }}</el-tag>
+          <el-tag>{{ data.PERIOD_AT }}</el-tag>
+        </span>
+      </span>
+    </el-tree>
   </div>
 </template>
 
 <script>
-import {fetchMainUserInfo, fetchPlacementNetwork, fetchPlacementNetworkList} from '@/api/atlas'
+import { fetchMainUserInfo, fetchPlacementNetwork, fetchPlacementNetworkList } from '@/api/atlas'
 import Pagination from '@/components/Pagination'
 import waves from '@/directive/waves'
 import tool from '@/utils/tool'
 
 export default {
-  name: 'placementNetwork',
+  name: 'PlacementNetwork',
   components: { Pagination },
   directives: { waves },
   data() {
     return {
-			loading: true,
-			tabActiveName: 'first',
-			props: {
-				label: 'USER_NAME',
-				children: 'children',
-				icon: 'icon',
-			},
-			treeData: null,
-			expandDeep: 5,
-			topDeep: 0,
-			mainUserName: '',
-			periodNum: null,
-			listPeriodNum: null,
-			allData: null,
-			tableHeaders: null,
-			tableData: null,
-			currentPage: 1,
-			totalPages: 1,
-			totalCount: 1,
-			tool: tool,
-			filterForm: {
-				userName: null,
-				deep: 5,
-				periodNum: null,
-				page: 1,
-				pageSize: 20
-			},
-			listTopDeep: 0,
+      loading: true,
+      tabActiveName: 'first',
+      props: {
+        label: 'USER_NAME',
+        children: 'children',
+        icon: 'icon'
+      },
+      treeData: null,
+      expandDeep: 5,
+      topDeep: 0,
+      mainUserName: '',
+      periodNum: null,
+      listPeriodNum: null,
+      allData: null,
+      tableHeaders: null,
+      tableData: null,
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      tool: tool,
+      filterForm: {
+        userName: null,
+        deep: 5,
+        periodNum: null,
+        page: 1,
+        pageSize: 20
+      },
+      listTopDeep: 0
     }
   },
   created() {
-		this.getMainData(null,true)
+    this.getMainData(null, true)
   },
   methods: {
-		getMainData(userName = null, getList = false) {
-			this.$message({
-				message: this.$t('common.awaitData')
-			})
-			let params = {
-				periodNum: this.periodNum
-			}
-			if (this.mainUserName !== null) {
-				params = {userName: this.mainUserName, periodNum: this.periodNum}
-			}
-			this.loading = true
-			fetchMainUserInfo(params).then(response => {
-				this.treeData = response.data
-				this.topDeep = Number(response.data[0].TOP_NETWORK_DEEP)
-				this.listPeriodNum = response.data[0].listPeriodNum
-				if (getList) {
-					this.getListData()
-				}
-
-				setTimeout(() => {
-					this.loading = false
-				}, 1.5 * 1000)
-			})
-		},
-		getChildData(data, node) {
-			let userId = data.USER_ID
-			let that = data
-			if (that.leaf) {
-				return ''
-			}
-			if (that.isExpanded) {
-				return ''
-			}
-			if (that.children !== null && that.children.length > 0) {
-				return ''
-			}
-			that.displayNone = ''
-
-			this.loading = true
-			fetchPlacementNetwork({id: userId, deep: this.expandDeep, periodNum: this.periodNum}).then(response => {
-				this.$refs.tree.updateKeyChildren(userId, response.data.allData)
-				this.listPeriodNum = response.data.periodNum
-				that.displayNone = 'display-none'
-				that.isExpanded = true
-
-				setTimeout(() => {
-					this.loading = false
-				}, 1.5 * 1000)
-			})
-		},
-		getListData(page, pageSize) {
-			this.filterForm.page = page
-			this.filterForm.pageSize = pageSize
-			fetchPlacementNetworkList(this.filterForm).then(response => {
-				this.allData = response.data
-				this.listTopDeep = response.data.listTopDeep
+    getMainData(userName = null, getList = false) {
+      this.$message({
+        message: this.$t('common.awaitData')
+      })
+      let params = {
+        periodNum: this.periodNum
+      }
+      if (this.mainUserName !== null) {
+        params = { userName: this.mainUserName, periodNum: this.periodNum }
+      }
+      this.loading = true
+      fetchMainUserInfo(params).then(response => {
+        this.treeData = response.data
+        this.topDeep = Number(response.data[0].TOP_NETWORK_DEEP)
+        this.listPeriodNum = response.data[0].listPeriodNum
+        if (getList) {
+          this.getListData()
+        }
+
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    },
+    getChildData(data, node) {
+      const userId = data.USER_ID
+      const that = data
+      if (that.leaf) {
+        return ''
+      }
+      if (that.isExpanded) {
+        return ''
+      }
+      if (that.children !== null && that.children.length > 0) {
+        return ''
+      }
+      that.displayNone = ''
+
+      this.loading = true
+      fetchPlacementNetwork({ id: userId, deep: this.expandDeep, periodNum: this.periodNum }).then(response => {
+        this.$refs.tree.updateKeyChildren(userId, response.data.allData)
+        this.listPeriodNum = response.data.periodNum
+        that.displayNone = 'display-none'
+        that.isExpanded = true
+
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    },
+    getListData(page, pageSize) {
+      this.filterForm.page = page
+      this.filterForm.pageSize = pageSize
+      fetchPlacementNetworkList(this.filterForm).then(response => {
+        this.allData = response.data
+        this.listTopDeep = response.data.listTopDeep
 
         setTimeout(() => {
           this.loading = false
         }, 1.5 * 1000)
       })
     },
-		countTopDeep (deep, topDeep) {
-			return Number(deep) - Number(topDeep)
-		},
-		handleCurrentChange (page) {
-			this.getListData(page, this.pageSize)
-		},
-		handleSizeChange (pageSize) {
-			this.getListData(this.currentPage, pageSize)
-		},
-		handleFilter () {
-			this.getListData(1, this.pageSize)
-			this.tabActiveName = 'two'
-		},
-		handleShow (row) {
-			this.loading = true
-			this.filterForm.userName = row.SEE_USER_NAME
-			this.getListData(1, this.pageSize)
-			this.tabActiveName = 'two'
-		},
+    countTopDeep(deep, topDeep) {
+      return Number(deep) - Number(topDeep)
+    },
+    handleCurrentChange(page) {
+      this.getListData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getListData(this.currentPage, pageSize)
+    },
+    handleFilter() {
+      this.getListData(1, this.pageSize)
+      this.tabActiveName = 'two'
+    },
+    handleShow(row) {
+      this.loading = true
+      this.filterForm.userName = row.SEE_USER_NAME
+      this.getListData(1, this.pageSize)
+      this.tabActiveName = 'two'
+    }
   }
 }
 </script>

+ 215 - 0
src/views/atlas/sponsor-network-ex.vue

@@ -0,0 +1,215 @@
+
+<template>
+  <div v-loading="loading" class="treeCharBody">
+    <div class="filter-user" style="margin: 5px 0" @keyup.enter="getMainData()">
+      <el-input
+        v-model="mainUserName"
+        size="small"
+        class="top-member"
+        style="width: 300px; margin-top: 10px"
+      >
+        <template slot="prepend">{{ $t("atlas.topMember") }}</template>
+      </el-input>
+      <el-input
+        v-model="expandDeep"
+        size="small"
+        style="width: 200px; margin-top: 10px"
+        class="spread-depth"
+      >
+        <template slot="prepend">{{ $t("atlas.spreadDepth") }}</template>
+      </el-input>
+      <el-input
+        v-show="false"
+        v-model="periodNum"
+        size="small"
+        style="width: 150px"
+      >
+        <template slot="prepend">{{ $t("atlas.periodNumber") }}</template>
+      </el-input>
+      <el-button
+        type="primary"
+        size="small"
+        style="margin-top: 10px"
+        @click="getMainData()"
+      >{{ $t("common.confirm") }}</el-button>
+    </div>
+    <div v-if="treeChartShow" class="tree-chart">
+      <tree-chart :tree-data="treeData" :top-deep="topDeep" type="sponsor" @clickNode="getNodeData" />
+    </div>
+  </div>
+</template>
+<script>
+
+import { fetchMainUserInfo, fetchSponsorNetwork, fetchSponsorNetworkList } from '@/api/atlas'
+import treeChart from '@/components/TreeChart/index.vue'
+import tool from '@/utils/tool'
+
+export default {
+  name: 'sponsorNetworkEx',
+  components: {
+    treeChart
+  },
+  data() {
+    return {
+      treeChartShow: false,
+      treeData: {
+        name: null,
+        children: null
+      },
+      tool: tool,
+      expandDeep: 5,
+      topDeep: 0,
+      mainUserName: '',
+      periodNum: null,
+      listPeriodNum: null,
+      filterForm: {
+        userName: null,
+        deep: 5,
+        periodNum: null,
+        page: 1,
+        pageSize: 20
+      },
+      listTopDeep: 0,
+      loading: false
+    }
+  },
+  created() {
+    this.getMainData(null, true)
+  },
+  mounted() {},
+  methods: {
+    getNodeData(e) {
+      console.log(e)
+      if (e.collapsed === false) {
+        console.log(e.name + '---节点展开')
+      }
+      if (e.data.children == null) {
+        this.clickNodeUserId = e.data.USER_ID
+        this.getChildData(e.data, 'clickNode')
+      }
+    },
+    getList() {
+      this.treeData = {
+        name: null,
+        children: []
+      }
+    },
+    getMainData(userName = null, getList = false) {
+      const that = this
+      this.$message({
+        message: that.$t('common.awaitData')
+      })
+      let params = {
+        periodNum: that.periodNum
+      }
+      if (that.mainUserName !== null) {
+        params = { userName: that.mainUserName, periodNum: that.periodNum }
+      }
+      this.loading = true
+      fetchMainUserInfo(params).then((response) => {
+        const treeData = Object.assign(response.data[0])
+        console.log(treeData)
+        that.treeData = {
+          ...treeData
+        }
+        that.topDeep = Number(treeData.TOP_NETWORK_DEEP)
+        that.listPeriodNum = treeData.listPeriodNum
+        if (getList) {
+          // that.getListData()
+        }
+        this.getChildData(treeData)
+      })
+    },
+    getChildData(data, type) {
+      const that = this
+      const userId = data.USER_ID
+      if (data.leaf) {
+        return ''
+      }
+      if (data.isExpanded) {
+        return ''
+      }
+      if (data.children !== null && data.children.length > 0) {
+        return ''
+      }
+      that.loading = true
+      that.treeChartShow = false
+      fetchSponsorNetwork({
+        id: userId,
+        deep: this.expandDeep,
+        periodNum: this.periodNum
+      }).then((response) => {
+        that.listPeriodNum = response.data.periodNum
+        const resAllData = response.data.allData
+        if (type === 'clickNode') {
+          this.clickNodeList = resAllData
+          that.treeData.children = that.treeAddNode(that.treeData.children)
+        } else {
+          that.treeData.children = that.traversalTree(resAllData, that)
+        }
+
+        that.treeChartShow = true
+        that.loading = false
+      })
+    },
+    traversalTree(tree) {
+      const that = this
+      tree.forEach((item) => {
+        item.name = item.USER_NAME
+        if (item.children && item.children.length > 0) {
+          that.traversalTree(item.children)
+        }
+      })
+      return tree
+    },
+    treeAddNode(tree) {
+      const that = this
+      tree.forEach((item) => {
+        if (item.USER_ID == that.clickNodeUserId) {
+          item.children = this.clickNodeList
+        }
+        if (item.children && item.children.length > 0) {
+          that.treeAddNode(item.children)
+        }
+      })
+      return tree
+    },
+    getListData(page, pageSize) {
+      this.filterForm.page = page
+      this.filterForm.pageSize = pageSize
+      fetchSponsorNetworkList(this.filterForm).then((response) => {
+        this.allData = response.data
+        this.listTopDeep = response.data.listTopDeep
+        this.treeData.children = response.data.list
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.treeCharBody {
+  min-height: calc(100vh - 100px);
+}
+.filter-user {
+  font-size: 14px;
+  margin-bottom: 20px;
+  padding: 0px 20px;
+
+}
+.filter-user:after {
+  content: "";
+  display: table;
+  clear: both;
+}
+.filter-user .el-input-group {
+  float: left;
+  margin-right: 15px;
+}
+.tree-chart {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 131 - 131
src/views/atlas/sponsor-network.vue

@@ -1,160 +1,160 @@
 <template>
   <div class="app-container">
-		<div class="filter-user" @keyup.enter="getMainData()" style="margin: 5px 0">
-			<el-input v-model="mainUserName" size="small" style="width:300px; margin-top: 10px;" class="top-member">
-				<template slot="prepend">{{ $t('atlas.topMember') }}</template>
-			</el-input>
-			<el-input v-model="expandDeep" size="small" style="width:200px; margin-top: 10px;" class="spread-depth">
-				<template slot="prepend">{{ $t('atlas.spreadDepth') }}</template>
-			</el-input>
-			<el-input v-model="periodNum" size="small" style="width:150px; margin-top: 10px;" v-show="false">
-				<template slot="prepend">{{ $t('atlas.periodNumber') }}</template>
-			</el-input>
-			<el-button type="primary" size="small" @click="getMainData()" style="margin-top: 10px;">{{ $t('common.confirm') }}</el-button>
-		</div>
-		<el-tree :props="props" :data="treeData" node-key="USER_ID" @node-click="getChildData" ref="tree" :indent="0" default-expand-all :height="tool.getTableHeight(true)" style="margin-top: 15px;">
-			<span :id="'node_'+data.USER_ID" :class="'custom-tree-node '+data.className" slot-scope="{ node, data }">
-				<span :class="'el-icon-loading '+ data.displayNone"></span>
-				<span :class="data.icon"></span>
-				<span>
-					<el-tag type="danger">{{ node.label }}</el-tag>
-					<el-tag>{{data.REAL_NAME}}</el-tag>
-					<el-tag type="success">{{data.DEC_LV_NAME}}</el-tag>
-					<el-tag type="warning">Highest: {{data.EMP_LV_NAME}}, {{data.CROWN_LV_NAME}}</el-tag>
-					<el-tag>{{data.PERIOD_AT}}</el-tag>
-				</span>
-			</span>
-		</el-tree>
+    <div class="filter-user" style="margin: 5px 0" @keyup.enter="getMainData()">
+      <el-input v-model="mainUserName" size="small" style="width:300px; margin-top: 10px;" class="top-member">
+        <template slot="prepend">{{ $t('atlas.topMember') }}</template>
+      </el-input>
+      <el-input v-model="expandDeep" size="small" style="width:200px; margin-top: 10px;" class="spread-depth">
+        <template slot="prepend">{{ $t('atlas.spreadDepth') }}</template>
+      </el-input>
+      <el-input v-show="false" v-model="periodNum" size="small" style="width:150px; margin-top: 10px;">
+        <template slot="prepend">{{ $t('atlas.periodNumber') }}</template>
+      </el-input>
+      <el-button type="primary" size="small" style="margin-top: 10px;" @click="getMainData()">{{ $t('common.confirm') }}</el-button>
+    </div>
+    <el-tree ref="tree" :props="props" :data="treeData" node-key="USER_ID" :indent="0" default-expand-all :height="tool.getTableHeight(true)" style="margin-top: 15px;" @node-click="getChildData">
+      <span :id="'node_'+data.USER_ID" slot-scope="{ node, data }" :class="'custom-tree-node '+data.className">
+        <span :class="'el-icon-loading '+ data.displayNone" />
+        <span :class="data.icon" />
+        <span>
+          <el-tag type="danger">{{ node.label }}</el-tag>
+          <el-tag>{{ data.REAL_NAME }}</el-tag>
+          <el-tag type="success">{{ data.DEC_LV_NAME }}</el-tag>
+          <el-tag type="warning">Highest: {{ data.EMP_LV_NAME }}</el-tag>
+          <el-tag>{{ data.PERIOD_AT }}</el-tag>
+        </span>
+      </span>
+    </el-tree>
   </div>
 </template>
 
 <script>
-import {fetchMainUserInfo, fetchSponsorNetwork, fetchSponsorNetworkList} from '@/api/atlas'
+import { fetchMainUserInfo, fetchSponsorNetwork, fetchSponsorNetworkList } from '@/api/atlas'
 import Pagination from '@/components/Pagination'
 import waves from '@/directive/waves'
 import tool from '@/utils/tool'
 
 export default {
-  name: 'sponsorNetwork',
+  name: 'SponsorNetwork',
   components: { Pagination },
   directives: { waves },
   data() {
     return {
-			loading: true,
-			tabActiveName: 'first',
-			props: {
-				label: 'USER_NAME',
-				children: 'children',
-				icon: 'icon',
-			},
-			treeData: null,
-			expandDeep: 5,
-			topDeep: 0,
-			mainUserName: '',
-			periodNum: null,
-			listPeriodNum: null,
-			allData: null,
-			tableHeaders: null,
-			tableData: null,
-			currentPage: 1,
-			totalPages: 1,
-			totalCount: 1,
-			tool: tool,
-			filterForm: {
-				userName: null,
-				deep: 5,
-				periodNum: null,
-				page: 1,
-				pageSize: 20
-			},
-			listTopDeep: 0,
+      loading: true,
+      tabActiveName: 'first',
+      props: {
+        label: 'USER_NAME',
+        children: 'children',
+        icon: 'icon'
+      },
+      treeData: null,
+      expandDeep: 5,
+      topDeep: 0,
+      mainUserName: '',
+      periodNum: null,
+      listPeriodNum: null,
+      allData: null,
+      tableHeaders: null,
+      tableData: null,
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      tool: tool,
+      filterForm: {
+        userName: null,
+        deep: 5,
+        periodNum: null,
+        page: 1,
+        pageSize: 20
+      },
+      listTopDeep: 0
     }
   },
   created() {
-		this.getMainData(null,true)
+    this.getMainData(null, true)
   },
   methods: {
-		getMainData(userName = null, getList = false) {
-			this.$message({
-				message: this.$t('common.awaitData')
-			})
-			let params = {
-				periodNum: this.periodNum
-			}
-			if (this.mainUserName !== null) {
-				params = {userName: this.mainUserName, periodNum: this.periodNum}
-			}
-			this.loading = true
-			fetchMainUserInfo(params).then(response => {
-				this.treeData = response.data
-				this.topDeep = Number(response.data[0].TOP_NETWORK_DEEP)
-				this.listPeriodNum = response.data[0].listPeriodNum
-				if (getList) {
-					this.getListData()
-				}
-
-				setTimeout(() => {
-					this.loading = false
-				}, 1.5 * 1000)
-			})
-		},
-		getChildData(data, node) {
-			let userId = data.USER_ID
-			let that = data
-			if (that.leaf) {
-				return ''
-			}
-			if (that.isExpanded) {
-				return ''
-			}
-			if (that.children !== null && that.children.length > 0) {
-				return ''
-			}
-			that.displayNone = ''
-
-			this.loading = true
-			fetchSponsorNetwork({id: userId, deep: this.expandDeep, periodNum: this.periodNum}).then(response => {
-				this.$refs.tree.updateKeyChildren(userId, response.data.allData)
-				this.listPeriodNum = response.data.periodNum
-				that.displayNone = 'display-none'
-				that.isExpanded = true
-
-				setTimeout(() => {
-					this.loading = false
-				}, 1.5 * 1000)
-			})
-		},
-		getListData(page, pageSize) {
-			this.filterForm.page = page
-			this.filterForm.pageSize = pageSize
-			fetchSponsorNetworkList(this.filterForm).then(response => {
-				this.allData = response.data
-				this.listTopDeep = response.data.listTopDeep
+    getMainData(userName = null, getList = false) {
+      this.$message({
+        message: this.$t('common.awaitData')
+      })
+      let params = {
+        periodNum: this.periodNum
+      }
+      if (this.mainUserName !== null) {
+        params = { userName: this.mainUserName, periodNum: this.periodNum }
+      }
+      this.loading = true
+      fetchMainUserInfo(params).then(response => {
+        this.treeData = response.data
+        this.topDeep = Number(response.data[0].TOP_NETWORK_DEEP)
+        this.listPeriodNum = response.data[0].listPeriodNum
+        if (getList) {
+          this.getListData()
+        }
+
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    },
+    getChildData(data, node) {
+      const userId = data.USER_ID
+      const that = data
+      if (that.leaf) {
+        return ''
+      }
+      if (that.isExpanded) {
+        return ''
+      }
+      if (that.children !== null && that.children.length > 0) {
+        return ''
+      }
+      that.displayNone = ''
+
+      this.loading = true
+      fetchSponsorNetwork({ id: userId, deep: this.expandDeep, periodNum: this.periodNum }).then(response => {
+        this.$refs.tree.updateKeyChildren(userId, response.data.allData)
+        this.listPeriodNum = response.data.periodNum
+        that.displayNone = 'display-none'
+        that.isExpanded = true
+
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+      })
+    },
+    getListData(page, pageSize) {
+      this.filterForm.page = page
+      this.filterForm.pageSize = pageSize
+      fetchSponsorNetworkList(this.filterForm).then(response => {
+        this.allData = response.data
+        this.listTopDeep = response.data.listTopDeep
 
         setTimeout(() => {
           this.loading = false
         }, 1.5 * 1000)
       })
     },
-		countTopDeep (deep, topDeep) {
-			return Number(deep) - Number(topDeep)
-		},
-		handleCurrentChange (page) {
-			this.getListData(page, this.pageSize)
-		},
-		handleSizeChange (pageSize) {
-			this.getListData(this.currentPage, pageSize)
-		},
-		handleFilter () {
-			this.getListData(1, this.pageSize)
-			this.tabActiveName = 'two'
-		},
-		handleShow (row) {
-			this.loading = true
-			this.filterForm.userName = row.SEE_USER_NAME
-			this.getListData(1, this.pageSize)
-			this.tabActiveName = 'two'
-		},
+    countTopDeep(deep, topDeep) {
+      return Number(deep) - Number(topDeep)
+    },
+    handleCurrentChange(page) {
+      this.getListData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getListData(this.currentPage, pageSize)
+    },
+    handleFilter() {
+      this.getListData(1, this.pageSize)
+      this.tabActiveName = 'two'
+    },
+    handleShow(row) {
+      this.loading = true
+      this.filterForm.userName = row.SEE_USER_NAME
+      this.getListData(1, this.pageSize)
+      this.tabActiveName = 'two'
+    }
   }
 }
 </script>

+ 214 - 154
src/views/bonus/account-list.vue

@@ -1,179 +1,239 @@
 <template>
-  <div class="app-container" v-loading="loading">
-		<el-row :gutter="20">
-			<el-col :xs="24" :sm="12" :lg="6" :span="6" v-for="item in walletData" :key="item.walletType">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="info" :title="item.walletName" :subTitle="item.amount | toThousandFilter">
-<!--						<template slot="icon">-->
-<!--							<el-image fit="cover" :src="tool.getArImage(item.walletType + '.png', '/files/')" style="width: 100px; height: 100px; border-radius: 50%;"></el-image>-->
-<!--						</template>-->
-						<template slot="extra">
-							<el-button type="primary" size="small" @click="handleBonusFlow(item.walletType, item.walletName)" v-show="dealSwitch">{{ $t('bonus.viewRecord') }}</el-button>
-						</template>
-					</el-result>
-				</el-card>
-			</el-col>
-		</el-row>
+  <div v-loading="loading" class="app-container">
+    <el-row :gutter="20">
+      <el-col v-for="item in walletData" :key="item.walletType" :xs="24" :sm="12" :lg="6" :span="6">
+        <el-card shadow="hover" style="margin: 10px auto;">
+          <el-result icon="info" :title="item.walletName" :sub-title="item.amount | toThousandFilter">
+            <!--						<template slot="icon">-->
+            <!--							<el-image fit="cover" :src="tool.getArImage(item.walletType + '.png', '/files/')" style="width: 100px; height: 100px; border-radius: 50%;"></el-image>-->
+            <!--						</template>-->
+            <template slot="icon">
+              <i class="el-icon-wallet" />
+            </template>
+            <template slot="extra">
+              <el-button v-show="dealSwitch" type="primary" size="small" @click="handleBonusFlow(item.walletType, item.walletName)">{{ $t('bonus.viewRecord') }}</el-button>
+            </template>
+          </el-result>
+        </el-card>
+      </el-col>
+    </el-row>
 
-		<el-dialog :title="bonusFlowType" :visible.sync="dialog" :width="screenWidth" v-loading="loading" style="margin-top: -80px;">
-			<el-row :gutter="10" style="margin-top: -30px;">
-						<el-col :xs="24" :sm="24" :lg="6">
-							<el-date-picker
-								v-model="listQuery.createAt[0]"
-								type="date"
-								:placeholder="$t('common.startDate')"
-								value-format="yyyy-MM-dd"
-								clearable
-								style="width: 100%; margin: 10px 0;">
-							</el-date-picker>
-						</el-col>
-						<el-col :xs="24" :sm="24" :lg="6" :span="6">
-								<el-date-picker
-									v-model="listQuery.createAt[1]"
-									type="date"
-									:placeholder="$t('common.endDate')"
-									value-format="yyyy-MM-dd"
-									clearable
-									style="width: 100%; margin: 10px 0;">
-								</el-date-picker>
-						</el-col>
-						<el-col :xs="24" :sm="24" :lg="6" :span="6">
-								<el-select size="small" v-model="listQuery.dealType" :placeholder="$t('bonus.transType')" clearable style="width: 100%; margin: 10px 0;">
-									<el-option v-for="(item, key) in dealTypeList" :label="item" :value="key" :key="key"></el-option>
-								</el-select>
-						</el-col>
-						<el-col :xs="24" :sm="24" :lg="6" :span="6">
-								<el-input size="small" v-model="listQuery.remark" :placeholder="$t('bonus.remark')" clearable  style="width: 100%; margin: 10px 0;"></el-input>
-						</el-col>
-						<el-col :xs="24" :sm="24" :lg="24" :span="24">
-							<div class="grid-content bg-purple">
-								<el-button size="small" type="primary" @click="handleBonusFlow(listQuery.walletType, walletName)">{{ $t('common.select') }}</el-button>
-								<el-button size="small" type="warning" @click="handleFilterClear(listQuery.walletType, walletName)">{{ $t('common.reset') }}</el-button>
-							</div>
-						</el-col>
-					</el-row>
+    <el-dialog v-loading="loading" :title="bonusFlowType" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px;">
+      <el-row :gutter="10" style="margin-top: -30px;">
+        <el-col :xs="24" :sm="24" :lg="6">
+          <el-date-picker
+            v-model="listQuery.createAt[0]"
+            type="date"
+            :placeholder="$t('common.startDate')"
+            value-format="yyyy-MM-dd"
+            clearable
+            style="width: 100%; margin: 10px 0;"
+          />
+        </el-col>
+        <el-col :xs="24" :sm="24" :lg="6" :span="6">
+          <el-date-picker
+            v-model="listQuery.createAt[1]"
+            type="date"
+            :placeholder="$t('common.endDate')"
+            value-format="yyyy-MM-dd"
+            clearable
+            style="width: 100%; margin: 10px 0;"
+          />
+        </el-col>
+        <el-col v-if="listQuery.walletType !== 'cash'" :xs="24" :sm="24" :lg="6" :span="6">
+          <el-select v-model="listQuery.dealType" size="small" :placeholder="$t('bonus.transType')" clearable style="width: 100%; margin: 10px 0;">
+            <el-option v-for="(item, key) in dealTypeList" :key="key" :label="item" :value="key" />
+          </el-select>
+        </el-col>
+        <el-col :xs="24" :sm="24" :lg="6" :span="6">
+          <el-input v-model="listQuery.remark" size="small" :placeholder="$t('bonus.remark')" clearable style="width: 100%; margin: 10px 0;" />
+        </el-col>
+        <el-col :xs="24" :sm="24" :lg="24" :span="24">
+          <div class="grid-content bg-purple">
+            <el-button size="small" type="primary" @click="handleBonusFlow(listQuery.walletType, walletName)">{{ $t('common.select') }}</el-button>
+            <el-button size="small" type="warning" @click="handleFilterClear(listQuery.walletType, walletName)">{{ $t('common.reset') }}</el-button>
+          </div>
+        </el-col>
+      </el-row>
 
-			<el-table
-					:data="bonusData"
-					border
-					fit
-					highlight-current-row
-					style="margin-top: 10px;"
-					:xs="24" :sm="24" :lg="6"
-				>
-					<el-table-column :label="$t('bonus.transTime')" align="center" min-width="140px">
-						<template slot-scope="{row}">
-							<span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
-						</template>
-					</el-table-column>
-					<el-table-column :label="$t('bonus.transType')" align="center" min-width="150px" v-if="dealTypeSwitch">
-						<template slot-scope="{row}">
-							<span>{{ row.DEAL_TYPE_NAME }}</span>
-						</template>
-					</el-table-column>
-					<el-table-column :label="$t('bonus.preTransactionBalance')" align="center" min-width="150px">
-						<template slot-scope="{row}">
-							<span>{{ tool.formatPrice(row.TOTAL - row.AMOUNT) | amountFilter }}</span>
-						</template>
-					</el-table-column>
-					<el-table-column :label="$t('bonus.postTransactionBalance')" align="center" min-width="160px">
-						<template slot-scope="{row}">
-							<span>{{ row.AMOUNT | amountFilter }}</span>
-						</template>
-					</el-table-column>
-					<el-table-column :label="$t('bonus.transAmount')" align="center" min-width="120px">
-						<template slot-scope="{row}">
-							<el-tag :type="row.IS_INCR > 0 ? 'danger' : 'info'" size="small" class="no-border">
-								<span class="text-danger">{{ row.IS_INCR > 0 ? '+' : '' }}  {{ row.AMOUNT | amountFilter }}</span>
-							</el-tag>
-						</template>
-					</el-table-column>
-					<el-table-column :label="$t('bonus.remark')" align="center" min-width="240px">
-						<template slot-scope="{row}">
-							<span>{{ row.REMARK }}</span>
-						</template>
-					</el-table-column>
-				</el-table>
+      <el-table
+        :data="bonusData"
+        border
+        fit
+        highlight-current-row
+        style="margin-top: 10px;"
+        :xs="24"
+        :sm="24"
+        :lg="6"
+      >
+        <el-table-column :label="$t('bonus.transTime')" align="center" min-width="140px">
+          <template slot-scope="{row}">
+            <span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column v-if="dealTypeSwitch" :label="$t('bonus.transType')" align="center" min-width="150px">
+          <template slot-scope="{row}">
+            <span>{{ row.DEAL_TYPE_NAME }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('bonus.preTransactionBalance')" align="center" min-width="150px">
+          <template slot-scope="{row}">
+            <span>{{ tool.formatPrice(row.TOTAL - row.AMOUNT) | amountFilter }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('bonus.postTransactionBalance')" align="center" min-width="160px">
+          <template slot-scope="{row}">
+            <span>{{ row.AMOUNT | amountFilter }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('bonus.transAmount')" align="center" min-width="120px">
+          <template slot-scope="{row}">
+            <el-tag :type="row.IS_INCR > 0 ? 'danger' : 'info'" size="small" class="no-border">
+              <span class="text-danger">{{ row.IS_INCR > 0 ? '+' : '' }}  {{ row.AMOUNT | amountFilter }}</span>
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('bonus.remark')" align="center" min-width="240px">
+          <template slot-scope="{row}">
+            <span>{{ row.REMARK }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
 
-			<el-row :gutter="10">
-					<el-col :xs="24" :sm="24" :lg="24" :span="24">
-						<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="handleBonusFlow(listQuery.walletType, walletName)" />
-					</el-col>
-				</el-row>
-		</el-dialog>
-	</div>
+      <el-row :gutter="10">
+        <el-col :xs="24" :sm="24" :lg="24" :span="24">
+          <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="handleBonusFlow(listQuery.walletType, walletName)" />
+        </el-col>
+      </el-row>
+    </el-dialog>
+
+    <el-dialog v-loading="loading" :title="bonusFlowType" :visible.sync="userPerformanceBonusDialog" :width="screenWidth" style="margin-top: -80px;">
+      <el-table
+        :data="bonusData"
+        border
+        fit
+        highlight-current-row
+        style="margin-top: 10px;"
+        :xs="24"
+        :sm="24"
+        :lg="6"
+      >
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.No')" prop="ID" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.amount')" prop="AMOUNTS" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.originalAmount')" prop="ORIGINAL" />
+        <el-table-column :label="$t('bonus.expiredTime')" align="center" min-width="140px">
+          <template slot-scope="{row}">
+            <span>{{ row.EXPIRED_AT | parseTime('{y}-{m}-{d}') }}</span>
+          </template>
+        </el-table-column>
+
+      </el-table>
+
+      <el-row :gutter="10">
+        <el-col :xs="24" :sm="24" :lg="24" :span="24">
+          <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="handleBonusFlow(listQuery.walletType, walletName)" />
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchAccount,fetchAccountFlow} from '@/api/bonus'
+import { fetchAccount, fetchAccountFlow } from '@/api/bonus'
 import Pagination from '@/components/Pagination'
-import tool from "@/utils/tool"
-import {formatAmount, getScreenWidth} from "@/utils"
+import { getScreenWidth } from '@/utils'
+import tool from '@/utils/tool'
 
 export default {
-  name: 'memberAccount',
-	components: { Pagination },
+  name: 'MemberAccount',
+  components: { Pagination },
   data() {
     return {
-			tool: tool,
-			loading: true,
-			walletData: [],
-			dealSwitch: 0,
-			dealTypeSwitch: true,
+      tool: tool,
+      loading: true,
+      walletData: [],
+      dealSwitch: 0,
+      dealTypeSwitch: true,
 
-			dialog: false,
-			bonusFlowType: '',
-			walletName: '',
-			dealTypeList: null,
-			bonusData: null,
-			total: 0,
-			listQuery: {
-				page: 1,
-				pageSize: 10,
-				walletType: '',
-				createAt: [],
-				remark: '',
-				dealType: '',
-			},
-			screenWidth: getScreenWidth() > 600 ? '70%' : getScreenWidth() + 'px'
+      dialog: false,
+      userPerformanceBonusDialog: false,
+      bonusFlowType: '',
+      walletName: '',
+      dealTypeList: null,
+      bonusData: null,
+      total: 0,
+      listQuery: {
+        page: 1,
+        pageSize: 10,
+        walletType: '',
+        createAt: [],
+        remark: '',
+        dealType: ''
+      },
+      screenWidth: getScreenWidth() > 600 ? '70%' : getScreenWidth() + 'px'
     }
   },
   created() {
     this.getList()
   },
-	methods: {
+  methods: {
     getList() {
       this.loading = true
-			fetchAccount().then(response => {
-				this.walletData = response.data.wallet
-				this.dealSwitch = parseInt(response.data.dealSwitch) === 1
-				this.loading = false
+      fetchAccount().then(response => {
+        this.walletData = response.data.wallet
+        this.dealSwitch = parseInt(response.data.dealSwitch) === 1
+        this.loading = false
+      })
+    },
+    handleBonusFlow(walletType, walletName) {
+      this.loading = true
+      this.bonusFlowType = this.$t('bonus.bonusFlowTitle').replace('%s', walletName)
+      this.listQuery.walletType = walletType
+      this.walletName = walletName
+      fetchAccountFlow(this.listQuery).then(response => {
+        this.bonusData = response.data.list
+        this.total = response.data.totalCount
+        this.dealTypeList = response.data.dealTypes
+        this.dealTypeSwitch = walletType !== 'cash'
+        if(this.listQuery.walletType === 'userPerformanceBonus'){
+          this.userPerformanceBonusDialog = true
+        }else {
+          this.dialog = true
+        }
+        this.loading = false
       })
     },
-		handleBonusFlow(walletType, walletName) {
-			this.loading = true
-			this.bonusFlowType = this.$t('bonus.bonusFlowTitle').replace('%s', walletName)
-			this.listQuery.walletType = walletType
-			this.walletName = walletName
-			fetchAccountFlow(this.listQuery).then(response => {
-				this.bonusData = response.data.list
-				this.total = response.data.totalCount
-				this.dealTypeList = response.data.dealTypes
-				this.dealTypeSwitch = walletType !== 'cash'
-				this.dialog = true
-				this.loading = false
-			})
-		},
-		handleFilterClear(walletType, walletName){
-			this.walletName = walletName
-			this.listQuery.page = 1
-			this.listQuery.pageSize = 5
-			this.listQuery.walletType = walletType
-			this.listQuery.createAt = []
-			this.listQuery.remark = ''
-			this.listQuery.dealType = ''
-			this.handleBonusFlow(walletType, walletName)
-		},
+    handleFilterClear(walletType, walletName) {
+      this.walletName = walletName
+      this.listQuery.page = 1
+      this.listQuery.pageSize = 5
+      this.listQuery.walletType = walletType
+      this.listQuery.createAt = []
+      this.listQuery.remark = ''
+      this.listQuery.dealType = ''
+      this.handleBonusFlow(walletType, walletName)
+    }
   }
 }
 </script>
+
+<style lang="scss" scoped>
+
+.app-container{
+	i{
+		display: block;
+		font-size: 60px;
+		/* margin-bottom: 15px; */
+		transition: color .15s linear;
+		// color: #13ce66;
+	}
+
+}
+::v-deep .el-result__subtitle{
+		font-weight: bold;
+		p{
+			font-size: 1.5em!important;
+			color: #000;
+		}
+	}
+</style>

+ 82 - 100
src/views/bonus/bonus-list.vue

@@ -1,125 +1,107 @@
 <template>
-  <div class="app-container" v-loading="loading">
-    <el-table
-      :data="tableData"
-      border
-      fit
-      highlight-current-row
-    >
-      <el-table-column align="center" min-width="100px" :label="$t('bonus.payCycle')" prop="PERIOD_NUM.value"></el-table-column>
-			<el-table-column align="center" min-width="150px" :label="$t('bonus.welcomeBonus')" prop="BONUS_TG.value" v-show="welcomeBonusSwitch === 1">
-				<template slot-scope="{row}">
-					{{ row.BONUS_TG.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-      <el-table-column align="center" min-width="130px" :label="$t('bonus.teamBonus')" prop="ORI_BONUS_QY.value" v-show="teamBonusSwitch === 1">
-				<template slot-scope="{row}">
-					{{ row.ORI_BONUS_QY.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-      <el-table-column align="center" min-width="130px" :label="$t('bonus.directorBonus')" prop="ORI_BONUS_BS.value">
-				<template slot-scope="{row}">
-					{{ row.ORI_BONUS_BS.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-      <el-table-column align="center" min-width="150px" :label="$t('bonus.quarterlyBonus')" prop="ORI_BONUS_QUARTER.value">
-				<template slot-scope="{row}">
-					{{ row.ORI_BONUS_QUARTER.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-			<el-table-column align="center" min-width="170px" :label="$t('bonus.stockistCommission')" prop="BONUS_BD.value" v-show="stockistCommissionSwitch === 1">
-				<template slot-scope="{row}">
-					{{ row.BONUS_BD.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-			<el-table-column align="center" min-width="120px" :label="$t('bonus.actualBonus')" prop="BONUS_REAL.value">
-				<template slot-scope="{row}">
-					{{ row.BONUS_REAL.value | toThousandFilter }}
-				</template>
-			</el-table-column>
-      <el-table-column align="center" min-width="100px" :label="$t('common.action')">
-        <template slot-scope="{row}">
-					<el-button-group>
-						<el-button type="primary" size="mini" @click="getOne(row.PERIOD_NUM.value)">{{ $t('common.view') }}</el-button>
-					</el-button-group>
-        </template>
-      </el-table-column>
-    </el-table>
+  <div class="app-container">
+    <div v-if="!loading" v-loading="loading" >
+      <el-table
+        :data="tableData"
+        border
+        fit
+        highlight-current-row
+      >
+        <el-table-column align="center" min-width="50px" :label="$t('bonus.payCycle')" prop="period" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.eliteBonus')" prop="welcomeBonus">
+          <template slot-scope="{row}">
+            {{ row.eliteBonus | toThousandFilter }}
+          </template>
+        </el-table-column>
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.proEliteBonus')" prop="proEliteBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.superEliteBonus')" prop="superEliteBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.stockistBonus')" prop="stockistBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.leaderShipBonus')" prop="leaderShipBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.welcomeBonus')" prop="welcomeBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.carBonus')" prop="carBonus" />
+        <el-table-column align="center" min-width="100px" :label="$t('bonus.userPerformanceBonus')" prop="userPerformanceBonus" />
 
-		<el-dialog :title="bonusPayCycle" :visible.sync="dialog" :width="screenWidth" v-if="bonusData" style="margin-top: -80px">
-			<el-descriptions title="" class="bonus-list" :column="column" border size="medium" style="width: 100%">
-				<el-descriptions-item label-class-name="labelClass" :label="$t('shop.memberCode')"><span style="white-space: nowrap;">{{ bonusData.USER_NAME.value }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.payCycle')"><span style="white-space: nowrap;">{{ bonusData.PERIOD_NUM.value }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('profile.memberLevel')"><span style="white-space: nowrap;">{{ bonusData.LAST_DEC_LV.value }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.whetherActive')"><span style="white-space: nowrap;">{{ bonusData.IS_ACTIVE.value === 1 ? $t('common.yes') : $t('common.no') }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('profile.latestDirector')"><span style="white-space: nowrap;">{{ bonusData.LAST_EMP_LV.value }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('profile.latestCrown')"><span style="white-space: nowrap;">{{ bonusData.LAST_CROWN_LV.value }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.directorPGSPerformance')"><span style="white-space: nowrap;">{{ bonusData.DIRECTOR_BONUS_PGS.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.directorBonus')"><span style="white-space: nowrap;">{{ bonusData.ORI_BONUS_BS.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.welcomeBonus')" v-if="bonusData.ORI_BONUS_TG_SWITCH === 1"><span style="white-space: nowrap;">{{ bonusData.ORI_BONUS_TG.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.teamBonus')" v-if="bonusData.ORI_BONUS_QY_SWITCH === 1"><span style="white-space: nowrap;">{{ bonusData.ORI_BONUS_QY.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.quarterlyBonus')"><span style="white-space: nowrap;">{{ bonusData.ORI_BONUS_QUARTER.value | amountFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.stockistCommission')" v-if="bonusData.BONUS_BD_SWITCH === 1"><span style="white-space: nowrap;">{{ bonusData.BONUS_BD.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.totalBonus')"><span style="white-space: nowrap;">{{ bonusData.BONUS_TOTAL.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.actualBonus')"><span style="white-space: nowrap;">{{ bonusData.BONUS_REAL.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.leftNewlyIncreasedPerformance')"><span style="white-space: nowrap;">{{ bonusData.PV_1L.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.leftSurplusPerformance')"><span style="white-space: nowrap;">{{ bonusData.SURPLUS_1L.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.rightNewlyIncreasedPerformance')"><span style="white-space: nowrap;">{{ bonusData.PV_2L.value | toThousandFilter }}</span></el-descriptions-item>
-				<el-descriptions-item label-class-name="labelClass" :label="$t('bonus.rightSurplusPerformance')"><span style="white-space: nowrap;">{{ bonusData.SURPLUS_2L.value | toThousandFilter }}</span></el-descriptions-item>
-			</el-descriptions>
-		</el-dialog>
-	</div>
+        <el-table-column align="center" min-width="100px" :label="$t('common.action')">
+          <template slot-scope="{row}">
+            <el-button-group>
+              <el-button v-if="flowBonusSwitch === 1" type="primary" size="mini" @click="getOne(row.period)">{{ $t('common.view') }}</el-button>
+            </el-button-group>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div v-else>
+      <el-empty :description="$t('common.noData')"></el-empty>
+    </div>
+
+    <el-dialog v-if="bonusData" :title="bonusPayCycle" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px">
+      <el-descriptions title="" class="bonus-list" :column="column" border size="medium" style="width: 100%">
+        <el-descriptions-item label-class-name="labelClass" :label="$t('shop.memberCode')"><span style="white-space: nowrap;">{{ bonusData.userName }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('profile.memberLevel')"><span style="white-space: nowrap;">{{ bonusData.decLevel }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('profile.highestDirector')"><span style="white-space: nowrap;">{{ bonusData.empLevel }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('profile.eliteLevel')"><span style="white-space: nowrap;">{{ bonusData.eliteLevel }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.eliteBonus')"><span style="white-space: nowrap;">{{ bonusData.eliteBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.proEliteBonus')"><span style="white-space: nowrap;">{{ bonusData.proEliteBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.superEliteBonus')"><span style="white-space: nowrap;">{{ bonusData.superEliteBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.stockistBonus')"><span style="white-space: nowrap;">{{ bonusData.stockistBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.leaderShipBonus')"><span style="white-space: nowrap;">{{ bonusData.leaderShipBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.welcomeBonus')"><span style="white-space: nowrap;">{{ bonusData.welcomeBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.carBonus')"><span style="white-space: nowrap;">{{ bonusData.carBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.totalBonus')"><span style="white-space: nowrap;">{{ bonusData.totalBonus }}</span></el-descriptions-item>
+        <el-descriptions-item label-class-name="labelClass" :label="$t('bonus.userPerformanceBonus')"><span style="white-space: nowrap;">{{ bonusData.userPerformanceBonus }}</span></el-descriptions-item>
+     </el-descriptions>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchBonusList, fetchBonusDetail} from '@/api/bonus'
-import {formatAmount, getOperatingSystem, getScreenWidth} from "@/utils";
+import { fetchBonusList, fetchBonusDetail } from '@/api/bonus'
+import { formatAmount, getOperatingSystem, getScreenWidth } from '@/utils'
 
 export default {
-  name: 'previousBonus',
+  name: 'PreviousBonus',
   data() {
     return {
-			tableData: [],
+      tableData: [],
       total: 0,
-			loading: true,
+      loading: true,
 
-			welcomeBonusSwitch: 0,
-			teamBonusSwitch: 0,
-			stockistCommissionSwitch: 0,
+      flowBonusSwitch: 0,
 
-			dialog: false,
-			bonusData: null,
-			bonusPayCycle: '',
+      dialog: false,
+      bonusData: null,
+      bonusPayCycle: '',
 
-			screenWidth: getScreenWidth() > 600 ? '70%' : getScreenWidth() + 'px',
-			column: ['Android', 'ios'].includes(getOperatingSystem()) ? 1 : 2,
+      screenWidth: getScreenWidth() > 600 ? '70%' : getScreenWidth() + 'px',
+      column: ['Android', 'ios'].includes(getOperatingSystem()) ? 1 : 2
     }
   },
   created() {
     this.getList()
   },
-	methods: {
+  methods: {
     getList() {
       this.loading = true
-			fetchBonusList().then(response => {
-				const {tableData, bonusSwitch} = response.data
-				this.tableData = tableData
-				this.welcomeBonusSwitch = bonusSwitch.welcomeBonusSwitch
-				this.teamBonusSwitch = bonusSwitch.teamBonusSwitch
-				this.stockistCommissionSwitch = bonusSwitch.stockistCommissionSwitch
-
-				this.loading = false
+      fetchBonusList().then(response => {
+        const { tableData, flowBonusSwitch } = response.data
+        this.tableData = tableData
+        this.flowBonusSwitch = parseInt(flowBonusSwitch)
+        // this.teamBonusSwitch = parseInt(bonusSwitch.teamBonusSwitch)
+        // this.stockistCommissionSwitch = parseInt(bonusSwitch.stockistCommissionSwitch)
+        if(tableData.length > 0){
+          this.loading = false
+        }
       })
     },
-		getOne(periodNum) {
-			this.loading = true
-			this.bonusPayCycle = this.$t('bonus.periodBonus').replace('%s', periodNum)
-			fetchBonusDetail({periodNum: periodNum}).then(response => {
-				this.bonusData = response.data
-				this.dialog = true
-				this.loading = false
-			})
-		},
+    getOne(periodNum) {
+      this.loading = true
+      this.bonusPayCycle = this.$t('bonus.periodBonus').replace('%s', periodNum)
+      fetchBonusDetail({ periodNum: periodNum }).then(response => {
+        this.bonusData = response.data
+        this.dialog = true
+        this.loading = false
+      })
+    }
   }
 }
 </script>

+ 44 - 96
src/views/bonus/historical-cumulative-bonus.vue

@@ -1,116 +1,64 @@
 <template>
-  <div class="app-container" v-loading="loading">
-		<el-row :gutter="20">
-			<el-col :xs="24" :sm="12" :lg="6" :span="6" v-show="welcomeBonusSwitch === 1">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.welcomeBonus')" :subTitle="tableData.BONUS_TG.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :lg="6" :span="6" v-show="teamBonusSwitch === 1">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.teamBonus')" :subTitle="tableData.ORI_BONUS_QY.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :lg="6" :span="6">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.directorBonus')" :subTitle="tableData.ORI_BONUS_BS.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :lg="6" :span="6">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.quarterlyBonus')" :subTitle="tableData.ORI_BONUS_QUARTER.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :lg="6" :span="6" v-show="stockistCommissionSwitch === 1">
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.stockistCommission')" :subTitle="tableData.BONUS_BD.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-
-			<el-col :xs="24" :sm="12" :lg="6" :span="6" >
-				<el-card shadow="hover" style="margin: 10px auto;">
-					<el-result icon="success" :title="$t('bonus.totalBonus')" :subTitle="tableData.BONUS_TOTAL.value | toThousandFilter"></el-result>
-				</el-card>
-			</el-col>
-		</el-row>
-
-<!--    <el-table-->
-<!--      :data="tableData"-->
-<!--      border-->
-<!--      fit-->
-<!--      highlight-current-row-->
-<!--      style="width: 100%; margin-top: 25px;"-->
-<!--    >-->
-<!--			<el-table-column align="center" min-width="130px" :label="$t('bonus.welcomeBonus')" prop="BONUS_TG.value" v-show="welcomeBonusSwitch === 1">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.BONUS_TG.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--      <el-table-column align="center" min-width="120px" :label="$t('bonus.teamBonus')" prop="ORI_BONUS_QY.value" v-show="teamBonusSwitch === 1">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.ORI_BONUS_QY.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--      <el-table-column align="center" min-width="130px" :label="$t('bonus.directorBonus')" prop="ORI_BONUS_BS.value">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.ORI_BONUS_BS.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--      <el-table-column align="center" min-width="140px" :label="$t('bonus.quarterlyBonus')" prop="ORI_BONUS_QUARTER.value">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.ORI_BONUS_QUARTER.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--			<el-table-column align="center" min-width="170px" :label="$t('bonus.stockistCommission')" prop="BONUS_BD.value" v-show="stockistCommissionSwitch === 1">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.BONUS_BD.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--			<el-table-column align="center" min-width="120px" :label="$t('bonus.totalBonus')" prop="BONUS_TOTAL.value">-->
-<!--				<template slot-scope="{row}">-->
-<!--					{{ row.BONUS_TOTAL.value | toThousandFilter }}-->
-<!--				</template>-->
-<!--			</el-table-column>-->
-<!--    </el-table>-->
-	</div>
+  <div v-loading="loading" class="app-container">
+    <el-row :gutter="20">
+      <el-col :xs="24" :sm="12" :lg="8" :span="6" v-for="(item,index) in tableData" :key="index">
+        <el-card shadow="hover" style="margin: 10px auto;" >
+          <el-result :title="$t(`bonus.${item.name}`)" :sub-title="item.bonus | toThousandFilter">
+            <template slot="icon">
+              <i class="el-icon-money" />
+            </template>
+          </el-result>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
 </template>
 
 <script>
-import {fetchHistoricalCumulativeBonus} from '@/api/bonus'
+import { fetchHistoricalCumulativeBonus } from '@/api/bonus'
 
 export default {
-  name: 'historicalCumulativeBonus',
+  name: 'HistoricalCumulativeBonus',
   data() {
     return {
-			tableData: [],
+      tableData: [],
       total: 0,
-			loading: true,
-
-			welcomeBonusSwitch: 0,
-			teamBonusSwitch: 0,
-			stockistCommissionSwitch: 0,
+      loading: true,
     }
   },
   created() {
     this.getList()
   },
-	methods: {
+  methods: {
     getList() {
       this.loading = true
-			fetchHistoricalCumulativeBonus().then(response => {
-				const {tableData, bonusSwitch} = response.data
-				this.tableData = tableData.length > 0 ? tableData[0] : {}
-				this.welcomeBonusSwitch = bonusSwitch.welcomeBonusSwitch
-				this.teamBonusSwitch = bonusSwitch.teamBonusSwitch
-				this.stockistCommissionSwitch = bonusSwitch.stockistCommissionSwitch
-
-				this.loading = false
+      fetchHistoricalCumulativeBonus().then(response => {
+        const { tableData, bonusSwitch } = response.data
+        this.tableData = tableData
+        this.loading = false
       })
-    },
+    }
   }
 }
 </script>
+
+<style lang="scss" scoped>
+
+.app-container{
+	i{
+		display: block;
+		font-size: 60px;
+		/* margin-bottom: 15px; */
+		transition: color .15s linear;
+		// color: #13ce66;
+	}
+
+}
+::v-deep .el-result__subtitle{
+		font-weight: bold;
+		p{
+			font-size: 1.5em!important;
+			color: #000;
+		}
+	}
+</style>

+ 85 - 85
src/views/bonus/team-inquiry.vue

@@ -1,107 +1,107 @@
 <template>
-  <div class="app-container" v-loading="loading">
-		<el-table border :data="userData" style="width: 100%" :cell-style="tableCellStyle">
-			<el-table-column :label="$t('bonus.personalDetails')">
-				<el-table-column type="index" :index="indexMethod" width="60px" label=""></el-table-column>
-				<el-table-column min-width="120px" prop="number" :label="$t('shop.memberCode')"></el-table-column>
-				<el-table-column min-width="210px" prop="name" :label="$t('shop.memberName')"></el-table-column>
-				<el-table-column min-width="70px" prop="perf_status_name" :label="$t('bonus.status')"></el-table-column>
-				<el-table-column min-width="120px" prop="user_perf" :label="$t('bonus.personalBV')">
-					<template slot-scope="{row}">
-						{{ row.user_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-				<el-table-column min-width="120px" prop="team_perf" :label="$t('bonus.PGS')">
-					<template slot-scope="{row}">
-						{{ row.team_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-				<el-table-column min-width="120px" prop="total_perf" :label="$t('bonus.totalBV')">
-					<template slot-scope="{row}">
-						{{ row.total_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-			</el-table-column>
-		</el-table>
+  <div v-loading="loading" class="app-container">
+    <el-table border :data="userData" style="width: 100%" :cell-style="tableCellStyle">
+      <el-table-column :label="$t('bonus.personalDetails')">
+        <el-table-column type="index" :index="indexMethod" width="60px" label="" />
+        <el-table-column min-width="120px" prop="number" :label="$t('shop.memberCode')" />
+        <el-table-column min-width="210px" prop="name" :label="$t('shop.memberName')" />
+        <el-table-column min-width="70px" prop="perf_status_name" :label="$t('bonus.status')" />
+        <el-table-column min-width="120px" prop="user_perf" :label="$t('bonus.personalBV')">
+          <template slot-scope="{row}">
+            {{ row.user_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+        <el-table-column min-width="120px" prop="team_perf" :label="$t('bonus.PGS')">
+          <template slot-scope="{row}">
+            {{ row.team_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+        <el-table-column min-width="120px" prop="total_perf" :label="$t('bonus.totalBV')">
+          <template slot-scope="{row}">
+            {{ row.total_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+      </el-table-column>
+    </el-table>
 
-		<el-table border :data="tableData" style="width: 100%;margin-top:20px;" :cell-style="tableCellStyle">
-			<el-table-column :label="$t('bonus.teamDetails')">
-				<el-table-column type="index" :index="indexMethod" width="60px" label=""></el-table-column>
-				<el-table-column min-width="120px" prop="number" :label="$t('shop.memberCode')"></el-table-column>
-				<el-table-column min-width="210px" prop="name" :label="$t('shop.memberName')"></el-table-column>
-				<el-table-column min-width="70px" prop="perf_status_name" :label="$t('bonus.status')"></el-table-column>
-				<el-table-column min-width="120px" prop="user_perf" :label="$t('bonus.personalBV')">
-					<template slot-scope="{row}">
-						{{ row.user_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-				<el-table-column min-width="120px" prop="team_perf" :label="$t('bonus.PGS')">
-					<template slot-scope="{row}">
-						{{ row.team_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-				<el-table-column min-width="120px" prop="total_perf" :label="$t('bonus.totalBV')">
-					<template slot-scope="{row}">
-						{{ row.total_perf | toThousandFilter }}
-					</template>
-				</el-table-column>
-			</el-table-column>
-		</el-table>
+    <el-table border :data="tableData" style="width: 100%;margin-top:20px;" :cell-style="tableCellStyle">
+      <el-table-column :label="$t('bonus.teamDetails')">
+        <el-table-column type="index" :index="indexMethod" width="60px" label="" />
+        <el-table-column min-width="120px" prop="number" :label="$t('shop.memberCode')" />
+        <el-table-column min-width="210px" prop="name" :label="$t('shop.memberName')" />
+        <el-table-column min-width="70px" prop="perf_status_name" :label="$t('bonus.status')" />
+        <el-table-column min-width="120px" prop="user_perf" :label="$t('bonus.personalBV')">
+          <template slot-scope="{row}">
+            {{ row.user_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+        <el-table-column min-width="120px" prop="team_perf" :label="$t('bonus.PGS')">
+          <template slot-scope="{row}">
+            {{ row.team_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+        <el-table-column min-width="120px" prop="total_perf" :label="$t('bonus.totalBV')">
+          <template slot-scope="{row}">
+            {{ row.total_perf | toThousandFilter }}
+          </template>
+        </el-table-column>
+      </el-table-column>
+    </el-table>
 
-		<el-descriptions  :column="2">
-			<el-descriptions-item :label="$t('bonus.latestCalculationTime')">{{ getWatTime(calcTime) }}</el-descriptions-item>
-		</el-descriptions>
-	</div>
+    <el-descriptions :column="2">
+      <el-descriptions-item :label="$t('bonus.latestCalculationTime')">{{ getWatTime(calcTime) }}</el-descriptions-item>
+    </el-descriptions>
+  </div>
 </template>
 
 <script>
-import {fetchTeamInquiry} from '@/api/bonus'
-import tool from "@/utils/tool"
+import { fetchTeamInquiry } from '@/api/bonus'
+import tool from '@/utils/tool'
 
 export default {
-  name: 'teamInquiry',
+  name: 'TeamInquiry',
   data() {
     return {
-			calcTime: '',
-			userData: [],
-			tableData: [],
-			loading: true,
+      calcTime: '',
+      userData: [],
+      tableData: [],
+      loading: true,
 
-			tool: tool,
+      tool: tool
     }
   },
   created() {
     this.getList()
   },
-	methods: {
+  methods: {
     getList() {
       this.loading = true
-			fetchTeamInquiry().then(response => {
-				this.calcTime = response.data.calcAt
-				this.tableData = response.data.team
-				this.userData = response.data.user
+      fetchTeamInquiry().then(response => {
+        this.calcTime = response.data.calcAt
+        this.tableData = response.data.team
+        this.userData = response.data.user
 
-				this.loading = false
+        this.loading = false
       })
     },
-		tableCellStyle ({row, column, rowIndex, columnIndex}) {
-			if (row.perf_status === '0' && columnIndex === 3) {
-				return 'background-color:rgb(225, 25, 98);font-weight:bold'
-			} else if (row.perf_status === '1' && columnIndex === 3) {
-				return 'background-color:rgb(31, 156, 18);font-weight:bold'
-			}
-		},
-		indexMethod(index) {
-			return index + 1
-		},
-		getWatTime(ts) {
-			ts = parseInt(ts)
-			if (ts) {
-				return this.$moment(ts * 1000).utcOffset('+0100').format('YYYY-MM-DD HH:mm:ss')
-			} else {
-				return ''
-			}
-		}
+    tableCellStyle({ row, column, rowIndex, columnIndex }) {
+      if (row.perf_status === '0' && columnIndex === 3) {
+        return 'background-color:rgb(225, 25, 98);font-weight:bold'
+      } else if (row.perf_status === '1' && columnIndex === 3) {
+        return 'background-color:rgb(31, 156, 18);font-weight:bold'
+      }
+    },
+    indexMethod(index) {
+      return index + 1
+    },
+    getWatTime(ts) {
+      ts = parseInt(ts)
+      if (ts) {
+        return this.$moment(ts * 1000).utcOffset('+0100').format('YYYY-MM-DD HH:mm:ss')
+      } else {
+        return ''
+      }
+    }
   }
 }
 </script>
@@ -160,10 +160,10 @@ export default {
 .el-descriptions {
 	margin-top:20px;
 }
-/deep/ .el-descriptions-item__container {
+::v-deep .el-descriptions-item__container {
 	margin-top:10px;
 }
-/deep/ .el-descriptions-item__label.has-colon {
+::v-deep .el-descriptions-item__label.has-colon {
 	margin-left:10px;
 }
 </style>

+ 0 - 101
src/views/components-demo/markdown.vue

@@ -1,101 +0,0 @@
-<template>
-  <div class="components-container">
-    <aside>Markdown is based on
-      <a href="https://github.com/nhnent/tui.editor" target="_blank">tui.editor</a> ,simply wrapped with Vue.
-      <a
-        target="_blank"
-        href="https://panjiachen.github.io/vue-element-admin-site/feature/component/markdown-editor.html"
-      >
-        Documentation </a>
-    </aside>
-
-    <div class="editor-container">
-      <el-tag class="tag-title">
-        Basic:
-      </el-tag>
-      <markdown-editor v-model="content1" height="300px" />
-    </div>
-
-    <div class="editor-container">
-      <el-tag class="tag-title">
-        Markdown Mode:
-      </el-tag>
-      <markdown-editor ref="markdownEditor" v-model="content2" :options="{hideModeSwitch:true,previewStyle:'tab'}" height="200px" />
-    </div>
-
-    <div class="editor-container">
-      <el-tag class="tag-title">
-        Customize Toolbar:
-      </el-tag>
-      <markdown-editor v-model="content3" :options="{ toolbarItems: ['heading','bold','italic']}" />
-    </div>
-
-    <div class="editor-container">
-      <el-tag class="tag-title">
-        I18n:
-      </el-tag>
-      <el-alert
-        :closable="false"
-        title="You can change the language of the admin system to see the effect"
-        type="success"
-      />
-      <markdown-editor ref="markdownEditor" v-model="content4" :language="language" height="300px" />
-    </div>
-
-    <el-button style="margin-top:80px;" type="primary" icon="el-icon-document" @click="getHtml">
-      Get HTML
-    </el-button>
-    <div v-html="html" />
-  </div>
-</template>
-
-<script>
-import MarkdownEditor from '@/components/MarkdownEditor'
-
-const content = `
-**This is test**
-
-* vue
-* element
-* webpack
-
-`
-export default {
-  name: 'MarkdownDemo',
-  components: { MarkdownEditor },
-  data() {
-    return {
-      content1: content,
-      content2: content,
-      content3: content,
-      content4: content,
-      html: '',
-      languageTypeList: {
-        'en': 'en_US',
-        'zh': 'zh_CN',
-        'es': 'es_ES'
-      }
-    }
-  },
-  computed: {
-    language() {
-      return this.languageTypeList[this.$store.getters.language]
-    }
-  },
-  methods: {
-    getHtml() {
-      this.html = this.$refs.markdownEditor.getHtml()
-      console.log(this.html)
-    }
-  }
-}
-</script>
-
-<style scoped>
-.editor-container{
-  margin-bottom: 30px;
-}
-.tag-title{
-  margin-bottom: 5px;
-}
-</style>

+ 9 - 4
src/views/config/shipping-address-list.vue

@@ -39,7 +39,7 @@
       <el-table-column align="center" :label="$t('common.action')" min-width="150px">
         <template slot-scope="{row}">
 					<el-button-group>
-						<el-button type="primary" size="mini" @click="handleEdit(row)">{{ $t('common.edit') }}</el-button>
+						<el-button type="primary" size="mini" @click="handleEdit(row), getRegion()">{{ $t('common.edit') }}</el-button>
 						<el-button type="danger" size="mini" @click="handleDelete(row.ID)">{{ $t('common.delete') }}</el-button>
 					</el-button-group>
         </template>
@@ -47,7 +47,7 @@
     </el-table>
 
 		<div class="white-box-footer" style="margin-top: 10px;">
-			<el-button size="small" type="primary" @click="dialog = true">{{ $t('config.createAddress') }}</el-button>
+			<el-button size="small" type="primary" @click="dialog = true, getRegion()">{{ $t('config.createAddress') }}</el-button>
 			<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
 		</div>
 
@@ -127,7 +127,7 @@
 </template>
 
 <script>
-import {createAddress, fetchAddressList, updateAddress, deleteAddress} from '@/api/config'
+import {createAddress, fetchAddressList, updateAddress, deleteAddress, getRegionList} from '@/api/config'
 import waves from '@/directive/waves'
 import Pagination from '@/components/Pagination'
 import {getScreenWidth} from "@/utils"
@@ -171,7 +171,7 @@ export default {
 				address: '',
 				isDefault: '',
 			},
-			regionData: region.regionInfo.regionData,
+			regionData: [],
 			screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
 			labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
     }
@@ -180,6 +180,11 @@ export default {
     this.getList()
   },
   methods: {
+    getRegion(){
+      getRegionList().then(response => {
+        this.regionData = response.data
+      })
+    },
     getList() {
       this.listLoading = true
 			fetchAddressList(this.listQuery).then(response => {

+ 102 - 102
src/views/dashboard/admin/components/BarChart.vue

@@ -1,102 +1,102 @@
-<template>
-  <div :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-require('echarts/theme/macarons') // echarts theme
-import resize from './mixins/resize'
-
-const animationDuration = 6000
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '100%'
-    },
-    height: {
-      type: String,
-      default: '300px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.initChart()
-    })
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(this.$el, 'macarons')
-
-      this.chart.setOption({
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: { // 坐标轴指示器,坐标轴触发有效
-            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
-          }
-        },
-        grid: {
-          top: 10,
-          left: '2%',
-          right: '2%',
-          bottom: '3%',
-          containLabel: true
-        },
-        xAxis: [{
-          type: 'category',
-          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
-          axisTick: {
-            alignWithLabel: true
-          }
-        }],
-        yAxis: [{
-          type: 'value',
-          axisTick: {
-            show: false
-          }
-        }],
-        series: [{
-          name: 'pageA',
-          type: 'bar',
-          stack: 'vistors',
-          barWidth: '60%',
-          data: [79, 52, 200, 334, 390, 330, 220],
-          animationDuration
-        }, {
-          name: 'pageB',
-          type: 'bar',
-          stack: 'vistors',
-          barWidth: '60%',
-          data: [80, 52, 200, 334, 390, 330, 220],
-          animationDuration
-        }, {
-          name: 'pageC',
-          type: 'bar',
-          stack: 'vistors',
-          barWidth: '60%',
-          data: [30, 52, 200, 334, 390, 330, 220],
-          animationDuration
-        }]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+const animationDuration = 6000
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
+          }
+        },
+        grid: {
+          top: 10,
+          left: '2%',
+          right: '2%',
+          bottom: '3%',
+          containLabel: true
+        },
+        xAxis: [{
+          type: 'category',
+          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+          axisTick: {
+            alignWithLabel: true
+          }
+        }],
+        yAxis: [{
+          type: 'value',
+          axisTick: {
+            show: false
+          }
+        }],
+        series: [{
+          name: 'pageA',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [79, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }, {
+          name: 'pageB',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [80, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }, {
+          name: 'pageC',
+          type: 'bar',
+          stack: 'vistors',
+          barWidth: '60%',
+          data: [30, 52, 200, 334, 390, 330, 220],
+          animationDuration
+        }]
+      })
+    }
+  }
+}
+</script>

+ 135 - 135
src/views/dashboard/admin/components/LineChart.vue

@@ -1,135 +1,135 @@
-<template>
-  <div :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-require('echarts/theme/macarons') // echarts theme
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '100%'
-    },
-    height: {
-      type: String,
-      default: '350px'
-    },
-    autoResize: {
-      type: Boolean,
-      default: true
-    },
-    chartData: {
-      type: Object,
-      required: true
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  watch: {
-    chartData: {
-      deep: true,
-      handler(val) {
-        this.setOptions(val)
-      }
-    }
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.initChart()
-    })
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(this.$el, 'macarons')
-      this.setOptions(this.chartData)
-    },
-    setOptions({ expectedData, actualData } = {}) {
-      this.chart.setOption({
-        xAxis: {
-          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
-          boundaryGap: false,
-          axisTick: {
-            show: false
-          }
-        },
-        grid: {
-          left: 10,
-          right: 10,
-          bottom: 20,
-          top: 30,
-          containLabel: true
-        },
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            type: 'cross'
-          },
-          padding: [5, 10]
-        },
-        yAxis: {
-          axisTick: {
-            show: false
-          }
-        },
-        legend: {
-          data: ['expected', 'actual']
-        },
-        series: [{
-          name: 'expected', itemStyle: {
-            normal: {
-              color: '#FF005A',
-              lineStyle: {
-                color: '#FF005A',
-                width: 2
-              }
-            }
-          },
-          smooth: true,
-          type: 'line',
-          data: expectedData,
-          animationDuration: 2800,
-          animationEasing: 'cubicInOut'
-        },
-        {
-          name: 'actual',
-          smooth: true,
-          type: 'line',
-          itemStyle: {
-            normal: {
-              color: '#3888fa',
-              lineStyle: {
-                color: '#3888fa',
-                width: 2
-              },
-              areaStyle: {
-                color: '#f3f8ff'
-              }
-            }
-          },
-          data: actualData,
-          animationDuration: 2800,
-          animationEasing: 'quadraticOut'
-        }]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '350px'
+    },
+    autoResize: {
+      type: Boolean,
+      default: true
+    },
+    chartData: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler(val) {
+        this.setOptions(val)
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+      this.setOptions(this.chartData)
+    },
+    setOptions({ expectedData, actualData } = {}) {
+      this.chart.setOption({
+        xAxis: {
+          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+          boundaryGap: false,
+          axisTick: {
+            show: false
+          }
+        },
+        grid: {
+          left: 10,
+          right: 10,
+          bottom: 20,
+          top: 30,
+          containLabel: true
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross'
+          },
+          padding: [5, 10]
+        },
+        yAxis: {
+          axisTick: {
+            show: false
+          }
+        },
+        legend: {
+          data: ['expected', 'actual']
+        },
+        series: [{
+          name: 'expected', itemStyle: {
+            normal: {
+              color: '#FF005A',
+              lineStyle: {
+                color: '#FF005A',
+                width: 2
+              }
+            }
+          },
+          smooth: true,
+          type: 'line',
+          data: expectedData,
+          animationDuration: 2800,
+          animationEasing: 'cubicInOut'
+        },
+        {
+          name: 'actual',
+          smooth: true,
+          type: 'line',
+          itemStyle: {
+            normal: {
+              color: '#3888fa',
+              lineStyle: {
+                color: '#3888fa',
+                width: 2
+              },
+              areaStyle: {
+                color: '#f3f8ff'
+              }
+            }
+          },
+          data: actualData,
+          animationDuration: 2800,
+          animationEasing: 'quadraticOut'
+        }]
+      })
+    }
+  }
+}
+</script>

+ 4 - 6
src/views/dashboard/admin/components/PanelGroup.vue

@@ -17,15 +17,13 @@
     </el-col>
 		<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
 			<div class="card-panel">
-				<!-- <div class="card-panel-icon-wrapper icon-people">
-					<svg-icon icon-class="star" class-name="card-panel-icon" />
-				</div> -->
+
 				<div class="card-panel-description">
 					<div class="card-panel-text">
-						{{ $t('dashboard.highestCrown') }}
+						{{ $t('dashboard.eliteLevel') }}
 					</div>
 					<div class="" style="padding: 10px;">
-						{{ $t(`crownLevels.${heightCrownLv}`) }}
+						{{ $t(`eliteLevels.${eliteLv}`) }}
 					</div>
 				</div>
 			</div>
@@ -100,7 +98,7 @@
 export default {
   props: {
     heightEmpLv : String,
-		heightCrownLv: String,
+    eliteLv: String,
     decLv: String,
     cycle: String,
     rmBv: String | Number,

+ 79 - 79
src/views/dashboard/admin/components/PieChart.vue

@@ -1,79 +1,79 @@
-<template>
-  <div :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-require('echarts/theme/macarons') // echarts theme
-import resize from './mixins/resize'
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '100%'
-    },
-    height: {
-      type: String,
-      default: '300px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.initChart()
-    })
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(this.$el, 'macarons')
-
-      this.chart.setOption({
-        tooltip: {
-          trigger: 'item',
-          formatter: '{a} <br/>{b} : {c} ({d}%)'
-        },
-        legend: {
-          left: 'center',
-          bottom: '10',
-          data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
-        },
-        series: [
-          {
-            name: 'WEEKLY WRITE ARTICLES',
-            type: 'pie',
-            roseType: 'radius',
-            radius: [15, 95],
-            center: ['50%', '38%'],
-            data: [
-              { value: 320, name: 'Industries' },
-              { value: 240, name: 'Technology' },
-              { value: 149, name: 'Forex' },
-              { value: 100, name: 'Gold' },
-              { value: 59, name: 'Forecasts' }
-            ],
-            animationEasing: 'cubicInOut',
-            animationDuration: 2600
-          }
-        ]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'item',
+          formatter: '{a} <br/>{b} : {c} ({d}%)'
+        },
+        legend: {
+          left: 'center',
+          bottom: '10',
+          data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
+        },
+        series: [
+          {
+            name: 'WEEKLY WRITE ARTICLES',
+            type: 'pie',
+            roseType: 'radius',
+            radius: [15, 95],
+            center: ['50%', '38%'],
+            data: [
+              { value: 320, name: 'Industries' },
+              { value: 240, name: 'Technology' },
+              { value: 149, name: 'Forex' },
+              { value: 100, name: 'Gold' },
+              { value: 59, name: 'Forecasts' }
+            ],
+            animationEasing: 'cubicInOut',
+            animationDuration: 2600
+          }
+        ]
+      })
+    }
+  }
+}
+</script>

+ 116 - 116
src/views/dashboard/admin/components/RaddarChart.vue

@@ -1,116 +1,116 @@
-<template>
-  <div :class="className" :style="{height:height,width:width}" />
-</template>
-
-<script>
-import echarts from 'echarts'
-require('echarts/theme/macarons') // echarts theme
-import resize from './mixins/resize'
-
-const animationDuration = 3000
-
-export default {
-  mixins: [resize],
-  props: {
-    className: {
-      type: String,
-      default: 'chart'
-    },
-    width: {
-      type: String,
-      default: '100%'
-    },
-    height: {
-      type: String,
-      default: '300px'
-    }
-  },
-  data() {
-    return {
-      chart: null
-    }
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.initChart()
-    })
-  },
-  beforeDestroy() {
-    if (!this.chart) {
-      return
-    }
-    this.chart.dispose()
-    this.chart = null
-  },
-  methods: {
-    initChart() {
-      this.chart = echarts.init(this.$el, 'macarons')
-
-      this.chart.setOption({
-        tooltip: {
-          trigger: 'axis',
-          axisPointer: { // 坐标轴指示器,坐标轴触发有效
-            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
-          }
-        },
-        radar: {
-          radius: '66%',
-          center: ['50%', '42%'],
-          splitNumber: 8,
-          splitArea: {
-            areaStyle: {
-              color: 'rgba(127,95,132,.3)',
-              opacity: 1,
-              shadowBlur: 45,
-              shadowColor: 'rgba(0,0,0,.5)',
-              shadowOffsetX: 0,
-              shadowOffsetY: 15
-            }
-          },
-          indicator: [
-            { name: 'Sales', max: 10000 },
-            { name: 'Administration', max: 20000 },
-            { name: 'Information Technology', max: 20000 },
-            { name: 'Customer Support', max: 20000 },
-            { name: 'Development', max: 20000 },
-            { name: 'Marketing', max: 20000 }
-          ]
-        },
-        legend: {
-          left: 'center',
-          bottom: '10',
-          data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
-        },
-        series: [{
-          type: 'radar',
-          symbolSize: 0,
-          areaStyle: {
-            normal: {
-              shadowBlur: 13,
-              shadowColor: 'rgba(0,0,0,.2)',
-              shadowOffsetX: 0,
-              shadowOffsetY: 10,
-              opacity: 1
-            }
-          },
-          data: [
-            {
-              value: [5000, 7000, 12000, 11000, 15000, 14000],
-              name: 'Allocated Budget'
-            },
-            {
-              value: [4000, 9000, 15000, 15000, 13000, 11000],
-              name: 'Expected Spending'
-            },
-            {
-              value: [5500, 11000, 12000, 15000, 12000, 12000],
-              name: 'Actual Spending'
-            }
-          ],
-          animationDuration: animationDuration
-        }]
-      })
-    }
-  }
-}
-</script>
+<template>
+  <div :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script>
+import * as echarts from 'echarts'
+require('echarts/theme/macarons') // echarts theme
+import resize from './mixins/resize'
+
+const animationDuration = 3000
+
+export default {
+  mixins: [resize],
+  props: {
+    className: {
+      type: String,
+      default: 'chart'
+    },
+    width: {
+      type: String,
+      default: '100%'
+    },
+    height: {
+      type: String,
+      default: '300px'
+    }
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initChart()
+    })
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    initChart() {
+      this.chart = echarts.init(this.$el, 'macarons')
+
+      this.chart.setOption({
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
+          }
+        },
+        radar: {
+          radius: '66%',
+          center: ['50%', '42%'],
+          splitNumber: 8,
+          splitArea: {
+            areaStyle: {
+              color: 'rgba(127,95,132,.3)',
+              opacity: 1,
+              shadowBlur: 45,
+              shadowColor: 'rgba(0,0,0,.5)',
+              shadowOffsetX: 0,
+              shadowOffsetY: 15
+            }
+          },
+          indicator: [
+            { name: 'Sales', max: 10000 },
+            { name: 'Administration', max: 20000 },
+            { name: 'Information Technology', max: 20000 },
+            { name: 'Customer Support', max: 20000 },
+            { name: 'Development', max: 20000 },
+            { name: 'Marketing', max: 20000 }
+          ]
+        },
+        legend: {
+          left: 'center',
+          bottom: '10',
+          data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
+        },
+        series: [{
+          type: 'radar',
+          symbolSize: 0,
+          areaStyle: {
+            normal: {
+              shadowBlur: 13,
+              shadowColor: 'rgba(0,0,0,.2)',
+              shadowOffsetX: 0,
+              shadowOffsetY: 10,
+              opacity: 1
+            }
+          },
+          data: [
+            {
+              value: [5000, 7000, 12000, 11000, 15000, 14000],
+              name: 'Allocated Budget'
+            },
+            {
+              value: [4000, 9000, 15000, 15000, 13000, 11000],
+              name: 'Expected Spending'
+            },
+            {
+              value: [5500, 11000, 12000, 15000, 12000, 12000],
+              name: 'Actual Spending'
+            }
+          ],
+          animationDuration: animationDuration
+        }]
+      })
+    }
+  }
+}
+</script>

+ 10 - 5
src/views/dashboard/admin/index.vue

@@ -17,7 +17,7 @@
         </el-carousel-item>
       </el-carousel>
     </el-row>
-    <panel-group @handleSetLineChartData="handleSetLineChartData" :rmBv="rmBv" :endTime="endTime" :heightEmpLv='heightEmpLv' :heightCrownLv='heightCrownLv' :decLv="decLv" :key="num" :cycle="cycle" />
+    <panel-group @handleSetLineChartData="handleSetLineChartData" :rmBv="rmBv" :endTime="endTime" :heightEmpLv='heightEmpLv' :eliteLv='eliteLv' :decLv="decLv" :key="num" :cycle="cycle" />
     <el-row :gutter="40" v-loading="loading">
       <el-col :xs="24" :sm="24" :lg="12" v-for="(item,key) in news" :key="key">
         <el-card class="box-card">
@@ -36,7 +36,7 @@
 								</el-button>
 							</template>
 							<template slot-scope="{row}">
-								<span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d}') }}</span>
+								<span>{{ tool.convertToNigeriaDayTime(row.CREATED_AT) }}</span>
 							</template>
 						</el-table-column>
 					</el-table>
@@ -59,7 +59,7 @@
 			<div class="white-box" style="margin-top: -20px; padding: 0;">
 				<div class="white-box-title" style="text-align: center">
 					<h1>{{ article.TITLE }}</h1>
-					<span>{{ article.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+					<span>{{ tool.convertToNigeriaTime(article.CREATED_AT) }}</span>
 				</div>
 				<div v-html="article.CONTENT" class="white-box-content">
 				</div>
@@ -103,6 +103,11 @@ const lineChartData = {
 
 export default {
   name: 'DashboardAdmin',
+  computed: {
+    tool() {
+      return tool
+    }
+  },
   components: {
     GithubCorner,
     PanelGroup,
@@ -127,7 +132,7 @@ export default {
       activeEnd: '',
       baseEmpLevels: [],
       heightEmpLv: '', // 最高级别
-			heightCrownLv: '',
+			eliteLv: '',
       decLv:'', // 当前等级
       cycle: '',//当前业绩期
       rmBv: '',
@@ -196,7 +201,7 @@ export default {
       this.activeEnd = ret.activeEnd
       this.decLv = ret.decLv
       this.heightEmpLv = ret.empLv
-			this.heightCrownLv = ret.crownLv
+			this.eliteLv = ret.eliteLv
       this.cycle = ret.periodNum
       this.rmBv = ret.myRemainPv
       this.endTime = ret.activeEnd

+ 313 - 248
src/views/finance/recharge-list.vue

@@ -1,274 +1,339 @@
 <template>
-	<div class="app-container" v-loading="listLoading">
-		<el-table :data="list" border fit highlight-current-row>
-			<el-table-column align="center" :label="$t('finance.createdTime')" prop="CREATED_AT" min-width="140px">
-				<template slot-scope="{row}">
-					<span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
-				</template>
-			</el-table-column>
-			<el-table-column align="center" min-width="160px" :label="$t('finance.rechargeAmount')" prop="AMOUNT">
-				<template slot-scope="{row}">
-					{{ row.AMOUNT | toThousandFilter }}
-				</template>
-			</el-table-column>
-			<el-table-column align="center" min-width="150px" :label="$t('finance.rechargeStatus')" prop="STATUS_NAME">
-				<template slot-scope="{row}">
-					<el-tag :type="row.AUDIT_STATUS | statusFilter">{{row.STATUS_NAME}}</el-tag>
-				</template>
-			</el-table-column>
-			<el-table-column align="center" min-width="180px" :label="$t('finance.bankName')" prop="OPEN_BANK_NAME"></el-table-column>
-			<el-table-column align="center" min-width="150px" :label="$t('finance.bankAccount')" prop="BANK_NO"></el-table-column>
-			<el-table-column align="center" min-width="150px" :label="$t('finance.printVoucher')">
-				<template slot-scope="{row}">
-					<el-button type="primary" size="mini" v-if="row.AUDIT_STATUS === '0'" @click="handleUpload(row.ID)">{{ $t('finance.uploadVoucher') }}</el-button>
-					<el-button type="success" size="mini" v-if="row.AUDIT_STATUS !== '0'" @click="handleView(row)">{{ $t('finance.viewVoucher') }}</el-button>
-				</template>
-			</el-table-column>
-		</el-table>
+  <div v-loading="listLoading" class="app-container">
+    <el-table :data="list" border fit highlight-current-row>
+      <el-table-column align="center" :label="$t('finance.createdTime')" prop="CREATED_AT" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ tool.convertToNigeriaTime(row.CREATED_AT) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" min-width="160px" :label="$t('finance.rechargeAmount')" prop="AMOUNT">
+        <template slot-scope="{row}">
+          {{ row.AMOUNT | toThousandFilter }}
+        </template>
+      </el-table-column>
+      <el-table-column align="center" min-width="150px" :label="$t('finance.rechargeStatus')" prop="STATUS_NAME">
+        <template slot-scope="{row}">
+          <el-tag :type="row.AUDIT_STATUS | statusFilter">{{ row.STATUS_NAME }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" min-width="180px" :label="$t('finance.bankName')" prop="OPEN_BANK_NAME" />
+      <el-table-column align="center" min-width="150px" :label="$t('finance.paymentReference')" prop="BANK_NO" />
+      <el-table-column align="center" min-width="150px" :label="$t('finance.printVoucher')">
+        <template slot-scope="{row}">
+          <el-button v-if="row.AUDIT_STATUS === '0'" type="primary" size="mini" @click="handleUpload(row.ID)">{{ $t('finance.uploadVoucher') }}</el-button>
+          <el-button v-if="row.AUDIT_STATUS !== '0'" type="success" size="mini" @click="handleView(row)">{{ $t('finance.viewVoucher') }}</el-button>
+          <el-button v-if="row.AUDIT_STATUS === '0'" type="success" size="mini" @click="handleEdit(row)">{{ $t('finance.uploadEdit') }}</el-button>
 
-		<div class="white-box-footer" style="margin-top: 10px;">
-			<el-button size="small" type="primary" @click="dialog = true">{{ $t('finance.recharge') }}</el-button>
-			<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
-		</div>
+        </template>
+      </el-table-column>
+    </el-table>
 
-		<el-dialog :title="$t('finance.recharge')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -70px;">
-			<el-form ref="form" :model="form" :rules="rules" :label-position="labelPosition" v-loading="loading" style="margin-top: -20px; margin-bottom: -30px;">
-				<el-row :gutter="20">
-					<el-col :xs="24" :sm="24" :lg="24">
-						<el-form-item :label="$t('finance.rechargeAmount')" prop="applyAmount" required>
-							<el-input-number v-model.number="form.applyAmount" :min="minAmount" :max="maxAmount" :step="10000" style="width: 100%" clearable></el-input-number>
-						</el-form-item>
-						<el-form-item :label="$t('finance.bankAccount')" prop="bankNo" required>
-							<el-input v-model.trim="form.bankNo" type="text" clearable style="width: 100%"></el-input>
-						</el-form-item>
-						<el-form-item :label="$t('finance.bankName')" prop="openBank" required>
-							<el-select v-model="form.openBank" clearable filterable style="width: 100%">
-								<el-option v-for="(item,key) in bankList" :key="key" :label="item.BANK_NAME" :value="item.BANK_CODE"></el-option>
-							</el-select>
-						</el-form-item>
-						<el-form-item>
-							<el-button type="warning" size="small" @click="onCancel">{{ $t('table.cancel') }}</el-button>
-							<el-button type="primary" size="small" @click="onSubmit">{{ $t('table.confirm') }}</el-button>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-		</el-dialog>
+    <div class="white-box-footer" style="margin-top: 10px;">
+      <el-button size="small" type="primary" @click="dialog = true, isEdit = false">{{ $t('finance.recharge') }}</el-button>
+      <pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
+    </div>
 
-		<el-dialog :title="$t('finance.viewVoucher')" :visible.sync="viewVoucher" :width="screenWidth" style="margin-top: -70px;">
-			<div>
-				<img :src="voucher" alt="" style="height: 100%; width: 100%;" />
-			</div>
-			<div slot="footer" class="dialog-footer">
-				<el-button size="small" type="primary" @click="uploadAgain(auditId)">{{ $t('finance.uploadVoucher') }}</el-button>
-				<el-button size="small" type="normal"  @click="viewVoucher = false">{{ $t('common.close') }}</el-button>
-			</div>
-		</el-dialog>
+    <el-dialog :title="$t('finance.recharge')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -70px;">
+      <el-form ref="form" v-if="dialog" v-loading="loading" :model="form" :rules="rules" :label-position="labelPosition" style="margin-top: -20px; margin-bottom: -30px;">
+        <el-row :gutter="20">
+          <el-col :xs="24" :sm="24" :lg="24">
+            <el-form-item :label="$t('finance.rechargeAmount')" prop="applyAmount" required>
+              <el-input-number v-model.number="form.applyAmount" :min="minAmount" :max="maxAmount" :step="10000" style="width: 100%" clearable />
+            </el-form-item>
+            <el-form-item :label="$t('finance.paymentReference')" prop="bankNo" required>
+              <el-input v-model="form.bankNo" type="text" clearable style="width: 100%" />
+            </el-form-item>
+            <el-form-item :label="$t('finance.bankName')" prop="openBank" required>
+              <el-select v-model="form.openBank" clearable filterable style="width: 100%">
+                <el-option v-for="(item,key) in bankList" :key="key" :label="item.BANK_NAME" :value="item.BANK_CODE" />
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="warning" size="small" @click="onCancel">{{ $t('table.cancel') }}</el-button>
+              <el-button type="primary" size="small" @click="onSubmit">{{ $t('table.confirm') }}</el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-dialog>
 
-		<el-dialog :title="$t('finance.uploadVoucher')" :visible.sync="uploadVoucher" :width="screenWidth" style="margin-top: -70px;">
-			<el-upload
-				class="avatar-uploader"
-				:action="uploadUrl"
-				:show-file-list="false"
-				:headers="uploaderHeaders"
-				:data="uploaderData"
-				:on-success="handleSuccess"
-				:before-upload="uploaderHandleBefore"
-				:on-error="handleError">
-				<img v-if="imageUrl" :src="imageUrl" class="avatar" alt="" />
-				<i v-else class="el-icon-plus avatar-uploader-icon"></i>
-			</el-upload>
-		</el-dialog>
-	</div>
+    <el-dialog :title="$t('finance.viewVoucher')" :visible.sync="viewVoucher" :width="screenWidth" style="margin-top: -70px;">
+      <div>
+        <img :src="voucher" alt="" style="height: 100%; width: 100%;">
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="small" type="primary" @click="uploadAgain(auditId)">{{ $t('finance.uploadVoucher') }}</el-button>
+        <el-button size="small" type="normal" @click="viewVoucher = false">{{ $t('common.close') }}</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog :title="$t('finance.uploadVoucher')" :visible.sync="uploadVoucher" :width="screenWidth" style="margin-top: -70px;">
+      <el-upload
+        class="avatar-uploader"
+        :action="uploadUrl"
+        :show-file-list="false"
+        :headers="uploaderHeaders"
+        :data="uploaderData"
+        :on-success="handleSuccess"
+        :before-upload="uploaderHandleBefore"
+        :on-error="handleError"
+      >
+        <img v-if="imageUrl" :src="imageUrl" class="avatar" alt="">
+        <i v-else class="el-icon-plus avatar-uploader-icon" />
+      </el-upload>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchApplyRecharge,fetchBankList, fetchRechargeList} from '@/api/finance'
-import {fetchToken} from "@/api/file"
+import { fetchApplyRecharge, fetchBankList, fetchRechargeList, editApplyRecharge } from '@/api/finance'
+import { fetchToken } from '@/api/file'
 import waves from '@/directive/waves'
 import Pagination from '@/components/Pagination'
-import tool from "@/utils/tool"
-import {formatAmount, getScreenWidth} from "@/utils"
-import {integer, range, required} from "@/utils/rules"
-import LeoUploader from "@/components/Upload/Uploader"
+import tool from '@/utils/tool'
+import { formatAmount, getScreenWidth } from '@/utils'
+import { integer, range, required } from '@/utils/rules'
+import LeoUploader from '@/components/Upload/Uploader'
 
 export default {
-	name: 'RechargeDetails',
-	components: { Pagination,LeoUploader },
-	directives: { waves },
-	filters: {
-		statusFilter(status) {
-			const statusEnums = {
-				'0': 'info',
-				'1': 'primary',
-				'2': 'success',
-				'3': 'danger',
-			}
-			return statusEnums[status] || 'warning'
-		},
-	},
-	data() {
-		return {
-			tool: tool,
-			list: [],
-			total: 0,
-			listLoading: true,
-			listQuery: {
-				page: 1,
-				pageSize: 5,
-			},
+  name: 'RechargeDetails',
+  components: { Pagination, LeoUploader },
+  directives: { waves },
+  filters: {
+    statusFilter(status) {
+      const statusEnums = {
+        '0': 'info',
+        '1': 'primary',
+        '2': 'success',
+        '3': 'danger'
+      }
+      return statusEnums[status] || 'warning'
+    }
+  },
+  watch: {
+    dialog: {
+      handler(newValue, old){
+        if(newValue === false){
+          this.form = {
+            applyAmount: 1,
+            bankNo: '',
+            openBank: '',
+            bankAddress: ''
+          }
+          this.$forceUpdate()
+        }
+      }
+    },
+    uploadVoucher: {
+      handler(newValue, old){
+        if(newValue === false){
+          this.imageUrl = ''
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      tool: tool,
+      list: [],
+      total: 0,
+      listLoading: true,
+      listQuery: {
+        page: 1,
+        pageSize: 10
+      },
+      dialog: false,
+      loading: false,
+      form: {
+        applyAmount: 0,
+        bankNo: '',
+        openBank: '',
+        bankAddress: ''
+      },
+      minAmount: 1,
+      maxAmount: 10000000000,
+      rules: {
+        applyAmount: [required, integer, range(this.minAmount, this.maxAmount)],
+        bankNo: [{ required: true, message: this.$t('finance.paymentReference') + this.$t('common.require'), trigger: 'blur' }],
+        openBank: [{ required: true, message: this.$t('finance.bankName') + this.$t('common.require'), trigger: 'blur' }]
+      },
+      bankList: [],
+
+      screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+
+      viewVoucher: false,
+      voucher: '',
+      auditId: null,
 
-			dialog: false,
-			loading: false,
-			form: {
-				applyAmount: 0,
-				bankNo: '',
-				openBank: '',
-				bankAddress: '',
-			},
-			minAmount: 1,
-			maxAmount: 10000000000,
-			rules: {
-				applyAmount: [required, integer, range(this.minAmount, this.maxAmount)],
-				bankNo: [required],
-				openBank: [required],
-			},
-			bankList: [],
+      voucherLoading: false,
+      uploadVoucher: false,
+      imageUrl: '',
+      uploadUrl: '',
+      uploaderData: {
+        uploadToken: ''
+      },
+      uploaderHeaders: {
+        'Device-Type': 'pc',
+        'Suppress-Response-Code': '1',
+        'Authorization': ''
+      },
+      isEdit: false,
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {
+    this.fetchBankList()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      fetchRechargeList(this.listQuery).then(response => {
+        this.list = response.data.list
+        this.total = response.data.totalCount
 
-			screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
-			labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+        setTimeout(() => {
+          this.listLoading = false
+        }, 0.5 * 1000)
+      })
+    },
+    fetchBankList() {
+      fetchBankList().then(response => {
+        this.bankList = response.data.allOpenBank
+      })
+    },
+    onSubmit() {
+      this.$refs['form'].validate((valid) => {
+        if (valid) {
+          this.loading = true
+          let form = {}
+          let { applyAmount, bankNo, openBank, bankAddress, ID } = this.form
+          if(this.isEdit){
+            form = { applyAmount, bankNo, openBank, bankAddress, id: ID }
+            editApplyRecharge(form).then(response => {
+              this.$message({
+                message: response.data,
+                type: 'success',
+                duration: 1.5 * 1000
+              })
 
-			viewVoucher: false,
-			voucher: '',
-			auditId: null,
+              this.$refs['form'].resetFields()
+              this.dialog = false
+              this.loading = false
 
-			voucherLoading: false,
-			uploadVoucher: false,
-			imageUrl: '',
-			uploadUrl: '',
-			uploaderData: {
-				uploadToken: '',
-			},
-			uploaderHeaders: {
-				'Device-Type': 'pc',
-				'Suppress-Response-Code': '1',
-				'Authorization': '',
-			},
-		}
-	},
-	created() {
-		this.getList()
-	},
-	mounted() {
-		this.fetchBankList()
-	},
-	methods: {
-		getList() {
-			this.listLoading = true
-			fetchRechargeList(this.listQuery).then(response => {
-				this.list = response.data.list
-				this.total = response.data.totalCount
+              this.getList()
+            }).catch((err) => {
+              this.$message({
+                message: err,
+                type: 'error',
+                duration: 3 * 1000
+              })
 
-				setTimeout(() => {
-					this.listLoading = false
-				}, 0.5 * 1000)
-			})
-		},
-		fetchBankList() {
-			fetchBankList().then(response => {
-				this.bankList = response.data.allOpenBank
-			})
-		},
-		onSubmit() {
-			this.$refs['form'].validate((valid) => {
-				if (valid) {
-					this.loading = true
-					fetchApplyRecharge(this.form).then(response => {
-						this.$message({
-							message: response.data,
-							type: 'success',
-							duration: 1.5 * 1000
-						})
+              this.loading = false
+            })
+          } else {
+            form = { applyAmount, bankNo, openBank, bankAddress }
+            fetchApplyRecharge(form).then(response => {
+              this.$message({
+                message: response.data,
+                type: 'success',
+                duration: 1.5 * 1000
+              })
 
-						this.$refs['form'].resetFields()
-						this.dialog = false
-						this.loading = false
+              this.$refs['form'].resetFields()
+              this.dialog = false
+              this.loading = false
 
-						this.getList()
-					}).catch((err) => {
-						this.$message({
-							message: err,
-							type: 'error',
-							duration: 3 * 1000
-						})
+              this.getList()
+            }).catch((err) => {
+              this.$message({
+                message: err,
+                type: 'error',
+                duration: 3 * 1000
+              })
 
-						this.loading = false
-					})
-				} else {
-					return false;
-				}
-			});
-		},
-		onCancel() {
-			this.dialog = false
-			this.$refs['form'].resetFields()
-		},
-		handleView(row) {
-			this.voucher = tool.getArImage(row.BANK_PROVE, 'files/')
-			this.auditId = row.ID
-			this.viewVoucher = true
-		},
-		uploadAgain(id) {
-			this.viewVoucher = false
-			this.auditId = id
-			this.uploadUrl = `${process.env.VUE_APP_BASE_API}/v1/finance/prove-add?id=${this.auditId}`
-			this.uploadVoucher = true
-		},
-		handleUpload(id) {
-			setTimeout(() => {
-				this.auditId = id
-				this.uploadUrl = `${process.env.VUE_APP_BASE_API}/v1/finance/prove-add?id=${this.auditId}`
-				this.uploadVoucher = true
-			}, 0.5 * 1000)
-		},
-		async uploaderHandleBefore() {
-			this.$message({
-				message: this.$t('common.uploadHints'),
-				type: 'warning',
-				duration: 500,
-			})
+              this.loading = false
+            })
+          }
+        } else {
+          return false
+        }
+      })
+    },
+    onCancel() {
+      this.dialog = false
+      this.$refs['form'].resetFields()
+    },
+    handleView(row) {
+      this.voucher = tool.getArImage(row.BANK_PROVE, 'files/')
+      this.auditId = row.ID
+      this.viewVoucher = true
+    },
+    uploadAgain(id) {
+      this.viewVoucher = false
+      this.auditId = id
+      this.uploadUrl = `${process.env.VUE_APP_BASE_API}/v1/finance/prove-add?id=${this.auditId}`
+      this.uploadVoucher = true
+    },
+    handleUpload(id) {
+      setTimeout(() => {
+        this.auditId = id
+        this.uploadUrl = `${process.env.VUE_APP_BASE_API}/v1/finance/prove-add?id=${this.auditId}`
+        this.uploadVoucher = true
+      }, 0.5 * 1000)
+    },
+    handleEdit(row){
+      let { AMOUNT, BANK_NO, OPEN_BANK, ID } = row
+      this.form = {
+        applyAmount: AMOUNT,
+        bankNo: BANK_NO,
+        openBank: OPEN_BANK,
+        ID: ID
+      }
+      this.isEdit = true
+      this.dialog = true
+      this.$forceUpdate()
+    },
+    async uploaderHandleBefore() {
+      this.$message({
+        message: this.$t('common.uploadHints'),
+        type: 'warning',
+        duration: 500
+      })
 
-			await fetchToken().then(response => {
-				this.uploaderHeaders.Authorization = process.env.VUE_APP_ACCESS_TOKEN_PREFIX + response.data
-				this.uploaderData.uploadToken = response.data
-			})
-		},
-		handleSuccess(res, file) {
-			this.imageUrl = URL.createObjectURL(file.raw)
+      await fetchToken().then(response => {
+        this.uploaderHeaders.Authorization = process.env.VUE_APP_ACCESS_TOKEN_PREFIX + response.data
+        this.uploaderData.uploadToken = response.data
+      })
+    },
+    handleSuccess(res, file) {
+      this.imageUrl = URL.createObjectURL(file.raw)
 
-			setTimeout(() => {
-				this.uploadVoucher = false
-				this.getList()
-			}, 2 * 1000)
-		},
-		beforeUpload(file) {
-			const typeAllowed = ['image/jpeg', 'image/jpg', 'image/png']
-			const isLt2M = file.size / 1024 / 1024 < 2
-			if (!typeAllowed.includes(file.type)) {
-				this.$message.error('图片只能是 JPG/JPEG/PNG 格式!')
-				return false
-			}
-			if (!isLt2M) {
-				this.$message.error('图片大小不能超过 2MB!')
-				return false
-			}
+      setTimeout(() => {
+        this.uploadVoucher = false
+        this.getList()
+      }, 2 * 1000)
+    },
+    beforeUpload(file) {
+      const typeAllowed = ['image/jpeg', 'image/jpg', 'image/png']
+      const isLt2M = file.size / 1024 / 1024 < 2
+      if (!typeAllowed.includes(file.type)) {
+        this.$message.error('图片只能是 JPG/JPEG/PNG 格式!')
+        return false
+      }
+      if (!isLt2M) {
+        this.$message.error('图片大小不能超过 2MB!')
+        return false
+      }
 
-			return true
-		},
-		handleError(err, file) {
-			console.log(err, file)
-		},
-	}
+      return true
+    },
+    handleError(err, file) {
+      console.log(err, file)
+    }
+  }
 }
 </script>
 

+ 11 - 11
src/views/finance/transfer-list.vue

@@ -76,7 +76,7 @@
 			</el-table-column>
 			<el-table-column min-width="160px"  align="center" :label="$t('finance.transferTime')" prop="CREATED_AT">
 				<template slot-scope="{row}">
-					<span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+					<span>{{ tool.convertToNigeriaTime(row.CREATED_AT) }}</span>
 				</template>
 			</el-table-column>
 			<el-table-column align="center" min-width="150px" :label="$t('finance.remark')" prop="REMARK"></el-table-column>
@@ -97,30 +97,30 @@
 							</el-select>
 						</el-form-item>
 						<el-form-item :label="$t('finance.currentAvailableBonus')">
-							<el-input v-model="balance" readonly>
-								<template slot="append">{{ $t('currency.naira') }}</template>
+							<el-input v-model="balance" readonly disabled>
+<!--								<template slot="append">{{ $t('currency.naira') }}</template>-->
 							</el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.currentAvailableEcoin')">
-							<el-input v-model="cash" readonly>
-								<template slot="append">{{ $t('currency.naira') }}</template>
+							<el-input v-model="cash" readonly disabled>
+<!--								<template slot="append">{{ $t('currency.naira') }}</template>-->
 							</el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.currentTransferRatio')" v-if="false">
 							<el-input v-model="transferProp" readonly>
-								<template slot="append">{{ $t('currency.naira') }}</template>
+<!--								<template slot="append">{{ $t('currency.naira') }}</template>-->
 							</el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.maximumTransferAmount')" v-if="false">
 							<el-input v-model="maxAmount" readonly>
-								<template slot="append">{{ $t('currency.naira') }}</template>
+<!--								<template slot="append">{{ $t('currency.naira') }}</template>-->
 							</el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.memberCode')" prop="toUserName" required>
-							<el-input size="small" v-model.trim="form.toUserName" type="text" @change="fetchMember"></el-input>
+							<el-input size="small" v-model="form.toUserName" type="text" @change="fetchMember"></el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.memberName')" prop="toRealName" v-show="form.toRealName !== null">
-							<el-input size="small" v-model.trim="form.toRealName" type="text" disabled></el-input>
+							<el-input size="small" v-model="form.toRealName" type="text" disabled></el-input>
 						</el-form-item>
 						<el-form-item :label="$t('finance.transferAmount')" prop="amount" required>
 							<el-input v-model.number="form.amount" type="number" :min="minAmount" :max="maxAmount" @change="chkReal"></el-input>
@@ -129,10 +129,10 @@
 							<el-tag type="info">{{ fee }}%</el-tag>
 						</el-form-item>
 						<el-form-item :label="$t('finance.actualAmountTransferredInto')" v-show="fee > 0">
-							<el-tag type="warning">{{ realAmount }} {{ $t('currency.naira') }}</el-tag>
+							<el-tag type="warning">{{ realAmount }}</el-tag>
 						</el-form-item>
 						<el-form-item :label="$t('finance.remark')" prop="remark">
-							<el-input size="small" v-model.trim="form.remark" type="text"></el-input>
+							<el-input size="small" v-model="form.remark" type="text"></el-input>
 						</el-form-item>
 						<el-form-item>
 							<el-button type="warning" size="small" @click="onCancel">{{ $t('table.cancel') }}</el-button>

+ 15 - 0
src/views/login/index.vue

@@ -210,6 +210,21 @@ export default {
       })
     },
     handleLogin() {
+			if (!this.loginForm.username) {
+				this.$message({
+					message: this.$t('login.username') + this.$t('common.canNotBeBlank'),
+					type: 'error'
+				})
+				return false;
+			}
+			if (!this.loginForm.password) {
+				this.$message({
+					message: this.$t('login.password') + this.$t('common.canNotBeBlank'),
+					type: 'error'
+				})
+				return false;
+			}
+
       this.$refs.loginForm.validate(valid => {
         if (valid) {
           this.loading = true

+ 91 - 60
src/views/profile/components/Account.vue

@@ -1,27 +1,30 @@
 <template>
-	<el-card style="margin: 2px 1px;">
-		<div slot="header" class="clearfix">
-			<span>{{ $t('profile.personalInformation') }}</span>
-		</div>
+  <el-card style="margin: 2px 1px;">
+    <div slot="header" class="clearfix">
+      <span>{{ $t('profile.personalInformation') }}</span>
+    </div>
 
-		<el-form wi v-loading="loading">
-			<el-form-item :label="$t('shop.memberCode')">
-				<el-input size="medium" v-model.trim="user.name" prefix-icon="el-icon-user-solid" readonly />
-			</el-form-item>
-			<el-form-item :label="$t('shop.memberName')">
-				<el-input size="medium" v-model.trim="user.realName" prefix-icon="el-icon-user" readonly />
-			</el-form-item>
-			<el-form-item :label="$t('shop.phoneNumber')">
-				<el-input size="medium" v-model.trim="user.mobile" prefix-icon="el-icon-phone-outline" readonly />
-			</el-form-item>
-			<el-form-item :label="$t('user.email')">
-				<el-input size="medium" v-model.trim="user.email" prefix-icon="el-icon-s-comment" />
-			</el-form-item>
-			<el-form-item>
-				<el-button type="primary" size="small" @click="submit">{{ $t('common.save') }}</el-button>
-			</el-form-item>
-		</el-form>
-	</el-card>
+    <el-form v-loading="loading">
+      <el-form-item :label="$t('shop.country')">
+        <el-input v-model="countryName" size="medium" prefix-icon="el-icon-user-solid" readonly />
+      </el-form-item>
+      <el-form-item :label="$t('shop.memberCode')">
+        <el-input v-model="user.name" size="medium" prefix-icon="el-icon-user-solid" readonly />
+      </el-form-item>
+      <el-form-item :label="$t('shop.memberName')">
+        <el-input v-model="user.realName" size="medium" prefix-icon="el-icon-user" readonly />
+      </el-form-item>
+      <el-form-item :label="$t('shop.phoneNumber')">
+        <el-input v-model.trim="user.mobile" size="medium" prefix-icon="el-icon-phone-outline" readonly />
+      </el-form-item>
+      <el-form-item :label="$t('user.email')">
+        <el-input v-model.trim="user.email" size="medium" prefix-icon="el-icon-s-comment" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" size="small" @click="submit">{{ $t('common.save') }}</el-button>
+      </el-form-item>
+    </el-form>
+  </el-card>
 </template>
 
 <script>
@@ -36,51 +39,79 @@ export default {
         return {
           name: '',
           email: '',
-					mobile: '',
-					realName: '',
+          mobile: '',
+          realName: ''
         }
       }
     }
   },
-	data() {
-		return {
-			loading: false,
-		}
-	},
+  data() {
+    return {
+      loading: false,
+      countryName:''
+    }
+  },
+  mounted() {
+    this.getCountries()
+  },
+  watch:{
+    countriesList: {
+      handler(newValue, old) {
+        if (newValue) {
+          this.getCountryId()
+        }
+      },
+    },
+  },
+  computed:{
+    countriesList() {
+      return this.$store.getters.getCountriesList
+    },
+  },
   methods: {
     submit() {
-			const data = {
-				bankNo: '1',
-				bankAddress: '1',
-				email: this.user.email,
-				mobile: this.user.mobile,
-				nation: '',
-				openBank: '',
-				realName: this.user.realName,
-			}
+      const data = {
+        bankNo: '1',
+        bankAddress: '1',
+        email: this.user.email,
+        mobile: this.user.mobile,
+        nation: '',
+        openBank: '',
+        realName: this.user.realName
+      }
 
-			this.loading = true
-			updateInfo(data).then(() => {
-				setTimeout(() => {
-					this.loading = false
-				}, 1.5 * 1000)
-				this.$message({
-					message: 'User information has been updated successfully.',
-					type: 'success',
-					duration: 5 * 1000
-				})
-				// 覆盖localStorage
-				usersInfo.userEmail(this.user.email)
-				// 页面重载
-				location.reload()
-			}).catch((err) => {
-				this.$message({
-					message: err,
-					type: 'error',
-					duration: 5 * 1000
-				})
-				this.loading = false
-			})
+      this.loading = true
+      updateInfo(data).then(() => {
+        setTimeout(() => {
+          this.loading = false
+        }, 1.5 * 1000)
+        this.$message({
+          message: 'User information has been updated successfully.',
+          type: 'success',
+          duration: 5 * 1000
+        })
+        // 覆盖localStorage
+        usersInfo.userEmail(this.user.email)
+        // 页面重载
+        location.reload()
+      }).catch((err) => {
+        this.$message({
+          message: err,
+          type: 'error',
+          duration: 5 * 1000
+        })
+        this.loading = false
+      })
+    },
+    //国家列表
+    getCountries() {
+      this.$store.dispatch('settings/getCountries')
+    },
+    getCountryId(){
+      let countryId = JSON.parse(window.localStorage.getItem('baseData')).COUNTRY_ID
+      let country =  this.countriesList.find(item => item.ID === countryId)
+      console.log(country)
+      this.countryName = country.NAME
     }
   }
 }

+ 26 - 4
src/views/profile/components/UserCard.vue

@@ -30,7 +30,7 @@
 							</el-col>
 							<el-col :span="12">
 								<div class="grid-content bg-purple-light">
-									<span>{{ tool.formatDate(tool.getTimestamp()) }}</span>
+									<span>{{ nowDateTime }}</span>
 								</div>
 							</el-col>
 						</el-row>
@@ -89,12 +89,12 @@
 							<el-col :span="12">
 								<div class="grid-content bg-purple">
 									<i class="el-icon-medal-1"></i>
-									<span>{{ $t('profile.highestCrown') }}</span>
+									<span>{{ $t('profile.eliteLevel') }}</span>
 								</div>
 							</el-col>
 							<el-col :span="12">
 								<div class="grid-content bg-purple-light">
-									<span>{{ user.crownLv }}</span>
+									<span>{{ user.eliteLv }}</span>
 								</div>
 							</el-col>
 						</el-row>
@@ -124,6 +124,7 @@ export default {
 					empLv: '',
 					crownLv: '',
 					periodNum: '',
+          eliteLv: ''
         }
       }
     },
@@ -131,8 +132,29 @@ export default {
 	data() {
 		return {
 			tool: tool,
-		}
+      nowTime: this.getTime()
+    }
 	},
+  computed: {
+    nowDateTime() {
+      return this.$moment(this.nowTime * 1000).utcOffset('+0100' ).format('YYYY-MM-DD HH:mm:ss') + ' (WAT)'
+    },
+  },
+  mounted() {
+    this.calcTime()
+  },
+  methods: {
+    getTime() {
+      let dateObj = new Date()
+      return Math.round(dateObj.getTime() / 1000 + (0 * 86400))
+    },
+    calcTime () {
+      let obj = this
+      setInterval(function () {
+        obj.nowTime += 1
+      }, 1000)
+    },
+  }
 }
 </script>
 

+ 37 - 30
src/views/profile/index.vue

@@ -1,33 +1,33 @@
 <template>
   <div class="app-container">
     <div v-if="user">
-      <el-row :gutter="20">
+      <el-row :gutter="20" class="el_c">
 
         <el-col :span="8" :xs="24">
           <user-card :user="user" />
 
-					<account :user="user" />
+          <account :user="user" />
 
-					<login-password />
+          <login-password />
 
-					<payment-password />
+          <payment-password />
         </el-col>
 
-<!--        <el-col :span="8" :xs="24">-->
-<!--          <el-card style="margin: 2px 1px;">-->
-<!--            <el-tabs v-model="activeTab">-->
-<!--              <el-tab-pane :label="$t('profile.account')" name="account">-->
-<!--                <account :user="user" />-->
-<!--              </el-tab-pane>-->
-<!--              <el-tab-pane :label="$t('profile.loginPassword')" name="loginPassword">-->
-<!--                <login-password />-->
-<!--              </el-tab-pane>-->
-<!--              <el-tab-pane :label="$t('profile.paymentPassword')" name="paymentPassword">-->
-<!--                <payment-password />-->
-<!--              </el-tab-pane>-->
-<!--            </el-tabs>-->
-<!--          </el-card>-->
-<!--        </el-col>-->
+        <!--        <el-col :span="8" :xs="24">-->
+        <!--          <el-card style="margin: 2px 1px;">-->
+        <!--            <el-tabs v-model="activeTab">-->
+        <!--              <el-tab-pane :label="$t('profile.account')" name="account">-->
+        <!--                <account :user="user" />-->
+        <!--              </el-tab-pane>-->
+        <!--              <el-tab-pane :label="$t('profile.loginPassword')" name="loginPassword">-->
+        <!--                <login-password />-->
+        <!--              </el-tab-pane>-->
+        <!--              <el-tab-pane :label="$t('profile.paymentPassword')" name="paymentPassword">-->
+        <!--                <payment-password />-->
+        <!--              </el-tab-pane>-->
+        <!--            </el-tabs>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
 
       </el-row>
     </div>
@@ -35,18 +35,18 @@
 </template>
 
 <script>
+import usersInfo from '@/utils/usersInfo'
+import LoginPassword from '@/views/profile/components/LoginPassword'
+import PaymentPassword from '@/views/profile/components/PaymentPassword'
 import { mapGetters } from 'vuex'
-import UserCard from './components/UserCard'
+import Account from './components/Account'
 import Activity from './components/Activity'
 import Timeline from './components/Timeline'
-import Account from './components/Account'
-import usersInfo from '@/utils/usersInfo'
-import LoginPassword from '@/views/profile/components/LoginPassword'
-import PaymentPassword from "@/views/profile/components/PaymentPassword";
+import UserCard from './components/UserCard'
 
 export default {
   name: 'Profile',
-  components: {PaymentPassword, LoginPassword, UserCard, Activity, Timeline, Account },
+  components: { PaymentPassword, LoginPassword, UserCard, Activity, Timeline, Account },
   data() {
     return {
       user: {},
@@ -61,7 +61,7 @@ export default {
       'mobile',
       'realName',
       'decLv',
-      'crownLv',
+      'crownLv'
     ])
 
   },
@@ -71,18 +71,25 @@ export default {
   methods: {
     getUser() {
       this.user = {
-				role: this.roles.join(' | '),
+        role: this.roles.join(' | '),
         name: usersInfo.userName(),
         email: usersInfo.userEmail(),
         mobile: usersInfo.baseData().MOBILE,
         realName: usersInfo.baseData().REAL_NAME,
         // avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
-				decLv: usersInfo.getBaseInfo().decLevels[usersInfo.baseData().DEC_LV].LEVEL_NAME,
+        decLv: usersInfo.getBaseInfo().decLevels[usersInfo.baseData().DEC_LV].LEVEL_NAME,
         empLv: usersInfo.getBaseInfo().empLevels[usersInfo.baseData().EMP_LV].LEVEL_NAME,
-        crownLv: usersInfo.getBaseInfo().crownLevels[usersInfo.baseData().CROWN_LV].LEVEL_NAME,
-				periodNum: usersInfo.getBaseInfo().periodNum,
+        periodNum: usersInfo.getBaseInfo().periodNum,
+        eliteLv: usersInfo.getBaseInfo().eliteLevels[usersInfo.baseData().ELITE_LV].LEVEL_NAME,
       }
     }
   }
 }
 </script>
+
+<style lang="scss" scoped>
+.el_c{
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 4 - 4
src/views/shop/ba-dec-order-list.vue

@@ -29,12 +29,12 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.productPrice')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row.REAL_PRICE | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row.REAL_PRICE | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalPrice')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | priceAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | priceAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalBV')">
@@ -49,7 +49,7 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalTaxAmount')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | taxAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | taxAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 							</el-table>
@@ -180,7 +180,7 @@ export default {
 				const { fileUrl, targetName } = response.data
 				const downloadElement = document.createElement('a')
 				downloadElement.target = '_blank'
-				downloadElement.href = process.env.VUE_APP_BASE_API + '/' + fileUrl
+				downloadElement.href = process.env.VUE_APP_BASE_DO_API + '/' + fileUrl
 				downloadElement.download = targetName
 				downloadElement.click()
 			})

+ 541 - 531
src/views/shop/car-fund-products.vue

@@ -1,564 +1,574 @@
 <template>
-	<div class="app-container">
-		<el-table :data="tableData" :show-header="false" :key="tableKey" v-loading="listLoading" fit ref="multipleTable" @selection-change="handleSelectionChange">
-			<el-table-column type="selection" width="30" align="center"></el-table-column>
-			<el-table-column align="center">
-				<template slot-scope="{row, $index}">
-					<el-container>
-						<el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-							<el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-						</el-aside>
-						<el-main style="padding: 5px 5px; text-align: left;">
-							<el-row :gutter="10">
-								<el-col :xs="24" :sm="24" :lg="6">
-									<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="4">
-									<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="5">
-								<span style="font-size: 13px;">
-									<span style="font-weight: bold; color: tomato;">{{ $t('shop.productPrice') }}:{{ row.SELL_PRICE | toThousandFilter }}</span>
-								</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="4">
-									<span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="5">
-									<el-input-number size="mini" v-model="storeNums[$index]" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)"></el-input-number>
-								</el-col>
-							</el-row>
-						</el-main>
-					</el-container>
-				</template>
-			</el-table-column>
-		</el-table>
+  <div class="app-container">
+    <el-table :key="tableKey" ref="multipleTable" v-loading="listLoading" :data="tableData" :show-header="false" fit @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="30" align="center" />
+      <el-table-column align="center">
+        <template slot-scope="{row, $index}">
+          <el-container>
+            <el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+              <el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+            </el-aside>
+            <el-main style="padding: 5px 5px; text-align: left;">
+              <el-row :gutter="10">
+                <el-col :xs="24" :sm="24" :lg="6">
+                  <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <span style="font-size: 13px;">
+                    <span style="font-weight: bold; color: tomato;">{{ $t('shop.productPrice') }}:{{ row.SELL_PRICE | toThousandFilter }}</span>
+                  </span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <el-input-number v-model="storeNums[$index]" size="mini" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)" />
+                </el-col>
+              </el-row>
+            </el-main>
+          </el-container>
+        </template>
+      </el-table-column>
+    </el-table>
 
-		<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
 
-		<div class="white-box-footer" style="margin-top: 15px;" v-show="total>0">
-			<div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
-				<el-button type="primary" size="small" @click="settlement()" style="float: left;">{{ $t('shop.checkOut') }}</el-button>
-			</div>
-			<div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
-				<div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ sellPriceSum | toThousandFilter }}</div>
-				<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ taxSum | toThousandFilter }}</div>
-			</div>
-		</div>
+    <div v-show="total>0" class="white-box-footer" style="margin-top: 15px;">
+      <div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
+        <el-button type="primary" size="small" style="float: left;" @click="settlement()">{{ $t('shop.checkOut') }}</el-button>
+      </div>
+      <div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}: {{ sellPriceSum | toThousandFilter }}</div>
+        <div style="display: inline-block;">{{ $t('shop.taxAmount') }}: {{ taxSum | toThousandFilter }}</div>
+      </div>
+    </div>
 
-		<!-- 购物车	-->
-		<el-dialog :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;">
-			<div v-loading="loading">
-				<div class="white-box">
-					<el-table :data="goods" :show-header="false">
-						<el-table-column align="center">
-							<template slot-scope="{row}">
-								<el-container>
-									<el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-										<el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-									</el-aside>
-									<el-main style="padding: 10px 5px; text-align: left;">
-										<el-row :gutter="10">
-											<el-col :xs="24" :sm="8" :lg="8">
-												<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-											</el-col>
-											<el-col :xs="24" :sm="4" :lg="4">
-												<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-											</el-col>
-											<el-col :xs="16" :sm="4" :lg="4">
-												<span style="font-weight: bold;">{{ row.member_price | toThousandFilter }}</span>
-											</el-col>
-											<el-col :xs="8" :sm="3" :lg="3">
-												<span style="">x {{ row.chose_num }}</span>
-											</el-col>
-											<el-col :xs="24" :sm="5" :lg="5">
-												<span style="color: tomato; font-weight: bold;">{{ row.member_price_plus | toThousandFilter }}</span>
-											</el-col>
-										</el-row>
-									</el-main>
-								</el-container>
-							</template>
-						</el-table-column>
-					</el-table>
+    <!-- 购物车	-->
+    <el-dialog :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;" :close="cleanShowCart" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false">
+      <div v-loading="loading">
+        <div class="white-box">
+          <el-table :data="goods" :show-header="false">
+            <el-table-column align="center">
+              <template slot-scope="{row}">
+                <el-container>
+                  <el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+                    <el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+                  </el-aside>
+                  <el-main style="padding: 10px 5px; text-align: left;">
+                    <el-row :gutter="10">
+                      <el-col :xs="24" :sm="8" :lg="8">
+                        <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="4" :lg="4">
+                        <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                      </el-col>
+                      <el-col :xs="16" :sm="4" :lg="4">
+                        <span style="font-weight: bold;">{{ row.member_price | toThousandFilter }}</span>
+                      </el-col>
+                      <el-col :xs="8" :sm="3" :lg="3">
+                        <span style="">x {{ row.chose_num }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="5" :lg="5">
+                        <span style="color: tomato; font-weight: bold;">{{ row.member_price_plus | toThousandFilter }}</span>
+                      </el-col>
+                    </el-row>
+                  </el-main>
+                </el-container>
+              </template>
+            </el-table-column>
+          </el-table>
 
-					<div class="white-box-footer">
-						<!-- 订单合计 -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="20">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
-									<span>{{ $t('shop.total') }}:{{ parseFloat(pointsSum) | toThousandFilter }}</span>
-									<span>{{ $t('shop.freight') }}:{{ pointFreight }}</span>
-								</el-col>
-							</el-row>
-						</div>
-						<el-divider></el-divider>
-						<!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-									<el-radio-group v-model="payType" @change='chosePayType'>
-										<div v-for="(item, index) in payList" :key='index' class="address">
-											<el-radio :label="item.label" border>
-												{{ item.name }}<span v-if="item.label === payType" style="color: tomato;">({{ userBalance[payType] | toThousandFilter }})</span>
-											</el-radio>
-										</div>
-									</el-radio-group>
-								</el-col>
-							</el-row>
-						</div>
-						<el-divider></el-divider>
-						<!-- 收货地址 -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-									<el-radio-group v-model="addressId" @change='choseAddress'>
-										<div class="address">
-											<el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
-										</div>
-										<div v-for="(item, index) in shippingAddressList" :key='index' class="address">
-											<el-radio :label="item.ID" style="word-break: break-all; white-space: normal;">
-												<span>{{item.ADDRESS}}, {{item.LGA_NAME}}, {{item.PROVINCE_NAME}}</span>
-												<el-divider direction="vertical"></el-divider>
-												<span>{{item.MOBILE}}</span>
-												<el-divider direction="vertical"></el-divider>
-												<span>{{item.CONSIGNEE}}</span>
-											</el-radio>
-										</div>
-									</el-radio-group>
-								</el-col>
-							</el-row>
-						</div>
-					</div>
+          <div class="white-box-footer">
+            <!-- 订单合计 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
+                  <span>{{ $t('shop.total') }}:{{ parseFloat(pointsSum) | toThousandFilter }}</span>
+                  <span>{{ $t('shop.freight') }}:{{ pointFreight }}</span>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="payType" @change="chosePayType">
+                    <div v-for="(item, index) in payList" :key="index" class="address">
+                      <el-radio :label="item.label" border>
+                        {{ item.name }}<span v-if="item.label === payType" style="color: tomato;">({{ userBalance[payType] | toThousandFilter }})</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <!-- 收货地址 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="addressId" @change="choseAddress">
+                    <div class="address">
+                      <el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
+                    </div>
+                    <div v-for="(item, index) in shippingAddressList" :key="index" class="address">
+                      <el-radio :label="item.ID" style="word-break: break-all; white-space: normal;">
+                        <span>{{ item.ADDRESS }}, {{ item.LGA_NAME }}, {{ item.PROVINCE_NAME }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.MOBILE }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.CONSIGNEE }}</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
 
-					<div class="white-box-footer" >
-						<el-row :gutter="40">
-							<el-col :xs="24" :sm="24" :lg="24" align="left">
-								<el-button type="warning"  size="small" @click="visibleShoppingCart = false">{{ $t('shop.goBack') }}</el-button>
-								<el-button type="primary" size="small" @click="orderSubmit" :loading="submitButtonStat">{{ $t('shop.goPay') }}</el-button>
-							</el-col>
-						</el-row>
-					</div>
-				</div>
-			</div>
-		</el-dialog>
+          <div class="white-box-footer">
+            <el-row :gutter="40">
+              <el-col :xs="24" :sm="24" :lg="24" align="left">
+                <el-button type="warning" size="small" @click="cleanShowCart">{{ $t('shop.goBack') }}</el-button>
+                <el-button type="primary" size="small" :loading="submitButtonStat" @click="orderSubmit">{{ $t('shop.goPay') }}</el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
 
-		<!-- 商品详情 -->
-		<el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
-			<el-row :gutter="20">
-				<el-col :xs="24" :sm="12" :lg="12">
-					<el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')"></el-image>
-				</el-col>
-				<el-col :xs="24" :sm="12" :lg="12">
-					<div style="text-align: left; line-height: 50px; font-size: 16px;">
-						<span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br />
-						<span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br />
-						<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ product.SELL_PRICE | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br />
-						<span>{{ $t('shop.taxAmount') }}:{{ product.taxAmount | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
-					</div>
-				</el-col>
-			</el-row>
-		</el-dialog>
-	</div>
+    <!-- 商品详情 -->
+    <el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="12" :lg="12">
+          <el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')" />
+        </el-col>
+        <el-col :xs="24" :sm="12" :lg="12">
+          <div style="text-align: left; line-height: 50px; font-size: 16px;">
+            <span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br>
+            <span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br>
+            <span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ product.SELL_PRICE | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br>
+            <span>{{ $t('shop.taxAmount') }}:{{ product.taxAmount | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchProductList, fetchShoppingCart, createOrder} from '@/api/shop'
+import { createOrder, fetchProductList, fetchShoppingCart } from '@/api/shop'
+import Pagination from '@/components/Pagination'
 import waves from '@/directive/waves'
-import {formatAmount, getMedia, getScreenWidth} from '@/utils'
+import { getScreenWidth } from '@/utils'
 import tool from '@/utils/tool'
-import Pagination from '@/components/Pagination'
-import usersInfo from "@/utils/usersInfo"
+import usersInfo from '@/utils/usersInfo'
 
 export default {
-	name: 'CarFundProducts',
-	components: { Pagination },
-	directives: { waves },
-	filters: {
-		priceFilter(price) {
-			return tool.formatPrice(price)
-		},
-		taxAmountFilter(row) {
-			return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-		},
-		statusFilter(status) {
-			const statusMap = {
-				Unpaid: 'info',
-				Paid: 'success',
-			}
-			return statusMap[status]
-		},
-	},
-	data() {
-		return {
-			tableKey: 0,
-			list: [],
-			total: 0,
-			tableData: [],
-			listLoading: true,
-			listQuery: {
-				categoryType: 5,
-				page: 1,
-				limit: 50,
-			},
-			tool: tool,
-			multipleSelection: [],
-			sellPriceSum: 0.00,
-			pricePvSum: 0.00,
-			taxSum: 0.00,
-			storeNums: [],
-			display: false,
-			currentPage: 1,
-			shoppingCartGoods: [],
+  name: 'CarFundProducts',
+  components: { Pagination },
+  directives: { waves },
+  filters: {
+    priceFilter(price) {
+      return tool.formatPrice(price)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: [],
+      total: 0,
+      tableData: [],
+      listLoading: true,
+      listQuery: {
+        categoryType: 5,
+        page: 1,
+        limit: 50
+      },
+      tool: tool,
+      multipleSelection: [],
+      sellPriceSum: 0.00,
+      pricePvSum: 0.00,
+      taxSum: 0.00,
+      storeNums: [],
+      display: false,
+      currentPage: 1,
+      shoppingCartGoods: [],
 
-			visibleShoppingCart: false,
-			loading: false,
+      visibleShoppingCart: false,
+      loading: false,
 
-			goods: [],
-			payList: [],
-			cashCurrency: '',
-			currency: {},
-			pointsSum: 0,
-			pointFreight: 0,
-			freeShipping: '',
-			goodsId: '',
-			goodsNum: '',
-			payPassword: '',
-			submitButtonStat: false,
-			sn: '',
-			orderType: '',
-			payDialog: false,
-			totalAmount: 0.00,
-			freight: 0.00,
-			userBalance: {},
+      goods: [],
+      payList: [],
+      cashCurrency: '',
+      currency: {},
+      pointsSum: 0,
+      pointFreight: 0,
+      freeShipping: '',
+      goodsId: '',
+      goodsNum: '',
+      payPassword: '',
+      submitButtonStat: false,
+      sn: '',
+      orderType: '',
+      payDialog: false,
+      totalAmount: 0.00,
+      freight: 0.00,
+      userBalance: {},
 
-			payType: 'garage_points',
-			addressId: '',
-			selfPickUpAddressId: '100000000000000000',
-			shippingAddressList: [],
+      payType: 'garage_points',
+      addressId: '',
+      selfPickUpAddressId: '100000000000000000',
+      shippingAddressList: [],
 
-			screenWidth: getScreenWidth() > 600 ? '80%' : getScreenWidth() + 'px',
-			labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      screenWidth: getScreenWidth() > 600 ? '80%' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
 
-			visibleProduct: false,
-			product: {
-				GOODS_NAME: '',
-				GOODS_NO: '',
-				COVER: '',
-				SELL_PRICE: 0,
-				PRICE_PV: 0,
-				TAX_RATE: 0,
-				taxAmount: 0,
-			},
-			imageStyle: 'margin-top: -50px;',
-		}
-	},
-	created() {
-		this.getList()
-	},
-	mounted() {
-		// 支付方式、账户信息、余额
-		this.getShoppingCart()
-	},
-	methods: {
-		getList() {
-			this.listLoading = true
-			fetchProductList(this.listQuery).then(response => {
-				this.list = response.data.list
-				this.total = response.data.totalCount
+      visibleProduct: false,
+      product: {
+        GOODS_NAME: '',
+        GOODS_NO: '',
+        COVER: '',
+        SELL_PRICE: 0,
+        PRICE_PV: 0,
+        TAX_RATE: 0,
+        taxAmount: 0
+      },
+      imageStyle: 'margin-top: -50px;'
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {
+    // 支付方式、账户信息、余额
+    this.getShoppingCart()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      fetchProductList(this.listQuery).then(response => {
+        this.list = response.data.list
+        this.total = response.data.totalCount
 
-				setTimeout(() => {
-					this.listLoading = false
-				}, 1.5 * 1000)
+        setTimeout(() => {
+          this.listLoading = false
+        }, 1.5 * 1000)
 
-				let settingObj = this.list
-				for (let i in this.list) {
-					this.storeNums[i] = 1
-					settingObj[i].chose_num = 0
-				}
+        const settingObj = this.list
+        for (const i in this.list) {
+          this.storeNums[i] = 1
+          settingObj[i].chose_num = 0
+        }
 
-				this.tableData = Object.values(settingObj)
-				let pageList = this.multipleSelection[this.currentPage]
-				this.$nextTick(function () {
-					for (let i in this.tableData) {
-						for( let j in  pageList) {
-							if( pageList[j].ID === this.tableData[i].ID ) {
-								this.$data.storeNums[i] = pageList[j].chose_num
-								this.tableData[i].chose_num = pageList[j].chose_num
-								break
-							}
-						}
-					}
-				})
-			})
-		},
-		// 选择商品计数
-		handleInputNumber(current, row){
-			let pageList = this.multipleSelection[this.listQuery.page]
-			let selectStatus = false
-			for (let i in pageList) {
-				if (pageList[i].ID === row.ID) {
-					pageList[i].chose_num = current
-					selectStatus = true
-					break
-				}
-			}
-			if (selectStatus) {
-				this.multipleSelection[this.listQuery.page] = pageList
-				this.handleSureChange()
-			}
-		},
-		// 统计商品
-		handleSureChange() {
-			if (this.multipleSelection.length > 0) {
-				let accumulatorSellPrice = 0, accumulatorPricePv = 0, accumulatorTax = 0
-				this.multipleSelection.forEach(item => {
-					item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100; })
-					item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100); })
-					item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)); })
-				})
+        this.tableData = Object.values(settingObj)
+        const pageList = this.multipleSelection[this.currentPage]
+        this.$nextTick(function() {
+          for (const i in this.tableData) {
+            for (const j in pageList) {
+              if (pageList[j].ID === this.tableData[i].ID) {
+                this.$data.storeNums[i] = pageList[j].chose_num
+                this.tableData[i].chose_num = pageList[j].chose_num
+                break
+              }
+            }
+          }
+        })
+      })
+    },
+    // 选择商品计数
+    handleInputNumber(current, row) {
+      const pageList = this.multipleSelection[this.listQuery.page]
+      let selectStatus = false
+      for (const i in pageList) {
+        if (pageList[i].ID === row.ID) {
+          pageList[i].chose_num = current
+          selectStatus = true
+          break
+        }
+      }
+      if (selectStatus) {
+        this.multipleSelection[this.listQuery.page] = pageList
+        this.handleSureChange()
+      }
+    },
+    // 统计商品
+    handleSureChange() {
+      if (this.multipleSelection.length > 0) {
+        let accumulatorSellPrice = 0; let accumulatorPricePv = 0; let accumulatorTax = 0
+        this.multipleSelection.forEach(item => {
+          item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100 })
+          item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100) })
+          item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)) })
+        })
 
-				this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
-				this.pricePvSum = tool.formatPrice(accumulatorPricePv)
-				this.taxSum = tool.formatPrice(accumulatorTax)
+        this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
+        this.pricePvSum = tool.formatPrice(accumulatorPricePv)
+        this.taxSum = tool.formatPrice(accumulatorTax)
 
-				this.display = true
-			} else {
-				this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
-				this.display = true
-			}
-		},
-		// 选择商品
-		handleSelectionChange(val) {
-			let idx = -1, num
-			for (let i in this.tableData) {
-				for (let v in val){
-					if (val[v].ID === this.tableData[i].ID) {
-						idx = i
-						num = this.storeNums[idx]
-						val[v]['chose_num'] = num
-						break
-					}
-				}
-			}
-			this.multipleSelection[this.listQuery.page] = val
-			// 计算统计
-			this.handleSureChange()
-		},
-		// 结算商品
-		settlement() {
-			if (this.multipleSelection.length <= 0) {
-				this.$message.error(this.$t('shop.chooseTips'))
-				return false
-			}
-			// 弹出购物车
-			this.visibleShoppingCart = true
-			// 展示购物车商品数据
-			this.getShowCart()
-		},
-		// 设置运费
-		setFreight() {
-			// 如果地址为自提,则运费为0
-			this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight);
-		},
-		// 表格合并
-		getSummaries(param) {
-			const {columns, data} = param
-			const sums = []
-			columns.forEach((column, index) => {
-				if (index === 0) {
-					sums[index] = this.$t('shop.total')
-					return
-				}
-				const values = data.map(item => Number(item[column.property]));
-				if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
-					sums[index] = values.reduce((prev, curr) => {
-						const value = Number(curr)
-						if (!isNaN(value)) {
-							return Math.round((prev + curr) * 100) / 100
-						} else {
-							return Math.round(prev * 100) / 100
-						}
-					}, 0);
-					if (index !== 2) {
-						sums[index] = sums[index]
-					}
-				}
-			});
+        this.display = true
+      } else {
+        this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
+        this.display = true
+      }
+    },
+    // 选择商品
+    handleSelectionChange(val) {
+      let idx = -1; let num
+      for (const i in this.tableData) {
+        for (const v in val) {
+          if (val[v].ID === this.tableData[i].ID) {
+            idx = i
+            num = this.storeNums[idx]
+            val[v]['chose_num'] = num
+            break
+          }
+        }
+      }
+      this.multipleSelection[this.listQuery.page] = val
+      // 计算统计
+      this.handleSureChange()
+    },
+    // 结算商品
+    settlement() {
+      if (this.multipleSelection.length <= 0) {
+        this.$message.error(this.$t('shop.chooseTips'))
+        return false
+      }
+      // 弹出购物车
+      this.visibleShoppingCart = true
+      // 展示购物车商品数据
+      this.getShowCart()
+    },
+    // 设置运费
+    setFreight() {
+      // 如果地址为自提,则运费为0
+      this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight)
+    },
+    // 表格合并
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = this.$t('shop.total')
+          return
+        }
+        const values = data.map(item => Number(item[column.property]))
+        if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr)
+            if (!isNaN(value)) {
+              return Math.round((prev + curr) * 100) / 100
+            } else {
+              return Math.round(prev * 100) / 100
+            }
+          }, 0)
+          if (index !== 2) {
+            sums[index] = sums[index]
+          }
+        }
+      })
 
-			return sums
-		},
-		// 支付方式、账户信息、余额
-		getShoppingCart() {
-			fetchShoppingCart({categoryType: this.listQuery.categoryType}).then(response => {
-				// 收货地址
-				this.shippingAddressList = response.data.allAddress
-				this.shippingAddressList.map(item => {
-					if (item.IS_DEFAULT === '1') {
-						this.addressId = item.ID
-					}
-				})
-				// 账户
-				this.userBalance = response.data.userBalance
-				// 支付方式处理
-				this.currency = response.data.payList
-				this.cashCurrency = response.data.payList[this.payType].name
-				// 支付方式
-				for (let item of response.data.sellType) {
-					if (item.id === this.listQuery.categoryType) {
-						this.payList = item.sell_type
-						break
-					}
-				}
-				// 免运费阈值
-				this.freeShipping = response.data.freeShipping
-				// 运费
-				this.freight = response.data.freight
-			})
-		},
-		// 支付
-		orderSubmit() {
-			// 账户余额
-			let amountBalance = this.userBalance[this.payType]
-			// 账户类型提示信息
-			let accountType = this.currency[this.payType].name
-			if (amountBalance < 0 || !accountType) {
-				this.$message({
-					message: this.$t('shop.paymentError'),
-					type: 'error'
-				})
-				return false
-			}
-			// 余额是否充足
-			if ((amountBalance - this.pointsSum) < 0) {
-				this.$message({
-					message: accountType + this.$t('shop.balanceNotAllow'),
-					type: 'error'
-				})
-				this.submitButtonStat = false
-				return false
-			}
+      return sums
+    },
+    // 支付方式、账户信息、余额
+    getShoppingCart() {
+      fetchShoppingCart({ categoryType: this.listQuery.categoryType }).then(response => {
+        // 收货地址
+        this.shippingAddressList = response.data.allAddress
+        this.shippingAddressList.map(item => {
+          if (item.IS_DEFAULT === '1') {
+            this.addressId = item.ID
+          }
+        })
+        // 账户
+        this.userBalance = response.data.userBalance
+        // 支付方式处理
+        this.currency = response.data.payList
+        this.cashCurrency = response.data.payList[this.payType].name
+        // 支付方式
+        for (const item of response.data.sellType) {
+          if (item.id === this.listQuery.categoryType) {
+            this.payList = item.sell_type
+            break
+          }
+        }
+        // 免运费阈值
+        this.freeShipping = response.data.freeShipping
+        // 运费
+        this.freight = response.data.freight
+      })
+    },
+    // 关闭时清空购物车等信息
+    cleanShowCart() {
+      this.visibleShoppingCart = false
+      this.goods = []
+      this.totalAmount = 0.00
+      this.goodsNum = ''
+      this.goodsId = ''
+      this.pointFreight = 0
+      this.pointsSum = 0
+    },
+    // 支付
+    orderSubmit() {
+      // 账户余额
+      const amountBalance = this.userBalance[this.payType]
+      // 账户类型提示信息
+      const accountType = this.currency[this.payType].name
+      if (amountBalance < 0 || !accountType) {
+        this.$message({
+          message: this.$t('shop.paymentError'),
+          type: 'error'
+        })
+        return false
+      }
+      // 余额是否充足
+      if ((amountBalance - this.pointsSum) < 0) {
+        this.$message({
+          message: accountType + this.$t('shop.balanceNotAllow'),
+          type: 'error'
+        })
+        this.submitButtonStat = false
+        return false
+      }
 
-			this.submitButtonStat = true
-			this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
-				confirmButtonText: this.$t('common.confirm'),
-				cancelButtonText: this.$t('common.cancel'),
-				customClass: 'csClass',
-				type: 'info',
-				inputType: 'password',
-				inputPattern: /\S+/,
-				inputErrorMessage: this.$t('shop.inputPasswordTips')
-			}).then(({value}) => {
-				this.payPassword = value
-				let params = {
-					goodsId: this.goodsId,
-					goodsNum: this.goodsNum,
-					payPassword: this.payPassword,
-					email: usersInfo.userEmail(),
-					addressId: this.addressId,
-					address: this.address,
-					payType: this.payType,
-				}
+      this.submitButtonStat = true
+      this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
+        confirmButtonText: this.$t('common.confirm'),
+        cancelButtonText: this.$t('common.cancel'),
+        customClass: 'csClass',
+        type: 'info',
+        inputType: 'password',
+        inputPattern: /\S+/,
+        inputErrorMessage: this.$t('shop.inputPasswordTips')
+      }).then(({ value }) => {
+        this.payPassword = value
+        const params = {
+          goodsId: this.goodsId,
+          goodsNum: this.goodsNum,
+          payPassword: this.payPassword,
+          email: usersInfo.userEmail(),
+          addressId: this.addressId,
+          address: this.address,
+          payType: this.payType
+        }
 
-				createOrder(params).then(() => {
-					this.submitButtonStat = false
-					this.$message({
-						message: this.$t('common.successfully'),
-						type: 'success',
-						duration: 5 * 1000
-					})
-					this.$router.push({path: `/shop/order-list`})
-				}).catch(err => {
-					this.$message({
-						message: err,
-						type: 'error',
-						duration: 5 * 1000
-					})
-					this.submitButtonStat = false
-				})
-			}).catch(err => {
-				this.submitButtonStat = false
-			})
-		},
-		// 计算价格
-		getSumMoney () {
-			let cash_plus_sum = [];
-			let goodsId = [];
-			let goodsNum = [];
-			let choseNum = 0;
-			this.goods.map(item => {
-				choseNum = Number(item.chose_num);
-				if (choseNum > 0) {
-					cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100));
-					goodsId.push(item.ID);
-					goodsNum.push(choseNum);
-				}
-			})
-			this.goodsNum = goodsNum;
-			this.goodsId = goodsId;
-			// 增加运费
-			let payAmount = tool.sum(cash_plus_sum);
-			// 设置运费
-			this.setFreight();
-			// 商品总价大于预定值,免运费
-			this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
-			// 计算总价
-			this.pointsSum = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight) ;
-		},
-		// 展示购物车信息
-		getShowCart () {
-			let orderGoods = this.multipleSelection
-			let cartGoods = []
-			for (let i in orderGoods) {
-				cartGoods = orderGoods[i]
-				if (!cartGoods) continue
+        createOrder(params).then(() => {
+          this.submitButtonStat = false
+          this.$message({
+            message: this.$t('common.successfully'),
+            type: 'success',
+            duration: 5 * 1000
+          })
+          this.$router.push({ path: `/shop/own-order` })
+        }).catch(err => {
+          this.$message({
+            message: err,
+            type: 'error',
+            duration: 5 * 1000
+          })
+          this.submitButtonStat = false
+        })
+      }).catch(err => {
+        this.submitButtonStat = false
+      })
+    },
+    // 计算价格
+    getSumMoney() {
+      const cash_plus_sum = []
+      const goodsId = []
+      const goodsNum = []
+      let choseNum = 0
+      this.goods.map(item => {
+        choseNum = Number(item.chose_num)
+        if (choseNum > 0) {
+          cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100))
+          goodsId.push(item.ID)
+          goodsNum.push(choseNum)
+        }
+      })
+      this.goodsNum = goodsNum
+      this.goodsId = goodsId
+      // 增加运费
+      const payAmount = tool.sum(cash_plus_sum)
+      // 设置运费
+      this.setFreight()
+      // 商品总价大于预定值,免运费
+      this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
+      // 计算总价
+      this.pointsSum = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight)
+    },
+    // 展示购物车信息
+    getShowCart() {
+      const orderGoods = this.multipleSelection
+      let cartGoods = []
+      for (const i in orderGoods) {
+        cartGoods = orderGoods[i]
+        if (!cartGoods) continue
 
-				cartGoods.map(item => {
-					if (Number(item.chose_num) > 0) {
-						let discount = item.DISCOUNT / 100
-						item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100;
-						item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100;
-						item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100;
-						this.goods.push(item)
-						this.totalAmount += item.member_price_plus
-					}
-				})
-			}
+        cartGoods.map(item => {
+          if (Number(item.chose_num) > 0) {
+            const discount = item.DISCOUNT / 100
+            item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100
+            item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100
+            item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100
+            this.goods.push(item)
+            this.totalAmount += item.member_price_plus
+          }
+        })
+      }
 
-			this.goods = cartGoods
+      this.goods = cartGoods
 
-			// 计算价格
-			this.getSumMoney();
-		},
-		// 选择收货地址
-		choseAddress (addressId) {
-			this.addressId = addressId
-			// 设置运费
-			this.setFreight()
-			// 计算价格
-			this.getSumMoney()
-		},
-		// 切换支付方式
-		chosePayType(type) {
-			this.payType = type
-		},
-		// 商品详情
-		handleProduct(row) {
-			this.product = row
-			this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-			this.visibleProduct = true
-		},
-	},
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 选择收货地址
+    choseAddress(addressId) {
+      this.addressId = addressId
+      // 设置运费
+      this.setFreight()
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 切换支付方式
+    chosePayType(type) {
+      this.payType = type
+    },
+    // 商品详情
+    handleProduct(row) {
+      this.product = row
+      this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+      this.visibleProduct = true
+    }
+  }
 }
 </script>
 

+ 4 - 4
src/views/shop/dec-order-list.vue

@@ -29,12 +29,12 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.productPrice')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row.REAL_PRICE | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row.REAL_PRICE | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalPrice')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | priceAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | priceAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalBV')">
@@ -49,7 +49,7 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalTaxAmount')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | taxAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | taxAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 							</el-table>
@@ -180,7 +180,7 @@ export default {
 				const { fileUrl, targetName } = response.data
 				const downloadElement = document.createElement('a')
 				downloadElement.target = '_blank'
-				downloadElement.href = process.env.VUE_APP_BASE_API + '/' + fileUrl
+				downloadElement.href = process.env.VUE_APP_BASE_DO_API + '/' + fileUrl
 				downloadElement.download = targetName
 				downloadElement.click()
 			})

+ 24 - 10
src/views/shop/order-list.vue

@@ -29,12 +29,12 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.productPrice')" min-width="150px">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row.REAL_PRICE | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row.REAL_PRICE | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalPrice')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | priceAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | priceAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalBV')">
@@ -49,7 +49,7 @@
 								</el-table-column>
 								<el-table-column align="center" :label="$t('shop.totalTaxAmount')">
 									<template slot-scope="{row}">
-										<span style="white-space: nowrap;">{{ $t('currency.sign') }} {{ row | taxAmountFilter | toThousandFilter }}</span>
+										<span style="white-space: nowrap;"> {{ row | taxAmountFilter | toThousandFilter }}</span>
 									</template>
 								</el-table-column>
 							</el-table>
@@ -79,15 +79,25 @@
 					<span>{{ row.FULL_ADDRESS }}</span>
 				</template>
 			</el-table-column>
+      <el-table-column align="center" :label="$t('shop.country')" prop="COUNTRY" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ row.COUNTRY }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.paymentCurrency')" prop="COUNTRY" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ row.CURRENCY }}</span>
+        </template>
+      </el-table-column>
       <el-table-column align="center" :label="$t('shop.payment')" prop="PAY_TYPE" min-width="100px"></el-table-column>
       <el-table-column align="center" :label="$t('shop.createdTime')" prop="CREATED_AT" min-width="110px">
         <template slot-scope="{row}">
-          <span>{{ row.CREATED_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+          <span>{{ tool.convertToNigeriaTime(row.CREATED_AT) }}</span>
         </template>
       </el-table-column>
       <el-table-column align="center" :label="$t('shop.payTime')" prop="PAY_AT" min-width="110px">
         <template slot-scope="{row}">
-          <span>{{ row.PAY_AT | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+          <span>{{ tool.convertToNigeriaTime(row.PAY_AT) }}</span>
         </template>
       </el-table-column>
       <el-table-column align="center" :label="$t('shop.payStatus')" prop="STATUS" min-width="110px">
@@ -110,14 +120,19 @@
 </template>
 
 <script>
-import {downloadOrder, fetchOrderList} from '@/api/shop'
+import { downloadOrder, fetchOrderList } from '@/api/shop'
+import Pagination from '@/components/Pagination'
 import waves from '@/directive/waves'
+import { getScreenWidth } from "@/utils"
 import tool from '@/utils/tool'
-import Pagination from '@/components/Pagination'
-import {formatAmount, getScreenWidth} from "@/utils"
 
 export default {
   name: 'OrderList',
+  computed: {
+    tool() {
+      return tool
+    }
+  },
   components: { Pagination },
   directives: { waves },
   filters: {
@@ -164,7 +179,6 @@ export default {
       fetchOrderList(this.listQuery).then(response => {
         this.tableData = response.data.list
         this.total = +response.data.totalCount
-
         setTimeout(() => {
           this.listLoading = false
         }, 0.5 * 1000)
@@ -176,7 +190,7 @@ export default {
         const { fileUrl, targetName } = response.data
         const downloadElement = document.createElement('a')
         downloadElement.target = '_blank'
-        downloadElement.href = process.env.VUE_APP_BASE_API + '/' + fileUrl
+        downloadElement.href = process.env.VUE_APP_BASE_DO_API + '/' + fileUrl
         downloadElement.download = targetName
         downloadElement.click()
       })

+ 921 - 0
src/views/shop/reconsume.vue

@@ -0,0 +1,921 @@
+<template>
+  <div class="app-container">
+    <div class="noList">
+      <el-input
+          v-model.trim="memberDetails.number"
+          :placeholder="$t('user.enterMemberCode')"
+          clearable
+          @change="memberRemoteMethod"
+          style="max-width: 50%"
+      ></el-input>
+    </div>
+    <el-table :key="tableKey" ref="multipleTable" v-loading="listLoading" :data="tableData" :show-header="false" fit @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="30" align="center" />
+      <!--		<el-table-column align="center" type="index" width="50"></el-table-column>-->
+      <el-table-column align="center">
+        <template slot-scope="{row, $index}">
+          <el-container>
+            <el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+              <el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+            </el-aside>
+            <el-main style="padding: 5px 5px; text-align: left;">
+              <el-row :gutter="10">
+                <el-col :xs="24" :sm="24" :lg="6">
+                  <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="font-size: 13px;">
+                    <span style="font-weight: bold; color: tomato;">
+                       DP:{{row.COIN}} {{ row.SELL_PRICE | toThousandFilter }}
+                      <span style="font-weight:normal; color: #606266;">({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span>
+                    </span>
+                  </span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-size: 13px;">RP:{{row.COIN}} {{ row.MARKET_PRICE }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <el-input-number v-model="storeNums[$index]" size="mini" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)" />
+                </el-col>
+              </el-row>
+            </el-main>
+          </el-container>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+
+    <div v-show="total>0" class="white-box-footer" style="margin-top: 15px;">
+      <div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
+        <el-button type="primary" size="small" style="float: left;" @click="settlement()">{{ $t('shop.checkOut') }}</el-button>
+      </div>
+      <div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{currencyUnitCode}} {{ sellPriceSum | toThousandFilter }}</div>
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
+        <div style="display: inline-block;">{{ $t('shop.taxAmount') }}: {{currencyUnitCode}} {{ taxSum | toThousandFilter }}</div>
+      </div>
+    </div>
+
+    <!-- 购物车	-->
+    <el-dialog v-loading="shoppingCartLoading" :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;" :close="cleanShowCart" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false">
+      <div v-loading="loading">
+        <div class="white-box">
+          <el-table :data="goods" :show-header="false">
+            <el-table-column align="center">
+              <template slot-scope="{row}">
+                <el-container>
+                  <el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+                    <el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+                  </el-aside>
+                  <el-main style="padding: 10px 5px; text-align: left;">
+                    <el-row :gutter="10">
+                      <el-col :xs="24" :sm="8" :lg="7">
+                        <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="4" :lg="3">
+                        <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                      </el-col>
+                      <el-col :xs="20" :sm="8" :lg="6">
+                        <span style="font-weight: bold;"> {{currencyUnitCode}} {{ row.member_price | toThousandFilter }}</span>
+                        <!-- <span style="font-weight:normal; color: #606266;">({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span> -->
+                        <span>({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                      </el-col>
+                      <el-col :xs="8" :sm="3" :lg="2">
+                        <span style="">x {{ row.chose_num }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="5" :lg="4">
+                        <span style="color: tomato; font-weight: bold;"> {{currencyUnitCode}} {{ row.member_price_plus | toThousandFilter }}</span>
+                        <span>({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                      </el-col>
+                    </el-row>
+                  </el-main>
+                </el-container>
+              </template>
+            </el-table-column>
+          </el-table>
+
+          <div class="white-box-footer">
+            <!-- 订单合计 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
+                  <span>{{ $t('shop.total') }}: {{currencyUnitCode}} {{ parseFloat(cashSum) | toThousandFilter }}({{ pricePvSum | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                  <span>{{ $t('shop.freight') }}: {{currencyUnitCode}} {{ pointFreight }}</span>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <div class="" style="margin: 15px 0;">
+
+              <el-form ref="newOrder" :model="newOrder" label-position="top">
+                <el-col :xs="24" :sm="24" :lg="24">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.customerInfo') }}:</span>
+                </el-col>
+                <el-form-item :label="$t('shop.reconsumeUserCode')">
+                  <el-input v-model.trim="newOrder.userName" disabled @change="handleChkRecUser" />
+                  <span style="margin-left: 10px">【{{ newOrder.recRealName }}】</span>
+                </el-form-item>
+                <el-form-item :label="$t('user.stockistCode')" :required="Number(isDec) === 0" >
+                  <el-input v-model="newOrder.decUserName" :disabled="Number(isDec) === 1" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.recipientName')">
+                  <el-input v-model="newOrder.consignee" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.mobile')">
+                  <el-input v-model.trim="newOrder.mobile" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.province')">
+                  <el-cascader v-model="newOrder.areaSelected" :disabled="areaDisabled" size="large" :placeholder="$t('shop.delivery')" :options="regionData" style="width: 100%;" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.lgaName')">
+                  <el-input v-model="newOrder.lgaName" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.cityName')">
+                  <el-input v-model="newOrder.cityName" />
+                </el-form-item>
+                <el-form-item :label="$t('shop.address')">
+                  <el-input v-model="newOrder.address" />
+                </el-form-item>
+
+              </el-form>
+
+            </div>
+            <el-divider />
+            <!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="payType" @change="chosePayType">
+                    <div v-for="(item, index) in payList" :key="index" class="address">
+                      <el-radio :label="item.label" border>
+                        {{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">( {{currencyUnitCode}} {{ userBalance.cash | toThousandFilter }})</span>
+                          <span v-if="item.label === 'prp'" style="color: tomato;">( {{currencyUnitCode}} {{ userBalance.prp | toThousandFilter }})</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+          </div>
+
+          <div class="white-box-footer">
+            <el-row :gutter="40">
+              <el-col :xs="24" :sm="24" :lg="24" align="left">
+                <el-button type="warning" size="small" @click="cleanShowCart">{{ $t('shop.goBack') }}</el-button>
+                <el-button type="primary" size="small" :loading="submitButtonStat" @click="orderSubmit">{{ $t('shop.goPay') }}</el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- payStack模态框 -->
+    <el-dialog v-loading="payStackLoading" :title="$t('shop.goPay')" :visible.sync="visible" :width="payStackScreenWidth" :before-close="handleClose">
+      <section>
+        <el-form :model="form">
+          <el-form-item :label="$t('user.email')" label-width="100px" required>
+            <el-input v-model="form.email" autocomplete="off" />
+          </el-form-item>
+          <el-form-item :label="$t('shop.amount')" label-width="100px" required>
+            <el-input v-model="form.amount" autocomplete="off" readonly />
+          </el-form-item>
+        </el-form>
+      </section>
+      <paystack
+        :firstname="form.firstname"
+        :lastname="form.lastname"
+        :amount="form.amount * 100"
+        :email="form.email"
+        :metadata="form.metadata"
+        :currency="form.currency"
+        :paystackkey="form.publicKey"
+        :reference="reference"
+        :channels="channels"
+        :callback="processPayment"
+        :close="handleClose"
+      >
+        <el-button type="primary" size="small">{{ $t('shop.goPay') }}</el-button>
+      </paystack>
+      <el-button type="danger" size="small" class="cancelButton" style="margin-left: 10px;" @click="handleClose">{{ $t('common.cancel') }}</el-button>
+    </el-dialog>
+
+    <!-- 倒计时页面 -->
+    <el-dialog :title="$t('common.hint')" :visible.sync="payDialog" :width="payStackScreenWidth" :show-close="false" :close="handleOrderList">
+      <el-card shadow="always">
+        <el-result icon="success" :title="$t('common.successfully')" :sub-title="$t('shop.successOrderTips')">
+          <template slot="extra">
+            <el-button type="primary" size="medium" @click="handleOrderList">{{ $t('shop.goBack') }}({{ countdown }})</el-button>
+          </template>
+        </el-result>
+      </el-card>
+    </el-dialog>
+
+    <!-- 商品详情 -->
+    <el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="12" :lg="12">
+          <el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')" />
+        </el-col>
+        <el-col :xs="24" :sm="12" :lg="12">
+          <div style="text-align: left; line-height: 50px; font-size: 16px;">
+            <span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br>
+            <span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br>
+            <span style="color: tomato;">{{ $t('shop.salesPrice') }}:{{currencyUnitCode}} {{ product.SELL_PRICE }}</span><br>
+            <span>{{ $t('shop.marketPrice') }}:{{currencyUnitCode}} {{ product.MARKET_PRICE }}</span><br>
+            <span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br>
+            <span>{{ $t('shop.taxAmount') }}: {{ product.taxAmount | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  createApproachReconsumeOrder,
+  createReconsumeOrder,
+  deleteApproachOrder,
+  fetchReconsumeProductList,
+  fetchShoppingCart
+} from '@/api/shop'
+import {getRegionList} from '@/api/config'
+
+import { fetchFullInfo } from '@/api/user'
+import Pagination from '@/components/Pagination'
+import waves from '@/directive/waves'
+import region from '@/store/modules/region'
+import { getScreenWidth } from '@/utils'
+import tool from '@/utils/tool'
+import usersInfo from '@/utils/usersInfo'
+import paystack from 'vue-paystack'
+
+export default {
+  name: 'StandardProducts',
+  components: { Pagination, paystack },
+  directives: { waves },
+  filters: {
+    priceFilter(price) {
+      return tool.formatPrice(price)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: [],
+      total: 0,
+      tableData: [],
+      listLoading: false,
+      listQuery: {
+        categoryType: 1,
+        page: 1,
+        limit: 50,
+      },
+      tool: tool,
+      multipleSelection: [],
+      sellPriceSum: 0.00,
+      pricePvSum: 0.00,
+      taxSum: 0.00,
+      storeNums: [],
+      display: false,
+      currentPage: 1,
+      shoppingCartGoods: [],
+
+      shoppingCartLoading: false,
+      visibleShoppingCart: false,
+      loading: false,
+
+      goods: [],
+      payList: [],
+      cashCurrency: '',
+      currency: {},
+      pointsSum: 0,
+      cashSum: 0,
+      pointFreight: 0,
+      freeShipping: '',
+      goodsId: '',
+      goodsNum: '',
+      payPassword: '',
+      submitButtonStat: false,
+      sn: '',
+      orderType: '',
+      payDialog: false,
+      countdown: 5,
+      visible: false,
+      totalAmount: 0.00,
+      freight: 0.00,
+      userBalance: {},
+
+      payType: 'cash',
+      payStackLoading: false,
+      channels: ['card', 'bank', 'ussd', 'qr'],
+      regionData: [],
+      areaDisabled: false,
+      form: {
+        publicKey: process.env.VUE_APP_BASE_PAY_STACK_PUBLIC_KEY,
+        currency: 'NGN',
+        firstname: usersInfo.userName(),
+        lastname: '',
+        email: usersInfo.userEmail(),
+        amount: 0,
+        orderSn: '',
+        metadata: {
+          cart_id: '',
+          custom_fields: [
+            {
+              display_name: 'orderSn',
+              variable_name: 'orderSn',
+              value: this.sn
+            },
+            {
+              display_name: 'orderType',
+              variable_name: 'orderType',
+              value: 'userOrder'
+            }
+          ]
+        }
+      },
+      newOrder: {
+        userName: '',
+        recRealName: '-',
+        consignee: '',
+        mobile: '',
+        areaSelected: [],
+        lgaName: '',
+        cityName: '',
+        address: '',
+        decUserName: ''
+      },
+      payStackScreenWidth: getScreenWidth() > 500 ? '450px' : getScreenWidth() + 'px',
+
+      addressId: '',
+      selfPickUpAddressId: '100000000000000000',
+      shippingAddressList: [],
+
+      screenWidth: getScreenWidth() > 600 ? '50%' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      dialog: false,
+      dialogLoading: false,
+
+      visibleProduct: false,
+      product: {
+        GOODS_NAME: '',
+        GOODS_NO: '',
+        COVER: '',
+        SELL_PRICE: 0,
+        PRICE_PV: 0,
+        TAX_RATE: 0,
+        taxAmount: 0
+      },
+      imageStyle: 'margin-top: 0px;',
+      countries: null,
+      memberLoading: false,
+      memberList: [],
+      memberDetails: {
+        number: '',
+      },
+      currencyUnitCode: "",
+      isDec: ""
+    }
+  },
+  computed: {
+    // PayStack混淆串
+    reference() {
+      let text = ''
+      const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+      for (let i = 0; i < 10; i++) {
+        text += possible.charAt(Math.floor(Math.random() * possible.length))
+      }
+      return text
+    },
+  },
+  watch: {
+    isDec: {
+      handler(newValue, old) {
+        if (newValue == '1') {
+          this.newOrder.decUserName = usersInfo.userName();
+        }
+      },
+    }
+  },
+  created() {
+    // this.getList()
+  },
+  mounted() {
+    // 支付方式、账户信息、余额
+  },
+  methods: {
+    getRegion(){
+      getRegionList({countryId: this.memberDetails.countryId}).then(response => {
+        this.regionData = response.data
+      })
+    },
+    memberRemoteMethod(e){
+      console.log(e)
+      if (e) {
+        this.memberLoading = true
+        fetchFullInfo({ userName: e }).then(response => {
+          let memberDetails = {...response.data}
+          // countryId
+          this.memberDetails = {...this.memberDetails, ...response.data}
+          this.newOrder.recRealName = response.data.REAL_NAME
+          this.newOrder.userName = this.memberDetails.number
+          this.listQuery.userId = memberDetails.userId
+          this.memberLoading = false
+          this.getList()
+          this.getShoppingCart()
+        }).catch(() => {
+          this.memberLoading = false
+        })
+      } else {
+        this.newOrder.recRealName = null
+        this.newOrder.userName = null
+        this.listQuery.userId = null
+        this.tableData = []
+        this.total = 0
+      }
+    },
+    // 商品列表
+    getList() {
+      this.listLoading = true
+      fetchReconsumeProductList(this.listQuery).then(response => {
+        this.list = response.data.list
+        this.total = response.data.totalCount
+
+        setTimeout(() => {
+          this.listLoading = false
+        }, 1.5 * 1000)
+
+        const settingObj = this.list
+        for (const i in this.list) {
+          this.storeNums[i] = 1
+          settingObj[i].chose_num = 0
+        }
+        if(this.list && this.list.length > 0){
+          this.currencyUnitCode = this.list[0].COIN
+        }
+        this.tableData = Object.values(settingObj)
+        const pageList = this.multipleSelection[this.currentPage]
+        this.$nextTick(function() {
+          for (const i in this.tableData) {
+            for (const j in pageList) {
+              if (pageList[j].ID === this.tableData[i].ID) {
+                this.$data.storeNums[i] = pageList[j].chose_num
+                this.tableData[i].chose_num = pageList[j].chose_num
+                break
+              }
+            }
+          }
+        })
+      })
+    },
+    // 会员查询
+    handleChkRecUser() {
+      if (this.newOrder.userName) {
+        this.loading = true
+        fetchFullInfo({ userName: this.newOrder.userName }).then(response => {
+          this.newOrder.recRealName = response.data.REAL_NAME
+          this.loading = false
+        }).catch(() => {
+          this.recRealName = '-'
+          this.loading = false
+        })
+      }
+    },
+    // 选择商品计数
+    handleInputNumber(current, row) {
+      const pageList = this.multipleSelection[this.listQuery.page]
+      let selectStatus = false
+      for (const i in pageList) {
+        if (pageList[i].ID === row.ID) {
+          pageList[i].chose_num = current
+          selectStatus = true
+          break
+        }
+      }
+      if (selectStatus) {
+        this.multipleSelection[this.listQuery.page] = pageList
+        this.handleSureChange()
+      }
+    },
+    // 统计商品
+    handleSureChange() {
+      if (this.multipleSelection.length > 0) {
+        let accumulatorSellPrice = 0; let accumulatorPricePv = 0; let accumulatorTax = 0
+        this.multipleSelection.forEach(item => {
+          item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100 })
+          item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100) })
+          item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)) })
+        })
+
+        this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
+        this.pricePvSum = tool.formatPrice(accumulatorPricePv)
+        this.taxSum = tool.formatPrice(accumulatorTax)
+
+        this.display = true
+      } else {
+        this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
+        this.display = true
+      }
+    },
+    // 选择商品
+    handleSelectionChange(val) {
+      let idx = -1; let num
+      for (const i in this.tableData) {
+        for (const v in val) {
+          if (val[v].ID === this.tableData[i].ID) {
+            idx = i
+            num = this.storeNums[idx]
+            val[v]['chose_num'] = num
+            break
+          }
+        }
+      }
+      this.multipleSelection[this.listQuery.page] = val
+      // 计算统计
+      this.handleSureChange()
+    },
+    // 结算商品
+    settlement() {
+      if (this.multipleSelection.length <= 0) {
+        this.$message.error(this.$t('shop.chooseTips'))
+        return false
+      }
+      // 弹出购物车
+      this.visibleShoppingCart = true
+      // 展示购物车商品数据
+      this.getShowCart()
+      this.getRegion()
+    },
+    // 设置运费
+    setFreight() {
+      // 如果地址为自提,则运费为0
+      this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight)
+    },
+    // 表格合并
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = this.$t('shop.total')
+          return
+        }
+        const values = data.map(item => Number(item[column.property]))
+        if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr)
+            if (!isNaN(value)) {
+              return Math.round((prev + curr) * 100) / 100
+            } else {
+              return Math.round(prev * 100) / 100
+            }
+          }, 0)
+          if (index !== 2) {
+            sums[index] = sums[index]
+          }
+        }
+      })
+
+      return sums
+    },
+    // 支付方式、账户信息、余额
+    getShoppingCart() {
+      fetchShoppingCart({ categoryType: this.listQuery.categoryType, userId: this.listQuery.userId }).then(response => {
+        // 收货地址
+        this.shippingAddressList = response.data.allAddress
+        this.shippingAddressList.map(item => {
+          if (item.IS_DEFAULT === '1') {
+            this.addressId = item.ID
+          }
+        })
+        // 账户
+        this.userBalance = response.data.userBalance
+        // 支付方式处理
+        this.currency = response.data.payList
+        this.cashCurrency = response.data.payList[this.payType].name
+        // 支付方式
+        for (const item of response.data.sellType) {
+          if (item.id === this.listQuery.categoryType) {
+            this.payList = item.sell_type
+            break
+          }
+        }
+        // 支付方式的第一项默认选中
+        this.payType = Object.values(this.payList)[0]['label']
+        // 免运费阈值
+        this.freeShipping = response.data.freeShipping
+        // 运费
+        this.freight = response.data.freight
+        //
+        console.log(response.data.isDec)
+        this.isDec = response.data.isDec
+
+      })
+    },
+    // 支付
+    orderSubmit() {
+      // 账户余额
+      const amountBalance = this.userBalance[this.payType]
+      // 账户类型提示信息
+      let accountType = this.currency[this.payType].name
+      // if (amountBalance < 0 || !accountType) {
+      // 	this.$message({
+      // 		message: this.$t('shop.paymentError'),
+      // 		type: 'error'
+      // 	})
+      // 	return false
+      // }
+      // 支付方式处理
+      if (['cash', 'pay_stack'].includes(this.payType)) {
+        const payObj = this.payList.find((item) => {
+          return item.label === this.payType
+        })
+        accountType = (payObj.length <= 0) ? '' : payObj.name
+      }
+
+      if (!this.newOrder.decUserName) {
+        this.$message({
+          message: this.$t('shop.declarationCenterNumberTips'),
+          type: 'error'
+        })
+        return false
+      }
+
+      if (this.newOrder.recRealName === '-') {
+        this.$message({
+          message: this.$t('shop.memberNotFound'),
+          type: 'error'
+        })
+        return false
+      }
+
+      // 余额是否充足
+      if ((this.payType !== 'pay_stack') && ((amountBalance - this.cashSum) < 0)) {
+        this.$message({
+          message: accountType + this.$t('shop.balanceNotAllow'),
+          type: 'error'
+        })
+        this.submitButtonStat = false
+        return false
+      }
+
+      this.submitButtonStat = true
+      this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
+        confirmButtonText: this.$t('common.confirm'),
+        cancelButtonText: this.$t('common.cancel'),
+        customClass: 'csClass',
+        type: 'info',
+        inputType: 'password',
+        inputPattern: /\S+/,
+        inputErrorMessage: this.$t('shop.inputPasswordTips')
+      }).then(({ value }) => {
+        this.payPassword = value
+        const params = {
+          goodsId: this.goodsId,
+          goodsNum: this.goodsNum,
+          payPassword: this.payPassword,
+          email: this.form.email,
+          addressId: this.addressId,
+          payType: this.payType,
+          userName: this.newOrder.userName,
+          consignee: this.newOrder.consignee,
+          acceptMobile: this.newOrder.mobile,
+          province: this.newOrder.areaSelected,
+          lgaName: this.newOrder.lgaName,
+          cityName: this.newOrder.cityName,
+          detailaddress: this.newOrder.address,
+          decUserName: this.newOrder.decUserName
+        }
+        if (this.payType === 'pay_stack') {
+          // PayStack支付
+          createApproachReconsumeOrder(params).then(response => {
+            this.visibleShoppingCart = false
+            this.submitButtonStat = false
+            this.visible = true
+            this.form.orderSn = response.data.SN
+            this.form.amount = this.cashSum
+            this.form.metadata.cart_id = response.data.SN
+            this.form.metadata.custom_fields[0].value = response.data.SN
+          }).catch(err => {
+            this.$message({
+              message: err,
+              type: 'error',
+              duration: 5 * 1000
+            })
+            this.submitButtonStat = false
+          })
+        } else {
+          console.log(params)
+          // 非PayStack支付
+          createReconsumeOrder(params).then(() => {
+            this.submitButtonStat = false
+            this.$message({
+              message: this.$t('common.successfully'),
+              type: 'success',
+              duration: 5 * 1000
+            })
+            this.$router.push({ path: `/shop/member-order` })
+          }).catch(err => {
+            this.$message({
+              message: err,
+              type: 'warning',
+              duration: 5 * 1000
+            })
+            this.submitButtonStat = false
+          })
+        }
+      }).catch(() => {
+        this.submitButtonStat = false
+      })
+    },
+    // 计算价格
+    getSumMoney() {
+      const cash_plus_sum = []
+      const goodsId = []
+      const goodsNum = []
+      let choseNum = 0
+      this.goods.map(item => {
+        choseNum = Number(item.chose_num)
+        if (choseNum > 0) {
+          cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100))
+          goodsId.push(item.ID)
+          goodsNum.push(choseNum)
+        }
+      })
+      this.goodsNum = goodsNum
+      this.goodsId = goodsId
+      // 增加运费
+      const payAmount = tool.sum(cash_plus_sum)
+      // 设置运费
+      this.setFreight()
+      // 商品总价大于预定值,免运费
+      this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
+      // 计算总价
+      this.pointsSum = this.cashSum = this.form.amount = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight)
+    },
+    // 展示购物车信息
+    getShowCart() {
+      const orderGoods = this.multipleSelection
+      let cartGoods = []
+      for (const i in orderGoods) {
+        cartGoods = orderGoods[i]
+        if (!cartGoods) continue
+
+        cartGoods.map(item => {
+          if (Number(item.chose_num) > 0) {
+            const discount = item.DISCOUNT / 100
+            item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100
+            item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100
+            item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100
+            this.goods.push(item)
+            this.totalAmount += item.member_price_plus
+          }
+        })
+      }
+
+      this.goods = cartGoods
+
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 关闭时清空购物车等信息
+    cleanShowCart() {
+      this.visibleShoppingCart = false
+      this.goods = []
+      this.totalAmount = 0.00
+      this.goodsNum = ''
+      this.goodsId = ''
+      this.pointFreight = 0
+      this.pointsSum = 0
+    },
+    // 选择收货地址
+    choseAddress(addressId) {
+      this.addressId = addressId
+      // 设置运费
+      this.setFreight()
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 切换支付方式
+    chosePayType(type) {
+      this.payType = type
+    },
+    // 关闭支付回调
+    handleClose() {
+      this.$confirm(this.$t('shop.confirmClose')).then(_ => {
+        deleteApproachOrder({ orderSn: this.form.orderSn }).then(() => {
+          // 关闭支付模态框
+          this.visible = false
+          // 关闭购物车
+          this.visibleShoppingCart = false
+          this.submitButtonStat = false
+        })
+      })
+    },
+    // 支付成功回调
+    processPayment() {
+      // 关闭支付页面
+      this.visible = false
+      this.payStackLoading = false
+      // 显示支付成功模态框
+      this.payDialog = true
+      // 启动支付成功倒计时
+      this.handleCountdown()
+    },
+    // 倒计时结束跳转
+    handleOrderList() {
+      this.$router.push({ path: `/shop/member-order` })
+    },
+    // 启动倒计时
+    handleCountdown() {
+      // 创建定时器
+      setInterval(() => {
+        // 每隔1秒把time的值减一,赋值给span标签
+        this.countdown--
+        if (this.countdown === 0) {
+          // 倒计时结束,跳转到订单列表
+          this.$router.push({ path: `/shop/member-order` })
+        }
+      }, 1000)
+    },
+    // 商品详情
+    handleProduct(row) {
+      this.product = row
+      this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+      this.visibleProduct = true
+    }
+  }
+}
+</script>
+
+<style >
+.el-table--medium .el-table__cell {
+  padding: 3px 0;
+}
+
+.csClass{
+  width: 360px;
+}
+
+.address{
+  line-height: 2.5rem;
+}
+.address_box{
+  border-bottom: 1px solid #e3e3e3;
+}
+.sum{
+  display: inline-block;
+}
+.box{
+  margin: 1rem 0;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  padding-bottom: 1rem;
+}
+.sum_box{
+  display: flex;
+  margin-left: 1rem;
+}
+.sum_box > div{
+  line-height: 2rem;
+}
+.sum_box > div:nth-child(1){
+  margin-right: 1rem;
+}
+.payButton {
+  border: none;
+  padding: 0;
+}
+.noList{
+  margin: 10px 0;
+}
+</style>

+ 789 - 730
src/views/shop/standard-products.vue

@@ -1,766 +1,825 @@
 <template>
-<div class="app-container">
-	<el-table :data="tableData" :show-header="false" :key="tableKey" v-loading="listLoading" fit ref="multipleTable" @selection-change="handleSelectionChange">
-		<el-table-column type="selection" width="30" align="center"></el-table-column>
-<!--		<el-table-column align="center" type="index" width="50"></el-table-column>-->
-		<el-table-column align="center">
-			<template slot-scope="{row, $index}">
-				<el-container>
-					<el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-						<el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-					</el-aside>
-					<el-main style="padding: 5px 5px; text-align: left;">
-						<el-row :gutter="10">
-							<el-col :xs="24" :sm="24" :lg="6">
-								<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="4">
-								<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="5">
-								<span style="font-size: 13px;">
-									<span style="font-weight: bold; color: tomato;">
-										{{ $t('currency.sign') }} {{ row.SELL_PRICE | toThousandFilter }}
-										<span style="font-weight:normal; color: #606266;">({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span>
-									</span>
-								</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="4">
-								<span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="5">
-								<el-input-number size="mini" v-model="storeNums[$index]" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)"></el-input-number>
-							</el-col>
-						</el-row>
-					</el-main>
-				</el-container>
-			</template>
-		</el-table-column>
-	</el-table>
-
-	<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
-
-	<div class="white-box-footer" style="margin-top: 15px;" v-show="total>0">
-		<div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
-			<el-button type="primary" size="small" @click="settlement()" style="float: left;">{{ $t('shop.checkOut') }}</el-button>
-		</div>
-		<div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
-			<div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ sellPriceSum | toThousandFilter }}</div>
-			<div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
-			<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ taxSum | toThousandFilter }}</div>
-		</div>
-	</div>
-
-	<!-- 购物车	-->
-	<el-dialog :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" v-loading="shoppingCartLoading" style="margin-top: -95px;">
-		<div v-loading="loading">
-			<div class="white-box">
-				<el-table :data="goods" :show-header="false">
-					<el-table-column align="center">
-						<template slot-scope="{row}">
-							<el-container>
-								<el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-									<el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-								</el-aside>
-								<el-main style="padding: 10px 5px; text-align: left;">
-									<el-row :gutter="10">
-										<el-col :xs="24" :sm="8" :lg="8">
-											<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-										</el-col>
-										<el-col :xs="24" :sm="4" :lg="4">
-											<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-										</el-col>
-										<el-col :xs="16" :sm="4" :lg="4">
-											<span style="font-weight: bold;">{{ $t('currency.sign') }} {{ row.member_price | toThousandFilter }}</span>
-										</el-col>
-										<el-col :xs="8" :sm="3" :lg="3">
-											<span style="">x {{ row.chose_num }}</span>
-										</el-col>
-										<el-col :xs="24" :sm="5" :lg="5">
-											<span style="color: tomato; font-weight: bold;">{{ $t('currency.sign') }} {{ row.member_price_plus | toThousandFilter }}</span>
-										</el-col>
-									</el-row>
-								</el-main>
-							</el-container>
-						</template>
-					</el-table-column>
-				</el-table>
-
-				<div class="white-box-footer">
-					<!-- 订单合计 -->
-					<div class="" style="margin: 15px 0;">
-						<el-row :gutter="20">
-							<el-col :xs="24" :sm="24" :lg="3">
-								<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
-								<span>{{ $t('shop.total') }}:{{ $t('currency.sign') }} {{ parseFloat(cashSum) | toThousandFilter }}</span><br />
-								<span>{{ $t('shop.freight') }}:{{ $t('currency.sign') }} {{ pointFreight }}</span>
-							</el-col>
-						</el-row>
-					</div>
-					<el-divider></el-divider>
-					<!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
-					<div class="" style="margin: 15px 0;">
-						<el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
-							<el-col :xs="24" :sm="24" :lg="3">
-								<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-								<el-radio-group v-model="payType" @change='chosePayType'>
-									<div v-for="(item, index) in payList" :key='index' class="address">
-										<el-radio :label="item.label" border>
-											{{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">({{ $t('currency.sign') }} {{ userBalance.cash | toThousandFilter }})</span>
-										</el-radio>
-									</div>
-								</el-radio-group>
-							</el-col>
-						</el-row>
-					</div>
-					<el-divider></el-divider>
-					<!-- 收货地址 -->
-					<div class="" style="margin: 15px 0;">
-						<el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
-							<el-col :xs="24" :sm="24" :lg="3">
-								<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
-							</el-col>
-							<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-								<el-radio-group v-model="addressId" @change='choseAddress'>
-									<div class="address">
-										<el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
-									</div>
-									<div v-for="(item, index) in shippingAddressList" :key='index' class="address">
-										<el-radio :label="item.ID"  style="word-break: break-all; white-space: normal;">
-											<span>{{item.ADDRESS}}, {{item.LGA_NAME}}, {{item.PROVINCE_NAME}}</span>
-											<el-divider direction="vertical"></el-divider>
-											<span>{{item.MOBILE}}</span>
-											<el-divider direction="vertical"></el-divider>
-											<span>{{item.CONSIGNEE}}</span>
-										</el-radio>
-									</div>
-								</el-radio-group>
-							</el-col>
-						</el-row>
-					</div>
-				</div>
-
-				<div class="white-box-footer" >
-					<el-row :gutter="40">
-						<el-col :xs="24" :sm="24" :lg="24" align="left">
-							<el-button type="warning"  size="small" @click="visibleShoppingCart = false">{{ $t('shop.goBack') }}</el-button>
-							<el-button type="primary" size="small" @click="orderSubmit" :loading="submitButtonStat">{{ $t('shop.goPay') }}</el-button>
-						</el-col>
-					</el-row>
-				</div>
-			</div>
-		</div>
-	</el-dialog>
-
-	<!-- payStack模态框 -->
-	<el-dialog :title="$t('shop.goPay')" :visible.sync="visible" :width="payStackScreenWidth" v-loading="payStackLoading" :before-close="handleClose">
-		<section>
-			<el-form :model="form">
-				<el-form-item :label="$t('user.email')" label-width="100px" required>
-					<el-input v-model="form.email" autocomplete="off"></el-input>
-				</el-form-item>
-				<el-form-item :label="$t('shop.amount')" label-width="100px" required>
-					<el-input v-model="form.amount" autocomplete="off" readonly></el-input>
-				</el-form-item>
-			</el-form>
-		</section>
-		<paystack
-			:firstname="form.firstname"
-			:lastname="form.lastname"
-			:amount="form.amount * 100"
-			:email="form.email"
-			:metadata="form.metadata"
-			:currency="form.currency"
-			:paystackkey="form.publicKey"
-			:reference="reference"
-			:channels="channels"
-			:callback="processPayment"
-			:close="handleClose"
-		>
-			<el-button type="primary" size="small">{{ $t('shop.goPay') }}</el-button>
-		</paystack>
-		<el-button type="danger" size="small" class="cancelButton" @click="handleClose" style="margin-left: 10px;">{{ $t('common.cancel') }}</el-button>
-	</el-dialog>
-
-	<!-- 倒计时页面 -->
-	<el-dialog :title="$t('common.hint')" :visible.sync="payDialog" :width="payStackScreenWidth" :show-close="false" :close="handleOrderList">
-		<el-card shadow="always">
-			<el-result icon="success" :title="$t('common.successfully')" :subTitle="$t('shop.successOrderTips')">
-				<template slot="extra">
-					<el-button type="primary" size="medium" @click="handleOrderList">{{ $t('shop.goBack') }}({{ countdown }})</el-button>
-				</template>
-			</el-result>
-		</el-card>
-	</el-dialog>
-
-	<!-- 商品详情 -->
-	<el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
-		<el-row :gutter="20">
-			<el-col :xs="24" :sm="12" :lg="12">
-				<el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')"></el-image>
-			</el-col>
-			<el-col :xs="24" :sm="12" :lg="12">
-				<div style="text-align: left; line-height: 50px; font-size: 16px;">
-					<span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br />
-					<span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br />
-					<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ product.SELL_PRICE | toThousandFilter }}</span><br />
-					<span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br />
-					<span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br />
-					<span>{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ product.taxAmount | toThousandFilter }}</span><br />
-					<span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
-				</div>
-			</el-col>
-		</el-row>
-	</el-dialog>
-</div>
+  <div class="app-container">
+    <el-table :key="tableKey" ref="multipleTable" v-loading="listLoading" :data="tableData" :show-header="false" fit @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="30" align="center" />
+      <!--    <el-table-column align="center" type="index" width="50"></el-table-column>-->
+      <el-table-column align="center">
+        <template slot-scope="{row, $index}">
+          <el-container>
+            <el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+              <el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+            </el-aside>
+            <el-main style="padding: 5px 5px; text-align: left;">
+              <el-row :gutter="10">
+                <el-col :xs="24" :sm="24" :lg="6">
+                  <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="font-size: 13px;">
+                    <span style="font-weight: bold; color: tomato;">
+                       DP:{{row.COIN}} {{ row.SELL_PRICE | toThousandFilter }}
+                      <span style="font-weight:normal; color: #606266;">({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span>
+                    </span>
+                  </span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-size: 13px;">RP:{{row.COIN}} {{ row.MARKET_PRICE }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <el-input-number v-model="storeNums[$index]" size="mini" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)" />
+                </el-col>
+              </el-row>
+            </el-main>
+          </el-container>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+
+    <div v-show="total>0" class="white-box-footer" style="margin-top: 15px;">
+      <div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
+        <el-button type="primary" size="small" style="float: left;" @click="settlement()">{{ $t('shop.checkOut') }}</el-button>
+      </div>
+      <div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}: {{currencyUnitCode}} {{ sellPriceSum | toThousandFilter }}</div>
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
+        <div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{currencyUnitCode}}  {{ taxSum | toThousandFilter }}</div>
+      </div>
+    </div>
+
+    <!-- 购物车  -->
+    <el-dialog v-loading="shoppingCartLoading" :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;" :close="cleanShowCart" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false">
+      <div v-loading="loading">
+        <div class="white-box">
+          <el-table :data="goods" :show-header="false">
+            <el-table-column align="center">
+              <template slot-scope="{row}">
+                <el-container>
+                  <el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+                    <el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+                  </el-aside>
+                  <el-main style="padding: 10px 5px; text-align: left;">
+                    <el-row :gutter="10">
+                      <el-col :xs="24" :sm="8" :lg="8">
+                        <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="4" :lg="4">
+                        <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                      </el-col>
+                      <el-col :xs="16" :sm="4" :lg="4">
+                        <span style="font-weight: bold;"> {{currencyUnitCode}} {{ row.member_price | toThousandFilter }}</span>
+                        <span>({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                      </el-col>
+                      <el-col :xs="8" :sm="3" :lg="3">
+                        <span style="">x {{ row.chose_num }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="5" :lg="5">
+                        <span style="color: tomato; font-weight: bold;">{{currencyUnitCode}} {{ row.member_price_plus | toThousandFilter }}</span>
+                        <span style="color: tomato;">({{ row.PRICE_PV | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                      </el-col>
+                    </el-row>
+                  </el-main>
+                </el-container>
+              </template>
+            </el-table-column>
+          </el-table>
+
+          <div class="white-box-footer">
+            <!-- 订单合计 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
+                  <span>{{ $t('shop.total') }}:{{currencyUnitCode}} {{ parseFloat(cashSum) | toThousandFilter }}({{ pricePvSum | toThousandFilter }}{{ $t('shop.productBV') }})</span><br>
+                  <span>{{ $t('shop.freight') }}:{{currencyUnitCode}} {{ pointFreight }}</span>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <el-form :rules="rules" ref="payForm" :model="payForm">
+              <el-form-item :label="$t('shop.declarationCenterNumber')" prop="recUserName">
+                <el-input v-model="payForm.recUserName" :disabled="isDec == '1'" />
+              </el-form-item>
+            </el-form>
+
+            <!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="payType" @change="chosePayType">
+                    <div v-for="(item, index) in payList" :key="index" class="address">
+                      <el-radio :label="item.label" border>
+                        {{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">( {{currencyUnitCode}} {{ userBalance.cash | toThousandFilter }})</span>
+                          <span v-if="item.label === 'prp'" style="color: tomato;">( {{currencyUnitCode}} {{ userBalance.prp | toThousandFilter }})</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <!-- 收货地址 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="addressId" @change="choseAddress">
+                    <div class="address">
+                      <el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
+                    </div>
+                    <div v-for="(item, index) in shippingAddressList" :key="index" class="address">
+                      <el-radio :label="item.ID" style="word-break: break-all; white-space: normal;">
+                        <span>{{ item.ADDRESS }}, {{ item.LGA_NAME }}, {{ item.PROVINCE_NAME }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.MOBILE }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.CONSIGNEE }}</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+
+          <div class="white-box-footer">
+            <el-row :gutter="40">
+              <el-col :xs="24" :sm="24" :lg="24" align="left">
+                <el-button type="warning" size="small" @click="cleanShowCart">{{ $t('shop.goBack') }}</el-button>
+                <el-button type="primary" size="small" :loading="submitButtonStat" @click="orderSubmit">{{ $t('shop.goPay') }}</el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- payStack模态框 -->
+    <el-dialog v-loading="payStackLoading" :title="$t('shop.goPay')" :visible.sync="visible" :width="payStackScreenWidth" :before-close="handleClose">
+      <section>
+        <el-form :model="form">
+          <el-form-item :label="$t('user.email')" label-width="100px" required>
+            <el-input v-model="form.email" autocomplete="off" />
+          </el-form-item>
+          <el-form-item :label="$t('shop.amount')" label-width="100px" required>
+            <el-input v-model="form.amount" autocomplete="off" readonly />
+          </el-form-item>
+        </el-form>
+      </section>
+      <paystack
+        :firstname="form.firstname"
+        :lastname="form.lastname"
+        :amount="form.amount * 100"
+        :email="form.email"
+        :metadata="form.metadata"
+        :currency="form.currency"
+        :paystackkey="form.publicKey"
+        :reference="reference"
+        :channels="channels"
+        :callback="processPayment"
+        :close="handleClose"
+      >
+        <el-button type="primary" size="small">{{ $t('shop.goPay') }}</el-button>
+      </paystack>
+      <el-button type="danger" size="small" class="cancelButton" style="margin-left: 10px;" @click="handleClose">{{ $t('common.cancel') }}</el-button>
+    </el-dialog>
+
+    <!-- 倒计时页面 -->
+    <el-dialog :title="$t('common.hint')" :visible.sync="payDialog" :width="payStackScreenWidth" :show-close="false" :close="handleOrderList">
+      <el-card shadow="always">
+        <el-result icon="success" :title="$t('common.successfully')" :sub-title="$t('shop.successOrderTips')">
+          <template slot="extra">
+            <el-button type="primary" size="medium" @click="handleOrderList">{{ $t('shop.goBack') }}({{ countdown }})</el-button>
+          </template>
+        </el-result>
+      </el-card>
+    </el-dialog>
+
+    <!-- 商品详情 -->
+    <el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="12" :lg="12">
+          <el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')" />
+        </el-col>
+        <el-col :xs="24" :sm="12" :lg="12">
+          <div style="text-align: left; line-height: 50px; font-size: 16px;">
+            <span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br>
+            <span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br>
+            <span style="color: tomato;">{{ $t('shop.salesPrice') }}:{{currencyUnitCode}} {{ product.SELL_PRICE }}</span><br>
+            <span>{{ $t('shop.marketPrice') }}:{{currencyUnitCode}} {{ product.MARKET_PRICE }}</span><br>
+            <span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br>
+            <span>{{ $t('shop.taxAmount') }}:{{ product.taxAmount | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
 </template>
 
-  <script>
-	import {fetchProductList, createApproachOrder, deleteApproachOrder, fetchShoppingCart, createOrder} from '@/api/shop'
-  import waves from '@/directive/waves'
-	import {formatAmount, getMedia, getScreenWidth} from '@/utils'
-	import tool from '@/utils/tool'
-  import Pagination from '@/components/Pagination'
-	import usersInfo from "@/utils/usersInfo"
-	import paystack from 'vue-paystack'
-
-  export default {
-    name: 'StandardProducts',
-    components: { Pagination, paystack },
-    directives: { waves },
-		filters: {
-			priceFilter(price) {
-				return tool.formatPrice(price)
-			},
-			taxAmountFilter(row) {
-				return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-			},
-			statusFilter(status) {
-				const statusMap = {
-					Unpaid: 'info',
-					Paid: 'success',
-				}
-				return statusMap[status]
-			},
-		},
-    data() {
-      return {
-        tableKey: 0,
-        list: [],
-        total: 0,
-				tableData: [],
-        listLoading: true,
-        listQuery: {
-					categoryType: 1,
-          page: 1,
-          limit: 50,
+<script>
+import { createApproachOrder, createOrder, deleteApproachOrder, fetchProductList, fetchShoppingCart } from '@/api/shop'
+import Pagination from '@/components/Pagination'
+import waves from '@/directive/waves'
+import { getScreenWidth } from '@/utils'
+import tool from '@/utils/tool'
+import usersInfo from '@/utils/usersInfo'
+import paystack from 'vue-paystack'
+
+export default {
+  name: 'StandardProducts',
+  components: { Pagination, paystack },
+  directives: { waves },
+  filters: {
+    priceFilter(price) {
+      return tool.formatPrice(price)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: [],
+      total: 0,
+      tableData: [],
+      listLoading: true,
+      listQuery: {
+        categoryType: 1,
+        page: 1,
+        limit: 50
+      },
+      tool: tool,
+      multipleSelection: [],
+      sellPriceSum: 0.00,
+      pricePvSum: 0.00,
+      taxSum: 0.00,
+      storeNums: [],
+      display: false,
+      currentPage: 1,
+      shoppingCartGoods: [],
+
+      shoppingCartLoading: false,
+      visibleShoppingCart: false,
+      loading: false,
+
+      goods: [],
+      payList: [],
+      cashCurrency: '',
+      currency: {},
+      pointsSum: 0,
+      cashSum: 0,
+      pointFreight: 0,
+      freeShipping: '',
+      goodsId: '',
+      goodsNum: '',
+      payPassword: '',
+      submitButtonStat: false,
+      sn: '',
+      orderType: '',
+      payDialog: false,
+      countdown: 5,
+      visible: false,
+      totalAmount: 0.00,
+      freight: 0.00,
+      userBalance: {},
+
+      payType: 'cash',
+      payStackLoading: false,
+      channels: ['card', 'bank', 'ussd', 'qr'],
+      form: {
+        publicKey: process.env.VUE_APP_BASE_PAY_STACK_PUBLIC_KEY,
+        currency: 'NGN',
+        firstname: usersInfo.userName(),
+        lastname: '',
+        email: usersInfo.userEmail(),
+        amount: 0,
+        orderSn: '',
+        metadata: {
+          cart_id: '',
+          custom_fields: [
+            {
+              display_name: 'orderSn',
+              variable_name: 'orderSn',
+              value: this.sn
+            },
+            {
+              display_name: 'orderType',
+              variable_name: 'orderType',
+              value: 'userOrder'
+            }
+          ]
+        },
+
+      },
+      payStackScreenWidth: getScreenWidth() > 500 ? '450px' : getScreenWidth() + 'px',
+
+      addressId: '',
+      selfPickUpAddressId: '100000000000000000',
+      shippingAddressList: [],
+
+      screenWidth: getScreenWidth() > 600 ? '50%' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      dialog: false,
+      dialogLoading: false,
+
+      visibleProduct: false,
+      product: {
+        GOODS_NAME: '',
+        GOODS_NO: '',
+        COVER: '',
+        SELL_PRICE: 0,
+        PRICE_PV: 0,
+        TAX_RATE: 0,
+        taxAmount: 0
+      },
+      imageStyle: 'margin-top: -50px;',
+      recRealName:null,
+      // recUserName:usersInfo.userName(),
+      recUserName:null,
+      isDec:null,
+      currencyUnitCode: "",
+        rules: {
+            recUserName: [
+                {required: true, message: this.$t('shop.declarationCenterNumberTips'), trigger: 'blur'},
+            ],
         },
-				tool: tool,
-				multipleSelection: [],
-				sellPriceSum: 0.00,
-				pricePvSum: 0.00,
-				taxSum: 0.00,
-				storeNums: [],
-				display: false,
-				currentPage: 1,
-				shoppingCartGoods: [],
-
-				shoppingCartLoading: false,
-				visibleShoppingCart: false,
-				loading: false,
-
-				goods: [],
-				payList: [],
-				cashCurrency: '',
-				currency: {},
-				pointsSum: 0,
-				cashSum: 0,
-				pointFreight: 0,
-				freeShipping: '',
-				goodsId: '',
-				goodsNum: '',
-				payPassword: '',
-				submitButtonStat: false,
-				sn: '',
-				orderType: '',
-				payDialog: false,
-				countdown: 5,
-				visible: false,
-				totalAmount: 0.00,
-				freight: 0.00,
-				userBalance: {},
-
-				payType: 'cash',
-				payStackLoading: false,
-				channels: ["card", "bank", "ussd", "qr"],
-				form: {
-					publicKey: process.env.VUE_APP_BASE_PAY_STACK_PUBLIC_KEY,
-					currency: 'NGN',
-					firstname: usersInfo.userName(),
-					lastname: '',
-					email: usersInfo.userEmail(),
-					amount: 0,
-					orderSn: '',
-					metadata: {
-						cart_id: '',
-						custom_fields: [
-							{
-								display_name: 'orderSn',
-								variable_name: 'orderSn',
-								value: this.sn,
-							},
-							{
-								display_name: 'orderType',
-								variable_name: 'orderType',
-								value: 'userOrder'
-							},
-						]
-					},
-				},
-				payStackScreenWidth: getScreenWidth() > 500 ? '450px' : getScreenWidth() + 'px',
-
-				addressId: '',
-				selfPickUpAddressId: '100000000000000000',
-				shippingAddressList: [],
-
-				screenWidth: getScreenWidth() > 600 ? '80%' : getScreenWidth() + 'px',
-				labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
-				dialog: false,
-				dialogLoading: false,
-
-				visibleProduct: false,
-				product: {
-					GOODS_NAME: '',
-					GOODS_NO: '',
-					COVER: '',
-					SELL_PRICE: 0,
-					PRICE_PV: 0,
-					TAX_RATE: 0,
-					taxAmount: 0,
-				},
-				imageStyle: 'margin-top: -50px;',
+        payForm: {
+            recUserName: null
+        }
+    }
+  },
+  computed: {
+    // PayStack混淆串
+    reference() {
+      let text = ''
+      const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+      for (let i = 0; i < 10; i++) {
+        text += possible.charAt(Math.floor(Math.random() * possible.length))
       }
+      return text
+    }
+  },
+     watch: {
+     isDec: {
+       handler(newValue, old) {
+         if (newValue == '1') {
+            this.payForm.recUserName = usersInfo.userName();
+         }
+       },
+     }
+   },
+  created() {
+    this.getList()
+  },
+  mounted() {
+    // 支付方式、账户信息、余额
+    this.getShoppingCart()
+  },
+  methods: {
+    // 商品列表
+    getList() {
+      this.listLoading = true
+      fetchProductList(this.listQuery).then(response => {
+        this.list = response.data.list
+        this.total = response.data.totalCount
+
+        setTimeout(() => {
+          this.listLoading = false
+        }, 1.5 * 1000)
+
+        const settingObj = this.list
+        for (const i in this.list) {
+          this.storeNums[i] = 1
+          settingObj[i].chose_num = 0
+        }
+
+        this.tableData = Object.values(settingObj)
+        const pageList = this.multipleSelection[this.currentPage]
+        this.$nextTick(function() {
+          for (const i in this.tableData) {
+            for (const j in pageList) {
+              if (pageList[j].ID === this.tableData[i].ID) {
+                this.$data.storeNums[i] = pageList[j].chose_num
+                this.tableData[i].chose_num = pageList[j].chose_num
+                break
+              }
+            }
+          }
+        })
+      })
     },
-    created() {
-      this.getList()
+    // 选择商品计数
+    handleInputNumber(current, row) {
+      const pageList = this.multipleSelection[this.listQuery.page]
+      let selectStatus = false
+      for (const i in pageList) {
+        if (pageList[i].ID === row.ID) {
+          pageList[i].chose_num = current
+          selectStatus = true
+          break
+        }
+      }
+      if (selectStatus) {
+        this.multipleSelection[this.listQuery.page] = pageList
+        this.handleSureChange()
+      }
     },
-		mounted() {
-			// 支付方式、账户信息、余额
-			this.getShoppingCart()
-		},
-		computed: {
-			// PayStack混淆串
-			reference() {
-				let text = ''
-				let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-				for (let i = 0; i < 10; i++) {
-					text += possible.charAt(Math.floor(Math.random() * possible.length))
-				}
-				return text
-			}
-		},
-		methods: {
-			// 商品列表
-      getList() {
-        this.listLoading = true
-				fetchProductList(this.listQuery).then(response => {
-          this.list = response.data.list
-          this.total = response.data.totalCount
-
-					setTimeout(() => {
-						this.listLoading = false
-					}, 1.5 * 1000)
-
-					let settingObj = this.list
-					for (let i in this.list) {
-						this.storeNums[i] = 1
-						settingObj[i].chose_num = 0
-					}
-
-					this.tableData = Object.values(settingObj)
-					let pageList = this.multipleSelection[this.currentPage]
-					this.$nextTick(function () {
-						for (let i in this.tableData) {
-							for( let j in  pageList) {
-								if( pageList[j].ID === this.tableData[i].ID ) {
-									this.$data.storeNums[i] = pageList[j].chose_num
-									this.tableData[i].chose_num = pageList[j].chose_num
-									break
-								}
-							}
-						}
-					})
+    // 统计商品
+    handleSureChange() {
+      if (this.multipleSelection.length > 0) {
+        let accumulatorSellPrice = 0; let accumulatorPricePv = 0; let accumulatorTax = 0
+        this.multipleSelection.forEach(item => {
+          item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100 })
+          item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100) })
+          item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)) })
         })
-      },
-			// 选择商品计数
-			handleInputNumber(current, row){
-				let pageList = this.multipleSelection[this.listQuery.page]
-				let selectStatus = false
-				for (let i in pageList) {
-					if (pageList[i].ID === row.ID) {
-						pageList[i].chose_num = current
-						selectStatus = true
-						break
-					}
-				}
-				if (selectStatus) {
-					this.multipleSelection[this.listQuery.page] = pageList
-					this.handleSureChange()
-				}
-			},
-			// 统计商品
-			handleSureChange() {
-				if (this.multipleSelection.length > 0) {
-					let accumulatorSellPrice = 0, accumulatorPricePv = 0, accumulatorTax = 0
-					this.multipleSelection.forEach(item => {
-						item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100; })
-						item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100); })
-						item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)); })
-					})
-
-					this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
-					this.pricePvSum = tool.formatPrice(accumulatorPricePv)
-					this.taxSum = tool.formatPrice(accumulatorTax)
-
-					this.display = true
-				} else {
-					this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
-					this.display = true
-				}
-			},
-			// 选择商品
-			handleSelectionChange(val) {
-				let idx = -1, num
-				for (let i in this.tableData) {
-					for (let v in val){
-						if (val[v].ID === this.tableData[i].ID) {
-							idx = i
-							num = this.storeNums[idx]
-							val[v]['chose_num'] = num
-							break
-						}
-					}
-				}
-				this.multipleSelection[this.listQuery.page] = val
-				// 计算统计
-				this.handleSureChange()
-			},
-			// 结算商品
-			settlement() {
-				if (this.multipleSelection.length <= 0) {
-					this.$message.error(this.$t('shop.chooseTips'))
-					return false
-				}
-				// 弹出购物车
-				this.visibleShoppingCart = true
-				// 展示购物车商品数据
-				this.getShowCart()
-			},
-			// 设置运费
-			setFreight() {
-				// 如果地址为自提,则运费为0
-				this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight);
-			},
-			// 表格合并
-			getSummaries(param) {
-				const {columns, data} = param
-				const sums = []
-				columns.forEach((column, index) => {
-					if (index === 0) {
-						sums[index] = this.$t('shop.total')
-						return;
-					}
-					const values = data.map(item => Number(item[column.property]));
-					if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
-						sums[index] = values.reduce((prev, curr) => {
-							const value = Number(curr)
-							if (!isNaN(value)) {
-								return Math.round((prev + curr) * 100) / 100
-							} else {
-								return Math.round(prev * 100) / 100
-							}
-						}, 0);
-						if (index !== 2) {
-							sums[index] = this.$t('currency.sign') + ' ' + sums[index]
-						}
-					}
-				});
-
-				return sums
-			},
-			// 支付方式、账户信息、余额
-			getShoppingCart() {
-			 fetchShoppingCart({categoryType: this.listQuery.categoryType}).then(response => {
-					// 收货地址
-					this.shippingAddressList = response.data.allAddress
-					this.shippingAddressList.map(item => {
-						if (item.IS_DEFAULT === '1') {
-							this.addressId = item.ID
-						}
-					})
-					// 账户
-					this.userBalance = response.data.userBalance
-				 	// 支付方式处理
-				  this.currency = response.data.payList
-				  this.cashCurrency = response.data.payList[this.payType].name
-					// 支付方式
-					for (let item of response.data.sellType) {
-						if (item.id === this.listQuery.categoryType) {
-							this.payList = item.sell_type
-							break
-						}
-					}
-					// 支付方式的第一项默认选中
-					this.payType = Object.values(this.payList)[1]['label']
-					// 免运费阈值
-					this.freeShipping = response.data.freeShipping
-					// 运费
-					this.freight = response.data.freight
-					})
-			},
-			// 支付
-			orderSubmit() {
-				// 账户余额
-				let amountBalance = this.userBalance[this.payType]
-				// 账户类型提示信息
-				let accountType = this.currency[this.payType].name
-				// if (amountBalance < 0 || !accountType) {
-				// 	this.$message({
-				// 		message: this.$t('shop.paymentError'),
-				// 		type: 'error'
-				// 	})
-				// 	return false
-				// }
-				// 支付方式处理
-				if (['cash', 'pay_stack'].includes(this.payType)) {
-					let payObj = this.payList.find((item) => {
-						return item.label === this.payType
-					})
-					accountType = (payObj.length <= 0) ? '' : payObj.name
-				}
-
-				// 余额是否充足
-				if ((this.payType !== 'pay_stack') && ((amountBalance - this.cashSum) < 0)) {
-					this.$message({
-						message: accountType + this.$t('shop.balanceNotAllow'),
-						type: 'error'
-					})
-					this.submitButtonStat = false
-					return false
-				}
-
-				this.submitButtonStat = true
-				this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
-					confirmButtonText: this.$t('common.confirm'),
-					cancelButtonText: this.$t('common.cancel'),
-					customClass: 'csClass',
-					type: 'info',
-					inputType: 'password',
-					inputPattern: /\S+/,
-					inputErrorMessage: this.$t('shop.inputPasswordTips')
-				}).then(({value}) => {
-					this.payPassword = value
-					let params = {
-						goodsId: this.goodsId,
-						goodsNum: this.goodsNum,
-						payPassword: this.payPassword,
-						email: this.form.email,
-						addressId: this.addressId,
-						address: this.address,
-						payType: this.payType,
-					}
-					if (this.payType === 'pay_stack') {
-						// PayStack支付
-						createApproachOrder(params).then(response => {
-							this.visibleShoppingCart = false
-							this.submitButtonStat = false
-							this.visible = true
-							this.form.orderSn = response.data.SN
-							this.form.amount = this.cashSum
-							this.form.metadata.cart_id = response.data.SN
-							this.form.metadata.custom_fields[0].value = response.data.SN
-						}).catch(err => {
-							this.$message({
-								message: err,
-								type: 'error',
-								duration: 5 * 1000
-							})
-							this.submitButtonStat = false
-						})
-					} else {
-						// 非PayStack支付
-						createOrder(params).then(() => {
-							this.submitButtonStat = false
-							this.$message({
-								message: this.$t('common.successfully'),
-								type: 'success',
-								duration: 5 * 1000
-							})
-							this.$router.push({path: `/shop/order-list`})
-						}).catch(err => {
-							this.$message({
-								message: err,
-								type: 'error',
-								duration: 5 * 1000
-							})
-							this.submitButtonStat = false
-						})
-					}
-				}).catch(() => {
-					this.submitButtonStat = false
-				})
-			},
-			// 计算价格
-			getSumMoney () {
-				let cash_plus_sum = [];
-				let goodsId = [];
-				let goodsNum = [];
-				let choseNum = 0;
-				this.goods.map(item => {
-					choseNum = Number(item.chose_num);
-					if (choseNum > 0) {
-						cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100));
-						goodsId.push(item.ID);
-						goodsNum.push(choseNum);
-					}
-				})
-				this.goodsNum = goodsNum;
-				this.goodsId = goodsId;
-				// 增加运费
-				let payAmount = tool.sum(cash_plus_sum);
-				// 设置运费
-				this.setFreight();
-				// 商品总价大于预定值,免运费
-				this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
-				// 计算总价
-				this.pointsSum = this.cashSum = this.form.amount = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight) ;
-			},
-			// 展示购物车信息
-			getShowCart () {
-				let orderGoods = this.multipleSelection
-				let cartGoods = []
-				for (let i in orderGoods) {
-					cartGoods = orderGoods[i]
-					if (!cartGoods) continue
-
-					cartGoods.map(item => {
-						if (Number(item.chose_num) > 0) {
-							let discount = item.DISCOUNT / 100
-							item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100;
-							item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100;
-							item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100;
-							this.goods.push(item)
-							this.totalAmount += item.member_price_plus
-						}
-					})
-				}
-
-				this.goods = cartGoods
-
-				// 计算价格
-				this.getSumMoney();
-			},
-			// 选择收货地址
-			choseAddress (addressId) {
-				this.addressId = addressId
-				// 设置运费
-				this.setFreight()
-				// 计算价格
-				this.getSumMoney()
-			},
-			// 切换支付方式
-			chosePayType(type) {
-				this.payType = type
-			},
-			// 关闭支付回调
-			handleClose() {
-				this.$confirm(this.$t('shop.confirmClose')).then(_ => {
-					deleteApproachOrder({ orderSn: this.form.orderSn }).then(() => {
-						// 关闭支付模态框
-						this.visible = false
-						// 关闭购物车
-						this.visibleShoppingCart = false
-						this.submitButtonStat = false
-					})
-				})
-			},
-			// 支付成功回调
-			processPayment() {
-				// 关闭支付页面
-				this.visible = false
-				this.payStackLoading = false
-				// 显示支付成功模态框
-				this.payDialog = true;
-				// 启动支付成功倒计时
-				this.handleCountdown()
-			},
-			// 倒计时结束跳转
-			handleOrderList () {
-				this.$router.push({path: `/shop/order-list`})
-			},
-			// 启动倒计时
-			handleCountdown () {
-				// 创建定时器
-				setInterval(() => {
-					// 每隔1秒把time的值减一,赋值给span标签
-					this.countdown--
-					if (this.countdown === 0) {
-						// 倒计时结束,跳转到订单列表
-						this.$router.push({path: `/shop/order-list`});
-					}
-				}, 1000)
-			},
-			// 商品详情
-			handleProduct(row) {
-				this.product = row
-				this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-				this.visibleProduct = true
-			},
+
+        this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
+        this.pricePvSum = tool.formatPrice(accumulatorPricePv)
+        this.taxSum = tool.formatPrice(accumulatorTax)
+
+        this.display = true
+      } else {
+        this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
+        this.display = true
+      }
+    },
+    // 选择商品
+    handleSelectionChange(val) {
+      let idx = -1; let num
+      for (const i in this.tableData) {
+        for (const v in val) {
+          if (val[v].ID === this.tableData[i].ID) {
+            idx = i
+            num = this.storeNums[idx]
+            val[v]['chose_num'] = num
+            break
+          }
+        }
+      }
+      this.multipleSelection[this.listQuery.page] = val
+      // 计算统计
+      this.handleSureChange()
+    },
+    // 结算商品
+    settlement() {
+      if (this.multipleSelection.length <= 0) {
+        this.$message.error(this.$t('shop.chooseTips'))
+        return false
+      }
+      // 弹出购物车
+      this.visibleShoppingCart = true
+      // 展示购物车商品数据
+      this.getShowCart()
+    },
+    // 设置运费
+    setFreight() {
+      // 如果地址为自提,则运费为0
+      this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight)
+    },
+    // 表格合并
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = this.$t('shop.total')
+          return
+        }
+        const values = data.map(item => Number(item[column.property]))
+        if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr)
+            if (!isNaN(value)) {
+              return Math.round((prev + curr) * 100) / 100
+            } else {
+              return Math.round(prev * 100) / 100
+            }
+          }, 0)
+          if (index !== 2) {
+            sums[index] = sums[index]
+          }
+        }
+      })
+
+      return sums
+    },
+    // 支付方式、账户信息、余额
+    getShoppingCart() {
+      fetchShoppingCart({ categoryType: this.listQuery.categoryType }).then(response => {
+        // 收货地址
+        this.shippingAddressList = response.data.allAddress
+        this.shippingAddressList.map(item => {
+          if (item.IS_DEFAULT === '1') {
+            this.addressId = item.ID
+          }
+        })
+        // 账户
+        this.userBalance = response.data.userBalance
+        // 支付方式处理
+        this.currency = response.data.payList
+        this.cashCurrency = response.data.payList[this.payType].name
+        // 支付方式
+        for (const item of response.data.sellType) {
+          if (item.id === this.listQuery.categoryType) {
+            this.payList = item.sell_type
+            break
+          }
+        }
+        // 支付方式的第一项默认选中
+        this.payType = Object.values(this.payList)[0]['label']
+        // 免运费阈值
+        this.freeShipping = response.data.freeShipping
+        // 运费
+        this.freight = response.data.freight
+        //是否是报单中心
+        this.isDec = response.data.isDec
+        //货币单位
+        this.currencyUnitCode = response.data.coin
+
+      })
+    },
+    // 支付
+    orderSubmit() {
+        this.$refs['payForm'].validate((valid) => {
+            if (valid) {
+                // 账户余额
+                const amountBalance = this.userBalance[this.payType]
+                // 账户类型提示信息
+                let accountType = this.currency[this.payType].name
+                // if (amountBalance < 0 || !accountType) {
+                //   this.$message({
+                //     message: this.$t('shop.paymentError'),
+                //     type: 'error'
+                //   })
+                //   return false
+                // }
+                // 支付方式处理
+                if (['cash', 'pay_stack'].includes(this.payType)) {
+                    const payObj = this.payList.find((item) => {
+                        return item.label === this.payType
+                    })
+                    accountType = (payObj.length <= 0) ? '' : payObj.name
+                }
+
+                // 余额是否充足
+                if ((this.payType !== 'pay_stack') && ((amountBalance - this.cashSum) < 0)) {
+                    this.$message({
+                        message: accountType + this.$t('shop.balanceNotAllow'),
+                        type: 'error'
+                    })
+                    this.submitButtonStat = false
+                    return false
+                }
+
+                this.submitButtonStat = true
+                this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
+                    confirmButtonText: this.$t('common.confirm'),
+                    cancelButtonText: this.$t('common.cancel'),
+                    customClass: 'csClass',
+                    type: 'info',
+                    inputType: 'password',
+                    inputPattern: /\S+/,
+                    inputErrorMessage: this.$t('shop.inputPasswordTips')
+                }).then(({value}) => {
+                    this.payPassword = value
+                    const params = {
+                        goodsId: this.goodsId,
+                        goodsNum: this.goodsNum,
+                        payPassword: this.payPassword,
+                        email: this.form.email,
+                        addressId: this.addressId,
+                        address: this.address,
+                        payType: this.payType,
+                        userName: this.payForm.recUserName
+                    }
+                    if (this.payType === 'pay_stack') {
+                        // PayStack支付
+                        createApproachOrder(params).then(response => {
+                            this.visibleShoppingCart = false
+                            this.submitButtonStat = false
+                            this.visible = true
+                            this.form.orderSn = response.data.SN
+                            this.form.amount = this.cashSum
+                            this.form.metadata.cart_id = response.data.SN
+                            this.form.metadata.custom_fields[0].value = response.data.SN
+                        }).catch(err => {
+                            this.$message({
+                                message: err,
+                                type: 'error',
+                                duration: 5 * 1000
+                            })
+                            this.submitButtonStat = false
+                        })
+                    } else {
+                        // 非PayStack支付
+                        createOrder(params).then(() => {
+                            this.submitButtonStat = false
+                            this.$message({
+                                message: this.$t('common.successfully'),
+                                type: 'success',
+                                duration: 5 * 1000
+                            })
+                            this.$router.push({path: `/shop/own-order`})
+                        }).catch(err => {
+                            this.$message({
+                                message: err,
+                                type: 'warning',
+                                duration: 5 * 1000
+                            })
+                            this.submitButtonStat = false
+                        })
+                    }
+                }).catch(() => {
+                    this.submitButtonStat = false
+                })
+            } else {
+                console.log('error submit!!');
+                return false;
+            }
+        });
+    },
+    // 计算价格
+    getSumMoney() {
+      const cash_plus_sum = []
+      const goodsId = []
+      const goodsNum = []
+      let choseNum = 0
+      this.goods.map(item => {
+        choseNum = Number(item.chose_num)
+        if (choseNum > 0) {
+          cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100))
+          goodsId.push(item.ID)
+          goodsNum.push(choseNum)
+        }
+      })
+      this.goodsNum = goodsNum
+      this.goodsId = goodsId
+      // 增加运费
+      const payAmount = tool.sum(cash_plus_sum)
+      // 设置运费
+      this.setFreight()
+      // 商品总价大于预定值,免运费
+      this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
+      // 计算总价
+      this.pointsSum = this.cashSum = this.form.amount = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight)
     },
+    // 展示购物车信息
+    getShowCart() {
+      const orderGoods = this.multipleSelection
+      let cartGoods = []
+      for (const i in orderGoods) {
+        cartGoods = orderGoods[i]
+        if (!cartGoods) continue
+
+        cartGoods.map(item => {
+          if (Number(item.chose_num) > 0) {
+            const discount = item.DISCOUNT / 100
+            item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100
+            item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100
+            item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100
+            this.goods.push(item)
+            this.totalAmount += item.member_price_plus
+          }
+        })
+      }
+
+      this.goods = cartGoods
+
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 关闭时清空购物车等信息
+    cleanShowCart() {
+      this.visibleShoppingCart = false
+      this.goods = []
+      this.totalAmount = 0.00
+      this.goodsNum = ''
+      this.goodsId = ''
+      this.pointFreight = 0
+      this.pointsSum = 0
+    },
+    // 选择收货地址
+    choseAddress(addressId) {
+      this.addressId = addressId
+      // 设置运费
+      this.setFreight()
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 切换支付方式
+    chosePayType(type) {
+      this.payType = type
+    },
+    // 关闭支付回调
+    handleClose() {
+      this.$confirm(this.$t('shop.confirmClose')).then(_ => {
+        deleteApproachOrder({ orderSn: this.form.orderSn }).then(() => {
+          // 关闭支付模态框
+          this.visible = false
+          // 关闭购物车
+          this.visibleShoppingCart = false
+          this.submitButtonStat = false
+        })
+      })
+    },
+    // 支付成功回调
+    processPayment() {
+      // 关闭支付页面
+      this.visible = false
+      this.payStackLoading = false
+      // 显示支付成功模态框
+      this.payDialog = true
+      // 启动支付成功倒计时
+      this.handleCountdown()
+    },
+    // 倒计时结束跳转
+    handleOrderList() {
+      this.$router.push({ path: `/shop/own-order` })
+    },
+    // 启动倒计时
+    handleCountdown() {
+      // 创建定时器
+      setInterval(() => {
+        // 每隔1秒把time的值减一,赋值给span标签
+        this.countdown--
+        if (this.countdown === 0) {
+          // 倒计时结束,跳转到订单列表
+          this.$router.push({ path: `/shop/own-order` })
+        }
+      }, 1000)
+    },
+    // 商品详情
+    handleProduct(row) {
+      this.product = row
+      this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+      this.visibleProduct = true
+    }
   }
+}
 </script>
 
 <style>
 .el-table--medium .el-table__cell {
-	padding: 3px 0;
+  padding: 3px 0;
 }
 
 .csClass{
-	width: 360px;
+  width: 360px;
 }
 
 .address{
-	line-height: 2.5rem;
+  line-height: 2.5rem;
 }
 .address_box{
-	border-bottom: 1px solid #e3e3e3;
+  border-bottom: 1px solid #e3e3e3;
 }
 .sum{
-	display: inline-block;
+  display: inline-block;
 }
 .box{
-	margin: 1rem 0;
-	display: flex;
-	justify-content: flex-start;
-	align-items: center;
-	padding-bottom: 1rem;
+  margin: 1rem 0;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  padding-bottom: 1rem;
 }
 .sum_box{
-	display: flex;
-	margin-left: 1rem;
+  display: flex;
+  margin-left: 1rem;
 }
 .sum_box > div{
-	line-height: 2rem;
+  line-height: 2rem;
 }
 .sum_box > div:nth-child(1){
-	margin-right: 1rem;
+  margin-right: 1rem;
 }
 .payButton {
-	border: none;
-	padding: 0;
+  border: none;
+  padding: 0;
 }
 </style>

+ 541 - 531
src/views/shop/villa-fund-products.vue

@@ -1,564 +1,574 @@
 <template>
-	<div class="app-container">
-		<el-table :data="tableData" :show-header="false" :key="tableKey" v-loading="listLoading" fit ref="multipleTable" @selection-change="handleSelectionChange">
-			<el-table-column type="selection" width="30" align="center"></el-table-column>
-			<el-table-column align="center">
-				<template slot-scope="{row, $index}">
-					<el-container>
-						<el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-							<el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-						</el-aside>
-						<el-main style="padding: 5px 5px; text-align: left;">
-							<el-row :gutter="10">
-								<el-col :xs="24" :sm="24" :lg="6">
-									<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="4">
-									<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="5">
-								<span style="font-size: 13px;">
-									<span style="font-weight: bold; color: tomato;">{{ $t('shop.productPrice') }}:{{ row.SELL_PRICE | toThousandFilter }}</span>
-								</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="4">
-									<span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="5">
-									<el-input-number size="mini" v-model="storeNums[$index]" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)"></el-input-number>
-								</el-col>
-							</el-row>
-						</el-main>
-					</el-container>
-				</template>
-			</el-table-column>
-		</el-table>
+  <div class="app-container">
+    <el-table :key="tableKey" ref="multipleTable" v-loading="listLoading" :data="tableData" :show-header="false" fit @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="30" align="center" />
+      <el-table-column align="center">
+        <template slot-scope="{row, $index}">
+          <el-container>
+            <el-aside width="80px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+              <el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+            </el-aside>
+            <el-main style="padding: 5px 5px; text-align: left;">
+              <el-row :gutter="10">
+                <el-col :xs="24" :sm="24" :lg="6">
+                  <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <span style="font-size: 13px;">
+                    <span style="font-weight: bold; color: tomato;">{{ $t('shop.productPrice') }}:{{ row.SELL_PRICE | toThousandFilter }}</span>
+                  </span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="4">
+                  <span style="font-size: 13px;">{{ $t('shop.inventory') }}:{{ row.STORE_NUMS }}</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="5">
+                  <el-input-number v-model="storeNums[$index]" size="mini" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)" />
+                </el-col>
+              </el-row>
+            </el-main>
+          </el-container>
+        </template>
+      </el-table-column>
+    </el-table>
 
-		<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
 
-		<div class="white-box-footer" style="margin-top: 15px;" v-show="total>0">
-			<div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
-				<el-button type="primary" size="small" @click="settlement()" style="float: left;">{{ $t('shop.checkOut') }}</el-button>
-			</div>
-			<div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
-				<div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ sellPriceSum | toThousandFilter }}</div>
-				<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ taxSum | toThousandFilter }}</div>
-			</div>
-		</div>
+    <div v-show="total>0" class="white-box-footer" style="margin-top: 15px;">
+      <div class="flex data" style="float: left; display: inline-block; margin-top: 20px;">
+        <el-button type="primary" size="small" style="float: left;" @click="settlement()">{{ $t('shop.checkOut') }}</el-button>
+      </div>
+      <div class="flex data" style="float: right; display: inline-block; line-height: 28px; font-size: 14px; margin-top: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
+        <div style="margin-right: 2rem; display: inline-block;">{{ $t('shop.productPrice') }}: {{ sellPriceSum | toThousandFilter }}</div>
+        <div style="display: inline-block;">{{ $t('shop.taxAmount') }}: {{ taxSum | toThousandFilter }}</div>
+      </div>
+    </div>
 
-		<!-- 购物车	-->
-		<el-dialog :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;">
-			<div v-loading="loading">
-				<div class="white-box">
-					<el-table :data="goods" :show-header="false">
-						<el-table-column align="center">
-							<template slot-scope="{row}">
-								<el-container>
-									<el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
-										<el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)"></el-image>
-									</el-aside>
-									<el-main style="padding: 10px 5px; text-align: left;">
-										<el-row :gutter="10">
-											<el-col :xs="24" :sm="8" :lg="8">
-												<span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
-											</el-col>
-											<el-col :xs="24" :sm="4" :lg="4">
-												<span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
-											</el-col>
-											<el-col :xs="16" :sm="4" :lg="4">
-												<span style="font-weight: bold;">{{ row.member_price | toThousandFilter }}</span>
-											</el-col>
-											<el-col :xs="8" :sm="3" :lg="3">
-												<span style="">x {{ row.chose_num }}</span>
-											</el-col>
-											<el-col :xs="24" :sm="5" :lg="5">
-												<span style="color: tomato; font-weight: bold;">{{ row.member_price_plus | toThousandFilter }}</span>
-											</el-col>
-										</el-row>
-									</el-main>
-								</el-container>
-							</template>
-						</el-table-column>
-					</el-table>
+    <!-- 购物车	-->
+    <el-dialog :title="$t('shop.productsSettlement')" :visible.sync="visibleShoppingCart" :width="screenWidth" style="margin-top: -95px;" :close="cleanShowCart" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false">
+      <div v-loading="loading">
+        <div class="white-box">
+          <el-table :data="goods" :show-header="false">
+            <el-table-column align="center">
+              <template slot-scope="{row}">
+                <el-container>
+                  <el-aside width="100px" style="background-color: #ffffff; padding: 0; margin-bottom: 0;">
+                    <el-image style="width: 100px; height: 100px" :src="tool.getArImage(row.COVER, '/files/')" @click="handleProduct(row)" />
+                  </el-aside>
+                  <el-main style="padding: 10px 5px; text-align: left;">
+                    <el-row :gutter="10">
+                      <el-col :xs="24" :sm="8" :lg="8">
+                        <span style="cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="4" :lg="4">
+                        <span style="color: #9c9c9c; cursor: pointer;">{{ row.GOODS_NO }}</span>
+                      </el-col>
+                      <el-col :xs="16" :sm="4" :lg="4">
+                        <span style="font-weight: bold;">{{ row.member_price | toThousandFilter }}</span>
+                      </el-col>
+                      <el-col :xs="8" :sm="3" :lg="3">
+                        <span style="">x {{ row.chose_num }}</span>
+                      </el-col>
+                      <el-col :xs="24" :sm="5" :lg="5">
+                        <span style="color: tomato; font-weight: bold;">{{ row.member_price_plus | toThousandFilter }}</span>
+                      </el-col>
+                    </el-row>
+                  </el-main>
+                </el-container>
+              </template>
+            </el-table-column>
+          </el-table>
 
-					<div class="white-box-footer">
-						<!-- 订单合计 -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="20">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
-									<span>{{ $t('shop.total') }}:{{ parseFloat(pointsSum) | toThousandFilter }}</span>
-									<span>{{ $t('shop.freight') }}:{{ pointFreight }}</span>
-								</el-col>
-							</el-row>
-						</div>
-						<el-divider></el-divider>
-						<!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-									<el-radio-group v-model="payType" @change='chosePayType'>
-										<div v-for="(item, index) in payList" :key='index' class="address">
-											<el-radio :label="item.label" border>
-												{{ item.name }}<span v-if="item.label === payType" style="color: tomato;">({{ userBalance[payType] | toThousandFilter }})</span>
-											</el-radio>
-										</div>
-									</el-radio-group>
-								</el-col>
-							</el-row>
-						</div>
-						<el-divider></el-divider>
-						<!-- 收货地址 -->
-						<div class="" style="margin: 15px 0;">
-							<el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
-								<el-col :xs="24" :sm="24" :lg="3">
-									<span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
-								</el-col>
-								<el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
-									<el-radio-group v-model="addressId" @change='choseAddress'>
-										<div class="address">
-											<el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
-										</div>
-										<div v-for="(item, index) in shippingAddressList" :key='index' class="address">
-											<el-radio :label="item.ID" style="word-break: break-all; white-space: normal;">
-												<span>{{item.ADDRESS}}, {{item.LGA_NAME}}, {{item.PROVINCE_NAME}}</span>
-												<el-divider direction="vertical"></el-divider>
-												<span>{{item.MOBILE}}</span>
-												<el-divider direction="vertical"></el-divider>
-												<span>{{item.CONSIGNEE}}</span>
-											</el-radio>
-										</div>
-									</el-radio-group>
-								</el-col>
-							</el-row>
-						</div>
-					</div>
+          <div class="white-box-footer">
+            <!-- 订单合计 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.totalOrders') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap; line-height: 28px;">
+                  <span>{{ $t('shop.total') }}:{{ parseFloat(pointsSum) | toThousandFilter }}</span>
+                  <span>{{ $t('shop.freight') }}:{{ pointFreight }}</span>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <!-- 支付方式/账户余额 {{ cashCurrency }}:  -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="20" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectPayment') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="payType" @change="chosePayType">
+                    <div v-for="(item, index) in payList" :key="index" class="address">
+                      <el-radio :label="item.label" border>
+                        {{ item.name }}<span v-if="item.label === payType" style="color: tomato;">({{ userBalance[payType] | toThousandFilter }})</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+            <el-divider />
+            <!-- 收货地址 -->
+            <div class="" style="margin: 15px 0;">
+              <el-row :gutter="10" type="flex" style="flex-wrap: wrap;">
+                <el-col :xs="24" :sm="24" :lg="3">
+                  <span style="font-weight: bold; word-break: normal; white-space: normal; line-height: 28px;">{{ $t('shop.selectAddress') }}:</span>
+                </el-col>
+                <el-col :xs="24" :sm="24" :lg="21" style="word-break: normal; white-space: nowrap;">
+                  <el-radio-group v-model="addressId" @change="choseAddress">
+                    <div class="address">
+                      <el-radio :label="selfPickUpAddressId">{{ $t('shop.selfPickUp') }}</el-radio>
+                    </div>
+                    <div v-for="(item, index) in shippingAddressList" :key="index" class="address">
+                      <el-radio :label="item.ID" style="word-break: break-all; white-space: normal;">
+                        <span>{{ item.ADDRESS }}, {{ item.LGA_NAME }}, {{ item.PROVINCE_NAME }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.MOBILE }}</span>
+                        <el-divider direction="vertical" />
+                        <span>{{ item.CONSIGNEE }}</span>
+                      </el-radio>
+                    </div>
+                  </el-radio-group>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
 
-					<div class="white-box-footer" >
-						<el-row :gutter="40">
-							<el-col :xs="24" :sm="24" :lg="24" align="left">
-								<el-button type="warning"  size="small" @click="visibleShoppingCart = false">{{ $t('shop.goBack') }}</el-button>
-								<el-button type="primary" size="small" @click="orderSubmit" :loading="submitButtonStat">{{ $t('shop.goPay') }}</el-button>
-							</el-col>
-						</el-row>
-					</div>
-				</div>
-			</div>
-		</el-dialog>
+          <div class="white-box-footer">
+            <el-row :gutter="40">
+              <el-col :xs="24" :sm="24" :lg="24" align="left">
+                <el-button type="warning" size="small" @click="cleanShowCart">{{ $t('shop.goBack') }}</el-button>
+                <el-button type="primary" size="small" :loading="submitButtonStat" @click="orderSubmit">{{ $t('shop.goPay') }}</el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
 
-		<!-- 商品详情 -->
-		<el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
-			<el-row :gutter="20">
-				<el-col :xs="24" :sm="12" :lg="12">
-					<el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')"></el-image>
-				</el-col>
-				<el-col :xs="24" :sm="12" :lg="12">
-					<div style="text-align: left; line-height: 50px; font-size: 16px;">
-						<span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br />
-						<span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br />
-						<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ product.SELL_PRICE | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br />
-						<span>{{ $t('shop.taxAmount') }}:{{ product.taxAmount | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
-					</div>
-				</el-col>
-			</el-row>
-		</el-dialog>
-	</div>
+    <!-- 商品详情 -->
+    <el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="12" :lg="12">
+          <el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')" />
+        </el-col>
+        <el-col :xs="24" :sm="12" :lg="12">
+          <div style="text-align: left; line-height: 50px; font-size: 16px;">
+            <span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br>
+            <span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br>
+            <span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ product.SELL_PRICE | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br>
+            <span>{{ $t('shop.taxAmount') }}:{{ product.taxAmount | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchProductList, fetchShoppingCart, createOrder} from '@/api/shop'
+import { createOrder, fetchProductList, fetchShoppingCart } from '@/api/shop'
+import Pagination from '@/components/Pagination'
 import waves from '@/directive/waves'
-import {formatAmount, getMedia, getScreenWidth} from '@/utils'
+import { getScreenWidth } from '@/utils'
 import tool from '@/utils/tool'
-import Pagination from '@/components/Pagination'
-import usersInfo from "@/utils/usersInfo";
+import usersInfo from '@/utils/usersInfo'
 
 export default {
-	name: 'VillaFundProducts',
-	components: { Pagination },
-	directives: { waves },
-	filters: {
-		priceFilter(price) {
-			return tool.formatPrice(price)
-		},
-		taxAmountFilter(row) {
-			return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-		},
-		statusFilter(status) {
-			const statusMap = {
-				Unpaid: 'info',
-				Paid: 'success',
-			}
-			return statusMap[status]
-		},
-	},
-	data() {
-		return {
-			tableKey: 0,
-			list: [],
-			total: 0,
-			tableData: [],
-			listLoading: true,
-			listQuery: {
-				categoryType: 6,
-				page: 1,
-				limit: 50,
-			},
-			tool: tool,
-			multipleSelection: [],
-			sellPriceSum: 0.00,
-			pricePvSum: 0.00,
-			taxSum: 0.00,
-			storeNums: [],
-			display: false,
-			currentPage: 1,
-			shoppingCartGoods: [],
+  name: 'VillaFundProducts',
+  components: { Pagination },
+  directives: { waves },
+  filters: {
+    priceFilter(price) {
+      return tool.formatPrice(price)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      list: [],
+      total: 0,
+      tableData: [],
+      listLoading: true,
+      listQuery: {
+        categoryType: 6,
+        page: 1,
+        limit: 50
+      },
+      tool: tool,
+      multipleSelection: [],
+      sellPriceSum: 0.00,
+      pricePvSum: 0.00,
+      taxSum: 0.00,
+      storeNums: [],
+      display: false,
+      currentPage: 1,
+      shoppingCartGoods: [],
 
-			visibleShoppingCart: false,
-			loading: false,
+      visibleShoppingCart: false,
+      loading: false,
 
-			goods: [],
-			payList: [],
-			cashCurrency: '',
-			currency: {},
-			pointsSum: 0,
-			pointFreight: 0,
-			freeShipping: '',
-			goodsId: '',
-			goodsNum: '',
-			payPassword: '',
-			submitButtonStat: false,
-			sn: '',
-			orderType: '',
-			payDialog: false,
-			totalAmount: 0.00,
-			freight: 0.00,
-			userBalance: {},
+      goods: [],
+      payList: [],
+      cashCurrency: '',
+      currency: {},
+      pointsSum: 0,
+      pointFreight: 0,
+      freeShipping: '',
+      goodsId: '',
+      goodsNum: '',
+      payPassword: '',
+      submitButtonStat: false,
+      sn: '',
+      orderType: '',
+      payDialog: false,
+      totalAmount: 0.00,
+      freight: 0.00,
+      userBalance: {},
 
-			payType: 'villa_points',
-			addressId: '',
-			selfPickUpAddressId: '100000000000000000',
-			shippingAddressList: [],
+      payType: 'villa_points',
+      addressId: '',
+      selfPickUpAddressId: '100000000000000000',
+      shippingAddressList: [],
 
-			screenWidth: getScreenWidth() > 600 ? '80%' : getScreenWidth() + 'px',
-			labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+      screenWidth: getScreenWidth() > 600 ? '80%' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
 
-			visibleProduct: false,
-			product: {
-				GOODS_NAME: '',
-				GOODS_NO: '',
-				COVER: '',
-				SELL_PRICE: 0,
-				PRICE_PV: 0,
-				TAX_RATE: 0,
-				taxAmount: 0,
-			},
-			imageStyle: 'margin-top: -50px;',
-		}
-	},
-	created() {
-		this.getList()
-	},
-	mounted() {
-		// 支付方式、账户信息、余额
-		this.getShoppingCart()
-	},
-	methods: {
-		getList() {
-			this.listLoading = true
-			fetchProductList(this.listQuery).then(response => {
-				this.list = response.data.list
-				this.total = response.data.totalCount
+      visibleProduct: false,
+      product: {
+        GOODS_NAME: '',
+        GOODS_NO: '',
+        COVER: '',
+        SELL_PRICE: 0,
+        PRICE_PV: 0,
+        TAX_RATE: 0,
+        taxAmount: 0
+      },
+      imageStyle: 'margin-top: -50px;'
+    }
+  },
+  created() {
+    this.getList()
+  },
+  mounted() {
+    // 支付方式、账户信息、余额
+    this.getShoppingCart()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      fetchProductList(this.listQuery).then(response => {
+        this.list = response.data.list
+        this.total = response.data.totalCount
 
-				setTimeout(() => {
-					this.listLoading = false
-				}, 1.5 * 1000)
+        setTimeout(() => {
+          this.listLoading = false
+        }, 1.5 * 1000)
 
-				let settingObj = this.list
-				for (let i in this.list) {
-					this.storeNums[i] = 1
-					settingObj[i].chose_num = 0
-				}
+        const settingObj = this.list
+        for (const i in this.list) {
+          this.storeNums[i] = 1
+          settingObj[i].chose_num = 0
+        }
 
-				this.tableData = Object.values(settingObj)
-				let pageList = this.multipleSelection[this.currentPage]
-				this.$nextTick(function () {
-					for (let i in this.tableData) {
-						for( let j in  pageList) {
-							if( pageList[j].ID === this.tableData[i].ID ) {
-								this.$data.storeNums[i] = pageList[j].chose_num
-								this.tableData[i].chose_num = pageList[j].chose_num
-								break
-							}
-						}
-					}
-				})
-			})
-		},
-		// 选择商品计数
-		handleInputNumber(current, row){
-			let pageList = this.multipleSelection[this.listQuery.page]
-			let selectStatus = false
-			for (let i in pageList) {
-				if (pageList[i].ID === row.ID) {
-					pageList[i].chose_num = current
-					selectStatus = true
-					break
-				}
-			}
-			if (selectStatus) {
-				this.multipleSelection[this.listQuery.page] = pageList
-				this.handleSureChange()
-			}
-		},
-		// 统计商品
-		handleSureChange() {
-			if (this.multipleSelection.length > 0) {
-				let accumulatorSellPrice = 0, accumulatorPricePv = 0, accumulatorTax = 0
-				this.multipleSelection.forEach(item => {
-					item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100; })
-					item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100); })
-					item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)); })
-				})
+        this.tableData = Object.values(settingObj)
+        const pageList = this.multipleSelection[this.currentPage]
+        this.$nextTick(function() {
+          for (const i in this.tableData) {
+            for (const j in pageList) {
+              if (pageList[j].ID === this.tableData[i].ID) {
+                this.$data.storeNums[i] = pageList[j].chose_num
+                this.tableData[i].chose_num = pageList[j].chose_num
+                break
+              }
+            }
+          }
+        })
+      })
+    },
+    // 选择商品计数
+    handleInputNumber(current, row) {
+      const pageList = this.multipleSelection[this.listQuery.page]
+      let selectStatus = false
+      for (const i in pageList) {
+        if (pageList[i].ID === row.ID) {
+          pageList[i].chose_num = current
+          selectStatus = true
+          break
+        }
+      }
+      if (selectStatus) {
+        this.multipleSelection[this.listQuery.page] = pageList
+        this.handleSureChange()
+      }
+    },
+    // 统计商品
+    handleSureChange() {
+      if (this.multipleSelection.length > 0) {
+        let accumulatorSellPrice = 0; let accumulatorPricePv = 0; let accumulatorTax = 0
+        this.multipleSelection.forEach(item => {
+          item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100 })
+          item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100) })
+          item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)) })
+        })
 
-				this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
-				this.pricePvSum = tool.formatPrice(accumulatorPricePv)
-				this.taxSum = tool.formatPrice(accumulatorTax)
+        this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
+        this.pricePvSum = tool.formatPrice(accumulatorPricePv)
+        this.taxSum = tool.formatPrice(accumulatorTax)
 
-				this.display = true
-			} else {
-				this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
-				this.display = true
-			}
-		},
-		// 选择商品
-		handleSelectionChange(val) {
-			let idx = -1, num
-			for (let i in this.tableData) {
-				for (let v in val){
-					if (val[v].ID === this.tableData[i].ID) {
-						idx = i
-						num = this.storeNums[idx]
-						val[v]['chose_num'] = num
-						break
-					}
-				}
-			}
-			this.multipleSelection[this.listQuery.page] = val
-			// 计算统计
-			this.handleSureChange()
-		},
-		// 结算商品
-		settlement() {
-			if (this.multipleSelection.length <= 0) {
-				this.$message.error(this.$t('shop.chooseTips'))
-				return false
-			}
-			// 弹出购物车
-			this.visibleShoppingCart = true
-			// 展示购物车商品数据
-			this.getShowCart()
-		},
-		// 设置运费
-		setFreight() {
-			// 如果地址为自提,则运费为0
-			this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight);
-		},
-		// 表格合并
-		getSummaries(param) {
-			const {columns, data} = param
-			const sums = []
-			columns.forEach((column, index) => {
-				if (index === 0) {
-					sums[index] = this.$t('shop.total')
-					return
-				}
-				const values = data.map(item => Number(item[column.property]));
-				if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
-					sums[index] = values.reduce((prev, curr) => {
-						const value = Number(curr)
-						if (!isNaN(value)) {
-							return Math.round((prev + curr) * 100) / 100
-						} else {
-							return Math.round(prev * 100) / 100
-						}
-					}, 0);
-					if (index !== 2) {
-						sums[index] = sums[index]
-					}
-				}
-			});
+        this.display = true
+      } else {
+        this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
+        this.display = true
+      }
+    },
+    // 选择商品
+    handleSelectionChange(val) {
+      let idx = -1; let num
+      for (const i in this.tableData) {
+        for (const v in val) {
+          if (val[v].ID === this.tableData[i].ID) {
+            idx = i
+            num = this.storeNums[idx]
+            val[v]['chose_num'] = num
+            break
+          }
+        }
+      }
+      this.multipleSelection[this.listQuery.page] = val
+      // 计算统计
+      this.handleSureChange()
+    },
+    // 结算商品
+    settlement() {
+      if (this.multipleSelection.length <= 0) {
+        this.$message.error(this.$t('shop.chooseTips'))
+        return false
+      }
+      // 弹出购物车
+      this.visibleShoppingCart = true
+      // 展示购物车商品数据
+      this.getShowCart()
+    },
+    // 设置运费
+    setFreight() {
+      // 如果地址为自提,则运费为0
+      this.pointFreight = (this.addressId === this.selfPickUpAddressId) ? Number(0) : Number(this.freight)
+    },
+    // 表格合并
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = this.$t('shop.total')
+          return
+        }
+        const values = data.map(item => Number(item[column.property]))
+        if ((!values.every(value => isNaN(value))) && [2, 3, 4, 6].includes(index)) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr)
+            if (!isNaN(value)) {
+              return Math.round((prev + curr) * 100) / 100
+            } else {
+              return Math.round(prev * 100) / 100
+            }
+          }, 0)
+          if (index !== 2) {
+            sums[index] = sums[index]
+          }
+        }
+      })
 
-			return sums
-		},
-		// 支付方式、账户信息、余额
-		getShoppingCart() {
-			fetchShoppingCart({categoryType: this.listQuery.categoryType}).then(response => {
-				// 收货地址
-				this.shippingAddressList = response.data.allAddress
-				this.shippingAddressList.map(item => {
-					if (item.IS_DEFAULT === '1') {
-						this.addressId = item.ID
-					}
-				})
-				// 账户
-				this.userBalance = response.data.userBalance
-				// 支付方式处理
-				this.currency = response.data.payList
-				this.cashCurrency = response.data.payList[this.payType].name
-				// 支付方式
-				for (let item of response.data.sellType) {
-					if (item.id === this.listQuery.categoryType) {
-						this.payList = item.sell_type
-						break
-					}
-				}
-				// 免运费阈值
-				this.freeShipping = response.data.freeShipping
-				// 运费
-				this.freight = response.data.freight
-			})
-		},
-		// 支付
-		orderSubmit() {
-			// 账户余额
-			let amountBalance = this.userBalance[this.payType]
-			// 账户类型提示信息
-			let accountType = this.currency[this.payType].name
-			if (amountBalance < 0 || !accountType) {
-				this.$message({
-					message: this.$t('shop.paymentError'),
-					type: 'error'
-				})
-				return false
-			}
-			// 余额是否充足
-			if ((amountBalance - this.pointsSum) < 0) {
-				this.$message({
-					message: accountType + this.$t('shop.balanceNotAllow'),
-					type: 'error'
-				})
-				this.submitButtonStat = false
-				return false
-			}
+      return sums
+    },
+    // 支付方式、账户信息、余额
+    getShoppingCart() {
+      fetchShoppingCart({ categoryType: this.listQuery.categoryType }).then(response => {
+        // 收货地址
+        this.shippingAddressList = response.data.allAddress
+        this.shippingAddressList.map(item => {
+          if (item.IS_DEFAULT === '1') {
+            this.addressId = item.ID
+          }
+        })
+        // 账户
+        this.userBalance = response.data.userBalance
+        // 支付方式处理
+        this.currency = response.data.payList
+        this.cashCurrency = response.data.payList[this.payType].name
+        // 支付方式
+        for (const item of response.data.sellType) {
+          if (item.id === this.listQuery.categoryType) {
+            this.payList = item.sell_type
+            break
+          }
+        }
+        // 免运费阈值
+        this.freeShipping = response.data.freeShipping
+        // 运费
+        this.freight = response.data.freight
+      })
+    },
+    // 关闭时清空购物车等信息
+    cleanShowCart() {
+      this.visibleShoppingCart = false
+      this.goods = []
+      this.totalAmount = 0.00
+      this.goodsNum = ''
+      this.goodsId = ''
+      this.pointFreight = 0
+      this.pointsSum = 0
+    },
+    // 支付
+    orderSubmit() {
+      // 账户余额
+      const amountBalance = this.userBalance[this.payType]
+      // 账户类型提示信息
+      const accountType = this.currency[this.payType].name
+      if (amountBalance < 0 || !accountType) {
+        this.$message({
+          message: this.$t('shop.paymentError'),
+          type: 'error'
+        })
+        return false
+      }
+      // 余额是否充足
+      if ((amountBalance - this.pointsSum) < 0) {
+        this.$message({
+          message: accountType + this.$t('shop.balanceNotAllow'),
+          type: 'error'
+        })
+        this.submitButtonStat = false
+        return false
+      }
 
-			this.submitButtonStat = true
-			this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
-				confirmButtonText: this.$t('common.confirm'),
-				cancelButtonText: this.$t('common.cancel'),
-				customClass: 'csClass',
-				type: 'info',
-				inputType: 'password',
-				inputPattern: /\S+/,
-				inputErrorMessage: this.$t('shop.inputPasswordTips')
-			}).then(({value}) => {
-				this.payPassword = value
-				let params = {
-					goodsId: this.goodsId,
-					goodsNum: this.goodsNum,
-					payPassword: this.payPassword,
-					email: usersInfo.userEmail(),
-					addressId: this.addressId,
-					address: this.address,
-					payType: this.payType,
-				}
+      this.submitButtonStat = true
+      this.$prompt(this.$t('shop.inputPasswordTips'), this.$t('common.hint'), {
+        confirmButtonText: this.$t('common.confirm'),
+        cancelButtonText: this.$t('common.cancel'),
+        customClass: 'csClass',
+        type: 'info',
+        inputType: 'password',
+        inputPattern: /\S+/,
+        inputErrorMessage: this.$t('shop.inputPasswordTips')
+      }).then(({ value }) => {
+        this.payPassword = value
+        const params = {
+          goodsId: this.goodsId,
+          goodsNum: this.goodsNum,
+          payPassword: this.payPassword,
+          email: usersInfo.userEmail(),
+          addressId: this.addressId,
+          address: this.address,
+          payType: this.payType
+        }
 
-				createOrder(params).then(() => {
-					this.submitButtonStat = false
-					this.$message({
-						message: this.$t('common.successfully'),
-						type: 'success',
-						duration: 5 * 1000
-					})
-					this.$router.push({path: `/shop/order-list`})
-				}).catch(err => {
-					this.$message({
-						message: err,
-						type: 'error',
-						duration: 5 * 1000
-					})
-					this.submitButtonStat = false
-				})
-			}).catch(err => {
-				this.submitButtonStat = false
-			})
-		},
-		// 计算价格
-		getSumMoney () {
-			let cash_plus_sum = [];
-			let goodsId = [];
-			let goodsNum = [];
-			let choseNum = 0;
-			this.goods.map(item => {
-				choseNum = Number(item.chose_num);
-				if (choseNum > 0) {
-					cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100));
-					goodsId.push(item.ID);
-					goodsNum.push(choseNum);
-				}
-			})
-			this.goodsNum = goodsNum;
-			this.goodsId = goodsId;
-			// 增加运费
-			let payAmount = tool.sum(cash_plus_sum);
-			// 设置运费
-			this.setFreight();
-			// 商品总价大于预定值,免运费
-			this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
-			// 计算总价
-			this.pointsSum = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight) ;
-		},
-		// 展示购物车信息
-		getShowCart () {
-			let orderGoods = this.multipleSelection
-			let cartGoods = []
-			for (let i in orderGoods) {
-				cartGoods = orderGoods[i]
-				if (!cartGoods) continue
+        createOrder(params).then(() => {
+          this.submitButtonStat = false
+          this.$message({
+            message: this.$t('common.successfully'),
+            type: 'success',
+            duration: 5 * 1000
+          })
+          this.$router.push({ path: `/shop/own-order` })
+        }).catch(err => {
+          this.$message({
+            message: err,
+            type: 'error',
+            duration: 5 * 1000
+          })
+          this.submitButtonStat = false
+        })
+      }).catch(err => {
+        this.submitButtonStat = false
+      })
+    },
+    // 计算价格
+    getSumMoney() {
+      const cash_plus_sum = []
+      const goodsId = []
+      const goodsNum = []
+      let choseNum = 0
+      this.goods.map(item => {
+        choseNum = Number(item.chose_num)
+        if (choseNum > 0) {
+          cash_plus_sum.push(item.SELL_PRICE * choseNum * (item.DISCOUNT / 100))
+          goodsId.push(item.ID)
+          goodsNum.push(choseNum)
+        }
+      })
+      this.goodsNum = goodsNum
+      this.goodsId = goodsId
+      // 增加运费
+      const payAmount = tool.sum(cash_plus_sum)
+      // 设置运费
+      this.setFreight()
+      // 商品总价大于预定值,免运费
+      this.pointFreight = (this.pointFreight > 0) ? ((payAmount >= this.freeShipping) ? 0 : this.freight) : 0
+      // 计算总价
+      this.pointsSum = tool.formatPrice(tool.sum(cash_plus_sum) + this.pointFreight)
+    },
+    // 展示购物车信息
+    getShowCart() {
+      const orderGoods = this.multipleSelection
+      let cartGoods = []
+      for (const i in orderGoods) {
+        cartGoods = orderGoods[i]
+        if (!cartGoods) continue
 
-				cartGoods.map(item => {
-					if (Number(item.chose_num) > 0) {
-						let discount = item.DISCOUNT / 100
-						item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100;
-						item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100;
-						item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100;
-						this.goods.push(item)
-						this.totalAmount += item.member_price_plus
-					}
-				})
-			}
+        cartGoods.map(item => {
+          if (Number(item.chose_num) > 0) {
+            const discount = item.DISCOUNT / 100
+            item.member_price = Math.round(item.SELL_PRICE * discount * 100) / 100
+            item.member_price_plus = Math.round(item.SELL_PRICE * Number(item.chose_num) * discount * 100) / 100
+            item.tax_amount_plus = Math.round((item.member_price - item.member_price / (1 + item.TAX_RATE / 100)) * item.chose_num * 100) / 100
+            this.goods.push(item)
+            this.totalAmount += item.member_price_plus
+          }
+        })
+      }
 
-			this.goods = cartGoods
+      this.goods = cartGoods
 
-			// 计算价格
-			this.getSumMoney();
-		},
-		// 选择收货地址
-		choseAddress (addressId) {
-			this.addressId = addressId
-			// 设置运费
-			this.setFreight()
-			// 计算价格
-			this.getSumMoney()
-		},
-		// 切换支付方式
-		chosePayType(type) {
-			this.payType = type
-		},
-		// 商品详情
-		handleProduct(row) {
-			this.product = row
-			this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-			this.visibleProduct = true
-		},
-	},
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 选择收货地址
+    choseAddress(addressId) {
+      this.addressId = addressId
+      // 设置运费
+      this.setFreight()
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 切换支付方式
+    chosePayType(type) {
+      this.payType = type
+    },
+    // 商品详情
+    handleProduct(row) {
+      this.product = row
+      this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+      this.visibleProduct = true
+    }
+  }
 }
 </script>
 

+ 12 - 12
src/views/user/brand-ambassador.vue

@@ -30,7 +30,7 @@
 														<div style="text-align: left; line-height: 25px;">
 															<span style="font-weight: bold; cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span><br />
 															<span>{{ row.GOODS_NO }}</span><br />
-															<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ row.SELL_PRICE | toThousandFilter}}</span><br />
+															<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ row.SELL_PRICE | toThousandFilter}}</span><br />
 															<span>{{ $t('shop.productBV') }}:{{ row.PRICE_PV | toThousandFilter }}</span><br />
 															<span style="display: inline-block; float: right; ">
 																<el-input-number size="mini" v-model="storeNums[$index]" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)"></el-input-number>
@@ -45,9 +45,9 @@
 
 									<div class="white-box-footer">
 										<div class="flex data" style="display: inline-block; line-height: 30px; font-size: 14px; margin-top: 15px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
-											<div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ sellPriceSum | toThousandFilter }}</div>
+											<div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productPrice') }}: {{ sellPriceSum | toThousandFilter }}</div>
 											<div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
-											<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ taxSum | toThousandFilter }}</div>
+											<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ taxSum | toThousandFilter }}</div>
 										</div>
 									</div>
 								</el-tab-pane>
@@ -107,7 +107,7 @@
 						<el-form-item :label="$t('shop.paymentMethod')" required>
 							<el-radio-group v-model="form.payType" @change="chosePayType">
 								<el-radio border v-for="(item, index) in payList" :key='index' :label="item.label" style="margin: 5px;">
-									{{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">({{ $t('currency.sign') }} {{ userBalance.cash | toThousandFilter }})</span>
+									{{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">( {{ userBalance.cash | toThousandFilter }})</span>
 								</el-radio>
 							</el-radio-group>
 						</el-form-item>
@@ -171,10 +171,10 @@
 					<div style="text-align: left; line-height: 50px; font-size: 16px;">
 						<span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br />
 						<span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br />
-						<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ product.SELL_PRICE | toThousandFilter }}</span><br />
+						<span style="color: tomato;">{{ $t('shop.productPrice') }}: {{ product.SELL_PRICE | toThousandFilter }}</span><br />
 						<span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br />
 						<span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br />
-						<span>{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ product.taxAmount | toThousandFilter }}</span><br />
+						<span>{{ $t('shop.taxAmount') }}: {{ product.taxAmount | toThousandFilter }}</span><br />
 						<span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
 					</div>
 				</el-col>
@@ -184,15 +184,15 @@
 </template>
 
 <script>
-import {fetchBrandAmbassador, createBrandAmbassador, fetchFullInfo} from '@/api/user'
-import waves from '@/directive/waves'
-import {formatAmount, getScreenWidth} from "@/utils"
+import { deleteApproachOrder } from "@/api/shop"
+import { createBrandAmbassador, fetchBrandAmbassador, fetchFullInfo } from '@/api/user'
 import Pagination from '@/components/Pagination'
-import paystack from 'vue-paystack'
+import waves from '@/directive/waves'
+import region from "@/store/modules/region"
+import { getScreenWidth } from "@/utils"
 import tool from "@/utils/tool"
 import usersInfo from "@/utils/usersInfo"
-import {deleteApproachOrder} from "@/api/shop"
-import region from "@/store/modules/region"
+import paystack from 'vue-paystack'
 
 export default {
   name: 'brandAmbassador',

+ 214 - 0
src/views/user/member-order.vue

@@ -0,0 +1,214 @@
+<template>
+  <div class="app-container">
+    <el-table
+      v-loading="listLoading"
+      fit
+      lazy
+      highlight-current-row
+      :data="tableData"
+    >
+      <el-table-column type="expand">
+        <template slot-scope="props">
+          <el-col :xs="18" :sm="18" :lg="18">
+            <el-card class="box-card" shadow="hover">
+              <el-table v-loading="listLoading" fit lazy highlight-current-row :data="props.row.hasChildren">
+                <el-table-column align="center" min-width="120px" :label="$t('shop.productCode')" prop="SKU_CODE">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;">{{ row.SKU_CODE }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" min-width="200px" :label="$t('shop.productName')" prop="GOODS_TITLE">
+                  <template slot-scope="{row}">
+                    <span>{{ row.GOODS_TITLE }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.qty')" prop="BUY_NUMS">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;">{{ row.BUY_NUMS }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.productPrice')" min-width="150px">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;"> {{ row.REAL_PRICE | toThousandFilter }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.totalPrice')">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;"> {{ row | priceAmountFilter | toThousandFilter }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.totalBV')">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;">{{ row | bvFilter | toThousandFilter }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.taxRate')">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;">{{ row.TAX_RATE / 100 }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" :label="$t('shop.totalTaxAmount')">
+                  <template slot-scope="{row}">
+                    <span style="white-space: nowrap;">  {{ row | taxAmountFilter | toThousandFilter }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-card>
+          </el-col>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.orderCode')" prop="SN" min-width="120px" style="white-space: pre-wrap;">
+        <template slot-scope="{row}">
+          <span style="white-space: pre-wrap; display: inline-block; min-width: 120px; word-break: break-all;">{{ row.SN }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.memberCode')" prop="USER_NAME" min-width="150px" />
+      <el-table-column align="center" :label="$t('shop.memberName')" prop="REAL_NAME" min-width="150px">
+        <template slot-scope="{row}">
+          <span style="white-space: pre-wrap; display: inline-block; min-width: 120px; word-break: break-all;">{{ row.REAL_NAME }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.recipientName')" prop="CONSIGNEE" min-width="150px">
+        <template slot-scope="{row}">
+          <span style="white-space: pre-wrap; min-width: 120px; word-break: break-all;">{{ row.CONSIGNEE }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.phoneNumber')" prop="MOBILE" min-width="130px" />
+      <el-table-column align="center" :label="$t('shop.shippingAddress')" prop="FULL_ADDRESS" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ row.FULL_ADDRESS }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.country')" prop="COUNTRY" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ row.COUNTRY }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.paymentCurrency')" prop="COUNTRY" min-width="140px">
+        <template slot-scope="{row}">
+          <span>{{ row.CURRENCY }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.payment')" prop="PAY_TYPE" min-width="100px" />
+      <el-table-column align="center" :label="$t('shop.createdTime')" prop="CREATED_AT" min-width="110px">
+        <template slot-scope="{row}">
+          <span>{{ tool.convertToNigeriaTime(row.CREATED_AT) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.payTime')" prop="PAY_AT" min-width="110px">
+        <template slot-scope="{row}">
+          <span>{{ tool.convertToNigeriaTime(row.PAY_AT) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.payStatus')" prop="STATUS" min-width="110px">
+        <template slot-scope="{row}">
+          <el-tag :type="row.STATUS | statusFilter">
+            {{ row.STATUS }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" :label="$t('shop.orderType')" prop="ORDER_TYPE" min-width="110px" />
+      <el-table-column align="center" :label="$t('shop.action')" class-name="small-padding fixed-width">
+        <template slot-scope="{row}">
+          <el-button type="text" size="mini" @click="handleDownload(row.SN)">{{ $t('shop.download') }}</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getList" />
+  </div>
+</template>
+
+<script>
+import { downloadOrder, fetchOrderList } from '@/api/user'
+import Pagination from '@/components/Pagination'
+import waves from '@/directive/waves'
+import { getScreenWidth } from '@/utils'
+import tool from '@/utils/tool'
+
+export default {
+  name: 'MemberOrder',
+  computed: {
+    tool() {
+      return tool
+    }
+  },
+  components: { Pagination },
+  directives: { waves },
+  filters: {
+    bvFilter(row) {
+      return tool.calculateBV(row.REAL_PV, row.BUY_NUMS)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.REAL_PRICE, row.BUY_NUMS)
+    },
+    priceAmountFilter(row) {
+      return tool.formatPrice(row.REAL_PRICE * row.BUY_NUMS)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+      total: 0,
+      tableData: [],
+      listLoading: true,
+      downloadLoading: false,
+      listQuery: {
+        v: 2,
+        page: 1,
+        pageSize: 20
+      },
+      childrenNode: [],
+      screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top'
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      fetchOrderList(this.listQuery).then(response => {
+        this.tableData = response.data.list
+        this.total = +response.data.totalCount
+
+        setTimeout(() => {
+          this.listLoading = false
+        }, 0.5 * 1000)
+      })
+    },
+    handleDownload(orderSn) {
+      this.downloadLoading = true
+      downloadOrder(orderSn).then(response => {
+        const { fileUrl, targetName } = response.data
+        const downloadElement = document.createElement('a')
+        downloadElement.target = '_blank'
+        downloadElement.href = process.env.VUE_APP_BASE_DO_API + '/' + fileUrl
+        downloadElement.download = targetName
+        downloadElement.click()
+      })
+
+      this.downloadLoading = false
+    }
+  }
+}
+</script>
+
+<style>
+.el-table th.el-table__cell > .cell {
+	white-space: nowrap;
+}
+
+.el-table td.el-table__cell > .cell {
+	word-break: keep-all;
+	white-space: pre-wrap;
+}
+</style>

+ 630 - 592
src/views/user/member-upgrade.vue

@@ -1,637 +1,675 @@
 <template>
-	<div v-loading="loading">
-		<div class="white-box" style="padding: 15px 25px;">
-			<el-row :gutter="20">
-				<el-col :xs="24" :sm="16" :lg="16">
-					<el-form :model="form" ref="form" :label-position="labelPosition" label-width="180px" class="form-page">
-						<el-form-item :label="$t('shop.memberCode')" prop="insertUserName">
-							<el-input v-model.trim="form.insertUserName" @blur="fetchUpgradeInfo" :placeholder="$t('user.enterMemberCode')" :rules="{ required: true, message: $t('user.enterMemberCode'), trigger: 'blur' }"></el-input>
-						</el-form-item>
-						<el-form-item :label="$t('profile.memberLevel')">
-							<el-input v-model="form.userDecName" disabled></el-input>
-						</el-form-item>
-						<el-form-item :label="$t('shop.memberName')">
-							<el-input v-model="form.userRealName" disabled></el-input>
-						</el-form-item>
-						<el-form-item :label="$t('profile.joiningDate')">
-							<el-input v-model="form.addAt" disabled></el-input>
-						</el-form-item>
+  <div v-loading="loading">
+    <div class="white-box" style="padding: 15px 25px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="16" :lg="16">
+          <el-form ref="form" :model="form" :label-position="labelPosition" label-width="180px" class="form-page">
+            <el-form-item :label="$t('shop.memberCode')" prop="insertUserName">
+              <el-input v-model="form.insertUserName" :placeholder="$t('user.enterMemberCode')" :disabled="isDec" :rules="{ required: true, message: $t('user.enterMemberCode'), trigger: 'blur' }" @blur="fetchUpgradeInfo" />
+            </el-form-item>
+            <el-form-item :label="$t('profile.memberLevel')">
+              <el-input v-model="form.userDecName" disabled />
+            </el-form-item>
+            <el-form-item :label="$t('shop.memberName')">
+              <el-input v-model="form.userRealName" disabled />
+            </el-form-item>
+            <el-form-item :label="$t('profile.joiningDate')">
+              <el-input v-model="form.addAt" disabled />
+            </el-form-item>
 
-						<el-form-item v-if="!isMax" :label="$t('profile.upgradeWay')">
-							<el-input v-model="form.upgradeFunc" disabled></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" prop="upgradeValue" :label="$t('profile.toUpgradeLevel')">
-							<el-select v-model="form.upgradeValue" :placeholder="$t('profile.selectLevel')" @change="handleChangeLevel($event)" style="width: 100%;">
-								<el-option v-for="item in upgradeOption" :key="item.ID" :label="item.LEVEL_NAME" :value="{value:item.ID, diffPv:item.REPAIR_PV}"></el-option>
-							</el-select>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('profile.topUpBV')">
-							<el-input v-model="needDiffPv" disabled></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax">
-							<template slot="label">{{ $t('profile.upgradePurchaseProduct') }}</template>
-							<el-tabs type="border-card" v-model="decWay" style="position: relative; width: 100%;">
-								<el-tab-pane :label="$t('shop.product')" name="2">
-									<el-collapse accordion v-model="activeName">
-										<el-collapse-item name="product">
-											<el-table :data="tableData" :show-header="false" @selection-change="handleSelectionChange">
-												<el-table-column type="selection" width="30" align="center" style="top: -30px;"></el-table-column>
-												<el-table-column align="center">
-													<template slot-scope="{row, $index}">
-														<el-container>
-															<el-aside width="80px" style=" padding: 0; margin-bottom: 0; background-color: #ffffff;">
-																<el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')"></el-image>
-															</el-aside>
-															<el-main style="padding: 0;">
-																<div style="text-align: left; line-height: 25px;">
-																	<span style="font-weight: bold; cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span><br />
-																	<span>{{ row.GOODS_NO }}</span><br />
-																	<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ row.SELL_PRICE | toThousandFilter }}</span><br />
-																	<span>{{ $t('shop.productBV') }}:{{ row.PRICE_PV | toThousandFilter }}</span><br />
-																	<span style="display: inline-block; float: right; ">
-																	<el-input-number size="mini" v-model="storeNums[$index]" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)"></el-input-number>
-																</span>
-																	<br />
-																</div>
-															</el-main>
-														</el-container>
-													</template>
-												</el-table-column>
-											</el-table>
-										</el-collapse-item>
-									</el-collapse>
+            <el-form-item v-if="!isMax" :label="$t('profile.upgradeWay')">
+              <el-input v-model="form.upgradeFunc" disabled />
+            </el-form-item>
+            <el-form-item v-if="!isMax" prop="upgradeValue" :label="$t('profile.toUpgradeLevel')">
+              <el-select v-model="form.upgradeValue" :placeholder="$t('profile.selectLevel')" style="width: 100%;" @change="handleChangeLevel($event)">
+                <el-option v-for="item in upgradeOption" :key="item.ID" :label="item.LEVEL_NAME" :value="{value:item.ID, diffPv:item.REPAIR_PV}" />
+              </el-select>
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('profile.topUpBV')">
+              <el-input v-model="needDiffPv" disabled />
+            </el-form-item>
+            <el-form-item v-if="!isMax">
+              <template slot="label">{{ $t('profile.upgradePurchaseProduct') }}</template>
+              <el-tabs v-model="decWay" type="border-card" style="position: relative; width: 100%;">
+                <el-tab-pane :label="$t('shop.product')" name="2">
+                  <el-collapse v-model="activeName" accordion>
+                    <el-collapse-item name="product">
+                      <el-table :data="tableData" :show-header="false" @selection-change="handleSelectionChange">
+                        <el-table-column type="selection" width="30" align="center" style="top: -30px;" />
+                        <el-table-column align="center">
+                          <template slot-scope="{row, $index}">
+                            <el-container>
+                              <el-aside width="80px" style=" padding: 0; margin-bottom: 0; background-color: #ffffff;">
+                                <el-image style="width: 80px; height: 80px" :src="tool.getArImage(row.COVER, '/files/')" />
+                              </el-aside>
+                              <el-main style="padding: 0;">
+                                <div style="text-align: left; line-height: 25px;">
+                                  <span style="font-weight: bold; cursor: pointer;" @click="handleProduct(row)">{{ row.GOODS_NAME }}</span><br>
+                                  <span>{{ row.GOODS_NO }}</span><br>
+                                  <span style="color: tomato;">{{ $t('shop.salesPrice') }}:{{row.CODE}} {{ row.SELL_PRICE | toThousandFilter }}</span><br>
+                                  <span>{{ $t('shop.productBV') }}:{{ row.PRICE_PV | toThousandFilter }}</span><br>
+                                  <span>{{ $t('shop.marketPrice') }}:{{row.CODE}} {{ row.MARKET_PRICE | toThousandFilter }}</span><br>
+                                  <span style="display: inline-block; float: right; ">
+                                    <el-input-number v-model="storeNums[$index]" size="mini" :min="1" :max="Number(row.STORE_NUMS)" @change="handleInputNumber($event, row)" />
+                                  </span>
+                                  <br>
+                                </div>
+                              </el-main>
+                            </el-container>
+                          </template>
+                        </el-table-column>
+                      </el-table>
+                    </el-collapse-item>
+                  </el-collapse>
 
-									<div class="white-box-footer">
-										<div class="flex data" style="float: right; display: inline-block; line-height: 30px; font-size: 14px; margin-top: 15px; margin-bottom: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
-											<div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ sellPriceSum | toThousandFilter }}</div>
-											<div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
-											<div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ taxSum }}</div>
-										</div>
-									</div>
-								</el-tab-pane>
-							</el-tabs>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('shop.recipientName')">
-							<el-input v-model="form.consignee"></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('shop.phoneNumber')">
-							<el-input v-model="form.acceptMobile"></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" prop="areaSelected" :label="$t('config.state')">
-							<el-cascader size="large" :options="regionData" v-model="form.areaSelected" style="width: 100%;"></el-cascader>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('config.localGovernmentArea')">
-							<el-input v-model="form.lgaName"></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('config.city')">
-							<el-input v-model="form.cityName"></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('config.detailedAddress')">
-							<el-input v-model="form.address"></el-input>
-						</el-form-item>
-						<el-form-item v-if="!isMax" :label="$t('common.note')">
-							<el-input type="textarea" v-model="form.remark"></el-input>
-						</el-form-item>
+                  <div class="white-box-footer">
+                    <div class="flex data" style="float: right; display: inline-block; line-height: 30px; font-size: 14px; margin-top: 15px; margin-bottom: 10px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 5px;">
+                      <div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productPrice') }}:{{currencyUnitCode}} {{ sellPriceSum | toThousandFilter }}</div>
+                      <div style="margin-right: 1rem; display: inline-block;">{{ $t('shop.productBV') }}:{{ pricePvSum | toThousandFilter }}</div>
+                      <div style="display: inline-block;">{{ $t('shop.taxAmount') }}:{{currencyUnitCode}} {{ taxSum }}</div>
+                    </div>
+                  </div>
+                </el-tab-pane>
+              </el-tabs>
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('shop.recipientName')">
+              <el-input v-model="form.consignee" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('shop.phoneNumber')">
+              <el-input v-model="form.acceptMobile" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" prop="areaSelected" :label="$t('config.state')">
+              <el-cascader v-model="form.areaSelected" size="large" :options="regionData" style="width: 100%;" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('config.localGovernmentArea')">
+              <el-input v-model="form.lgaName" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('config.city')">
+              <el-input v-model="form.cityName" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('config.detailedAddress')">
+              <el-input v-model="form.address" />
+            </el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('common.note')">
+              <el-input v-model="form.remark" type="textarea" />
+            </el-form-item>
 
-						<el-form-item v-if="!isMax" :label="$t('shop.paymentMethod')" required style="padding-left: 0;">
-							<el-radio-group v-model="form.payType" @change="chosePayType">
-								<el-radio border v-for="(item, index) in payList" :key='index' :label="item.label" style="margin: 5px;">
-									{{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">({{ $t('currency.sign') }} {{ userBalance.cash | toThousandFilter }})</span>
-								</el-radio>
-							</el-radio-group>
-						</el-form-item>
+            <el-form-item v-if="!isMax" :label="$t('shop.paymentMethod')" required style="padding-left: 0;">
+              <el-radio-group v-model="form.payType" @change="chosePayType">
+                <el-radio v-for="(item, index) in payList" :key="index" border :label="item.label" style="margin: 5px;">
+                  {{ item.name }}<span v-if="item.label === 'cash'" style="color: tomato;">( {{currencyUnitCode}} {{ userBalance.cash | toThousandFilter }})</span>
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
 
-						<el-form-item v-if="!isMax">
-							<el-button size="small" type="primary" @click="onSubmit" :loading="submitButtonStat">{{ $t('common.save') }}</el-button>
-						</el-form-item>
-				</el-form>
-				</el-col>
-			</el-row>
-		</div>
+            <el-form-item v-if="!isMax">
+              <el-button size="small" type="primary" :loading="submitButtonStat" @click="onSubmit">{{ $t('common.save') }}</el-button>
+            </el-form-item>
+          </el-form>
+        </el-col>
+      </el-row>
+    </div>
 
-		<!-- payStack模态框 -->
-		<el-dialog :title="$t('shop.goPay')" :visible.sync="visible" :width="payStackScreenWidth" v-loading="payStackLoading" :before-close="handleClose">
-			<section>
-				<el-form :model="payForm">
-					<el-form-item :label="$t('user.email')" label-width="100px" required>
-						<el-input v-model="payForm.email" autocomplete="off"></el-input>
-					</el-form-item>
-					<el-form-item :label="$t('shop.amount')" label-width="100px" required>
-						<el-input v-model="payForm.amount" autocomplete="off" readonly></el-input>
-					</el-form-item>
-				</el-form>
-			</section>
-			<paystack
-				:firstname="payForm.firstname"
-				:lastname="payForm.lastname"
-				:amount="payForm.amount * 100"
-				:email="payForm.email"
-				:metadata="payForm.metadata"
-				:currency="payForm.currency"
-				:paystackkey="payForm.publicKey"
-				:reference="reference"
-				:channels="channels"
-				:callback="processPayment"
-				:close="handleClose"
-			>
-				<el-button type="primary" size="small">{{ $t('shop.goPay') }}</el-button>
-			</paystack>
-			<el-button type="danger" size="small" class="cancelButton" @click="handleClose" style="margin-left: 10px;">{{ $t('common.cancel') }}</el-button>
-		</el-dialog>
+    <!-- payStack模态框 -->
+    <el-dialog v-loading="payStackLoading" :title="$t('shop.goPay')" :visible.sync="visible" :width="payStackScreenWidth" :before-close="handleClose">
+      <section>
+        <el-form :model="payForm">
+          <el-form-item :label="$t('user.email')" label-width="100px" required>
+            <el-input v-model="payForm.email" autocomplete="off" />
+          </el-form-item>
+          <el-form-item :label="$t('shop.amount')" label-width="100px" required>
+            <el-input v-model="payForm.amount" autocomplete="off" readonly />
+          </el-form-item>
+        </el-form>
+      </section>
+      <paystack
+        :firstname="payForm.firstname"
+        :lastname="payForm.lastname"
+        :amount="payForm.amount * 100"
+        :email="payForm.email"
+        :metadata="payForm.metadata"
+        :currency="payForm.currency"
+        :paystackkey="payForm.publicKey"
+        :reference="reference"
+        :channels="channels"
+        :callback="processPayment"
+        :close="handleClose"
+      >
+        <el-button type="primary" size="small">{{ $t('shop.goPay') }}</el-button>
+      </paystack>
+      <el-button type="danger" size="small" class="cancelButton" style="margin-left: 10px;" @click="handleClose">{{ $t('common.cancel') }}</el-button>
+    </el-dialog>
 
-		<!-- 倒计时页面 -->
-		<el-dialog :title="$t('common.hint')" :visible.sync="payDialog" :width="payStackScreenWidth" :show-close="false" :close="handleOrderList">
-			<el-card shadow="always">
-				<el-result icon="success" :title="$t('common.successfully')" :subTitle="$t('shop.successOrderTips')">
-					<template slot="extra">
-						<el-button type="primary" size="medium" @click="handleOrderList">{{ $t('shop.goBack') }}({{ countdown }})</el-button>
-					</template>
-				</el-result>
-			</el-card>
-		</el-dialog>
+    <!-- 倒计时页面 -->
+    <el-dialog :title="$t('common.hint')" :visible.sync="payDialog" :width="payStackScreenWidth" :show-close="false" :close="handleOrderList">
+      <el-card shadow="always">
+        <el-result icon="success" :title="$t('common.successfully')" :sub-title="$t('shop.successOrderTips')">
+          <template slot="extra">
+            <el-button type="primary" size="medium" @click="handleOrderList">{{ $t('shop.goBack') }}({{ countdown }})</el-button>
+          </template>
+        </el-result>
+      </el-card>
+    </el-dialog>
 
-		<!-- 商品详情 -->
-		<el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
-			<el-row :gutter="20">
-				<el-col :xs="24" :sm="12" :lg="12">
-					<el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')"></el-image>
-				</el-col>
-				<el-col :xs="24" :sm="12" :lg="12">
-					<div style="text-align: left; line-height: 50px; font-size: 16px;">
-						<span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br />
-						<span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br />
-						<span style="color: tomato;">{{ $t('shop.productPrice') }}:{{ $t('currency.sign') }} {{ product.SELL_PRICE | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br />
-						<span>{{ $t('shop.taxAmount') }}:{{ $t('currency.sign') }} {{ product.taxAmount | toThousandFilter }}</span><br />
-						<span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
-					</div>
-				</el-col>
-			</el-row>
-		</el-dialog>
-	</div>
+    <!-- 商品详情 -->
+    <el-dialog :title="product.GOODS_NO" :visible.sync="visibleProduct" :width="screenWidth" style="margin-top: -95px;">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="12" :lg="12">
+          <el-image style="width: 100%; height: 100%" :style="imageStyle" :src="tool.getArImage(product.COVER, '/files/')" />
+        </el-col>
+        <el-col :xs="24" :sm="12" :lg="12">
+          <div style="text-align: left; line-height: 50px; font-size: 16px;">
+            <span style="font-weight: bold; font-size: 20px;">{{ product.GOODS_NAME }}</span><br>
+            <span style="font-weight: bold; font-size: 15px;">{{ $t('shop.productCode') }}:{{ product.GOODS_NO }}</span><br>
+            <span style="color: tomato;">{{ $t('shop.salesPrice') }}:{{currencyUnitCode}} {{ product.SELL_PRICE }}</span><br>
+            <span>{{ $t('shop.marketPrice') }}:{{currencyUnitCode}} {{ product.MARKET_PRICE }}</span><br>
+            <span>{{ $t('shop.productBV') }}:{{ product.PRICE_PV | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.taxRate') }}:{{ product.TAX_RATE / 100 }}</span><br>
+            <span>{{ $t('shop.taxAmount') }}:{{currencyUnitCode}} {{ product.taxAmount | toThousandFilter }}</span><br>
+            <span>{{ $t('shop.inventory') }}:{{ product.STORE_NUMS }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-import {fetchFullInfo, fetchSendUpgrade, fetchUpgrade, fetchUpgradeInfo} from '@/api/user'
-import waves from '@/directive/waves'
-import {formatAmount, getScreenWidth} from "@/utils"
+import { deleteApproachOrder } from '@/api/shop'
+import {fetchFullInfo, fetchSendUpgrade, fetchUpgrade, fetchUpgradeInfo, getUserInfo} from '@/api/user'
 import Pagination from '@/components/Pagination'
+import waves from '@/directive/waves'
+import region from '@/store/modules/region'
+import { getScreenWidth } from '@/utils'
+import tool from '@/utils/tool'
+import usersInfo from '@/utils/usersInfo'
 import paystack from 'vue-paystack'
-import tool from "@/utils/tool"
-import {deleteApproachOrder} from "@/api/shop"
-import usersInfo from "@/utils/usersInfo"
-import region from "@/store/modules/region"
 
 export default {
-  name: 'upgradeManagement',
+  name: 'UpgradeManagement',
   components: { Pagination, paystack },
   directives: { waves },
-	filters: {
-		bvFilter(row) {
-			return tool.calculateBV(row.REAL_PV, row.BUY_NUMS)
-		},
-		taxAmountFilter(row) {
-			return tool.calculateTax(row.REAL_PRICE, row.BUY_NUMS)
-		},
-		priceAmountFilter(row) {
-			return tool.formatPrice(row.REAL_PRICE * row.BUY_NUMS)
-		},
-		statusFilter(status) {
-			const statusMap = {
-				Unpaid: 'info',
-				Paid: 'success'
-			}
-			return statusMap[status]
-		}
-	},
-	computed: {
-		// PayStack混淆串
-		reference() {
-			let text = ''
-			let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-			for (let i = 0; i < 10; i++) {
-				text += possible.charAt(Math.floor(Math.random() * possible.length))
-			}
-			return text
-		}
-	},
+  filters: {
+    bvFilter(row) {
+      return tool.calculateBV(row.REAL_PV, row.BUY_NUMS)
+    },
+    taxAmountFilter(row) {
+      return tool.calculateTax(row.REAL_PRICE, row.BUY_NUMS)
+    },
+    priceAmountFilter(row) {
+      return tool.formatPrice(row.REAL_PRICE * row.BUY_NUMS)
+    },
+    statusFilter(status) {
+      const statusMap = {
+        Unpaid: 'info',
+        Paid: 'success'
+      }
+      return statusMap[status]
+    }
+  },
   data() {
-		return {
-			tool: tool,
+    return {
+      tool: tool,
 
-			nowPerf: '',
-			nextPerf: '',
-			decUserName: '',
-			needDiffPv: '',
-			isMax: true,
-			upgradeOption: [],
-			toLevel: '',
-			currentRow: null,
-			decWay: '2',
-			regionData: region.regionInfo.regionData,
-			form: {
-				address: '',
-				areaSelected:[],
-				consignee: '',
-				upgradeFunc: '',
-				upgradeValue: '',
-				addAt: '',
-				userRealName: '',
-				userDecName: '',
-				remark: '',
-				realName: '',
-				decLv: '',
-				insertUserName: '',
-				decUserName: '',
-				recUserName: '',
-				conUserName: '',
-				insertUserIdCard: '',
-				packageId: '',
-				goodsId:[],
-				goodsNum:[],
-				province: '',
-				// city: '',
-				// county: '',
-				lgaName: '',
-				cityName: '',
-				acceptMobile: '',
-				payType: '',
-			},
-			num: 1,
-			allDecPackage: {},
-			loading: false,
-			submitButtonStat: false,
-			submitButton: false,
-			allGoods: [],
-			goodsNums: [],
-			numList: [],
-			sell_price_sum: 0.00,
-			price_pv_sum: 0.00,
-			payList: [],
-			sn: '',
-			payDialog: false,
-			countdown: 5,
-			visible: false,
-			payStackLoading: false,
-			channels: ['card', 'bank', 'ussd', 'qr'], // eft(南非)  mobile_money(加纳)
-			payForm: {
-				publicKey: process.env.VUE_APP_BASE_PAY_STACK_PUBLIC_KEY,
-				currency: 'NGN',
-				firstname: usersInfo.userName(),
-				lastname: '',
-				email: usersInfo.userEmail(),
-				amount: 0, // kobo
-				orderSn: '',
-				metadata: {
-					cart_id: '',
-					custom_fields: [
-						{
-							display_name: 'orderSn',
-							variable_name: 'orderSn',
-							value: this.sn
-						},
-						{
-							display_name: 'orderType',
-							variable_name: 'orderType',
-							value: 'userUpgrade'
-						},
-					]
-				},
-			},
+      nowPerf: '',
+      nextPerf: '',
+      decUserName: '',
+      needDiffPv: '',
+      isMax: true,
+      upgradeOption: [],
+      toLevel: '',
+      currentRow: null,
+      decWay: '2',
+      regionData: [],
+      form: {
+        address: '',
+        areaSelected: [],
+        consignee: '',
+        upgradeFunc: '',
+        upgradeValue: '',
+        addAt: '',
+        userRealName: '',
+        userDecName: '',
+        remark: '',
+        realName: '',
+        decLv: '',
+        insertUserName: '',
+        decUserName: '',
+        recUserName: '',
+        conUserName: '',
+        insertUserIdCard: '',
+        packageId: '',
+        goodsId: [],
+        goodsNum: [],
+        province: '',
+        // city: '',
+        // county: '',
+        lgaName: '',
+        cityName: '',
+        acceptMobile: '',
+        payType: ''
+      },
+      num: 1,
+      allDecPackage: {},
+      loading: false,
+      submitButtonStat: false,
+      submitButton: false,
+      allGoods: [],
+      goodsNums: [],
+      numList: [],
+      sell_price_sum: 0.00,
+      price_pv_sum: 0.00,
+      payList: [],
+      sn: '',
+      payDialog: false,
+      countdown: 5,
+      visible: false,
+      payStackLoading: false,
+      channels: ['card', 'bank', 'ussd', 'qr'], // eft(南非)  mobile_money(加纳)
+      payForm: {
+        publicKey: process.env.VUE_APP_BASE_PAY_STACK_PUBLIC_KEY,
+        currency: 'NGN',
+        firstname: usersInfo.userName(),
+        lastname: '',
+        email: usersInfo.userEmail(),
+        amount: 0, // kobo
+        orderSn: '',
+        metadata: {
+          cart_id: '',
+          custom_fields: [
+            {
+              display_name: 'orderSn',
+              variable_name: 'orderSn',
+              value: this.sn
+            },
+            {
+              display_name: 'orderType',
+              variable_name: 'orderType',
+              value: 'userUpgrade'
+            }
+          ]
+        }
+      },
 
-			addressId: '',
-			selfPickUpAddressId: '100000000000000000',
-			shippingAddressList: [],
+      addressId: '',
+      selfPickUpAddressId: '100000000000000000',
+      shippingAddressList: [],
 
-			visibleProduct: false,
-			product: {
-				GOODS_NAME: '',
-				GOODS_NO: '',
-				COVER: '',
-				SELL_PRICE: 0,
-				PRICE_PV: 0,
-				TAX_RATE: 0,
-				taxAmount: 0,
-			},
-			imageStyle: 'margin-top: -50px;',
+      visibleProduct: false,
+      product: {
+        GOODS_NAME: '',
+        GOODS_NO: '',
+        COVER: '',
+        SELL_PRICE: 0,
+        PRICE_PV: 0,
+        TAX_RATE: 0,
+        taxAmount: 0
+      },
+      imageStyle: 'margin-top: 0px;',
 
-			screenWidth: getScreenWidth() > 600 ? '600px' : getScreenWidth() + 'px',
-			labelPosition: getScreenWidth() > 500 ? 'right' : 'top',
-			payStackScreenWidth: getScreenWidth() > 500 ? '450px' : getScreenWidth() + 'px',
+      screenWidth: getScreenWidth() > 600 ? '50%' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 500 ? 'right' : 'top',
+      payStackScreenWidth: getScreenWidth() > 500 ? '450px' : getScreenWidth() + 'px',
 
-			multipleSelection: [],
-			sellPriceSum: 0.00,
-			pricePvSum: 0.00,
-			taxSum: 0.00,
-			storeNums: [],
-			tableData: null,
-			payAmount: 0.00,
-			userBalance: {
-				cash: 0,
-			},
+      multipleSelection: [],
+      sellPriceSum: 0.00,
+      pricePvSum: 0.00,
+      taxSum: 0.00,
+      storeNums: [],
+      tableData: null,
+      payAmount: 0.00,
+      userBalance: {
+        cash: 0
+      },
 
-			activeName: 'product',
-		}
+      activeName: 'product',
+      currencyUnitCode: "",
+      isDec: false
+    }
+  },
+  computed: {
+    // PayStack混淆串
+    reference() {
+      let text = ''
+      const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+      for (let i = 0; i < 10; i++) {
+        text += possible.charAt(Math.floor(Math.random() * possible.length))
+      }
+      return text
+    }
   },
   created() {
-    this.fetchUpgrade()
+    // this.fetchUpgrade()
+      this.fetchUserInfo()
+  },
+  mounted() {
   },
-	mounted() {
-	},
   methods: {
-		fetchUpgrade() {
-			this.loading = true
-			fetchUpgrade().then(response => {
-				this.loading = false
-
-				this.userBalance = response.data.userBalance
-				this.decUserName = response.data.decUserName
-				this.allDecPackage = response.data.allDecPackage
-				this.allGoods = response.data.allGoods
+      //查询是否是保单中心
+      fetchUserInfo() {
+          getUserInfo().then(res =>{
+              console.log(res)
+              if (res.data.IS_DEC == 0){
+                  this.isDec = true
+                  this.$message({
+                      message: 'Stockist does not exist',
+                      type: 'error',
+                      duration: 20000,
+                  })
+              }
+          }).catch(error => {
+          })
+      },
+    fetchUpgrade() {
+      this.loading = true
+      fetchUpgrade({
+        userName: this.form.insertUserName
+      }).then(response => {
+        this.loading = false
 
-				let settingObj = this.allGoods
-				for (let i in this.allGoods) {
-					this.storeNums[i] = 1
-					settingObj[i].goodsNum = 0
-				}
+        this.userBalance = response.data.userBalance
+        this.decUserName = response.data.decUserName
+        this.allDecPackage = response.data.allDecPackage
+        this.allGoods = response.data.allGoods
+        this.regionData = response.data.region
 
-				this.tableData = Object.values(settingObj)
-				let pageList = this.multipleSelection
-				this.$nextTick(function () {
-					for (let i in this.tableData) {
-						for( let j in  pageList) {
-							if( pageList[j].ID === this.tableData[i].ID ) {
-								this.$data.storeNums[i] = pageList[j].goodsNum
-								this.tableData[i].goodsNum = pageList[j].goodsNum
-								break
-							}
-						}
-					}
-				})
+        const settingObj = this.allGoods
+        for (const i in this.allGoods) {
+          this.storeNums[i] = 1
+          settingObj[i].goodsNum = 0
+        }
+        if(response.data.allGoods && response.data.allGoods.length > 0){
+          this.currencyUnitCode = response.data.allGoods[0].CODE
+        }
+        this.tableData = Object.values(settingObj)
+        const pageList = this.multipleSelection
+        this.$nextTick(function() {
+          for (const i in this.tableData) {
+            for (const j in pageList) {
+              if (pageList[j].ID === this.tableData[i].ID) {
+                this.$data.storeNums[i] = pageList[j].goodsNum
+                this.tableData[i].goodsNum = pageList[j].goodsNum
+                break
+              }
+            }
+          }
+        })
 
-				// 支付方式
-				this.payList = response.data.sellType[0]['sell_type']
-				// 支付方式的第一项默认选中
-				this.form.payType = Object.values(this.payList)[1]['label']
+        // 支付方式
+        this.payList = response.data.sellType[0]['sell_type']
+        // 支付方式的第一项默认选中
+        this.form.payType = Object.values(this.payList)[1]['label']
 
         setTimeout(() => {
           this.loading = false
         }, 0.5 * 1000)
       })
     },
-		fetchUpgradeInfo() {
-			this.loading = true
-			fetchUpgradeInfo({ userName: this.form.insertUserName }).then(response => {
-				this.loading = false
-				this.form.addAt = response.data.baseInfo.ADD_AT
-				this.form.userRealName = response.data.baseInfo.REAL_NAME
-				this.form.userDecName = response.data.baseInfo.DEC_NAME
-				this.isMax = response.data.baseInfo.IS_MAX
-				this.upgradeOption = response.data.baseInfo.LEVEL_LIST
-				this.form.upgradeFunc = response.data.baseInfo.UPGRADE_FUNC
-				this.nowPerf = response.data.baseInfo.NOW_PERF
-				this.nextPerf = response.data.baseInfo.NEXT_PERF
+    fetchUpgradeInfo() {
+      if (!this.form.insertUserName) {
+        this.$message({
+          message: this.$t('user.enterMemberCode'),
+          type: 'error'
+        })
+        return false
+      }
 
-				setTimeout(() => {
-					this.loading = false
-				}, 0.5 * 1000)
-			})
-		},
-		// 商品详情
-		handleProduct(row) {
-			this.product = row
-			this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
-			this.visibleProduct = true
-		},
-		// 选择商品计数
-		handleInputNumber(current, row){
-			let pageList = this.multipleSelection
-			let selectStatus = false
-			for (let i in pageList) {
-				if (pageList[i].ID === row.ID) {
-					pageList[i].goodsNum = current
-					selectStatus = true
-					break
-				}
-			}
-			if (selectStatus) {
-				this.multipleSelection = pageList
-				this.handleSureChange()
-			}
-		},
-		// 统计商品
-		handleSureChange() {
-			if (this.multipleSelection.length > 0) {
-				let accumulatorSellPrice = 0, accumulatorPricePv = 0, accumulatorTax = 0
-				this.multipleSelection.forEach(accumulator => {
-					accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.goodsNum;
-					accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.goodsNum);
-					accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.goodsNum));
-				})
+      this.loading = true
+      fetchUpgradeInfo({ userName: this.form.insertUserName }).then(response => {
+        this.loading = false
+        this.form.addAt = response.data.baseInfo.ADD_AT
+        this.form.userRealName = response.data.baseInfo.REAL_NAME
+        this.form.userDecName = response.data.baseInfo.DEC_NAME
+        this.isMax = response.data.baseInfo.IS_MAX
+        this.upgradeOption = response.data.baseInfo.LEVEL_LIST
+        this.form.upgradeFunc = response.data.baseInfo.UPGRADE_FUNC
+        this.nowPerf = response.data.baseInfo.NOW_PERF
+        this.nextPerf = response.data.baseInfo.NEXT_PERF
+        this.fetchUpgrade()
+
+        setTimeout(() => {
+          this.loading = false
+        }, 0.5 * 1000)
+      })
+    },
+    // 商品详情
+    handleProduct(row) {
+      this.product = row
+      this.product.taxAmount = tool.calculateTax(row.SELL_PRICE, row.TAX_RATE)
+      this.visibleProduct = true
+    },
+    // 选择商品计数
+    handleInputNumber(current, row) {
+      const pageList = this.multipleSelection
+      let selectStatus = false
+      for (const i in pageList) {
+        if (pageList[i].ID === row.ID) {
+          pageList[i].goodsNum = current
+          selectStatus = true
+          break
+        }
+      }
+      if (selectStatus) {
+        this.multipleSelection = pageList
+        this.handleSureChange()
+      }
+    },
+    // 统计商品
+    handleSureChange() {
+      if (this.multipleSelection.length > 0) {
+        let accumulatorSellPrice = 0; let accumulatorPricePv = 0; let accumulatorTax = 0
+        this.multipleSelection.forEach(accumulator => {
+          accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.goodsNum
+          accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.goodsNum)
+          accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.goodsNum))
+        })
 
-				this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
-				this.pricePvSum = tool.formatPrice(accumulatorPricePv)
-				this.taxSum = tool.formatPrice(accumulatorTax)
+        this.sellPriceSum = tool.formatPrice(accumulatorSellPrice)
+        this.pricePvSum = tool.formatPrice(accumulatorPricePv)
+        this.taxSum = tool.formatPrice(accumulatorTax)
 
-				this.display = true
-			} else {
-				this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
-				this.display = true
-			}
-		},
-		// 选择商品
-		handleSelectionChange(val) {
-			let idx = -1, num
-			for (let i in this.tableData) {
-				for (let v in val){
-					if (val[v].ID === this.tableData[i].ID) {
-						idx = i
-						num = this.storeNums[idx]
-						val[v]['goodsNum'] = num
-						break
-					}
-				}
-			}
-			this.multipleSelection = val
-			// 计算统计
-			this.handleSureChange()
-		},
-		// 选择收货地址
-		choseAddress (addressId) {
-			this.addressId = addressId
-			// 设置运费
-			this.setFreight()
-			// 计算价格
-			this.getSumMoney()
-		},
-		// 切换支付方式
-		chosePayType(type) {
-			this.payType = type
-		},
-		// 关闭支付回调
-		handleClose() {
-			this.$confirm(this.$t('shop.confirmClose')).then(_ => {
-				deleteApproachOrder({ orderSn: this.form.orderSn }).then(() => {
-					// 关闭支付模态框
-					this.visible = false
-					// 关闭购物车
-					this.visibleShoppingCart = false
-					this.submitButtonStat = false
-				})
-			})
-		},
-		// 支付成功回调
-		processPayment() {
-			// 关闭支付页面
-			this.visible = false
-			this.payStackLoading = false
-			// 显示支付成功模态框
-			this.payDialog = true;
-			// 启动支付成功倒计时
-			this.handleCountdown()
-		},
-		// 倒计时结束跳转
-		handleOrderList () {
-			this.$router.push({path: `/shop/order-list`})
-		},
-		// 启动倒计时
-		handleCountdown () {
-			// 创建定时器
-			setInterval(() => {
-				// 每隔1秒把time的值减一,赋值给span标签
-				this.countdown--
-				if (this.countdown === 0) {
-					// 倒计时结束,跳转到订单列表
-					this.$router.push({path: `/shop/order-list`});
-				}
-			}, 1000)
-		},
-		// 会员查询
-		handleChkRecUser () {
-			this.form.conUserName = ''
-			this.conRealName = '-'
-			this.form.autoPlace = ''
-			if (this.form.recUserName) {
-				this.loading = true
-				fetchFullInfo({ userName: this.form.recUserName }).then(response => {
-					this.recRealName = response.data.REAL_NAME
-					this.loading = false
-				}).catch(() => {
-					this.recRealName = '-'
-					this.loading = false
-				})
-			}
-		},
-		// 返回方式
-		wayChange () {
-			if (this.form.way === 'pickup') {
-				this.areaDisabled = true
-				this.addressDisabled = true
-			} else {
-				this.areaDisabled = false
-				this.addressDisabled = false
-			}
-		},
-		// 提交订单
-		onSubmit () {
-			if (!this.form.insertUserName) {
-				this.$message({
-					message: this.$t('user.enterMemberCode'),
-					type: 'error'
-				})
-				return false;
-			}
-			if (!this.toLevel) {
-				this.$message({
-					message: this.$t('profile.selectLevel'),
-					type: 'error'
-				})
-				return false
-			}
-			// 已选择商品
-			this.selectProduct()
-			if (this.multipleSelection.length <= 0) {
-				this.$message.error(this.$t('shop.chooseTips'))
-				return false
-			}
-			// 余额
-			let amountBalance = this.userBalance[this.form.payType] || 0
-			// 余额是否充足
-			if ((this.form.payType === 'cash') && ((amountBalance - this.payAmount) < 0)) {
-				// 账户类型提示信息
-				let accountType = this.currency[this.form.payType].name || ''
-				this.$message({
-					message: accountType + this.$t('shop.balanceNotAllow'),
-					type: 'error'
-				})
-				return false
-			}
+        this.display = true
+      } else {
+        this.sellPriceSum = this.pricePvSum = this.taxSum = 0.00
+        this.display = true
+      }
+    },
+    // 选择商品
+    handleSelectionChange(val) {
+      let idx = -1; let num
+      for (const i in this.tableData) {
+        for (const v in val) {
+          if (val[v].ID === this.tableData[i].ID) {
+            idx = i
+            num = this.storeNums[idx]
+            val[v]['goodsNum'] = num
+            break
+          }
+        }
+      }
+      this.multipleSelection = val
+      // 计算统计
+      this.handleSureChange()
+    },
+    // 选择收货地址
+    choseAddress(addressId) {
+      this.addressId = addressId
+      // 设置运费
+      this.setFreight()
+      // 计算价格
+      this.getSumMoney()
+    },
+    // 切换支付方式
+    chosePayType(type) {
+      this.payType = type
+    },
+    // 关闭支付回调
+    handleClose() {
+      this.$confirm(this.$t('shop.confirmClose')).then(_ => {
+        deleteApproachOrder({ orderSn: this.form.orderSn }).then(() => {
+          // 关闭支付模态框
+          this.visible = false
+          // 关闭购物车
+          this.visibleShoppingCart = false
+          this.submitButtonStat = false
+        })
+      })
+    },
+    // 支付成功回调
+    processPayment() {
+      // 关闭支付页面
+      this.visible = false
+      this.payStackLoading = false
+      // 显示支付成功模态框
+      this.payDialog = true
+      // 启动支付成功倒计时
+      this.handleCountdown()
+    },
+    // 倒计时结束跳转
+    handleOrderList() {
+      this.$router.push({ path: `/shop/member-order` })
+    },
+    // 启动倒计时
+    handleCountdown() {
+      // 创建定时器
+      setInterval(() => {
+        // 每隔1秒把time的值减一,赋值给span标签
+        this.countdown--
+        if (this.countdown === 0) {
+          // 倒计时结束,跳转到订单列表
+          this.$router.push({ path: `/shop/member-order` })
+        }
+      }, 1000)
+    },
+    // 会员查询
+    handleChkRecUser() {
+      this.form.conUserName = ''
+      this.conRealName = '-'
+      this.form.autoPlace = ''
+      if (this.form.recUserName) {
+        this.loading = true
+        fetchFullInfo({ userName: this.form.recUserName }).then(response => {
+          this.recRealName = response.data.REAL_NAME
+          this.loading = false
+        }).catch(() => {
+          this.recRealName = '-'
+          this.loading = false
+        })
+      }
+    },
+    // 返回方式
+    wayChange() {
+      if (this.form.way === 'pickup') {
+        this.areaDisabled = true
+        this.addressDisabled = true
+      } else {
+        this.areaDisabled = false
+        this.addressDisabled = false
+      }
+    },
+    // 提交订单
+    onSubmit() {
+      if (!this.form.insertUserName) {
+        this.$message({
+          message: this.$t('user.enterMemberCode'),
+          type: 'error'
+        })
+        return false
+      }
+      if (!this.toLevel) {
+        this.$message({
+          message: this.$t('profile.selectLevel'),
+          type: 'error'
+        })
+        return false
+      }
+      // 已选择商品
+      this.selectProduct()
+      if (this.multipleSelection.length <= 0) {
+        this.$message.error(this.$t('shop.chooseTips'))
+        return false
+      }
+      // 余额
+      const amountBalance = this.userBalance[this.form.payType] || 0
+      // 余额是否充足
+      if ((this.form.payType === 'cash') && ((amountBalance - this.payAmount) < 0)) {
+        // 账户类型提示信息
+        const payListArray = Array.from(this.form.payType)
+        const account = payListArray.filter(item => {
+          return this.form.payType === item.label
+        })
+        const accountType = account[0] && account[0].name || ''
+        this.$message({
+          message: accountType + this.$t('shop.balanceNotAllow'),
+          type: 'error'
+        })
+        return false
+      }
 
-			this.submitButtonStat = true
+      this.submitButtonStat = true
 
-			let params = {
-				decUserName: this.decUserName,
-				packageId: this.form.packageId,
-				goodsId: this.form.goodsId,
-				goodsNum: this.form.goodsNum,
-				location: this.form.location,
-				decWay: this.decWay,
-				decLv: this.toLevel,
-				insertUserName: this.form.insertUserName,
-				remark: this.form.remark,
-				address: this.form.address,
-				consignee: this.form.consignee,
-				acceptMobile: this.form.acceptMobile,
-				province: this.form.areaSelected[0] ? this.form.areaSelected[0] : '',
-				lgaName: this.form.lgaName,
-				cityName: this.form.cityName,
-				nowPerf: this.nowPerf,
-				nextPerf: this.nextPerf,
-				payType: this.form.payType,
-			}
-			fetchSendUpgrade(params).then(response => {
-				if (this.form.payType !== 'pay_stack') {
-					// 余额支付
-					this.$message({
-						message: this.$t('common.successfully'),
-						type: 'success'
-					})
-					this.submitButtonStat = false
-					this.$router.push({path: `/shop/order-list`})
-				} else {
-					// PayStack支付
-					this.submitButtonStat = false
-					this.payForm.orderSn = response.data.SN
-					this.payForm.amount = response.data.ORDER_AMOUNT
-					this.payForm.metadata.custom_fields[0].value = response.data.SN
-					this.visible = true
-				}
-			}).catch(err => {
-				this.$message({
-					message: err,
-					type: 'error'
-				})
-				this.submitButtonStat = false
-			})
-		},
-		// 已选择商品
-		selectProduct() {
-			this.payAmount = 0
-			this.form.goodsId = []
-			this.form.goodsNum = []
-			this.multipleSelection.map((item) => {
-				this.form.goodsId.push(item.ID)
-				this.form.goodsNum.push(item.goodsNum)
-				this.payAmount += item.goodsNum * item.SELL_PRICE
-			})
-		},
-		// 等级变更
-		handleChangeLevel(data) {
-			let { value, diffPv } = data
-			this.needDiffPv = diffPv
-			this.toLevel = value
-		},
+      const params = {
+        decUserName: this.decUserName,
+        packageId: this.form.packageId,
+        goodsId: this.form.goodsId,
+        goodsNum: this.form.goodsNum,
+        location: this.form.location,
+        decWay: this.decWay,
+        decLv: this.toLevel,
+        insertUserName: this.form.insertUserName,
+        remark: this.form.remark,
+        address: this.form.address,
+        consignee: this.form.consignee,
+        acceptMobile: this.form.acceptMobile,
+        province: this.form.areaSelected[0] ? this.form.areaSelected[0] : '',
+        lgaName: this.form.lgaName,
+        cityName: this.form.cityName,
+        nowPerf: this.nowPerf,
+        nextPerf: this.nextPerf,
+        payType: this.form.payType
+      }
+      fetchSendUpgrade(params).then(response => {
+        if (this.form.payType !== 'pay_stack') {
+          // 余额支付
+          this.$message({
+            message: this.$t('common.successfully'),
+            type: 'success'
+          })
+          this.submitButtonStat = false
+          this.$router.push({ path: `/shop/member-order` })
+        } else {
+          // PayStack支付
+          this.submitButtonStat = false
+          this.payForm.orderSn = response.data.SN
+          this.payForm.amount = response.data.ORDER_AMOUNT
+          this.payForm.metadata.custom_fields[0].value = response.data.SN
+          this.visible = true
+        }
+      }).catch(err => {
+        this.$message({
+          message: err,
+          type: 'error'
+        })
+        this.submitButtonStat = false
+      })
+    },
+    // 已选择商品
+    selectProduct() {
+      this.payAmount = 0
+      this.form.goodsId = []
+      this.form.goodsNum = []
+      this.multipleSelection.map((item) => {
+        this.form.goodsId.push(item.ID)
+        this.form.goodsNum.push(item.goodsNum)
+        this.payAmount += item.goodsNum * item.SELL_PRICE
+      })
+    },
+    // 等级变更
+    handleChangeLevel(data) {
+      const { value, diffPv } = data
+      this.needDiffPv = diffPv
+      this.toLevel = value
+    }
   }
 }
 </script>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 838 - 747
src/views/user/welcome-pack.vue


+ 146 - 133
vue.config.js

@@ -1,133 +1,146 @@
-'use strict'
-const path = require('path')
-const defaultSettings = require('./src/settings.js')
-
-function resolve(dir) {
-  return path.join(__dirname, dir)
-}
-
-const name = defaultSettings.title || 'Member Management System' // page title
-
-// If your port is set to 80,
-// use administrator privileges to execute the command line.
-// For example, Mac: sudo npm run
-// You can change the port by the following method:
-// port = 9527 npm run dev OR npm run dev --port = 9527
-const port = process.env.port || process.env.npm_config_port || 9527 // dev port
-
-// All configuration item explanations can be find in https://cli.vuejs.org/config/
-module.exports = {
-  /**
-   * You will need to set publicPath if you plan to deploy your site under a sub path,
-   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
-   * then publicPath should be set to "/bar/".
-   * In most cases please use '/' !!!
-   * Detail: https://cli.vuejs.org/config/#publicpath
-   */
-  publicPath: '/',
-  outputDir: 'dist',
-  assetsDir: 'static',
-  lintOnSave: process.env.NODE_ENV === 'development',
-  productionSourceMap: false,
-  devServer: {
-    port: port,
-    open: true,
-    overlay: {
-      warnings: false,
-      errors: true
-    },
-    proxy: {
-      [process.env.VUE_APP_BASE_API]:{
-        target:"http://local.ng.frontend.api.com",
-        changeOrigin:true,
-        pathRewrite:{
-          ["^" + process.env.VUE_APP_BASE_API] : ""
-        }
-      }
-    }
-    /*before: require('./mock/mock-server.js')*/
-  },
-  configureWebpack: {
-    // provide the app's title in webpack's name field, so that
-    // it can be accessed in index.html to inject the correct title.
-    name: name,
-    resolve: {
-      alias: {
-        '@': resolve('src')
-      }
-    }
-  },
-  chainWebpack(config) {
-    // it can improve the speed of the first screen, it is recommended to turn on preload
-    // it can improve the speed of the first screen, it is recommended to turn on preload
-    config.plugin('preload').tap(() => [
-      {
-        rel: 'preload',
-        // to ignore runtime.js
-        // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
-        fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
-        include: 'initial'
-      }
-    ])
-
-    // when there are many pages, it will cause too many meaningless requests
-    config.plugins.delete('prefetch')
-
-    // set svg-sprite-loader
-    config.module
-      .rule('svg')
-      .exclude.add(resolve('src/icons'))
-      .end()
-    config.module
-      .rule('icons')
-      .test(/\.svg$/)
-      .include.add(resolve('src/icons'))
-      .end()
-      .use('svg-sprite-loader')
-      .loader('svg-sprite-loader')
-      .options({
-        symbolId: 'icon-[name]'
-      })
-      .end()
-
-    config
-      .when(process.env.NODE_ENV !== 'development',
-        config => {
-          config
-            .plugin('ScriptExtHtmlWebpackPlugin')
-            .after('html')
-            .use('script-ext-html-webpack-plugin', [{
-            // `runtime` must same as runtimeChunk name. default is `runtime`
-              inline: /runtime\..*\.js$/
-            }])
-            .end()
-          config
-            .optimization.splitChunks({
-              chunks: 'all',
-              cacheGroups: {
-                libs: {
-                  name: 'chunk-libs',
-                  test: /[\\/]node_modules[\\/]/,
-                  priority: 10,
-                  chunks: 'initial' // only package third parties that are initially dependent
-                },
-                elementUI: {
-                  name: 'chunk-elementUI', // split elementUI into a single package
-                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
-                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
-                },
-                commons: {
-                  name: 'chunk-commons',
-                  test: resolve('src/components'), // can customize your rules
-                  minChunks: 3, //  minimum common number
-                  priority: 5,
-                  reuseExistingChunk: true
-                }
-              }
-            })
-          // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
-          config.optimization.runtimeChunk('single')
-        }
-      )
-  }
-}
+'use strict'
+const path = require('path')
+const defaultSettings = require('./src/settings.js')
+const { WebUpdateNotificationPlugin } = require('@plugin-web-update-notification/webpack')
+
+function resolve(dir) {
+  return path.join(__dirname, dir)
+}
+
+const name = defaultSettings.title || 'Member Management System' // page title
+
+// If your port is set to 80,
+// use administrator privileges to execute the command line.
+// For example, Mac: sudo npm run
+// You can change the port by the following method:
+// port = 9527 npm run dev OR npm run dev --port = 9527
+const port = process.env.port || process.env.npm_config_port || 9526 // dev port
+
+// All configuration item explanations can be find in https://cli.vuejs.org/config/
+module.exports = {
+  /**
+   * You will need to set publicPath if you plan to deploy your site under a sub path,
+   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
+   * then publicPath should be set to "/bar/".
+   * In most cases please use '/' !!!
+   * Detail: https://cli.vuejs.org/config/#publicpath
+   */
+  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
+  outputDir: 'dist',
+  assetsDir: 'static',
+  lintOnSave: process.env.NODE_ENV === 'development',
+  productionSourceMap: false,
+  devServer: {
+    port: port,
+    open: true,
+    overlay: {
+      warnings: false,
+      errors: true
+    },
+    proxy: {
+      [process.env.VUE_APP_BASE_API]: {
+        target: 'http://16.163.228.151:8018',
+        changeOrigin: true,
+        pathRewrite: {
+          [ '^' + process.env.VUE_APP_BASE_API ]: ''
+        }
+      }
+    }
+    /* before: require('./mock/mock-server.js') */
+  },
+  configureWebpack: {
+    // provide the app's title in webpack's name field, so that
+    // it can be accessed in index.html to inject the correct title.
+    name: name,
+    resolve: {
+      alias: {
+        '@': resolve('src')
+      }
+    },
+    plugins: [
+      new WebUpdateNotificationPlugin({
+        logVersion: true,
+        hiddenDefaultNotification: true
+        // notificationProps: {
+        //   title: lang === 'en' ? '📢 System update' : '📢 系统更新',
+        //   description: lang === 'en' ? 'System update, please refresh the page' : '系统更新,请刷新页面',
+        //   buttonText: lang === 'en' ? 'refresh' : '刷新',
+        //   dismissButtonText: lang === 'en' ? 'dismiss' : '忽略'
+        // }
+      })
+    ]
+  },
+  chainWebpack(config) {
+    // it can improve the speed of the first screen, it is recommended to turn on preload
+    // it can improve the speed of the first screen, it is recommended to turn on preload
+    config.plugin('preload').tap(() => [
+      {
+        rel: 'preload',
+        // to ignore runtime.js
+        // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
+        fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
+        include: 'initial'
+      }
+    ])
+
+    // when there are many pages, it will cause too many meaningless requests
+    config.plugins.delete('prefetch')
+
+    // set svg-sprite-loader
+    config.module
+      .rule('svg')
+      .exclude.add(resolve('src/icons'))
+      .end()
+    config.module
+      .rule('icons')
+      .test(/\.svg$/)
+      .include.add(resolve('src/icons'))
+      .end()
+      .use('svg-sprite-loader')
+      .loader('svg-sprite-loader')
+      .options({
+        symbolId: 'icon-[name]'
+      })
+      .end()
+
+    config
+      .when(process.env.NODE_ENV !== 'development',
+        config => {
+          config
+            .plugin('ScriptExtHtmlWebpackPlugin')
+            .after('html')
+            .use('script-ext-html-webpack-plugin', [{
+            // `runtime` must same as runtimeChunk name. default is `runtime`
+              inline: /runtime\..*\.js$/
+            }])
+            .end()
+          config
+            .optimization.splitChunks({
+              chunks: 'all',
+              cacheGroups: {
+                libs: {
+                  name: 'chunk-libs',
+                  test: /[\\/]node_modules[\\/]/,
+                  priority: 10,
+                  chunks: 'initial' // only package third parties that are initially dependent
+                },
+                elementUI: {
+                  name: 'chunk-elementUI', // split elementUI into a single package
+                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
+                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
+                },
+                commons: {
+                  name: 'chunk-commons',
+                  test: resolve('src/components'), // can customize your rules
+                  minChunks: 3, //  minimum common number
+                  priority: 5,
+                  reuseExistingChunk: true
+                }
+              }
+            })
+          // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
+          config.optimization.runtimeChunk('single')
+        }
+      )
+  }
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů