Bladeren bron

merge master

david 2 jaren geleden
bovenliggende
commit
3f3618f3f3
44 gewijzigde bestanden met toevoegingen van 4615 en 212 verwijderingen
  1. 2 0
      .env.development
  2. 4 2
      .env.production
  3. 2 0
      .env.staging
  4. 3 0
      .gitignore
  5. 2 0
      package.json
  6. 143 0
      src/api/bonus.js
  7. 9 0
      src/api/file.js
  8. 348 0
      src/api/member.js
  9. 2 2
      src/components/FilterUser.vue
  10. 4 4
      src/components/Tinymce/components/EditorImage.vue
  11. 2 1
      src/components/Tinymce/index.vue
  12. 160 2
      src/lang/en.js
  13. 154 2
      src/lang/zh.js
  14. 5 0
      src/layout/index.vue
  15. 70 0
      src/router/index.js
  16. 25 2
      src/router/modules/member.js
  17. 23 0
      src/utils/importScript.js
  18. 115 0
      src/utils/region.js
  19. 10 12
      src/views/ad/edit.vue
  20. 13 13
      src/views/ad/list.vue
  21. 3 3
      src/views/article/category.vue
  22. 13 12
      src/views/article/edit.vue
  23. 36 35
      src/views/article/index.vue
  24. 262 0
      src/views/bonus/balance-list.vue
  25. 123 0
      src/views/bonus/flow-bonus.vue
  26. 178 0
      src/views/bonus/other-period-bonus.vue
  27. 150 0
      src/views/bonus/perf-adjustment.vue
  28. 143 0
      src/views/bonus/perf-month.vue
  29. 150 0
      src/views/bonus/perf-order.vue
  30. 143 0
      src/views/bonus/perf-period-list.vue
  31. 141 0
      src/views/bonus/user-perf.vue
  32. 2 2
      src/views/config/dec-level-config.vue
  33. 0 1
      src/views/dashboard/admin/index.vue
  34. 301 0
      src/views/file/export.vue
  35. 0 1
      src/views/log/admin-handle.vue
  36. 0 1
      src/views/log/admin-login.vue
  37. 0 1
      src/views/log/system.vue
  38. 0 1
      src/views/log/user-handle.vue
  39. 8 8
      src/views/log/user-login.vue
  40. 222 0
      src/views/user/dec-level-list.vue
  41. 299 0
      src/views/user/empty-order-operation.vue
  42. 552 107
      src/views/user/member-list.vue
  43. 656 0
      src/views/user/member-network-move.vue
  44. 137 0
      src/views/user/modify-stockist-level.vue

+ 2 - 0
.env.development

@@ -9,6 +9,8 @@ VUE_APP_BASE_DO_API='http://local.ng.backend.api.com'
 VUE_APP_CDN_API='http://172.19.124.45:9970'
 # 页面地址
 VUE_APP_BASE_WEBSITE='http://local.ng.backend.ele.com'
+# 会员端地址
+VUE_APP_FRONTEND_WEBSITE='http://local.ng.frontend.ele.com'
 # PayStack
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
 # 请求token前缀

+ 4 - 2
.env.production

@@ -7,8 +7,10 @@ VUE_APP_BASE_API=''
 VUE_APP_BASE_DO_API='https://ng-frontend-api.elken.com'
 # CDN文件地址
 VUE_APP_CDN_API='http://ng-upload.elken.com'
-# 页面地址
-VUE_APP_BASE_WEBSITE='https://ngds.elken.com'
+# 结算页面地址
+VUE_APP_BASE_WEBSITE='https://ngmanager.elken.com'
+# 会员页面地址
+VUE_APP_FRONTEND_WEBSITE='https://ngds.elken.com'
 # PayStack支付key
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_live_fae524f9d073d877beeb661fd825a37a9bc91f0a'
 # 请求token前缀

+ 2 - 0
.env.staging

@@ -11,6 +11,8 @@ VUE_APP_BASE_DO_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_FRONTEND_WEBSITE='http://16.163.228.151:8037'
 # PayStack支付key
 VUE_APP_BASE_PAY_STACK_PUBLIC_KEY='pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55'
 # 请求token前缀

+ 3 - 0
.gitignore

@@ -21,3 +21,6 @@ selenium-debug.log
 
 package-lock.json
 yarn.lock
+
+.env.development
+vue.config.js

+ 2 - 0
package.json

@@ -39,6 +39,8 @@
     "script-loader": "0.7.2",
     "sortablejs": "1.8.4",
     "squire-rte": "^2.0.2",
+    "tinymce": "^6.4.1",
+    "tinymce-vue": "^1.0.0",
     "to-mark": "^1.1.9",
     "tui-code-snippet": "^2.3.3",
     "vue": "^2.6.10",

+ 143 - 0
src/api/bonus.js

