فهرست منبع

Merge branch 'develop' of chelingzhu-web/storeCheck-admin-html into master

巡店运营平台
lilei 4 سال پیش
والد
کامیت
65e849685c
71فایلهای تغییر یافته به همراه5879 افزوده شده و 1862 حذف شده
  1. 1 1
      .env
  2. 1 1
      .env.preview
  3. 28 6
      package-lock.json
  4. 1 1
      package.json
  5. 26 0
      src/api/atorg.js
  6. 0 58
      src/api/card-voucher-user.js
  7. 3 3
      src/api/data.js
  8. 89 0
      src/api/evaluationItem.js
  9. 92 0
      src/api/evaluationPlan.js
  10. 2 2
      src/api/index.js
  11. 1 1
      src/api/job.js
  12. 5 6
      src/api/login.js
  13. 6 6
      src/api/power-role.js
  14. 6 6
      src/api/power-user.js
  15. 29 0
      src/api/store.js
  16. 34 0
      src/api/storeVsDevice.js
  17. 16 6
      src/api/supervision-role.js
  18. 77 0
      src/api/supervision-user.js
  19. 18 0
      src/api/vsDevice.js
  20. BIN
      src/assets/logo.png
  21. 53 53
      src/components/Cron/language/cn.js
  22. 53 53
      src/components/Cron/language/en.js
  23. 3 3
      src/components/Cron/language/index.js
  24. 1 1
      src/components/Table/index.js
  25. 122 122
      src/components/WEeditor/editor.vue
  26. 18 0
      src/components/global.less
  27. 1 1
      src/config/defaultSettings.js
  28. 117 54
      src/config/router.config.js
  29. 1 1
      src/core/directives/hasPermission.js
  30. 2 2
      src/layouts/BasicLayout.vue
  31. 2 2
      src/layouts/UserLayout.vue
  32. 61 61
      src/libs/getDate.js
  33. 22 18
      src/main.js
  34. 2 2
      src/permission.js
  35. 20 14
      src/store/modules/user.js
  36. 105 107
      src/utils/bg/bg.js
  37. 134 134
      src/utils/bg/bg1.js
  38. 118 119
      src/utils/bg/bg2.js
  39. 63 63
      src/utils/bg/bg3.js
  40. 100 100
      src/utils/bg/bg4.js
  41. 29 28
      src/utils/request.js
  42. 1 1
      src/utils/util.js
  43. 219 0
      src/views/BasicSettings/Organization.vue
  44. 364 0
      src/views/BasicSettings/StoreAssociatedEquipmentModal.vue
  45. 226 0
      src/views/BasicSettings/StoreManagement.vue
  46. 224 0
      src/views/BasicSettings/StoreModal.vue
  47. 0 255
      src/views/CardVoucherAuth/user/userList.vue
  48. 0 265
      src/views/CardVoucherAuth/user/userModal.vue
  49. 1 1
      src/views/Home.vue
  50. 13 27
      src/views/SupervisionAuth/role/menuModal.vue
  51. 58 45
      src/views/SupervisionAuth/role/roleList.vue
  52. 25 26
      src/views/SupervisionAuth/role/roleModal.vue
  53. 240 0
      src/views/SupervisionAuth/user/newStoreModal.vue
  54. 156 0
      src/views/SupervisionAuth/user/usedStoreModal.vue
  55. 276 0
      src/views/SupervisionAuth/user/userList.vue
  56. 339 0
      src/views/SupervisionAuth/user/userModal.vue
  57. 174 0
      src/views/evaluation/evaluationItem/AddEvaIndexModal.vue
  58. 196 0
      src/views/evaluation/evaluationItem/AddEvaItemModal.vue
  59. 274 0
      src/views/evaluation/evaluationItem/EvaluationItem.vue
  60. 173 0
      src/views/evaluation/evaluationItem/SetEvaItemModal.vue
  61. 253 0
      src/views/evaluation/evaluationPlan/AddEvaModal.vue
  62. 305 0
      src/views/evaluation/evaluationPlan/EvaluationPlan.vue
  63. 243 0
      src/views/evaluation/evaluationPlan/SetEvaDefaultModal.vue
  64. 393 0
      src/views/evaluation/evaluationPlan/SetEvaModal.vue
  65. 15 29
      src/views/power/role/menuModal.vue
  66. 65 35
      src/views/power/role/roleList.vue
  67. 46 40
      src/views/power/role/roleModal.vue
  68. 72 47
      src/views/power/user/userList.vue
  69. 62 50
      src/views/power/user/userModal.vue
  70. 1 3
      src/views/user/ChangePwd.vue
  71. 3 3
      vue.config.js

+ 1 - 1
.env

@@ -1,5 +1,5 @@
 NODE_ENV=production
 VUE_APP_PREVIEW=false
-VUE_APP_API_BASE_URL=https://carwash.zyucgj.com/cw-admin/
+VUE_APP_API_BASE_URL=https://aitour.zyucgj.com/at-admin
 VUE_APP_VERSION=V1.0.1
 VUE_APP_PRO_NAME=智能巡店运营管理平台

+ 1 - 1
.env.preview

@@ -1,5 +1,5 @@
 NODE_ENV=production
 VUE_APP_PREVIEW=true
-VUE_APP_API_BASE_URL=https://carwash.test.zyucgj.com/cw-admin/
+VUE_APP_API_BASE_URL=https://aitour.test.zyucgj.com/at-admin
 VUE_APP_VERSION=V1.0.1
 VUE_APP_PRO_NAME=智能巡店运营平台-pro

+ 28 - 6
package-lock.json

@@ -1148,6 +1148,22 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@simonwep/pickr": {
+      "version": "1.7.4",
+      "resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.7.4.tgz",
+      "integrity": "sha512-fq7jgKJT21uWGC1mARBHvvd1JYlEf93o7SuVOB4Lr0x/2UPuNC9Oe9n/GzVeg4oVtqMDfh1wIEJpsdOJEZb+3g==",
+      "requires": {
+        "core-js": "^3.6.5",
+        "nanopop": "^2.1.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "3.6.5",
+          "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
+          "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
+        }
+      }
+    },
     "@soda/friendly-errors-webpack-plugin": {
       "version": "1.7.1",
       "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
@@ -2313,12 +2329,13 @@
       "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
     },
     "ant-design-vue": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.5.2.tgz",
-      "integrity": "sha512-DmlOl+ld4hSQdEG1c2wAV+v9/Bl2aG+wBEnd1GJYV0LeOXaSrBGiIkZrmUrTrUL92yBdFO+OF25aFNb0UFMZOA==",
+      "version": "1.6.5",
+      "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.6.5.tgz",
+      "integrity": "sha512-FzLrK+JuJUq+g4vd+UjFFi13ZdSsb11EZFapisFXilJxpc1LxqyunZu5AP4nr9vFLs3J4UX2A6q+Rp/Fi6JrLg==",
       "requires": {
         "@ant-design/icons": "^2.1.1",
         "@ant-design/icons-vue": "^2.0.0",
+        "@simonwep/pickr": "~1.7.0",
         "add-dom-event-listener": "^1.0.2",
         "array-tree-filter": "^2.1.0",
         "async-validator": "^3.0.3",
@@ -2571,9 +2588,9 @@
       "dev": true
     },
     "async-validator": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.3.0.tgz",
-      "integrity": "sha512-cAHGD9EL8aCqWXjnb44q94MWiDFzUo1tMhvLb2WzcpWqGiKugsjWG9cvl+jPgkPca7asNbsBU3fa0cwkI/P+Xg=="
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.4.0.tgz",
+      "integrity": "sha512-VrFk4eYiJAWKskEz115iiuCf9O0ftnMMPXrOFMqyzGH2KxO7YwncKyn/FgOOP+0MDHMfXL7gLExagCutaZGigA=="
     },
     "asynckit": {
       "version": "0.4.0",
@@ -11878,6 +11895,11 @@
         }
       }
     },
+    "nanopop": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/nanopop/-/nanopop-2.1.0.tgz",
+      "integrity": "sha512-jGTwpFRexSH+fxappnGQtN9dspgE2ipa1aOjtR24igG0pv6JCxImIAmrLRHX+zUF5+1wtsFVbKyfP51kIGAVNw=="
+    },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",

+ 1 - 1
package.json

@@ -15,7 +15,7 @@
   },
   "dependencies": {
     "@antv/data-set": "^0.10.2",
-    "ant-design-vue": "^1.5.2",
+    "ant-design-vue": "^1.6.5",
     "axios": "^0.19.0",
     "core-js": "2.6.9",
     "enquire.js": "^2.1.6",

+ 26 - 0
src/api/atorg.js

@@ -0,0 +1,26 @@
+import { axios } from '@/utils/request'
+
+// 组织机构列表
+export const findOrgTree = params => {
+  return axios({
+    url: '/atorg/findOrgTree',
+    data: {},
+    method: 'get'
+  })
+}
+// 保存
+export const saveAtorg = params => {
+  return axios({
+    url: '/atorg/save',
+    data: params,
+    method: 'post'
+  })
+}
+// 删除
+export const delAtorg = params => {
+  return axios({
+    url: `/atorg/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}

+ 0 - 58
src/api/card-voucher-user.js

@@ -1,58 +0,0 @@
-import { axios } from '@/utils/request'
-
-// 重置密码
-export const resetPSD = params => {
-  return axios({
-    url: 'yyuser/resetPwd',
-    data: params,
-    method: 'POST'
-  })
-}
-
-// 获取列表数据
-export const getPowerUserList = params => {
-  const url = `yyuser/queryLike/${params.pageNo}/${params.pageSize}`
-  delete params.pageNo
-  delete params.pageSize
-  return axios({
-    url: url,
-    data: params,
-    method: 'POST'
-  })
-}
-
-// 改变权限状态接口
-export const updateEnableStatus = params => {
-  return axios({
-    url: `yyuser/enable/${params.id}/${params.flag}`,
-    data: {},
-    method: 'get'
-  })
-}
-
-// 删除用户接口
-export const delectUserPower = params => {
-  return axios({
-    url: `yyuser/delete/${params.id}`,
-    data: {},
-    method: 'get'
-  })
-}
-
-// 新增/编辑保存接口
-export const saveUserPower = params => {
-  return axios({
-    url: 'yyuser/save',
-    data: params,
-    method: 'POST'
-  })
-}
-
-// 获取角色列表接口
-export const getRoleList = params => {
-  return axios({
-    url: 'yyrole/findAll',
-    data: params,
-    method: 'POST'
-  })
-}

+ 3 - 3
src/api/data.js

@@ -2,14 +2,14 @@ import { axios } from '@/utils/request'
 
 export function login (parameter) {
   return axios({
-    url: '/login',
+    url: '/auth/login',
     method: 'post',
     data: parameter
   })
 }
 
 export const listLookUp = params => {
-  let url = `/lookup/queryLike`
+  const url = `/lookup/queryLike`
   return axios({
     url: url,
     data: params,
@@ -18,7 +18,7 @@ export const listLookUp = params => {
 }
 
 export const getLookUpData = (params) => {
-  let url = `/lookupItem/query/${params.pageNo}/${params.pageSize}`
+  const url = `/lookupItem/query/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({

+ 89 - 0
src/api/evaluationItem.js

@@ -0,0 +1,89 @@
+import { axios } from '@/utils/request'
+
+// 列表分页查询
+export const getItemListByPage = (params) => {
+  const url = `/assess/item/query/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 列表查询 (不带分页)
+export const getItemList = (params) => {
+  const url = `/assess/item/queryList`
+  return axios({
+    url: url,
+    data: {},
+    method: 'post'
+  })
+}
+// 保存考评项目
+export const itemSave = (params) => {
+  return axios({
+    url: '/assess/item/save',
+    data: params,
+    method: 'post'
+  })
+}
+// 考评项目启删除
+export const itemDelete = (params) => {
+  return axios({
+    url: `/assess/item/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 考评项目启禁用
+export const itemEnable = (params) => {
+  return axios({
+    url: `/assess/item/enable/${params.id}/${params.status}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 考评项目详情
+export const itemDetail = (params) => {
+  return axios({
+    url: `/assess/item/find/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+/**
+ * 考评指标管理
+ */
+// 考评指标列表查询
+export const itemIndexQuery = (params) => {
+  return axios({
+    url: `/assess/target/query`,
+    data: params,
+    method: 'post'
+  })
+}
+// 考评指标删除
+export const itemIndexDelete = (params) => {
+  return axios({
+    url: `/assess/target/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 考评指标详情
+export const itemIndexDetail = (params) => {
+  return axios({
+    url: `/assess/target/find/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 考评指标保存
+export const itemIndexSave = (params) => {
+  return axios({
+    url: `/assess/target/save`,
+    data: params,
+    method: 'post'
+  })
+}

+ 92 - 0
src/api/evaluationPlan.js

@@ -0,0 +1,92 @@
+import { axios } from '@/utils/request'
+
+// 列表分页查询
+export const planQueryByPage = (params) => {
+  const url = `/assess/scheme/query/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 列表查询 (不带分页)
+export const planQuery = (params) => {
+  const url = `/assess/scheme/queryList`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存考评项目
+export const planSave = (params) => {
+  return axios({
+    url: '/assess/scheme/save',
+    data: params,
+    method: 'post'
+  })
+}
+// 删除
+export const planDelete = (params) => {
+  return axios({
+    url: `/assess/scheme/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 启禁用
+export const planEnable = (params) => {
+  return axios({
+    url: `/assess/scheme/enable/${params.id}/${params.status}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 考评方案详情
+export const planDetail = (params) => {
+  return axios({
+    url: `/assess/scheme/find/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+/**
+ * 为考评方案选择项目
+ */
+// 考评方案包含项目查询
+export const planItemQuery = (params) => {
+  return axios({
+    url: `/assess/scheme/item/query`,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存考评方案项目
+export const planItemSave = (params) => {
+  return axios({
+    url: `/assess/scheme/item/save`,
+    data: params,
+    method: 'post'
+  })
+}
+/**
+ * 设置默认方案
+ */
+// 默认考评配置查询
+export const planDefaultQuery = (params) => {
+  return axios({
+    url: `/assess/default/query`,
+    data: {},
+    method: 'post'
+  })
+}
+// 保存默认考评配置
+export const planDefaultSave = (params) => {
+  return axios({
+    url: `/assess/default/save`,
+    data: params,
+    method: 'post'
+  })
+}

+ 2 - 2
src/api/index.js

@@ -1,6 +1,6 @@
 const api = {
-  Login: '/login',
-  Logout: '/logout',
+  Login: '/auth/login',
+  Logout: '/auth/logout',
   ForgePassword: '/auth/forge-password',
   Register: '/auth/register',
   twoStepCode: '/auth/2step-code',

+ 1 - 1
src/api/job.js

@@ -1,7 +1,7 @@
 import { axios } from '@/utils/request'
 
 export const listJob = (params) => {
-  let url = `/job/queryJob/${params.pageNo}/${params.pageSize}`
+  const url = `/job/queryJob/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({

+ 5 - 6
src/api/login.js

@@ -3,16 +3,15 @@ import { axios } from '@/utils/request'
 
 export function login ({ username, password }) {
   return axios({
-    url: 'login',
-    headers: { 'content-type': 'application/x-www-form-urlencoded', 'App-Type': 9 },
-    data: `username=${username}&password=${password}`,
+    url: 'auth/login',
+    data: { username, password },
     method: 'post'
-  }).then(res => res.data)
+  })
 }
 
 export function logout () {
   return axios({
-    url: 'logout',
+    url: 'auth/logout',
     method: 'get'
   })
 }
@@ -57,7 +56,7 @@ export function get2step (parameter) {
 // 修改密码
 export function changePwd (parameter) {
   return axios({
-    url: 'user/changePWD',
+    url: '/user/changePWD',
     method: 'post',
     data: parameter
   })

+ 6 - 6
src/api/power-role.js

@@ -2,7 +2,7 @@ import { axios } from '@/utils/request'
 
 // 分页查询角色
 export const getPowerRoleList = params => {
-  const url = `role/queryLike/${params.pageNo}/${params.pageSize}`
+  const url = `yyrole/queryLike/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -14,7 +14,7 @@ export const getPowerRoleList = params => {
 // 保存角色
 export const saveRolePower = params => {
   return axios({
-    url: 'role/save',
+    url: 'yyrole/save',
     data: params,
     method: 'POST'
   })
@@ -22,7 +22,7 @@ export const saveRolePower = params => {
 // flag 0:禁用 1:启用  启禁用角色
 export const updateEnableStatus = params => {
   return axios({
-    url: `role/enable/${params.id}/${params.flag}`,
+    url: `yyrole/enable/${params.id}/${params.flag}`,
     data: {},
     method: 'get'
   })
@@ -30,14 +30,14 @@ export const updateEnableStatus = params => {
 // 删除角色
 export const delectRolePower = params => {
   return axios({
-    url: `role/delete/${params.id}`,
+    url: `yyrole/delete/${params.id}`,
     data: {},
     method: 'get'
   })
 }
 // 查询可用所有菜单
 export const getMenuList = params => {
-  const url = `role/findAllMenu/${params.id}`
+  const url = `yyrole/findAllMenu/${params.id}`
   return axios({
     url: url,
     method: 'get'
@@ -45,7 +45,7 @@ export const getMenuList = params => {
 }
 // 保存角色菜单关系
 export const addMenuPower = params => {
-  const url = `role/saveRoleMenu`
+  const url = `yyrole/saveRoleMenu`
   return axios({
     url: url,
     data: params,

+ 6 - 6
src/api/power-user.js

@@ -3,7 +3,7 @@ import { axios } from '@/utils/request'
 // 重置密码
 export const resetPSD = params => {
   return axios({
-    url: 'user/resetPwd',
+    url: 'yyuser/resetPwd',
     data: params,
     method: 'POST'
   })
@@ -11,14 +11,14 @@ export const resetPSD = params => {
 // 启用禁用
 export const updateEnableStatus = params => {
   return axios({
-    url: `user/enable/${params.id}/${params.flag}`,
+    url: `yyuser/enable/${params.id}/${params.flag}`,
     data: {},
     method: 'get'
   })
 }
 // 分页查询用户
 export const getPowerUserList = params => {
-  const url = `user/queryLike/${params.pageNo}/${params.pageSize}`
+  const url = `yyuser/queryLike/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -30,7 +30,7 @@ export const getPowerUserList = params => {
 // 删除用户接口
 export const delectUserPower = params => {
   return axios({
-    url: `user/delete/${params.id}`,
+    url: `yyuser/delete/${params.id}`,
     data: {},
     method: 'get'
   })
@@ -38,7 +38,7 @@ export const delectUserPower = params => {
 // 查询所有角色
 export const getRoleList = params => {
   return axios({
-    url: 'role/findAll',
+    url: 'yyrole/findAll',
     data: params,
     method: 'POST'
   })
@@ -46,7 +46,7 @@ export const getRoleList = params => {
 // 保存用户
 export const saveUserPower = params => {
   return axios({
-    url: 'user/save',
+    url: 'yyuser/save',
     data: params,
     method: 'POST'
   })

+ 29 - 0
src/api/store.js

@@ -0,0 +1,29 @@
+import { axios } from '@/utils/request'
+
+// 查询门店明细
+export const findStoreDetail = params => {
+  return axios({
+    url: `/store/findDetail/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 分页查询门店列表
+export const findStoreList = params => {
+  const url = `/store/findPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 保存门店组织机构
+export const saveStoreOrg = params => {
+  return axios({
+    url: '/store/saveOrg',
+    data: params,
+    method: 'post'
+  })
+}

+ 34 - 0
src/api/storeVsDevice.js

@@ -0,0 +1,34 @@
+import { axios } from '@/utils/request'
+
+// 门店绑定设备信息
+export const bindVsDevice = params => {
+  return axios({
+    url: '/storeVsDevice/bindVsDevice',
+    data: params,
+    method: 'post'
+  })
+}
+// 查询门店设备信息
+export const findStoreVsDevice = params => {
+  return axios({
+    url: `/storeVsDevice/findStoreVsDevice/${params.code}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 根据设备编号查询设备信息
+export const findVsDevice = params => {
+  return axios({
+    url: `/storeVsDevice/findVsDevice/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 门店解绑设备信息
+export const unbindVsDevice = params => {
+  return axios({
+    url: '/storeVsDevice/unbindVsDevice',
+    data: params,
+    method: 'post'
+  })
+}

+ 16 - 6
src/api/card-voucher-role.js → src/api/supervision-role.js

@@ -2,7 +2,7 @@ import { axios } from '@/utils/request'
 
 // 获取列表数据
 export const getPowerRoleList = params => {
-  const url = `yyrole/queryLike/${params.pageNo}/${params.pageSize}`
+  const url = `ddrole/queryLike/${params.pageNo}/${params.pageSize}`
   delete params.pageNo
   delete params.pageSize
   return axios({
@@ -15,7 +15,7 @@ export const getPowerRoleList = params => {
 // 改变权限状态接口 flag 0:禁用 1:启用
 export const updateEnableStatus = params => {
   return axios({
-    url: `yyrole/enable/${params.id}/${params.flag}`,
+    url: `ddrole/enable/${params.id}/${params.flag}`,
     data: {},
     method: 'get'
   })
@@ -24,7 +24,7 @@ export const updateEnableStatus = params => {
 // 删除用户接口
 export const delectRolePower = params => {
   return axios({
-    url: `yyrole/delete/${params.id}`,
+    url: `ddrole/delete/${params.id}`,
     data: {},
     method: 'get'
   })
@@ -33,7 +33,7 @@ export const delectRolePower = params => {
 // 新增/编辑保存接口
 export const saveRolePower = params => {
   return axios({
-    url: 'yyrole/save',
+    url: 'ddrole/save',
     data: params,
     method: 'POST'
   })
@@ -41,7 +41,7 @@ export const saveRolePower = params => {
 
 // 获取菜单树数据
 export const getMenuList = params => {
-  const url = `yyrole/findAllMenu/${params.id}`
+  const url = `ddrole/findAllMenu/${params.id}`
   return axios({
     url: url,
     method: 'get'
@@ -50,7 +50,17 @@ export const getMenuList = params => {
 
 // 保存权限分配
 export const addMenuPower = params => {
-  const url = `yyrole/saveRoleMenu`
+  const url = `ddrole/saveRoleMenu`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 查询所有角色
+export const getAllRole = params => {
+  const url = `ddrole/findAll`
   return axios({
     url: url,
     data: params,

+ 77 - 0
src/api/supervision-user.js

@@ -0,0 +1,77 @@
+import { axios } from '@/utils/request'
+
+// 重置密码
+export const resetPSD = params => {
+  return axios({
+    url: 'dduser/resetPwd',
+    data: params,
+    method: 'POST'
+  })
+}
+// 启用禁用
+// export const updateEnableStatus = params => {
+//   return axios({
+//     url: `user/enable/${params.id}/${params.flag}`,
+//     data: {},
+//     method: 'get'
+//   })
+// }
+// 督导列表
+export const getPowerUserList = params => {
+  const url = `dduser/queryLike/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+// 删除督导用户
+export const delectUserPower = params => {
+  return axios({
+    url: `dduser/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 督导名下已选门店列表
+export const getUsedStoreList = params => {
+  return axios({
+    url: 'dduser/queryUsedStoreList',
+    data: params,
+    method: 'POST'
+  })
+}
+// 新增/编辑 保存用户
+export const saveUserPower = params => {
+  return axios({
+    url: 'dduser/save',
+    data: params,
+    method: 'POST'
+  })
+}
+// 解绑 (督导已选门店)
+export const deleteUsedStore = params => {
+  return axios({
+    url: `dduser/deleteUserStore/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+// 新增保存门店(督导巡店)
+export const saveNewUserStore = params => {
+  return axios({
+    url: 'dduser/saveUserStore',
+    data: params,
+    method: 'POST'
+  })
+}
+// 已选组织机构下的门店列表
+export const getOrgUsedStoreList = params => {
+  return axios({
+    url: 'dduser/queryStore',
+    data: params,
+    method: 'POST'
+  })
+}

+ 18 - 0
src/api/vsDevice.js

@@ -0,0 +1,18 @@
+import { axios } from '@/utils/request'
+
+// 获取设备下通道(流)列表
+export const vsDeviceChannels = params => {
+  return axios({
+    url: `/vs/device/channels/${params.id}`,
+    data: params,
+    method: 'post'
+  })
+}
+// 设备重命名
+export const vsDeviceRename = params => {
+  return axios({
+    url: `/vs/device/rename/${params.deviceId}/${params.deviceName}`,
+    data: {},
+    method: 'get'
+  })
+}

BIN
src/assets/logo.png


+ 53 - 53
src/components/Cron/language/cn.js

@@ -1,54 +1,54 @@
 export default {
-    Seconds:{
-        name:'秒',
-        every:'每一秒钟',
-        interval:['每隔','秒执行 从','秒开始'],
-        specific:'具体秒数(可多选)',
-        cycle:['周期从','到','秒']
-    },
-    Minutes:{
-        name:'分',
-        every:'每一分钟',
-        interval:['每隔','分执行 从','分开始'],
-        specific:'具体分钟数(可多选)',
-        cycle:['周期从','到','分']
-    },
-    Hours:{
-        name:'时',
-        every:'每一小时',
-        interval:['每隔','小时执行 从','小时开始'],
-        specific:'具体小时数(可多选)',
-        cycle:['周期从','到','小时']
-    },
-    Day:{
-        name:'天',
-        every:'每一天',
-        intervalWeek:['每隔','周执行 从','开始'],
-        intervalDay:['每隔','天执行 从','天开始'],
-        specificWeek:'具体星期几(可多选)',
-        specificDay:'具体天数(可多选)',
-        lastDay:'在这个月的最后一天',
-        lastWeekday:'在这个月的最后一个工作日',
-        lastWeek:['在这个月的最后一个'],
-        beforeEndMonth:['在本月底前','天'],
-        nearestWeekday:['最近的工作日(周一至周五)至本月','日'],
-        someWeekday:['在这个月的第','个'],
-    },
-    Week:['天','一','二','三','四','五','六'].map(val=>'星期'+val),
-    Month:{
-        name:'月',
-        every:'每一月',
-        interval:['每隔','月执行 从','月开始'],
-        specific:'具体月数(可多选)',
-        cycle:['从','到','月之间的每个月']
-    },
-    Year:{
-        name:'年',
-        every:'每一年',
-        interval:['每隔','年执行 从','年开始'],
-        specific:'具体年份(可多选)',
-        cycle:['从','到','年之间的每一年']
-    },
-    Save:'保存',
-    Close:'关闭'
-}
+  Seconds: {
+    name: '秒',
+    every: '每一秒钟',
+    interval: ['每隔', '秒执行 从', '秒开始'],
+    specific: '具体秒数(可多选)',
+    cycle: ['周期从', '到', '秒']
+  },
+  Minutes: {
+    name: '分',
+    every: '每一分钟',
+    interval: ['每隔', '分执行 从', '分开始'],
+    specific: '具体分钟数(可多选)',
+    cycle: ['周期从', '到', '分']
+  },
+  Hours: {
+    name: '时',
+    every: '每一小时',
+    interval: ['每隔', '小时执行 从', '小时开始'],
+    specific: '具体小时数(可多选)',
+    cycle: ['周期从', '到', '小时']
+  },
+  Day: {
+    name: '天',
+    every: '每一天',
+    intervalWeek: ['每隔', '周执行 从', '开始'],
+    intervalDay: ['每隔', '天执行 从', '天开始'],
+    specificWeek: '具体星期几(可多选)',
+    specificDay: '具体天数(可多选)',
+    lastDay: '在这个月的最后一天',
+    lastWeekday: '在这个月的最后一个工作日',
+    lastWeek: ['在这个月的最后一个'],
+    beforeEndMonth: ['在本月底前', '天'],
+    nearestWeekday: ['最近的工作日(周一至周五)至本月', '日'],
+    someWeekday: ['在这个月的第', '个']
+  },
+  Week: ['天', '一', '二', '三', '四', '五', '六'].map(val => '星期' + val),
+  Month: {
+    name: '月',
+    every: '每一月',
+    interval: ['每隔', '月执行 从', '月开始'],
+    specific: '具体月数(可多选)',
+    cycle: ['从', '到', '月之间的每个月']
+  },
+  Year: {
+    name: '年',
+    every: '每一年',
+    interval: ['每隔', '年执行 从', '年开始'],
+    specific: '具体年份(可多选)',
+    cycle: ['从', '到', '年之间的每一年']
+  },
+  Save: '保存',
+  Close: '关闭'
+}

+ 53 - 53
src/components/Cron/language/en.js

@@ -1,54 +1,54 @@
 export default {
-    Seconds:{
-        name:'Seconds',
-        every:'Every second',
-        interval:['Every','second(s) starting at second'],
-        specific:'Specific second (choose one or many)',
-        cycle:['Every second between second','and second']
-    },
-    Minutes:{
-        name:'Minutes',
-        every:'Every minute',
-        interval:['Every','minute(s) starting at minute'],
-        specific:'Specific minute (choose one or many)',
-        cycle:['Every minute between minute','and minute']
-    },
-    Hours:{
-        name:'Hours',
-        every:'Every hour',
-        interval:['Every','hour(s) starting at hour'],
-        specific:'Specific hour (choose one or many)',
-        cycle:['Every hour between hour','and hour']
-    },
-    Day:{
-        name:'Day',
-        every:'Every day',
-        intervalWeek:['Every','day(s) starting on'],
-        intervalDay:['Every','day(s) starting at the','of the month'],
-        specificWeek:'Specific day of week (choose one or many)',
-        specificDay:'Specific day of month (choose one or many)',
-        lastDay:'On the last day of the month',
-        lastWeekday:'On the last weekday of the month',
-        lastWeek:['On the last',' of the month'],
-        beforeEndMonth:['day(s) before the end of the month'],
-        nearestWeekday:['Nearest weekday (Monday to Friday) to the','of the month'],
-        someWeekday:['On the','of the month'],
-    },
-    Week:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
-    Month:{
-        name:'Month',
-        every:'Every month',
-        interval:['Every','month(s) starting in'],
-        specific:'Specific month (choose one or many)',
-        cycle:['Every month between','and']
-    },
-    Year:{
-        name:'Year',
-        every:'Any year',
-        interval:['Every','year(s) starting in'],
-        specific:'Specific year (choose one or many)',
-        cycle:['Every year between','and']
-    },
-    Save:'Save',
-    Close:'Close'
-}
+  Seconds: {
+    name: 'Seconds',
+    every: 'Every second',
+    interval: ['Every', 'second(s) starting at second'],
+    specific: 'Specific second (choose one or many)',
+    cycle: ['Every second between second', 'and second']
+  },
+  Minutes: {
+    name: 'Minutes',
+    every: 'Every minute',
+    interval: ['Every', 'minute(s) starting at minute'],
+    specific: 'Specific minute (choose one or many)',
+    cycle: ['Every minute between minute', 'and minute']
+  },
+  Hours: {
+    name: 'Hours',
+    every: 'Every hour',
+    interval: ['Every', 'hour(s) starting at hour'],
+    specific: 'Specific hour (choose one or many)',
+    cycle: ['Every hour between hour', 'and hour']
+  },
+  Day: {
+    name: 'Day',
+    every: 'Every day',
+    intervalWeek: ['Every', 'day(s) starting on'],
+    intervalDay: ['Every', 'day(s) starting at the', 'of the month'],
+    specificWeek: 'Specific day of week (choose one or many)',
+    specificDay: 'Specific day of month (choose one or many)',
+    lastDay: 'On the last day of the month',
+    lastWeekday: 'On the last weekday of the month',
+    lastWeek: ['On the last', ' of the month'],
+    beforeEndMonth: ['day(s) before the end of the month'],
+    nearestWeekday: ['Nearest weekday (Monday to Friday) to the', 'of the month'],
+    someWeekday: ['On the', 'of the month']
+  },
+  Week: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+  Month: {
+    name: 'Month',
+    every: 'Every month',
+    interval: ['Every', 'month(s) starting in'],
+    specific: 'Specific month (choose one or many)',
+    cycle: ['Every month between', 'and']
+  },
+  Year: {
+    name: 'Year',
+    every: 'Any year',
+    interval: ['Every', 'year(s) starting in'],
+    specific: 'Specific year (choose one or many)',
+    cycle: ['Every year between', 'and']
+  },
+  Save: 'Save',
+  Close: 'Close'
+}

+ 3 - 3
src/components/Cron/language/index.js

@@ -2,6 +2,6 @@ import en from './en'
 import cn from './cn'
 
 export default {
-    en,
-    cn
-}
+  en,
+  cn
+}

+ 1 - 1
src/components/Table/index.js

@@ -159,7 +159,7 @@ export default {
           // console.log(r, 'rrrrrrrrrr')
           this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {
             current: r.pageNo, // 返回结果中的当前分页数
-            total: r.count, // 返回结果中的总记录数
+            total: Number(r.count), // 返回结果中的总记录数
             showSizeChanger: this.showSizeChanger,
             pageSize: (pagination && pagination.pageSize) ||
               this.localPagination.pageSize

+ 122 - 122
src/components/WEeditor/editor.vue

@@ -6,146 +6,146 @@
 </template>
 
 <script>
-  import Editor from 'wangeditor'
-  import 'wangeditor/release/wangEditor.min.css'
-  import { uploadImgOnce } from '@/api/data'
-  import { oneOf } from '@/utils/util'
+import Editor from 'wangeditor'
+import 'wangeditor/release/wangEditor.min.css'
+import { uploadImgOnce } from '@/api/data'
+import { oneOf } from '@/utils/util'
 
-  export default {
-    name: 'Editor',
+export default {
+  name: 'Editor',
 
-    props: {
-      value: {
-        type: String,
-        default: ''
-      },
-      /**
+  props: {
+    value: {
+      type: String,
+      default: ''
+    },
+    /**
        * 绑定的值的类型, enum: ['html', 'text']
        */
-      valueType: {
-        type: String,
-        default: 'html',
-        validator: (val) => {
-          return oneOf(val, ['html', 'text'])
-        }
-      },
-      /**
+    valueType: {
+      type: String,
+      default: 'html',
+      validator: (val) => {
+        return oneOf(val, ['html', 'text'])
+      }
+    },
+    /**
        * @description 设置change事件触发时间间隔
        */
-      changeInterval: {
-        type: Number,
-        default: 200
-      },
-      /**
+    changeInterval: {
+      type: Number,
+      default: 200
+    },
+    /**
        * @description 是否开启本地存储
        */
-      cache: {
-        type: Boolean,
-        default: true
-      }
+    cache: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    editorId () {
+      return `editor${this._uid}`
+    }
+  },
+  methods: {
+    setHtml (val) {
+      this.editor.txt.html(val)
+    },
+	  getTxt () {
+      return this.editor.txt.text()
+	  },
+    getEdior () {
+      return new Editor(`#${this.editorId}`)
+    },
+    clearText () {
+      this.editor.txt.clear()
     },
-    computed: {
-      editorId () {
-        return `editor${this._uid}`
+    randomStr (len) {
+      len = len || 32
+      const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
+      const maxPos = chars.length
+      let pwd = ''
+      for (let i = 0; i < len; i++) {
+        pwd += chars.charAt(Math.floor(Math.random() * maxPos))
       }
+      return pwd
     },
-    methods: {
-      setHtml (val) {
-        this.editor.txt.html(val)
+    createFileName (filename) {
+      const pos = filename.lastIndexOf('.')
+      const suffix = filename.substring(pos)
+      return this.randomStr(20) + suffix
+    }
+
+  },
+  mounted () {
+    const _this = this
+    this.editor = new Editor(`#${this.editorId}`)
+    this.editor.customConfig.zIndex = 100
+    this.editor.customConfig.onchange = (html) => {
+      const text = this.editor.txt.text()
+      if (this.cache) localStorage.editorCache = html
+      this.$emit('input', this.valueType === 'html' ? html : text)
+      this.$emit('on-change', html, text)
+    }
+    this.editor.customConfig.onchangeTimeout = this.changeInterval
+    this.editor.customConfig.uploadImgServer = process.env.VUE_APP_API_BASE_URL + '/upload'
+    this.editor.customConfig.uploadFileName = 'file'
+    this.editor.customConfig.uploadImgParams = {
+      savePathType: 'ali'
+    }
+    this.editor.customConfig.uploadImgHooks = {
+      before: function (xhr, editor, files) {
+        console.log(xhr, editor, files)
+        // 图片上传之前触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
+
+        // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
+        // return {
+        //     prevent: true,
+        //     msg: '放弃上传'
+        // }
       },
-	  getTxt () {
-		return this.editor.txt.text()
-	  },
-      getEdior () {
-        return new Editor(`#${this.editorId}`)
+      success: function (xhr, editor, result) {
+        console.log(xhr, editor, result)
+        // 图片上传并返回结果,图片插入成功之后触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
       },
-      clearText () {
-        this.editor.txt.clear()
+      fail: function (xhr, editor, result) {
+        console.log(xhr, editor, result)
+        // 图片上传并返回结果,但图片插入错误时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
       },
-      randomStr (len) {
-        len = len || 32
-        let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
-        let maxPos = chars.length
-        let pwd = ''
-        for (let i = 0; i < len; i++) {
-          pwd += chars.charAt(Math.floor(Math.random() * maxPos))
-        }
-        return pwd
+      error: function (xhr, editor) {
+        console.log(xhr, editor)
+        // 图片上传出错时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
       },
-      createFileName (filename) {
-        let pos = filename.lastIndexOf('.')
-        let suffix = filename.substring(pos)
-        return this.randomStr(20) + suffix
-      }
-
-    },
-    mounted () {
-      let _this = this
-      this.editor = new Editor(`#${this.editorId}`)
-      this.editor.customConfig.zIndex = 100
-      this.editor.customConfig.onchange = (html) => {
-        let text = this.editor.txt.text()
-        if (this.cache) localStorage.editorCache = html
-        this.$emit('input', this.valueType === 'html' ? html : text)
-        this.$emit('on-change', html, text)
-      }
-      this.editor.customConfig.onchangeTimeout = this.changeInterval
-      this.editor.customConfig.uploadImgServer = process.env.VUE_APP_API_BASE_URL + '/upload'
-      this.editor.customConfig.uploadFileName = 'file'
-      this.editor.customConfig.uploadImgParams = {
-          savePathType: 'ali'
+      timeout: function (xhr, editor) {
+        // 图片上传超时时触发
+        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
+      },
+      // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
+      // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
+      customInsert: function (insertImg, result, editor) {
+        // console.log(insertImg, result, editor)
+        // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+        // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+        // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+        insertImg(result.data)
+        // result 必须是一个 JSON 格式字符串!!!否则报错
       }
-      this.editor.customConfig.uploadImgHooks = {
-          before: function (xhr, editor, files) {
-              console.log(xhr, editor, files)
-              // 图片上传之前触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
-              
-              // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传
-              // return {
-              //     prevent: true,
-              //     msg: '放弃上传'
-              // }
-          },
-          success: function (xhr, editor, result) {
-            console.log(xhr, editor, result)
-              // 图片上传并返回结果,图片插入成功之后触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
-          },
-          fail: function (xhr, editor, result) {
-              console.log(xhr, editor, result)
-              // 图片上传并返回结果,但图片插入错误时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
-          },
-          error: function (xhr, editor) {
-               console.log(xhr, editor)
-              // 图片上传出错时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
-          },
-          timeout: function (xhr, editor) {
-              // 图片上传超时时触发
-              // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
-          },
-          // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
-          // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
-          customInsert: function (insertImg, result, editor) {
-              // console.log(insertImg, result, editor)
-              // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
-              // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
-              // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
-              insertImg(result.data)
-              // result 必须是一个 JSON 格式字符串!!!否则报错
-          }
-        }
-
-      // create这个方法一定要在所有配置项之后调用
-      this.editor.create()
-      this.editor.txt.clear()
-      // 如果本地有存储加载本地存储内容
-      let html = this.value || localStorage.editorCache
-      if (html) this.editor.txt.html(html)
     }
+
+    // create这个方法一定要在所有配置项之后调用
+    this.editor.create()
+    this.editor.txt.clear()
+    // 如果本地有存储加载本地存储内容
+    const html = this.value || localStorage.editorCache
+    if (html) this.editor.txt.html(html)
   }
+}
 </script>
 
 <style lang="less">

+ 18 - 0
src/components/global.less

@@ -501,3 +501,21 @@ body {
     }
   }
 }
+
+/* 表格操作按钮样式 */
+  td .actionBtn {
+    font-size: 20px;
+    padding: 0 10px;
+  }
+  td .icon-blues {
+  	color: #1890FF;
+  }
+  td .icon-green {
+  	color: #16b50e;
+  }
+  td .icon-red {
+  	color: red;
+  }
+  td .icon-orange {
+  	color: #ffaa00;
+  }

+ 1 - 1
src/config/defaultSettings.js

@@ -14,7 +14,7 @@
  */
 
 export default {
-  primaryColor: '#52C41A', // primary color of ant design
+  primaryColor: '#1890FF', // primary color of ant design
   navTheme: 'dark', // theme for nav menu
   layout: 'sidemenu', // nav menu position: sidemenu or topmenu
   contentWidth: 'Fixed', // layout of content: Fluid or Fixed, only works when layout is topmenu

+ 117 - 54
src/config/router.config.js

@@ -9,7 +9,7 @@ export const asyncRouterMap = [{
   name: 'index',
   component: BasicLayout,
   meta: {
-    title: '首页'
+    title: '运营平台'
   },
   redirect: '/home',
   children: [{
@@ -29,17 +29,80 @@ export const asyncRouterMap = [{
       meta: {
         title: '首页',
         icon: 'home',
-        hidden: true
+        hiddenHeaderContent: true
+      }
+    }]
+  },
+  {
+    path: '/changePwd',
+    name: 'changePwd',
+    hidden: true,
+    component: () => import(/* webpackChunkName: "changePwd" */ '@/views/user/ChangePwd'),
+    meta: {
+      title: '修改密码',
+      icon: 'home'
+    }
+  },
+  // 考评管理
+  {
+    path: '/evaluation',
+    redirect: '/evaluation/evaluationItem',
+    component: PageView,
+    meta: {
+      title: '考评管理',
+      icon: 'block',
+      permission: 'M_evaluation_0'
+    },
+    children: [{
+      path: '/evaluation/evaluationItem',
+      name: 'EvaluationItem',
+      component: () => import(/* webpackChunkName: "evaluation" */
+        '@/views/evaluation/evaluationItem/EvaluationItem.vue'),
+      meta: {
+        title: '考评项目',
+        icon: 'save',
+        permission: 'M_evaluationItem_list'
+      }
+    }, {
+      path: '/evaluation/evaluationPlan',
+      name: 'EvaluationPlan',
+      component: () => import(/* webpackChunkName: "evaluation" */
+        '@/views/evaluation/evaluationPlan/EvaluationPlan.vue'),
+      meta: {
+        title: '考评方案',
+        icon: 'switcher',
+        permission: 'M_evaluationPlan_list'
+      }
+    }]
+  },
+  // 基础设置 BasicSettings
+  {
+    path: '/BasicSettings',
+    redirect: '/BasicSettings/Organization',
+    component: PageView,
+    meta: {
+      title: '基础设置',
+      icon: 'apartment',
+      permission: 'M_basicSettings_0'
+    },
+    children: [{
+      path: '/BasicSettings/Organization',
+      name: 'Organization',
+      component: () => import(/* webpackChunkName: "auth" */ '@/views/BasicSettings/Organization.vue'),
+      meta: {
+        title: '组织机构',
+        icon: 'user',
+        permission: 'M_basicSettings_organization'
       }
     },
     {
-      path: '/changePwd',
-      name: 'changePwd',
-      component: () => import(/* webpackChunkName: "home" */ '@/views/user/ChangePwd'),
+      path: '/BasicSettings/StoreManagement',
+      name: 'StoreManagement',
+      component: () => import(/* webpackChunkName: "auth" */ '@/views/BasicSettings/StoreManagement.vue'),
       meta: {
-        title: '修改密码',
-        icon: 'home',
-        hidden: true
+        title: '门店管理',
+        icon: 'user',
+        permission: 'M_basicSettings_store'
       }
     }
     ]
@@ -50,64 +113,64 @@ export const asyncRouterMap = [{
     component: PageView,
     meta: {
       title: '运营权限管理',
-      icon: 'apartment',
-      permission: 'M_yyAuth_0'
+      icon: 'wallet',
+      permission: 'M_power_0'
     },
-    children: [
-      {
-        path: '/auth/userList',
-        name: 'powerUserList',
-        component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
-        meta: {
-          title: '用户管理',
-          icon: 'user',
-          permission: 'M_auth_yyUser'
-        }
-      },
-      {
-        path: '/auth/roleList',
-        name: 'powerRoleList',
-        component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
-        meta: {
-          title: '角色管理',
-          icon: 'solution',
-          permission: 'M_auth_yyRole'
-        }
+    children: [{
+      path: '/auth/userList',
+      name: 'powerUserList',
+      component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
+      meta: {
+        title: '用户管理',
+        icon: 'user',
+        permission: 'M_power_user'
+      }
+    },
+    {
+      path: '/auth/roleList',
+      name: 'powerRoleList',
+      component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
+      meta: {
+        title: '角色管理',
+        icon: 'solution',
+        permission: 'M_power_role'
       }
+    }
     ]
   },
   {
-    path: '/CardVoucherAuth',
-    redirect: '/CardVoucherAuth/userList',
+    path: '/SupervisionAuth',
+    redirect: '/SupervisionAuth/userList',
     component: PageView,
     meta: {
       title: '督导权限管理',
       icon: 'wallet',
-      permission: 'M_kqAuth_0'
+      permission: 'M_supervision_0'
+    },
+    children: [{
+      path: '/SupervisionAuth/userList',
+      name: 'SupervisionUserList',
+      component: () => import(/* webpackChunkName: "CardVoucherAuth" */
+        '@/views/SupervisionAuth/user/userList.vue'),
+      meta: {
+        title: '用户管理',
+        icon: 'user',
+        permission: 'M_supervision_user'
+      }
     },
-    children: [
-      {
-        path: '/CardVoucherAuth/userList',
-        name: 'CardUserList',
-        component: () => import(/* webpackChunkName: "CardVoucherAuth" */ '@/views/CardVoucherAuth/user/userList.vue'),
-        meta: {
-          title: '用户管理',
-          icon: 'user',
-          permission: 'M_auth_kqUser'
-        }
-      },
-      {
-        path: '/CardVoucherAuth/roleList',
-        name: 'CardRoleList',
-        component: () => import(/* webpackChunkName: "CardVoucherAuth" */ '@/views/CardVoucherAuth/role/roleList.vue'),
-        meta: {
-          title: '角色管理',
-          icon: 'solution',
-          permission: 'M_auth_kqRole'
-        }
+    {
+      path: '/SupervisionAuth/roleList',
+      name: 'SupervisionRoleList',
+      component: () => import(/* webpackChunkName: "CardVoucherAuth" */
+        '@/views/SupervisionAuth/role/roleList.vue'),
+      meta: {
+        title: '角色管理',
+        icon: 'solution',
+        permission: 'M_supervision_role'
       }
+    }
     ]
-  },
+  }
   ]
 },
 {

+ 1 - 1
src/core/directives/hasPermission.js

@@ -16,7 +16,7 @@ import store from '@/store'
  */
 const hasPermission = Vue.directive('hasPermission', {
   inserted: function (el, binding, vnode) {
-    console.log(binding.value)
+    // console.log(binding.value)
     const roles = store.getters.roles
     const permissionList = roles.permissionList
     if (!permissionList.includes(binding.value)) {

+ 2 - 2
src/layouts/BasicLayout.vue

@@ -110,9 +110,9 @@ export default {
     }
   },
   created () {
-    if(this.mainMenu){
+    if (this.mainMenu) {
       this.menus = this.mainMenu.find((item) => item.path === '/').children
-    }else{
+    } else {
       // 没有权限时只显示首页
       const noqx = asyncRouterMap.find((item) => item.path === '/').children
       this.menus = [noqx.find(item => item.path === '/home')]

+ 2 - 2
src/layouts/UserLayout.vue

@@ -1,6 +1,6 @@
 <template>
   <div id="userLayout" :class="['user-layout-wrapper', device]">
-    <canvas id='canvas'></canvas>
+    <canvas id="canvas"></canvas>
     <div class="container">
       <div class="top">
         <div class="header">
@@ -10,7 +10,7 @@
           </a>
         </div>
         <div class="desc">
-          {{title}}
+          {{ title }}
         </div>
       </div>
 

+ 61 - 61
src/libs/getDate.js

@@ -1,65 +1,65 @@
 // 引入 moment 时间插件
-import moment from "moment";
-//获取今日/昨日/本周/上周/本月/上月 时间
+import moment from 'moment'
+// 获取今日/昨日/本周/上周/本月/上月 时间
 export default {
-    // 获取今日的开始结束时间
-    getToday() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().startOf("day").valueOf()).format("YYYY-MM-DD");
-        obj.endtime = moment(moment().valueOf()).format("YYYY-MM-DD");
-        return obj
-    },
-    // 获取昨日的开始结束时间
-    getYesterday() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().add(-1, 'days').startOf("day").valueOf()).format("YYYY-MM-DD");
-        obj.endtime = moment(moment().add(-1, 'days').endOf('day').valueOf()).format('YYYY-MM-DD');
-        return obj
-    },
-    // 获取当前周的开始结束时间
-    getCurrWeekDays() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().week(moment().week()).startOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
-        obj.endtime = moment(moment().week(moment().week()).endOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD');
-        return obj
-    },
-    // 获取上一周的开始结束时间
-    getLastWeekDays() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().week(moment().week() - 1).startOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
-        obj.endtime = moment(moment().week(moment().week() - 1).endOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD');
-        return obj
-    },
-    // 获取当前月的开始结束时间
-    getCurrMonthDays() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().month(moment().month()).startOf('month').valueOf()).format('YYYY-MM-DD');
-        obj.endtime = moment(moment().month(moment().month()).endOf('month').valueOf()).format('YYYY-MM-DD');
-        return obj
-    },
-    // 获取上一个月的开始结束时间
-    getLastMonthDays() {
-        let obj = {
-            starttime: '',
-            endtime: ''
-        }
-        obj.starttime = moment(moment().month(moment().month() - 1).startOf('month').valueOf()).format('YYYY-MM-DD');
-        obj.endtime = moment(moment().month(moment().month() - 1).endOf('month').valueOf()).format('YYYY-MM-DD');
-        return obj
+  // 获取今日的开始结束时间
+  getToday () {
+    const obj = {
+      starttime: '',
+      endtime: ''
     }
+    obj.starttime = moment(moment().startOf('day').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().valueOf()).format('YYYY-MM-DD')
+    return obj
+  },
+  // 获取昨日的开始结束时间
+  getYesterday () {
+    const obj = {
+      starttime: '',
+      endtime: ''
+    }
+    obj.starttime = moment(moment().add(-1, 'days').startOf('day').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().add(-1, 'days').endOf('day').valueOf()).format('YYYY-MM-DD')
+    return obj
+  },
+  // 获取当前周的开始结束时间
+  getCurrWeekDays () {
+    const obj = {
+      starttime: '',
+      endtime: ''
+    }
+    obj.starttime = moment(moment().week(moment().week()).startOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().week(moment().week()).endOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
+    return obj
+  },
+  // 获取上一周的开始结束时间
+  getLastWeekDays () {
+    const obj = {
+      starttime: '',
+      endtime: ''
+    }
+    obj.starttime = moment(moment().week(moment().week() - 1).startOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().week(moment().week() - 1).endOf('week').add(1, 'days').valueOf()).format('YYYY-MM-DD')
+    return obj
+  },
+  // 获取当前月的开始结束时间
+  getCurrMonthDays () {
+    const obj = {
+      starttime: '',
+      endtime: ''
+    }
+    obj.starttime = moment(moment().month(moment().month()).startOf('month').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().month(moment().month()).endOf('month').valueOf()).format('YYYY-MM-DD')
+    return obj
+  },
+  // 获取上一个月的开始结束时间
+  getLastMonthDays () {
+    const obj = {
+      starttime: '',
+      endtime: ''
+    }
+    obj.starttime = moment(moment().month(moment().month() - 1).startOf('month').valueOf()).format('YYYY-MM-DD')
+    obj.endtime = moment(moment().month(moment().month() - 1).endOf('month').valueOf()).format('YYYY-MM-DD')
+    return obj
+  }
 }

+ 22 - 18
src/main.js

@@ -8,39 +8,43 @@ import store from './store/'
 import { VueAxios } from './utils/request'
 
 // mock
-//import './mock'
+// import './mock'
 
 import bootstrap from './core/bootstrap'
 import './core/use'
 import './permission' // permission control
-import './utils/filter' // global filter
+import './utils/filter'
+
+import VueCookies from 'vue-cookies' // global filter
 
 Vue.config.productionTip = false
 
 // mount axios Vue.$http and this.$http
 Vue.use(VueAxios)
-
-import VueCookies from 'vue-cookies'
 Vue.use(VueCookies)
 Vue.$cookies.config('7d')
 /**
  * 权限检查
  */
 Vue.prototype.$hasPermissions = function (value) {
- let isExist = false;
- const roles = store.getters.roles
- const permissionList = roles.permissionList
- //console.log(permissionsStr,'permissionsStr')
- if (permissionList == undefined || permissionList == null) {
-  return false;
- }
- let has = permissionList.find(item => {
-   return item == value
- })
- if (has) {
-  isExist = true;
- }
- return isExist;
+  let isExist = false
+  const roles = store.getters.roles
+  const permissionList = roles.permissionList
+  // console.log(permissionsStr,'permissionsStr')
+  if (permissionList == undefined || permissionList == null) {
+    return false
+  }
+  const has = permissionList.find(item => {
+    return item == value
+  })
+  if (has) {
+    isExist = true
+  }
+  return isExist
+}
+// 禁止输入框输入空格,换行符,<,>
+Vue.prototype.$filterEmpty = function (e) {
+  return e.target.value.replace(/\s|\r\n|\n|<|>/g, '')
 }
 new Vue({
   router,

+ 2 - 2
src/permission.js

@@ -27,7 +27,7 @@ router.beforeEach((to, from, next) => {
       NProgress.done()
     } else {
       const userInfo = Vue.ls.get('userName')
-      // console.log(userInfo)
+      console.log(userInfo)
       if (userInfo) {
         store.dispatch('SetInfo', userInfo)
       } else {
@@ -41,7 +41,7 @@ router.beforeEach((to, from, next) => {
           .dispatch('GetInfo', token)
           .then(res => {
             const roles = res
-            // console.log(roles, 'roles')
+            console.log(roles, 'roles')
             if (roles.permissionList.length == 0 || !roles) {
               store.dispatch('Logout').then(() => {
                 store.dispatch('ResetRoutes').then(() => {

+ 20 - 14
src/store/modules/user.js

@@ -39,22 +39,28 @@ const user = {
     Login ({ commit }, userInfo) {
       console.log(userInfo, 'userInfo----')
       return new Promise((resolve, reject) => {
-        login(userInfo).then(res => {
-          console.log(res, 'login success')
-          if (res && res.userid) {
-            Vue.ls.set('hasError', 0)
-            commit('SET_TOKEN', res.userid)
-            commit('SET_NAME', { name: res.userNameCN, welcome: welcome() })
-            commit('SET_AVATAR', res.avatar ? res.avatar : '')
-            Vue.ls.set('rolesAccess', { permissionList: res.permCodes }, 7 * 24 * 60 * 60 * 1000)
-            // 记住密码
-            if (userInfo.rememberMe) {
-              VueCookies.set('REMEMBER_ME', JSON.stringify(userInfo))
-            } else {
-              VueCookies.remove('REMEMBER_ME')
+        login(userInfo).then(ret => {
+          console.log(ret, 'login success')
+          if (ret.status == 200) {
+            const res = ret.data
+            if (res.access_token && res.auth_user) {
+              const users = res.auth_user
+              Vue.ls.set('hasError', 0)
+              commit('SET_TOKEN', res.access_token)
+              commit('SET_NAME', { name: users.userNameCN, welcome: welcome() })
+              Vue.ls.set('rolesAccess', { permissionList: users.permCodes }, 7 * 24 * 60 * 60 * 1000)
+              commit('SET_AVATAR', res.avatar ? res.avatar : '')
+              // 记住密码
+              if (userInfo.rememberMe) {
+                VueCookies.set('REMEMBER_ME', JSON.stringify(userInfo))
+              } else {
+                VueCookies.remove('REMEMBER_ME')
+              }
             }
+            resolve(res)
+          } else {
+            reject(ret)
           }
-          resolve()
         }).catch(error => {
           reject(error)
         })

+ 105 - 107
src/utils/bg/bg.js

@@ -1,148 +1,146 @@
-export function bgStart(){
+export function bgStart () {
   // Little Canvas things
-  var canvas = document.querySelector("#canvas"),
-      ctx = canvas.getContext('2d');
-  
+  var canvas = document.querySelector('#canvas')
+  var ctx = canvas.getContext('2d')
+
   // Set Canvas to be window size
-  canvas.width = window.innerWidth;
-  canvas.height = window.innerHeight;
-  
+  canvas.width = window.innerWidth
+  canvas.height = window.innerHeight
+
   // Configuration, Play with these
   var config = {
     particleNumber: 800,
     maxParticleSize: 10,
     maxSpeed: 40,
     colorVariation: 50
-  };
-  
+  }
+
   // Colors
   var colorPalette = {
-      bg: {r:12,g:9,b:29},
-      matter: [
-        {r:36,g:18,b:42}, // darkPRPL
-        {r:78,g:36,b:42}, // rockDust
-        {r:252,g:178,b:96}, // solorFlare
-        {r:253,g:238,b:152} // totesASun
-      ]
-  };
-  
+    bg: { r: 12, g: 9, b: 29 },
+    matter: [
+      { r: 36, g: 18, b: 42 }, // darkPRPL
+      { r: 78, g: 36, b: 42 }, // rockDust
+      { r: 252, g: 178, b: 96 }, // solorFlare
+      { r: 253, g: 238, b: 152 } // totesASun
+    ]
+  }
+
   // Some Variables hanging out
-  var particles = [],
-      centerX = canvas.width / 2,
-      centerY = canvas.height / 2,
-      drawBg,
-  
+  var particles = []
+  var centerX = canvas.width / 2
+  var centerY = canvas.height / 2
+  var drawBg
+
   // Draws the background for the canvas, because space
-  drawBg = function (ctx, color) {
-      ctx.fillStyle = "rgb(" + color.r + "," + color.g + "," + color.b + ")";
-      ctx.fillRect(0,0,canvas.width,canvas.height);
-  };
-  
+  var drawBg = function (ctx, color) {
+    ctx.fillStyle = 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')'
+    ctx.fillRect(0, 0, canvas.width, canvas.height)
+  }
+
   // Particle Constructor
   var Particle = function (x, y) {
-      // X Coordinate
-      this.x = x || Math.round(Math.random() * canvas.width);
-      // Y Coordinate
-      this.y = y || Math.round(Math.random() * canvas.height);
-      // Radius of the space dust
-      this.r = Math.ceil(Math.random() * config.maxParticleSize);
-      // Color of the rock, given some randomness
-      this.c = colorVariation(colorPalette.matter[Math.floor(Math.random() * colorPalette.matter.length)],true );
-      // Speed of which the rock travels
-      this.s = Math.pow(Math.ceil(Math.random() * config.maxSpeed), .7);
-      // Direction the Rock flies
-      this.d = Math.round(Math.random() * 360);
-  };
-  
+    // X Coordinate
+    this.x = x || Math.round(Math.random() * canvas.width)
+    // Y Coordinate
+    this.y = y || Math.round(Math.random() * canvas.height)
+    // Radius of the space dust
+    this.r = Math.ceil(Math.random() * config.maxParticleSize)
+    // Color of the rock, given some randomness
+    this.c = colorVariation(colorPalette.matter[Math.floor(Math.random() * colorPalette.matter.length)], true)
+    // Speed of which the rock travels
+    this.s = Math.pow(Math.ceil(Math.random() * config.maxSpeed), 0.7)
+    // Direction the Rock flies
+    this.d = Math.round(Math.random() * 360)
+  }
+
   // Provides some nice color variation
   // Accepts an rgba object
   // returns a modified rgba object or a rgba string if true is passed in for argument 2
   var colorVariation = function (color, returnString) {
-      var r,g,b,a, variation;
-      r = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation/2)) + color.r);
-      g = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation/2)) + color.g);
-      b = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation/2)) + color.b);
-      a = Math.random() + .5;
-      if (returnString) {
-          return "rgba(" + r + "," + g + "," + b + "," + a + ")";
-      } else {
-          return {r,g,b,a};
-      }
-  };
-  
+    var r, g, b, a, variation
+    r = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation / 2)) + color.r)
+    g = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation / 2)) + color.g)
+    b = Math.round(((Math.random() * config.colorVariation) - (config.colorVariation / 2)) + color.b)
+    a = Math.random() + 0.5
+    if (returnString) {
+      return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'
+    } else {
+      return { r, g, b, a }
+    }
+  }
+
   // Used to find the rocks next point in space, accounting for speed and direction
   var updateParticleModel = function (p) {
-      var a = 180 - (p.d + 90); // find the 3rd angle
-      p.d > 0 && p.d < 180 ? p.x += p.s * Math.sin(p.d) / Math.sin(p.s) : p.x -= p.s * Math.sin(p.d) / Math.sin(p.s);
-      p.d > 90 && p.d < 270 ? p.y += p.s * Math.sin(a) / Math.sin(p.s) : p.y -= p.s * Math.sin(a) / Math.sin(p.s);
-      return p;
-  };
-  
+    var a = 180 - (p.d + 90) // find the 3rd angle
+    p.d > 0 && p.d < 180 ? p.x += p.s * Math.sin(p.d) / Math.sin(p.s) : p.x -= p.s * Math.sin(p.d) / Math.sin(p.s)
+    p.d > 90 && p.d < 270 ? p.y += p.s * Math.sin(a) / Math.sin(p.s) : p.y -= p.s * Math.sin(a) / Math.sin(p.s)
+    return p
+  }
+
   // Just the function that physically draws the particles
   // Physically? sure why not, physically.
   var drawParticle = function (x, y, r, c) {
-      ctx.beginPath();
-      ctx.fillStyle = c;
-      ctx.arc(x, y, r, 0, 2*Math.PI, false);
-      ctx.fill();
-      ctx.closePath();
-  };
-  
+    ctx.beginPath()
+    ctx.fillStyle = c
+    ctx.arc(x, y, r, 0, 2 * Math.PI, false)
+    ctx.fill()
+    ctx.closePath()
+  }
+
   // Remove particles that aren't on the canvas
   var cleanUpArray = function () {
-      particles = particles.filter((p) => { 
-        return (p.x > -100 && p.y > -100); 
-      });
-  };
-  
-  
+    particles = particles.filter((p) => {
+      return (p.x > -100 && p.y > -100)
+    })
+  }
+
   var initParticles = function (numParticles, x, y) {
-      for (let i = 0; i < numParticles; i++) {
-          particles.push(new Particle(x, y));
-      }
-      particles.forEach((p) => {
-          drawParticle(p.x, p.y, p.r, p.c);
-      });
-  };
-  
+    for (let i = 0; i < numParticles; i++) {
+      particles.push(new Particle(x, y))
+    }
+    particles.forEach((p) => {
+      drawParticle(p.x, p.y, p.r, p.c)
+    })
+  }
+
   // That thing
-  window.requestAnimFrame = (function() {
+  window.requestAnimFrame = (function () {
     return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
-       function(callback) {
-          window.setTimeout(callback, 1000 / 60);
-       };
-  })();
-  
-  
+       function (callback) {
+         window.setTimeout(callback, 1000 / 60)
+       }
+  })()
+
   // Our Frame function
   var frame = function () {
     // Draw background first
-    drawBg(ctx, colorPalette.bg);
+    drawBg(ctx, colorPalette.bg)
     // Update Particle models to new position
     particles.map((p) => {
-      return updateParticleModel(p);
-    });
+      return updateParticleModel(p)
+    })
     // Draw em'
     particles.forEach((p) => {
-        drawParticle(p.x, p.y, p.r, p.c);
-    });
+      drawParticle(p.x, p.y, p.r, p.c)
+    })
     // Play the same song? Ok!
-    window.requestAnimFrame(frame);
-  };
-  
+    window.requestAnimFrame(frame)
+  }
+
   // Click listener
-  document.body.addEventListener("click", function (event) {
-      var x = event.clientX,
-          y = event.clientY;
-      cleanUpArray();
-      initParticles(config.particleNumber, x, y);
-  });
-  
+  document.body.addEventListener('click', function (event) {
+    var x = event.clientX
+    var y = event.clientY
+    cleanUpArray()
+    initParticles(config.particleNumber, x, y)
+  })
+
   // First Frame
-  frame();
-  
+  frame()
+
   // First particle explosion
-  initParticles(config.particleNumber);
-}
+  initParticles(config.particleNumber)
+}

+ 134 - 134
src/utils/bg/bg1.js

@@ -1,188 +1,188 @@
-export function bgStart(){
+export function bgStart () {
   /*
   (Book REF) HTML5 Canvas Ch. 5:  Math, Physics, and Animation ::: Uniform Circular Motion
   By Steve Fulton and Jeff Fulton
   */
-  window.requestAnimFrame = (function() {
+  window.requestAnimFrame = (function () {
     return window.requestAnimationFrame ||
       window.webkitRequestAnimationFrame ||
       window.mozRequestAnimationFrame ||
       window.oRequestAnimationFrame ||
       window.msRequestAnimationFrame ||
-      function(callback) {
-        window.setTimeout(callback, 1000 / 60);
-      };
-  })();
- 
-  var c,
-  $,
-  w,
-  h,
-  msX,
-  msY,
-  midX,
-  midY,
-  num = 650,
-  parts = [],
-  begin = 50,
-  repeat = 20,
-  end = Math.PI * 2,
-  flow,
-  force = null,
-  msdn = false;
-  
-  function start() {
-    c = document.getElementById('canvas');
-    $ = c.getContext('2d');
-    w = c.width = window.innerWidth;
-    h = c.height = window.innerHeight;
-    midX = w / 2;
-    midY = h / 2;
-    force = Math.max(w, h) * 0.09;
-    flow = begin;
-  
-    window.requestAnimFrame(create);
-    run();
+      function (callback) {
+        window.setTimeout(callback, 1000 / 60)
+      }
+  })()
+
+  var c
+  var $
+  var w
+  var h
+  var msX
+  var msY
+  var midX
+  var midY
+  var num = 650
+  var parts = []
+  var begin = 50
+  var repeat = 20
+  var end = Math.PI * 2
+  var flow
+  var force = null
+  var msdn = false
+
+  function start () {
+    c = document.getElementById('canvas')
+    $ = c.getContext('2d')
+    w = c.width = window.innerWidth
+    h = c.height = window.innerHeight
+    midX = w / 2
+    midY = h / 2
+    force = Math.max(w, h) * 0.09
+    flow = begin
+
+    window.requestAnimFrame(create)
+    run()
   }
-  
-  function run() {
-    window.requestAnimFrame(run);
-    go();
+
+  function run () {
+    window.requestAnimFrame(run)
+    go()
   }
-  
-  function Part() {
-    this.deg = 0;
-    this.rad = 0;
-    this.x = 0;
-    this.y = 0;
-    this.distX = 0;
-    this.distY = 0;
-    this.color = 'rgb(' + Math.floor(Math.random() * 130) + ',' + Math.floor(Math.random() * 50) + ',' + Math.floor(Math.random() * 100) + ')';
-    this.size;
+
+  function Part () {
+    this.deg = 0
+    this.rad = 0
+    this.x = 0
+    this.y = 0
+    this.distX = 0
+    this.distY = 0
+    this.color = 'rgb(' + Math.floor(Math.random() * 130) + ',' + Math.floor(Math.random() * 50) + ',' + Math.floor(Math.random() * 100) + ')'
+    this.size
   }
-  
-  function create() {
-    var n = num;
+
+  function create () {
+    var n = num
     while (n--) {
-      var p = new Part();
-      p.deg = Math.floor(Math.random() * 360);
-      p.rad = Math.floor(Math.random() * w * 0.5);
-      p.x = p.distX = Math.floor(Math.random() * w);
-      p.y = p.distY = Math.floor(Math.random() * h);
-      p.size = 1 + Math.floor(Math.random() * (p.rad * 0.055));
-      parts[n] = p;
+      var p = new Part()
+      p.deg = Math.floor(Math.random() * 360)
+      p.rad = Math.floor(Math.random() * w * 0.5)
+      p.x = p.distX = Math.floor(Math.random() * w)
+      p.y = p.distY = Math.floor(Math.random() * h)
+      p.size = 1 + Math.floor(Math.random() * (p.rad * 0.055))
+      parts[n] = p
     }
-    c.onmousemove = msmv;
-    c.onmousedown = msdn;
-    c.onmouseup = msup;
-  
-    var int = setInterval(function() {
-      flow--;
-      if (flow === repeat) clearInterval(int);
-    }, 20);
+    c.onmousemove = msmv
+    c.onmousedown = msdn
+    c.onmouseup = msup
+
+    var int = setInterval(function () {
+      flow--
+      if (flow === repeat) clearInterval(int)
+    }, 20)
   }
-  
-  function go() {
-    $.globalCompositeOperation = 'source-over';
-    $.fillStyle = 'hsla(242, 30%, 5%, .55)';
-    $.fillRect(0, 0, w, h);
-    $.globalCompositeOperation = 'lighter';
-    var mx = msX;
-    var my = msY;
-    var bounds = force;
+
+  function go () {
+    $.globalCompositeOperation = 'source-over'
+    $.fillStyle = 'hsla(242, 30%, 5%, .55)'
+    $.fillRect(0, 0, w, h)
+    $.globalCompositeOperation = 'lighter'
+    var mx = msX
+    var my = msY
+    var bounds = force
     if (msdn) {
-      bounds = force * 2;
+      bounds = force * 2
     }
-    var n = num;
+    var n = num
     while (n--) {
-      var p = parts[n];
-      var radi = Math.PI / 180 * p.deg;
-      p.distX = midX + p.rad * Math.cos(radi);
-      p.distY = midY + p.rad * Math.sin(radi) * 0.4;
+      var p = parts[n]
+      var radi = Math.PI / 180 * p.deg
+      p.distX = midX + p.rad * Math.cos(radi)
+      p.distY = midY + p.rad * Math.sin(radi) * 0.4
       if (mx && my) {
-        var react = Math.floor((bounds * 0.5) + Math.random() * (bounds * 0.9));
+        var react = Math.floor((bounds * 0.5) + Math.random() * (bounds * 0.9))
         if (p.distX - mx > 0 &&
           p.distX - mx < bounds &&
           p.distY - my > 0 &&
           p.distY - my < bounds) {
-          p.distX += react;
-          p.distY += react;
+          p.distX += react
+          p.distY += react
         } else if (p.distX - mx > 0 &&
           p.distX - mx < bounds &&
           p.distY - my < 0 &&
           p.distY - my > -bounds) {
-          p.distX += react;
-          p.distY -= react;
+          p.distX += react
+          p.distY -= react
         } else if (p.distX - mx < 0 &&
           p.distX - mx > -bounds &&
           p.distY - my > 0 &&
           p.distY - my < bounds) {
-          p.distX -= react;
-          p.distY += react;
+          p.distX -= react
+          p.distY += react
         } else if (p.distX - mx < 0 &&
           p.distX - mx > -bounds &&
           p.distY - my < 0 &&
           p.distY - my > -bounds) {
-          p.distY -= react;
-          p.distY -= react;
+          p.distY -= react
+          p.distY -= react
         }
       }
-      p.x += ((p.distX - p.x) / flow);
-      p.y += ((p.distY - p.y) / flow);
-      var x = p.x;
-      var y = p.y;
-      var s = p.size * (p.y * 1.5 / h);
+      p.x += ((p.distX - p.x) / flow)
+      p.y += ((p.distY - p.y) / flow)
+      var x = p.x
+      var y = p.y
+      var s = p.size * (p.y * 1.5 / h)
       if (s < 0.1) {
-        s = 0;
+        s = 0
       }
-      $.beginPath();
-      $.fillStyle = p.color;
-      $.arc(x, y, s, 0, end, true);
-      $.fill();
-      $.closePath();
-      var vary;
+      $.beginPath()
+      $.fillStyle = p.color
+      $.arc(x, y, s, 0, end, true)
+      $.fill()
+      $.closePath()
+      var vary
       if (p.size < 2) {
-        vary = 4;
+        vary = 4
       } else if (p.size < 3) {
-        vary = 3;
+        vary = 3
       } else if (p.size < 4) {
-        vary = 2;
+        vary = 2
       } else {
-        vary = 1;
+        vary = 1
       }
-      vary *= (p.y / (h * 0.9));
-      p.deg += vary;
-      p.deg = p.deg % 360;
+      vary *= (p.y / (h * 0.9))
+      p.deg += vary
+      p.deg = p.deg % 360
     }
   }
-  
-  function msmv(e) {
-    var p = getPos(e.target);
-    var sX = window.pageXOffset;
-    var sY = window.pageYOffset;
-    msX = e.clientX - p.x + sX;
-    msY = e.clientY - p.y + sY;
+
+  function msmv (e) {
+    var p = getPos(e.target)
+    var sX = window.pageXOffset
+    var sY = window.pageYOffset
+    msX = e.clientX - p.x + sX
+    msY = e.clientY - p.y + sY
   }
-  
-  function msdn(e) {
-    msdn = true;
+
+  function msdn (e) {
+    msdn = true
   }
-  
-  function msup(e) {
-    msdn = false;
+
+  function msup (e) {
+    msdn = false
   }
-  
-  function getPos(el) {
-    var cosmo = {};
-    cosmo.x = el.offsetLeft;
-    cosmo.y = el.offsetTop;
+
+  function getPos (el) {
+    var cosmo = {}
+    cosmo.x = el.offsetLeft
+    cosmo.y = el.offsetTop
     while (el.offsetParent) {
-      el = el.offsetParent;
-      cosmo.x += el.offsetLeft;
-      cosmo.y += el.offsetTop;
+      el = el.offsetParent
+      cosmo.x += el.offsetLeft
+      cosmo.y += el.offsetTop
     }
-    return cosmo;
+    return cosmo
   }
-  
+
   start()
 }

+ 118 - 119
src/utils/bg/bg2.js

@@ -1,50 +1,50 @@
-export function bgStart(){
+export function bgStart () {
   /**
    * Generates random particles using canvas
-   * 
+   *
    * @class Particles
    * @constructor
    */
-  function Particles(){
-    //particle colors
+  function Particles () {
+    // particle colors
     this.colors = [
       '255, 255, 255',
       '255, 99, 71',
       '19, 19, 19'
     ]
-    //adds gradient to particles on true
-    this.blurry = true;
-    //adds white border
-    this.border = false;
-    //particle radius min/max
-    this.minRadius = 10; 
-    this.maxRadius = 35;
-    //particle opacity min/max
-    this.minOpacity = .005;
-    this.maxOpacity = .5;
-    //particle speed min/max
-    this.minSpeed = .05;
-    this.maxSpeed = .5;
-    //frames per second 
-    this.fps = 60;
-    //number of particles
-    this.numParticles = 75;
-    //required canvas variables
-    this.canvas = document.getElementById('canvas');
-    if(this.canvas){
-      this.ctx = this.canvas.getContext('2d');
+    // adds gradient to particles on true
+    this.blurry = true
+    // adds white border
+    this.border = false
+    // particle radius min/max
+    this.minRadius = 10
+    this.maxRadius = 35
+    // particle opacity min/max
+    this.minOpacity = 0.005
+    this.maxOpacity = 0.5
+    // particle speed min/max
+    this.minSpeed = 0.05
+    this.maxSpeed = 0.5
+    // frames per second
+    this.fps = 60
+    // number of particles
+    this.numParticles = 75
+    // required canvas variables
+    this.canvas = document.getElementById('canvas')
+    if (this.canvas) {
+      this.ctx = this.canvas.getContext('2d')
     }
   }
-  
+
   /**
    * Initializes everything
    * @method init
    */
-  Particles.prototype.init = function(){
-    this.render();
-    this.createCircle();
+  Particles.prototype.init = function () {
+    this.render()
+    this.createCircle()
   }
-  
+
   /**
    * generates random number between min and max values
    * @param  {number} min value
@@ -52,145 +52,144 @@ export function bgStart(){
    * @return {number} random number between min and max
    * @method _rand
    */
-  Particles.prototype._rand = function(min, max){
-    return Math.random() * (max - min) + min;
+  Particles.prototype._rand = function (min, max) {
+    return Math.random() * (max - min) + min
   }
-  
+
   /**
    * Sets canvas size and updates values on resize
    * @method render
    */
-  Particles.prototype.render = function(){ 
-    var self = this,
-        wHeight = window.innerHeight,
-        wWidth = window.innerWidth;
-    
-    self.canvas.width = wWidth;
-    self.canvas.height = wHeight;
-    window.addEventListener('onresize',self.render)
+  Particles.prototype.render = function () {
+    var self = this
+    var wHeight = window.innerHeight
+    var wWidth = window.innerWidth
+
+    self.canvas.width = wWidth
+    self.canvas.height = wHeight
+    window.addEventListener('onresize', self.render)
 
     document.body.style.background = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAI0lEQVQIW2NkwAT/GdHE/gP5jMiCYAGQIpggXAAmiCIAEgQAAE4FBbECyZcAAAAASUVORK5CYII=) #222'
   }
-  
+
   /**
    * Randomly creates particle attributes
    * @method createCircle
    */
-  Particles.prototype.createCircle = function(){
-    var particle = [];
-  
+  Particles.prototype.createCircle = function () {
+    var particle = []
+
     for (var i = 0; i < this.numParticles; i++) {
-      var self = this,
-          color = self.colors[~~(self._rand(0, self.colors.length))];
-      
+      var self = this
+      var color = self.colors[~~(self._rand(0, self.colors.length))]
+
       particle[i] = {
-        radius    : self._rand(self.minRadius, self.maxRadius),
-        xPos      : self._rand(0, canvas.width),
-        yPos      : self._rand(0, canvas.height),
-        xVelocity : self._rand(self.minSpeed, self.maxSpeed),
-        yVelocity : self._rand(self.minSpeed, self.maxSpeed),
-        color     : 'rgba(' + color + ',' + self._rand(self.minOpacity, self.maxOpacity) + ')'
+        radius: self._rand(self.minRadius, self.maxRadius),
+        xPos: self._rand(0, canvas.width),
+        yPos: self._rand(0, canvas.height),
+        xVelocity: self._rand(self.minSpeed, self.maxSpeed),
+        yVelocity: self._rand(self.minSpeed, self.maxSpeed),
+        color: 'rgba(' + color + ',' + self._rand(self.minOpacity, self.maxOpacity) + ')'
       }
-      
-      //once values are determined, draw particle on canvas
-      self.draw(particle, i);
+
+      // once values are determined, draw particle on canvas
+      self.draw(particle, i)
     }
-    //...and once drawn, animate the particle
-    self.animate(particle);
+    // ...and once drawn, animate the particle
+    self.animate(particle)
   }
-  
+
   /**
    * Draws particles on canvas
    * @param  {array} Particle array from createCircle method
    * @param  {number} i value from createCircle method
    * @method draw
    */
-  Particles.prototype.draw = function(particle, i){
-    var self = this,
-        ctx = self.ctx;
-    
-    if (self.blurry === true ) {
-      //creates gradient if blurry === true
-      var grd = ctx.createRadialGradient(particle[i].xPos, particle[i].yPos, particle[i].radius, particle[i].xPos, particle[i].yPos, particle[i].radius/1.25);
-      
-      grd.addColorStop(1.000, particle[i].color);
-      grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)');
-      ctx.fillStyle = grd;
+  Particles.prototype.draw = function (particle, i) {
+    var self = this
+    var ctx = self.ctx
+
+    if (self.blurry === true) {
+      // creates gradient if blurry === true
+      var grd = ctx.createRadialGradient(particle[i].xPos, particle[i].yPos, particle[i].radius, particle[i].xPos, particle[i].yPos, particle[i].radius / 1.25)
+
+      grd.addColorStop(1.000, particle[i].color)
+      grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)')
+      ctx.fillStyle = grd
     } else {
-      //otherwise sets to solid color w/ opacity value
-      ctx.fillStyle = particle[i].color; 
+      // otherwise sets to solid color w/ opacity value
+      ctx.fillStyle = particle[i].color
     }
-    
+
     if (self.border === true) {
-      ctx.strokeStyle = '#fff';
-      ctx.stroke();
+      ctx.strokeStyle = '#fff'
+      ctx.stroke()
     }
-    
-    ctx.beginPath();
-    ctx.arc(particle[i].xPos, particle[i].yPos, particle[i].radius, 0, 2 * Math.PI, false);
-    ctx.fill();
+
+    ctx.beginPath()
+    ctx.arc(particle[i].xPos, particle[i].yPos, particle[i].radius, 0, 2 * Math.PI, false)
+    ctx.fill()
   }
-  
+
   /**
-   * Animates particles 
+   * Animates particles
    * @param  {array} particle value from createCircle & draw methods
    * @method animate
    */
-  Particles.prototype.animate = function(particle){
-    var self = this,
-            ctx = self.ctx;
-    
-    setInterval(function(){
-      //clears canvas
-      self.clearCanvas();
-      //then redraws particles in new positions based on velocity
+  Particles.prototype.animate = function (particle) {
+    var self = this
+    var ctx = self.ctx
+
+    setInterval(function () {
+      // clears canvas
+      self.clearCanvas()
+      // then redraws particles in new positions based on velocity
       for (var i = 0; i < self.numParticles; i++) {
-        particle[i].xPos += particle[i].xVelocity;
-        particle[i].yPos -= particle[i].yVelocity;
-       
-        //if particle goes off screen call reset method to place it offscreen to the left/bottom
+        particle[i].xPos += particle[i].xVelocity
+        particle[i].yPos -= particle[i].yVelocity
+
+        // if particle goes off screen call reset method to place it offscreen to the left/bottom
         if (particle[i].xPos > self.canvas.width + particle[i].radius || particle[i].yPos > self.canvas.height + particle[i].radius) {
-          self.resetParticle(particle, i);
+          self.resetParticle(particle, i)
         } else {
-          self.draw(particle, i);
+          self.draw(particle, i)
         }
-      }  
-    }, 1000/self.fps); 
+      }
+    }, 1000 / self.fps)
   }
-  
+
   /**
    * Resets position of particle when it goes off screen
    * @param  {array} particle value from createCircle & draw methods
    * @param  {number} i value from createCircle method
    * @method resetParticle
    */
-  Particles.prototype.resetParticle = function(particle, i){
-    var self = this;
-    
-    var random = self._rand(0, 1);
-    
-    if (random > .5) { 
+  Particles.prototype.resetParticle = function (particle, i) {
+    var self = this
+
+    var random = self._rand(0, 1)
+
+    if (random > 0.5) {
       // 50% chance particle comes from left side of window...
-      particle[i].xPos = -particle[i].radius;
-      particle[i].yPos = self._rand(0, self.canvas.height);
+      particle[i].xPos = -particle[i].radius
+      particle[i].yPos = self._rand(0, self.canvas.height)
     } else {
-      //... or bottom of window
-      particle[i].xPos = self._rand(0, self.canvas.width);
-      particle[i].yPos = self.canvas.height + particle[i].radius;   
+      // ... or bottom of window
+      particle[i].xPos = self._rand(0, self.canvas.width)
+      particle[i].yPos = self.canvas.height + particle[i].radius
     }
-    //redraw particle with new values
-    self.draw(particle, i);
+    // redraw particle with new values
+    self.draw(particle, i)
   }
-  
+
   /**
    * Clears canvas between animation frames
    * @method clearCanvas
    */
-  Particles.prototype.clearCanvas = function(){
-    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+  Particles.prototype.clearCanvas = function () {
+    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
   }
-  
-   
+
   // go go go!
-  var particle = new Particles().init(); 
-}
+  var particle = new Particles().init()
+}

+ 63 - 63
src/utils/bg/bg3.js

@@ -1,24 +1,24 @@
-export function bgStart(){
+export function bgStart () {
   // modified version of random-normal
-  function normalPool(o){var r=0;do{var a=Math.round(normal({mean:o.mean,dev:o.dev}));if(a<o.pool.length&&a>=0)return o.pool[a];r++}while(r<100)}function randomNormal(o){if(o=Object.assign({mean:0,dev:1,pool:[]},o),Array.isArray(o.pool)&&o.pool.length>0)return normalPool(o);var r,a,n,e,l=o.mean,t=o.dev;do{r=(a=2*Math.random()-1)*a+(n=2*Math.random()-1)*n}while(r>=1);return e=a*Math.sqrt(-2*Math.log(r)/r),t*e+l}
-  
-  const NUM_PARTICLES = 100;
-  const PARTICLE_SIZE = 0.5; // View heights
-  const SPEED = 10000; // Milliseconds 
-  
-  let particles = [];
-  
-  function rand(low, high) {
-    return Math.random() * (high - low) + low;
+  function normalPool (o) { var r = 0; do { var a = Math.round(normal({ mean: o.mean, dev: o.dev })); if (a < o.pool.length && a >= 0) return o.pool[a]; r++ } while (r < 100) } function randomNormal (o) { if (o = Object.assign({ mean: 0, dev: 1, pool: [] }, o), Array.isArray(o.pool) && o.pool.length > 0) return normalPool(o); var r; var a; var n; var e; var l = o.mean; var t = o.dev; do { r = (a = 2 * Math.random() - 1) * a + (n = 2 * Math.random() - 1) * n } while (r >= 1);return e = a * Math.sqrt(-2 * Math.log(r) / r), t * e + l }
+
+  const NUM_PARTICLES = 100
+  const PARTICLE_SIZE = 0.5 // View heights
+  const SPEED = 10000 // Milliseconds
+
+  const particles = []
+
+  function rand (low, high) {
+    return Math.random() * (high - low) + low
   }
-  
-  function createParticle(canvas) {
+
+  function createParticle (canvas) {
     const colour = {
       r: 255,
       g: randomNormal({ mean: 125, dev: 20 }),
       b: 50,
-      a: rand(0, 1),
-    };
+      a: rand(0, 1)
+    }
     return {
       x: -2,
       y: -2,
@@ -28,25 +28,25 @@ export function bgStart(){
       offsetY: randomNormal({ mean: 0, dev: 10 }),
       arc: Math.PI * 2,
       startTime: performance.now() - rand(0, SPEED),
-      colour: `rgba(${colour.r}, ${colour.g}, ${colour.b}, ${colour.a})`,
+      colour: `rgba(${colour.r}, ${colour.g}, ${colour.b}, ${colour.a})`
     }
   }
-  
-  function moveParticle(particle, canvas, time) {
-    const progress = ((time - particle.startTime) % particle.duration) / particle.duration;
+
+  function moveParticle (particle, canvas, time) {
+    const progress = ((time - particle.startTime) % particle.duration) / particle.duration
     return {
       ...particle,
       x: progress,
-      y: ((Math.sin(progress * particle.arc) * particle.amplitude) + particle.offsetY),
-    };
+      y: ((Math.sin(progress * particle.arc) * particle.amplitude) + particle.offsetY)
+    }
   }
-  
-  function drawParticle(particle, canvas, ctx) {
-    canvas = document.getElementById('canvas');
-    const vh = canvas.height / 100;
-  
-    ctx.fillStyle = particle.colour;
-    ctx.beginPath();
+
+  function drawParticle (particle, canvas, ctx) {
+    canvas = document.getElementById('canvas')
+    const vh = canvas.height / 100
+
+    ctx.fillStyle = particle.colour
+    ctx.beginPath()
     ctx.ellipse(
       particle.x * canvas.width,
       particle.y * vh + (canvas.height / 2),
@@ -55,68 +55,68 @@ export function bgStart(){
       0,
       0,
       2 * Math.PI
-    );
-    ctx.fill();
+    )
+    ctx.fill()
   }
-  
-  function draw(time, canvas, ctx) {
+
+  function draw (time, canvas, ctx) {
     // Move particles
     particles.forEach((particle, index) => {
-      particles[index] = moveParticle(particle, canvas, time);
+      particles[index] = moveParticle(particle, canvas, time)
     })
-  
+
     // Clear the canvas
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
-  
+    ctx.clearRect(0, 0, canvas.width, canvas.height)
+
     // Draw the particles
     particles.forEach((particle) => {
-      drawParticle(particle, canvas, ctx);
+      drawParticle(particle, canvas, ctx)
     })
-  
+
     // Schedule next frame
-    requestAnimationFrame((time) => draw(time, canvas, ctx));
+    requestAnimationFrame((time) => draw(time, canvas, ctx))
   }
-  
-  function initializeCanvas() {
-    let canvas = document.getElementById('canvas');
-    canvas.width = canvas.offsetWidth * window.devicePixelRatio;
-    canvas.height = canvas.offsetHeight * window.devicePixelRatio;
+
+  function initializeCanvas () {
+    const canvas = document.getElementById('canvas')
+    canvas.width = canvas.offsetWidth * window.devicePixelRatio
+    canvas.height = canvas.offsetHeight * window.devicePixelRatio
     canvas.style.background = 'linear-gradient(to bottom, rgb(10, 10, 50) 0%,rgb(60, 10, 60) 100%)'
     canvas.style.verticalAlign = 'middle'
     canvas.overflow = 'hidden'
-    let ctx = canvas.getContext("2d");
-  
+    let ctx = canvas.getContext('2d')
+
     window.addEventListener('onresize', () => {
-      canvas.width = canvas.offsetWidth * window.devicePixelRatio;
-      canvas.height = canvas.offsetHeight * window.devicePixelRatio;
+      canvas.width = canvas.offsetWidth * window.devicePixelRatio
+      canvas.height = canvas.offsetHeight * window.devicePixelRatio
       canvas.style.background = 'linear-gradient(to bottom, rgb(10, 10, 50) 0%,rgb(60, 10, 60) 100%)'
       canvas.style.verticalAlign = 'middle'
       canvas.overflow = 'hidden'
-      ctx = canvas.getContext("2d");
+      ctx = canvas.getContext('2d')
     })
-  
-    return [canvas, ctx];
+
+    return [canvas, ctx]
   }
-  
-  function startAnimation() {
-    const [canvas, ctx] = initializeCanvas();
-  
+
+  function startAnimation () {
+    const [canvas, ctx] = initializeCanvas()
+
     // Create a bunch of particles
     for (let i = 0; i < NUM_PARTICLES; i++) {
-      particles.push(createParticle(canvas));
+      particles.push(createParticle(canvas))
     }
-    
-    requestAnimationFrame((time) => draw(time, canvas, ctx));
+
+    requestAnimationFrame((time) => draw(time, canvas, ctx))
   };
-  
+
   // Start animation when document is loaded
   (function () {
     if (document.readystate !== 'loading') {
-      startAnimation();
+      startAnimation()
     } else {
       document.addEventListener('DOMContentLoaded', () => {
-        startAnimation();
+        startAnimation()
       })
     }
-  }());
-}
+  }())
+}

+ 100 - 100
src/utils/bg/bg4.js

@@ -1,108 +1,108 @@
-export function bgStart(){
-    //更新页面用requestAnimationFrame替代setTimeout
-    window.requestAnimationFrame = window.requestAnimationFrame 
-    || window.mozRequestAnimationFrame 
-    || window.webkitRequestAnimationFrame 
-    || window.msRequestAnimationFrame;
-    
-    var canvas = document.getElementById('canvas');
-    var ctx = canvas.getContext('2d');
-    
-    var w = canvas.width = canvas.offsetWidth;
-    var h = canvas.height = canvas.offsetHeight;
-    var circles = [];
-    var current_circle = new currentCircle(0, 0);
-    
-    function init(num) {
-      document.getElementById('userLayout').style.background='#333'
-      for(var i = 0; i < num; i ++) {
-        circles.push(new circle(Math.random() * w, Math.random() * h));
+export function bgStart () {
+  // 更新页面用requestAnimationFrame替代setTimeout
+  window.requestAnimationFrame = window.requestAnimationFrame ||
+    window.mozRequestAnimationFrame ||
+    window.webkitRequestAnimationFrame ||
+    window.msRequestAnimationFrame
+
+  var canvas = document.getElementById('canvas')
+  var ctx = canvas.getContext('2d')
+
+  var w = canvas.width = canvas.offsetWidth
+  var h = canvas.height = canvas.offsetHeight
+  var circles = []
+  var current_circle = new currentCircle(0, 0)
+
+  function init (num) {
+    document.getElementById('userLayout').style.background = '#333'
+    for (var i = 0; i < num; i++) {
+      circles.push(new circle(Math.random() * w, Math.random() * h))
+    }
+    draw()
+  }
+
+  function draw () {
+    ctx.clearRect(0, 0, w, h)
+    for (var i = 0; i < circles.length; i++) {
+      circles[i].move(w, h)
+      circles[i].drawCircle(ctx)
+      for (var j = i + 1; j < circles.length; j++) {
+        circles[i].drawLine(ctx, circles[j])
       }
-      draw();
     }
-    
-    function draw() {
-      ctx.clearRect(0, 0, w, h);
-      for(var i = 0; i < circles.length; i ++) {
-        circles[i].move(w, h);
-        circles[i].drawCircle(ctx);
-        for(var j = i + 1; j < circles.length; j++) {
-          circles[i].drawLine(ctx, circles[j]);
-        }
-      } 
-      if (current_circle.x) {
-        current_circle.drawCircle(ctx);
-        for (var k = 0; k < circles.length; k++) {
-          current_circle.drawLine(ctx, circles[k])
-        }
+    if (current_circle.x) {
+      current_circle.drawCircle(ctx)
+      for (var k = 0; k < circles.length; k++) {
+        current_circle.drawLine(ctx, circles[k])
       }
-      requestAnimationFrame(draw);
     }
-    
-    window.onmousemove = function(e) {
-      e = e || window.event;
-      current_circle.x = e.clientX;
-      current_circle.y = e.clientY;
+    requestAnimationFrame(draw)
+  }
+
+  window.onmousemove = function (e) {
+    e = e || window.event
+    current_circle.x = e.clientX
+    current_circle.y = e.clientY
+  }
+  window.onmouseout = function () {
+    current_circle.x = null
+    current_circle.y = null
+  }
+
+  // 创建对象:圆
+  // x, y为坐标点, r为半径, _mx, _my为移动的距离
+  function circle (x, y) {
+    this.x = x
+    this.y = y
+    this.r = Math.random() * 10
+    this._mx = 1 - (Math.random() * 2)
+    this._my = 1 - (Math.random() * 2)
+
+    // canvas画圆
+    this.drawCircle = drawCircle
+    function drawCircle (ctx) {
+      ctx.beginPath()
+      ctx.arc(this.x, this.y, this.r, 0, 360)
+      ctx.fillStyle = 'rgba(204, 204, 204, 0.3)'
+      ctx.fill()
     }
-    window.onmouseout = function() {
-      current_circle.x = null;
-      current_circle.y = null;
-     }
-    
-    //创建对象:圆
-    //x, y为坐标点, r为半径, _mx, _my为移动的距离
-    function circle(x, y) {
-      this.x = x;
-      this.y = y;
-      this.r = Math.random() * 10;
-      this._mx = 1 - (Math.random() * 2);
-      this._my = 1 - (Math.random() * 2);
-      
-      //canvas画圆
-      this.drawCircle = drawCircle;
-      function drawCircle(ctx) {
-        ctx.beginPath();
-        ctx.arc(this.x, this.y, this.r, 0, 360);
-        ctx.fillStyle = 'rgba(204, 204, 204, 0.3)';
-        ctx.fill();
-      }
-      
-      this.move = move;
-      function move(w, h) {
-        this._mx = (this.x < w && this.x > 0) ? this._mx : (-this._mx);
-        this._my = (this.y < h && this.y > 0) ? this._my : (-this._my);
-        this.x += this._mx / 2;
-        this.y += this._my / 2;
-      }
-      
-      //canvas画线
-      //画直线是两个圆连线,为了避免直线过多,给圆圈距离设置了一个值,距离很远的圆圈,就不做连线处理
-      this.drawLine = drawLine;
-      function drawLine(ctx, _circle) {
-        var dx = this.x - _circle.x;
-        var dy = this.y - _circle.y;
-        var d = Math.sqrt(dx * dx + dy * dy);
-        if (d < 150) {
-          ctx.beginPath();
-          ctx.moveTo(this.x, this.y);//起点
-          ctx.lineTo(_circle.x, _circle.y);//终点
-          ctx.strokeStyle = 'rgba(204, 204, 204, 0.3)';
-          ctx.stroke();
-        }
-      }
+
+    this.move = move
+    function move (w, h) {
+      this._mx = (this.x < w && this.x > 0) ? this._mx : (-this._mx)
+      this._my = (this.y < h && this.y > 0) ? this._my : (-this._my)
+      this.x += this._mx / 2
+      this.y += this._my / 2
     }
-    
-    function currentCircle(x, y) {
-      circle.call(this, x, y);
-      
-      this.drawCircle = drawCircle;
-      function drawCircle(ctx) {
-        ctx.beginPath();
-        ctx.arc(this.x, this.y, 8, 0, 360);
-        ctx.fillStyle = 'rgba(255, 77, 54, 0.6)';
-        ctx.fill();
+
+    // canvas画线
+    // 画直线是两个圆连线,为了避免直线过多,给圆圈距离设置了一个值,距离很远的圆圈,就不做连线处理
+    this.drawLine = drawLine
+    function drawLine (ctx, _circle) {
+      var dx = this.x - _circle.x
+      var dy = this.y - _circle.y
+      var d = Math.sqrt(dx * dx + dy * dy)
+      if (d < 150) {
+        ctx.beginPath()
+        ctx.moveTo(this.x, this.y)// 起点
+        ctx.lineTo(_circle.x, _circle.y)// 终点
+        ctx.strokeStyle = 'rgba(204, 204, 204, 0.3)'
+        ctx.stroke()
       }
     }
-    
-    init(100)
-}
+  }
+
+  function currentCircle (x, y) {
+    circle.call(this, x, y)
+
+    this.drawCircle = drawCircle
+    function drawCircle (ctx) {
+      ctx.beginPath()
+      ctx.arc(this.x, this.y, 8, 0, 360)
+      ctx.fillStyle = 'rgba(255, 77, 54, 0.6)'
+      ctx.fill()
+    }
+  }
+
+  init(100)
+}

+ 29 - 28
src/utils/request.js

@@ -1,10 +1,11 @@
-import Vue from 'vue'
+// import Vue from 'vue'
 import axios from 'axios'
 import store from '@/store'
 import notification from 'ant-design-vue/es/notification'
+import modal from 'ant-design-vue/es/modal'
 import { VueAxios } from './axios'
-import { ACCESS_TOKEN } from '@/store/mutation-types'
-console.log(process.env.VUE_APP_PRO_NAME)
+// import { ACCESS_TOKEN } from '@/store/mutation-types'
+// console.log(process.env.VUE_APP_PRO_NAME)
 // 创建 axios 实例
 const service = axios.create({
   baseURL: process.env.VUE_APP_API_BASE_URL, // api base_url
@@ -12,19 +13,15 @@ const service = axios.create({
 })
 
 const err = (error) => {
+  console.log(error.response.data.message, 'error')
   if (error.response) {
-    const data = error.response.data
-    if ((error.response.status == 403 || error.response.status == 401) && window.location.pathname != '/user/login') {
+    const status = error.response.status
+    if ((status == 503 || status == 500) && window.location.pathname != '/user/login') {
       notification.destroy()
       notification.error({
         message: '提示',
-        description: data.message
+        description: error.response.data.message
       })
-      setTimeout(function () {
-        store.dispatch('Logout').then(() => {
-          window.location.reload()
-        })
-      }, 2000)
     }
   }
   // 超时无法访问服务
@@ -32,47 +29,51 @@ const err = (error) => {
     notification.destroy()
     notification.error({
       message: '提示',
-      description: error.message
+      description: '请求超时'
     })
-    setTimeout(function () {
-      store.dispatch('Logout').then(() => {
-        window.location.reload()
-      })
-    }, 2000)
   }
   return Promise.reject(error)
 }
 
 // request interceptor
 service.interceptors.request.use(config => {
-  const token = Vue.ls.get(ACCESS_TOKEN)
+  const token = store.getters.token
+  config.headers['App-Type'] = 1 // 平台类型
   if (token) {
-    // config.headers['Access-Token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
+    config.headers['access-token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
   }
   return config
 }, err)
 
 // response interceptor
 service.interceptors.response.use((response) => {
-  console.log(response, response.data.status, 'responseresponseresponse')
+  console.log(response, 'response.data.status')
   if (window.location.pathname != '/user/login') {
-    if (response.data.status == '900') {
+    if (response.data.status == '500') {
       notification.destroy()
       notification.error({
         message: '提示',
         description: response.data.message
       })
     }
-  } else {
-    if (response.data.status == '500') {
-      notification.destroy()
-      notification.error({
-        message: '提示',
-        description: response.data.message
+    const et = sessionStorage.getItem('errorTips')
+    if (response.data.status.length == 4 && !et) {
+      sessionStorage.setItem('errorTips', 1)
+      modal.destroyAll()
+      modal.error({
+        title: '提示',
+        content: response.data.message,
+        onOk () {
+          sessionStorage.setItem('errorTips', 0)
+          if (['1001', '1002', '1006', '1099', '1100', '9000'].indexOf(response.data.status) >= 0) {
+            store.dispatch('Logout').then(() => {
+              window.location.reload()
+            })
+          }
+        }
       })
     }
   }
-
   return response.data
 }, err)
 

+ 1 - 1
src/utils/util.js

@@ -70,4 +70,4 @@ export function oneOf (value, validList) {
     }
   }
   return false
-}
+}

+ 219 - 0
src/views/BasicSettings/Organization.vue

@@ -0,0 +1,219 @@
+<template>
+  <a-card class="organization-wrap" :bordered="false">
+    <!-- 新建 -->
+    <div class="table-operator"><a-button id="organization-add" type="primary" icon="plus" @click="addOrg()" v-hasPermission="'B_basicSettings_organization_add'">新增最高级</a-button></div>
+    <!-- 表格列表 -->
+    <s-table
+      class="s-table"
+      ref="table"
+      size="default"
+      rowKey="id"
+      :showPagination="false"
+      :columns="columns"
+      :data="loadData"
+      :defaultExpandedRowKeys="defaultExpandedRowKeys"
+      :bordered="true">
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          v-if="record.parentIdPaths.split(',').length < 5"
+          type="link"
+          size="small"
+          icon="plus"
+          class="btn-add-s"
+          id="organization-addSubItem"
+          @click="addOrg(text)"
+          v-hasPermission="'B_basicSettings_organization_add_child'">新增子级</a-button>
+        <a-button
+          v-if="record.pid != 0"
+          type="link"
+          size="small"
+          icon="edit"
+          class="btn-edit-s"
+          id="organization-edit"
+          @click="editOrg(text)"
+          v-hasPermission="'B_basicSettings_organization_edit'">编辑</a-button>
+        <a-button
+          v-if="record.pid != 0"
+          type="link"
+          size="small"
+          icon="delete"
+          class="btn-del-s"
+          id="organization-del"
+          @click="delOrg(text)"
+          v-hasPermission="'B_basicSettings_organization_del'">删除</a-button>
+      </template>
+    </s-table>
+    <!-- 新增子级 -->
+    <a-modal
+      class="organization-modal"
+      centered
+      :title="title"
+      :visible="visible"
+      :footer="null"
+      :closable="true"
+      @cancel="onCancel"
+      width="600px">
+      <!-- 表单 -->
+      <a-form-model ref="ruleForm" :model="form" :rules="rules">
+        <a-form-model-item label="组织机构名称" prop="name">
+          <a-input v-model.trim="form.name" @input="removeSpaces('name')" id="organization-itemName" :maxLength="30" placeholder="请输入组织机构名称(最多30个字符)" />
+        </a-form-model-item>
+        <a-form-model-item class="btn-cont">
+          <a-button type="primary" id="organization-save" @click="onSubmit">保存</a-button>
+          <a-button class="cancel" id="organization-cancel" @click="onCancel">取消</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-modal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { findOrgTree, saveAtorg, delAtorg } from '@/api/atorg.js'
+export default {
+  components: { STable, VSelect },
+  data () {
+    return {
+      columns: [
+        { title: '组织机构名称', dataIndex: 'name', width: 200, align: 'left' },
+        { title: '创建时间', dataIndex: 'createDate', width: 150, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 150, align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return findOrgTree().then(res => {
+          //  递归去除空children
+          this.recursionFun(res.data)
+          this.defaultExpandedRowKeys[0] = res.data[0].id
+          return res.data
+        })
+      },
+      title: '新增', //  对话框标题
+      visible: false, //  对话框是否可见
+      form: { //  新增编辑  组织机构
+        name: ''
+      },
+      rules: { //  表单校验规则
+        name: [{ required: true, message: '请输入组织机构名称', trigger: 'blur' }]
+      },
+      nowId: '', //  当前操作的数据id
+      nowPid: '', //  当前操作的数据上级id
+      defaultExpandedRowKeys: [] //  树形数据默认展开项
+    }
+  },
+  methods: {
+    //  去除空格
+    removeSpaces (val) {
+      this.form[val] = this.form[val].replace(/\s|\r\n|\n|<|>/g, '')
+    },
+    //  新增子级
+    addOrg (item) {
+      this.nowId = ''
+      this.form.name = ''
+      if (item) { //  子级
+        this.nowPid = item.id
+      } else { //  最高级
+        this.nowPid = ''
+      }
+      this.title = '新增'
+      this.visible = true
+    },
+    //  编辑
+    editOrg (item) {
+      this.nowId = item.id
+      this.nowPid = item.pid
+      this.title = '编辑'
+      this.form.name = item.name
+      this.visible = true
+    },
+    //  保存
+    onSubmit () {
+      const _this = this
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const formData = JSON.parse(JSON.stringify(_this.form))
+          formData.id = _this.nowId
+          formData.pid = _this.nowPid
+          saveAtorg(formData).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh(true)
+              _this.visible = false
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    //  关闭对话框
+    onCancel () {
+      this.$refs.ruleForm.resetFields()
+      this.visible = false
+    },
+    //  删除
+    delOrg (item) {
+      const _this = this
+      _this.nowId = item.id
+      _this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '删除后原数据不可恢复,是否删除?',
+        onOk () {
+          delAtorg({ id: _this.nowId }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$refs.table.refresh()
+            }
+          })
+        }
+      })
+    },
+    //  递归函数
+    recursionFun (data) {
+      if (data) {
+        data.map((item, index) => {
+          if (item.children && item.children.length == 0) {
+            delete item.children
+          } else {
+            this.recursionFun(item.children)
+          }
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .organization-wrap{
+    // 表格
+    .s-table{
+      .btn-edit-s{
+        color: #1891ff;
+        margin: 0 5px;
+      }
+      .btn-del-s{
+        color: #ff4d4f;
+      }
+      .btn-edit-s.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger), .btn-edit-s.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger){
+        color: #1891ff;
+        border-color: #1891ff;
+      }
+      .btn-del-s.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger), .btn-del-s.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger){
+        color: #ff4d4f;
+        border-color: #ff4d4f;
+      }
+    }
+  }
+  // 弹框
+  .organization-modal{
+    .btn-cont{
+      text-align: center;
+      .cancel {
+      	margin-left: 50px;
+      }
+    }
+  }
+</style>

+ 364 - 0
src/views/BasicSettings/StoreAssociatedEquipmentModal.vue

@@ -0,0 +1,364 @@
+<template>
+  <a-modal
+    class="StoreAssociatedEquipmentModal-wrap"
+    centered
+    title="关联摄像设备"
+    :width="1000"
+    :footer="null"
+    :destroyOnClose="true"
+    @cancel="isShow = false"
+    v-model="isShow">
+    <!-- 搜索设备 -->
+    <div class="search-con" @blur="isFocus=false">
+      <a-input-search
+        id="equipment-search"
+        class="search-s"
+        allow-clear
+        placeholder="请通过设备国标ID搜索"
+        enter-button="查询"
+        size="large"
+        @blur="noData=0"
+        @focus="isFocus=true"
+        @search="onSearch"
+      />
+      <a-card class="search-sub" :bordered="false">
+        <div class="noData" v-if="noData==1" style="text-align: center;">未查询到结果</div>
+        <div class="search-sub-item" v-if="resultData && isFocus">
+          <p>{{ resultData.name }}</p>
+          <a-button
+            id="equipment-bind"
+            v-if="!resultData.params"
+            type="primary"
+            ghost
+            size="small"
+            @click="onBundling(resultData)"
+            v-hasPermission="'B_store_device_bind'">立即绑定</a-button>
+          <a-button v-else disabled type="link">已绑定</a-button>
+        </div>
+      </a-card>
+    </div>
+    <!-- 已绑设备 -->
+    <div class="eq-tit">已绑设备:</div>
+    <a-table
+      class="table"
+      ref="table"
+      bordered
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data-source="equipmentData"
+      :pagination="false"
+      :expandedRowKeys="expandedRowKeys"
+      @expand="eqExpand"
+      @expandedRowsChange="expandedRowsChange">
+      <div slot="expandedRowRender" slot-scope="record" style="margin: 30px 30px;">
+        <div class="eq-subTit">设备通道(机位):</div>
+        <a-table
+          ref="tables"
+          bordered
+          size="small"
+          :rowKey="(record) => record.gbId"
+          :columns="passagewayColumns"
+          :data-source="record.passagewayData"
+          :pagination="false">
+          <template slot="action" slot-scope="record">
+            <a-button type="link" id="equipment-edit" @click="onEdit(record)" v-hasPermission="'B_store_deviceTd_edit'">编辑</a-button>
+          </template>
+        </a-table>
+      </div>
+      <template slot="action" slot-scope="record">
+        <a-button
+          type="primary"
+          ghost
+          size="small"
+          id="equipment-unBind"
+          @click="onUnbundling(record)"
+          v-hasPermission="'B_store_device_unbind'">解绑</a-button>
+      </template>
+    </a-table>
+    <!-- 编辑  通道/机位名称 -->
+    <a-modal
+      class="passagewayModal"
+      title="编辑"
+      centered
+      :visible="visible"
+      :footer="null"
+      :closable="true"
+      @cancel="visible=false"
+      width="600px">
+      <!-- 表单 -->
+      <a-form-model ref="ruleForm" :model="form" :rules="rules">
+        <a-form-model-item label="名称" prop="deviceName">
+          <a-input v-model.trim="form.deviceName" id="equipment-name" :maxLength="30" placeholder="请输入名称,30个字以内" />
+        </a-form-model-item>
+        <a-form-model-item class="btn-cont">
+          <a-button type="primary" id="equipment-save" @click="onSubmit">保存</a-button>
+          <a-button class="cancel" id="equipment-cancel" @click="visible=false">取消</a-button>
+        </a-form-model-item>
+      </a-form-model>
+    </a-modal>
+  </a-modal>
+</template>
+
+<script>
+import { findStoreVsDevice, unbindVsDevice, findVsDevice, bindVsDevice } from '@/api/storeVsDevice.js'
+import { vsDeviceChannels, vsDeviceRename } from '@/api/vsDevice.js'
+export default {
+  name: 'StoreAssociatedEquipmentModal',
+  props: {
+    openModal: {
+      //  弹框是否展示
+      type: Boolean,
+      default: false
+    },
+    storeId: {
+      //  门店id
+      type: String,
+      default: ''
+    },
+    storeCode: {
+      //  门店code
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  弹框是否展示
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 60, align: 'center' },
+        { title: '设备名称', dataIndex: 'vsDeviceName', width: 100, align: 'center' },
+        { title: '设备ID', dataIndex: 'vsDeviceId', width: 150, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 80, align: 'center' }
+      ],
+      equipmentData: [], //  已绑设备
+      passagewayData: [], //  设备通道
+      passagewayColumns: [
+        { title: '序号', dataIndex: 'no', width: 60, align: 'center' },
+        { title: '设备通道名称', dataIndex: 'name', width: 100, align: 'center' },
+        { title: '设备ID', dataIndex: 'deviceId', width: 150, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 80, align: 'center' }
+      ],
+      visible: false, //  编辑  通道/机位名称
+      form: {
+        deviceName: '' //  名称
+      },
+      rules: { //  表单校验规则
+        deviceName: [{ required: true, message: '请输入名称', trigger: 'blur' }]
+      },
+      resultData: null, //  设备搜索结果
+      noData: 0,
+      isFocus: false, //  搜索框是否获取焦点
+      vsDeviceId: '', //  设备id
+      deviceId: '', //  设备通道id
+      expandedRowKeys: []
+    }
+  },
+  methods: {
+    //  搜索设备
+    onSearch (value) {
+      if (value) {
+        findVsDevice({ id: value }).then(res => {
+          if (res.status == 200) {
+            if (res.data) {
+              this.noData = 2
+              this.resultData = res.data
+            } else {
+              this.noData = 1
+              this.resultData = null
+            }
+          }
+        })
+      } else {
+        this.noData = 0
+        this.resultData = null
+        this.isFocus = false
+      }
+    },
+    //  门店已绑设备
+    getStoreEquipment (id) {
+      findStoreVsDevice({ code: id }).then(res => {
+        if (res.status == 200) {
+          res.data.map((item, ind) => {
+            item.no = ind + 1
+          })
+          this.equipmentData = res.data
+        }
+      })
+    },
+    //  解绑
+    onUnbundling (item) {
+      const _this = this
+      _this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '确定解绑该设备吗?',
+        onOk () {
+          unbindVsDevice({ id: item.id }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.getStoreEquipment(_this.storeCode)
+            }
+          })
+        }
+      })
+    },
+    //  绑定
+    onBundling (item) {
+      const _this = this
+      _this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '确定要绑定该设备吗?',
+        onOk () {
+          bindVsDevice({ storeCode: _this.storeCode, vsDeviceId: item.id }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.expandedRowKeys = []
+              _this.resultData = null
+              _this.isFocus = false
+              _this.getStoreEquipment(_this.storeCode)
+            }
+          })
+        }
+      })
+    },
+    //  编辑  通道/机位名称
+    onEdit (item) {
+      this.form.deviceName = item.name
+      this.deviceId = item.deviceId
+      this.visible = true
+    },
+    //  提交更改的通道信息
+    onSubmit () {
+      const _this = this
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const formData = JSON.parse(JSON.stringify(_this.form))
+          formData.deviceId = this.deviceId
+          vsDeviceRename(formData).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.visible = false
+              _this.getDeviceChannels()
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+    //  设备行展开事件
+    eqExpand (expanded, record) {
+      if (expanded) { //  展开行
+        this.vsDeviceId = record.vsDeviceId
+        this.getDeviceChannels()
+      }
+    },
+    //  展开的行变化时触发
+    expandedRowsChange (expandedRows) {
+      this.expandedRowKeys = expandedRows
+    },
+    //  获取设备通道信息
+    getDeviceChannels () {
+      vsDeviceChannels({ id: this.vsDeviceId }).then(res => {
+        if (res.status == 200) {
+          if (res.data) {
+            res.data.map((item, ind) => {
+              item.no = ind + 1
+            })
+            const ind = this.equipmentData.findIndex(item => item.vsDeviceId == this.vsDeviceId)
+            if (ind != -1) {
+              this.$set(this.equipmentData[ind], 'passagewayData', res.data)
+            }
+            this.passagewayData = res.data
+          } else {
+            const ind = this.equipmentData.findIndex(item => item.vsDeviceId == this.vsDeviceId)
+            if (ind != -1) {
+              this.$set(this.equipmentData[ind], 'passagewayData', [])
+            }
+          }
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (val) {
+      if (!val) {
+        this.$emit('close')
+      } else {
+        //  重置信息
+        this.expandedRowKeys = []
+        this.resultData = null
+        this.isFocus = false
+      }
+    },
+    storeCode (newValue, oldValue) {
+      if (newValue && this.isShow) {
+        this.getStoreEquipment(newValue)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .StoreAssociatedEquipmentModal-wrap{
+    .search-con{
+      position: relative;
+      .search-s{
+        .ant-input-group-addon{
+          padding: 0;
+          border: none;
+        }
+      }
+      .search-sub{
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+        position: absolute;
+        left: 0;
+        top: 45px;
+        width: 100%;
+        z-index: 1;
+        border-radius: 6px;
+        .ant-card-body{
+          padding: 15px 24px;
+        }
+        .search-sub-item{
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding: 8px 0;
+          border-bottom: 1px dashed #f8f8f8;
+          p{
+            margin: 0;
+          }
+          &:last-child{
+            border-bottom: none;
+          }
+        }
+      }
+    }
+    .eq-tit{
+      line-height: 40px;
+      font-size: 16px;
+      margin: 85px 0 5px;
+    }
+    .eq-subTit{
+      margin: 0 0 10px;
+    }
+    .table{
+      padding-bottom: 50px;
+    }
+  }
+  .btn-cont{
+    text-align: center;
+    .cancel{
+      margin-left: 40px;
+    }
+  }
+</style>

+ 226 - 0
src/views/BasicSettings/StoreManagement.vue

@@ -0,0 +1,226 @@
+<template>
+  <a-card class="StoreManagement" :bordered="false">
+    <!-- 搜索条件 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="48">
+          <a-col :span="6">
+            <a-form-item class="search-item" label="门店名称">
+              <a-input id="store-name" v-model.trim="queryParam.name" placeholder="请输入门店名称" @pressEnter="$refs.table.refresh(true)" allowClear />
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-form-item class="search-item" label="负责人手机">
+              <a-input id="store-managerMobile" v-model.trim="queryParam.managerMobile" placeholder="请输入负责人手机" @pressEnter="$refs.table.refresh(true)" allowClear />
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-form-item class="search-item" label="组织机构">
+              <a-tree-select
+                showSearch
+                id="store-orgCode"
+                v-model="queryParam.orgCode"
+                allowClear
+                :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
+                :replace-fields="{children:'children', title:'name', key:'id', value: 'code' }"
+                :tree-data="treeData"
+                placeholder="请选择组织机构"
+                treeNodeFilterProp="title">
+              </a-tree-select>
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-form-item class="search-item" label="启用状态">
+              <v-select
+                id="store-status"
+                ref="enableFlag"
+                allowClear
+                placeholder="请选择启用状态"
+                v-model="queryParam.enableFlag"
+                code="ENABLE_FLAG"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :span="6" style="padding-bottom: 10px;">
+            <a-button type="primary" id="store-search" class="search-btn" @click="$refs.table.refresh(true)">查询</a-button>
+            <a-button id="store-reset" @click="reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 表格列表 -->
+    <s-table
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      bordered>
+      <!-- 组织机构 -->
+      <template slot="orgCode" slot-scope="text, record">
+        <span v-for="(item, index) in record.codeNameArr" :key="index">
+          {{ item }}
+          <strong v-if="index != record.codeNameArr.length-1">></strong>
+        </span>
+      </template>
+      <!-- 负责人名称 -->
+      <template slot="managerName" slot-scope="text, record">
+        <div v-if="record.managerName">{{ record.managerName }}</div>
+        <div v-else>--</div>
+      </template>
+      <!-- 启用状态 -->
+      <template slot="enableFlag" slot-scope="text, record">
+        <div v-if="record.enableFlag == 0" style="color: #ff4d4f">{{ record.enableFlagDictValue }}</div>
+        <div v-if="record.enableFlag == 1" style="color: #1890FF">{{ record.enableFlagDictValue }}</div>
+      </template>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-icon
+          type="edit"
+          title="编辑"
+          id="store-edit"
+          @click="edit(record)"
+          class="actionBtn icon-blues"
+          v-hasPermission="'B_basicSettings_store_edit'" />
+        <a-icon
+          type="setting"
+          title="关联摄像设备"
+          id="store-set"
+          @click="setEquipment(record)"
+          class="actionBtn icon-orange"
+          v-hasPermission="'M_store_device'" />
+      </template>
+    </s-table>
+
+    <!-- 编辑 门店所属组织 -->
+    <store-modal :openModal="openModal" :storeId="storeId" @success="storeSubmit" @close="closeModal" />
+    <!-- 门店 关联设备 -->
+    <store-associated-equipment-modal :openModal="openEquipmentModal" :storeId="storeId" :storeCode="storeCode" @close="closeDetailsModal" />
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import StoreModal from './StoreModal.vue'
+import StoreAssociatedEquipmentModal from './StoreAssociatedEquipmentModal.vue'
+import { findStoreList } from '@/api/store.js'
+import { findOrgTree } from '@/api/atorg.js'
+export default {
+  name: 'StoreManagement',
+  components: { STable, VSelect, StoreModal, StoreAssociatedEquipmentModal },
+  data () {
+    return {
+      queryParam: {
+        name: '', //  门店名称
+        managerMobile: '', //  负责人手机
+        orgCode: null, //  组织机构
+        enableFlag: '' //  启用状态
+      },
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 60, align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: 150, align: 'center' },
+        { title: '组织机构', scopedSlots: { customRender: 'orgCode' }, width: 150, align: 'center' },
+        { title: '门店名称', dataIndex: 'name', width: 120, align: 'center' },
+        { title: '负责人名称', scopedSlots: { customRender: 'managerName' }, width: 100, align: 'center' },
+        { title: '负责人手机', dataIndex: 'managerMobile', width: 100, align: 'center' },
+        { title: '启用状态', scopedSlots: { customRender: 'enableFlag' }, width: 80, align: 'center' },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 120, align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return findStoreList(Object.assign(parameter, this.queryParam)).then(res => {
+          if (res.status == 200) {
+            const no = (res.data.pageNo - 1) * res.data.pageSize
+            for (let i = 0; i < res.data.list.length; i++) {
+              const _item = res.data.list[i]
+              _item.no = no + i + 1
+              // 重组组织机构
+              let codeNameArr = []
+              if (_item.orgPCodeName) { //  父级组织机构名称
+                const orgPCodeNameArr = _item.orgPCodeName.split(',')
+                codeNameArr = orgPCodeNameArr.splice(0, orgPCodeNameArr.length - 1)
+              }
+              if (_item.orgCodeName) { //  当前组织机构名称
+                codeNameArr.push(_item.orgCodeName)
+              }
+              _item.codeNameArr = codeNameArr
+            }
+            return res.data
+          }
+        })
+      },
+      openModal: false, //  编辑 门店所属组织  弹框展示状态
+      openEquipmentModal: false, //  门店 关联设备  弹框展示状态
+      storeId: '', //  门店id
+      storeCode: '', //  门店code
+      treeData: [] //  组织机构
+    }
+  },
+  mounted () {
+    this.getOrgList()
+  },
+  methods: {
+    //  获取组织机构  数据
+    getOrgList () {
+      findOrgTree().then(res => {
+        if (res.status == 200) {
+          this.treeData = res.data
+        } else {
+          this.treeData = []
+        }
+      })
+    },
+    //  编辑
+    edit (item) {
+      this.storeId = String(item.id)
+      this.storeCode = String(item.code)
+      this.openModal = true
+      this.openEquipmentModal = false
+    },
+    // 新增编辑  提交成功
+    storeSubmit () {
+      this.$refs.table.refresh(true)
+      this.openModal = false
+    },
+    //  设置
+    setEquipment (item) {
+      this.storeId = String(item.id)
+      this.storeCode = String(item.code)
+      this.openEquipmentModal = true
+      this.openModal = false
+    },
+    //  重置
+    reset () {
+      this.queryParam = {
+        name: '', //  门店名称
+        managerMobile: '', //  负责人手机
+        orgCode: null, //  组织机构
+        enableFlag: '' //  启用状态
+      }
+      this.addrCityList = []
+      this.$refs.table.refresh(true)
+    },
+    // 新增、编辑 弹框关闭
+    closeModal () {
+      this.storeId = ''
+      this.storeCode = ''
+      this.openModal = false
+    },
+    // 关联设备 弹框关闭
+    closeDetailsModal () {
+      this.storeId = ''
+      this.storeCode = ''
+      this.openEquipmentModal = false
+    }
+  }
+}
+</script>
+
+<style lang="less">
+.StoreManagement {
+	.table-page-search-wrapper {
+		.search-btn {
+			margin-right: 10px;
+		}
+	}
+}
+</style>

+ 224 - 0
src/views/BasicSettings/StoreModal.vue

@@ -0,0 +1,224 @@
+<template>
+  <a-modal
+    class="StoreModal"
+    centered
+    title="编辑"
+    :width="1000"
+    :footer="null"
+    :destroyOnClose="true"
+    @cancel="isShow = false"
+    v-model="isShow">
+    <!-- 表单 -->
+    <a-form-model
+      class="form"
+      ref="ruleForm"
+      labelAlign="left"
+      :model="form"
+      :rules="rules"
+      :label-col="{ span: 6 }"
+      :wrapper-col="{ span: 18 }">
+      <a-row :gutter="20" v-if="storeInfo">
+        <a-col :span="8" class="item-w">
+          <div class="item-label">门店名称:</div>
+          <div class="item-cont">{{ storeInfo.name ? storeInfo.name : '--' }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">门店负责人:</div>
+          <div class="item-cont">{{ storeInfo.managerName ? storeInfo.managerName : '--' }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">负责人手机:</div>
+          <div class="item-cont">{{ storeInfo.managerMobile ? storeInfo.managerMobile : '--' }}</div>
+        </a-col>
+        <a-col :span="24" class="item-w">
+          <div class="item-label">门店地址:</div>
+          <div class="item-cont" v-if="!storeInfo.addrProvinceName && !storeInfo.addrCityName && !storeInfo.addrDistrictName && !storeInfo.addrDetail">--</div>
+          <div class="item-cont" v-else>{{ storeInfo.addrProvinceName }}{{ storeInfo.addrCityName }}{{ storeInfo.addrDistrictName }}{{ storeInfo.addrDetail }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">纬度:</div>
+          <div class="item-cont">{{ storeInfo.lat ? storeInfo.lat : '--' }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">经度:</div>
+          <div class="item-cont">{{ storeInfo.lng ? storeInfo.lng : '--' }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">营业时间:</div>
+          <div class="item-cont" v-if="!storeInfo.beginTime && !storeInfo.endTime">--</div>
+          <div class="item-cont" v-else>{{ storeInfo.beginTime }} - {{ storeInfo.endTime }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">是否自营:</div>
+          <div class="item-cont">{{ storeInfo.selfFlagDictValue ? storeInfo.selfFlagDictValue : '--' }}</div>
+        </a-col>
+        <a-col :span="8" class="item-w">
+          <div class="item-label">启用状态:</div>
+          <div class="item-cont">{{ storeInfo.enableFlagDictValue ? storeInfo.enableFlagDictValue : '--' }}</div>
+        </a-col>
+        <a-col :span="8">
+          <a-form-model-item class="form-label" label="组织归属" prop="orgCode" :label-col="{ span: 7 }" :wrapper-col="{ span: 17 }">
+            <a-tree-select
+              showSearch
+              id="store-editOrg"
+              v-model="form.orgCode"
+              allowClear
+              style="width: 100%"
+              :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
+              :tree-data="treeData"
+              :replace-fields="{children:'children', title:'name', key:'id', value: 'code' }"
+              placeholder="请选择组织归属"
+              @change="treeChange">
+            </a-tree-select>
+          </a-form-model-item>
+        </a-col>
+        <a-col :span="24">
+          <a-form-model-item class="btn-cont" :label-col="{ span: 0 }" :wrapper-col="{ span: 24 }">
+            <a-button id="store-saveOrg" type="primary" @click="onSubmit">保存</a-button>
+            <a-button id="store-cancelOrg" class="cancel" @click="isShow = false">取消</a-button>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+    </a-form-model>
+  </a-modal>
+</template>
+
+<script>
+import { findStoreDetail, saveStoreOrg } from '@/api/store.js'
+import { findOrgTree } from '@/api/atorg.js'
+export default {
+  name: 'StoreModal',
+  props: {
+    openModal: {
+      //  弹框是否展示
+      type: Boolean,
+      default: false
+    },
+    storeId: {
+      //  门店id
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  弹框是否展示
+      form: { //  编辑
+        orgCode: null //  机构编码
+      },
+      rules: { //  表单校验规则
+        orgCode: [{ required: true, message: '请选择所属组织归属', trigger: 'change' }]
+      },
+      treeData: [], //  组织机构
+      parentCodePaths: '', //  机构编码父路径
+      orgPid: '', //  父级id
+      storeInfo: null //  门店详情
+    }
+  },
+  methods: {
+    //  门店详情
+    getStoreInfo (id) {
+      findStoreDetail({ id: id }).then(res => {
+        if (res.status == 200) {
+          this.storeInfo = res.data
+          this.form.orgCode = res.data.orgCode
+          this.parentCodePaths = res.data.orgCodePaths
+          this.orgPid = res.data.orgPid
+        }
+      })
+    },
+    //  获取组织机构  数据
+    getOrgList () {
+      findOrgTree().then(res => {
+        if (res.status == 200) {
+          this.treeData = res.data
+        } else {
+          this.treeData = []
+        }
+      })
+    },
+    //  组织归属  change
+    treeChange (value, label, extra) {
+      this.parentCodePaths = extra.triggerNode.$options.propsData.dataRef.parentCodePaths
+      this.orgPid = extra.triggerNode.$options.propsData.dataRef.pid
+    },
+    //  保存
+    onSubmit () {
+      const _this = this
+      _this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          const formData = JSON.parse(JSON.stringify(_this.form))
+          formData.id = this.storeId
+          formData.orgCodePaths = this.parentCodePaths
+          formData.orgPid = this.orgPid
+          saveStoreOrg(formData).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('success')
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (val) {
+      if (!val) {
+        this.$emit('close')
+      } else {
+        //  重置表单数据
+        this.form.orgCode = null
+      }
+    },
+    storeId (newValue, oldValue) {
+      if (newValue && this.isShow) {
+        this.getOrgList()
+        this.getStoreInfo(newValue)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .StoreModal{
+    .form{
+      .item-w{
+        display: flex;
+        line-height: 24px;
+        padding: 8px 0;
+        margin-bottom: 24px;
+        .item-label{
+          flex-shrink: 0;
+          width: 90px;
+          text-align: left;
+          font-weight: bold;
+        }
+        .item-cont{
+          flex-grow: 1;
+        }
+      }
+      .btn-cont {
+        text-align: center;
+        .cancel {
+          margin-left: 40px;
+        }
+      }
+      .form-label{
+        .ant-form-item-label{
+          .ant-form-item-required{
+            font-weight: bold;
+            color: rgba(0, 0, 0, 0.65);
+          }
+        }
+      }
+    }
+  }
+</style>

+ 0 - 255
src/views/CardVoucherAuth/user/userList.vue

@@ -1,255 +0,0 @@
-<template>
-  <a-card :bordered="false">
-    <div class="table-page-search-wrapper">
-      <a-form layout="inline">
-        <a-row :gutter="48">
-          <a-col :md="6" :sm="24">
-            <a-form-item label="用户名称">
-              <a-input allowClear v-model.trim="queryParam.name" @pressEnter="$refs.table.refresh(true)" placeholder="请输入用户名称"/>
-            </a-form-item>
-          </a-col>
-          <a-col :md="6" :sm="24">
-            <a-form-item label="手机号码">
-              <a-input allowClear v-model.trim="queryParam.phone" @pressEnter="$refs.table.refresh(true)" placeholder="请输入手机号码"/>
-            </a-form-item>
-          </a-col>
-          <a-col :md="6" :sm="24">
-            <a-form-item label="状态">
-              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.loginFlag" allowClear placeholder="请选择状态"></v-select>
-            </a-form-item>
-          </a-col>
-          <a-col :md="4" :sm="24" class="flex-sp">
-            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
-            <a-button @click="reset">重置</a-button>
-          </a-col>
-        </a-row>
-      </a-form>
-    </div>
-    <a-divider/>
-    <div class="table-operator">
-      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
-    </div>
-    <s-table
-      ref="table"
-      size="default"
-      rowKey="id"
-      :columns="columns"
-      :data="loadData"
-      bordered
-    >
-      <span slot="status" slot-scope="text, record">
-        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.loginFlag" @change="changeFlagHandle(text, record)"/>
-      </span>
-      <div slot="roleNames" slot-scope="text, record" :title="record.roleNames">
-        <span v-if="record.roleNames">{{ record.roleNames.substr(0,12) + '...' }}</span>
-        <span v-else>无</span>
-      </div>
-      <span slot="action" slot-scope="text, record">
-        <template>
-          <div >
-            <a class="action-button" @click="handleEdit(record)">修改</a>
-            <a v-if="record.loginFlag" class="action-button reset-text" @click="resetPassword(record)">重置密码</a>
-            <a v-if="!record.loginFlag" class="action-button red-text" @click="delect(record)">删除</a>
-          </div>
-        </template>
-      </span>
-    </s-table>
-    <userModal :visible="showModal" @refresh="$refs.table.refresh(true)" :data="itemData" @close="showModal = false"></userModal>
-  </a-card>
-</template>
-
-<script>
-import { STable, VSelect } from '@/components'
-import userModal from './userModal.vue'
-import { resetPSD, updateEnableStatus, getPowerUserList, delectUserPower } from '@/api/card-voucher-user.js'
-export default {
-  name: 'UserList',
-  components: {
-    STable, VSelect, userModal
-  },
-  data () {
-    return {
-      // 查询参数
-      queryParam: {
-        name: '',
-        phone: '',
-        loginFlag: ''
-      },
-      showModal: false,
-      itemData: {}, // 编辑行数据
-      // 表头
-      columns: [
-        {
-          title: '序号',
-          dataIndex: 'no',
-          width: '40',
-          align: 'center'
-        },
-        {
-          title: '用户名称',
-          dataIndex: 'name',
-          width: '100',
-          align: 'center'
-        },
-        {
-          title: '手机号码',
-          dataIndex: 'phone',
-          width: '100',
-          align: 'center'
-        },
-        {
-          title: '角色',
-          width: '100',
-          align: 'center',
-          scopedSlots: { customRender: 'roleNames' }
-        },
-        {
-          title: '状态',
-          width: '100',
-          align: 'center',
-          scopedSlots: { customRender: 'status' }
-        },
-        {
-          title: '创建时间',
-          dataIndex: 'createDate',
-          width: '120',
-          align: 'center'
-        },
-        {
-          title: '操作',
-          width: '100',
-          align: 'center',
-          scopedSlots: { customRender: 'action' }
-        }
-      ],
-      // 加载数据方法 必须为 Promise 对象
-      loadData: parameter => {
-        return getPowerUserList(Object.assign(parameter, this.queryParam)).then(res => {
-          const no = (res.data.pageNo - 1) * res.data.pageSize
-          for (let i = 0; i < res.data.list.length; i++) {
-            const _item = res.data.list[i]
-            _item.no = no + i + 1
-            _item.loginFlag = _item.loginFlag + '' === '1'
-          }
-          return res.data
-        })
-      },
-      optionAlertShow: false
-    }
-  },
-  beforeRouteEnter (to, from, next) {
-    next(vm => {
-      // vm.$refs.table.refresh()
-    })
-  },
-  methods: {
-    // 刷新列表
-    refreshTable () {
-      this.$refs.table.refresh(true)
-    },
-    //  重置
-    reset () {
-      this.queryParam = {
-        name: '',
-        phone: '',
-        loginFlag: ''
-      }
-      this.$refs.table.refresh(true)
-    },
-    // 新建
-    openModal () {
-      this.showModal = true
-      this.itemData = {}
-    },
-    // 重置密码
-    resetPassword (row) {
-      resetPSD({
-        id: row.id
-      }).then(res => {
-        if (res.status == 200) {
-          this.$message.success('密码重置成功')
-        } else {
-          this.$message.error(res.message)
-        }
-      }).catch(() => {
-        this.$message.success('密码重置失败, 请稍后重试')
-      })
-    },
-    // 删除
-    delect (row) {
-      const _this = this
-      this.$confirm({
-        title: '警告',
-        content: '删除后无法恢复,确认删除?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          delectUserPower({
-            id: row.id
-          }).then(res => {
-            if (res.status == 200) {
-              _this.$message.success('删除成功')
-              _this.$refs.table.refresh()
-            } else {
-              _this.$message.error(res.message)
-            }
-          }).catch(() => {
-            _this.$message.success('删除失败, 请稍后重试')
-          })
-        }
-      })
-    },
-    getBizStr (storeBizList) {
-      const str = []
-      storeBizList.forEach(item => {
-        str.push(item.bizTypeName)
-      })
-      return str.join(',')
-    },
-    handleEdit (row) {
-      this.showModal = true
-      this.itemData = row
-    },
-    // 修改状态
-    changeFlagHandle (text, record) {
-      const _data = {
-        id: record.id,
-        flag: record.loginFlag ? '1' : '0'
-      }
-      updateEnableStatus(_data).then(res => {
-        if (res.status + '' === '200') {
-          this.$message.success('修改成功')
-        } else {
-          this.$message.error(res.message)
-          record.loginFlag = !record.loginFlag
-        }
-      })
-    }
-  }
-}
-</script>
-<style scoped>
-  .table-page-search-wrapper .ant-form-inline .ant-form-item{
-    margin-bottom: 0;
-  }
-  .flex-sp{
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
-  .action-button{
-   line-height: 40px;
-   white-space: nowrap;
-    padding: 5px 10px;
-    background-color: #1890ff;
-    border-radius: 4px;
-    color: #fff;
-    margin-right: 5px;
-  }
-  .red-text{
-    background-color: red;
-  }
-  .reset-text {
-    background-color: #31b50b;
-  }
-</style>

+ 0 - 265
src/views/CardVoucherAuth/user/userModal.vue

@@ -1,265 +0,0 @@
-<template>
-  <div>
-    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
-      <a-form :form="form" @submit="handleSubmit">
-        <a-row :gutter="24">
-          <a-col :span="12">
-            <!-- 用户名称 -->
-            <a-form-item label="用户名称" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
-              <a-input
-                placeholder="请输入用户名称"
-                v-decorator="['formData.name', {
-                  initialValue: formData.name,
-                  rules: [{ required: true, message: '请输入用户名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
-              />
-            </a-form-item>
-          </a-col>
-          <a-col :span="12">
-            <!-- 手机号码 -->
-            <a-form-item label="手机号码" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
-              <a-input
-                placeholder="请输入手机号码"
-                v-decorator="['formData.phone', {
-                  initialValue: formData.phone,
-                  rules: [{ required: true, message: '请输入手机号码!' },{pattern:/^[1][0-9]{10}$/, message: '请输入正确的手机号码!'}] }]"
-              />
-            </a-form-item>
-          </a-col>
-        </a-row>
-        <a-row :gutter="24">
-          <!-- 性别 -->
-          <a-col :span="12">
-            <a-form-item label="性别" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
-              <v-select
-                code="SEX"
-                v-decorator="[
-                  'formData.sex',
-                  {
-                    initialValue: formData.sex,
-                    rules: [{ required: true, message: '请选择性别!' }] },
-                ]"
-                allowClear ></v-select>
-
-            </a-form-item>
-          </a-col>
-          <!-- 状态 -->
-          <a-col :span="12">
-            <a-form-item label="状态" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
-              <a-radio-group
-                name="radioGroup"
-                v-decorator="[
-                  'formData.loginFlag',
-                  {
-                    initialValue: formData.loginFlag,
-                    rules: [{ required: true, message: '请选择状态!' }] },
-                ]"
-              >
-                <a-radio :value="1">是</a-radio>
-                <a-radio :value="0">否</a-radio>
-              </a-radio-group>
-
-            </a-form-item>
-          </a-col>
-        </a-row>
-        <a-row :gutter="24">
-          <a-col :span="24">
-            <a-form-item label="角色" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
-              <a-select
-                v-decorator="[
-                  'formData.roleNames',
-                  {
-                    initialValue: formData.roleNames,
-                    rules: [{ required: true, message: '请选择状态!' }] },
-                ]"
-                mode="multiple"
-                style="width: 100%"
-                placeholder="请选择角色"
-              >
-                <a-select-option
-                  v-for="item in roleList"
-                  :key="item.id"
-                  :disabled="item.isEnable == '0' ? true : false"
-                >{{ item.name }}</a-select-option
-                >
-              </a-select>
-            </a-form-item>
-          </a-col>
-        </a-row>
-        <a-row :gutter="24">
-          <a-col :span="24">
-            <a-form-item label="备注" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
-              <a-textarea
-                v-decorator="[
-                  'formData.remarks',
-                  {
-                    initialValue: formData.remarks,
-                    rules: [] },
-                ]"
-                style="min-height: 50px;"
-                placeholder=""
-                autosize />
-            </a-form-item>
-          </a-col>
-        </a-row>
-        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
-          <a-button type="primary" @click="handleSubmit()">
-            保存
-          </a-button>
-          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
-            取消
-          </a-button>
-        </a-form-item>
-      </a-form>
-    </a-modal>
-  </div>
-</template>
-
-<script>
-import { STable, VSelect } from '@/components'
-import { getRoleList, saveUserPower } from '@/api/card-voucher-user.js'
-export default {
-  name: 'UserModal',
-  components: {
-    STable, VSelect
-  },
-  props: {
-    visible: {
-      type: Boolean,
-      default: false
-    },
-    data: {
-      type: Object,
-      default: function () {
-        return {}
-      }
-    }
-  },
-  data () {
-    return {
-      titleText: '添加用户',
-      isshow: this.visible,
-      formLayout: 'horizontal',
-      form: this.$form.createForm(this, { name: 'miniForm' }),
-      roleList: [],
-      formData: {
-        roleNames: undefined, // 角色
-        name: '',
-        loginFlag: '', // 活动状态
-        phone: '',
-        sex: '',
-        remarks: ''
-      }
-    }
-  },
-  methods: {
-    cancel (e) {
-      this.clear()
-      this.$emit('close')
-    },
-    // 保存提交
-    handleSubmit () {
-      const _this = this
-      this.form.validateFields((err, values) => {
-        if (!err) {
-          values.formData.roleNames = values.formData.roleNames.join(',')
-          saveUserPower(Object.assign({ id: this.data.id ? this.data.id : '' }, values.formData)).then(res => {
-            if (res.status == 200) {
-              this.$message.success(res.message ? res.message : '保存成功')
-              this.$emit('refresh')
-              setTimeout(function () {
-                _this.cancel()
-              }, 300)
-            } else {
-              this.$message.error(res.message)
-            }
-          })
-        }
-      })
-    },
-    // 取消
-    handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
-    },
-    clear () {
-      this.form.resetFields()
-      delete this.formData.id
-      this.formData.roleNames = []
-      this.formData.name = ''
-      this.formData.loginFlag = ''
-      this.formData.phone = ''
-      this.formData.sex = ''
-      this.formData.remarks = ''
-    },
-    // 获取角色列表接口
-    getRoleList () {
-      getRoleList().then(res => {
-        if (res.status == 200) {
-          this.roleList = res.data
-        } else {
-          this.$message.warning(res.message)
-        }
-      })
-    }
-  },
-  mounted () {
-    this.getRoleList()
-  },
-  beforeCreate () {
-    this.form = this.$form.createForm(this, { name: 'miniForm' })
-  },
-  watch: {
-    visible (newValue, oldValue) {
-      this.isshow = newValue
-    },
-    isshow (newValue, oldValue) {
-      if (newValue) {
-        if (this.data.id) { // 编辑
-          this.titleText = '编辑用户'
-          this.formData = Object.assign({}, this.data)
-          delete this.formData.no
-          let roleNames = this.formData.roleNames
-          if (roleNames) {
-            roleNames = roleNames.split(',')
-            const arr = []
-            roleNames.map(item => {
-              const row = this.roleList.find(a => {
-                return a.name == item
-              })
-              if (row) {
-                arr.push(row.id)
-              }
-            })
-            this.formData.roleNames = arr
-          } else {
-            this.formData.roleNames = []
-          }
-
-          this.formData.loginFlag = Number(this.formData.loginFlag)
-        } else {
-          this.titleText = '添加用户'
-        }
-      } else {
-        this.cancel()
-      }
-    }
-  }
-}
-</script>
-
-<style >
-  .modalBox{
-  }
-  .ant-modal-footer {
-    display: none;
-  }
-</style>

+ 1 - 1
src/views/Home.vue

@@ -13,7 +13,7 @@ export default {
   },
   created () {
   },
-  methods: { 
+  methods: {
   }
 }
 </script>

+ 13 - 27
src/views/CardVoucherAuth/role/menuModal.vue → src/views/SupervisionAuth/role/menuModal.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <a-modal class="modalBox" :title="roleName" v-model="isshow" @cancle="cancel">
+    <a-modal class="modalBox" :title="roleName" v-model="isshow" @cancle="cancel" :centered="true">
       <a-form class="form-box" style="max-height: 600px;" :form="form" @submit="handleSubmit">
         <a-tree
           checkable
@@ -13,10 +13,10 @@
         />
       </a-form>
       <a-form-item :wrapper-col="{ offset: 15 }">
-        <a-button type="primary" @click="handleSubmit()">
+        <a-button type="primary" @click="handleSubmit()" id="menuModal-handleSubmit">
           保存
         </a-button>
-        <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+        <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()" id="menuModal-handleCancel">
           取消
         </a-button>
       </a-form-item>
@@ -26,7 +26,7 @@
 
 <script>
 import { STable, VSelect } from '@/components'
-import { addMenuPower } from '@/api/card-voucher-role.js'
+import { addMenuPower } from '@/api/supervision-role.js'
 export default {
   name: 'RoleModal',
   components: {
@@ -60,13 +60,12 @@ export default {
   },
   methods: {
     onExpand (expandedKeys) {
-      // if not set autoExpandParent to false, if children expanded, parent can not collapse.
-      // or, you can remove all expanded children keys.
       this.expandedKeys = expandedKeys
       this.autoExpandParent = false
     },
     onCheck (checkedKeys, info) {
       this.checkedData = [...checkedKeys, ...info.halfCheckedKeys]
+	  console.log(this.checkedData,'---选中菜单')
       this.checkedKeys = checkedKeys
     },
     cancel (e) {
@@ -84,13 +83,11 @@ export default {
           const arr = this.checkedData.join(',')
           addMenuPower({ id: this.id, menuIds: arr }).then(res => {
             if (res.status == 200) {
-              this.$message.success(res.message ? res.message : '保存成功')
+              this.$message.success(res.message)
               this.$emit('refresh')
               setTimeout(function () {
                 _this.cancel()
               }, 300)
-            } else {
-              this.$message.error(res.message)
             }
           })
         }
@@ -98,24 +95,16 @@ export default {
     },
     // 取消
     handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
+      this.cancel()
     },
     clear () {
       this.form.resetFields()
       this.roleName = ''
       this.id = ''
       this.checkedKeys = []
+      this.expandedKeys = []
     },
+    // 查找叶子节点
     findLeaf (data, arr) {
       for (let i = 0; i < data.length; i++) {
         const node = data[i]
@@ -126,6 +115,7 @@ export default {
             return item == node.id
           })
           if (hasNode) {
+            this.expandedKeys.push(node.id)
             this.checkedKeys.push(node.id)
           }
         }
@@ -142,19 +132,15 @@ export default {
     isshow (newValue, oldValue) {
       if (newValue) {
         if (this.data) { // 编辑
+          console.log(this.data)
           this.treeData = this.data.allMenuList
           this.id = this.data.role.id
           this.roleName = '分配权限' + '(' + this.data.role.name + ')'
           if (this.data.role.menuIds) {
             const arr = this.data.role.menuIds.split(',')
-            const temp = []
-            arr.map(item => {
-              temp.push(Number(item))
-            })
-            this.checkedData = temp
-            this.expandedKeys = temp
+            this.checkedData = arr
             // 找出叶子节点
-            this.findLeaf(this.treeData, temp)
+            this.findLeaf(this.treeData, arr)
           }
         }
       } else {

+ 58 - 45
src/views/CardVoucherAuth/role/roleList.vue → src/views/SupervisionAuth/role/roleList.vue

@@ -5,47 +5,72 @@
         <a-row :gutter="48">
           <a-col :md="6" :sm="24">
             <a-form-item label="角色名称">
-              <a-input allowClear v-model.trim="queryParam.name" @pressEnter="$refs.table.refresh(true)" placeholder="请输入角色名称"/>
+              <a-input allowClear v-model.trim="queryParam.name" @pressEnter="$refs.table.refresh(true)" id="roleList-name" placeholder="请输入角色名称"/>
             </a-form-item>
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="状态">
-              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.isEnable" allowClear placeholder="请选择状态" ></v-select>
+              <v-select code="ENABLE_FLAG" v-model="queryParam.isEnable" id="roleList-isEnable" allowClear placeholder="请选择状态" ></v-select>
             </a-form-item>
           </a-col>
-          <a-col :md="4" :sm="24" class="flex-sp">
-            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
-            <a-button @click="reset">重置</a-button>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)" style="margin-right: 10px;" id="roleList-handSubmit">查询</a-button>
+            <a-button @click="reset" id="roleList-reset">重置</a-button>
           </a-col>
         </a-row>
       </a-form>
     </div>
     <a-divider/>
     <div class="table-operator">
-      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
+      <a-button type="primary" icon="plus" @click="openModal" v-hasPermission="'B_supervision_role_add'" id="roleList-openModal">新增</a-button>
     </div>
 
     <s-table
       ref="table"
       size="default"
-      rowKey="id"
+      :rowKey="(row)=>row.id"
       :columns="columns"
       :data="loadData"
       bordered
     >
       <span slot="status" slot-scope="text, record">
-        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.isEnable" @change="changeFlagHandle(text, record)"/>
+        <a-switch
+          checkedChildren="启用"
+          unCheckedChildren="禁用"
+          v-model="record.isEnable"
+          @change="changeFlagHandle(text, record)"
+          v-hasPermission="'B_supervision_role_enable'"
+          id="roleList-changeFlagHandle"/>
       </span>
-
+      <!-- 角色描述 -->
+      <template slot="remarks" slot-scope="text, record">
+        <span :title="record.remarks" style="display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ record.remarks ?record.remarks :'--' }}</span>
+      </template>
       <span slot="action" slot-scope="text, record">
-        <template>
-          <a class="action-button menu-text" @click="openMenuModal(record)">菜单权限</a>
-          <a class="action-button" @click="handleEdit(record)">修改</a>
-          <a v-if="!record.isEnable" class="action-button red-text" @click="delect(record)">删除</a>
-        </template>
+        <a-icon
+          type="setting"
+          title="菜单权限"
+          class="actionBtn icon-orange"
+          @click="openMenuModal(record)"
+          v-hasPermission="'M_supervision_role_menu'" />
+        <a-icon
+          type="edit"
+          title="编辑"
+          class="actionBtn icon-blues"
+          @click="handleEdit(record)"
+          v-hasPermission="'B_supervision_role_edit'" />
+        <a-icon
+          type="delete"
+          title="删除"
+          class="actionBtn icon-red"
+          v-if="!record.isEnable"
+          v-hasPermission="'B_supervision_role_del'"
+          @click="delect(record)"/>
       </span>
     </s-table>
+    <!-- 新增、编辑角色弹窗 -->
     <roleModal :visible="showModal" :data="itemData" @refresh="refreshTable" @close="showModal = false"></roleModal>
+    <!-- 菜单权限弹窗 -->
     <menuModal :visible="showMenuModal" :data="menuData" @close="showMenuModal = false"></menuModal>
   </a-card>
 </template>
@@ -54,7 +79,7 @@
 import { STable, VSelect } from '@/components'
 import roleModal from './roleModal.vue'
 import menuModal from './menuModal.vue'
-import { getPowerRoleList, updateEnableStatus, delectRolePower, getMenuList } from '@/api/card-voucher-role.js'
+import { getPowerRoleList, updateEnableStatus, delectRolePower, getMenuList } from '@/api/supervision-role.js'
 export default {
   name: 'RoleList',
   components: {
@@ -76,36 +101,38 @@ export default {
         {
           title: '序号',
           dataIndex: 'no',
-          width: '40',
+          width: 60,
+          align: 'center'
+        },
+        {
+          title: '创建时间',
+          dataIndex: 'createDate',
+          width: 200,
           align: 'center'
         },
         {
           title: '角色名称',
           dataIndex: 'name',
-          width: '100',
+          width: 150,
           align: 'center'
         },
         {
           title: '角色描述',
           dataIndex: 'remarks',
-          width: '100',
-          align: 'center'
+          width: 200,
+		  ellipsis: true, // 内容超过宽度 自动出现省略号
+          align: 'center',
+		  scopedSlots: { customRender: 'remarks' }
         },
         {
           title: '状态',
-          width: '100',
+          width: 150,
           align: 'center',
           scopedSlots: { customRender: 'status' }
         },
-        {
-          title: '创建时间',
-          dataIndex: 'createDate',
-          width: '120',
-          align: 'center'
-        },
         {
           title: '操作',
-          width: '100',
+          width: 200,
           align: 'center',
           scopedSlots: { customRender: 'action' }
         }
@@ -117,7 +144,7 @@ export default {
           for (let i = 0; i < res.data.list.length; i++) {
             const _item = res.data.list[i]
             _item.no = no + i + 1
-            _item.isEnable = _item.isEnable + '' === '1'
+            _item.isEnable = _item.isEnable == 1
           }
           return res.data
         })
@@ -125,11 +152,6 @@ export default {
       optionAlertShow: false
     }
   },
-  beforeRouteEnter (to, from, next) {
-    next(vm => {
-      // vm.$refs.table.refresh()
-    })
-  },
   methods: {
     // 刷新列表
     refreshTable () {
@@ -167,6 +189,7 @@ export default {
       const _this = this
       this.$confirm({
         title: '警告',
+		centered: true,
         content: '删除后无法恢复,确认删除?',
         okText: '确定',
         cancelText: '取消',
@@ -175,13 +198,9 @@ export default {
             id: row.id
           }).then(res => {
             if (res.status == 200) {
-              _this.$message.success('删除成功')
+              _this.$message.success(res.message)
               _this.$refs.table.refresh()
-            } else {
-              this.$message.error(res.message)
             }
-          }).catch(() => {
-            _this.$message.success('删除失败, 请稍后重试')
           })
         }
       })
@@ -198,9 +217,8 @@ export default {
       }
       updateEnableStatus(_data).then(res => {
         if (res.status == 200) {
-          this.$message.success('修改成功')
+          this.$message.success(res.message)
         } else {
-          this.$message.error(res.message)
           record.isEnable = !record.isEnable
         }
       })
@@ -212,11 +230,6 @@ export default {
   .table-page-search-wrapper .ant-form-inline .ant-form-item{
     margin-bottom: 0;
   }
-  .flex-sp{
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
   .action-button{
     line-height: 40px;
     white-space: nowrap;

+ 25 - 26
src/views/CardVoucherAuth/role/roleModal.vue → src/views/SupervisionAuth/role/roleModal.vue

@@ -1,21 +1,30 @@
 <template>
   <div>
-    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+    <a-modal
+      class="modalBox"
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      width="45%"
+      :centered="true">
       <a-form :form="form" @submit="handleSubmit">
         <!-- 用户名称 -->
         <a-form-item label="角色名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-input
-            placeholder="请输入角色名称"
+            placeholder="请输入角色名称(最多30个字符)"
+            allowClear
+            :maxLength="30"
+            id="roleModal-name"
             v-decorator="['formData.name', {
-              initialValue: formData.name,
-              rules: [{ required: true, message: '请输入角色名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
+              initialValue: formData.name,getValueFromEvent: $filterEmpty,
+              rules: [{ required: true, message: '请输入角色名称(最多30个字符)!' },{pattern:'^[^<|>]{1,30}$',message:'请输入不含<或>的字符,最多30个字符'}] }]"
           />
         </a-form-item>
-
         <!-- 状态 -->
         <a-form-item label="状态" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-radio-group
             name="radioGroup"
+            id="roleModal-isEnable"
             v-decorator="[
               'formData.isEnable',
               {
@@ -30,21 +39,23 @@
 
         <a-form-item label="角色描述" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-textarea
+            id="roleModal-remarks"
             v-decorator="[
               'formData.remarks',
-              { initialValue: formData.remarks,
+              { initialValue: formData.remarks,getValueFromEvent: $filterEmpty,
                 rules: [] },
             ]"
             style="min-height: 60px;"
-            placeholder=""
+            placeholder="请输入角色描述(最多500个字符)"
+            :maxLength="500"
             autosize />
         </a-form-item>
 
-        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
-          <a-button type="primary" @click="handleSubmit()">
+        <a-form-item :wrapper-col="{ span: 24, offset: 10}" >
+          <a-button type="primary" @click="handleSubmit()" id="roleModal-handleSubmit" :style="{ marginRight: '15px' }">
             保存
           </a-button>
-          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+          <a-button :style="{ marginLeft: '15px' }" @click="handleCancel()" id="roleModal-handleCancel">
             取消
           </a-button>
         </a-form-item>
@@ -56,7 +67,7 @@
 
 <script>
 import { STable, VSelect } from '@/components'
-import { saveRolePower } from '@/api/card-voucher-role.js'
+import { saveRolePower } from '@/api/supervision-role.js'
 export default {
   name: 'RoleModal',
   components: {
@@ -76,7 +87,7 @@ export default {
   },
   data () {
     return {
-      titleText: '添加角色',
+      titleText: '新增角色',
       isshow: this.visible,
       formLayout: 'horizontal',
       form: this.$form.createForm(this, { name: 'roleModal' }),
@@ -106,8 +117,6 @@ export default {
               setTimeout(function () {
                 _this.cancel()
               }, 300)
-            } else {
-              this.$message.error(res.message)
             }
           })
         }
@@ -115,17 +124,7 @@ export default {
     },
     // 取消
     handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
+      this.cancel()
     },
     clear () {
       this.form.resetFields()
@@ -153,7 +152,7 @@ export default {
           delete this.formData.no
           this.formData.isEnable = Number(this.formData.isEnable)
         } else {
-          this.titleText = '添加角色'
+          this.titleText = '新增角色'
         }
       } else {
         this.cancel()

+ 240 - 0
src/views/SupervisionAuth/user/newStoreModal.vue

@@ -0,0 +1,240 @@
+<template>
+  <a-modal
+    v-model="isShow"
+    v-if="isShow"
+    @cancel="cancel"
+    title="选择关联门店"
+    width="60%"
+    :centered="true"
+    :footer="null">
+    <a-row :gutter="24">
+      <a-form class="form-box" :form="form" @submit="handleSubmit">
+        <a-col :span="10">
+          <a-tree
+            v-if="treeData"
+            @expand="onExpand"
+            @select="onSelect"
+            :expandedKeys="expandedKeys"
+			 :autoExpandParent="autoExpandParent"
+            :default-selected-keys="defaultSelectedOrgId"
+            v-model="checkedKeys"
+            :treeData="treeData" />
+        </a-col>
+        <a-col :span="14">
+          <a-table :columns="columns" :data-source="loadData" :pagination="false" :rowKey="(record) => record.id" bordered>
+            <template slot="title">
+              选择门店
+            </template>
+            <span slot="action" slot-scope="text, record">
+              <a-button type="danger" v-if="record.usedFlag == 1" :disabled="true" size="small" id="newStoreModal-delect">已绑定</a-button>
+              <a-button type="primary" v-if="record.usedFlag == 0" @click="handleSubmit(record)" size="small" id="newStoreModal-handleSubmit">绑定</a-button>
+            </span>
+          </a-table>
+        </a-col>
+      </a-form>
+    </a-row>
+  </a-modal>
+</template>
+
+<script>
+import {
+  findOrgTree
+} from '@/api/atorg.js'
+import {
+  STable
+} from '@/components'
+import {
+  getOrgUsedStoreList,
+  saveNewUserStore,
+  deleteUsedStore
+} from '@/api/supervision-user.js'
+export default {
+  name: 'NewStoreModal',
+  components: {
+    STable
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    ddId: {
+      type: String,
+      default: ''
+    }
+
+  },
+  data () {
+    return {
+      isShow: this.visible,
+      loadData: [], // 列表数据
+      expandedKeys: [], // 树节点
+      autoExpandParent: true, // 自动展开父节点
+      checkedKeys: [], // 选中的key值
+      checkedData: [], // 选中的数据
+	  defaultSelectedOrgId: [], // 默认选中的组织机构
+	  selectedKeys: '',	// 组织机构id
+      treeData: [], // 组织机构
+      storeId: '', // 门店id
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '门店名称',
+        dataIndex: 'storeName',
+        width: 100,
+        align: 'center'
+      },
+      {
+        title: '操作',
+        width: 100,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ]
+    }
+  },
+
+  methods: {
+    //  递归函数
+    recursionFun (data) {
+      if (data) {
+        data.map(item => {
+          if (item.children && item.children.length == 0) {
+            item.key = item.id ? item.id : ''
+            item.value = item.id ? item.id : ''
+            item.title = item.name ? item.name : ''
+          } else {
+            item.key = item.id ? item.id : ''
+            item.value = item.id ? item.id : ''
+            item.title = item.name ? item.name : ''
+            this.recursionFun(item.children)
+          }
+        })
+      }
+      return data
+    },
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+    // 点击左侧三角控制展开收起
+    onExpand (expandedKeys) {
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+    onSelect (selectedKeys, info) {
+      this.selectedKeys = selectedKeys[0]	// 选中项的id
+      this.getListData(this.selectedKeys)
+    },
+    // 关闭弹窗
+    clear () {
+      this.selectedKeys = ''
+	  this.treeData = []
+      this.expandedKeys = []	// 为空时显示收起
+	  this.defaultSelectedOrgId = []
+    },
+    // 获取列表数据
+    getListData () {
+      getOrgUsedStoreList({
+        orgId: this.selectedKeys
+      }).then(res => {
+        if (res.status == 200) {
+          res.data.map((item, index) => {
+            item.no = index + 1
+          })
+          this.loadData = res.data
+        } else {
+          this.loadData = []
+        }
+      })
+    },
+    // 绑定
+    handleSubmit (record) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '确认给该督导绑定该门店?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          saveNewUserStore({
+            userId: _this.ddId,
+            storeId: record.storeId
+          }).then(res => {
+            if (res.status == 200) {
+              _this.getListData()
+              _this.$message.success(res.message)
+            } else {
+              _this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 解绑
+    // delect (row) {
+    //   const _this = this
+    //   this.$confirm({
+    //     title: '提示',
+    //     centered: true,
+    //     content: '解绑后数据无法恢复,确认解绑?',
+    //     okText: '确定',
+    //     cancelText: '取消',
+    //     onOk () {
+    //       deleteUsedStore({
+    //         id: row.id
+    //       }).then(res => {
+    //         if (res.status == 200) {
+    //           _this.$message.success(res.message)
+    //           _this.getListData(this.selectedKeys)
+    //         } else {
+    //           _this.$message.error(res.message)
+    //         }
+    //       })
+    //     }
+    //   })
+    // }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'NewStoreModal'
+    })
+  },
+  watch: {
+    checkedKeys (val) {
+      console.log('onCheck', val)
+    },
+    visible (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    isShow (newValue, oldValue) {
+      if (newValue) {
+        // 获取组织机构树的数据
+        findOrgTree().then(res => {
+          if (res.status == 200) {
+            this.treeData = this.recursionFun(res.data)
+            if (this.treeData.length > 0) {
+              this.defaultSelectedOrgId[0] = this.treeData[0].value
+            }
+            console.log(this.treeData, this.defaultSelectedOrgId)
+            this.getListData()
+          } else {
+            this.treeData = []
+            this.loadData = []
+            this.defaultSelectedOrgId = []
+          }
+        })
+      } else {
+        this.$emit('close')
+      }
+    }
+  }
+}
+</script>

+ 156 - 0
src/views/SupervisionAuth/user/usedStoreModal.vue

@@ -0,0 +1,156 @@
+<template>
+  <div>
+    <a-modal
+      v-model="isShow"
+      @cancel="cancel"
+      title="点检关联门店"
+      width="35%"
+      :footer="null"
+      :centered="true">
+      <!-- 新增点检门店按钮 -->
+      <a-button type="primary" icon="plus" @click="openModal" style="margin-bottom: 20px;" id="usedStoreModal-openModal">关联门店</a-button>
+      <!-- 列表 -->
+      <a-table :columns="columns" :data-source="loadData" :pagination="false" :rowKey="(record) => record.id" bordered>
+        <template slot="title">
+          已选门店
+        </template>
+        <span slot="action" slot-scope="text, record">
+         <a-button type="primary" @click="delect(record)" size="small" id="usedStoreModal-delect">解绑</a-button>
+        </span>
+      </a-table>
+    </a-modal>
+    <!-- 新增点检门店弹窗 -->
+    <newStoreModal :visible="showAllStoreModal" :ddId="userId" @close="closeModal"></newStoreModal>
+  </div>
+
+</template>
+
+<script>
+import {
+  STable
+} from '@/components'
+import newStoreModal from './newStoreModal.vue'
+import {
+  getUsedStoreList,
+  deleteUsedStore
+} from '@/api/supervision-user.js'
+export default {
+  name: 'StoreModal',
+  components: {
+    STable,
+    newStoreModal
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    userId: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.visible,
+      showAllStoreModal: false,
+      ddId: '',
+      loadData: [],
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '门店名称',
+        dataIndex: 'storeName',
+        width: 100,
+        align: 'center'
+      },
+      {
+        title: '状态',
+        key: '状态',
+        width: 100,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ]
+    }
+  },
+  methods: {
+    // 关闭弹窗事件
+    closeModal () {
+      this.showAllStoreModal = false
+      this.getListData(this.userId)
+    },
+    // 获取已选列表数据
+    getListData (id) {
+      getUsedStoreList({
+        userId: id
+      }).then(res => {
+        if (res.status == 200) {
+          res.data.map((item, index) => {
+            item.no = index + 1
+          })
+          this.loadData = res.data
+        }
+      })
+    },
+    // 关闭弹窗
+    cancel (e) {
+      this.$emit('close')
+    },
+    // 新增点检门店
+    openModal () {
+      this.showAllStoreModal = true
+      this.ddId = this.userId
+    },
+    // 解绑门店
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '删除后无法恢复,确认删除?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          deleteUsedStore({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.getListData(_this.userId)
+            } else {
+              _this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    isShow (val) {
+      if (!val) {
+        this.$emit('close')
+      }
+    },
+    userId (newValue, oldValue) {
+      console.log(newValue)
+      if (newValue && this.isShow) {
+        this.getListData(newValue)
+      }
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 276 - 0
src/views/SupervisionAuth/user/userList.vue

@@ -0,0 +1,276 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="48">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="员工姓名">
+              <a-input
+                allowClear
+                v-model.trim="queryParam.name"
+                id="userList-name"
+                :maxLength="30"
+                @pressEnter="$refs.table.refresh(true)"
+                placeholder="请输入员工姓名" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="手机号码">
+              <a-input
+                allowClear
+                v-model.trim="queryParam.phone"
+                id="userList-phone"
+                :maxLength="11"
+                @pressEnter="$refs.table.refresh(true)"
+                placeholder="请输入手机号码" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-form-item label="状态">
+              <v-select code="ENABLE_FLAG" id="userList-loginFlag" v-model="queryParam.loginFlag" allowClear placeholder="请选择状态"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)" style="margin-right: 10px;" id="userList-handSubmit">查询</a-button>
+            <a-button @click="reset" id="userList-reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider />
+    <div class="table-operator">
+      <a-button type="primary" icon="plus" @click="openModal" v-hasPermission="'B_supervision_user_add'" id="userList-openModal">新增</a-button>
+    </div>
+    <s-table
+      :columns="columns"
+      :data="loadData"
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      bordered>
+      <template slot="loginFlag" slot-scope="text">
+        <span :style="{ color: text == '1' ? '#12b512' : 'red' }">{{ text == '1' ? '已启用' : '已禁用' }}</span>
+      </template>
+      <template slot="action" slot-scope="text, record">
+        <!-- 点检关联门店 -->
+        <a-icon
+          type="apartment"
+          title="关联点检门店"
+          v-if="record.storeSetFlag==1"
+          v-hasPermission="'M_supervision_user_spotCheckStore'"
+          class="actionBtn icon-green"
+          @click="selectStore(record)" />
+        <a-icon
+          type="unlock"
+          title="重置密码"
+          v-if="record.loginFlag==1"
+          v-hasPermission="'B_supervision_user_restPwd'"
+          class="actionBtn icon-orange"
+          @click="resetPassword(record)" />
+        <a-icon
+          type="edit"
+          title="编辑"
+          class="actionBtn icon-blues"
+          @click="handleEdit(record)"
+          v-hasPermission="'B_supervision_user_edit'" />
+        <a-icon
+          type="delete"
+          title="删除"
+          class="actionBtn icon-red"
+          @click="delect(record)"
+          v-hasPermission="'B_supervision_user_delete'" />
+      </template>
+    </s-table>
+    <!-- 新增用户弹窗 -->
+    <userModal :visible="showModal" @refresh="$refs.table.refresh(true)" :data="itemData" @close="showModal = false"></userModal>
+    <!-- 点检门店弹窗 已选门店 -->
+    <usedStoreModal :visible="showStoreModal" :userId="userId" @close="showStoreModal=false"></usedStoreModal>
+  </a-card>
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import userModal from './userModal.vue'
+import usedStoreModal from './usedStoreModal.vue'
+import {
+  resetPSD,
+  getPowerUserList,
+  delectUserPower
+} from '@/api/supervision-user.js'
+export default {
+  name: 'UserList',
+  components: {
+    STable,
+    VSelect,
+    userModal,
+    usedStoreModal
+  },
+  data () {
+    return {
+      // 查询参数
+      queryParam: {
+        name: '', // 员工姓名
+        phone: '', // 手机号码
+        loginFlag: '' // 状态
+      },
+      showModal: false, // 新增弹框showModal控制打开或关闭  false--默认关闭  true--打开
+      showStoreModal: false, // 点检门店弹框showStoreModal控制打开或关闭  false--默认关闭  true--打开
+      itemData: {}, // 编辑行数据
+      userId: '', // 用户id
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '创建时间',
+        dataIndex: 'createDate',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '员工姓名',
+        dataIndex: 'name',
+        width: 150,
+        align: 'center'
+      },
+      {
+        title: '手机号码',
+        dataIndex: 'phone',
+        width: 150,
+        align: 'center'
+      },
+      {
+        title: '角色',
+        dataIndex: 'roleNames',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '启用状态',
+        dataIndex: 'loginFlag',
+        width: 150,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'loginFlag'
+        }
+      },
+      {
+        title: '操作',
+        dataIndex: 'action',
+        width: 200,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return getPowerUserList(Object.assign(parameter, this.queryParam)).then(res => {
+          const no = (res.data.pageNo - 1) * res.data.pageSize
+          for (let i = 0; i < res.data.list.length; i++) {
+            const _item = res.data.list[i]
+            _item.no = no + i + 1
+          }
+          return res.data
+        })
+      },
+      optionAlertShow: false
+    }
+  },
+  methods: {
+    // 刷新列表
+    refreshTable () {
+      this.$refs.table.refresh(true)
+    },
+    //  重置
+    reset () {
+      this.queryParam = {
+        name: '',
+        phone: '',
+        loginFlag: ''
+      }
+      this.$refs.table.refresh(true)
+    },
+    // 新建
+    openModal () {
+      this.itemData = {}
+      this.showModal = true
+    },
+    // 选择点检门店
+    selectStore (row) {
+      this.userId = row.id
+      this.showStoreModal = true
+    },
+    // 重置密码
+    resetPassword (row) {
+      resetPSD({
+        id: row.id
+      }).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+        } else {
+          this.$message.error(res.message)
+        }
+      })
+    },
+    // 删除
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        centered: true,
+        content: '删除后数据无法恢复,确认删除?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          delectUserPower({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.refreshTable()
+            } else {
+              _this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 编辑
+    handleEdit (row) {
+      this.itemData = row
+      console.log(this.itemData)
+      this.showModal = true
+    }
+  }
+}
+</script>
+<style scoped>
+	.table-page-search-wrapper .ant-form-inline .ant-form-item {
+		margin-bottom: 0;
+	}
+
+	.action-button {
+		line-height: 40px;
+		white-space: nowrap;
+		padding: 5px 10px;
+		background-color: #1890ff;
+		border-radius: 4px;
+		color: #fff;
+		margin-right: 5px;
+	}
+
+	.red-text {
+		background-color: red;
+	}
+
+	.reset-text {
+		background-color: #31b50b;
+	}
+</style>

+ 339 - 0
src/views/SupervisionAuth/user/userModal.vue

@@ -0,0 +1,339 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      width="45%"
+      :centered="true"
+      :footer="null">
+      <a-form :form="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="12">
+            <!-- 用户名称 -->
+            <a-form-item label="员工姓名" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-input
+                placeholder="请输入员工姓名(最多30个字符)"
+                :maxLength="30"
+                id="userModal-name"
+                v-decorator="['formData.name', {
+                  initialValue: formData.name,getValueFromEvent: $filterEmpty,
+                  rules: [{ required: true, message: '请输入员工姓名(最多30个字符)!' }] }]"
+                allowClear />
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <!-- 手机号码 -->
+            <a-form-item label="手机号码" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-input
+                placeholder="请输入手机号码"
+                :maxLength="11"
+                id="userModal-phone"
+                v-decorator="['formData.phone', {
+                  initialValue: formData.phone,getValueFromEvent: $filterEmpty,
+                  rules: [{ required: true, message: '请输入手机号码!' },{pattern:/^[1][0-9]{10}$/, message: '请输入正确的手机号码!'}] }]"
+                allowClear />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <!-- 性别 -->
+          <a-col :span="12">
+            <a-form-item label="性别" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <v-select
+                code="SEX"
+                id="userModal-sex"
+                placeholder="请选择性别"
+                v-decorator="[
+                  'formData.sex',
+                  {
+                    initialValue: formData.sex,
+                    rules: [{ required: true, message: '请选择性别!' }] },
+                ]"
+                allowClear></v-select>
+
+            </a-form-item>
+          </a-col>
+          <!-- 角色 -->
+          <a-col :span="12">
+            <a-form-item label="角色" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-select
+                id="userModal-roleNames"
+                allowClear
+                v-decorator="[
+                  'formData.roleNames',
+                  {
+                    initialValue: formData.roleNames,
+                    rules: [{ required: true, message: '请选择角色!' }] },
+                ]"
+                style="width: 100%"
+                placeholder="请选择角色"
+                mode="multiple">
+                <a-select-option v-for="item in roleList" :key="item.id" :disabled="item.isEnable == '0' ? true : false">{{ item.name }}</a-select-option>
+              </a-select>
+
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="12">
+            <a-form-item class="form-label" label="所属机构" prop="orgCode" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-tree-select
+                id="userModal-orgCode"
+                allowClear
+                style="width: 100%"
+                :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
+                :tree-data="treeData"
+                placeholder="请选择所属机构"
+                treeNodeFilterProp="title"
+                v-decorator="[
+                  'formData.orgCode',
+                  {
+                    initialValue: formData.orgCode,
+                    rules: [{ required: true, message: '请选择所属机构!' }] },
+                ]">
+              </a-tree-select>
+            </a-form-item>
+          </a-col>
+          <!-- 状态 -->
+          <a-col :span="12">
+            <a-form-item label="状态" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-radio-group
+                id="userModal-loginFlag"
+                name="radioGroup"
+                v-decorator="[
+                  'formData.loginFlag',
+                  {
+                    initialValue: formData.loginFlag,
+                    rules: [{ required: true, message: '请选择状态!' }] },
+                ]">
+                <a-radio :value="1">开启</a-radio>
+                <a-radio :value="0">关闭</a-radio>
+              </a-radio-group>
+
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 24, offset: 10 }">
+          <a-button type="primary" @click="handleSubmit()" :style="{ marginRight: '15px' }" id="userModal-handleSubmit">
+            保存
+          </a-button>
+          <a-button :style="{ marginLeft: '15px' }" @click="handleCancel()" id="userModal-handleCancel">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  STable,
+  VSelect,
+  Tree
+} from '@/components'
+import {
+  saveUserPower
+} from '@/api/supervision-user.js'
+import {
+  getAllRole
+} from '@/api/supervision-role.js'
+import {
+  findOrgTree
+} from '@/api/atorg.js'
+export default {
+  name: 'UserModal',
+  components: {
+    STable,
+    VSelect,
+    Tree
+  },
+  props: {
+    // 弹窗是否显示
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 编辑督导的数据
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      titleText: '新增用户',
+      isshow: this.visible,
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, {
+        name: 'miniForm'
+      }),
+      roleList: [], // 角色
+      parentCodePaths: '', // 组织机构父路径
+      formData: {
+        orgCode: null, // 组织机构
+        name: '', // 员工姓名
+        loginFlag: '', // 状态
+        phone: '', // 手机号码
+        sex: '', // 性别
+        roleNames: undefined // 角色
+      },
+      treeData: []
+
+    }
+  },
+  methods: {
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+    // 获取组织机构树的数据
+    getOrgData () {
+      findOrgTree().then(res => {
+        if (res.status == 200) {
+          this.treeData = this.recursionFun(res.data)
+        } else {
+          this.treeData = []
+        }
+      })
+    },
+    //  组织归属  change
+    // treeChange (value, label, extra) {
+    //   this.parentCodePaths = extra.triggerNode.$options.propsData.dataRef.parentCodePaths
+    // },
+    // 递归函数
+    recursionFun (data) {
+      if (data) {
+        data.map(item => {
+          if (item.children && item.children.length == 0) {
+            item.key = item.id ? 'org' + item.id : ''
+            item.value = item.id ? item.id : ''
+            item.title = item.name ? item.name : ''
+          } else {
+            item.key = item.id ? 'org' + item.id : ''
+            item.value = item.id ? item.id : ''
+            item.title = item.name ? item.name : ''
+            this.recursionFun(item.children)
+          }
+        })
+      }
+      return data
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          values.formData.roleNames = values.formData.roleNames.join(',')
+          const formData = JSON.parse(JSON.stringify(values.formData))
+          formData.org = {
+            id: formData.orgCode
+          }
+          delete formData.orgCode
+          saveUserPower(Object.assign({
+            id: this.data.id ? this.data.id : ''
+          }, formData)).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      this.cancel()
+    },
+    clear () {
+      this.form.resetFields()
+      delete this.formData.id
+      this.formData.orgCode = null // 所属机构
+      this.formData.name = '' // 员工姓名
+      this.formData.loginFlag = '' // 状态
+      this.formData.phone = '' // 手机号码
+      this.formData.sex = '' // 性别
+      this.formData.roleNames = undefined // 角色
+    },
+    // 获取角色列表接口
+    getRoleData () {
+      getAllRole().then(res => {
+        if (res.status == 200) {
+          this.roleList = res.data
+        } else {
+          this.$message.warning(res.message)
+        }
+      })
+    },
+    // 编辑赋值
+    pageInitData () {
+      const _this = this
+      this.titleText = '编辑用户'
+      this.formData.name = this.data.name // 员工姓名
+      this.formData.loginFlag = Number(this.data.loginFlag) // 状态
+      this.formData.phone = this.data.phone // 手机号码
+      this.formData.sex = this.data.sex // 性别
+      let roleNames = this.data.roleNames
+      if (roleNames) {
+        roleNames = roleNames.split(',')
+        setTimeout(() => {
+          const arr = []
+          roleNames.map(item => {
+            console.log(item)
+            const row = _this.roleList.find(a => a.name == item)
+            if (row) {
+              arr.push(row.id)
+            }
+          })
+          this.formData.roleNames = arr
+        }, 500)
+      } else {
+        this.formData.roleNames = []
+      }
+      if (this.data.org) {
+        this.formData.orgCode = this.data.org.id // 组织机构
+      } else {
+        this.formData.orgCode = null
+      }
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'miniForm'
+    })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        // console.log(this.data)
+        this.getOrgData() // 打开弹窗获取组织机构数据
+        this.getRoleData() // 打开弹窗获取角色列表数据
+        if (this.data.id) { // 编辑
+          // console.log(this.data.id)
+          this.pageInitData()
+        } else {
+          this.titleText = '新增用户'
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+	.ant-modal-footer {
+		display: none;
+	}
+</style>

+ 174 - 0
src/views/evaluation/evaluationItem/AddEvaIndexModal.vue

@@ -0,0 +1,174 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      :footer="null"
+      centered
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="600">
+      <a-form :form="form" ref="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 考评指标名称 -->
+            <a-form-item label="考评指标名称:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <a-input
+                allowClear
+                id="addEvaIndexModal-name"
+                :maxLength="128"
+                v-decorator="[
+                  'formData.name',
+                  { initialValue: formData.name,
+                    getValueFromEvent: $filterEmpty,
+                    rules: [{ required: true, message: '请输入考评指标名称!' }] },
+                ]"
+                placeholder="请输入考评指标名称(最多128个字符)" />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 15, offset: 9 }">
+          <a-button :loading="loading" id="addEvaIndexModal-submit" type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button id="addEvaIndexModal-cancel" :style="{ marginLeft: '8px' }" @click="cancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  itemIndexSave,
+  itemIndexDetail
+} from '@/api/evaluationItem.js'
+export default {
+  name: 'AddEvaIndexModal',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 关联的考评项id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 要编辑的考评指标id
+    itemIndexId: {
+	  type: [String, Number],
+	  default: ''
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+		  // 编辑 查数据
+        if (this.itemIndexId) {
+          this.getData(this.itemIndexId)
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      form: this.$form.createForm(this, {
+        name: 'AddEvaIndexModal'
+      }),
+      formData: {
+        name: '' // 指标名称
+      },
+	  loading: false // 确定按钮loading
+
+    }
+  },
+  computed: {
+    // 弹框标题
+    titleText () {
+      return this.itemIndexId ? '编辑' : '新增'
+    }
+  },
+  methods: {
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+    // 编辑时,获取数据详情
+    getData (id) {
+      itemIndexDetail({ id: id }).then(res => {
+        if (res.status == 200) {
+          // console.log(res, 'rrrrrrrrrr')
+          this.form.setFieldsValue({ 'formData.name': res.data.name })
+        }
+      })
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          this.loading = true
+          const params = this.itemIndexId ? Object.assign({ assessItemId: this.itemId, id: this.itemIndexId }, values.formData) : Object.assign({ assessItemId: this.itemId }, values.formData)
+          // console.log(params, 'ppppppppppppp')
+          itemIndexSave(params).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    },
+
+    clear () {
+      this.form.resetFields()
+    }
+
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'AddEvaIndexModal'
+    })
+  }
+
+}
+</script>
+
+<style scoped>
+	.modalBox {}
+
+	.ant-modal-footer {
+		display: none;
+	}
+
+	.time-text {
+		color: #1890FF;
+		padding: 0px 20px;
+		cursor: pointer;
+	}
+
+	.labelT {
+		position: absolute;
+		left: -135px;
+		top: 20px;
+		color: rgba(0, 0, 0, 0.85);
+	}
+</style>

+ 196 - 0
src/views/evaluation/evaluationItem/AddEvaItemModal.vue

@@ -0,0 +1,196 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      :footer="null"
+      centered
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="600">
+      <a-form :form="form" ref="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 考评项目名称 -->
+            <a-form-item label="考评项目名称:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <a-input
+                allowClear
+                id="addEvaItemModal-name"
+                :maxLength="128"
+                v-decorator="[
+                  'formData.name',
+                  { initialValue: formData.name,
+                    getValueFromEvent: $filterEmpty,
+                    rules: [{ required: true, message: '请输入考评项目名称!' }] },
+                ]"
+                placeholder="请输入考评项目名称(最多128个字符)!" />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 考评项目说明 -->
+            <a-form-item label="考评项目说明:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <a-textarea
+                allowClear
+                id="addEvaItemModal-desc"
+                :maxLength="500"
+                Input.TextArea
+                :autoSize="{minRows:5}"
+                v-decorator="[
+                  'formData.desc',
+                  { initialValue: formData.desc,getValueFromEvent: $filterEmpty },
+                ]"
+                placeholder="请输入考评项目说明(最多500个字符)" />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 15, offset: 9 }">
+          <a-button :loading="loading" id="addEvaItemModal-submit" type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button id="addEvaItemModal-cancel" :style="{ marginLeft: '8px' }" @click="cancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  itemDetail,
+  itemSave
+} from '@/api/evaluationItem.js'
+export default {
+  name: 'AddEvaItemModal',
+  components: {
+    STable,
+    VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 要编辑的项目id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        this.form.resetFields()
+        // 编辑查详情
+        if (this.itemId) {
+          this.getFormData(this.itemId)
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      form: this.$form.createForm(this, {
+        name: 'AddEvaItemModal'
+      }),
+      formData: {
+        name: '', // 方案名称
+        desc: '' // 方案说明
+      },
+	  loading: false // 确定按钮loading
+    }
+  },
+  computed: {
+    // 弹框标题
+    titleText () {
+      return this.itemId ? '编辑' : '新增'
+    }
+  },
+  methods: {
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.formData.name = ''
+      this.formData.desc = ''
+      this.$emit('close')
+    },
+    // 查详情
+    getFormData (id) {
+      itemDetail({
+        id: id
+      }).then(res => {
+        if (res.status == 200) {
+          // console.log(res, 'rrrrrrrrrr')
+          this.formData = Object.assign(this.formData, res.data)
+          console.log(this.formData, 'this.formData')
+        }
+      })
+    },
+    // 保存提交
+    handleSubmit () {
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          this.loading = true
+          const params = this.itemId ? Object.assign({
+            id: this.itemId
+          }, values.formData) : values.formData
+          // console.log(params, 'ppppppppppppp')
+          itemSave(params).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(() => {
+                this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'AddEvaItemModal'
+    })
+  }
+
+}
+</script>
+
+<style scoped>
+	.modalBox {}
+
+	.ant-modal-footer {
+		display: none;
+	}
+
+	.time-text {
+		color: #1890FF;
+		padding: 0px 20px;
+		cursor: pointer;
+	}
+
+	.labelT {
+		position: absolute;
+		left: -135px;
+		top: 20px;
+		color: rgba(0, 0, 0, 0.85);
+	}
+</style>

+ 274 - 0
src/views/evaluation/evaluationItem/EvaluationItem.vue

@@ -0,0 +1,274 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+        <a-row :gutter="48">
+          <a-col :span="6">
+            <a-form-item label="考评项目名称">
+              <a-input id="evaluationItem-name" allowClear v-model.trim="queryParam.name" placeholder="请输入考评项目名称" />
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-form-item label="启用状态">
+              <v-select
+                id="evaluationItem-status"
+                ref="status"
+                allowClear
+                placeholder="状态"
+                v-model="queryParam.status"
+                code="ENABLE_FLAG"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-button id="evaluationItem-search" type="primary" style="margin-right: 10px;" @click="$refs.table.refresh(true)">查询</a-button>
+            <a-button id="evaluationItem-reset" type="" @click="reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider />
+    <div class="table-operator">
+      <a-button v-hasPermission="'B_evaluationItem_add'" id="evaluationItem-add" type="primary" icon="plus" @click="openModal">新增</a-button>
+    </div>
+    <s-table
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      bordered>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-icon
+          v-hasPermission="'M_evaluationItem_set'"
+          title="设置考评指标"
+          id="evaluationItem-setting"
+          type="setting"
+          class="actionBtn icon-orange"
+          @click="handleSet(record)" />
+        <a-icon
+          id="evaluationItem-edit"
+          title="编辑"
+          type="edit"
+          class="actionBtn icon-blues"
+          v-if="record.status == '0'&& $hasPermissions('B_evaluation_edit')"
+          @click="openModal(record)" />
+        <a-icon
+          id="evaluationItem-delete"
+          title="删除"
+          type="delete"
+          class="actionBtn icon-red"
+          v-if="record.status == '0'&& $hasPermissions('B_evaluationItem_del')"
+          @click="delect(record)" />
+        <span v-if="(!$hasPermissions('B_evaluation_edit') && !$hasPermissions('B_evaluationItem_del') && !$hasPermissions('M_evaluationItem_set'))||(record.status == '1'&& !$hasPermissions('M_evaluationItem_set'))">--</span>
+      </template>
+      <!-- 启用禁用 -->
+      <template slot="enable" slot-scope="text, row">
+        <a-switch
+          v-if="$hasPermissions('B_evaluationItem_enable')"
+          id="evaluationItem-enableStatus"
+          checkedChildren="启用"
+          unCheckedChildren="禁用"
+          v-model="row.status"
+          @change="changeFlagHandle(row)"/>
+        <span v-else :class="[text==1 ? 'green' : 'red']">{{ text==1 ? '已启用' : '已禁用' }}</span>
+      </template>
+    </s-table>
+    <!-- 新增/编辑 弹窗 -->
+    <add-evaItemModal :itemId="itemId" :visible="openAddModal" @refresh="reset" @close="openAddModal=false"></add-evaItemModal>
+    <!-- 设置弹窗 -->
+    <set-evaItemModal :itemId="itemId" :itemName="itemName" :visible="openSetting" @close="openSetting=false"></set-evaItemModal>
+  </a-card>
+
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  getItemListByPage,
+  itemDelete,
+  itemEnable
+} from '@/api/evaluationItem.js'
+import addEvaItemModal from './AddEvaItemModal.vue'
+import setEvaItemModal from './SetEvaItemModal.vue'
+import moment from 'moment'
+export default {
+  name: 'EvaluationPlanList',
+  components: {
+    STable,
+    VSelect,
+    addEvaItemModal,
+    setEvaItemModal
+  },
+  data () {
+    return {
+      moment,
+      pageNo: 1,
+      pageSize: 10,
+      openAddModal: false, // 打开新增弹窗
+	  openSetting: false, // 打开设置弹窗
+      itemId: '', // 要编辑的考评项id
+      itemName: '', // 要编辑的考评项名称
+      // 查询参数
+      queryParam: {
+        name: '', // 项目名称
+        status: '' // 状态
+      },
+      // 表头
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '考评项目名称',
+        dataIndex: 'name',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '考评项目说明',
+        dataIndex: 'desc',
+        width: 300,
+        align: 'center',
+        customRender: (text) => {
+          return text || '--'
+        }
+      },
+      {
+        title: '状态',
+        width: 150,
+        align: 'center',
+        dataIndex: 'status',
+        scopedSlots: {
+          customRender: 'enable'
+        }
+      },
+      {
+        title: '操作',
+        width: 200,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return getItemListByPage(Object.assign(parameter, this.queryParam)).then(res => {
+          if (res.status == 200) {
+            const no = (res.data.pageNo - 1) * res.data.pageSize
+            for (let i = 0; i < res.data.list.length; i++) {
+              const _item = res.data.list[i]
+              _item.no = no + i + 1
+              _item.status = _item.status + '' === '1'
+            }
+            res.data.count = Number(res.data.count)
+            return res.data
+          }
+        })
+      }
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.reset()
+    })
+  },
+  methods: {
+    // 修改状态
+    changeFlagHandle (record) {
+      console.log(record, '222222222')
+      const _data = {
+        id: record.id,
+        status: record.status ? '1' : '0'
+      }
+      itemEnable(_data).then(res => {
+        console.log(res.status)
+        if (res.status == '200') {
+          this.$message.success(res.message)
+          this.$refs.table.refresh()
+        } else {
+          record.status = !record.status
+        }
+      })
+    },
+    // 打开新增弹窗
+    openModal (row) {
+      this.itemId = row ? row.id : ''
+      this.openAddModal = true
+    },
+    // 删除
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '警告',
+        centered: true,
+        content: '删除考评项目时,其关联的考评指标将被同步删除,确认删除吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          itemDelete({
+          	id: row.id
+          }).then(res => {
+          	if (res.status == 200) {
+          		_this.$message.success(res.message)
+          		_this.$refs.table.refresh()
+          	}
+          })
+        }
+      })
+    },
+    // 打开设置弹框
+    handleSet (row) {
+      this.openSetting = true
+	  this.itemId = row.id
+	  this.itemName = row.name
+    },
+    // 重置
+    reset () {
+      this.queryParam = {
+        name: '',
+        status: '' // 状态
+      }
+      this.$refs.table.refresh(true)
+    }
+  }
+}
+</script>
+<style scoped>
+	.table-page-search-wrapper,
+	.addButton {
+		margin-bottom: 0;
+	}
+	.table-page-search-wrapper .ant-form-inline .ant-form-item {
+		margin-bottom: 10px;
+	}
+	.table-operator {
+		margin-bottom: 10px;
+	}
+	.textCount {
+		border: 1px solid #91d5ff;
+		background-color: #e6f7ff;
+		padding: 10px 0;
+		border-radius: 5px;
+		padding-left: 20px;
+		margin: 10px 0;
+	}
+	.action-button {
+		line-height: 40px;
+		white-space: nowrap;
+		padding: 5px 10px;
+		background-color: #1890ff;
+		border-radius: 4px;
+		color: #fff;
+		margin-right: 5px;
+	}
+	.menu-text {
+		background-color: #f90;
+	}
+</style>

+ 173 - 0
src/views/evaluation/evaluationItem/SetEvaItemModal.vue

@@ -0,0 +1,173 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      centered
+      :footer="null"
+      title="设置考评指标"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="'60%'">
+      <a-row :gutter="24" class="header">
+        <div>请给考评项目为【{{ itemName }}】设置考评指标</div>
+        <a-button v-hasPermission="'B_target_add'" id="setEvaItemModal-add" type="primary" @click="openModal">新增</a-button>
+      </a-row>
+      <a-table
+        ref="table"
+        size="default"
+        :pagination="false"
+        :rowKey="(record) => record.id"
+        :columns="columns"
+        :dataSource="list"
+        bordered>
+        <!-- 操作 -->
+        <template slot="action" slot-scope="text, record">
+          <a-icon v-hasPermission="'B_target_edit'" id="setEvaItemModal-edit" type="edit" class="actionBtn icon-blues" @click="openModal(record)" />
+          <a-icon v-hasPermission="'B_target_del'" id="setEvaItemModal-delete" type="delete" class="actionBtn icon-red" @click="delect(record)" />
+          <span v-if="!$hasPermissions('B_target_edit') && !$hasPermissions('B_target_del')">--</span>
+        </template>
+      </a-table>
+      <!-- 新增/编辑 弹窗 -->
+      <add-evaIndexModal :itemId="itemId" :itemIndexId="itemIndexId" :visible="openAddModal" @refresh="getList" @close="openAddModal=false"></add-evaIndexModal>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  itemIndexQuery,
+  itemIndexDelete
+} from '@/api/evaluationItem.js'
+import addEvaIndexModal from './AddEvaIndexModal.vue'
+export default {
+  name: 'SetEvaItemModal',
+  components: {
+    addEvaIndexModal
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 要编辑的考评项id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 要编辑的考评项名称
+    itemName: {
+      type: String,
+      default: ''
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        this.getList()
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      openAddModal: false, // 是否打开编辑/新增弹框
+      itemIndexId: '', // 考评指标id
+      // 表头
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '考评指标名称',
+        dataIndex: 'name',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '操作',
+        width: 150,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ],
+      list: []
+    }
+  },
+  computed: {},
+  methods: {
+    // 获取列表数据
+    getList () {
+      itemIndexQuery({
+        assessItemId: this.itemId
+      }).then(res => {
+        if (res.status == 200) {
+          res.data.map((item, index) => {
+            item.no = index + 1
+          })
+          this.list = res.data
+        } else {
+          this.list = []
+        }
+      })
+    },
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.$emit('close')
+    },
+    // 打开新增/编辑 弹窗
+    openModal (row) {
+      this.itemIndexId = row ? row.id : ''
+      this.openAddModal = true
+    },
+    // 删除考评指标
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '警告',
+        centered: true,
+        content: '删除后原数据不可恢复,是否删除?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          itemIndexDelete({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.getList()
+            }
+          })
+        }
+      })
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'SetEvaItemModal'
+    })
+  }
+
+}
+</script>
+
+<style lang="sass">
+  .modalBox{
+    .header {
+    	font-size: 16px;
+    	font-weight: 600;
+      padding: 0 15px 20px 15px;
+    }
+    .header div {
+    	margin-bottom: 20px;
+    }
+  }
+</style>

+ 253 - 0
src/views/evaluation/evaluationPlan/AddEvaModal.vue

@@ -0,0 +1,253 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      :footer="null"
+      centered
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="600">
+      <a-form :form="form" :model="formData" ref="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 考评方案名称 -->
+            <a-form-item label="考评方案名称:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <a-input
+                allowClear
+                id="addEvaModal-name"
+                :maxLength="128"
+                v-decorator="[
+                  'formData.name',
+                  { initialValue: formData.name,
+                    getValueFromEvent: $filterEmpty,
+                    rules: [{ required: true, message: '请输入考评方案名称!' }] },
+                ]"
+                placeholder="请输入考评方案名称(最多128个字符)" />
+            </a-form-item>
+          </a-col>
+        </a-row>
+
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 适用模式 -->
+            <a-form-item label="适用模式:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <v-select
+                ref="orgType"
+                id="addEvaModal-scopeType"
+                allowClear
+                mode="multiple"
+                @change="scopeTypeChange"
+                v-decorator="[
+                  'formData.scopeType',
+                  { initialValue: formData.scopeType,
+                    rules: [{ required: true, message: '请选择适用模式!' }] },
+                ]"
+                code="ASSESS_SCHEME_SCOPE_TYPE"></v-select>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="20">
+            <!-- 考评方案说明 -->
+            <a-form-item label="考评方案说明:" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+              <a-textarea
+                allowClear
+                id="addEvaModal-desc"
+                :maxLength="500"
+                Input.TextArea
+                :autoSize="{minRows:5}"
+                v-decorator="[
+                  'formData.desc',
+                  { initialValue: formData.desc,getValueFromEvent: $filterEmpty },
+                ]"
+                placeholder="请输入考评方案说明(最多500个字符)" />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 24, offset: 10 }">
+          <a-button :loading="loading" id="addEvaModal-submit" type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button id="addEvaModal-cancel" :style="{ marginLeft: '8px' }" @click="cancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  VSelect
+} from '@/components'
+import {
+  planSave,
+  planDetail
+} from '@/api/evaluationPlan.js'
+export default {
+  name: 'AddEvaModal',
+  components: {
+    VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 要编辑的方案id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        this.form.resetFields()
+        // 编辑查详情
+        if (this.itemId) {
+          this.getFormData(this.itemId)
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      form: this.$form.createForm(this, {
+        name: 'AddEvaModal'
+      }),
+      formData: {
+        name: '', // 方案名称
+        scopeType: [], // 适用类型
+        desc: '' // 方案说明
+      },
+	  loading: false, // 确定按钮loading
+      options: [{
+        code: 'VIDEO_INSPECTION',
+        dispName: '视频巡店',
+        id: 1
+      },
+      {
+        code: 'SPOT_INSPECTION',
+        dispName: '现场巡店',
+        id: 12
+      },
+      {
+        code: 'POINT_INSPECTION',
+        dispName: '点检',
+        id: 13
+      }
+      ]
+    }
+  },
+  computed: {
+    // 弹框标题
+    titleText () {
+      return this.itemId ? '编辑' : '新增'
+    }
+  },
+  methods: {
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.formData = {
+        name: '', // 方案名称
+        scopeType: [], // 适用类型
+        desc: '' // 方案说明
+      }
+      this.$emit('close')
+    },
+    // 查详情
+    getFormData (id) {
+      planDetail({
+        id: id
+      }).then(res => {
+        if (res.status == 200) {
+          // console.log(res, 'rrrrrrrrrr')
+          this.formData = Object.assign(this.formData, res.data)
+          this.formData.scopeType = this.formData.scopeType.split(',')
+        }
+      })
+    },
+    // 使用模式改变
+    scopeTypeChange (v) {
+      this.formData.scopeType = v
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          this.loading = true
+          const params = this.itemId ? Object.assign({
+            id: this.itemId
+          }, values.formData) : values.formData
+          params.scopeType = params.scopeType.join(',')
+          // console.log(params, 'ppppppppppppp')
+          planSave(params).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.cancel()
+        }
+      })
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'AddEvaModal'
+    })
+  }
+
+}
+</script>
+
+<style scoped>
+	.modalBox {}
+
+	.ant-modal-footer {
+		display: none;
+	}
+
+	.time-text {
+		color: #1890FF;
+		padding: 0px 20px;
+		cursor: pointer;
+	}
+
+	.labelT {
+		position: absolute;
+		left: -135px;
+		top: 20px;
+		color: rgba(0, 0, 0, 0.85);
+	}
+</style>

+ 305 - 0
src/views/evaluation/evaluationPlan/EvaluationPlan.vue

@@ -0,0 +1,305 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+        <a-row :gutter="48">
+          <a-col :span="6">
+            <a-form-item label="方案名称">
+              <a-input id="evaluationPlan-name" allowClear v-model.trim="queryParam.name" placeholder="请输入方案名称" />
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-form-item label="启用状态">
+              <v-select
+                id="evaluationPlan-status"
+                ref="status"
+                allowClear
+                placeholder="状态"
+                v-model="queryParam.status"
+                code="ENABLE_FLAG"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :span="6">
+            <a-button id="evaluationPlan-search" type="primary" style="margin-right: 10px;" @click="$refs.table.refresh(true)">查询</a-button>
+            <a-button id="evaluationPlan-reset" type="" @click="reset">重置</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider />
+    <a-row class="add-btn" type="flex" justify="space-between">
+      <a-button v-hasPermission="'B_evaluationPlan_add'" id="evaluationPlan-add" type="primary" icon="plus" @click="openModal">新增</a-button>
+      <a-col v-hasPermission="'M_evaluationPlan_default'" id="evaluationPlan-setDefaultPlan" @click="handleDefaultSet">
+        <a-icon type="setting" class="setting-icon" />
+        <span class="setting">默认方案设置</span>
+      </a-col>
+    </a-row>
+    <s-table
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      bordered>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-icon
+          v-hasPermission="'M_evaluationPlan_setItem'"
+          title="选择考评项目"
+          id="evaluationPlan-setting"
+          type="setting"
+          class="actionBtn icon-orange"
+          @click="handleSet(record)" />
+        <a-icon
+          id="evaluationPlan-edit"
+          title="编辑"
+          type="edit"
+          class="actionBtn icon-blues"
+          v-if="record.status == '0' && $hasPermissions('M_evaluationPlan_edit')"
+          @click="openModal(record)" />
+        <a-icon
+          id="evaluationPlan-delete"
+          title="删除"
+          type="delete"
+          class="actionBtn icon-red"
+          v-if="record.status == '0' && $hasPermissions('B_evaluationPlan_del')"
+          @click="delect(record)" />
+        <span v-if="(!$hasPermissions('M_evaluationPlan_edit') && !$hasPermissions('B_evaluationPlan_del') && !$hasPermissions('M_evaluationPlan_setItem'))||(record.status == '1' && !$hasPermissions('M_evaluationPlan_setItem'))">--</span>
+      </template>
+      <!-- 启用禁用 -->
+      <template slot="enable" slot-scope="text, row">
+        <a-switch
+          v-if="$hasPermissions('B_evaluationPlan_enable')"
+          id="evaluationPlan-enableStatus"
+          checkedChildren="启用"
+          unCheckedChildren="禁用"
+          v-model="row.status"
+          @change="changeFlagHandle(row)" />
+        <span v-else :class="[text==1 ? 'green' : 'red']">{{ text==1 ? '已启用' : '已禁用' }}</span>
+      </template>
+    </s-table>
+    <!-- 新增/编辑 弹窗 -->
+    <add-evaModal :itemId="itemId" :visible="openAddModal" @refresh="reset" @close="openAddModal=false"></add-evaModal>
+    <!-- 选择考评项弹窗 -->
+    <set-evaModal :itemId="itemId" :itemName="itemName" :visible="openSetting" @close="openSetting=false"></set-evaModal>
+    <!-- 设置默认方案弹窗 -->
+    <set-evaDefaultModal :itemId="itemId" :defaultPlanList="defaultPlanList" :visible="openDefaultSetting" @refresh="getDefaultPlan" @close="openDefaultSetting=false"></set-evaDefaultModal>
+  </a-card>
+
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  planQueryByPage,
+  planEnable,
+  planDefaultQuery,
+  planDelete
+} from '@/api/evaluationPlan.js'
+import addEvaModal from './AddEvaModal.vue'
+import setEvaModal from './SetEvaModal.vue'
+import setEvaDefaultModal from './SetEvaDefaultModal.vue'
+export default {
+  name: 'EvaluationPlanList',
+  components: {
+    STable,
+    VSelect,
+    addEvaModal,
+    setEvaModal,
+    setEvaDefaultModal
+  },
+  data () {
+    return {
+      pageNo: 1,
+      pageSize: 10,
+      openAddModal: false, // 打开新增弹窗
+      openSetting: false, // 打开选择考评项弹窗
+      openDefaultSetting: false, // 打开设置默认方案弹窗
+      itemId: '', // 要编辑的方案id
+      itemName: '', // 方案名称
+      defaultPlanList: [], // 默认方案列表
+      // 查询参数
+      queryParam: {
+        name: '',
+        status: '' // 状态
+      },
+      // 表头
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '考评方案名称',
+        dataIndex: 'name',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '考评方案说明',
+        dataIndex: 'desc',
+        width: 300,
+        align: 'center',
+        customRender: (text) => {
+		  return text || '--'
+        }
+      },
+      {
+        title: '适用模式',
+        width: 200,
+        align: 'center',
+        dataIndex: 'scopeTypeDictValue'
+      },
+      {
+        title: '状态',
+        width: 150,
+        align: 'center',
+        dataIndex: 'status',
+        scopedSlots: {
+          customRender: 'enable'
+        }
+      },
+      {
+        title: '操作',
+        width: 200,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return planQueryByPage(Object.assign(parameter, this.queryParam)).then(res => {
+          if (res.status == 200) {
+            const no = (res.data.pageNo - 1) * res.data.pageSize
+            for (let i = 0; i < res.data.list.length; i++) {
+              const _item = res.data.list[i]
+              _item.no = no + i + 1
+              _item.status = _item.status + '' === '1'
+            }
+            return res.data
+          }
+        })
+      }
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.reset()
+      vm.getDefaultPlan()
+    })
+  },
+  methods: {
+    // 默认方案查询
+    getDefaultPlan () {
+      planDefaultQuery().then(res => {
+        // console.log(res, 'rrrrrrrr')
+        if (res.status == 200) {
+          this.defaultPlanList = res.data
+        } else {
+          this.defaultPlanList = []
+        }
+      })
+    },
+    // 修改状态
+    changeFlagHandle (record) {
+      const _data = {
+        id: record.id,
+        status: record.status ? '1' : '0'
+      }
+      planEnable(_data).then(res => {
+        console.log(res.status)
+        if (res.status == '200') {
+          this.$message.success('修改成功')
+          this.$refs.table.refresh()
+        } else {
+          record.status = !record.status
+        }
+      })
+    },
+    // 打开新增弹窗
+    openModal (row) {
+      this.itemId = row ? row.id : ''
+      this.openAddModal = true
+    },
+    // 打开默认方案设置弹窗
+    handleDefaultSet () {
+      this.openDefaultSetting = true
+    },
+    // 删除
+    delect (row) {
+      const _this = this
+      // 判断当前方案是否为默认方案
+      const has = this.defaultPlanList.find(item => item.assessId == row.id)
+      if (has) {
+        this.$warning({
+          title: '警告',
+          centered: true,
+          content: '该考评方案为当前默认考评方案,不能删除,请取消该方案的默认后再进行删除!'
+        })
+      } else {
+        this.$confirm({
+          title: '警告',
+          centered: true,
+          content: '删除后原数据不可恢复,是否删除?',
+          okText: '确定',
+          cancelText: '取消',
+          onOk () {
+            planDelete({
+              id: row.id
+            }).then(res => {
+              if (res.status == 200) {
+                _this.$message.success(res.message)
+                _this.$refs.table.refresh()
+              }
+            })
+          }
+        })
+      }
+    },
+    // 打开设置弹框
+    handleSet (row) {
+      this.itemId = row.id
+      this.itemName = row.name
+      this.openSetting = true
+      console.log(this.openSetting)
+    },
+    // 重置
+    reset () {
+      this.queryParam = {
+        name: '',
+        status: '' // 状态
+      }
+      this.$refs.table.refresh(true)
+    }
+  }
+}
+</script>
+<style scoped>
+	.table-page-search-wrapper,
+	.addButton {
+		margin-bottom: 0;
+	}
+	.table-page-search-wrapper .ant-form-inline .ant-form-item {
+		margin-bottom: 10px;
+	}
+	.add-btn {
+		margin-bottom: 10px;
+	}
+	.setting-icon {
+		font-size: 16px;
+		margin-right: 5px;
+		color: #1890FF;
+	}
+	.setting {
+		font-size: 16px;
+		color: #1890FF;
+		border-bottom: 1px solid #1890FF;
+		cursor: pointer;
+	}
+</style>

+ 243 - 0
src/views/evaluation/evaluationPlan/SetEvaDefaultModal.vue

@@ -0,0 +1,243 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      :footer="null"
+      centered
+      title="默认方案设置"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="600">
+      <a-form :form="form" ref="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="24">
+            <!-- 视频巡店默认方案 -->
+            <a-form-item label="视频巡店默认方案:" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+              <a-select
+                id="setEvaDefaultModal-videoType"
+                @change="videoTypeChange"
+                v-decorator="[
+                  'formData.videoType',
+                  { initialValue: formData.videoType,
+                    rules: [{ required: true, message: '请选择考评方案(单选)!' }] },
+                ]"
+                placeholder="请选择考评方案(单选)">
+                <a-select-option v-for="item in videoPlanList" :key="item.id" :value="item.id">
+                  {{ item.name }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="24">
+            <!-- 现场巡店默认方案 -->
+            <a-form-item label="现场巡店默认方案:" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+              <a-select
+                id="setEvaDefaultModal-spotType"
+                placeholder="请选择考评方案(单选)"
+                @change="spotTypeChange"
+                v-decorator="[
+                  'formData.spotType',
+                  { initialValue: formData.spotType,
+                    rules: [{ required: true, message: '请选择考评方案(单选)!' }] },
+                ]">
+                <a-select-option v-for="item in spotPlanList" :key="item.id" :value="item.id">
+                  {{ item.name }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 24, offset: 10 }">
+          <a-button :loading="loading" id="setEvaDefaultModal-submit" type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button id="setEvaDefaultModal-cancle" :style="{ marginLeft: '8px' }" @click="cancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  planQuery,
+  planDefaultSave
+} from '@/api/evaluationPlan.js'
+export default {
+  name: 'AddEvaModal',
+  components: {
+    STable,
+    VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 要编辑的方案id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 默认方案
+    defaultPlanList: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        this.form.resetFields()
+        // 获取方案列表数据
+        this.getPlanList('VIDEO_INSPECTION')
+        this.getPlanList('SPOT_INSPECTION')
+        // 默认方案回显
+        this.pageInit()
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      form: this.$form.createForm(this, {
+        name: 'AddEvaModal'
+      }),
+      // 默认值设为undefined, 解决placeholder不生效问题
+      formData: {
+        videoType: undefined, // 视频巡店默认方案
+        spotType: undefined // 现场巡店默认方案
+      },
+      videoPlanList: [], // 视频巡店考评方案列表
+      spotPlanList: [], // 现场巡店考评方案列表
+      loading: false // 确定按钮loading
+    }
+  },
+  computed: {},
+  methods: {
+    pageInit () {
+      if (this.defaultPlanList.length) {
+        this.formData.videoType = this.defaultPlanList.find(item => item.scopeType == 'VIDEO_INSPECTION').assessId
+        this.formData.spotType = this.defaultPlanList.find(item => item.scopeType == 'SPOT_INSPECTION').assessId
+      }
+    },
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.formData.videoType = undefined
+      this.formData.spotType = undefined
+      this.$emit('close')
+    },
+    // 获取方案列表数据 "适用范围(视频巡店 VIDEO_INSPECTION /现场巡店 SPOT_INSPECTION/点检 POINT_INSPECTION)
+    getPlanList (type) {
+      planQuery({
+        status: 1,
+        scopeType: type
+      }).then(res => {
+        // console.log(res, res.data, 'rrrrrrrrrr')
+        if (type == 'VIDEO_INSPECTION') {
+          this.videoPlanList = res.data || []
+        }
+        if (type == 'SPOT_INSPECTION') {
+          this.spotPlanList = res.data || []
+        }
+      })
+    },
+    // 视频巡店默认方案改变
+    videoTypeChange (v) {
+      this.formData.videoType = v
+    },
+    // 现场巡店默认方案改变
+    spotTypeChange (v) {
+      this.formData.spotType = v
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          this.loading = true
+          const params = [{
+            assessId: values.formData.videoType,
+            scopeType: 'VIDEO_INSPECTION'
+          },
+          {
+            assessId: values.formData.spotType,
+            scopeType: 'SPOT_INSPECTION'
+          }
+          ]
+          planDefaultSave(params).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              // 保存后更新默认方案
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.cancel()
+        }
+      })
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'AddEvaModal'
+    })
+  }
+
+}
+</script>
+
+<style scoped>
+	.modalBox {}
+
+	.ant-modal-footer {
+		display: none;
+	}
+
+	.time-text {
+		color: #1890FF;
+		padding: 0px 20px;
+		cursor: pointer;
+	}
+
+	.labelT {
+		position: absolute;
+		left: -135px;
+		top: 20px;
+		color: rgba(0, 0, 0, 0.85);
+	}
+</style>

+ 393 - 0
src/views/evaluation/evaluationPlan/SetEvaModal.vue

@@ -0,0 +1,393 @@
+<template>
+  <div>
+    <a-modal
+      class="modalBox"
+      centered
+      :footer="null"
+      title="选择考评项"
+      v-model="isshow"
+      @cancle="cancel"
+      :width="'80%'">
+      <a-row :gutter="24">
+        <a-col class="title" :span="20">
+          <!-- 考评方案名称 -->
+          <span>考评方案名称: {{ itemName }}</span>
+        </a-col>
+      </a-row>
+      <a-row :gutter="24">
+        <a-form :form="form" ref="form" @submit="handleSubmit">
+          <a-card class="card-content">
+            <a-col :span="15">
+              <p>已选考评项目:</p>
+              <!-- 已选考评项列表 -->
+              <a-table
+                ref="table"
+                size="default"
+                :scroll="{y:500}"
+                :pagination="false"
+                :rowKey="(record) => record.id"
+                :columns="columns"
+                :dataSource="checkedList"
+                bordered>
+                <!-- 操作 -->
+                <template slot="action" slot-scope="text, record, index">
+                  <a-button
+                    id="setEvaModal-moveUp"
+                    type="primary"
+                    ghost
+                    size="small"
+                    class="actionBtn"
+                    @click="moveUp(index)"
+                    v-if="index>0"
+                    icon="arrow-up">上移</a-button>
+                  <a-button
+                    id="setEvaModal-moveDown"
+                    type="primary"
+                    ghost
+                    size="small"
+                    class="actionBtn"
+                    @click="moveDown(index)"
+                    v-if="index < checkedList.length-1"
+                    icon="arrow-down">下移</a-button>
+                  <a-button
+                    id="setEvaModal-moveTop"
+                    type="danger"
+                    ghost
+                    size="small"
+                    class="actionBtn"
+                    @click="moveTop(index)"
+                    v-if="index>0"
+                    icon="up">置顶</a-button>
+                  <a-button
+                    id="setEvaModal-moveBottom"
+                    type="danger"
+                    ghost
+                    size="small"
+                    class="actionBtn"
+                    @click="moveBottom(index)"
+                    v-if="index < checkedList.length-1"
+                    icon="down">置底</a-button>
+                </template>
+              </a-table>
+
+            </a-col>
+            <a-col span="1" class="divider">
+            </a-col>
+            <a-col span="8">
+              <a-row>
+                <p>请选择需要的考评项目:</p>
+              </a-row>
+              <s-table
+                ref="tableItem"
+                size="default"
+                :scroll="{y:500}"
+                :showPagination="false"
+                :row-selection="rowSelection"
+                :rowKey="(record) => record.id"
+                :columns="itemColumns"
+                :data="loadItemData"
+                bordered>
+                <!-- 启用禁用 -->
+                <template slot="enable" slot-scope="text, row">
+                  <span :class="[text==1 ? 'green' : 'grey']">{{ text==1 ? '启用' : '禁用' }}</span>
+                </template>
+              </s-table>
+            </a-col>
+          </a-card>
+          <a-form-item class="footer" :wrapper-col="{ span: 24, offset: 12 }">
+            <a-button :loading="loading" id="setEvaModal-submit" type="primary" @click="handleSubmit()">
+              保存
+            </a-button>
+            <a-button id="setEvaModal-cancel" :style="{ marginLeft: '8px' }" @click="cancel()">
+              取消
+            </a-button>
+          </a-form-item>
+        </a-form>
+      </a-row>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  planItemQuery,
+  planItemSave
+} from '@/api/evaluationPlan.js'
+import {
+  getItemList
+} from '@/api/evaluationItem.js'
+export default {
+  name: 'AddEvaModal',
+  components: {
+    STable,
+    VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    // 要编辑的方案id
+    itemId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 要编辑的方案名字
+    itemName: {
+      type: String,
+      default: ''
+    }
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        // 获取已选列表数据
+        this.getCheckedList()
+      } else {
+        this.cancel()
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible, // 弹框显示隐藏
+      form: this.$form.createForm(this, {
+        name: 'SetEvaModal'
+      }),
+      loading: false, // 确定按钮loading
+      // 已选考评项数据
+      checkedList: [], // 已选考评项列表
+      // 表头
+      columns: [{
+        title: '序号',
+        dataIndex: 'no',
+        width: 60,
+        align: 'center'
+      },
+      {
+        title: '考评项目名称',
+        dataIndex: 'assessItemName',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '操作',
+        width: 200,
+        align: 'center',
+        scopedSlots: {
+          customRender: 'action'
+        }
+      }
+      ],
+      // 考评项列表数据
+      itemColumns: [{
+        title: '考评项目名称',
+        dataIndex: 'name',
+        width: 200,
+        align: 'center'
+      },
+      {
+        title: '状态',
+        width: 100,
+        dataIndex: 'status',
+        align: 'center',
+        scopedSlots: {
+          customRender: 'enable'
+        }
+      }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadItemData: parameter => {
+        return getItemList().then(res => {
+          if (res.status == 200) {
+            return res.data
+          }
+        })
+      }
+    }
+  },
+  computed: {
+    // 已选择的复选框
+    selectedRowKeys () {
+      const arr = []
+      this.checkedList.map(item => {
+        arr.push(item.assessItemId)
+      })
+      return arr
+    },
+    // 列表项是否可选择的配置
+    rowSelection () {
+      return {
+        columnTitle: '选择', // 选择框标题
+        columnWidth: 80, // 选择框宽度
+        selectedRowKeys: this.selectedRowKeys, // 指定选中项的 key 数组
+        // 选中项发生变化时的回调 selectedRowKeys:指定选中项的 key 数组 selectedRows:已选中的数组数据
+        onChange: (selectedRowKeys, selectedRows) => {
+          const arr = []
+          let index = 0
+          // 根据选择项的顺序展示已选列表
+          selectedRowKeys.map(item => {
+            index++
+            const p = selectedRows.find(row => row.id == item)
+            const row = {}
+            if (p) {
+              row.no = index
+              row.assessItemId = p.id
+              row.assessItemName = p.name
+              row.assessSchemeId = this.itemId
+              arr.push(row)
+            }
+          })
+          this.checkedList = arr
+          // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows)
+        },
+        getCheckboxProps: record => ({
+          props: {
+            disabled: record.status == '0' // 禁用状态不可选
+          }
+        })
+      }
+    }
+  },
+  methods: {
+    // 获取已选列表数据
+    getCheckedList () {
+      planItemQuery({
+        assessSchemeId: this.itemId
+      }).then(res => {
+        if (res.status == 200) {
+          this.checkedList = res.data
+          this.checkedList.map((item, index) => {
+            item.no = index + 1
+          })
+        } else {
+          this.checkedList = []
+          this.$message.warning(res.message)
+        }
+      })
+    },
+    // 点击弹框x号触发事件
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+    // 上移
+    moveUp (index) {
+      this.moveArr(index, index - 1)
+    },
+    // 下移
+    moveDown (index) {
+      this.moveArr(index, index + 1)
+    },
+    // 置顶
+    moveTop (index) {
+      this.goToArr(index, 1)
+    },
+    // 置底
+    moveBottom (index) {
+      this.goToArr(index, 0)
+    },
+    // 置顶和置底
+    goToArr (index, type) {
+      const arr = this.checkedList
+      const row = arr[index]
+      arr.splice(index, 1)
+      if (type) {
+        arr.unshift(row)
+      } else {
+        arr.push(row)
+      }
+      arr.map((item, index) => {
+        item.no = index + 1
+      })
+    },
+    // 移动
+    moveArr (index1, index2) {
+      const arr = this.checkedList
+      arr[index1] = arr.splice(index2, 1, arr[index1])[0]
+      arr.map((item, index) => {
+        item.no = index + 1
+      })
+      this.checkedList = arr
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          if (!this.checkedList.length) {
+            return this.$message.warning('请先选择考评项目')
+          }
+          this.loading = true
+          planItemSave(this.checkedList).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+    }
+
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, {
+      name: 'SetEvaModal'
+    })
+  }
+
+}
+</script>
+
+<style scoped>
+	.title {
+		font-size: 16px;
+		color: black;
+		padding-bottom: 30px;
+	}
+	.actionBtn {
+		font-size: 12px;
+		margin: 0 5px;
+	}
+	.green {
+		color: #16b50e;
+	}
+	.grey {
+		color: rgb(153, 153, 153);
+	}
+	.footer {
+		margin-top: 20px;
+	}
+</style>

+ 15 - 29
src/views/power/role/menuModal.vue

@@ -1,8 +1,7 @@
 <template>
   <div>
-    <a-modal class="modalBox" :title="roleName" v-model="isshow" @cancle="cancel">
+    <a-modal class="modalBox" :title="roleName" v-model="isshow" @cancle="cancel" :centered="true">
       <a-form class="form-box" style="max-height: 600px;" :form="form" @submit="handleSubmit">
-
         <a-tree
           checkable
           @check="onCheck"
@@ -12,20 +11,18 @@
           v-model="checkedKeys"
           :treeData="treeData"
         />
-
       </a-form>
       <a-form-item :wrapper-col="{ offset: 15 }">
-        <a-button type="primary" @click="handleSubmit()">
+        <a-button type="primary" @click="handleSubmit()" id="menuModal-handleSubmit">
           保存
         </a-button>
-        <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+        <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()" id="menuModal-handleCancel">
           取消
         </a-button>
       </a-form-item>
     </a-modal>
   </div>
 </template>
-
 <script>
 import { STable, VSelect } from '@/components'
 import { addMenuPower } from '@/api/power-role.js'
@@ -62,14 +59,15 @@ export default {
   },
   methods: {
     onExpand (expandedKeys) {
-      // if not set autoExpandParent to false, if children expanded, parent can not collapse.
-      // or, you can remove all expanded children keys.
       this.expandedKeys = expandedKeys
       this.autoExpandParent = false
     },
     onCheck (checkedKeys, info) {
+		
       this.checkedData = [...checkedKeys, ...info.halfCheckedKeys]
+	  console.log(this.checkedData,'选中菜单')
       this.checkedKeys = checkedKeys
+	  console.log(this.checkedKeys,'------',info)
     },
     cancel (e) {
       this.clear()
@@ -86,13 +84,11 @@ export default {
           const arr = this.checkedData.join(',')
           addMenuPower({ id: this.id, menuIds: arr }).then(res => {
             if (res.status == 200) {
-              this.$message.success(res.message ? res.message : '保存成功')
+              this.$message.success(res.message)
               this.$emit('refresh')
               setTimeout(function () {
                 _this.cancel()
               }, 300)
-            } else {
-              this.$message.error(res.message)
             }
           })
         }
@@ -100,24 +96,16 @@ export default {
     },
     // 取消
     handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
+      this.cancel()
     },
     clear () {
       this.form.resetFields()
       this.roleName = ''
       this.id = ''
       this.checkedKeys = []
+      this.expandedKeys = []
     },
+    // 查找叶子节点
     findLeaf (data, arr) {
       for (let i = 0; i < data.length; i++) {
         const node = data[i]
@@ -128,6 +116,7 @@ export default {
             return item == node.id
           })
           if (hasNode) {
+            this.expandedKeys.push(node.id)
             this.checkedKeys.push(node.id)
           }
         }
@@ -144,19 +133,16 @@ export default {
     isshow (newValue, oldValue) {
       if (newValue) {
         if (this.data) { // 编辑
+		console.log(this.data)
           this.treeData = this.data.allMenuList
           this.id = this.data.role.id
           this.roleName = '分配权限' + '(' + this.data.role.name + ')'
           if (this.data.role.menuIds) {
             const arr = this.data.role.menuIds.split(',')
-            const temp = []
-            arr.map(item => {
-              temp.push(Number(item))
-            })
-            this.checkedData = temp
-            this.expandedKeys = temp
+			console.log(arr)
+            this.checkedData = arr
             // 找出叶子节点
-            this.findLeaf(this.treeData, temp)
+            this.findLeaf(this.treeData, arr)
           }
         }
       } else {

+ 65 - 35
src/views/power/role/roleList.vue

@@ -5,24 +5,36 @@
         <a-row :gutter="48">
           <a-col :md="6" :sm="24">
             <a-form-item label="角色名称">
-              <a-input allowClear v-model.trim="queryParam.name" @pressEnter="$refs.table.refresh(true)" placeholder="请输入角色名称"/>
+              <a-input
+                allowClear
+                v-model.trim="queryParam.name"
+                @pressEnter="$refs.table.refresh(true)"
+                :maxLehgth="30"
+                id="roleList-name"
+                placeholder="请输入角色名称"/>
             </a-form-item>
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="状态">
-              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.isEnable" allowClear placeholder="请选择状态" ></v-select>
+              <v-select
+                code="ENABLE_FLAG"
+                v-model="queryParam.isEnable"
+                id="roleList-isEnable"
+                @pressEnter="$refs.table.refresh(true)"
+                allowClear
+                placeholder="请选择状态" ></v-select>
             </a-form-item>
           </a-col>
-          <a-col :md="4" :sm="24" class="flex-sp">
-            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
-            <a-button @click="reset">重置</a-button>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)" style="margin-right: 10px;" id="roleList-handSubmit">查询</a-button>
+            <a-button @click="reset" id="roleList-reset">重置</a-button>
           </a-col>
         </a-row>
       </a-form>
     </div>
     <a-divider/>
     <div class="table-operator">
-      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
+      <a-button type="primary" icon="plus" @click="openModal" id="roleList-openModal" v-hasPermission="'B_power_role_add'">新增</a-button>
     </div>
 
     <s-table
@@ -34,18 +46,43 @@
       bordered
     >
       <span slot="status" slot-scope="text, record">
-        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.isEnable" @change="changeFlagHandle(text, record)"/>
+        <a-switch
+          checkedChildren="启用"
+          unCheckedChildren="禁用"
+          id="roleList-changeFlagHandle"
+          v-model="record.isEnable"
+          @change="changeFlagHandle(text,record)"
+          v-hasPermission="'B_power_role_enable'"/>
       </span>
+      <!-- 角色描述 -->
+      <template slot="remarks" slot-scope="text, record">
+        <span :title="record.remarks" style="display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ record.remarks ?record.remarks : '--' }}</span>
 
+      </template>
       <span slot="action" slot-scope="text, record">
-        <template>
-          <a class="action-button menu-text" @click="openMenuModal(record)">菜单权限</a>
-          <a class="action-button" @click="handleEdit(record)">修改</a>
-          <a v-if="!record.isEnable" class="action-button red-text" @click="delect(record)">删除</a>
-        </template>
+        <a-icon
+          type="setting"
+          title="菜单权限"
+          class="actionBtn icon-orange"
+          @click="openMenuModal(record)"
+          v-hasPermission="'M_power_role_menu'" />
+        <a-icon
+          type="edit"
+          title="编辑"
+          class="actionBtn icon-blues"
+          @click="handleEdit(record)"
+          v-hasPermission="'B_power_role_edit'" />
+        <a-icon
+          type="delete"
+          title="删除"
+          class="actionBtn icon-red"
+          v-if="!record.isEnable && $hasPermissions('B_power_role_del')"
+          @click="delect(record)"/>
       </span>
     </s-table>
+    <!-- 新增、编辑弹窗 -->
     <roleModal :visible="showModal" :data="itemData" @refresh="refreshTable" @close="showModal = false"></roleModal>
+    <!-- 菜单权限弹窗 -->
     <menuModal :visible="showMenuModal" :data="menuData" @close="showMenuModal = false"></menuModal>
   </a-card>
 </template>
@@ -76,36 +113,38 @@ export default {
         {
           title: '序号',
           dataIndex: 'no',
-          width: '40',
+          width: 60,
           align: 'center'
         },
+        {
+		  title: '创建时间',
+		  dataIndex: 'createDate',
+		  width: 200,
+		  align: 'center'
+        },
         {
           title: '角色名称',
           dataIndex: 'name',
-          width: '100',
+          width: 150,
           align: 'center'
         },
         {
           title: '角色描述',
           dataIndex: 'remarks',
-          width: '100',
-          align: 'center'
+          width: 200,
+          ellipsis: true, // 内容超过宽度 自动出现省略号
+          align: 'center',
+          scopedSlots: { customRender: 'remarks' }
         },
         {
           title: '状态',
-          width: '100',
+          width: 150,
           align: 'center',
           scopedSlots: { customRender: 'status' }
         },
-        {
-          title: '创建时间',
-          dataIndex: 'createDate',
-          width: '120',
-          align: 'center'
-        },
         {
           title: '操作',
-          width: '100',
+          width: 200,
           align: 'center',
           scopedSlots: { customRender: 'action' }
         }
@@ -167,6 +206,7 @@ export default {
       const _this = this
       this.$confirm({
         title: '警告',
+        centered: true,
         content: '删除后无法恢复,确认删除?',
         okText: '确定',
         cancelText: '取消',
@@ -177,11 +217,7 @@ export default {
             if (res.status == 200) {
               _this.$message.success('删除成功')
               _this.$refs.table.refresh()
-            } else {
-              this.$message.error(res.message)
             }
-          }).catch(() => {
-            _this.$message.success('删除失败, 请稍后重试')
           })
         }
       })
@@ -198,9 +234,8 @@ export default {
       }
       updateEnableStatus(_data).then(res => {
         if (res.status == 200) {
-          this.$message.success('修改成功')
+          this.$message.success(res.message)
         } else {
-          this.$message.error(res.message)
           record.isEnable = !record.isEnable
         }
       })
@@ -212,11 +247,6 @@ export default {
   .table-page-search-wrapper .ant-form-inline .ant-form-item{
     margin-bottom: 0;
   }
-  .flex-sp{
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
   .action-button{
     line-height: 40px;
     white-space: nowrap;

+ 46 - 40
src/views/power/role/roleModal.vue

@@ -1,50 +1,58 @@
 <template>
   <div>
-    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+    <a-modal
+      class="modalBox"
+      :title="titleText"
+      v-model="isshow"
+      @cancle="cancel"
+      width="45%"
+      :centered="true">
       <a-form :form="form" @submit="handleSubmit">
         <!-- 用户名称 -->
         <a-form-item label="角色名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-input
-            placeholder="请输入角色名称"
+            placeholder="请输入角色名称(最多30个字符)"
+            allowClear
+            :maxLength="30"
+            id="roleModal-name"
             v-decorator="['formData.name', {
-              initialValue: formData.name,
-              rules: [{ required: true, message: '请输入角色名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
-          />
+              initialValue: formData.name,getValueFromEvent: $filterEmpty,
+              rules: [{ required: true, message: '请输入角色名称(最多30个字符)!' }] }]" />
         </a-form-item>
-
         <!-- 状态 -->
         <a-form-item label="状态" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-radio-group
             name="radioGroup"
+            id="roleModal-isEnable"
             v-decorator="[
               'formData.isEnable',
               {
                 initialValue: formData.isEnable,
                 rules: [{ required: true, message: '请选择状态!' }] },
-            ]"
-          >
+            ]">
             <a-radio :value="1">启用</a-radio>
             <a-radio :value="0">禁用</a-radio>
           </a-radio-group>
         </a-form-item>
-
         <a-form-item label="角色描述" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
           <a-textarea
+            id="roleModal-remarks"
             v-decorator="[
               'formData.remarks',
-              { initialValue: formData.remarks,
+              { initialValue: formData.remarks,getValueFromEvent: $filterEmpty,
                 rules: [] },
             ]"
             style="min-height: 60px;"
-            placeholder=""
+            placeholder="请输入角色描述(最多500个字符)"
+            :maxLength="500"
             autosize />
         </a-form-item>
 
-        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
-          <a-button type="primary" @click="handleSubmit()">
+        <a-form-item :wrapper-col="{ span: 24, offset: 10 }">
+          <a-button type="primary" @click="handleSubmit()" id="roleModal-handleSubmit" :style="{ marginRight: '15px' }">
             保存
           </a-button>
-          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+          <a-button :style="{ marginLeft: '15px' }" @click="handleCancel()" id="roleModal-handleCancel">
             取消
           </a-button>
         </a-form-item>
@@ -55,12 +63,18 @@
 </template>
 
 <script>
-import { STable, VSelect } from '@/components'
-import { saveRolePower } from '@/api/power-role.js'
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  saveRolePower
+} from '@/api/power-role.js'
 export default {
   name: 'RoleModal',
   components: {
-    STable, VSelect
+    STable,
+    VSelect
   },
   props: {
     visible: {
@@ -76,10 +90,12 @@ export default {
   },
   data () {
     return {
-      titleText: '添加角色',
+      titleText: '新增角色',
       isshow: this.visible,
       formLayout: 'horizontal',
-      form: this.$form.createForm(this, { name: 'roleModal' }),
+      form: this.$form.createForm(this, {
+        name: 'roleModal'
+      }),
       formData: {
         name: '',
         isEnable: '', // 活动状态
@@ -105,8 +121,6 @@ export default {
               setTimeout(function () {
                 _this.cancel()
               }, 300)
-            } else {
-              this.$message.error(res.message)
             }
           })
         }
@@ -114,17 +128,7 @@ export default {
     },
     // 取消
     handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
+      this.cancel()
     },
     clear () {
       this.form.resetFields()
@@ -136,7 +140,9 @@ export default {
 
   },
   beforeCreate () {
-    this.form = this.$form.createForm(this, { name: 'roleModal' })
+    this.form = this.$form.createForm(this, {
+      name: 'roleModal'
+    })
   },
   watch: {
     visible (newValue, oldValue) {
@@ -150,7 +156,7 @@ export default {
           delete this.formData.no
           this.formData.isEnable = Number(this.formData.isEnable)
         } else {
-          this.titleText = '添加角色'
+          this.titleText = '新增角色'
         }
       } else {
         this.cancel()
@@ -160,10 +166,10 @@ export default {
 }
 </script>
 
-<style >
-  .modalBox{
-  }
-  .ant-modal-footer {
-    display: none;
-  }
+<style>
+	.modalBox {}
+
+	.ant-modal-footer {
+		display: none;
+	}
 </style>

+ 72 - 47
src/views/power/user/userList.vue

@@ -5,31 +5,48 @@
         <a-row :gutter="48">
           <a-col :md="6" :sm="24">
             <a-form-item label="用户名称">
-              <a-input allowClear v-model.trim="queryParam.name" @pressEnter="$refs.table.refresh(true)" placeholder="请输入用户名称"/>
+              <a-input
+                allowClear
+                v-model.trim="queryParam.name"
+                @pressEnter="$refs.table.refresh(true)"
+                placeholder="请输入用户名称"
+                :maxLength="30"
+                id="userList-name"/>
             </a-form-item>
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="手机号码">
-              <a-input allowClear v-model.trim="queryParam.phone" @pressEnter="$refs.table.refresh(true)" placeholder="请输入手机号码"/>
+              <a-input
+                allowClear
+                v-model.trim="queryParam.phone"
+                @pressEnter="$refs.table.refresh(true)"
+                :maxLength="11"
+                placeholder="请输入手机号码"
+                id="userList-phone"/>
             </a-form-item>
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="状态">
-              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.loginFlag" allowClear placeholder="请选择状态"></v-select>
+              <v-select
+                code="ENABLE_FLAG"
+                v-model="queryParam.loginFlag"
+                @pressEnter="$refs.table.refresh(true)"
+                allowClear
+                placeholder="请选择状态"
+                id="userList-engble-flag"></v-select>
             </a-form-item>
           </a-col>
-          <a-col :md="4" :sm="24" class="flex-sp">
-            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
-            <a-button @click="reset">重置</a-button>
+          <a-col :md="6" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)" style="margin-right: 10px;" id="userList-handSubmit">查询</a-button>
+            <a-button @click="reset" id="userList-reset">重置</a-button>
           </a-col>
         </a-row>
       </a-form>
     </div>
     <a-divider/>
     <div class="table-operator">
-      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
+      <a-button type="primary" icon="plus" @click="openModal" v-hasPermission="'B_power_user_add'" id="userList-openModal">新增</a-button>
     </div>
-
     <s-table
       ref="table"
       size="default"
@@ -39,20 +56,36 @@
       bordered
     >
       <span slot="status" slot-scope="text, record">
-        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.loginFlag" @change="changeFlagHandle(text, record)"/>
+        <a-switch
+          checkedChildren="启用"
+          unCheckedChildren="禁用"
+          id="userList-loginFlag"
+          v-model="record.loginFlag"
+          @change="changeFlagHandle(text, record)"
+          v-hasPermission="'B_power_user_enable'"/>
       </span>
-      <div slot="roleNames" slot-scope="text, record" :title="record.roleNames">
-        <span v-if="record.roleNames">{{ record.roleNames.substr(0,12) + '...' }}</span>
-        <span v-else>无</span>
-      </div>
       <span slot="action" slot-scope="text, record">
-        <template>
-          <div >
-            <a class="action-button" @click="handleEdit(record)">修改</a>
-            <a v-if="record.loginFlag" class="action-button reset-text" @click="resetPassword(record)">重置密码</a>
-            <a v-if="!record.loginFlag" class="action-button red-text" @click="delect(record)">删除</a>
-          </div>
-        </template>
+		<template>
+			<a-icon
+			  type="unlock"
+			  title="重置密码"
+			  v-if="record.loginFlag==1 && $hasPermissions('B_power_user_resetPsd')"
+			  class="actionBtn icon-orange"
+			  @click="resetPassword(record)" />
+			<a-icon
+			  type="edit"
+			  title="编辑"
+			  class="actionBtn icon-blues"
+			  @click="handleEdit(record)"
+			  v-if="$hasPermissions('B_power_user_edit')"/>
+			<a-icon
+			  type="delete"
+			  title="删除"
+			  class="actionBtn icon-red"
+			  v-if="record.loginFlag==0 && $hasPermissions('B_power_user_del')"
+			  @click="delect(record)"/>
+			  <span v-if="(record.loginFlag==1 && !$hasPermissions('B_power_user_edit') && !$hasPermissions('B_power_user_resetPsd')) || (record.loginFlag==0 && !$hasPermissions('B_power_user_edit') && !$hasPermissions('B_power_user_del'))">--</span>
+		</template> 
       </span>
     </s-table>
     <userModal :visible="showModal" @refresh="$refs.table.refresh(true)" :data="itemData" @close="showModal = false"></userModal>
@@ -83,43 +116,44 @@ export default {
         {
           title: '序号',
           dataIndex: 'no',
-          width: '40',
+          width: 60,
           align: 'center'
         },
+        {
+		  title: '创建时间',
+		  dataIndex: 'createDate',
+		  width: 200,
+		  align: 'center'
+        },
         {
           title: '用户名称',
           dataIndex: 'name',
-          width: '100',
+          width: 150,
           align: 'center'
         },
         {
           title: '手机号码',
           dataIndex: 'phone',
-          width: '100',
+          width: 150,
           align: 'center'
         },
         {
           title: '角色',
-          width: '100',
-          align: 'center',
-          scopedSlots: { customRender: 'roleNames' }
+          width: 200,
+		  dataIndex: 'roleNames',
+          align: 'center'
+          // scopedSlots: { customRender: 'roleNames' }
         },
         {
           title: '状态',
-          width: '100',
+          width: 150,
           align: 'center',
           scopedSlots: { customRender: 'status' }
         },
-        {
-          title: '创建时间',
-          dataIndex: 'createDate',
-          width: '120',
-          align: 'center'
-        },
         {
           title: '操作',
-          width: '100',
           align: 'center',
+          width: 200,
           scopedSlots: { customRender: 'action' }
         }
       ],
@@ -172,6 +206,7 @@ export default {
       const _this = this
       this.$confirm({
         title: '警告',
+        centered: true,
         content: '删除后无法恢复,确认删除?',
         okText: '确定',
         cancelText: '取消',
@@ -180,13 +215,9 @@ export default {
             id: row.id
           }).then(res => {
             if (res.status == 200) {
-              _this.$message.success('删除成功')
+              _this.$message.success(res.message)
               _this.$refs.table.refresh()
-            } else {
-              _this.$message.error(res.message)
             }
-          }).catch(() => {
-            _this.$message.success('删除失败, 请稍后重试')
           })
         }
       })
@@ -218,10 +249,9 @@ export default {
         flag: record.loginFlag ? '1' : '0'
       }
       updateEnableStatus(_data).then(res => {
-        if (res.status + '' === '200') {
-          this.$message.success('修改成功')
+        if (res.status == 200) {
+          this.$message.success(res.message)
         } else {
-          this.$message.error(res.message)
           record.loginFlag = !record.loginFlag
         }
       })
@@ -233,11 +263,6 @@ export default {
   .table-page-search-wrapper .ant-form-inline .ant-form-item{
     margin-bottom: 0;
   }
-  .flex-sp{
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
   .action-button{
    line-height: 40px;
    white-space: nowrap;

+ 62 - 50
src/views/power/user/userModal.vue

@@ -1,17 +1,27 @@
 <template>
   <div>
-    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+    <a-modal
+      class="modalBox"
+      :title="titleText"
+      :footer="null"
+      v-model="isshow"
+      @cancle="cancel"
+      width="45%"
+      :centered="true">
       <a-form :form="form" @submit="handleSubmit">
         <a-row :gutter="24">
           <a-col :span="12">
             <!-- 用户名称 -->
             <a-form-item label="用户名称" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
               <a-input
-                placeholder="请输入用户名称"
+                placeholder="请输入用户名称(最多30个字符)"
+                allowClear
+                :maxLength="30"
+                id="userModal-name"
                 v-decorator="['formData.name', {
                   initialValue: formData.name,
-                  rules: [{ required: true, message: '请输入用户名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
-              />
+                  getValueFromEvent: $filterEmpty,
+                  rules: [{ required: true, message: '请输入用户名称(最多30个字符)!' }] }]" />
             </a-form-item>
           </a-col>
           <a-col :span="12">
@@ -19,10 +29,12 @@
             <a-form-item label="手机号码" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
               <a-input
                 placeholder="请输入手机号码"
+                allowClear
+                :maxLength="11"
+                id="userModal-phone"
                 v-decorator="['formData.phone', {
-                  initialValue: formData.phone,
-                  rules: [{ required: true, message: '请输入手机号码!' },{pattern:/^[1][0-9]{10}$/, message: '请输入正确的手机号码!'}] }]"
-              />
+                  initialValue: formData.phone,getValueFromEvent: $filterEmpty,
+                  rules: [{ required: true, message: '请输入手机号码!' },{pattern:/^[1][0-9]{10}$/, message: '请输入正确的手机号码!'}] }]" />
             </a-form-item>
           </a-col>
         </a-row>
@@ -32,13 +44,14 @@
             <a-form-item label="性别" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
               <v-select
                 code="SEX"
+                id="userModal-sex"
                 v-decorator="[
                   'formData.sex',
                   {
                     initialValue: formData.sex,
                     rules: [{ required: true, message: '请选择性别!' }] },
                 ]"
-                allowClear ></v-select>
+                allowClear></v-select>
 
             </a-form-item>
           </a-col>
@@ -47,15 +60,15 @@
             <a-form-item label="状态" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
               <a-radio-group
                 name="radioGroup"
+                id="userModal-loginFlag"
                 v-decorator="[
                   'formData.loginFlag',
                   {
                     initialValue: formData.loginFlag,
                     rules: [{ required: true, message: '请选择状态!' }] },
-                ]"
-              >
-                <a-radio :value="1">是</a-radio>
-                <a-radio :value="0">否</a-radio>
+                ]">
+                <a-radio :value="1">开启</a-radio>
+                <a-radio :value="0">关闭</a-radio>
               </a-radio-group>
 
             </a-form-item>
@@ -65,22 +78,17 @@
           <a-col :span="24">
             <a-form-item label="角色" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
               <a-select
+                id="userModal-roleNames"
                 v-decorator="[
                   'formData.roleNames',
                   {
                     initialValue: formData.roleNames,
-                    rules: [{ required: true, message: '请选择状态!' }] },
+                    rules: [{ required: true, message: '请选择角色!' }] },
                 ]"
                 mode="multiple"
                 style="width: 100%"
-                placeholder="请选择角色"
-              >
-                <a-select-option
-                  v-for="item in roleList"
-                  :key="item.id"
-                  :disabled="item.isEnable == '0' ? true : false"
-                >{{ item.name }}</a-select-option
-                >
+                placeholder="请选择角色">
+                <a-select-option v-for="item in roleList" :key="item.id" :disabled="item.isEnable == '0' ? true : false">{{ item.name }}</a-select-option>
               </a-select>
             </a-form-item>
           </a-col>
@@ -89,23 +97,26 @@
           <a-col :span="24">
             <a-form-item label="备注" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
               <a-textarea
+                id="userModal-remarks"
+                :maxLength="500"
                 v-decorator="[
                   'formData.remarks',
                   {
                     initialValue: formData.remarks,
+                    getValueFromEvent: $filterEmpty,
                     rules: [] },
                 ]"
                 style="min-height: 50px;"
-                placeholder=""
+                placeholder="请输入备注(最多500个字符)"
                 autosize />
             </a-form-item>
           </a-col>
         </a-row>
-        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
-          <a-button type="primary" @click="handleSubmit()">
+        <a-form-item :wrapper-col="{ span: 24, offset: 10 }">
+          <a-button type="primary" @click="handleSubmit()" id="userModal-handleSubmit">
             保存
           </a-button>
-          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()" id="userModal-handleCancel">
             取消
           </a-button>
         </a-form-item>
@@ -115,12 +126,19 @@
 </template>
 
 <script>
-import { STable, VSelect } from '@/components'
-import { getRoleList, saveUserPower } from '@/api/power-user.js'
+import {
+  STable,
+  VSelect
+} from '@/components'
+import {
+  getRoleList,
+  saveUserPower
+} from '@/api/power-user.js'
 export default {
   name: 'UserModal',
   components: {
-    STable, VSelect
+    STable,
+    VSelect
   },
   props: {
     visible: {
@@ -136,10 +154,12 @@ export default {
   },
   data () {
     return {
-      titleText: '添加用户',
+      titleText: '新增用户',
       isshow: this.visible,
       formLayout: 'horizontal',
-      form: this.$form.createForm(this, { name: 'miniForm' }),
+      form: this.$form.createForm(this, {
+        name: 'miniForm'
+      }),
       roleList: [],
       formData: {
         roleNames: undefined, // 角色
@@ -162,15 +182,15 @@ export default {
       this.form.validateFields((err, values) => {
         if (!err) {
           values.formData.roleNames = values.formData.roleNames.join(',')
-          saveUserPower(Object.assign({ id: this.data.id ? this.data.id : '' }, values.formData)).then(res => {
+          saveUserPower(Object.assign({
+            id: this.data.id ? this.data.id : ''
+          }, values.formData)).then(res => {
             if (res.status == 200) {
               this.$message.success(res.message ? res.message : '保存成功')
               this.$emit('refresh')
               setTimeout(function () {
                 _this.cancel()
               }, 300)
-            } else {
-              this.$message.error(res.message)
             }
           })
         }
@@ -178,17 +198,7 @@ export default {
     },
     // 取消
     handleCancel () {
-      const _this = this
-      this.$confirm({
-        title: '提示',
-        content: '确定取消吗?',
-        okText: '确定',
-        cancelText: '取消',
-        onOk () {
-          _this.clear()
-          _this.cancel()
-        }
-      })
+      this.cancel()
     },
     clear () {
       this.form.resetFields()
@@ -215,7 +225,9 @@ export default {
     this.getRoleList()
   },
   beforeCreate () {
-    this.form = this.$form.createForm(this, { name: 'miniForm' })
+    this.form = this.$form.createForm(this, {
+      name: 'miniForm'
+    })
   },
   watch: {
     visible (newValue, oldValue) {
@@ -245,7 +257,7 @@ export default {
           }
           this.formData.loginFlag = Number(this.formData.loginFlag)
         } else {
-          this.titleText = '添加用户'
+          this.titleText = '新增用户'
         }
       } else {
         this.cancel()
@@ -255,8 +267,8 @@ export default {
 }
 </script>
 
-<style >
-  .ant-modal-footer {
-    display: none;
-  }
+<style scoped>
+	.ant-modal-footer {
+		display: none;
+	}
 </style>

+ 1 - 3
src/views/user/ChangePwd.vue

@@ -120,10 +120,8 @@ export default {
             password: values.formCustom.passwd
           }).then(res => {
             if (res.status === '200') {
-              _this.$message.success('修改成功, 请重新登录')
+              _this.$message.success(res.message)
               _this.logout()
-            } else {
-              _this.$message.error(res.message)
             }
           })
         }

+ 3 - 3
vue.config.js

@@ -108,9 +108,9 @@ const vueConfig = {
     // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
     proxy: {
       '/api': {
-        // target: 'http://carwash.test.zyucgj.com/cw-admin/',
-        // target: 'http://192.168.16.102:8101/cw-admin/',
-        target: 'https://carwash.test.zyucgj.com/cw-admin/',
+        // target: 'http://192.168.16.100:9102/at-admin/',
+        // target: 'http://192.168.16.105:8202/at-admin/',
+        target: 'https://aitour.test.zyucgj.com/at-admin/',
         ws: false,
         changeOrigin: true,
         pathRewrite: {