@@ -0,0 +1,143 @@
+import request from '@/utils/request'
+
+export function fetchGetUserStatus() {
+  return request({
+    url: '/v1/user/status-audit-get-statuses',
+    method: 'get'
+  })
+}
+
+export function fetchBalanceList(query) {
+  return request({
+    url: '/v1/bonus/balance-list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchBalanceExport(query) {
+  return request({
+    url: '/v1/bonus/balance-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchOtherPeriodBonusFilterTypes(query) {
+  return request({
+    url: '/v1/bonus/other-period-bonus-filter-types',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchOtherPeriodBonus(query) {
+  return request({
+    url: '/v1/bonus/other-period-bonus',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchOtherPeriodBonusExport(query) {
+  return request({
+    url: '/v1/bonus/other-period-bonus-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchFlowBonus(query) {
+  return request({
+    url: '/v1/bonus/flow-bonus',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchFlowBonusExport(query) {
+  return request({
+    url: '/v1/bonus/flow-bonus-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchUserPerf(query) {
+  return request({
+    url: '/v1/bonus/user-perf',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchUserPerfExport(query) {
+  return request({
+    url: '/v1/bonus/user-perf-export',
+    method: 'get',
+    params: query
+  })
+}
+export function fetchPerfOrder(query) {
+  return request({
+    url: '/v1/bonus/perf-order',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfOrderExport(query) {
+  return request({
+    url: '/v1/bonus/perf-order-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfPeriodList(query) {
+  return request({
+    url: '/v1/bonus/perf-period-list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfPeriodListExport(query) {
+  return request({
+    url: '/v1/bonus/perf-period-list-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfMonth(query) {
+  return request({
+    url: '/v1/bonus/perf-month',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfMonthExport(query) {
+  return request({
+    url: '/v1/bonus/perf-month-export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfAdjustment(query) {
+  return request({
+    url: '/v1/bonus/perf-adjustment',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchPerfAdjustmentPost(data) {
+  return request({
+    url: '/v1/bonus/perf-adjustment',
+    method: 'post',
+    data
+  })
+}

+ 9 - 0
src/api/file.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function fetchExport(query) {
+  return request({
+    url: '/v1/file/export',
+    method: 'get',
+    params: query
+  })
+}

+ 348 - 0
src/api/member.js

@@ -11,3 +11,351 @@ export function fetchMemberList(data) {
     params: data
   })
 }
+
+/**
+ * 会员列表导出
+ * @returns {*}
+ */
+export function fetchMemberExport(data) {
+  return request({
+    url: '/v1/user/index-export',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 会员列表导出
+ * @returns {*}
+ */
+export function fetchProfileGet(data) {
+  return request({
+    url: '/v1/user/profile-get',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateSetAsStockist(data) {
+  return request({
+    url: '/v1/user/is-dec',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 显示报单网络图谱
+ * @param data
+ * @returns {*}
+ */
+export function updateSetChartDisplay(data) {
+  return request({
+    url: '/v1/user/is-atlas',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 显示充值功能
+ * @param data
+ * @returns {*}
+ */
+export function updateSetRechargeDisplay(data) {
+  return request({
+    url: '/v1/user/is-recharge',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateSetActive(data) {
+  return request({
+    url: '/v1/user/modify-status',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateModifyPassword(data) {
+  return request({
+    url: '/v1/user/modify-password',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateModifyProfile(data) {
+  return request({
+    url: '/v1/user/modify-profile',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateSetLock(data) {
+  return request({
+    url: '/v1/user/modify-status',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 设为报单中心
+ * @param data
+ * @returns {*}
+ */
+export function updateSetModifyPassword(data) {
+  return request({
+    url: '/v1/user/is-modify-password-status',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 查询会员信息
+ * @returns {*}
+ */
+export function fetchMemberFullInfo(data) {
+  return request({
+    url: '/v1/user/full-info',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 查询会员信息
+ * @returns {*}
+ */
+export function fetchCloseLoginGet() {
+  return request({
+    url: '/v1/user/close-login-get',
+    method: 'get',
+  })
+}
+
+/**
+ * 查询会员信息
+ * @returns {*}
+ */
+export function fetchCloseDecGet() {
+  return request({
+    url: '/v1/user/close-dec-get',
+    method: 'get',
+  })
+}
+
+/**
+ * 查询会员信息
+ * @returns {*}
+ */
+export function fetchCloseDec() {
+  return request({
+    url: '/v1/user/close-dec',
+    method: 'get',
+  })
+}
+
+/**
+ * 修改报单中心级别
+ * @param data
+ * @returns {*}
+ */
+export function updateUserStockistLevel(data) {
+  return request({
+    url: '/v1/user/change-user-dec-role',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 查询会员等级调整信息
+ * @returns {*}
+ */
+export function fetchEntryLevelList(data) {
+  return request({
+    url: '/v1/user/dec-level-list',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 修改会员报单级别
+ * @param data
+ * @returns {*}
+ */
+export function updateUserEntryLevel(data) {
+  return request({
+    url: '/v1/user/change-user-dec-level',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 查询移网类型
+ * @returns {*}
+ */
+export function fetchNetworkType(data) {
+  return request({
+    url: '/v1/user/move-net-type',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 查询移网数据
+ * @returns {*}
+ */
+export function fetchNetworkMoveList(data) {
+  return request({
+    url: '/v1/user/move',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 移网导出
+ * @returns {*}
+ */
+export function fetchNetworkMoveExport(data) {
+  return request({
+    url: '/v1/user/move-export',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 移网审核通过
+ * @param data
+ * @returns {*}
+ */
+export function updateNetworkMovePass(data) {
+  return request({
+    url: '/v1/user/move-pass',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 移网信息
+ * @returns {*}
+ */
+export function fetchNetworkMoveGet(data) {
+  return request({
+    url: '/v1/user/move-get',
+    method: 'get',
+    params: data
+  })
+}
+
+/**
+ * 移网审核编辑
+ * @param data
+ * @returns {*}
+ */
+export function updateNetworkMoveEdit(data) {
+  return request({
+    url: '/v1/user/move-edit',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 移网审核
+ * @param data
+ * @returns {*}
+ */
+export function updateNetworkMoveAudit(data) {
+  return request({
+    url: '/v1/user/move-audit',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 移网删除
+ * @param data
+ * @returns {*}
+ */
+export function updateNetworkMoveDelete(data) {
+  return request({
+    url: '/v1/user/move-delete',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 发起移网
+ * @param data
+ * @returns {*}
+ */
+export function updateNetworkMoveApply(data) {
+  return request({
+    url: '/v1/user/move-add',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 空单操作查询
+ * @returns {*}
+ */
+export function fetchUserAdd() {
+  return request({
+    url: '/v1/user/user-add',
+    method: 'get',
+  })
+}
+
+/**
+ * 空单添加会员
+ * @param data
+ * @returns {*}
+ */
+export function updateUserAdd(data) {
+  return request({
+    url: '/v1/user/user-add',
+    method: 'post',
+    data
+  })
+}

+ 2 - 2
src/components/FilterUser.vue

@@ -82,9 +82,9 @@
         <el-option v-for="(item,key) in filterRelations" :key="key" :label="item" :value="key" />
       </el-select>
       <el-button class="filter-item" icon="el-icon-plus" @click="handleOptionPlus" />
-      <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilterUser">{{ filterBtnName }}</el-button>
+      <el-button class="filter-item" type="primary" @click="handleFilterUser">{{ filterBtnName }}</el-button>
       <el-button class="filter-item" type="" @click="handleFilterClear">{{ $t('common.reset') }}</el-button>
-      <!-- <el-button class="down-button" type="text"><i class="el-icon-arrow-down" /></el-button> -->
+<!--      <el-button class="down-button" type="text"><i class="el-icon-arrow-down" /></el-button>-->
     </div>
     <div v-show="filterSelected.length > 0" class="filter-selected">
       <el-tag

+ 4 - 4
src/components/Tinymce/components/EditorImage.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="upload-container">
     <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
-      upload
+      {{$t('article.upload')}}
     </el-button>
     <el-dialog :visible.sync="dialogVisible">
       <el-upload
@@ -18,14 +18,14 @@
         :headers="uploaderHeaders"
       >
         <el-button size="small" type="primary">
-          Click upload
+          {{$t('article.clickUpload')}}
         </el-button>
       </el-upload>
       <el-button @click="dialogVisible = false">
-        Cancel
+        {{$t('article.cancel')}}
       </el-button>
       <el-button type="primary" @click="handleSubmit">
-        Confirm
+        {{$t('article.confirm')}}
       </el-button>
     </el-dialog>
   </div>

+ 2 - 1
src/components/Tinymce/index.vue

@@ -19,6 +19,8 @@ import load from './dynamicLoadScript'
 
 // why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
 const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
+//const tinymceCDN = 'http://lib.baomitu.com/tinymce/4.9.3/tinymce.min.js'
+
 
 export default {
   name: 'Tinymce',
@@ -117,7 +119,6 @@ export default {
   },
   methods: {
     init() {
-      console.log(this.uploaderRequestUrl)
       // dynamic load tinymce from cdn
       load(tinymceCDN, (err) => {
         if (err) {

+ 160 - 2
src/lang/en.js

@@ -110,6 +110,48 @@ export default {
     hide: 'Hide',
     unhide: 'Unhide'
   },
+  article: {
+    clickUpload: 'Click Upload',
+    confirm: 'Confirm',
+    cancel: 'Cancel',
+    upload: 'Upload',
+    id: 'ID',
+    title: 'Title',
+    category: 'Category',
+    sort: 'Sort',
+    creationTime: 'Creation Time',
+    status: 'Status',
+    action: 'Action',
+    newArticle: 'New article',
+    content: 'Content',
+    order: 'Order',
+    show: 'Show',
+    categoryName: 'Category Name'
+  },
+  file: {
+    exportName: 'Export Name',
+    route: 'Route',
+    download: 'Download',
+    operationAdministrator: 'Operation Administrator',
+    exportProgress: 'Export Progress',
+    exportStart: 'Export Start',
+    exportComplete: 'Export Complete',
+    createTime: 'Create time',
+    exportStartTime: 'Export Start Time',
+    exportEndTime: 'Export End Time',
+    creationTime: 'Creation Time',
+    all: 'All'
+  },
+  bonus: {
+    welcomePackOrder: 'Welcome Pack Order',
+    memberCode: 'Member Code',
+    balancePerformance: 'Balance Performance',
+    entryBalancePerformance:'Entry Balance Performance',
+    reconditioningBalancePerformance: 'Reconditioning Balance Performance',
+    LMarketBalancePerformance: 'L. Market Balance Performance',
+    RMarketBalancePerformance: 'R. Market Balance Performance',
+    confirmAndReviseMemberPerformance: 'Confirm and revise member performance?'
+  },
   documentation: {
     documentation: 'Documentation',
     github: 'Github Repository'
@@ -246,10 +288,19 @@ export default {
     desc: '描述',
     upload: 'Upload',
     modifyData:'Modifying data',
+    hide: 'Hide',
+    unhide: 'Unhide',
+    selectData: 'Select Data',
+    deleteSelectedData: 'Are you sure to delete the selected data?',
+    notice: 'Notice',
+    hideSelectedData: 'Are you sure to hide the selected data?',
+    unHideSelectedData: 'Are you sure to un-hide the selected data?',
+    exportCurrentData: 'Are you sure you want to export the current data?',
+    all: 'All'
   },
 
   filter: {
-    memberSelect: '会员筛选',
+    memberSelect: 'Select',
     memberNumber: '会员编号',
     name: '姓名',
     idNumber: '证件号码',
@@ -350,8 +401,115 @@ export default {
   },
 
   // 会员
-  user: {
+  member: {
+    memberCode: 'Member Code',
+    memberName: 'Member Name',
+    currentLevel: 'Current Level',
+    stockistLevel: 'Stockist Level',
+    entryLevel: 'Entry Level',
+    pleaseSelectStockistLevel: 'Please Select The Stockist Level',
+    remark: 'Remark',
+    modifyEntryLevelHits: 'Do you want to modify the current member entry level?',
+    modifyMemberLevel: 'Modify member level',
+    selectEntryLevelHint: 'Please Select The Entry Level',
+    modifyMemberEntryLevelHits: 'Do you want to modify the current member level?',
+    all: 'All',
+    reviewed: 'To be reviewed',
+    approved: 'Approved',
+    rejected: 'Rejected',
+    selectedData: 'Selected data',
+    deleteData: 'Delete data',
+    batchesDelete: 'Delete in batches',
+    applyNetworkMove: 'New network transfer application',
+    exportExcel: 'Export Excel',
+    exportExcelHint: 'Are you sure you want to export the current data?',
+    passingAudit: 'Passing Audit',
+    modifyingData: 'Modifying data',
+    selectedNonData: 'Please select the record to operate',
+    passAuditNote: 'Are you sure you want to pass the audit? note:',
+    rejectAuditNote: 'Are you sure you want to reject the approval? note:',
+    operationInProcess: 'Operation in progress, please wait',
+    deleteHint: 'Are you sure to delete the selected data?',
+    applyNetworkTransfer: 'Apply for moving network',
+    modifyNetworkTransfer: 'Modify network transfer information',
+    reviewNetworkTransfer: 'Review network transfer information',
+    networkTransferType: 'Network transfer type',
+    selectNetworkTransferType: 'Please select a network transfer type',
+    mobileMemberCode: 'Mobile member code',
+    mobileMemberName: 'Mobile member name',
+    originalSuperiorNo: 'Original superior No',
+    originalSuperiorName: 'Original superior name',
+    moveToPlacementMemberCode: 'Move to placement member code',
+    moveToPlacementMemberName: 'Move to placement member name',
+    originalDeveloperNo: 'Original developer No',
+    nameOfOriginalDeveloper: 'Name of original developer',
+    moveToSponsorMemberCode: 'Move to sponsor member code',
+    moveToSponsorMemberName: 'Move to sponsor member name',
+    moveToLocation: 'Move to location',
+    oneMarket: 'I. Market',
+    twoMarket: 'II. Market',
+    adopted: 'Adopted',
+    stockistOrNot: 'Stockist or not',
+    accountInformation: 'Account Information',
+    networkInformation: 'Network Information',
+    otherInformation: 'Other Information',
+    bankInformation: 'Bank Information',
+    stockistNo: 'Stockist No',
+    autoDetectMember: 'After entering the number, click the blank space to detect the member name of the number',
+    contactPerson: 'Contact Person',
+    resettlementLocation: 'Resettlement Location',
+    left: 'Left',
+    right: 'Right',
+    sponsor: 'Sponsor',
+    personalData: 'Personal Data',
+    phoneNumber: 'Phone Number',
+    bankName: 'Bank Name',
+    selectBankDeposit: 'Please select the Bank of deposit',
+    subBankName: 'Account opening sub branch',
+    bankAccount: 'Bank Account',
+    bankRegion: 'Bank Region',
+    addManually: 'Add manually',
+    quickLogon: 'Quick Logon',
+    changePassword: 'Change Password',
+    modifyPersonalData: 'Modify personal data',
+    statusActivation: 'Status Activation',
+    statusLock: 'Status Lock',
+    openPasswordModification: 'Open password modification',
+    turnOffPasswordModification: 'Turn off password modification',
+    stockistManagement: 'Stockist Management',
+    setAsStockist: 'Set as Stockist',
+    cancelStockist: 'Cancel Stockist',
+    chartManagement: 'Chart Management',
+    displayChart: 'Display Chart',
+    hiddenChart: 'Hidden Chart',
+    rechargeManagement: 'Recharge Management',
+    displayRecharge: 'Display Recharge',
+    hideRecharge: 'Display Recharge',
+    type: 'Type',
+    selectType: 'Please select a type',
+    password: 'Password',
+    identityNo: 'Identity No.',
+    selectBankName: 'Please select a bank name',
+    bankAddress: 'Bank Address',
+
+    loginManagement: 'Login Management',
+    entryManage: 'Manage entry',
+    loginPassword: 'Login Password',
+    paymentPassword: 'Payment Password',
+    selectMemberData: 'Please check the member to be operated',
+    sureWant: 'Are you sure you want to',
+    byDesignatedMember: 'By designated member',
+    expandNetworkBy: 'Expand network by',
+    byPlacementNetwork: 'By placement network',
+    byMembershipSystem: 'By membership system',
+    byProvinceAndRegion: 'By province and region',
+    exportDataHint: 'Are you sure you want to export the current data?',
+  },
 
+  // 网络
+  network: {
+    placementNetwork: 'Placement Network',
+    sponsorNetwork: 'Sponsor Network',
   },
 
   // 配置

+ 154 - 2
src/lang/zh.js

@@ -109,6 +109,48 @@ export default {
     hide: '展示',
     unhide: '不展示'
   },
+  article: {
+    clickUpload: '点击上传',
+    confirm: '确定',
+    cancel: '取消',
+    upload: '上传',
+    id: '序号',
+    title: '标题',
+    category: '分类',
+    sort: '排序',
+    creationTime: '创建时间',
+    status: '状态',
+    action: '操作',
+    newArticle: '新增文章',
+    content: '内容',
+    order: '排序',
+    show: '展示',
+    categoryName: '分类名称'
+  },
+  file: {
+    exportName: '导出名称',
+    route: '路径',
+    download: '下载',
+    operationAdministrator: '操作管理员',
+    exportProgress: '导出进度',
+    exportStart: '导出开始',
+    exportComplete: '导出完成',
+    createTime: '创建时间',
+    exportStartTime: '导出开始时间',
+    exportEndTime: '导出结束时间',
+    creationTime: '创建时间',
+    all: '全部'
+  },
+  bonus: {
+    welcomePackOrder: '首购单',
+    memberCode:'会员编号',
+    balancePerformance: '综合结余业绩',
+    entryBalancePerformance: '首单结余业绩',
+    reconditioningBalancePerformance: '复消结余业绩',
+    LMarketBalancePerformance: '一市场结余业绩',
+    RMarketBalancePerformance: '二市场结余业绩',
+    confirmAndReviseMemberPerformance: '确认修改会员业绩?'
+  },
   documentation: {
     documentation: '文档',
     github: 'Github 地址'
@@ -246,10 +288,20 @@ export default {
     exportPDF:'导出PDF',
     upload: '上传',
     modifyData:'正在修改数据',
+    upload: '上传',
+    hide: '展示',
+    unhide: '不展示',
+    selectData: '所选数据',
+    deleteSelectedData: '您确定要删除所选数据吗?',
+    notice: '提示',
+    hideSelectedData: '您确定要隐藏所选数据吗?',
+    unHideSelectedData: '您确定要展示所选数据吗?',
+    exportCurrentData: '您确定要导出当前数据吗?',
+    all: '全部'
   },
 
   filter: {
-    memberSelect: '会员筛选',
+    memberSelect: '筛选',
     memberNumber: '会员编号',
     name: '姓名',
     idNumber: '证件号码',
@@ -351,8 +403,108 @@ export default {
   },
 
   // 会员
-  user: {
+  member: {
+    memberCode: '会员编号',
+    memberName: '会员名字',
+    currentLevel: '当前级别',
+    stockistLevel: '报单中心级别',
+    entryLevel: '报单级别',
+    pleaseSelectStockistLevel: '请选择报单中心级别',
+    remark: '备注',
+    modifyEntryLevelHits: '是否要修改当前会员报单级别?',
+    modifyMemberLevel: '修改会员级别',
+    selectEntryLevelHint: '请选择报单级别',
+    modifyMemberEntryLevelHits: '是否要修改当前会员级别',
+    all: '全部',
+    reviewed: '待审核',
+    approved: '审核通过',
+    rejected: '审核拒绝',
+    selectedData: '所选数据',
+    batchesDelete: '批量删除',
+    applyNetworkMove: '新建移网申请',
+    exportExcel: '表格导出',
+    exportExcelHint: '确定导出选中的数据?',
+    passingAudit: '审核中',
+    modifyingData: '正在修改数据',
+    selectedNonData: '请选择要操作的记录',
+    passAuditNote: '确定要通过审核?备注:',
+    rejectAuditNote: '确定要拒绝审核?备注:',
+    operationInProcess: '正在操作,请稍后',
+    deleteHint: '确定删除选定的数据',
+    applyNetworkTransfer: '发起移网信息',
+    modifyNetworkTransfer: '修改移网信息',
+    reviewNetworkTransfer: '审核移网信息',
+    networkTransferType: '移网类型',
+    selectNetworkTransferType: '请选择移网类型',
+    mobileMemberCode: '移动会员编号',
+    mobileMemberName: '移动会员姓名',
+    originalSuperiorNo: '原上级编号',
+    originalSuperiorName: '原上级姓名',
+    moveToPlacementMemberCode: '移动到节点会员编号',
+    moveToPlacementMemberName: '移动到节点会员姓名',
+    originalDeveloperNo: '原开拓人编号',
+    nameOfOriginalDeveloper: '原开拓人姓名',
+    moveToSponsorMemberCode: '移动到开拓会员编号',
+    moveToSponsorMemberName: '移动到开拓会员姓名',
+    moveToLocation: '移动到区位',
+    oneMarket: '一市场',
+    twoMarket: '二市场',
+    adopted: '通过',
+    stockistOrNot: '是否报单中心',
+    accountInformation: '账号信息',
+    networkInformation: '网络信息',
+    otherInformation: '其他信息',
+    bankInformation: '银行信息',
+    stockistNo: '报单中心编号',
+    autoDetectMember: '输入编号后点击空白处,可检测该编号的会员姓名',
+    contactPerson: '接点人',
+    resettlementLocation: '安置区位',
+    left: '左区',
+    right: '中区',
+    sponsor: '开拓人',
+    personalData: '个人资料',
+    phoneNumber: '手机号',
+    bankName: '开户行',
+    selectBankDeposit: '请选择开户行',
+    subBankName: '开户支行',
+    bankAccount: '银行账号',
+    bankRegion: '银行所在地区',
+    addManually: '手动添加',
+    quickLogon: '快速登录',
+    changePassword: '修改密码',
+    modifyPersonalData: '修改个人资料',
+    statusActivation: '状态激活',
+    statusLock: '状态锁定',
+    openPasswordModification: '开启密码修改',
+    turnOffPasswordModification: '关闭密码修改',
+    stockistManagement: '报单中心管理',
+    setAsStockist: '设为报单中心',
+    cancelStockist: '取消报单中心',
+    chartManagement: '图谱管理',
+    displayChart: '显示图谱',
+    hiddenChart: '隐藏图谱',
+    rechargeManagement: '充值管理',
+    displayRecharge: '显示充值',
+    hideRecharge: '隐藏充值',
+    type: '类型',
+    selectType: '请选择类型',
+    password: '密码',
+    identityNo: '身份证号',
+    selectBankName: '请选择银行',
+    bankAddress: '银行地址',
+    loginManagement: '登录管理',
+    entryManage: '管理报单',
+    loginPassword: '登录密码',
+    paymentPassword: '支付密码',
+    selectMemberData: '请勾选要操作的会员',
+    sureWant: '确定要对所选会员',
+    exportDataHint: '确定要导出所选数据?',
+  },
 
+  // 网络
+  network: {
+    placementNetwork: '安置网络',
+    sponsorNetwork: '推荐网路',
   },
 
   // 配置

+ 5 - 0
src/layout/index.vue

@@ -20,9 +20,14 @@ import RightPanel from '@/components/RightPanel'
 import { AppMain, Navbar, Settings, Sidebar, TagsView } 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,

+ 70 - 0
src/router/index.js

@@ -392,6 +392,76 @@ export const asyncRoutes = [
       }
     ]
   },
+  {
+    path: '/file',
+    component: Layout,
+    redirect: '/file/export',
+    hidden: true,
+    children: [
+      {
+        path: 'export',
+        component: () => import('@/views/file/export'),
+        name: 'export',
+        meta: { title: 'export', noCache: true }
+      }
+    ]
+  },
+  {
+    path: '/bonus',
+    component: Layout,
+    redirect: '/bonus/balance-list',
+    hidden: true,
+    children: [
+      {
+        path: 'balance-list',
+        component: () => import('@/views/bonus/balance-list'),
+        name: 'balance-list',
+        meta: { title: 'balance-list', noCache: true }
+      },
+      {
+        path: 'other-period-bonus',
+        component: () => import('@/views/bonus/other-period-bonus'),
+        name: 'other-period-bonus',
+        meta: { title: 'other-period-bonus', noCache: true }
+      },
+      {
+        path: 'flow-bonus',
+        component: () => import('@/views/bonus/flow-bonus'),
+        name: 'flow-bonus',
+        meta: { title: 'flow-bonus', noCache: true }
+      },
+      {
+        path: 'user-perf',
+        component: () => import('@/views/bonus/user-perf'),
+        name: 'user-perf',
+        meta: { title: 'user-perf', noCache: true }
+      },
+      {
+        path: 'perf-order',
+        component: () => import('@/views/bonus/perf-order'),
+        name: 'perf-order',
+        meta: { title: 'perf-order', noCache: true }
+      },
+      {
+        path: 'perf-period-list',
+        component: () => import('@/views/bonus/perf-period-list'),
+        name: 'perf-period-list',
+        meta: { title: 'perf-period-list', noCache: true }
+      },
+      {
+        path: 'perf-month',
+        component: () => import('@/views/bonus/perf-month'),
+        name: 'perf-month',
+        meta: { title: 'perf-month', noCache: true }
+      },
+      {
+        path: 'perf-adjustment',
+        component: () => import('@/views/bonus/perf-adjustment'),
+        name: 'perf-adjustment',
+        meta: { title: 'perf-adjustment', noCache: true }
+      }
+    ]
+  },
   {
     path: '/tab',
     component: Layout,

+ 25 - 2
src/router/modules/member.js

@@ -17,8 +17,31 @@ const memberRouter = {
       component: () => import('@/views/user/member-list'),
       name: 'memberList',
       meta: { title: 'Member List', icon: 'el-icon-user-solid' }
-    }
-
+    },
+    {
+      path: 'user-add-opt', // 空单操作
+      component: () => import('@/views/user/empty-order-operation'),
+      name: 'emptyOrderOperation',
+      meta: { title: 'Empty Order Operation', icon: 'el-icon-user-solid' }
+    },
+    {
+      path: 'move', // 会员移网
+      component: () => import('@/views/user/member-network-move'),
+      name: 'memberNetworkMove',
+      meta: { title: 'Move Network Management', icon: 'el-icon-user-solid' }
+    },
+    {
+      path: 'dec-level-list', // 会员等级调整
+      component: () => import('@/views/user/dec-level-list'),
+      name: 'decLevelList',
+      meta: { title: 'Member Level Adjustment List', icon: 'el-icon-user-solid' }
+    },
+    {
+      path: 'change-user-dec-role', // 修改报单中心级别
+      component: () => import('@/views/user/modify-stockist-level'),
+      name: 'modifyStockistLevel',
+      meta: { title: 'Modify Stockist Level', icon: 'el-icon-user-solid' }
+    },
   ]
 }
 

+ 23 - 0
src/utils/importScript.js

@@ -0,0 +1,23 @@
+const importScript = function (path, success, error) {
+	let isLoaded = false
+	let scriptElements = document.getElementsByTagName('script')
+	for(let i in scriptElements){
+		if(scriptElements[i].src === path){
+			isLoaded = true
+		}
+	}
+	if(isLoaded === false){
+		let oS = document.createElement('script')
+		oS.src = path
+		document.getElementsByTagName('head')[0].appendChild(oS)
+		oS.onload = function () {
+			success && success()
+		}
+
+		oS.onerror = function () {
+			error && error()
+		}
+	}
+}
+
+export default importScript

+ 115 - 0
src/utils/region.js

@@ -0,0 +1,115 @@
+//ANRAN_REGION_DATA from cdn/jsdata
+// 深拷贝数组
+// let scriptEle = document.createElement('script')
+// scriptEle.setAttribute('src', 'http://upload.ar.wqcms.com/cdn/jsdata/ar_region_data.js?ver=0.1')
+// document.getElementsByTagName('head')[0].appendChild(scriptEle)
+// // document.write("<script language='javascript' src='http://upload.ar.wqcms.com/cdn/jsdata/ar_region_data.js?ver=0.1'></script>");
+// require('http://tool.anran.io/cdn/jsdata/ar_region_data.js')
+import importScript from "@/utils/importScript"
+import regionInfo from "@/store/modules/region";
+
+let regionScriptLoaded = false
+
+const initRegion = function (vueObj) {
+	importScript(process.env.VUE_APP_CDN_API + `/cdn/jsdata/ar_region_data.js?ver=0.1`, () => {
+		if (regionScriptLoaded) return true
+		regionScriptLoaded = true
+		let ANRAN_REGION_DATA = AR_REGION_DATA
+
+		// 汉字转code大对象
+		const rootCode = '234'
+
+		vueObj.$set(regionInfo.regionInfo.CodeToText, '', '全部')
+		// 计算省
+		for (const prop in ANRAN_REGION_DATA[rootCode]) {
+			regionInfo.regionInfo.regionData.push({
+				value: prop,
+				label: ANRAN_REGION_DATA[rootCode][prop]
+			})
+
+			regionInfo.regionInfo.CodeToText[prop] = ANRAN_REGION_DATA[rootCode][prop]
+			regionInfo.regionInfo.TextToCode[ANRAN_REGION_DATA[rootCode][prop]] = {
+				code: prop
+			}
+			regionInfo.regionInfo.TextToCode[ANRAN_REGION_DATA[rootCode][prop]]['全部'] = {
+				code: ''
+			}
+		}
+
+		// 计算市
+		for (let i = 0, len = regionInfo.regionInfo.regionData.length; i < len; i++) {
+			const provinceCode = regionInfo.regionInfo.regionData[i].value
+			const provinceText = regionInfo.regionInfo.regionData[i].label
+			const provinceChildren = []
+			for (const prop in ANRAN_REGION_DATA[provinceCode]) {
+				provinceChildren.push({
+					value: prop,
+					label: ANRAN_REGION_DATA[provinceCode][prop]
+				})
+				regionInfo.regionInfo.CodeToText[prop] = ANRAN_REGION_DATA[provinceCode][prop]
+				regionInfo.regionInfo.TextToCode[provinceText][ANRAN_REGION_DATA[provinceCode][prop]] = {
+					code: prop
+				}
+				regionInfo.regionInfo.TextToCode[provinceText][ANRAN_REGION_DATA[provinceCode][prop]]['全部'] = {
+					code: ''
+				}
+			}
+			if (provinceChildren.length) {
+				regionInfo.regionInfo.regionData[i].children = provinceChildren
+			}
+		}
+
+		regionInfo.regionInfo.provinceAndCityData = cloneArray(regionInfo.regionInfo.regionData)
+
+		// 计算区
+		for (let i = 0, len = regionInfo.regionInfo.regionData.length; i < len; i++) {
+			const province = regionInfo.regionInfo.regionData[i].children
+			const provinceText = regionInfo.regionInfo.regionData[i].label
+			if (province) {
+				for (let j = 0, len = province.length; j < len; j++) {
+					const cityCode = province[j].value
+					const cityText = province[j].label
+					const cityChildren = []
+					for (const prop in ANRAN_REGION_DATA[cityCode]) {
+						cityChildren.push({
+							value: prop,
+							label: ANRAN_REGION_DATA[cityCode][prop]
+						})
+						regionInfo.regionInfo.CodeToText[prop] = ANRAN_REGION_DATA[cityCode][prop]
+						regionInfo.regionInfo.TextToCode[provinceText][cityText][ANRAN_REGION_DATA[cityCode][prop]] = {
+							code: prop
+						}
+					}
+					if (cityChildren.length) {
+						province[j].children = cityChildren
+					}
+				}
+			}
+		}
+
+		// 添加“全部”选项
+		regionInfo.regionInfo.provinceAndCityDataPlus = cloneArray(regionInfo.regionInfo.provinceAndCityData)
+		regionInfo.regionInfo.provinceAndCityDataPlus.unshift({
+			value: '',
+			label: '全部'
+		})
+
+		regionInfo.regionInfo.regionDataPlus = cloneArray(regionInfo.regionInfo.regionData)
+		regionInfo.regionInfo.regionDataPlus.unshift({
+			value: '',
+			label: '全部'
+		})
+	})
+}
+
+
+//let ANRAN_REGION_DATA = AR_REGION_DATA
+const cloneArray = function (obj) {
+	const newArray = []
+	for (const i in obj) {
+		newArray[i] = typeof obj[i] === 'object' ? cloneArray(obj[i]) : obj[i]
+	}
+	return newArray
+}
+
+export default initRegion

+ 10 - 12
src/views/ad/edit.vue

@@ -57,6 +57,7 @@
 import { fetchDetail, fetchEdit, fetchAdd } from '@/api/ad'
 import tool from '@/utils/tool'
 import Upload from '@/components/Upload'
+import ElementUI from 'element-ui'
 export default {
   name: 'RoleAdd',
   components: { Upload },
@@ -107,8 +108,8 @@ export default {
           this.article = response.data.oneData.CONTENT
         }
         this.loading = false
-      }).catch(err => {
-        console.log('err---------' + err)
+      }).catch((error) => {
+          ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
       })
     } else {
       fetchDetail(this.$route.params.ID).then(response => {
@@ -116,8 +117,8 @@ export default {
         this.allArticle = response.data.allArticle
 
         this.loading = false
-      }).catch(err => {
-        console.log('err---------' + err)
+      }).catch((error) => {
+          ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
       })
     }
   },
@@ -128,27 +129,24 @@ export default {
       if (this.$route.name === 'ad-edit') {
         fetchEdit(this.$route.params.ID, this.form).then(response => {
           this.submitButtonStat = false
-          console.log(response)
           this.$message({
             message: response.data,
             type: "$t('common.successfully')"
           })
           this.$router.go(-1)
-        }).catch(err => {
-          console.log('err---------' + err)
-        })
+       }).catch((error) => {
+           ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+       })
       } else {
-        console.log(this.form)
         fetchAdd(this.form).then(response => {
           this.submitButtonStat = false
-          console.log(response)
           this.$message({
             message: response.data,
             type: 'success'
           })
           this.$router.go(-1)
-        }).catch(err => {
-          console.log('err---------' + err)
+        }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       }
     },

+ 13 - 13
src/views/ad/list.vue

@@ -127,6 +127,7 @@ import { parseTime } from '@/utils'
 import tool from '@/utils/tool'
 import permission from '@/utils/permission'
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+import ElementUI from 'element-ui'
 
 const calendarTypeOptions = [
   { key: 'CN', display_name: 'China' },
@@ -274,7 +275,6 @@ export default {
     },
     getContent(aid) {
       const titles = this.allArticle.filter(article => article.ID === aid).map(article => article.TITLE)
-      console.log(titles)
       return titles.length > 0 ? titles[0] : aid
     },
     getHref(link) {
@@ -303,9 +303,9 @@ export default {
     },
     handleDelete(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to delete the selected data?', 'Notice', { // 确定删除选定的数据?
-        confirmButtonText: 'confirm', // 确定
-        cancelButtonText: 'cancel', // 取消
+      obj.$confirm(this.$t('common.deleteSelectedData'), this.$t('common.notice'), { // 确定删除选定的数据?
+       confirmButtonText: this.$t('common.confirm'), // 确定
+       cancelButtonText: this.$t('common.cancel'), // 取消
         type: 'warning'
       }).then(() => {
         const selectedIds = []
@@ -322,14 +322,14 @@ export default {
             type: 'success'
           })
           obj.getList(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
+        }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       })
     },
     handleHide(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to hide the selected data?', 'Notice', { // 确定删除选定的数据?
+     obj.$confirm(this.$t('common.hideSelectedData'), this.$t('common.notice'), {  // 确定删除选定的数据?
         confirmButtonText: 'confirm', // 确定
         cancelButtonText: 'cancel', // 取消
         type: 'warning'
@@ -348,8 +348,8 @@ export default {
             type: 'success'
           })
           obj.getList(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
+        }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       })
     },
@@ -358,7 +358,7 @@ export default {
     },
     handleUnhide(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to hide the selected data?', 'Notice', { // 确定删除选定的数据?
+     obj.$confirm(this.$t('common.unHideSelectedData'), this.$t('common.notice'), { // 确定删除选定的数据?
         confirmButtonText: 'confirm', // 确定
         cancelButtonText: 'cancel', // 取消
         type: 'warning'
@@ -377,9 +377,9 @@ export default {
             type: 'success'
           })
           obj.getList(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
-        })
+       }).catch((error) => {
+           ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+       })
       })
     }
   }

+ 3 - 3
src/views/article/category.vue

@@ -3,8 +3,8 @@
     <div class="white-box">
       <el-table :data="tableData" stripe style="width: 100%;" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" />
-        <el-table-column label="Category Name" prop="CATE_NAME" /><!--分类名称-->
-        <el-table-column label="Order" width="100"><!--排序-->
+        <el-table-column :label="$t('article.categoryName')" prop="CATE_NAME" /><!--分类名称-->
+        <el-table-column :label="$t('article.order')" width="100"><!--排序-->
           <template slot-scope="scope">
             <el-input
               v-model="scope.row.SORT"
@@ -14,7 +14,7 @@
             />
           </template>
         </el-table-column>
-        <el-table-column label="Creation Time"><!--创建时间-->
+        <el-table-column :label="$t('article.creationTime')"><!--创建时间-->
           <template slot-scope="scope">
             {{ tool.formatDate(scope.row.CREATED_AT) }}
           </template>

+ 13 - 12
src/views/article/edit.vue

@@ -2,18 +2,18 @@
   <div v-loading="loading">
     <div class="white-box">
       <el-form ref="form" :model="form" label-width="100px">
-        <el-form-item label="Title" style="width: 500px;"><!--标题-->
+        <el-form-item :label="$t('article.title')" style="width: 500px;"><!--标题-->
           <el-input v-model="form.title" />
         </el-form-item>
-        <el-form-item label="Category"><!--分类-->
+        <el-form-item :label="$t('article.category')"><!--分类-->
           <el-select v-model="form.cid" placeholder="please select category"><!--请选择分类-->
             <el-option v-for="item in allCategory" :key="item.ID" :label="item.CATE_NAME" :value="item.ID" />
           </el-select>
         </el-form-item>
-        <el-form-item label="Order" style="width: 500px;"><!--排序值-->
+        <el-form-item :label="$t('article.order')" style="width: 500px;"><!--排序值-->
           <el-input v-model="form.sort" />
         </el-form-item>
-        <el-form-item label="Content"><!--内容-->
+        <el-form-item :label="$t('article.content')"><!--内容-->
           <div class="components-container" style="margin:0">
             <!-- <aside>
               {{ $t('components.tinymceTips') }}
@@ -26,7 +26,7 @@
           </div>
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" :loading="submitButtonStat" @click="onSubmit">Confirm<!-- 提交 --></el-button>
+          <el-button type="primary" :loading="submitButtonStat" @click="onSubmit">{{$t('article.confirm')}}<!-- 提交 --></el-button>
         </el-form-item>
       </el-form>
     </div>
@@ -36,6 +36,8 @@
 <script>
 import Tinymce from '@/components/Tinymce'
 import { fetchArticleDetail, fetchArticleAdd, fetchArticleAddList, fetchArticleEdit } from '@/api/article'
+import tool from '@/utils/tool'
+import ElementUI from 'element-ui'
 
 export default {
   name: 'ArticleEdit',
@@ -50,7 +52,7 @@ export default {
       },
       content: '',
       allCategory: null,
-      loading: false,
+      loading: true,
       submitButtonStat: false,
       isEdit: false
     }
@@ -58,12 +60,11 @@ export default {
   mounted() {
     if (this.$route.name === 'edit') {
       fetchArticleDetail(this.$route.params.ID).then(response => {
-        console.log(response)
         this.form.title = response.data.oneData.TITLE
         this.form.cid = response.data.oneData.CID
         this.form.content = response.data.oneData.CONTENT
         this.form.sort = response.data.oneData.SORT
-        this.allCategory = response.allCategory
+        this.allCategory = response.data.allCategory
         this.loading = false
         this.isEdit = true
       })
@@ -86,8 +87,8 @@ export default {
             type: 'success'
           })
           this.$router.go(-1)
-        }).catch(() => {
-          this.submitButtonStat = false
+          }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       } else {
         fetchArticleAdd(this.form).then(response => {
@@ -97,8 +98,8 @@ export default {
             type: 'success'
           })
           this.$router.go(-1)
-        }).catch(() => {
-          this.submitButtonStat = false
+        }).catch((error) => {
+          ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       }
     }

+ 36 - 35
src/views/article/index.vue

@@ -3,53 +3,53 @@
     <div class="white-box">
       <el-table :data="tableData" stripe style="width: 100%;" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" />
-        <el-table-column label="ID" prop="ID">
+        <el-table-column :label="$t('article.id')" prop="ID">
           <template slot-scope="scope">
             <router-link :to="`/article/detail/${scope.row.ID}`" target="_blank" class="islide">
               <span>{{ scope.row.ID }}</span>
             </router-link>
           </template>
         </el-table-column>
-        <el-table-column label="Title" prop="TITLE">
+        <el-table-column :label="$t('article.title')" prop="TITLE">
           <template slot-scope="scope">
             <router-link :to="`/article/detail/${scope.row.ID}`" target="_blank" class="islide">
               <span>{{ scope.row.TITLE }}</span>
             </router-link>
           </template>
         </el-table-column><!--标题-->
-        <el-table-column label="Category"><!--分类-->
+        <el-table-column :label="$t('article.category')"><!--分类-->
           <template slot-scope="scope">
             {{ allData.allCategory[scope.row.CID].CATE_NAME }}
           </template>
         </el-table-column>
-        <el-table-column label="Sort" width="100"> <!-- 排序 -->
+        <el-table-column :label="$t('article.sort')" width="100"> <!-- 排序 -->
           <template slot-scope="scope">
             <el-input v-model="scope.row.SORT" min="0" max="99" @change="handleChangeSort(scope.row, scope.row.SORT)" />
           </template>
         </el-table-column>
-        <el-table-column label="Creation Time"><!--创建时间-->
+        <el-table-column :label="$t('article.creationTime')"><!--创建时间-->
           <template slot-scope="scope">
             {{ tool.formatDate(scope.row.CREATED_AT) }}
           </template>
         </el-table-column>
-        <el-table-column label="Status"> <!-- 状态 -->
+        <el-table-column :label="$t('article.status')"> <!-- 状态 -->
           <template slot-scope="scope">
-            <div v-if="scope.row.STATUS === '1'">Show</div>
-            <div v-else>Hide</div>
+            <div v-if="scope.row.STATUS === '1'">{{$t('article.show')}}</div>
+            <div v-else>{{$t('common.hide')}}</div>
           </template>
         </el-table-column>
 
-        <el-table-column fixed="right" label="Action" width="180"><!--操作-->
+        <el-table-column fixed="right" :label="$t('article.action')" width="180"><!--操作-->
           <template slot-scope="scope">
             <el-dropdown size="small" trigger="click">
               <el-button type="primary" size="small" @click.stop="">
-                Action<i class="el-icon-arrow-down el-icon--right" />
+                {{$t('article.action')}}<i class="el-icon-arrow-down el-icon--right" />
               </el-button>
               <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item command="edit" @click.native="handleEdit(scope.row)">Edit</el-dropdown-item>
-                <el-dropdown-item command="delete" @click.native="handleDelete(scope.row)">Delete</el-dropdown-item>
-                <el-dropdown-item command="hide" @click.native="handleHide(scope.row)">Hide</el-dropdown-item>
-                <el-dropdown-item command="un-hide" @click.native="handleUnHide(scope.row)">Unhide</el-dropdown-item>
+                <el-dropdown-item command="edit" @click.native="handleEdit(scope.row)">{{$t('common.edit')}}</el-dropdown-item>
+                <el-dropdown-item command="delete" @click.native="handleDelete(scope.row)">{{$t('common.delete')}}</el-dropdown-item>
+                <el-dropdown-item command="hide" @click.native="handleHide(scope.row)">{{$t('common.hide')}}</el-dropdown-item>
+                <el-dropdown-item command="un-hide" @click.native="handleUnHide(scope.row)">{{$t('common.unhide')}}</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
           </template>
@@ -58,15 +58,15 @@
       <div class="white-box-footer">
         <el-dropdown size="small" trigger="click">
           <el-button type="primary" size="small">
-            Selected data<!--所选数据--><i class="el-icon-arrow-down el-icon--right" />
+            {{$t('common.selectData')}}<!--所选数据--><i class="el-icon-arrow-down el-icon--right" />
           </el-button>
           <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item command="delete" @click.native="handleMuliDel()">Delete</el-dropdown-item>
-            <el-dropdown-item command="hide" @click.native="handleMultiHide()">Hide</el-dropdown-item>
-            <el-dropdown-item command="un-hide" @click.native="handleMultiUnHide()">Unhide</el-dropdown-item>
+            <el-dropdown-item command="delete" @click.native="handleMuliDel()">{{$t('common.delete')}}</el-dropdown-item>
+            <el-dropdown-item command="hide" @click.native="handleMultiHide()">{{$t('common.hide')}}</el-dropdown-item>
+            <el-dropdown-item command="un-hide" @click.native="handleMultiUnHide()">{{$t('common.unhide')}}</el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
-        <el-button type="primary" size="small" @click="handleAdd">New article</el-button><!--添加文章-->
+        <el-button type="primary" size="small" @click="handleAdd">{{$t('article.newArticle')}}</el-button><!--添加文章-->
         <el-pagination
           :current-page="currentPage"
           :page-sizes="[20, 50, 100, 200]"
@@ -84,6 +84,7 @@
 <script>
 import { fetchArticleIndex, fetchChangeArticleSort, fetchArticleHide, fetchArticleUnhide, fetchArticleDel } from '@/api/article'
 import tool from '@/utils/tool'
+import ElementUI from 'element-ui'
 
 export default {
   name: 'ArticleIndex',
@@ -158,9 +159,9 @@ export default {
     },
     delData(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to delete the selected data?', 'Hint', { // 确定删除选定的数据
-        confirmButtonText: 'confirm', // 确定
-        cancelButtonText: 'cancel', // 取消
+      obj.$confirm(this.$t('common.deleteSelectedData'), this.$t('common.notice'), { // 确定删除选定的数据
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
         type: 'warning'
       }).then(() => {
         const selectedIds = []
@@ -177,16 +178,16 @@ export default {
             type: 'success'
           })
           obj.getData(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
+        }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       })
     },
     hideData(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to hide the selected data?', 'Notice', { // 确定删除选定的数据?
-        confirmButtonText: 'confirm', // 确定
-        cancelButtonText: 'cancel', // 取消
+      obj.$confirm(this.$t('common.hideSelectedData'), this.$t('common.notice'), { // 确定删除选定的数据?
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
         type: 'warning'
       }).then(() => {
         const selectedIds = []
@@ -203,16 +204,16 @@ export default {
             type: 'success'
           })
           obj.getData(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
+        }).catch((error) => {
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
         })
       })
     },
     unHideData(id = null) {
       const obj = this
-      obj.$confirm('Are you sure to un-hide the selected data?', 'Notice', { // 确定删除选定的数据?
-        confirmButtonText: 'confirm', // 确定
-        cancelButtonText: 'cancel', // 取消
+      obj.$confirm(this.$t('common.unHideSelectedData'), this.$t('common.notice'), { // 确定删除选定的数据?
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
         type: 'warning'
       }).then(() => {
         const selectedIds = []
@@ -229,9 +230,9 @@ export default {
             type: 'success'
           })
           obj.getData(obj.currentPage, obj.pageSize)
-        }).catch(response => {
-
-        })
+       }).catch((error) => {
+           ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+       })
       })
     }
   }

+ 262 - 0
src/views/bonus/balance-list.vue

@@ -0,0 +1,262 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user :filter-types="filterTypes"  :filter-btn-name="$t('common.screen')" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        ref="multipleTable"
+        class="table-box"
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :summary-method="getSummaries"
+        show-summary
+        :height="tool.getTableHeight()"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column v-if="tableHeaders" type="selection" width="70" />
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+
+      </el-table>
+      <div class="white-box-footer">
+        <!--<el-button type="primary" size="small" @click="handleSendShow" icon="el-icon-plus"-->
+        <!--v-show="permission.hasPermission(`bonus/cf-lx-apply`)">年度奖申请发放-->
+        <!--</el-button>-->
+        <el-button v-show="permission.hasPermission(`bonus/balance-export`)" type="success" size="small" @click="handleExport"><!-- 导出Excel -->{{$t('common.exportExcel')}}</el-button>
+        <pagination
+          :total="totalCount"
+          :page_size="pageSize"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+    <!--<el-dialog v-loading="dialogLoading" title="Annual award distribution" :visible.sync="dialogVisible"><!-- 年度奖发放
+      <el-form :model="form" label-width="250px" class="form-dialog">
+        <el-form-item label="Distribution type"><!-- 发放类型
+          <el-select v-model="form.sendType" placeholder="Please select the distribution type"><!-- 请选择发放类型
+            <el-option
+              v-for="(item,index) in applyTypes"
+              :key="index"
+              :label="item.NAME"
+              :value="item.ID"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="Include member status"><!-- 包含会员状态
+          <el-select v-model="form.statusValue" placeholder="Please select a status" multiple><!-- 请选择状态
+            <el-option v-for="(item,key) in statuses" :key="key" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="Remark"><!-- 备注
+          <el-input v-model="form.remark" type="textarea" :row="2" placeholder="Please enter the content"><!-- 请输入内容 </el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false"><!-- 取消 cancel</el-button>
+        <el-button type="primary" @click.native="handleSend"><!-- 发放 grant</el-button>
+      </div>
+    </el-dialog>
+    </el-dialog> -->
+  </div>
+</template>
+
+<script>
+import { fetchGetUserStatus, fetchBalanceList, fetchBalanceExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'BonusBalanceList',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      tableHeight: window.innerHeight - 310,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {},
+      dialogVisible: false,
+      dialogLoading: false,
+      statuses: null,
+      applyTypes: [
+        { 'ID': 'all', 'NAME': 'All' }, // 全部
+        { 'ID': 'cf', 'NAME': 'Garage endowment' }, // 车房养老
+        { 'ID': 'lx', 'NAME': 'Leader bonus' }// 领袖分红
+      ],
+      form: {
+        selectedIds: [],
+        statusValue: [],
+        sendType: null,
+        remark: null
+      }
+    }
+  },
+  mounted() {
+    fetchGetUserStatus().then(response => {
+      this.statuses = response.data.statuses
+      return this.getData()
+      // Just to simulate the time of the request
+    })
+  },
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchBalanceList(paramsData).then(response => {
+        console.log(response)
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        this.sumData = response.data.sumData
+        this.loading = false
+      })
+    },
+    // handleSendShow() {
+    //   if (this.multipleSelection.length < 1) {
+    //     this.$message({
+    //       message: 'Please check the member to apply for distribution', // 请勾选要申请发放的会员
+    //       type: 'warning'
+    //     })
+    //     return false
+    //   }
+    //   this.dialogVisible = true
+    // },
+    // handleSend() {
+    //   this.dialogLoading = true
+    //   this.$message({
+    //     message: 'Applying for distribution, please wait', // 正在申请发放请稍后
+    //     type: 'info'
+    //   })
+    //   for (const val of this.multipleSelection) {
+    //     this.form.selectedIds.push(val.USER_ID)
+    //   }
+    //   network.postData(`bonus/cf-lx-apply`,
+    //     this.form
+    //   ).then(response => {
+    //     this.$message({
+    //       message: response,
+    //       type: 'success'
+    //     })
+    //     this.dialogVisible = false
+    //     this.dialogLoading = false
+    //     this.form = {
+    //       selectedIds: [],
+    //       year: null,
+    //       sendType: null,
+    //       remark: null
+    //     }
+    //     this.getData()
+    //   }).catch(response => {
+    //     this.dialogLoading = false
+    //   })
+    // },
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      if (columns && data && columns.length > 0 && data.length > 0) {
+        columns.forEach((column, index) => {
+          if (index === 0) {
+            sums[index] = 'sub-total' + '\n' + 'Total' // '小计' + "\n" + '合计'
+            return
+          }
+          const values = data.map(item => {
+            if (typeof item[column.property] === 'object') {
+              return Number(item[column.property].value)
+            } else {
+              return Number(undefined)
+            }
+          })
+          if (!values.every(value => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => {
+              const value = Number(curr)
+              if (!isNaN(value)) {
+                return prev + curr
+              } else {
+                return prev
+              }
+            }, 0)
+            const field = 'SUM_' + column.property
+            if (typeof this.sumData[field] !== 'undefined') {
+              sums[index] = tool.formatPrice(sums[index]) + '\n' + tool.formatPrice(this.sumData[field])
+            } else {
+              sums[index] = tool.formatPrice(sums[index])
+            }
+          } else {
+            sums[index] = '-'
+          }
+        })
+      }
+      return sums
+    },
+    handleExport() {
+     this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), {  // `确定要导出当前数据吗?`, '提示',
+     confirmButtonText: this.$t('common.confirm'), // 确定
+     cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        return fetchBalanceExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+     }).catch((error) => {
+         if(error !== 'cancel'){
+             ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+         }
+     })
+    }
+  }
+}
+
+</script>
+
+<style scoped>
+</style>

+ 123 - 0
src/views/bonus/flow-bonus.vue

@@ -0,0 +1,123 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user :filter-types="filterTypes" :filter-btn-name="$t('common.screen')" @select-value="handleFilterUser" />
+      </div>
+      <el-table ref="multipleTable" class="table-box" :data="tableData" stripe style="width: 100%;" :height="tool.getTableHeight()">
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/flow-bonus-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchFlowBonus, fetchFlowBonusExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '../../components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'BonusFlowBonus',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {}
+    }
+  },
+  mounted() {
+    this.getData()
+  },
+  methods: {
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchFlowBonus(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        // vueObj.sumData = response.sumData
+      })
+    },
+    handleExport() {
+    this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), {  // `确定要导出当前数据吗?`, '提示',
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
+      }).then(() => {
+        return fetchFlowBonusExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+     }).catch((error) => {
+         if(error !== 'cancel'){
+             ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+         }
+     })
+    }
+  }
+}
+
+</script>
+
+<style scoped>
+  .table-box .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .table-box .el-form-item {
+    width: 30%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 178 - 0
src/views/bonus/other-period-bonus.vue

@@ -0,0 +1,178 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user :filter-types.sync="filterTypes" :filter-btn-name="$t('common.screen')" @select-value="handleFilterUser" />
+      </div>
+      <el-table ref="multipleTable" class="table-box" :data="tableData" stripe style="width: 100%;" :height="tool.getTableHeight()">
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/new-period-bonus-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchOtherPeriodBonusFilterTypes, fetchOtherPeriodBonus, fetchOtherPeriodBonusExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import baseInfo from '@/utils/baseInfo'
+import Pagination from '@/components/Pagination'
+import filterHelper from '../../utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'BonusOtherPeriodBonus',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      sumData: {
+        'SUM_PV_1L': null
+      },
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      filterTypes: null,
+      filterModel: {},
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels()
+    }
+  },
+  mounted() {
+    this.loading = false
+    this.getData()
+  },
+  methods: {
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    handleFilter() {
+      this.getData()
+    },
+    getFilterTypes() {
+      fetchOtherPeriodBonusFilterTypes.then(response => {
+        this.filterTypes = response.data
+        // 如果地址栏不为空则执行getData()
+        // if(window.location.href.match(/filter=/) !== null){
+        this.getData()
+        // }
+      })
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchOtherPeriodBonus(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        this.loading = false
+        // vueObj.sumData = response.sumData
+      })
+    },
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      if (columns && data && columns.length > 0 && data.length > 0) {
+        columns.forEach((column, index) => {
+          if (index === 0) {
+            sums[index] = 'sub-total' + '\n' + 'Total' // '小计' + "\n" + '合计'
+            return
+          }
+          const values = data.map(item => {
+            if (typeof item[column.property] === 'object') {
+              return Number(item[column.property].value)
+            } else {
+              return Number(undefined)
+            }
+          })
+          if (!values.every(value => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => {
+              const value = Number(curr)
+              if (!isNaN(value)) {
+                return prev + curr
+              } else {
+                return prev
+              }
+            }, 0)
+            const field = 'SUM_' + column.property
+            if (typeof this.sumData[field] !== 'undefined') {
+              sums[index] = tool.formatPrice(sums[index]) + '\n' + tool.formatPrice(this.sumData[field])
+            } else {
+              sums[index] = tool.formatPrice(sums[index])
+            }
+          } else {
+            sums[index] = '-'
+          }
+        })
+      }
+      return sums
+    },
+    handleExport() {
+    this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), {  // `确定要导出当前数据吗?`, '提示',
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
+      }).then(() => {
+        return fetchOtherPeriodBonusExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+    }).catch((error) => {
+        if(error !== 'cancel'){
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+        }
+    })
+    }
+  }
+}
+
+</script>
+
+<style scoped>
+  .table-box .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .table-box .el-form-item {
+    width: 30%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 150 - 0
src/views/bonus/perf-adjustment.vue

@@ -0,0 +1,150 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-user" @keyup.enter="getData()">
+        <el-input v-model="memberCode" size="small" style="width:400px;">
+          <template slot="prepend">{{$t('bonus.memberCode')}}</template>
+        </el-input>
+        <el-button type="primary" icon="el-icon-search" size="small" @click="getData()">{{$t('common.confirm')}}<!-- 确定 --></el-button>
+      </div>
+
+      <div v-show="show" style="margin-top: 25px;">
+        <el-row>
+          <el-col :span="16">
+            <div class="grid-content bg-purple" style="width: 100%">
+              <el-card class="box-card" shadow="hover">
+                <el-form ref="perfForm" :model="perfForm" status-icon label-width="250px" width="100%" class="demo-ruleForm">
+                  <el-form-item v-show="false" label="Member Code" prop="USER_NAME">
+                    <el-input v-model="perfForm.USER_ID" type="text" size="small" />
+                    <el-input v-model="perfForm.USER_NAME" type="text" size="small" />
+                  </el-form-item>
+
+                  <el-divider><span style="font-weight: bold;">{{$t('bonus.LMarketBalancePerformance')}}</span></el-divider>
+                  <el-form-item :label="$t('bonus.memberCode')" prop="SURPLUS_1L_USER_NAME"><!--会员编号-->
+                    <el-input v-model="perfForm.SURPLUS_1L_USER_NAME" type="text" size="small" autocomplete="off" readonly />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.balancePerformance')" prop="SURPLUS_1L"><!--综合结余业绩-->
+                    <el-input v-model="perfForm.SURPLUS_1L" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.entryBalancePerformance')" prop="SURPLUS_1L_ZC"><!--首单结余业绩-->
+                    <el-input v-model="perfForm.SURPLUS_1L_ZC" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.reconditioningBalancePerformance')" prop="SURPLUS_1L_FX"><!--复消结余业绩-->
+                    <el-input v-model="perfForm.SURPLUS_1L_FX" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+
+                  <el-divider><span style="font-weight: bold;">{{$t('bonus.RMarketBalancePerformance')}}</span></el-divider>
+                  <el-form-item :label="$t('bonus.memberCode')" prop="SURPLUS_2L_USER_NAME"><!--会员编号-->
+                    <el-input v-model="perfForm.SURPLUS_2L_USER_NAME" type="text" size="small" autocomplete="off" readonly />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.balancePerformance')" prop="SURPLUS_2L"><!--综合结余业绩-->
+                    <el-input v-model="perfForm.SURPLUS_2L" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.entryBalancePerformance')" prop="SURPLUS_2L_ZC">
+                    <el-input v-model="perfForm.SURPLUS_2L_ZC" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+                  <el-form-item :label="$t('bonus.reconditioningBalancePerformance')" prop="SURPLUS_2L_FX"><!--复消结余业绩-->
+                    <el-input v-model="perfForm.SURPLUS_2L_FX" type="text" size="small" autocomplete="off" />
+                  </el-form-item>
+
+                  <el-form-item>
+                    <el-button type="primary" size="small" @click="handlePerfAdjustment('perfForm')">{{$t('common.save')}}</el-button>
+                  </el-form-item>
+                </el-form>
+              </el-card>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+
+import { fetchPerfAdjustment, fetchPerfAdjustmentPost } from '@/api/bonus'
+
+export default {
+  name: 'BonusPerfAdjustment',
+  data() {
+    return {
+      loading: false,
+      memberCode: '',
+      show: false,
+      perfForm: {
+        USER_ID: '',
+        USER_NAME: '',
+        SURPLUS_1L: '',
+        SURPLUS_1L_ZC: '',
+        SURPLUS_1L_FX: '',
+        SURPLUS_21L_USER_NAME: '',
+        SURPLUS_2L: '',
+        SURPLUS_2L_ZC: '',
+        SURPLUS_2L_FX: '',
+        SURPLUS_2L_USER_NAME: ''
+      }
+    }
+  },
+  methods: {
+    // 查询安置网的下级会员和业绩
+    getData() {
+      if (!this.memberCode.length) {
+        this.$message({
+          message: 'Please enter member code',
+          type: 'info'
+        })
+        return false
+      }
+
+      // 清除上一次的填充结果
+      this.$refs['perfForm'].resetFields()
+      this.show = false
+
+      fetchPerfAdjustment({ memberCode: this.memberCode }).then(response => {
+        this.perfForm = response.data.allData
+        this.show = true
+        this.loading = false
+        // vueObj.sumData = response.sumData
+      }).catch(error => {
+        this.$message({
+          message: error,
+          type: 'warning'
+        })
+
+        this.loading = false
+      })
+    },
+    // 修改会员业绩
+    handlePerfAdjustment(formName) {
+      this.$confirm(this.$t('bonus.confirmAndReviseMemberPerformance'), this.$t('common.hint'), { // 确认修改会员业绩
+        confirmButtonText: this.$t('common.confirm'), // 确定
+        cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        this.loading = true
+        return fetchPerfAdjustmentPost(this.perfForm).then(response => {
+          this.$message({
+            message: response.data,
+            type: 'success'
+          })
+          this.loading = false
+
+          // 刷新数据
+          this.getData()
+        }).catch(error => {
+          this.$message({
+            message: error,
+            type: 'warning'
+          })
+          this.loading = false
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style>
+  .filter-user { font-size: 14px; margin-bottom: 20px; }
+  .filter-user:after { content: ''; display: table;  clear: both; }
+</style>

+ 143 - 0
src/views/bonus/perf-month.vue

@@ -0,0 +1,143 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-btn-name="$t('common.screen')" :filter-types="filterTypes" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :height="tool.getTableHeight(true)"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column v-if="tableHeaders" type="selection" width="55" />
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/perf-month-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchPerfMonth, fetchPerfMonthExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'LeoPerfMonthTable',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {},
+      filterStatus: 'ALL'
+    }
+  },
+  mounted() {
+    this.getData()
+  },
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchPerfMonth(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        // vueObj.sumData = response.sumData
+      })
+    },
+    handleExport() {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+     this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), { // '确定要导出当前表格中的数据吗?', '提示',
+       confirmButtonText: this.$t('common.confirm'), // 确定
+       cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        return fetchPerfMonthExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+    }).catch((error) => {
+        if(error !== 'cancel'){
+            ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+        }
+    })
+    }
+  }
+}
+</script>
+
+<style>
+  .leo-withdrawTable .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .leo-withdrawTable .el-form-item {
+    width: 40%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 150 - 0
src/views/bonus/perf-order.vue

@@ -0,0 +1,150 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-tabs v-model="filterStatus" @tab-click="handleFilterStatusClick">
+        <el-tab-pane :label="$t('common.all')" name="ALL" :lazy="true" /><!-- 全部 -->
+        <el-tab-pane :label="$t('bonus.welcomePackOrder')" name="ZC" :lazy="true" /><!-- 首购单 -->
+      </el-tabs>
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-btn-name="$t('common.screen')" :filter-types="filterTypes" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :height="tool.getTableHeight(true)"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column v-if="tableHeaders" type="selection" width="55" />
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/perf-order-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchPerfOrder, fetchPerfOrderExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'LeoPerfOrderTable',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {},
+      filterStatus: 'ALL'
+    }
+  },
+  mounted() {
+    this.getData()
+  },
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    handleFilterStatusClick(tab, event) {
+      filterHelper.clearFilterOption(this)
+      this.getData()
+    },
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchPerfOrder(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        // vueObj.sumData = response.sumData
+      })
+    },
+    handleExport() {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+      this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), { // '确定要导出当前表格中的数据吗?', '提示'
+      confirmButtonText: this.$t('common.confirm'), // 确定
+      cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        return fetchPerfOrderExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+     }).catch((error) => {
+         if(error !== 'cancel'){
+             ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+         }
+     })
+    }
+  }
+}
+</script>
+
+<style>
+  .leo-withdrawTable .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .leo-withdrawTable .el-form-item {
+    width: 40%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 143 - 0
src/views/bonus/perf-period-list.vue

@@ -0,0 +1,143 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-btn-name="$t('common.screen')" :filter-types="filterTypes" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :height="tool.getTableHeight(true)"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column v-if="tableHeaders" type="selection" width="55" />
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/perf-period-list-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchPerfPeriodList, fetchPerfPeriodListExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'LeoPerfPeriodListTable',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {},
+      filterStatus: 'ALL'
+    }
+  },
+  mounted() {
+    this.getData()
+  },
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchPerfPeriodList(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        // vueObj.sumData = response.sumData
+      })
+    },
+    handleExport() {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+       this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'),  { // '确定要导出当前表格中的数据吗?', '提示',
+       confirmButtonText: this.$t('common.confirm'), // 确定
+       cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        return fetchPerfPeriodListExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+     }).catch((error) => {
+         if(error !== 'cancel'){
+             ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+         }
+     })
+    }
+  }
+}
+</script>
+
+<style>
+  .leo-withdrawTable .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .leo-withdrawTable .el-form-item {
+    width: 40%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 141 - 0
src/views/bonus/user-perf.vue

@@ -0,0 +1,141 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-btn-name="$t('common.screen')" :filter-types="filterTypes" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :height="tool.getTableHeight(true)"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :prop="tableHeader.other.prop ? tableHeader.other.prop : null">
+          <template slot-scope="scope">
+            <template v-if="scope.row[tableHeader.index].other.tag">
+              <el-tag :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null" :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null" :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">{{ scope.row[tableHeader.index].value }}</el-tag>
+            </template>
+            <template v-else>
+              <div v-html="scope.row[tableHeader.index].value" />
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <el-button v-show="permission.hasPermission(`bonus/user-perf-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { fetchUserPerf, fetchUserPerfExport } from '@/api/bonus'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import Pagination from '@/components/Pagination'
+import filterHelper from '@/utils/filterHelper'
+import ElementUI from 'element-ui'
+
+export default {
+  name: 'LeoUserPerfTable',
+  components: { FilterUser, Pagination },
+  data() {
+    return {
+      tableHeaders: null,
+      tableData: null,
+      loading: true,
+      multipleSelection: [],
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      permission: permission,
+      baseDecLevels: baseInfo.decLevels(),
+      baseEmpLevels: baseInfo.empLevels(),
+      filterTypes: null,
+      filterModel: {},
+      filterStatus: 'ALL'
+    }
+  },
+  mounted() {
+    this.getData()
+  },
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    getData(page, pageSize) {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+
+      this.loading = true
+      const paramsData = Object.assign({
+        page: (page === null || page === undefined) ? 1 : page,
+        pageSize: (pageSize === null || pageSize === undefined) ? this.pageSize : pageSize
+      }, filterData)
+      fetchUserPerf(paramsData).then(response => {
+        this.filterTypes = response.data.filterTypes
+        this.tableData = response.data.list
+        this.tableHeaders = response.data.columnsShow ? response.data.columnsShow : []
+        this.loading = false
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+      })
+    },
+    handleExport() {
+      const filterData = this.filterModel
+      if (window.location.href.indexOf('filter') === -1) {
+        filterData.filterType = this.filterStatus !== 'ALL' ? `=,${this.filterStatus}` : ''
+      }
+      this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), { // '确定要导出当前表格中的数据吗?', '提示',
+       confirmButtonText: this.$t('common.confirm'), // 确定
+       cancelButtonText: this.$t('common.cancel'), // 取消
+        type: 'warning'
+      }).then(() => {
+        return fetchUserPerfExport(this.filterModel)
+      }).then(response => {
+        this.$message({
+          message: response.data,
+          type: 'success'
+        })
+     }).catch((error) => {
+         if(error !== 'cancel'){
+             ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
+         }
+     })
+    }
+  }
+}
+</script>
+
+<style>
+  .leo-withdrawTable .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .leo-withdrawTable .el-form-item {
+    width: 40%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 2 - 2
src/views/config/dec-level-config.vue

@@ -47,7 +47,7 @@
 
     <!-- 编辑	-->
     <el-dialog v-loading="editLoading" :title="$t('common.edit')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px">
-      <el-form ref="editForm" :model="editForm" :label-position="labelPosition" label-width="100px" style="width: 100%; margin-top: -30px; margin-bottom: -15px;">
+      <el-form ref="editForm" :model="editForm" :label-position="labelPosition" label-width="150px" style="width: 100%; margin-top: -30px; margin-bottom: -15px;">
         <el-row :gutter="3">
           <el-col :xs="24" :sm="24" :lg="12">
             <el-input v-show="false" v-model="editForm.ID" size="small" type="text" />
@@ -102,7 +102,7 @@ export default {
         PERF: '',
         isAdjustGift: false,
         isDec: false
-      }
+      },
     }
   },
   mounted() {

+ 0 - 1
src/views/dashboard/admin/index.vue

@@ -107,7 +107,6 @@ export default {
 				email: 'admin@test.com',
 				avatar: this.avatar
 			}
-			console.log(this.user)
 		}
   }
 }

+ 301 - 0
src/views/file/export.vue

@@ -0,0 +1,301 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-tabs v-model="moduleName" @tab-click="handleFilterStatusClick">
+        <el-tab-pane :label="$t('file.all')" name="all" :lazy="true" /><!-- 全部 -->
+        <el-tab-pane
+          v-for="(item,key) in allModuleName"
+          :key="key"
+          :label="item.label"
+          :name="item.value"
+          :lazy="true"
+        />
+      </el-tabs>
+      <div class="filter-box">
+        <filter-user :filter-types.sync="filterTypes" :filter-btn-name="$t('common.screen')" @select-value="handleFilterUser" />
+      </div>
+      <el-table
+        ref="multipleTable"
+        class="table-box"
+        :data="tableData"
+        stripe
+        style="width: 100%;"
+        :height="tool.getTableHeight(true)"
+        @selection-change="handleSelectionChange"
+      >
+        <!--        <el-table-column type="selection" width="55"></el-table-column>-->
+        <!-- <el-table-column
+          :label="$t('file.exportName')"
+          prop="EXPORT_NAME"
+          :width="flexWidth('EXPORT_NAME',tableData,$t('file.exportName'))"
+        > --><!-- 导出名称 -->
+        <el-table-column
+          :label="$t('file.exportName')"
+          prop="EXPORT_NAME"
+          :width="flexWidth('EXPORT_NAME',tableData,$t('file.exportName'))"
+        >
+          <!-- <template slot-scope="scope">
+            {{ scope.row.EXPORT_NAME }}
+          </template> -->
+
+        </el-table-column>
+        <el-table-column
+          :label="$t('file.route')"
+          prop="EXPORT_PERCENT"
+          :width="flexWidth('EXPORT_PERCENT',tableData,$t('file.download'))"
+        ><!-- 路径 -->
+          <template slot-scope="scope">
+            <el-button
+              v-if="Number(scope.row.EXPORT_PERCENT)===100"
+              type="success"
+              size="small"
+              @click="singleDownload(scope.row)"
+            >{{ $t('file.download') }}
+            </el-button>
+          </template>
+        </el-table-column>
+        <el-table-column
+          :label="$t('file.operationAdministrator')"
+          prop="ADMIN_NAME"
+          :width="flexWidth('ADMIN_NAME',tableData,$t('file.operationAdministrator'))"
+        ><!-- 操作管理员 -->
+          <!-- <template slot-scope="scope">
+            {{ scope.row.ADMIN_NAME }}
+          </template> -->
+        </el-table-column>
+        <el-table-column
+          :label="$t('file.exportProgress')"
+          prop="EXPORT_PERCENT"
+          :width="flexWidth('EXPORT_PERCENT',tableData,$t('file.exportProgress'))"
+        ><!-- 导出进度 -->
+          <template slot-scope="scope">
+            <el-progress
+              type="circle"
+              :percentage="Number.parseInt(percentList['EXPORT_PERCENT'][scope.row.ID])"
+              :width="50"
+              :stroke-width="3"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('file.exportStart')" width="180"><!-- 导出开始 -->
+          <template slot-scope="scope">
+            {{ tool.formatDate(scope.row.STARTED_AT) }}
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('file.exportComplete')" width="180"><!-- 导出完成 -->
+          <template slot-scope="scope">
+            {{ tool.formatDate(scope.row.ENDED_AT) }}
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('file.createTime')" width="180"><!-- 创建时间 -->
+          <template slot-scope="scope">
+            {{ tool.formatDate(scope.row.CREATED_AT) }}
+          </template>
+        </el-table-column>
+          <!--        <el-table-column fixed="right" label="操作" width="180">-->
+          <!--          <template slot-scope="scope">-->
+          <!--            <el-dropdown size="small" trigger="click" v-if="permission.hasPermission(`file/export-delete`)">-->
+          <!--              <el-button type="primary" size="small" @click.stop="">-->
+          <!--                操作该数据<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
+          <!--              </el-button>-->
+          <!--              <el-dropdown-menu slot="dropdown">-->
+          <!--                <el-dropdown-item command="delete" @click.native="handleDelete(scope.row)">删除</el-dropdown-item>-->
+          <!--              </el-dropdown-menu>-->
+          <!--            </el-dropdown>-->
+          <!--          </template>-->
+          <!--        </el-table-column>-->
+        </el-table-column>
+      </el-table>
+      <!--      <div class="white-box-footer"
+      >-->
+      <!--        <el-dropdown size="small" trigger="click" v-if="permission.hasPermission(`file/export-delete`)">-->
+      <!--          <el-button type="primary" size="small">-->
+      <!--            所选数据<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
+      <!--          </el-button>-->
+      <!--          <el-dropdown-menu slot="dropdown">-->
+      <!--            <el-dropdown-item command="delete" @click.native="handleDelete()">删除</el-dropdown-item>-->
+      <!--          </el-dropdown-menu>-->
+      <!--        </el-dropdown>-->
+      <!--        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange"-->
+      <!--                    @current-change="handleCurrentChange"></pagination>-->
+      <!--      </div>-->
+    </div>
+  </div>
+</template>
+
+<script>
+import tool from '@/utils/tool'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
+import filterHelper from '../../utils/filterHelper'
+import { fetchExport } from '@/api/file'
+import store from '@/utils/vuexStore'
+
+export default {
+  name: 'FileExport',
+  components: { FilterUser },
+  data() {
+    return {
+      tableData: null,
+      multipleSelection: [],
+      loading: true,
+      currentPage: 1,
+      totalPages: 1,
+      totalCount: 1,
+      pageSize: 20,
+      tool: tool,
+      EXPORT_NAME: '',
+      permission: permission,
+      filterTypes: {
+        'EXPORT_NAME': { isUserTable: false, name: this.$t('file.exportName') }, // 导出名称
+        'STARTED_AT': { isUserTable: false, name: this.$t('file.exportStartTime'), other: 'date' }, // 导出开始时间
+        'ENDED_AT': { isUserTable: false, name: this.$t('file.exportEndTime'), other: 'date' }, // 导出结束时间
+        'createdAt': { isUserTable: false, name: this.$t('file.creationTime'), other: 'date' }// 创建时间
+      },
+      filterModel: {},
+      filterStatus: '0',
+      auditStatus: ['not approved', 'approved', 'rejected'], // '未审核', '已审核', '已拒绝'
+      allModuleName: null,
+      moduleName: 'all',
+      percentList: {
+        'EXPORT_PERCENT': {}
+      }
+    }
+  },
+  mounted() {
+    this.getData()
+    store.state.socket.onMessageCallback = this.onMessageCallback
+  },
+  methods: {
+    singleDownload(row) {
+      const url = (row.REMOTE_URL) ? row.REMOTE_URL : process.env.VUE_APP_CDN_API + '/' + 'upload/excel_export' + '/' + row.FILE_NAME
+      window.open(url)
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    handleCurrentChange(page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange(pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    handleDownload(url) {
+      window.open(url)
+    },
+    handleFilterStatusClick(tab, event) {
+      this.getData()
+    },
+    handleFilterUser(filterData) {
+      filterHelper.handleFilterUser(this, filterData)
+    },
+    handleFilter() {
+      this.getData()
+    },
+    getData(page, pageSize) {
+      if (page === undefined) page = 1
+      if (pageSize === undefined) pageSize = 20
+      const filterData = this.filterModel
+      filterData.moduleName = this.moduleName !== 'all' ? `=,${this.moduleName}` : ''
+      let paramsData = {
+        page: page,
+        pageSize: pageSize
+      }
+      paramsData = Object.assign(paramsData, filterData)
+      console.log(paramsData)
+      fetchExport(paramsData).then(response => {
+        this.allModuleName = response.data.allModuleName
+        this.tableData = response.data.list
+        console.log(this.tableData)
+        this.currentPage = page
+        this.totalPages = parseInt(response.data.totalPages)
+        this.totalCount = parseInt(response.data.totalCount)
+        this.pageSize = pageSize
+        this.loading = false
+        const EXPORT_PERCENT = ['EXPORT_PERCENT']
+        if (EXPORT_PERCENT !== null) {
+          if (EXPORT_PERCENT.length > 0) {
+            for (const i in this.tableData) {
+              for (const j in EXPORT_PERCENT) {
+                this.$set(this.percentList[EXPORT_PERCENT[j]], this.tableData[i].ID, this.tableData[i][EXPORT_PERCENT[j]])
+              }
+            }
+          }
+        }
+      }, null, ['EXPORT_PERCENT'])
+    },
+    onMessageCallback(data) {
+      console.log(data)
+      if (data) {
+        if (data.other && data.other.MODEL === 'EXPORT' && data.other.ID) {
+          this.$set(this.percentList[data.other.FIELD], data.other.ID, data.percent)
+        }
+        if (data.percent && data.percent === 100) {
+          this.getData(this.currentPage, this.pageSize)
+        }
+      }
+    },
+    /**
+     * flexWidth
+     * @param prop 每列的prop 可传''
+     * @param tableData 表格数据
+     * @param title 标题长内容短的,传标题  可不传
+     * @param num 列中有标签等加的富余量
+     * @returns 列的宽度
+     * 注:prop,title有一个必传
+     */
+    flexWidth(prop, tableData = '', title, num = 0) {
+      if (tableData === undefined || tableData === null) {
+        return
+      }
+      let flexWidth = 0// 初始化表格列宽
+      let columnContent = ''// 占位最宽的内容
+      const canvas = document.createElement('canvas')
+      const context = canvas.getContext('2d')
+      context.font = '14px Microsoft YaHei'
+      if ((prop === '') && title) { // 标题长内容少的,取标题的值,
+        columnContent = title
+      } else { // 获取该列中占位最宽的内容
+        let index = 0
+        for (let i = 0; i < Object.values(tableData).length; i++) {
+          const now_temp = tableData[i][prop] + ''
+          const max_temp = tableData[index][prop] + ''
+          const now_temp_w = context.measureText(now_temp).width
+          const max_temp_w = context.measureText(max_temp).width
+          if (now_temp_w > max_temp_w) {
+            index = i
+          }
+        }
+        if (tableData[index] === undefined || tableData[index] === null) {
+          return
+        }
+        columnContent = tableData[index][prop]
+        // 比较占位最宽的值跟标题、标题为空的留出四个位置
+        const column_w = context.measureText(columnContent).width
+        const title_w = context.measureText(title).width
+        if (column_w < title_w) {
+          columnContent = title || '留四个字'
+        }
+      }
+      // 计算最宽内容的列宽
+      const width = context.measureText(columnContent)
+      flexWidth = width.width + 40 + num
+      return flexWidth + 'px'
+    }
+  }
+}
+
+</script>
+
+<style scoped>
+  .table-box .el-form-item__label {
+    width: 100px;
+    color: #99a9bf;
+  }
+
+  .table-box .el-form-item {
+    width: 30%;
+    margin-right: 0;
+    margin-bottom: 0;
+  }
+</style>

+ 0 - 1
src/views/log/admin-handle.vue

@@ -73,7 +73,6 @@ export default {
     },
     getData(page, pageSize) {
       const filterData = this.filterModel
-      console.log(filterData)
       const vueObj = this
       const paramsData = Object.assign({
         page: (page === null || page === undefined) ? 1 : page,

+ 0 - 1
src/views/log/admin-login.vue

@@ -73,7 +73,6 @@ export default {
     },
     getData(page, pageSize) {
       const filterData = this.filterModel
-      console.log(filterData)
       const vueObj = this
       const paramsData = Object.assign({
         page: (page === null || page === undefined) ? 1 : page,

+ 0 - 1
src/views/log/system.vue

@@ -73,7 +73,6 @@ export default {
     },
     getData(page, pageSize) {
       const filterData = this.filterModel
-      console.log(filterData)
       const vueObj = this
       const paramsData = Object.assign({
         page: (page === null || page === undefined) ? 1 : page,

+ 0 - 1
src/views/log/user-handle.vue

@@ -73,7 +73,6 @@ export default {
     },
     getData(page, pageSize) {
       const filterData = this.filterModel
-      console.log(filterData)
       const vueObj = this
       const paramsData = Object.assign({
         page: (page === null || page === undefined) ? 1 : page,

+ 8 - 8
src/views/log/user-login.vue

@@ -20,7 +20,7 @@
       </el-table-column>
     </el-table>
     <div class="white-box-footer">
-      <el-button v-show="permission.hasPermission(`v1/log/user-login-export`)" type="success" size="small" @click="handleExport">Export Excel<!-- 导出Excel --></el-button>
+      <el-button v-show="permission.hasPermission(`v1/log/user-login-export`)" type="success" size="small" @click="handleExport">{{$t('common.exportExcel')}}<!-- 导出Excel --></el-button>
       <pagination
         :total="totalCount"
         :page_size="pageSize"
@@ -38,6 +38,7 @@ import { fetchUserLoginList, fetchUserLoginExport } from '@/api/log'
 import filterHelper from '@/utils/filterHelper'
 import FilterUser from '@/components/FilterUser'
 import Pagination from '@/components/Pagination'
+import ElementUI from 'element-ui'
 
 export default {
   name: 'LogAdminLogin',
@@ -74,7 +75,6 @@ export default {
     },
     getData(page, pageSize) {
       const filterData = this.filterModel
-      console.log(filterData)
       const vueObj = this
       const paramsData = Object.assign({
         page: (page === null || page === undefined) ? 1 : page,
@@ -95,19 +95,19 @@ export default {
       this.getData()
     },
     handleExport() {
-      this.$confirm(`Are you sure you want to export the current data?`, 'Hint', { // `确定要导出当前数据吗?`, '提示',
-        confirmButtonText: 'confirm', // 确定
-        cancelButtonText: 'cancel', // 取消
+       this.$confirm(this.$t('common.exportCurrentData'), this.$t('common.notice'), {  // `确定要导出当前数据吗?`, '提示',
+      confirmButtonText: this.$t('common.confirm'), // 确定
+      cancelButtonText: this.$t('common.cancel'), // 取消
         type: 'warning'
       }).then(() => {
         return fetchUserLoginExport(this.filterModel)
       }).then(response => {
         this.$message({
-          message: response,
+          message: response.data,
           type: 'success'
         })
-      }).catch(response => {
-
+      }).catch((error) => {
+          ElementUI.Message({type: 'error', message: error.message, showClose: true, duration: 0})
       })
     }
   }

+ 222 - 0
src/views/user/dec-level-list.vue

@@ -0,0 +1,222 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-types="filterTypes" @select-value="handleFilterUser"></filter-user>
+      </div>
+
+      <el-table :data="tableData" stripe style="width: 100%;">
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header">
+          <template slot-scope="{row}">
+            <template v-if="row[tableHeader.index].other.tag">
+							<el-tag :type="row[tableHeader.index].other.tag.type ? row[tableHeader.index].other.tag.type : null" :size="row[tableHeader.index].other.tag.size ? row[tableHeader.index].other.tag.size : null" :class="row[tableHeader.index].other.tag.class ? row[tableHeader.index].other.tag.class : null" >
+								<span style="word-break: keep-all; word-wrap: break-word; white-space: pre-wrap;">{{ row[tableHeader.index].value }}</span>
+							</el-tag>
+						</template>
+            <template v-else-if="row[tableHeader.index].other.progress">
+              <el-progress type="circle" :percentage="Number.parseInt(percentList['MOVE_PERCENT'][row.ID])" :width="50" :stroke-width="3"></el-progress>
+            </template>
+            <template v-else>
+              <div v-html="row[tableHeader.index].value"></div>
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div class="white-box-footer">
+        <el-button type="primary" size="small" @click="dialog = true" icon="el-icon-plus" v-show="permission.hasPermission(`user/change-user-dec-level`)">{{ $t('member.modifyMemberLevel') }}</el-button>
+
+				<pagination v-show="total>0" :total="total" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+
+    <!-- 修改会员级别	-->
+		<el-dialog :title="$t('member.modifyMemberLevel')" :visible.sync="dialog" :width="screenWidth" style="margin-top: -80px">
+			<el-form ref="form" :model="form" label-width="150px" :label-position="labelPosition">
+				<el-form-item :label="$t('member.memberCode')">
+					<el-input v-model.trim="form.userName" @change="handleChange"></el-input>
+					<el-tag style="margin-top: 15px;" v-show="userInfo.REAL_NAME!==null">{{ $t('member.memberName') }}:{{ userInfo.REAL_NAME }} {{ $t('member.currentLevel') }}:{{ userInfo.LEVEL_NAME }}</el-tag>
+				</el-form-item>
+				<el-form-item :label="$t('member.entryLevel')">
+					<el-select v-model="form.levelId" :placeholder="$t('member.selectEntryLevelHint')">
+						<el-option v-for="(item,key) in allDecLevel" :label="item.LEVEL_NAME" :value="item.ID" :key="key"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.remark')">
+					<el-input type="textarea" :rows="2" placeholder="" v-model="form.remark">
+					</el-input>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" :loading="submitButtonStat" @click="onSubmit">{{ $t('common.confirm') }}</el-button>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+  </div>
+</template>
+
+<script>
+	import FilterUser from '@/components/FilterUser'
+	import baseInfo from '@/utils/baseInfo'
+	import permission from '@/utils/permission'
+	import Pagination from '@/components/Pagination'
+	import filterHelper from '@/utils/filterHelper'
+	import {getScreenWidth} from "@/utils";
+	import {fetchEntryLevelList, fetchMemberFullInfo, updateUserEntryLevel} from "@/api/member";
+	import tool from "@/utils/tool";
+
+	export default {
+		name: 'decLevelList',
+		components: {FilterUser,Pagination},
+		mounted() {
+			this.getData()
+		},
+		data() {
+			return {
+				tableHeaders: null,
+				tableData: null,
+				loading: false,
+				tool: tool,
+				permission: permission,
+				allDecLevel: baseInfo.decLevels(),
+				filterTypes: {},
+				filterModel: {},
+				filterStatus: '0',
+				total: 0,
+				page: 1,
+				pageSize: 20,
+				currentPage: 1,
+
+				screenWidth: getScreenWidth() > 500 ? '500px' : getScreenWidth() + 'px',
+				labelPosition: getScreenWidth() >= 500 ? 'right' : 'top',
+
+				submitButtonStat: false,
+				dialog: false,
+				form: {
+					userName: null,
+					periodNum: null,
+					levelId: null,
+					remark: null,
+				},
+				userInfo: {
+					REAL_NAME: null,
+					DEC_LV: null,
+				},
+			}
+		},
+		methods: {
+			handleChange() {
+				this.submitButtonStat = true
+				fetchMemberFullInfo({ userName: this.form.userName }).then(response => {
+					this.userInfo = response.data
+					this.submitButtonStat = false
+				}).catch(error => {
+					this.userInfo.REAL_NAME = null
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.submitButtonStat = false
+				})
+			},
+			handleFilterUser(filterData) {
+				filterHelper.handleFilterUser(this, filterData)
+			},
+			handleCurrentChange(page) {
+				this.getData(page, this.pageSize)
+			},
+			handleSizeChange(pageSize) {
+				this.getData(this.currentPage, pageSize)
+			},
+			getData(page, pageSize) {
+				this.loading = true
+				const paramsData = Object.assign({
+					page: (page === null || page == undefined) ? 1 : page,
+					pageSize: (pageSize === null || pageSize == undefined) ? this.pageSize : pageSize
+				}, this.filterModel)
+				fetchEntryLevelList(paramsData).then(response => {
+					this.filterTypes = response.data.filterTypes
+					this.tableData = response.data.list
+					this.total = +response.data.totalCount
+					this.currentPage = page
+					this.pageSize = pageSize
+					this.filterTypes = response.data.filterTypes
+					this.tableHeaders = response.data.columnsShow
+
+					this.loading = false
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.loading = false
+				})
+			},
+			onSubmit() {
+				this.$confirm(this.$t('member.modifyMemberEntryLevelHits'), this.$t('common.hint'), {
+					confirmButtonText: this.$t('common.confirm'),
+					cancelButtonText: this.$t('common.cancel'),
+					type: 'warning'
+				}).then(() => {
+					this._handleSubmit()
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+				})
+			},
+			_handleSubmit() {
+				this.submitButtonStat = true
+				updateUserEntryLevel(this.form).then(response => {
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+
+					setTimeout(() => {
+						this.submitButtonStat = false
+					}, 0.5 * 1000)
+
+					this.submitButtonStat = false
+					this._clearData()
+					this.dialog = false
+					this.getData()
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+
+					this.submitButtonStat = false
+				})
+			},
+			_clearData(){
+				this.form = {
+					userName: null,
+					periodNum: null,
+					levelId: null,
+					remark: null,
+				}
+				this.userInfo= {
+					REAL_NAME: null,
+					DEC_LV: null,
+				}
+			},
+		}
+	}
+</script>
+
+<style>
+.app-main {
+	padding: 15px;
+}
+.app-container {
+	padding: 0;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
+}
+</style>

+ 299 - 0
src/views/user/empty-order-operation.vue

@@ -0,0 +1,299 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-tabs v-model="tabActiveName">
+        <el-tab-pane :label="$t('member.addManually')" name="first" v-if="permission.hasPermission(`user/user-add`)">
+          <el-form ref="form" :model="form" label-width="250px" :label-position="labelPosition">
+
+            <div class="hr-tip"><span>{{ $t('member.accountInformation') }}</span></div>
+
+            <el-form-item :label="$t('member.memberCode')" required>
+              <el-input v-model="form.userName"></el-input>
+            </el-form-item>
+            <el-form-item :label="$t('member.entryLevel')" required>
+              <el-select v-model="form.decLv" :placeholder="$t('member.selectEntryLevelHint')">
+                <el-option v-for="(item,index) in allDecLevel" :key="index" :label="item.LEVEL_NAME" :value="item.ID"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item :label="$t('member.stockistOrNot')">
+              <el-switch v-model="form.isDec"></el-switch>
+            </el-form-item>
+            <el-form-item :label="$t('member.stockistLevel')" v-show="form.isDec">
+              <el-select v-model="form.decRoleId" :placeholder="$t('member.pleaseSelectStockistLevel')">
+                <el-option v-for="(item,index) in allDecRole" :key="index" :label="item.ROLE_NAME" :value="item.ID"></el-option>
+              </el-select>
+            </el-form-item>
+
+            <div class="hr-tip"><span>{{ $t('member.networkInformation') }}</span></div>
+
+            <el-form-item :label="$t('member.stockistNo')" required>
+              <el-tooltip class="item" effect="dark" :content="$t('member.autoDetectMember')" placement="top-start">
+                <el-input v-model="form.decUserName" @change="handleChkDecUser">
+                  <template slot="append">【{{ decRealName }}】</template>
+                </el-input>
+              </el-tooltip>
+            </el-form-item>
+            <el-form-item :label="$t('member.contactPerson')" required>
+              <el-input v-model="form.conUserName" @change="handleChkConUser">
+                <template slot="append">【{{ conRealName }}】</template>
+              </el-input>
+            </el-form-item>
+            <el-form-item :label="$t('member.resettlementLocation')" required>
+              <el-radio-group v-model="form.location">
+                <el-radio-button :label="1">{{ $t('member.left') }}</el-radio-button>
+                <el-radio-button :label="2">{{ $t('member.right') }}</el-radio-button>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item :label="$t('member.sponsor')" required>
+              <el-input v-model="form.recUserName" @change="handleChkRecUser">
+                <template slot="append">【{{ recRealName }}】</template>
+              </el-input>
+            </el-form-item>
+
+            <div class="hr-tip"><span>{{ $t('member.personalData') }}</span></div>
+
+            <el-form-item :label="$t('member.memberName')" required>
+              <el-input v-model="form.realName"></el-input>
+            </el-form-item>
+            <el-form-item :label="$t('member.phoneNumber')">
+              <el-input v-model="form.mobile" maxlength="11"></el-input>
+            </el-form-item>
+
+            <el-collapse style="margin-bottom: 20px;">
+							<el-collapse-item :title="$t('member.otherInformation')" name="1">
+                <div class="hr-tip"><span>{{ $t('member.bankInformation') }}</span></div>
+
+                <el-form-item :label="$t('member.bankName')">
+                  <el-select v-model="form.openBank" :placeholder="$t('member.selectBankDeposit')">
+                    <el-option v-for="(item,index) in allOpenBank" :key="index" :label="item.BANK_NAME" :value="item.BANK_CODE"></el-option>
+                  </el-select>
+                </el-form-item>
+								<el-form-item :label="$t('member.bankRegion')" prop="bankAreaSelected">
+									<el-cascader size="large" :options="regionData" v-model="form.bankAreaSelected"></el-cascader>
+								</el-form-item>
+                <el-form-item :label="$t('member.subBankName')">
+                  <el-input v-model="form.bankAddress"></el-input>
+                </el-form-item>
+                <el-form-item :label="$t('member.bankAccount')">
+                  <el-input v-model="form.bankNo" maxlength="19"></el-input>
+                </el-form-item>
+
+              </el-collapse-item>
+            </el-collapse>
+            <el-form-item>
+              <el-button type="primary" @click="onSubmit" :loading="submitButtonStat">{{ $t('common.submit') }}</el-button>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+  import baseInfo from '@/utils/baseInfo'
+  import permission from '@/utils/permission'
+	import {getScreenWidth} from "@/utils"
+	import region from "@/store/modules/region"
+	import {fetchMemberFullInfo, fetchUserAdd, updateUserAdd} from "@/api/member"
+
+  export default {
+    name: 'emptyOrderOperation',
+    mounted() {
+      this.getData()
+    },
+    data() {
+      return {
+        form: {
+          userName: '',
+          nation: '',
+          realName: '',
+          idCard: '',
+          mobile: '',
+          address: '',
+          openBank: '',
+          bankAddress: '',
+          bankNo: '',
+          bankAreaSelected: [],
+          decLv: '',
+          areaSelected: [],
+          tel: '',
+          subComId: '',
+          isDec: false,
+          decUserName: '',
+          birthday: '',
+          decRoleId: '',
+          conUserName: '',
+          recUserName: '',
+          location: 1,
+        },
+        decRealName: '-',
+        conRealName: '-',
+        recRealName: '-',
+        excelForm: {
+          rowCount: 0,
+        },
+        loading: false,
+        tabActiveName: 'first',
+        submitButtonStat: false,
+        importButtonStat: false,
+        allNation: null,
+        allOpenBank: null,
+        regionData: region.regionInfo.regionData,
+        allDecLevel: baseInfo.decLevels(),
+        allDecRole: [],
+        delForm: {
+          delUserName: ''
+        },
+        userInfo: {
+          REAL_NAME: '',
+          DEC_USER_NAME: '',
+          DEC_REAL_NAME: '',
+          CON_USER_NAME: '',
+          CON_REAL_NAME: '',
+          LOCATION: '',
+          REC_USER_NAME: '',
+          REC_REAL_NAME: '',
+        },
+        delButtonStat: false,
+        delButtonDisabled: true,
+        permission: permission,
+				screenWidth: getScreenWidth() > 650 ? '650px' : getScreenWidth() + 'px',
+				labelPosition: getScreenWidth() >= 600 ? 'right' : 'top',
+      }
+    },
+    methods: {
+      getData() {
+        if (permission.hasPermission(`user/user-del`)) {
+          this.tabActiveName = 'third'
+        }
+        if (permission.hasPermission(`user/import-users-to-excel-table`) && permission.hasPermission(`user/import-users-add`)) {
+          this.tabActiveName = 'second'
+        }
+        if (permission.hasPermission(`user/user-add`)) {
+          this.tabActiveName = 'first'
+					this.loading = true
+					fetchUserAdd().then(response => {
+						this.loading = false
+						this.allNation = response.data.allNation
+						this.allOpenBank = response.data.allOpenBank
+						this.allDecRole = response.data.allDecRole
+						this.form.userName = response.data.userName
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+						this.loading = false
+					})
+        } else {
+          this.loading = false
+        }
+      },
+      onSubmit() {
+        this.submitButtonStat = true
+				updateUserAdd(this.form).then(response => {
+					this.submitButtonStat = false
+
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.submitButtonStat = false
+				})
+      },
+      handleChkDecUser() {
+        if (this.form.decUserName) {
+          this.loading = true
+					fetchMemberFullInfo({ userName: this.form.decUserName }).then(response => {
+						this.decRealName = response.data.REAL_NAME
+						this.loading = false
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+						this.loading = false
+					})
+        }
+      },
+      handleChkConUser() {
+        if (this.form.conUserName) {
+					this.loading = true
+					fetchMemberFullInfo({ userName: this.form.conUserName }).then(response => {
+						this.conRealName = response.data.REAL_NAME
+						this.loading = false
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+						this.loading = false
+					})
+        }
+      },
+      handleChkRecUser() {
+        if (this.form.recUserName) {
+					this.loading = true
+					fetchMemberFullInfo({ userName: this.form.recUserName }).then(response => {
+						this.recRealName = response.data.REAL_NAME
+						this.loading = false
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+						this.loading = false
+					})
+        }
+      },
+    }
+  }
+</script>
+
+<style>
+.app-main {
+	padding: 15px;
+}
+.app-container {
+	padding: 0;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
+}
+  .hr-tip {
+    font-size: 12px;
+    position: relative;
+    text-align: center;
+    height: 30px;
+    line-height: 30px;
+    color: #999;
+    margin-bottom: 20px;
+  }
+
+  .hr-tip:before {
+    content: '';
+    display: block;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 14px;
+    border-bottom: 1px dashed #ddd;
+    height: 1px;
+  }
+
+  .hr-tip span {
+    display: inline-block;
+    background: #fff;
+    position: relative;
+    padding: 0 10px;
+  }
+</style>

+ 552 - 107
src/views/user/member-list.vue

@@ -1,121 +1,566 @@
 <template>
-  <div class="app-container">
-    <el-table v-loading="loading" fit lazy highlight-current-row :data="memberData">
-      <!--			<el-table-column fixed type="selection" width="55" v-if="tableHeaders"></el-table-column>-->
-      <el-table-column
-        v-for="(tableHeader, key) in tableHeaders"
-        :key="key"
-        :label="tableHeader.header"
-        :width="tableHeader.other.width ? tableHeader.other.width : ''"
-        :fixed="tableHeader.index == 'USER_NAME' || tableHeader.index == 'REAL_NAME' ? true : false"
-      >
-        <template slot-scope="scope">
-          <template v-if="scope.row[tableHeader.index].other.tag">
-            <el-tag
-              :type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null"
-              :size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null"
-              :class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null"
-            >
-              {{ scope.row[tableHeader.index].value }}
-            </el-tag>
-          </template>
-          <template v-else>
-            <template v-if="tableHeader.index === 'USER_NAME'">
-              <el-dropdown v-if="permission.hasPermission(`user/login-to-frontend`)">
-                <span class="el-dropdown-link">
-                  {{ scope.row.USER_NAME.value }} <i class="el-icon-arrow-down el-icon--right" />
-                </span>
-                <el-dropdown-menu slot="dropdown">
-                  <el-dropdown-item v-show="scope.row.BTF_URL !== null" command="login">
-                    <a
-                      :href="`${frontendServer}/#/login-by-backend?${scope.row.BTF_URL}`"
-                      target="_blank"
-                      style="color:#606266;"
-                    >Quick logon<!-- 快速登录 --></a>
-                  </el-dropdown-item>
-                </el-dropdown-menu>
-              </el-dropdown>
-              <el-tag
-                v-if="!permission.hasPermission(`user/login-to-frontend`)"
-                type="primary"
-                size="small"
-                class="no-border"
-              >{{ scope.row.USER_NAME.value }}
-              </el-tag>
-            </template>
-            <template v-else>
-              <div v-html="scope.row[tableHeader.index].value" />
-            </template>
-          </template>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.pageSize" @pagination="getMemberList" />
-  </div>
+	<div v-loading="loading">
+		<div class="white-box">
+			<!-- 功能搜索 -->
+			<div class="filter-box">
+				<filter-user :filter-types="filterTypes" @select-value="handleFilterUser"></filter-user>
+			</div>
+
+			<!-- 列表展示 -->
+			<el-table ref="wrapper" :data="tableData" stripe style="width: 100%;" @selection-change="handleSelectionChange" :height="tool.getTableHeight()">
+				<el-table-column :fixed="leftFixed" type="selection" width="55" v-if="tableHeaders"></el-table-column>
+				<el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''" :fixed="tableHeader.index == 'USER_NAME' || tableHeader.index == 'REAL_NAME' ? leftFixed : false">
+					<template slot-scope="scope">
+						<template v-if="scope.row[tableHeader.index].other.tag">
+							<el-tag
+								:type="scope.row[tableHeader.index].other.tag.type ? scope.row[tableHeader.index].other.tag.type : null"
+								:size="scope.row[tableHeader.index].other.tag.size ? scope.row[tableHeader.index].other.tag.size : null"
+								:class="scope.row[tableHeader.index].other.tag.class ? scope.row[tableHeader.index].other.tag.class : null">
+								{{scope.row[tableHeader.index].value}}
+							</el-tag>
+						</template>
+						<template v-else>
+							<template v-if="tableHeader.index === 'USER_NAME'">
+								<el-dropdown v-if="permission.hasPermission(`user/login-to-frontend`)">
+									<span class="el-dropdown-link">
+										{{scope.row.USER_NAME.value}} <i class="el-icon-arrow-down el-icon--right"></i>
+									</span>
+									<el-dropdown-menu slot="dropdown">
+										<el-dropdown-item command="login" v-show="scope.row.BTF_URL !== null">
+											<a :href="`${frontendServer}/#/login-by-backend?${scope.row.BTF_URL}`" target="_blank" style="color:#606266;">{{ $t('member.quickLogon') }}</a>
+										</el-dropdown-item>
+									</el-dropdown-menu>
+								</el-dropdown>
+								<el-tag type="primary" size="small" class="no-border" v-if="!permission.hasPermission(`user/login-to-frontend`)">{{ scope.row.USER_NAME.value }}</el-tag>
+							</template>
+							<template v-else>
+								<div v-html="scope.row[tableHeader.index].value"></div>
+							</template>
+						</template>
+					</template>
+				</el-table-column>
+				<el-table-column :fixed="fixed" :label="$t('common.action')" width="180">
+					<template slot-scope="{row}">
+						<el-dropdown size="small" trigger="click">
+							<el-button type="primary" size="small" @click.stop="">{{ $t('common.action') }}<i class="el-icon-arrow-down el-icon--right"></i></el-button>
+							<el-dropdown-menu slot="dropdown">
+								<el-dropdown-item @click.native="handleModifyPassword(row)" v-if="permission.hasPermission(`user/modify-password`)">{{ $t('member.changePassword') }}</el-dropdown-item>
+								<el-dropdown-item @click.native="handleModifyProfile(row)" v-if="permission.hasPermission(`user/modify-profile`)">{{ $t('member.modifyPersonalData') }}</el-dropdown-item>
+								<el-dropdown-item @click.native="handleStatusActive(row)" v-if="permission.hasPermission(`user/modify-status`)">{{ $t('member.statusActivation') }}</el-dropdown-item>
+								<el-dropdown-item @click.native="handleStatusLock(row)" v-if="permission.hasPermission(`user/modify-status`)">{{ $t('member.statusLock') }}</el-dropdown-item>
+								<el-dropdown-item @click.native="handleIsModifyPassword(row, 1)" v-if="permission.hasPermission(`user/is-modify-password-status`)">{{ $t('member.openPasswordModification') }}</el-dropdown-item>
+								<el-dropdown-item @click.native="handleIsModifyPassword(row, 0)" v-if="permission.hasPermission(`user/is-modify-password-status`)">{{ $t('member.turnOffPasswordModification') }}</el-dropdown-item>
+							</el-dropdown-menu>
+						</el-dropdown>
+					</template>
+				</el-table-column>
+			</el-table>
+
+			<!-- 快捷功能 -->
+			<div class="white-box-footer">
+				<el-dropdown size="small" trigger="click" v-show="permission.hasPermission(`user/is-dec`)" style="margin: 5px;">
+					<el-button type="primary" size="small" @click.stop="">
+						{{ $t('member.stockistManagement') }}<i class="el-icon-arrow-down el-icon--right"></i>
+					</el-button>
+					<el-dropdown-menu slot="dropdown">
+						<el-dropdown-item command="isDec" @click.native="handleIsDecManage(true)">{{ $t('member.setAsStockist') }}</el-dropdown-item>
+						<el-dropdown-item command="notDec" @click.native="handleIsDecManage(false)">{{ $t('member.cancelStockist') }}</el-dropdown-item>
+					</el-dropdown-menu>
+				</el-dropdown>
+
+				<el-dropdown size="small" trigger="click" v-show="permission.hasPermission(`user/is-atlas`)" style="margin: 5px;">
+					<el-button type="primary" size="small" @click.stop="">
+						{{ $t('member.chartManagement') }}<i class="el-icon-arrow-down el-icon--right"></i>
+					</el-button>
+					<el-dropdown-menu slot="dropdown">
+						<el-dropdown-item command="isAtlas" @click.native="handleIsAtlasManage(true)">{{ $t('member.displayChart') }}</el-dropdown-item>
+						<el-dropdown-item command="notAtlas" @click.native="handleIsAtlasManage(false)">{{ $t('member.hiddenChart') }}</el-dropdown-item>
+					</el-dropdown-menu>
+				</el-dropdown>
+
+				<el-dropdown size="small" trigger="click" v-show="permission.hasPermission(`user/is-recharge`)" style="margin: 5px;">
+					<el-button type="primary" size="small" @click.stop="">
+						{{ $t('member.rechargeManagement') }}<i class="el-icon-arrow-down el-icon--right"></i>
+					</el-button>
+					<el-dropdown-menu slot="dropdown">
+						<el-dropdown-item command="isAtlas" @click.native="handleIsRechargeManage(true)">{{ $t('member.displayRecharge') }}</el-dropdown-item>
+						<el-dropdown-item command="notAtlas" @click.native="handleIsRechargeManage(false)">{{ $t('member.hideRecharge') }}</el-dropdown-item>
+					</el-dropdown-menu>
+				</el-dropdown>
+				<el-button type="success" size="small" @click="handleExport" v-show="permission.hasPermission(`user/index-export`)" style="margin: 5px;">{{ $t('member.exportExcel') }}</el-button>
+
+
+				<pagination v-show="totalCount>0" :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+			</div>
+		</div>
+
+		<!-- 修改密码 -->
+		<el-dialog :title="formModifyPassword.typeName" :visible.sync="dialogModifyPasswordVisible" :width="screenWidth">
+			<el-form ref="form" :model="formModifyPassword" label-width="120px" class="form-dialog" :label-position="labelPosition">
+				<el-form-item :label="$t('member.type')">
+					<el-select v-model="formModifyPassword.passwordType" :placeholder="$t('member.selectType')">
+						<el-option v-for="(item,key) in passwordType" :label="item.label" :value="item.type" :key="key"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.password')">
+					<el-input :placeholder="$t('member.password')"  v-model="formModifyPassword.password"></el-input>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleModifyPasswordSubmit" :loading="submitPasswordButtonStat">{{ $t('common.confirm') }}</el-button>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+
+		<!-- 修改会员信息 -->
+		<el-dialog :title="formModifyProfile.typeName" :visible.sync="dialogModifyProfileVisible" :width="screenWidth">
+			<el-form ref="form" :model="formModifyProfile" label-width="150px" :label-position="labelPosition">
+				<el-form-item :label="$t('member.memberName')">
+					<el-input v-model="formModifyProfile.realName"></el-input>
+				</el-form-item>
+				<el-form-item :label="$t('member.identityNo')">
+					<el-input v-model="formModifyProfile.idCard"></el-input>
+				</el-form-item>
+				<el-form-item :label="$t('member.phoneNumber')">
+					<el-input v-model="formModifyProfile.mobile"></el-input>
+				</el-form-item>
+				<el-form-item :label="$t('member.bankName')">
+					<el-select v-model="formModifyProfile.openBank" :placeholder="$t('member.selectBankName')">
+						<el-option v-for="(item,index) in allOpenBank" :key="index" :label="item.BANK_NAME" :value="item.BANK_CODE"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.bankAddress')">
+					<el-input v-model="formModifyProfile.bankAddress"></el-input>
+				</el-form-item>
+				<el-form-item :label="$t('member.bankAccount')">
+					<el-input v-model="formModifyProfile.bankNo"></el-input>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleModifyProfileSubmit" :loading="submitProfileButtonStat">{{ $t('common.confirm') }}</el-button>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+	</div>
 </template>
 
 <script>
-import waves from '@/directive/waves'
+import tool from '@/utils/tool'
+import baseInfo from '@/utils/baseInfo'
+import FilterUser from '@/components/FilterUser'
+import permission from '@/utils/permission'
 import Pagination from '@/components/Pagination'
-import { getScreenWidth } from '@/utils'
-import { fetchMemberList } from '@/api/member'
+import filterHelper from '@/utils/filterHelper'
+import waves from "@/directive/waves";
+import {getOperatingSystem, getScreenWidth} from "@/utils"
+import region from "@/store/modules/region"
+import {
+	fetchCloseDec, fetchCloseDecGet, fetchCloseLoginGet, fetchMemberExport, fetchMemberList, fetchProfileGet,
+	updateModifyPassword, updateModifyProfile, updateSetActive, updateSetAsStockist, updateSetChartDisplay, updateSetLock, updateSetModifyPassword, updateSetRechargeDisplay,
+} from "@/api/member"
 
 export default {
-  name: 'MemberList',
-  components: { Pagination },
-  directives: { waves },
-  filters: {
-    statusFilter(status) {
-      const statusMap = {
-        Unpaid: 'info',
-        Paid: 'success'
-      }
-      return statusMap[status]
-    }
-  },
-  data() {
-    return {
-      tableKey: 0,
-      total: 0,
-      memberData: [],
-      loading: true,
-      downloadLoading: false,
-      listQuery: {
-        page: 1,
-        pageSize: 20
-      },
-      childrenNode: [],
-      screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
-      labelPosition: getScreenWidth() > 600 ? 'right' : 'top'
-    }
-  },
-  created() {
-    this.getMemberList()
-  },
-  methods: {
-    getMemberList() {
-      this.loading = true
-      fetchMemberList(this.listQuery).then(response => {
-        this.memberData = response.data.list
-        this.total = +response.data.totalCount
-        console.log(this.memberData)
-        setTimeout(() => {
-          this.loading = false
-        }, 0.5 * 1000)
-      })
-    }
-  }
+	name: 'memberList',
+	directives: { waves },
+	components: {FilterUser, Pagination},
+	mounted() {
+		// TODO: 测试接口
+		// this.getData()
+
+		if (permission.hasPermission(`user/close-login`) || permission.hasPermission(`user/close-area-login`) || permission.hasPermission(`user/batch-close-login`)) {
+			fetchCloseLoginGet().then(response => {
+				this.apps = response.data.apps
+				this.closeSwitch = response.data.closeSwitch
+				if (permission.hasPermission(`user/close-dec`) || permission.hasPermission(`user/close-area-dec`) || permission.hasPermission(`user/batch-close-dec`)) {
+					fetchCloseDecGet().then(response => {
+						this.closeDecSwitch = response.data.closeSwitch
+						this.getData()
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+					})
+				} else {
+					this.getData()
+				}
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+			})
+		} else {
+			if (permission.hasPermission(`user/close-dec`) || permission.hasPermission(`user/close-area-dec`) || permission.hasPermission(`user/batch-close-dec`)) {
+				fetchCloseDecGet().then(response => {
+					this.closeDecSwitch = response.data.closeSwitch
+					this.getData()
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+				})
+			} else {
+				this.getData()
+			}
+		}
+	},
+	data() {
+		return {
+			tableHeaders: null,
+			tableData: null,
+			loading: true,
+			multipleSelection: [],
+			currentPage: 1,
+			totalPages: 1,
+			totalCount: 1,
+			pageSize: 20,
+			frontendServer: process.env.VUE_APP_FRONTEND_WEBSITE,
+			baseDecLevels: baseInfo.decLevels(),
+			baseEmpLevels: baseInfo.empLevels(),
+			tool: tool,
+			permission: permission,
+			filterTypes: null,
+			filterModel: {},
+			dialogVisible: false,
+			formCloseLogin: {
+				userName: null,
+				typeName: this.$t('member.loginManagement'),
+				type: null,
+				isClose: 0,
+				remark: '',
+				areaSelected: null,
+			},
+			regionDataPlus: region.regionInfo.regionData,
+			apps: null,
+			closeSwitch: null,
+			submitButtonStat: false,
+			dialogDecVisible: false,
+			dialogModifyPasswordVisible: false,
+			dialogModifyProfileVisible: false,
+			formCloseDec: {
+				userName: null,
+				typeName: this.$t('member.entryManage'),
+				type: null,
+				isClose: 0,
+				remark: '',
+				areaSelected: null,
+			},
+			formModifyPassword: {
+				userId:'',
+				password: '',
+				typeName: this.$t('member.changePassword'),
+				passwordType: 'password',
+			},
+			formModifyProfile: {
+				userId:'',
+				typeName: this.$t('member.modifyPersonalData'),
+				nation: '',
+				realName: '',
+				idCard: '',
+				mobile: '',
+				openBank: '',
+				bankAddress: '',
+				bankNo: '',
+			},
+			passwordType: [
+				{
+					type:"password",
+					label: this.$t('member.loginPassword'),
+				},
+				{
+					type:"payPassword",
+					label: this.$t('member.paymentPassword'),
+				},
+			],
+			allOpenBank:null,
+			allNation:null,
+			submitDecButtonStat: false,
+			submitPasswordButtonStat: false,
+			submitProfileButtonStat: false,
+			transferPropForm: {
+				userIds: [],
+				allowTransfer: true,
+				transferProp: 100,
+				withdrawProp: 0,
+				remark: '',
+			},
+			closeUserData: null,
+			screenWidth: getScreenWidth() > 500 ? '500px' : getScreenWidth() + 'px',
+			labelPosition: getScreenWidth() >= 500 ? 'right' : 'top',
+			leftFixed: ['Android', 'ios'].includes(getOperatingSystem()) ? false : 'left',
+			fixed: ['Android', 'ios'].includes(getOperatingSystem()) ? false : 'right',
+		}
+	},
+	methods: {
+		handleSelectionChange(val) {
+			this.multipleSelection = val
+		},
+		handleCurrentChange(page) {
+			this.getData(page, this.pageSize)
+		},
+		handleSizeChange(pageSize) {
+			this.getData(this.currentPage, pageSize)
+		},
+		handleFilterUser(filterData) {
+			filterHelper.handleFilterUser(this, filterData)
+		},
+		handleFilter() {
+			this.getData()
+		},
+		getData(page, pageSize) {
+			this.loading = true
+			const paramsData = Object.assign({
+				page: (page === null || page == undefined) ? 1 : page,
+				pageSize: (pageSize === null || pageSize == undefined) ? this.pageSize : pageSize
+			}, this.filterModel)
+			fetchMemberList(paramsData).then(response => {
+				this.filterTypes = response.data.filterTypes
+				this.tableData = response.data.list
+				this.totalCount = +response.data.totalCount
+				this.currentPage = page
+				this.pageSize = pageSize
+				this.filterTypes = response.data.filterTypes
+				this.tableHeaders = response.data.columnsShow
+				this.loading = false
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+		handleIsDecManage(isDec) {
+			if (this.multipleSelection.length < 1) {
+				this.$message({
+					message: this.$t('member.selectMemberData'),
+					type: 'warning'
+				})
+				return
+			}
+			let isDecTip = isDec === true ? this.$t('member.setAsStockist') : this.$t('member.cancelStockist')
+			this.$confirm( this.$t('member.sureWant') + `【${isDecTip}】?`, this.$t('common.hint'), {
+				confirmButtonText: this.$t('common.confirm'),
+				cancelButtonText: this.$t('common.cancel'),
+				type: 'warning'
+			}).then(() => {
+				let selectedIds = []
+				for (let val of this.multipleSelection) {
+					selectedIds.push(val.USER_ID)
+				}
+				this.loading = true
+				updateSetAsStockist( { userIds: selectedIds, isDec: isDec }).then(response => {
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+
+					this.loading = false
+					this.getData(this.currentPage, this.pageSize)
+				})
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+		handleIsAtlasManage(isAtlas) {
+			if (this.multipleSelection.length < 1) {
+				this.$message({
+					message: this.$t('member.selectMemberData'),
+					type: 'warning'
+				})
+				return
+			}
+			let isAtlasTip = isAtlas === true ? this.$t('member.displayChart') : this.$t('member.hiddenChart')
+			this.$confirm(this.$t('member.sureWant') + `【${isAtlasTip}】?`, this.$t('common.hint'), {
+				confirmButtonText: this.$t('common.confirm'),
+				cancelButtonText: this.$t('common.cancel'),
+				type: 'warning'
+			}).then(() => {
+				let selectedIds = []
+				for (let val of this.multipleSelection) {
+					selectedIds.push(val.USER_ID)
+				}
+				this.loading = true
+				updateSetChartDisplay( { userIds: selectedIds, isAtlas: isAtlas }).then(response => {
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+
+					this.loading = false
+					this.getData(this.currentPage, this.pageSize)
+				})
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+		handleIsRechargeManage(isRecharge) {
+			if (this.multipleSelection.length < 1) {
+				this.$message({
+					message: this.$t('member.selectMemberData'),
+					type: 'warning'
+				})
+				return false
+			}
+			let isRechargeTip = isRecharge === true ? this.$t('member.displayRecharge') : this.$t('member.hideRecharge')
+			this.$confirm(this.$t('member.sureWant') + `【${isRechargeTip}】?`, this.$t('common.hint'), {
+				confirmButtonText: this.$t('common.confirm'),
+				cancelButtonText: this.$t('common.cancel'),
+				type: 'warning'
+			}).then(() => {
+				let selectedIds = []
+				for (let val of this.multipleSelection) {
+					selectedIds.push(val.USER_ID)
+				}
+				this.loading = true
+				updateSetRechargeDisplay( { userIds: selectedIds, isRecharge: isRecharge }).then(response => {
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+					this.loading = false
+					this.getData(this.currentPage, this.pageSize)
+				})
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+		handleExport() {
+			this.$confirm(this.$t('member.exportDataHint'), this.$t('common.hint'), {
+				confirmButtonText: this.$t('common.confirm'),
+				cancelButtonText: this.$t('common.cancel'),
+				type: 'warning'
+			}).then(() => {
+				this.loading = true
+				fetchMemberExport( this.filterModel).then(response => {
+					this.$message({
+						message: response.data,
+						type: 'success'
+					})
+					this.loading = false
+					this.getData(this.currentPage, this.pageSize)
+				})
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+		handleModifyPassword(row){
+			this.formModifyPassword.userId = row.USER_ID;
+			this.dialogModifyPasswordVisible = true
+		},
+		handleModifyProfile(row){
+			this.dialogModifyProfileVisible = true
+			fetchProfileGet( { id: row.USER_ID }).then(response => {
+				this.formModifyProfile = response.data.userInfo
+				this.allOpenBank = response.data.allOpenBank
+				this.allNation = response.data.allNation
+			})
+		},
+		handleStatusActive(row) {
+			this.loading = true
+			updateSetActive( { userId: row.USER_ID, status: 1 }).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+				this.loading = false
+				this.getData(this.currentPage, this.pageSize)
+			})
+		},
+		handleStatusLock(row) {
+			this.loading = true
+			updateSetLock( { userId: row.USER_ID, status: 0 }).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+				this.loading = false
+				this.getData(this.currentPage, this.pageSize)
+			})
+		},
+		handleIsModifyPassword(row, status){
+			this.loading = true
+			updateSetModifyPassword( { userId: row.USER_ID, status: status }).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+				this.loading = false
+				this.getData(this.currentPage, this.pageSize)
+			})
+		},
+		handleModifyPasswordSubmit() {
+			this.submitPasswordButtonStat = true
+			updateModifyPassword( this.formModifyPassword).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+
+				this.submitPasswordButtonStat = false
+				this.dialogModifyPasswordVisible = false
+
+				this.getData(this.currentPage, this.pageSize)
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'success'
+				})
+				this.submitPasswordButtonStat = false
+			})
+		},
+		handleModifyProfileSubmit() {
+			this.submitProfileButtonStat = true
+			updateModifyProfile( this.formModifyProfile).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+
+				this.submitProfileButtonStat = false
+				this.dialogModifyProfileVisible = false
+
+				this.getData(this.currentPage, this.pageSize)
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'success'
+				})
+				this.submitProfileButtonStat = false
+				this.dialogModifyProfileVisible = false
+			})
+		},
+	}
 }
 </script>
 
 <style>
-.el-table th.el-table__cell > .cell {
-	white-space: nowrap;
+.app-main {
+	padding: 15px;
 }
-
-.el-table td.el-table__cell > .cell {
-	word-break: keep-all;
-	white-space: pre-wrap;
+.app-container {
+	padding: 0;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
 }
 </style>

+ 656 - 0
src/views/user/member-network-move.vue

@@ -0,0 +1,656 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-tabs v-model="filterStatus" @tab-click="handleFilterStatusClick">
+        <el-tab-pane :lazy="true" :label="$t('member.all')"      name="-1"></el-tab-pane>
+        <el-tab-pane :lazy="true" :label="$t('member.reviewed')" name="0"></el-tab-pane>
+        <el-tab-pane :lazy="true" :label="$t('member.approved')" name="1"></el-tab-pane>
+        <el-tab-pane :lazy="true" :label="$t('member.rejected')" name="3"></el-tab-pane>
+      </el-tabs>
+
+			<!-- 搜索	-->
+      <div class="filter-box">
+        <filter-user ref="filterUser" :filter-types.sync="filterTypes" @select-value="handleFilterUser"></filter-user>
+      </div>
+
+			<!-- 列表	-->
+      <el-table :data="tableData" stripe style="width: 100%;" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" v-if="tableHeaders"></el-table-column>
+        <el-table-column v-for="(tableHeader, key) in tableHeaders" :key="key" :label="tableHeader.header" :width="tableHeader.other.width ? tableHeader.other.width : ''">
+          <template slot-scope="{row}">
+            <template v-if="row[tableHeader.index].other.tag" >
+              <el-tag :type="row[tableHeader.index].other.tag.type ? row[tableHeader.index].other.tag.type : null" :size="row[tableHeader.index].other.tag.size ? row[tableHeader.index].other.tag.size : null" :class="row[tableHeader.index].other.tag.class ? row[tableHeader.index].other.tag.class : null" >
+								{{ row[tableHeader.index].value }}
+							</el-tag>
+            </template>
+            <template v-else-if="row[tableHeader.index].other.progress" >
+              <el-progress type="circle" :percentage="Number.parseInt(percentList['MOVE_PERCENT'][row.ID])" :width="50" :stroke-width="3"></el-progress>
+            </template>
+            <template v-else>
+              <div v-html="row[tableHeader.index].value"></div>
+            </template>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('common.action')" v-if="tableHeaders">
+          <template slot-scope="{row}" v-if="row.AUDIT_STATUS === '0' && (permission.hasPermission(`user/move-pass`) || permission.hasPermission(`user/move-audit`) || permission.hasPermission(`user/move-delete`))">
+            <el-dropdown size="small" trigger="click">
+              <el-button type="primary" size="small">{{ $t('common.action') }}<i class="el-icon-arrow-down el-icon--right"></i></el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item command="pass"   @click.native="handleAuditShow(row)" v-show="permission.hasPermission(`user/move-pass`)">{{ $t('member.approved') }}</el-dropdown-item>
+                <el-dropdown-item command="refuse" @click.native="handleAudit(row, 'reject')" v-show="permission.hasPermission(`user/move-audit`)">{{ $t('member.rejected') }}</el-dropdown-item>
+                <el-dropdown-item command="del"    @click.native="handleDel(row.ID)" v-show="permission.hasPermission(`user/move-delete`)">{{ $t('member.deleteData') }}</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </template>
+        </el-table-column>
+      </el-table>
+
+			<!-- 功能菜单	-->
+      <div class="white-box-footer">
+				<el-button type="danger"  size="small" @click.native="handleDel()" v-if="(filterStatus==='0') && permission.hasPermission(`user/move-delete`)" style="margin: 10px; margin-left: 10px;">{{ $t('member.batchesDelete') }}</el-button>
+        <el-button type="primary" size="small" @click="dialogApplyFormVisible = true" icon="el-icon-plus" v-show="permission.hasPermission(`user/move-add`)" style="margin: 10px;">{{ $t('member.applyNetworkMove') }}</el-button>
+        <el-button type="success" size="small" @click="handleExport" v-show="permission.hasPermission(`user/move-export`)" style="margin: 10px;">{{ $t('member.exportExcel') }}</el-button>
+
+				<!-- 分页	-->
+				<pagination v-show="total>0" :total="total" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </div>
+    </div>
+
+		<!-- 新建移网	-->
+		<el-dialog :title="$t('member.applyNetworkTransfer')" :visible.sync="dialogApplyFormVisible" :width="screenWidth" style="margin-top: -80px;">
+			<el-form :model="applyForm" label-width="230px" :label-position="labelPosition" v-loading="dialogApplyLoading" size="mini" style="padding: 10px 15px; margin-top: -25px; margin-bottom: -25px;">
+				<el-form-item :label="$t('member.networkTransferType')">
+					<el-select v-model="applyForm.type" :placeholder="$t('member.selectNetworkTransferType')" style="width: 100%;">
+						<el-option v-for="(item,key) in netType" :label="item.name" :value="item.id" :key="key"></el-option>
+					</el-select>
+				</el-form-item>
+				<div v-if="applyForm.type==='network'">
+					<el-form-item :label="$t('member.mobileMemberCode')">
+						<el-input v-model.trim="applyForm.moveUserName" @blur="handleChkUser"></el-input>
+					</el-form-item>
+					<el-form-item :label="$t('member.mobileMemberName')" v-if="moveUser">
+						<el-input v-model="moveUser.REAL_NAME" :disabled="true"></el-input>
+					</el-form-item>
+					<el-form-item :label="$t('member.moveToPlacementMemberCode')">
+						<el-input v-model.trim="applyForm.toConUserName"></el-input>
+						<el-tag v-if="showToName == '' ? false : true">{{ showToName }}</el-tag>
+						<el-alert :title="toAlertTile" :type="toAlertType" :closable="false" v-show="toAlertShow"></el-alert>
+					</el-form-item>
+					<el-form-item :label="$t('member.moveToPlacementMemberName')">
+						<el-input v-model="applyForm.toConRealName"></el-input>
+					</el-form-item>
+				</div>
+				<div v-if="applyForm.type === 'relation'">
+					<el-form-item :label="$t('member.mobileMemberCode')">
+						<el-input v-model.trim="applyForm.moveUserName" @blur="handleChkUser"></el-input>
+					</el-form-item>
+					<el-form-item :label="$t('member.mobileMemberName')" v-if="moveUser">
+						<el-input v-model="moveUser.REAL_NAME" :disabled="true"></el-input>
+					</el-form-item>
+					<el-form-item :label="$t('member.moveToSponsorMemberCode')">
+						<el-input v-model.trim="applyForm.toConUserName"></el-input>
+						<el-tag v-if="showToName == '' ? false : true">{{ showToName }}</el-tag>
+						<el-alert :title="toAlertTile" :type="toAlertType" :closable="false" v-show="toAlertShow"></el-alert>
+					</el-form-item>
+					<el-form-item :label="$t('member.moveToSponsorMemberName')">
+						<el-input v-model="applyForm.toConRealName"></el-input>
+					</el-form-item>
+				</div>
+				<el-form-item v-if="applyForm.type === 'network'" :label="$t('member.moveToLocation')">
+					<el-select v-model="applyForm.location" :placeholder="$t('member.moveToLocation')" style="width: 100%;">
+						<el-option :label="$t('member.oneMarket')" value="1" key="location_1" sele></el-option>
+						<el-option :label="$t('member.twoMarket')" value="2" key="location_2"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.remark')" v-if="applyForm.type">
+					<el-input v-model="applyForm.remark"></el-input>
+				</el-form-item>
+			</el-form>
+			<div slot="footer" class="dialog-footer" style="margin-top: -15px;">
+				<el-button size="mini" @click="dialogApplyFormVisible = false">{{ $t('common.cancel') }}</el-button>
+				<el-button size="mini" type="primary" @click="onSubmit" :loading="submitButtonStat">{{ $t('common.submit') }}</el-button>
+			</div>
+		</el-dialog>
+
+		<!-- 修改移网	-->
+    <el-dialog :title="$t('member.modifyNetworkTransfer')" :visible.sync="dialogEditFormVisible" :width="screenWidth" style="margin-top: -80px;">
+      <el-form :model="form" label-width="230px" :label-position="labelPosition" v-loading="dialogEditLoading" size="mini" style="padding: 10px 15px; margin-top: -25px; margin-bottom: -25px;">
+        <el-form-item :label="$t('member.networkTransferType')">
+          <el-select v-model="form.type" :placeholder="$t('member.selectNetworkTransferType')" style="width: 100%;">
+            <el-option v-for="(item,key) in netType" :label="item.name" :value="item.id" :key="key"></el-option>
+          </el-select>
+        </el-form-item>
+        <div v-if="form.type==='network'">
+          <el-form-item :label="$t('member.mobileMemberCode')">
+            <el-input v-model="form.baseInfo.USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.mobileMemberName')">
+            <el-input v-model="form.baseInfo.REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalSuperiorNo')">
+            <el-input v-model="form.baseInfo.CON_USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalSuperiorName')">
+            <el-input v-model="form.baseInfo.CON_REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToPlacementMemberCode')">
+            <el-input v-model="form.toConUserName"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToPlacementMemberName')">
+            <el-input v-model="form.toConRealName"></el-input>
+          </el-form-item>
+        </div>
+        <div v-if="form.type==='relation'">
+          <el-form-item :label="$t('member.mobileMemberCode')">
+            <el-input v-model="form.baseInfo.USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.mobileMemberName')">
+            <el-input v-model="form.baseInfo.REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalDeveloperNo')">
+            <el-input v-model="form.baseInfo.REC_USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.nameOfOriginalDeveloper')">
+            <el-input v-model="form.baseInfo.REC_REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToSponsorMemberCode')">
+            <el-input v-model="form.toConUserName"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToSponsorMemberName')">
+            <el-input v-model="form.toConRealName"></el-input>
+          </el-form-item>
+        </div>
+        <el-form-item v-if="form.type === 'network'" :label="$t('member.moveToLocation')">
+          <el-select v-model="form.location" :placeholder="$t('member.moveToLocation')" style="width: 100%;">
+            <el-option :label="$t('member.oneMarket')" value="1" key="location_1"></el-option>
+            <el-option :label="$t('member.twoMarket')" value="2" key="location_2"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('member.remark')" v-if="form.type">
+          <el-input v-model="form.remark"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer" style="margin-top: -15px;">
+        <el-button size="mini" @click="dialogEditFormVisible = false">{{ $t('common.cancel') }}</el-button>
+        <el-button size="mini" type="primary" @click.native="handleEdit">{{ $t('common.submit') }}</el-button>
+      </div>
+    </el-dialog>
+
+		<!-- 移网审核	-->
+    <el-dialog :title="$t('member.reviewNetworkTransfer')" :visible.sync="dialogAuditFormVisible" :width="screenWidth" style="margin-top: -80px">
+      <el-form :model="form" label-width="230px" :label-position="labelPosition" v-loading="dialogAuditLoading" size="mini" style="padding: 10px 15px;">>
+        <el-form-item :label="$t('member.networkTransferType')">
+          <el-select v-model="form.type" :placeholder="$t('member.selectNetworkTransferType')" style="width: 100%;">
+            <el-option v-for="(item,key) in netType" :label="item.name" :value="item.id" :key="key"></el-option>
+          </el-select>
+        </el-form-item>
+        <div v-if="form.type==='network'">
+          <el-form-item :label="$t('member.mobileMemberCode')">
+            <el-input v-model="form.baseInfo.USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.mobileMemberName')">
+            <el-input v-model="form.baseInfo.REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalSuperiorNo')">
+            <el-input v-model="form.baseInfo.CON_USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalSuperiorName')">
+            <el-input v-model="form.baseInfo.CON_REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToPlacementMemberCode')">
+            <el-input v-model="form.toConUserName"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToPlacementMemberName')">
+            <el-input v-model="form.toConRealName"></el-input>
+          </el-form-item>
+        </div>
+        <div v-if="form.type==='relation'">
+          <el-form-item :label="$t('member.mobileMemberCode')">
+            <el-input v-model="form.baseInfo.USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.mobileMemberName')">
+            <el-input v-model="form.baseInfo.REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.originalDeveloperNo')">
+            <el-input v-model="form.baseInfo.REC_USER_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.nameOfOriginalDeveloper')">
+            <el-input v-model="form.baseInfo.REC_REAL_NAME" :disabled="true"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToSponsorMemberCode')">
+            <el-input v-model="form.toConUserName"></el-input>
+          </el-form-item>
+          <el-form-item :label="$t('member.moveToSponsorMemberName')">
+            <el-input v-model="form.toConRealName"></el-input>
+          </el-form-item>
+        </div>
+				<el-form-item v-if="form.type==='network'" :label="$t('member.moveToLocation')">
+					<el-select v-model="form.location" :placeholder="$t('member.moveToLocation')" style="width: 100%;">
+						<el-option :label="$t('member.oneMarket')" value="1" key="location_1"></el-option>
+						<el-option :label="$t('member.twoMarket')" value="2" key="location_2"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.remark')" v-if="form.type">
+					<el-input v-model="form.remark"></el-input>
+				</el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="mini" @click="dialogAuditFormVisible = false">{{ $t('common.cancel') }}</el-button>
+        <el-button size="mini" type="primary" @click.native="handleAuditPass">{{ $t('member.adopted') }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import tool from '@/utils/tool'
+  import FilterUser from '@/components/FilterUser'
+  import permission from '@/utils/permission'
+  import Pagination from '@/components/Pagination'
+  import filterHelper from '../../utils/filterHelper'
+	import {
+		fetchMemberFullInfo,
+		fetchNetworkMoveExport, fetchNetworkMoveGet,
+		fetchNetworkMoveList,
+		fetchNetworkType, updateNetworkMoveApply, updateNetworkMoveAudit, updateNetworkMoveDelete, updateNetworkMoveEdit,
+		updateNetworkMovePass
+	} from "@/api/member";
+	import {getScreenWidth} from "@/utils";
+
+  export default {
+    name: 'memberNetworkMove',
+    components: {FilterUser,Pagination},
+    mounted() {
+      // store.state.socket.onMessageCallback = this.onMessageCallback
+			// 查询移网分类
+			fetchNetworkType().then(response => {
+				this.netType = response.data.netType
+				this.getData()
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+    },
+    data() {
+      return {
+        tableHeaders: null,
+        allData: null,
+        tableData: null,
+        netType: [],
+        loading: true,
+        multipleSelection: [],
+				total: 0,
+				page: 1,
+				pageSize: 20,
+				currentPage: 1,
+        tool: tool,
+        permission: permission,
+        filterTypes: {},
+        filterModel: {},
+        filterStatus: '0',
+        dialogEditLoading: false,
+        dialogAuditLoading: false,
+        dialogEditFormVisible: false,
+        dialogAuditFormVisible: false,
+				dialogApplyLoading: false,
+				dialogApplyFormVisible: false,
+        auditId: null,
+        form: {
+          baseInfo: {USER_NAME: null},
+          moveUserName: null,
+          toConUserName: null,
+          toConRealName: null,
+          type: '',
+          location: '1',
+          remark: null,
+          createRemark: '',
+          auditStatus: null
+        },
+        percentList: {
+          'MOVE_PERCENT': {},
+        },
+				screenWidth: getScreenWidth() > 600 ? '600px' : getScreenWidth() + 'px',
+				labelPosition: getScreenWidth() >= 600 ? 'right' : 'top',
+
+				applyForm: {
+					moveUserName: null,
+					toConUserName: null,
+					toConRealName: null,
+					type: null,
+					location: '1',
+					remark: null,
+				},
+				moveUser: {},
+				showToName: '',
+				toAlertTile: '',
+				toAlertShow: false,
+				toAlertType: 'success',
+				isRelation: false,
+				submitButtonStat: false,
+      }
+    },
+    methods: {
+      handleSelectionChange(val) {
+        this.multipleSelection = val
+      },
+      handleCurrentChange(page) {
+        this.getData(page, this.pageSize)
+      },
+      handleSizeChange(pageSize) {
+        this.getData(this.currentPage, pageSize)
+      },
+      handleEditShow(row) {
+        this.dialogEditLoading = true
+        this.auditId = row.ID
+        this.dialogEditFormVisible = true
+				fetchNetworkMoveGet({ id: this.auditId }).then(response => {
+					this.$message({
+						message: response,
+						type: 'success'
+					})
+					this.dialogEditLoading = false
+					this.form = response
+					this.form.type = String(response.type)
+					this.form.location = String(response.location)
+					this.form.createRemark = this.form.remark
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.dialogEditLoading = false
+				})
+      },
+      handleEdit() {
+        this.dialogEditFormVisible = false
+        this.$message({
+          message: this.$t('member.modifyingData'),
+          type: 'info'
+        })
+
+				updateNetworkMoveEdit(this.form).then(response => {
+					this.$message({
+						message: response,
+						type: 'success'
+					})
+
+					this.getData(this.currentPage, this.pageSize)
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+				})
+      },
+      handleAuditShow(row) {
+        this.dialogAuditLoading = true
+        this.auditId = row.ID
+        this.dialogAuditFormVisible = true
+				fetchNetworkMoveGet({ id: this.auditId }).then(response => {
+					this.$message({
+						message: response,
+						type: 'success'
+					})
+					this.dialogAuditLoading = false
+					this.form = response
+					this.form.type = String(response.type)
+					this.form.location = String(response.location) !== '0' ? String(response.location) : '1'
+					this.form.createRemark = this.form.remark
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.dialogAuditLoading = false
+				})
+      },
+      handleAuditPass() {
+        this.dialogAuditFormVisible = false
+        this.$message({
+          message: this.$t('member.passingAudit'),
+          type: 'info'
+        })
+        this.form.auditStatus = 'true'
+				updateNetworkMovePass(this.form).then(response => {
+					this.$message({
+						message: response,
+						type: 'success'
+					})
+					this.getData(this.currentPage, this.pageSize)
+
+					this.loading = false
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.loading = false
+				})
+      },
+      handleAudit(row = null, status) {
+        let obj = this
+        let title = (status === 'reject') ? this.$t('member.rejectAuditNote') : this.$t('member.passAuditNote')
+        this.$prompt(title, this.$t('common.hint'), {
+          confirmButtonText: this.$t('common.confirm'),
+          cancelButtonText: this.$t('common.cancel'),
+          inputValue: '',
+        }).then(({value}) => {
+          this.$message({
+            message: this.$t('member.operationInProcess'),
+            type: 'info'
+          })
+          let selectedIds = []
+          if (row === null) {
+            for (let val of obj.multipleSelection) {
+              selectedIds.push(val.ID)
+            }
+          } else {
+            selectedIds.push(row.ID)
+          }
+
+					const data = {
+						selected: selectedIds,
+						remark: value,
+						auditStatus: status
+					}
+					updateNetworkMoveAudit(data).then(response => {
+						this.$message({
+							message: response,
+							type: 'success'
+						})
+						this.getData(this.currentPage, this.pageSize)
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+					})
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+          this.getData(this.currentPage, this.pageSize)
+        }).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+        })
+      },
+      handleDel(id = null) {
+				if (id == null && this.multipleSelection.length === 0) {
+					this.$message({
+						message:this.$t('member.selectedNonData'),
+						type: 'warning'
+					})
+					return false
+				}
+
+        this.$confirm(this.$t('member.deleteHint'), this.$t('common.hint'), {
+					confirmButtonText: this.$t('common.confirm'),
+					cancelButtonText: this.$t('common.cancel'),
+          type: 'warning',
+					customClass: 'csClass',
+        }).then(() => {
+          let selectedIds = []
+          if (id === null) {
+            for (let val of this.multipleSelection) {
+              selectedIds.push(val.ID)
+            }
+          } else {
+            selectedIds.push(id)
+          }
+
+					updateNetworkMoveDelete({ selected: selectedIds }).then(response => {
+						this.$message({
+							message: response,
+							type: 'success'
+						})
+						this.getData(this.currentPage, this.pageSize)
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+					})
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+					this.getData(this.currentPage, this.pageSize)
+        }).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+        })
+      },
+      handleFilterStatusClick(tab, event) {
+        filterHelper.clearFilterOption(this)
+        this.getData()
+      },
+      handleFilterUser(filterData) {
+        filterHelper.handleFilterUser(this, filterData)
+      },
+      handleFilter() {
+        this.getData()
+      },
+      getData(page, pageSize) {
+				this.loading = true
+				let filterData = this.filterModel
+				filterData.filterStatus = this.filterStatus != '-1' ? `=,${this.filterStatus}` : ''
+				const paramsData = Object.assign({
+					page: (page === null || page == undefined) ? 1 : page,
+					pageSize: (pageSize === null || pageSize == undefined) ? this.pageSize : pageSize
+				}, filterData)
+				fetchNetworkMoveList(paramsData).then(response => {
+					this.filterTypes = response.data.filterTypes
+					this.tableData = response.data.list
+					this.total = +response.data.totalCount
+					this.currentPage = page
+					this.pageSize = pageSize
+					this.filterTypes = response.data.filterTypes
+					this.tableHeaders = response.data.columnsShow
+
+					this.loading = false
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.loading = false
+				})
+      },
+      handleExport() {
+        this.$confirm(this.$t('member.exportExcelHint'), this.$t('common.hint'), {
+          confirmButtonText: this.$t('common.confirm'),
+          cancelButtonText: this.$t('common.cancel'),
+          type: 'warning',
+					customClass: 'csClass',
+        }).then(() => {
+					fetchNetworkMoveExport(this.filterModel).then(response => {
+						this.$message({
+							message: response,
+							type: 'warning'
+						})
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+					})
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+        }).catch(() => {
+
+        })
+      },
+      onMessageCallback(data) {
+        if (data) {
+          if (data.other && data.other.MODEL === 'USER_MOVE' && data.other.ID) {
+            this.$set(this.percentList[data.other.FIELD], data.other.ID, data.percent)
+          }
+          if (data.percent && data.percent === 100) {
+            //this.getData(this.currentPage, this.pageSize)
+          }
+        }
+      },
+			handleChkUser() {
+				if (this.applyForm.moveUserName) {
+					fetchMemberFullInfo({ userName: this.applyForm.moveUserName }).then(response => {
+						this.moveUser = response.data
+					}).catch(error => {
+						this.$message({
+							message: error,
+							type: 'warning'
+						})
+					})
+				}
+			},
+			onSubmit() {
+				this.submitButtonStat = true
+				updateNetworkMoveApply(this.applyForm).then(response => {
+					this.$message({
+						message: response,
+						type: 'success'
+					})
+					this.dialogApplyFormVisible = false
+					this.submitButtonStat = false
+				}).catch(error => {
+					this.$message({
+						message: error,
+						type: 'warning'
+					})
+					this.submitButtonStat = false
+				})
+			},
+    }
+  }
+
+</script>
+
+<style>
+.app-main {
+	padding: 15px;
+}
+.app-container {
+	padding: 10px;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
+}
+.csClass{
+	margin-top: 50px;
+}
+</style>

+ 137 - 0
src/views/user/modify-stockist-level.vue

@@ -0,0 +1,137 @@
+<template>
+  <div class="app-container">
+    <div v-loading="loading" class="white-box">
+			<el-form ref="form" :model="form" label-width="250px" :label-position="labelPosition">
+				<el-form-item :label="$t('member.memberCode')">
+					<el-input v-model.trim="form.userName" @change="handleChange"></el-input>
+					<el-tag style="margin-top: 15px;" v-show="userInfo.REAL_NAME !== null">{{ $t('member.memberName') }}:{{ userInfo.REAL_NAME }} {{ $t('member.currentLevel') }}:{{ allDecRole[userInfo.DEC_ROLE_ID] ? allDecRole[userInfo.DEC_ROLE_ID]['ROLE_NAME'] : '' }}</el-tag>
+				</el-form-item>
+				<el-form-item :label="$t('member.stockistLevel')">
+					<el-select v-model="form.levelId" :placeholder="$t('member.pleaseSelectStockistLevel')">
+						<el-option v-for="(item,key) in allDecRole" :label="item.ROLE_NAME" :value="item.ID" :key="key"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item :label="$t('member.remark')">
+					<el-input type="textarea" :rows="2" placeholder="" v-model="form.remark">
+					</el-input>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" :loading="submitButtonStat" @click="onSubmit">{{ $t('common.confirm') }}</el-button>
+				</el-form-item>
+			</el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import waves from '@/directive/waves'
+import { getScreenWidth } from '@/utils'
+import {fetchMemberFullInfo, updateUserStockistLevel} from "@/api/member";
+import baseInfo from "@/utils/baseInfo";
+
+export default {
+  name: 'modifyStockistLevel',
+  directives: { waves },
+  data() {
+    return {
+			form: {
+				userName: null,
+				levelId: null,
+				remark: null,
+			},
+			loading: false,
+			submitButtonStat: false,
+			allDecRole: baseInfo.decRoles(),
+			periodArr: [],
+			userInfo: {
+				REAL_NAME: null,
+				DEC_ROLE_ID: null,
+			},
+      screenWidth: getScreenWidth() > 600 ? '500px' : getScreenWidth() + 'px',
+      labelPosition: getScreenWidth() > 600 ? 'right' : 'top',
+    }
+  },
+  methods: {
+		handleChange() {
+			this.loading = true
+			fetchMemberFullInfo({ userName: this.form.userName }).then(response => {
+				this.userInfo = response.data
+
+				setTimeout(() => {
+					this.loading = false
+				}, 0.5 * 1000)
+			}).catch(error => {
+				this.userInfo.REAL_NAME = null
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+				this.loading = false
+			})
+		},
+    onSubmit() {
+			this.$confirm(this.$t('member.modifyEntryLevelHits'), this.$t('common.hint'), {
+				confirmButtonText: this.$t('common.confirm'),
+				cancelButtonText: this.$t('common.cancel'),
+				type: 'warning'
+			}).then(() => {
+				this._handleSubmit()
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+			})
+    },
+		_handleSubmit() {
+			updateUserStockistLevel(this.form).then(response => {
+				this.$message({
+					message: response.data,
+					type: 'success'
+				})
+
+				setTimeout(() => {
+					this.submitButtonStat = false
+				}, 0.5 * 1000)
+
+				this.submitButtonStat = false
+			}).catch(error => {
+				this.$message({
+					message: error,
+					type: 'warning'
+				})
+
+				this.submitButtonStat = false
+			})
+
+			this._clearData()
+		},
+		_clearData(){
+			this.form = {
+				userName: null,
+				levelId: null,
+				remark: null,
+			}
+			this.userInfo= {
+				REAL_NAME: null,
+				DEC_ROLE_ID: null,
+			}
+		}
+  }
+}
+</script>
+
+<style>
+.app-main {
+	padding: 15px;
+}
+.app-container {
+	padding: 0;
+}
+.white-box {
+	padding: 15px;
+}
+.form-page {
+	width: 100%;
+}
+</style>