Browse Source

Merge branch 'develop' of http://code.dashoo.cn/chengjian/opms_frontend into develop

liuyaqi 3 years ago
parent
commit
abd42f9755
63 changed files with 9417 additions and 765 deletions
  1. 1 1
      .env.production
  2. 0 163
      mock/controller/router.js
  3. 0 40
      mock/controller/system.js
  4. 0 18
      mock/controller/test.js
  5. 0 99
      mock/controller/user.js
  6. 0 99
      mock/index.js
  7. 0 37
      mock/utils/index.js
  8. 4 6
      package.json
  9. 6 0
      src/api/system/user.js
  10. 24 5
      src/store/modules/user.js
  11. 8 0
      src/vab/components/VabAvatar/index.vue
  12. 7 19
      src/vab/components/VabTabs/index.vue
  13. 7 7
      src/vab/styles/default.scss
  14. 1 1
      src/views/base/distributor/components/DistrEdit.vue
  15. 11 3
      src/views/base/distributor/index.vue
  16. 123 90
      src/views/base/product/index.vue
  17. 6 11
      src/views/base/productAuth/index.vue
  18. 69 37
      src/views/base/region/index.vue
  19. 10 9
      src/views/base/regionAuth/index.vue
  20. 30 4
      src/views/contract/components/DetailsCollection.vue
  21. 13 4
      src/views/contract/components/DetailsEnclosure.vue
  22. 12 1
      src/views/contract/components/DetailsInvoice.vue
  23. 5 3
      src/views/contract/detail.vue
  24. 33 6
      src/views/contract/index.vue
  25. 10 2
      src/views/contract/invoice.vue
  26. 1 1
      src/views/customer/components/Allocate.vue
  27. 1 1
      src/views/customer/components/Shift.vue
  28. 10 4
      src/views/customer/detail.vue
  29. 3 3
      src/views/index/index.vue
  30. 12 9
      src/views/login/index.vue
  31. 47 6
      src/views/plat/task/detail.vue
  32. 5 2
      src/views/plat/task/index.vue
  33. 1 1
      src/views/proj/business/components/BusinessEdit.vue
  34. 2 0
      src/views/proj/business/components/BusinessGradation.vue
  35. 12 4
      src/views/proj/business/components/DetailsContact.vue
  36. 11 5
      src/views/proj/business/detail.vue
  37. 12 4
      src/views/proj/business/index.vue
  38. 8 4
      src/views/system/config/index.vue
  39. 18 4
      src/views/system/dept/index.vue
  40. 16 4
      src/views/system/dict/dataList.vue
  41. 16 4
      src/views/system/dict/index.vue
  42. 12 4
      src/views/system/group/index.vue
  43. 8 1
      src/views/system/loginLog/index.vue
  44. 5 3
      src/views/system/menu/index.vue
  45. 8 4
      src/views/system/notice/index.vue
  46. 14 6
      src/views/system/post/index.vue
  47. 12 3
      src/views/system/role/components/RoleDataScopeEdit.vue
  48. 17 9
      src/views/system/role/components/RoleEdit.vue
  49. 15 5
      src/views/system/role/index.vue
  50. 58 0
      src/views/system/user/components/RestPwd.vue
  51. 102 0
      src/views/system/user/components/UserRestPwd.vue
  52. 27 7
      src/views/system/user/index.vue
  53. 9 1
      src/views/work/order/index.vue
  54. BIN
      vab-icons/lib/fonts/remixicon.31d28485.eot
  55. BIN
      vab-icons/lib/fonts/remixicon.881fbc46.woff
  56. BIN
      vab-icons/lib/fonts/remixicon.888e61f0.ttf
  57. BIN
      vab-icons/lib/fonts/remixicon.9915fef9.woff2
  58. 153 0
      vab-icons/lib/img/remixicon.95138f36.svg
  59. 8115 0
      vab-icons/lib/img/remixicon.symbol.f09b1c74.svg
  60. 0 0
      vab-icons/lib/vab-icons.css
  61. 302 0
      vab-icons/lib/vab-icons.umd.min.js
  62. 5 0
      vab-icons/package.json
  63. 0 1
      vue.config.js

+ 1 - 1
.env.production

@@ -1,5 +1,5 @@
 # 租户码
-VUE_APP_TENANT=cp5vbwxy
+VUE_APP_TENANT=8b9ec443
 
 # GateWay地址
 VUE_APP_MicroSrvProxy_API=http://1.15.100.104:9982/

+ 0 - 163
mock/controller/router.js

@@ -1,163 +0,0 @@
-/**
- * @description router全局配置,如有必要可分文件抽离,其中asyncRoutes只有在intelligence模式下才会用到,pro版只支持remixIcon图标,具体配置请查看vip群文档
- */
-const List = [
-  {
-    path: '/',
-    name: 'Root',
-    component: 'Layout',
-    meta: {
-      title: '首页',
-      icon: 'home-2-line',
-      breadcrumbHidden: true,
-    },
-    children: [
-      {
-        path: 'index',
-        name: 'Index',
-        component: '@/views/index',
-        meta: {
-          title: '首页',
-          icon: 'home-2-line',
-          noClosable: true,
-        },
-      },
-    ],
-  },
-  {
-    path: '/test',
-    name: 'Test',
-    component: 'Layout',
-    meta: {
-      title: '测试',
-      icon: 'user-settings-line',
-    },
-    children: [
-      {
-        path: 'testIndex',
-        name: 'TestIndex',
-        // component: '@/views/setting/personalCenter',
-        component: '@/views/test/index',
-        meta: {
-          title: '测试',
-          icon: 'map-pin-user-line',
-        },
-      },
-    ],
-  },
-  {
-    path: '/setting',
-    name: 'PersonnelManagement',
-    component: 'Layout',
-    meta: {
-      title: '配置',
-      icon: 'user-settings-line',
-    },
-    children: [
-      {
-        path: 'personalCenter',
-        name: 'PersonalCenter',
-        // component: '@/views/setting/personalCenter',
-        component: '@/views/system/personal',
-        meta: {
-          title: '个人中心',
-          icon: 'map-pin-user-line',
-        },
-      },
-      {
-        path: 'userManagement',
-        name: 'UserManagement',
-        // component: '@/views/setting/userManagement',
-        component: '@/views/system/user/index',
-        meta: {
-          title: '用户管理',
-          icon: 'user-3-line',
-        },
-      },
-      {
-        path: 'roleManagement',
-        name: 'RoleManagement',
-        // component: '@/views/setting/roleManagement',
-        component: '@/views/system/role/index',
-        meta: {
-          title: '角色管理',
-          icon: 'admin-line',
-        },
-      },
-      {
-        path: 'departmentManagement',
-        name: 'DepartmentManagement',
-        // component: '@/views/setting/departmentManagement',
-        component: '@/views/system/dept/index',
-        meta: {
-          title: '部门管理',
-          icon: 'group-line',
-        },
-      },
-      {
-        path: 'menuManagement',
-        name: 'MenuManagement',
-        // component: '@/views/setting/menuManagement',
-        component: '@/views/system/menu/index',
-        meta: {
-          title: '菜单管理',
-          icon: 'menu-2-fill',
-        },
-      },
-      {
-        path: 'systemLog',
-        name: 'SystemLog',
-        // component: '@/views/setting/systemLog',
-        component: '@/views/system/log',
-        meta: {
-          title: '系统日志',
-          icon: 'file-shield-2-line',
-        },
-      },
-    ],
-  },
-]
-
-module.exports = [
-  {
-    url: '/router/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: { list: List },
-      }
-    },
-  },
-  {
-    url: '/menuManagement/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: {
-          list: [
-            {
-              id: 'root',
-              label: '全部角色',
-              children: [
-                {
-                  id: '610000201008234560',
-                  permission: 'admin',
-                  label: 'admin角色',
-                },
-                {
-                  id: '450000200912071734',
-                  permission: 'editor',
-                  label: 'editor角色',
-                },
-              ],
-            },
-          ],
-        },
-      }
-    },
-  },
-]

+ 0 - 40
mock/controller/system.js

@@ -1,40 +0,0 @@
-const roleList = [
-  {
-    id: 1,
-    role: 'admin',
-    btnRolesCheckedList: ['read:system', 'write:system', 'delete:system'],
-  },
-]
-const deptList = [
-  {
-    id: 1,
-    name: '研发部',
-    parentId: 0,
-    order: '1',
-    createTime: new Date().toLocaleString(),
-  },
-]
-module.exports = [
-  {
-    url: '/roleManagement/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: { list: roleList, total: 1 },
-      }
-    },
-  },
-  {
-    url: '/departmentManagement/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: { list: deptList, total: 1 },
-      }
-    },
-  },
-]

+ 0 - 18
mock/controller/test.js

@@ -1,18 +0,0 @@
-const List = [
-  {
-    id: 1,
-  },
-]
-module.exports = [
-  {
-    url: '/test/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: { list: List, total: 123 },
-      }
-    },
-  },
-]

+ 0 - 99
mock/controller/user.js

@@ -1,99 +0,0 @@
-const { Random } = require('mockjs')
-const tokens = {
-  admin: `admin-token-${Random.guid()}-${new Date().getTime()}`,
-  editor: `editor-token-${Random.guid()}-${new Date().getTime()}`,
-  test: `test-token-${Random.guid()}-${new Date().getTime()}`,
-}
-const username2role = {
-  admin: ['Admin'],
-  editor: ['Editor'],
-  test: ['Admin', 'Editor'],
-}
-const role2permission = {
-  Admin: ['read:system', 'write:system', 'delete:system'],
-  Editor: ['read:system', 'write:system'],
-  Test: ['read:system'],
-}
-
-module.exports = [
-  {
-    url: '/login',
-    type: 'post',
-    response(config) {
-      const { username } = config.body
-      const token = tokens[username]
-      if (!token)
-        return {
-          code: 500,
-          msg: '帐户或密码不正确',
-        }
-      return {
-        code: 200,
-        msg: 'success',
-        data: { token },
-      }
-    },
-  },
-  {
-    url: '/userInfo',
-    type: 'get',
-    response(config) {
-      const authorization =
-        config.headers.authorization || config.headers.Authorization
-      if (!authorization.startsWith('Bearer '))
-        return {
-          code: 401,
-          msg: '令牌无效',
-        }
-
-      const username = authorization.replace('Bearer ', '').split('-token-')[0]
-      const roles = username2role[username] || []
-      const permissions = [
-        ...new Set(roles.flatMap((role) => role2permission[role])),
-      ]
-
-      return {
-        code: 200,
-        msg: 'success',
-        data: {
-          username,
-          roles,
-          permissions,
-          avatar: 'https://i.gtimg.cn/club/item/face/img/2/16022_100.gif',
-        },
-      }
-    },
-  },
-  {
-    url: '/logout',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-      }
-    },
-  },
-  {
-    url: '/userManagement/getList',
-    type: 'get',
-    response() {
-      return {
-        code: 200,
-        msg: 'success',
-        data: {
-          list: [
-            {
-              id: 1,
-              username: '管理员',
-              email: '123@123.com',
-              roles: ['admin'],
-              datatime: new Date().toLocaleString(),
-            },
-          ],
-          total: 1,
-        },
-      }
-    },
-  },
-]

+ 0 - 99
mock/index.js

@@ -1,99 +0,0 @@
-const chokidarNext = require('chokidar-next')
-const bodyParser = require('body-parser')
-const chalkNext = require('chalk-next')
-const path = require('path')
-const { mock } = require('mockjs')
-const { baseURL } = require('../src/config')
-const mockDir = path.join(process.cwd(), 'mock')
-const { handleMockArray } = require('./utils')
-
-/**
- *
- * @param url
- * @param type
- * @param respond
- * @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
- */
-const responseFake = (url, type, respond) => {
-  return {
-    url: new RegExp(`${baseURL}${url}`),
-    type: type || 'get',
-    response(req, res) {
-      res.status(200)
-      console.log(chalkNext.green(`\n> 请求地址:${req.path}`))
-      if (JSON.stringify(req.body) !== '{}')
-        console.log(
-          chalkNext.green(`> 请求参数(body):${JSON.stringify(req.body)}`)
-        )
-      if (JSON.stringify(req.query) !== '{}')
-        console.log(
-          chalkNext.green(`> 请求参数(query):${JSON.stringify(req.query)}`)
-        )
-      res.json(mock(respond instanceof Function ? respond(req, res) : respond))
-    },
-  }
-}
-
-/**
- *
- * @param app
- * @returns {{mockStartIndex: number, mockRoutesLength: number}}
- */
-const registerRoutes = (app) => {
-  let mockLastIndex
-  const mocks = []
-  const mockArray = handleMockArray()
-  mockArray.forEach((item) => {
-    const obj = require(item)
-    mocks.push(...obj)
-  })
-  const mocksForServer = mocks.map((route) =>
-    responseFake(route.url, route.type, route.response)
-  )
-  const mockRoutesLength = Object.keys(mocksForServer).length
-  for (const item of mocksForServer) {
-    app[item.type](item.url, item.response)
-    mockLastIndex = app._router.stack.length
-  }
-  return {
-    mockRoutesLength,
-    mockStartIndex: mockLastIndex - mockRoutesLength,
-  }
-}
-
-/**
- *
- * @param app
- */
-module.exports = (app) => {
-  app.use(bodyParser.json())
-  app.use(
-    bodyParser.urlencoded({
-      extended: true,
-    })
-  )
-  const mockRoutes = registerRoutes(app)
-  let mockRoutesLength = mockRoutes.mockRoutesLength
-  let mockStartIndex = mockRoutes.mockStartIndex
-  chokidarNext
-    .watch(mockDir, {
-      ignored: /vab-mock-server/,
-      ignoreInitial: true,
-    })
-    .on('all', (event) => {
-      if (event === 'change' || event === 'add') {
-        try {
-          app._router.stack.splice(mockStartIndex, mockRoutesLength)
-          Object.keys(require.cache).forEach((item) => {
-            if (item.includes(mockDir))
-              delete require.cache[require.resolve(item)]
-          })
-          const mockRoutes = registerRoutes(app)
-          mockRoutesLength = mockRoutes.mockRoutesLength
-          mockStartIndex = mockRoutes.mockStartIndex
-        } catch (error) {
-          console.log(chalkNext.red(error))
-        }
-      }
-    })
-}

+ 0 - 37
mock/utils/index.js

@@ -1,37 +0,0 @@
-const fs = require('fs')
-const { Random } = require('mockjs')
-
-/**
- * @description 随机生成图片url。
- * @returns {string}
- */
-function handleRandomImage(/* width = 50, height = 50 */) {
-  //return `https://picsum.photos/${width}/${height}?random=${Random.guid()}`
-  return `https://gitee.com/chu1204505056/image/raw/master/table/vab-image-${Random.integer(
-    1,
-    38
-  )}.jpg`
-}
-
-/**
- * @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
- * @returns {[]}
- */
-function handleMockArray() {
-  const getFiles = (path, baseUrl = './controller') => {
-    const files = fs.readdirSync(path)
-    return files.flatMap((file) => {
-      const fPath = `${path}/${file}`
-      const stat = fs.statSync(fPath)
-      return stat.isDirectory()
-        ? getFiles(fPath, `${baseUrl}/${file}`)
-        : `${baseUrl}/${file}`
-    })
-  }
-  return getFiles('mock/controller')
-}
-
-module.exports = {
-  handleRandomImage,
-  handleMockArray,
-}

+ 4 - 6
package.json

@@ -32,13 +32,14 @@
     "qs": "^6.10.2",
     "resize-detector": "^0.3.0",
     "screenfull": "5.2.0",
-    "vab-icons": "^0.0.23",
+    "vab-icons": "file:vab-icons",
     "vue": "^2.6.14",
     "vue-grid-layout": "^2.4.0",
     "vue-i18n": "^8.26.7",
     "vue-router": "^3.5.3",
     "vuedraggable": "^2.24.3",
-    "vuex": "^3.6.2"
+    "vuex": "^3.6.2",
+    "watermark-dom": "^2.3.0"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "^4.5.15",
@@ -48,14 +49,12 @@
     "@vue/cli-service": "^4.5.15",
     "@vue/eslint-config-prettier": "^6.0.0",
     "body-parser": "^1.19.1",
-    "chalk-next": "^6.1.5",
-    "chokidar-next": "^4.0.10",
     "compression-webpack-plugin": "6.1.1",
     "eslint": "7.32.0",
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-vue": "^8.2.0",
     "filemanager-webpack-plugin": "3.1.1",
-    "image-webpack-loader": "^8.0.1",
+    "image-webpack-loader": "^8.1.0",
     "lint-staged": "^12.1.2",
     "plop": "^3.0.5",
     "postcss-html": "^1.3.0",
@@ -70,7 +69,6 @@
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-recess-order": "^3.0.0",
     "svg-sprite-loader": "^6.0.11",
-    "vab-templates": "^0.0.5",
     "vue-eslint-parser": "^8.0.1",
     "vue-template-compiler": "^2.6.14",
     "webpackbar": "^5.0.2"

+ 6 - 0
src/api/system/user.js

@@ -24,4 +24,10 @@ export default {
   doDelete(query) {
     return micro_request.postRequest(basePath, 'User', 'DeleteByIds', query)
   },
+  resetPwd(query) {
+    return micro_request.postRequest(basePath, 'User', 'ResetPassword', query)
+  },
+  changePwd(query) {
+    return micro_request.postRequest(basePath, 'User', 'ChangePassword', query)
+  },
 }

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

@@ -7,20 +7,25 @@ import { getToken, removeToken, setToken } from '@/utils/token'
 import { resetRouter } from '@/router'
 import { isArray, isString } from '@/utils/validate'
 import { title, tokenName } from '@/config'
+import watermark from 'watermark-dom'
 
 const state = () => ({
   id: '',
   token: getToken(),
   username: '游客',
   nickName: '',
-  avatar: 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif',
+  phone: '',
+  avatar: require('@/assets/login_images/user_avatar.png'),
+  isFirstLogin: false,
 })
 const getters = {
   id: (state) => state.id,
   token: (state) => state.token,
   username: (state) => state.username,
   nickName: (state) => state.nickName,
+  phone: (state) => state.phone,
   avatar: (state) => state.avatar,
+  isFirstLogin: (state) => state.isFirstLogin,
 }
 const mutations = {
   /**
@@ -32,6 +37,10 @@ const mutations = {
     state.token = token
     setToken(token)
   },
+  setIsFirstLogin(state, isFirstLogin) {
+    state.isFirstLogin = isFirstLogin
+    localStorage.setItem('isFirstLogin', isFirstLogin)
+  },
   /**
    * @description 设置用户名
    * @param {*} state
@@ -43,6 +52,9 @@ const mutations = {
   setNickName(state, nickName) {
     state.nickName = nickName
   },
+  setPhone(state, phone) {
+    state.phone = phone
+  },
   setUserId(state, id) {
     state.id = id
   },
@@ -62,7 +74,7 @@ const actions = {
    */
   setVirtualRoles({ commit, dispatch }) {
     dispatch('acl/setFull', true, { root: true })
-    commit('setAvatar', 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif')
+    commit('setAvatar', require('@/assets/login_images/user_avatar.png'))
     commit('setUsername', 'admin(未开启登录拦截)')
   },
   /**
@@ -72,9 +84,10 @@ const actions = {
    */
   async login({ commit }, userInfo) {
     const {
-      data: { [tokenName]: token },
+      data: { [tokenName]: token, isFirstLogin },
     } = await userApi.login(userInfo)
     if (token) {
+      commit('setIsFirstLogin', isFirstLogin)
       commit('setToken', token)
       const hour = new Date().getHours()
       const thisTime =
@@ -98,7 +111,7 @@ const actions = {
     // console.log(username, avatar, roles, permissions)
 
     const res = await userApi.getUserInfo()
-    const { id, userName, nickName, avatar } = res.data.entity
+    const { id, userName, nickName, phone, avatar } = res.data.entity
     const { roleIds, permissions } = res.data
     /**
      * 检验返回数据是否正常,无对应参数,将使用默认用户名,头像,Roles和Permissions
@@ -111,6 +124,7 @@ const actions = {
       (userName && !isString(userName)) ||
       (avatar && !isString(avatar)) ||
       (nickName && !isString(nickName)) ||
+      (phone && !isString(phone)) ||
       (roleIds && !isArray(roleIds)) ||
       (permissions && !isArray(permissions))
     ) {
@@ -123,12 +137,15 @@ const actions = {
       // 如不使用username用户名,可删除以下代码
       if (userName) commit('setUsername', userName)
       if (nickName) commit('setNickName', nickName)
+      if (phone) commit('setPhone', phone)
       // 如不使用avatar头像,可删除以下代码
       if (avatar) commit('setAvatar', avatar)
       // 如不使用roles权限控制,可删除以下代码
       if (roleIds) dispatch('acl/setRole', roleIds, { root: true })
       // 如不使用permissions权限控制,可删除以下代码
       if (permissions) dispatch('acl/setPermission', permissions, { root: true })
+
+      watermark.init({ watermark_txt: nickName + phone, watermark_width: 150, watermark_alpha: 0.08 })
     }
   },
   /**
@@ -145,7 +162,7 @@ const actions = {
    */
   async resetAll({ commit, dispatch }) {
     commit('setUsername', '游客')
-    commit('setAvatar', 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif')
+    commit('setAvatar', require('@/assets/login_images/user_avatar.png'))
     commit('routes/setRoutes', [], { root: true })
     await dispatch('setToken', '')
     await dispatch('acl/setFull', false, { root: true })
@@ -154,6 +171,8 @@ const actions = {
     await dispatch('tabs/delAllVisitedRoutes', null, { root: true })
     await resetRouter()
     removeToken()
+    watermark.init({ watermark_txt: '            ' })
+    watermark.remove()
   },
   /**
    * @description 设置token

+ 8 - 0
src/vab/components/VabAvatar/index.vue

@@ -9,6 +9,9 @@
     </span>
     <template #dropdown>
       <el-dropdown-menu>
+        <!--用户重置密码-->
+        <user-rest-pwd ref="userRestPwd" @fetch-data="logout" />
+
         <el-dropdown-item command="logout">
           <vab-icon icon="logout-circle-r-line" />
           {{ translateTitle('退出登录') }}
@@ -22,9 +25,11 @@
   import { translateTitle } from '@/utils/i18n'
   import { mapActions, mapGetters } from 'vuex'
   import { toLoginRoute } from '@/utils/routes'
+  import UserRestPwd from '@/views/system/user/components/UserRestPwd'
 
   export default {
     name: 'VabAvatar',
+    components: { UserRestPwd },
     data() {
       return {
         active: false,
@@ -47,6 +52,9 @@
           case 'logout':
             this.logout()
             break
+          case 'userRestPwd':
+            this.$refs['userRestPwd'].showEdit()
+            break
         }
       },
       handleVisibleChange(val) {

+ 7 - 19
src/vab/components/VabTabs/index.vue

@@ -10,15 +10,8 @@
       type="card"
       @tab-click="handleTabClick"
       @tab-remove="handleTabRemove">
-      <el-tab-pane
-        v-for="item in visitedRoutes"
-        :key="item.path"
-        :closable="!isNoClosable(item)"
-        :name="item.path">
-        <span
-          slot="label"
-          style="display: inline-block"
-          @contextmenu.prevent="openMenu($event, item)">
+      <el-tab-pane v-for="item in visitedRoutes" :key="item.path" :closable="!isNoClosable(item)" :name="item.path">
+        <span slot="label" style="display: inline-block" @contextmenu.prevent="openMenu($event, item)">
           <template v-if="theme.showTabsIcon">
             <vab-icon
               v-if="item.meta && item.meta.icon"
@@ -89,8 +82,7 @@
       <li
         class="el-dropdown-menu__item"
         :class="{
-          'is-disabled':
-            visitedRoutes.indexOf(hoverRoute) === visitedRoutes.length - 1,
+          'is-disabled': visitedRoutes.indexOf(hoverRoute) === visitedRoutes.length - 1,
         }"
         @click="closeRightTabs">
         <vab-icon icon="arrow-right-line" />
@@ -162,8 +154,7 @@
         delAllVisitedRoutes: 'tabs/delAllVisitedRoutes',
       }),
       handleTabClick(tab) {
-        if (this.isActive(tab.name))
-          this.$baseEventBus.$emit('reload-router-view')
+        if (this.isActive(tab.name)) this.$baseEventBus.$emit('reload-router-view')
         else this.$router.push(this.visitedRoutes[tab.index])
       },
       handleVisibleChange(val) {
@@ -220,8 +211,7 @@
         if (this.hoverRoute) {
           await this.$router.push(this.hoverRoute)
           await this.delOthersVisitedRoutes(this.hoverRoute.path)
-        } else
-          await this.delOthersVisitedRoutes(handleActivePath(this.$route, true))
+        } else await this.delOthersVisitedRoutes(handleActivePath(this.$route, true))
         await this.closeMenu()
       },
       /**
@@ -232,8 +222,7 @@
         if (this.hoverRoute) {
           await this.$router.push(this.hoverRoute)
           await this.delLeftVisitedRoutes(this.hoverRoute.path)
-        } else
-          await this.delLeftVisitedRoutes(handleActivePath(this.$route, true))
+        } else await this.delLeftVisitedRoutes(handleActivePath(this.$route, true))
         await this.closeMenu()
       },
       /**
@@ -244,8 +233,7 @@
         if (this.hoverRoute) {
           await this.$router.push(this.hoverRoute)
           await this.delRightVisitedRoutes(this.hoverRoute.path)
-        } else
-          await this.delRightVisitedRoutes(handleActivePath(this.$route, true))
+        } else await this.delRightVisitedRoutes(handleActivePath(this.$route, true))
         await this.closeMenu()
       },
       /**

+ 7 - 7
src/vab/styles/default.scss

@@ -4024,7 +4024,7 @@ $--background-color-base: $base-color-background;
 
 .el-avatar {
   color: $base-color-white;
-  background: $--color-text-placeholder;
+  background: $base-color-white;
 }
 
 .el-drawer {
@@ -4049,7 +4049,7 @@ $--background-color-base: $base-color-background;
     align-items: center;
     font-size: 14px;
     padding-right: 8px;
-    >span:first-child {
+    > span:first-child {
       flex: 1;
       overflow: hidden;
       text-overflow: ellipsis;
@@ -4089,22 +4089,22 @@ $--background-color-base: $base-color-background;
     border-right: 6px solid #f6f8f9;
     display: flex;
     flex-direction: column;
-    background: #fff; 
+    background: #fff;
     .el-tree {
-      flex:1;
+      flex: 1;
       overflow: auto;
     }
     footer {
-      flex:0 0 32px;
+      flex: 0 0 32px;
       display: flex;
       .el-button {
-        flex:1;
+        flex: 1;
       }
     }
   }
   .tree-table {
     width: calc(100% - 216px);
-    padding:0 6px;
+    padding: 0 6px;
     background: #fff;
   }
   .info-side {

+ 1 - 1
src/views/base/distributor/components/DistrEdit.vue

@@ -106,7 +106,7 @@
           <!-- <el-form-item label="销售人员" prop="businessScope">
             <el-input v-model.trim="form.businessScope" />
           </el-form-item> -->
-          <select-user ref="selectUser" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectUser" />
+          <select-user ref="selectUser" :query-params="{ roles: ['SalesEngineer'] }" @save="selectUser" />
           <el-form-item label="销售人员" prop="belongSale">
             <el-input v-model="form.belongSale" readonly>
               <el-button slot="append" icon="el-icon-search" @click="choose" />

+ 11 - 3
src/views/base/distributor/index.vue

@@ -47,7 +47,13 @@
         </vab-query-form>
 
         <vab-query-form-left-panel>
-          <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">新建</el-button>
+          <el-button
+            v-permissions="['base:distributor:add']"
+            icon="el-icon-plus"
+            type="primary"
+            @click="handleEdit($event)">
+            新建
+          </el-button>
         </vab-query-form-left-panel>
         <vab-query-form-right-panel>
           <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -78,8 +84,10 @@
 
           <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
             <template #default="{ row }">
-              <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-              <el-button type="text" @click="handleDelete(row)">删除</el-button>
+              <el-button v-permissions="['base:distributor:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+              <el-button v-permissions="['base:distributor:delete']" type="text" @click="handleDelete(row)">
+                删除
+              </el-button>
             </template>
           </el-table-column>
           <template #empty>

+ 123 - 90
src/views/base/product/index.vue

@@ -1,92 +1,114 @@
 <template>
   <div class="user-management-container">
-    <vab-query-form>
-      <vab-query-form-top-panel>
-        <el-form :inline="true" :model="queryForm" @submit.native.prevent>
-          <el-form-item>
-            <el-input v-model.trim="queryForm.prodCode" clearable placeholder="产品编码" />
-          </el-form-item>
+    <div class="side-layout">
+      <div class="tree-side">
+        <div class="head-container">
+          <span style="font-size: 25px">产品类别</span>
+        </div>
+        <el-tree
+          ref="tree"
+          class="filter-tree"
+          :data="prodClassOptions"
+          highlight-current
+          node-key="key"
+          :props="defaultProps"
+          @node-click="handleNodeClick" />
+      </div>
+      <div class="tree-table">
+        <vab-query-form>
+          <vab-query-form-top-panel>
+            <el-form :inline="true" :model="queryForm" @submit.native.prevent>
+              <el-form-item>
+                <el-input v-model.trim="queryForm.prodCode" clearable placeholder="产品编码" />
+              </el-form-item>
+              <el-form-item>
+                <el-input v-model.trim="queryForm.prodName" clearable placeholder="产品名称" />
+              </el-form-item>
+              <el-form-item>
+                <el-select v-model="queryForm.prodClass" placeholder="产品类别" style="width: 100%">
+                  <el-option v-for="item in prodClassOptions" :key="item.key" :label="item.value" :value="item.key" />
+                </el-select>
+              </el-form-item>
+              <el-form-item>
+                <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
+                <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
+              </el-form-item>
+            </el-form>
+          </vab-query-form-top-panel>
+          <vab-query-form-left-panel>
+            <el-button
+              v-permissions="['base:product:add']"
+              icon="el-icon-plus"
+              type="primary"
+              @click="handleEdit($event)">
+              添加
+            </el-button>
+          </vab-query-form-left-panel>
+          <vab-query-form-right-panel>
+            <table-tool :check-list.sync="checkList" :columns="columns" />
+          </vab-query-form-right-panel>
+        </vab-query-form>
 
-          <el-form-item>
-            <el-input v-model.trim="queryForm.prodName" clearable placeholder="产品名称" />
-          </el-form-item>
-          <el-form-item>
-            <el-select v-model="queryForm.prodClass" placeholder="产品类别" style="width: 100%">
-              <el-option v-for="item in classOptions" :key="item.value" :label="item.value" :value="item.value" />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
-            <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </vab-query-form-top-panel>
-    </vab-query-form>
-    <vab-query-form-left-panel>
-      <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-    </vab-query-form-left-panel>
-    <vab-query-form-right-panel>
-      <table-tool :check-list.sync="checkList" :columns="columns" />
-    </vab-query-form-right-panel>
-
-    <el-table v-loading="listLoading" border :data="list" :height="height" @selection-change="setSelectRows">
-      <el-table-column align="center" label="序号" show-overflow-tooltip width="80">
-        <template #default="{ $index }">
-          {{ $index + 1 }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        v-for="(item, index) in finallyColumns"
-        :key="index"
-        align="center"
-        :label="item.label"
-        :min-width="item.minWidth"
-        :prop="item.prop"
-        show-overflow-tooltip
-        :sortable="item.sortable"
-        :width="item.width">
-        <template #default="{ row }">
-          <el-button v-if="item.prop === 'prodName'" style="font-size: 14px" type="text" @click="handleDetail(row)">
-            {{ row.prodName }}
-          </el-button>
-          <span v-else-if="item.prop === 'prodClass'">
-            {{ row.prodClass }}
-          </span>
-          <span v-else-if="item.prop === 'prodCode'">
-            {{ row.prodCode }}
-          </span>
-          <span v-else-if="item.prop === 'agentPrice'">
-            {{ formatPrice(row.agentPrice) }}
-          </span>
-          <span v-else-if="item.prop === 'distPrice'">
-            {{ formatPrice(row.distPrice) }}
-          </span>
-          <span v-else-if="item.prop === 'guidPrice'">
-            {{ formatPrice(row.guidPrice) }}
-          </span>
-          <span v-else-if="item.prop === 'marketPrice'">
-            {{ formatPrice(row.marketPrice) }}
-          </span>
-        </template>
-      </el-table-column>
-      <el-table-column align="center" fixed="right" label="操作" show-overflow-tooltip width="120">
-        <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
-        </template>
-      </el-table-column>
-      <template #empty>
-        <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
-      </template>
-    </el-table>
-    <el-pagination
-      background
-      :current-page="queryForm.pageNum"
-      :layout="layout"
-      :page-size="queryForm.pageSize"
-      :total="total"
-      @current-change="handleCurrentChange"
-      @size-change="handleSizeChange" />
+        <el-table v-loading="listLoading" border :data="list" :height="height" @selection-change="setSelectRows">
+          <el-table-column align="center" label="序号" show-overflow-tooltip width="80">
+            <template #default="{ $index }">
+              {{ $index + 1 }}
+            </template>
+          </el-table-column>
+          <el-table-column
+            v-for="(item, index) in finallyColumns"
+            :key="index"
+            align="center"
+            :label="item.label"
+            :min-width="item.minWidth"
+            :prop="item.prop"
+            show-overflow-tooltip
+            :sortable="item.sortable"
+            :width="item.width">
+            <template #default="{ row }">
+              <el-button v-if="item.prop === 'prodName'" style="font-size: 14px" type="text" @click="handleDetail(row)">
+                {{ row.prodName }}
+              </el-button>
+              <span v-else-if="item.prop === 'prodClass'">
+                {{ selectDictLabel(prodClassOptions, row.prodClass) }}
+              </span>
+              <span v-else-if="item.prop === 'prodCode'">
+                {{ row.prodCode }}
+              </span>
+              <span v-else-if="item.prop === 'agentPrice'">
+                {{ formatPrice(row.agentPrice) }}
+              </span>
+              <span v-else-if="item.prop === 'distPrice'">
+                {{ formatPrice(row.distPrice) }}
+              </span>
+              <span v-else-if="item.prop === 'guidPrice'">
+                {{ formatPrice(row.guidPrice) }}
+              </span>
+              <span v-else-if="item.prop === 'marketPrice'">
+                {{ formatPrice(row.marketPrice) }}
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" label="操作" show-overflow-tooltip width="120">
+            <template #default="{ row }">
+              <el-button v-permissions="['base:product:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+              <el-button v-permissions="['base:product:delete']" type="text" @click="handleDelete(row)">删除</el-button>
+            </template>
+          </el-table-column>
+          <template #empty>
+            <el-image class="vab-data-empty" :src="require('@/assets/empty_images/data_empty.png')" />
+          </template>
+        </el-table>
+        <el-pagination
+          background
+          :current-page="queryForm.pageNum"
+          :layout="layout"
+          :page-size="queryForm.pageSize"
+          :total="total"
+          @current-change="handleCurrentChange"
+          @size-change="handleSizeChange" />
+      </div>
+    </div>
     <edit ref="edit" @fetch-data="fetchData" />
   </div>
 </template>
@@ -108,7 +130,9 @@
         queryForm: {
           pageNum: 1,
           pageSize: 10,
-          userName: '',
+          prodCode: '',
+          prodClass: '',
+          prodName: '',
         },
         checkList: [],
         columns: [
@@ -159,7 +183,11 @@
             sortable: false,
           },
         ],
-        classOptions: [], //产品分类
+        defaultProps: {
+          key: 'key',
+          label: 'value',
+        },
+        prodClassOptions: [], //产品分类
       }
     },
     computed: {
@@ -175,6 +203,11 @@
       this.fetchData()
     },
     methods: {
+      // 节点单击事件
+      handleNodeClick(data) {
+        this.queryForm.prodClass = data.key
+        this.fetchData()
+      },
       setSelectRows(val) {
         this.selectRows = val
       },
@@ -188,9 +221,9 @@
         }
       },
       getOptions() {
-        Promise.all([this.getDicts('product_type')])
+        Promise.all([this.getDicts('base_product_class')])
           .then(([productType]) => {
-            this.classOptions = productType.data.values || []
+            this.prodClassOptions = productType.data.values || []
           })
           .catch((err) => console.log(err))
       },

+ 6 - 11
src/views/base/productAuth/index.vue

@@ -10,7 +10,7 @@
   <div class="product-auth-container">
     <vab-query-form>
       <vab-query-form-left-panel>
-        <el-form :inline="true" :model="queryForm" @submit.native.prevent>
+        <el-form ref="queryForm" :inline="true" :model="queryForm" @submit.native.prevent>
           <el-form-item>
             <el-input v-model="queryForm.keyWords" placeholder="姓名" />
           </el-form-item>
@@ -40,7 +40,7 @@
       </el-table-column>
       <el-table-column align="center" label="操作" width="120px">
         <template #default="{ row }">
-          <el-button type="text" @click="handleAuth(row)">授权</el-button>
+          <el-button v-permissions="['base:productLine:grant']" type="text" @click="handleAuth(row)">授权</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -49,7 +49,6 @@
       :current-page="queryForm.pageNum"
       :layout="layout"
       :page-size="queryForm.pageSize"
-      :page-sizes="[5, 10]"
       :total="total"
       @current-change="handleCurrentChange"
       @size-change="handleSizeChange" />
@@ -75,6 +74,7 @@
   import proAuthApi from '@/api/base/productAuth'
   import TableTool from '@/components/table/TableTool'
   import to from 'await-to-js'
+
   export default {
     name: 'ProductAuthorize',
     components: {
@@ -85,9 +85,9 @@
         total: 0,
         queryForm: {
           pageNum: 1,
-          pageSize: 5,
+          pageSize: 10,
           keyWords: '',
-          deptId: 2,
+          deptId: 1001,
         },
         layout: 'total, sizes, prev, pager, next, jumper',
         listLoading: false,
@@ -167,12 +167,7 @@
         })
       },
       reset() {
-        this.queryForm = {
-          pageNum: 1,
-          pageSize: 10,
-          keyWords: '',
-          deptId: 2,
-        }
+        this.resetForm('queryForm')
         this.fetchData()
       },
       handleSizeChange(val) {

+ 69 - 37
src/views/base/region/index.vue

@@ -1,33 +1,10 @@
 <template>
   <div class="region-container">
-    <vab-query-form>
-      <vab-query-form-top-panel>
-        <el-form :inline="true" :model="queryForm" @submit.native.prevent>
-          <el-form-item>
-            <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
-          </el-form-item>
-          <el-form-item prop="custCode">
-            <el-input v-model="queryForm.custCode" clearable placeholder="客户编码" />
-          </el-form-item>
-
-          <el-form-item prop="custName">
-            <el-input v-model="queryForm.custName" clearable placeholder="客户名称" />
-          </el-form-item>
-          <el-form-item label="" prop="custIndustry">
-            <el-select v-model="custIndustry" placeholder="请选择客户行业" style="width: 100%">
-              <el-option v-for="item in industryOptions" :key="item.value" :label="item.value" :value="item.value" />
-            </el-select>
-          </el-form-item>
-
-          <el-form-item>
-            <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
-            <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </vab-query-form-top-panel>
-    </vab-query-form>
     <div class="side-layout">
       <div class="tree-side">
+        <div class="head-container">
+          <span style="font-size: 25px">销售大区</span>
+        </div>
         <el-tree
           ref="tree"
           class="filter-tree"
@@ -52,21 +29,57 @@
                   <!-- <i class="el-icon-arrow-down el-icon--right"></i> -->
                 </span>
                 <el-dropdown-menu slot="dropdown">
-                  <el-dropdown-item command="edit">编辑</el-dropdown-item>
-                  <el-dropdown-item command="del">删除</el-dropdown-item>
+                  <el-dropdown-item v-permissions="['base:region:edit']" command="edit">编辑</el-dropdown-item>
+                  <el-dropdown-item v-permissions="['base:region:delete']" command="del">删除</el-dropdown-item>
                 </el-dropdown-menu>
               </el-dropdown>
             </span>
           </span>
         </el-tree>
         <footer>
-          <el-button icon="el-icon-plus" @click="getCheckedNodes($event)">添加区域</el-button>
+          <el-button v-permissions="['base:region:add']" icon="el-icon-plus" @click="getCheckedNodes($event)">
+            添加区域
+          </el-button>
         </footer>
       </div>
       <div class="tree-table">
         <vab-query-form>
+          <vab-query-form-top-panel>
+            <el-form :inline="true" :model="queryForm" @submit.native.prevent>
+              <el-form-item>
+                <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
+              </el-form-item>
+              <el-form-item prop="custCode">
+                <el-input v-model="queryForm.custCode" clearable placeholder="客户编码" />
+              </el-form-item>
+
+              <el-form-item prop="custName">
+                <el-input v-model="queryForm.custName" clearable placeholder="客户名称" />
+              </el-form-item>
+              <el-form-item label="" prop="custIndustry">
+                <el-select v-model="custIndustry" placeholder="请选择客户行业" style="width: 100%">
+                  <el-option
+                    v-for="item in industryOptions"
+                    :key="item.value"
+                    :label="item.value"
+                    :value="item.value" />
+                </el-select>
+              </el-form-item>
+
+              <el-form-item>
+                <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
+                <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
+              </el-form-item>
+            </el-form>
+          </vab-query-form-top-panel>
           <vab-query-form-left-panel>
-            <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
+            <el-button
+              v-permissions="['base:regionDetail:add']"
+              icon="el-icon-plus"
+              type="primary"
+              @click="handleEdit($event)">
+              添加
+            </el-button>
           </vab-query-form-left-panel>
           <vab-query-form-right-panel>
             <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -84,18 +97,26 @@
             :key="index"
             align="center"
             :label="item.label"
+            :min-width="item.minWidth"
             :prop="item.prop"
             show-overflow-tooltip
             :sortable="item.sortable"
             :width="item.width">
             <template #default="{ row }">
-              <span>{{ row[item.prop] }}</span>
+              <span v-if="item.prop === 'createdTime'">
+                {{ parseTime(row.createdTime, '{y}-{m}-{d}') }}
+              </span>
+              <span v-else>{{ row[item.prop] }}</span>
             </template>
           </el-table-column>
           <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
             <template #default="{ row }">
-              <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-              <el-button type="text" @click="handleDelete(row)">删除</el-button>
+              <el-button v-permissions="['base:regionDetail:edit']" type="text" @click="handleEdit(row)">
+                编辑
+              </el-button>
+              <el-button v-permissions="['base:regionDetail:delete']" type="text" @click="handleDelete(row)">
+                删除
+              </el-button>
             </template>
           </el-table-column>
           <template #empty>
@@ -154,27 +175,36 @@
         columns: [
           {
             label: '省份',
-            width: '200px',
             prop: 'custProvince',
+            minWidth: '200px',
+            width: 'auto',
             sortable: false,
           },
           {
-            label: '客户数量',
+            label: '市',
+            prop: 'custCity',
+            minWidth: '200px',
             width: 'auto',
+            sortable: false,
+          },
+          {
+            label: '客户数量',
             prop: 'count',
+            minWidth: '200px',
+            width: 'auto',
             sortable: false,
             disableCheck: true,
           },
           {
             label: '创建人',
-            width: 'auto',
             prop: 'createdName',
+            width: '120',
             sortable: false,
             disableCheck: true,
           },
           {
             label: '创建时间',
-            width: 'auto',
+            width: '120',
             prop: 'createdTime',
             sortable: false,
             disableCheck: true,
@@ -344,11 +374,13 @@
   .side-layout {
     height: calc(100vh - 200px);
   }
+
   ::v-deep .custom-tree-node {
     .el-input__inner {
       padding: 0 !important;
     }
   }
+
   .el-tree-node:focus > .el-tree-node__content {
     /*设置选中的样式 */
     background-color: #dde9ff !important;

+ 10 - 9
src/views/base/regionAuth/index.vue

@@ -9,7 +9,7 @@
 <template>
   <div class="region-auth-container">
     <vab-query-form>
-      <el-form>
+      <el-form ref="queryForm">
         <vab-query-form-left-panel>
           <el-form-item>
             <el-input v-model="queryForm.keyWords" placeholder="姓名" />
@@ -20,7 +20,13 @@
           </el-form-item>
         </vab-query-form-left-panel>
         <vab-query-form-right-panel>
-          <el-button icon="el-icon-circle-check" type="primary" @click="handleAuth">授权</el-button>
+          <el-button
+            v-permissions="['base:regionAuth:grant']"
+            icon="el-icon-circle-check"
+            type="primary"
+            @click="handleAuth">
+            授权
+          </el-button>
           <table-tool :check-list.sync="checkList" :columns="columns" />
         </vab-query-form-right-panel>
       </el-form>
@@ -140,7 +146,7 @@
           pageNum: 1,
           pageSize: 10,
           keyWords: '',
-          deptId: 2,
+          deptId: 1001,
         },
         layout: 'total, sizes, prev, pager, next, jumper',
         listLoading: false,
@@ -233,12 +239,7 @@
         this.fetchData()
       },
       reset() {
-        this.queryForm = {
-          pageNum: 1,
-          pageSize: 10,
-          keyWords: '',
-          deptId: 2,
-        }
+        this.resetForm('queryForm')
         this.fetchData()
       },
       handleSizeChange(val) {

+ 30 - 4
src/views/contract/components/DetailsCollection.vue

@@ -12,7 +12,12 @@
     <div class="collection-plan mb10">
       <el-row class="mb10">
         <el-col class="text-right" :span="24">
-          <el-button icon="el-icon-plus" size="mini" type="primary" @click="$refs.collectionPlan.init()">
+          <el-button
+            v-permissions="['contract:detail:collectionPlan:add']"
+            icon="el-icon-plus"
+            size="mini"
+            type="primary"
+            @click="$refs.collectionPlan.init()">
             新建回款计划
           </el-button>
         </el-col>
@@ -40,13 +45,24 @@
         <el-table-column align="center" fixed="right" label="操作" width="120px">
           <template slot-scope="scope">
             <el-button
+              v-permissions="['contract:detail:collection:add']"
               :disabled="scope.row.contractStatus == '30'"
               type="text"
               @click="$refs.collection.init(scope.row.id)">
               回款
             </el-button>
-            <el-button type="text" @click="$refs.collectionPlan.init(scope.row.id)">编辑</el-button>
-            <el-button type="text" @click="handleDel(scope.row, 'plan')">删除</el-button>
+            <el-button
+              v-permissions="['contract:detail:collectionPlan:edit']"
+              type="text"
+              @click="$refs.collectionPlan.init(scope.row.id)">
+              编辑
+            </el-button>
+            <el-button
+              v-permissions="['contract:detail:collectionPlan:delete']"
+              type="text"
+              @click="handleDel(scope.row, 'plan')">
+              删除
+            </el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -55,7 +71,12 @@
     <div class="collection">
       <el-row class="mb10">
         <el-col class="text-right" :span="24">
-          <el-button icon="el-icon-plus" size="mini" type="primary" @click="$refs.collection.init()">
+          <el-button
+            v-permissions="['contract:detail:collection:add']"
+            icon="el-icon-plus"
+            size="mini"
+            type="primary"
+            @click="$refs.collection.init()">
             新建回款
           </el-button>
         </el-col>
@@ -102,6 +123,7 @@
   import EditPlan from '@/views/contract/components/EditPlan'
   import EditCollection from './EditCollection'
   import to from 'await-to-js'
+
   export default {
     name: 'DetailsCollection',
     components: {
@@ -261,14 +283,18 @@
     .mb10 {
       margin-bottom: 10px;
     }
+
     height: 100%;
+
     .collection-plan,
     .collection {
       height: 50%;
+
       .el-row {
         height: 30px;
       }
     }
+
     .text-right {
       text-align: right;
     }

+ 13 - 4
src/views/contract/components/DetailsEnclosure.vue

@@ -21,7 +21,7 @@
           "
           :file-list="fileList"
           :http-request="uploadrequest">
-          <el-button size="mini" type="primary">点击上传</el-button>
+          <el-button v-permissions="['contract:detail:enclosure:add']" size="mini" type="primary">点击上传</el-button>
         </el-upload>
       </el-col>
     </el-row>
@@ -43,9 +43,18 @@
       </el-table-column>
       <el-table-column align="center" fixed="right" label="操作">
         <template slot-scope="scope">
-          <el-button type="text" @click="downFile(scope.row.fileUrl, scope.row.fileName)">下载</el-button>
-          <el-button type="text" @click="rename(scope.row.id)">重命名</el-button>
-          <el-button type="text" @click="handleDel(scope.row)">删除</el-button>
+          <el-button
+            v-permissions="['contract:detail:enclosure:download']"
+            type="text"
+            @click="downFile(scope.row.fileUrl, scope.row.fileName)">
+            下载
+          </el-button>
+          <el-button v-permissions="['contract:detail:enclosure:rename']" type="text" @click="rename(scope.row.id)">
+            重命名
+          </el-button>
+          <el-button v-permissions="['contract:detail:enclosure:delete']" type="text" @click="handleDel(scope.row)">
+            删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>

+ 12 - 1
src/views/contract/components/DetailsInvoice.vue

@@ -11,7 +11,14 @@
   <div class="invoice-container">
     <el-row class="mb10">
       <el-col class="text-right" :span="24">
-        <el-button icon="el-icon-plus" size="mini" type="primary" @click="$refs.invoice.init()">新建发票</el-button>
+        <el-button
+          v-permissions="['contract:detail:invoice:add']"
+          icon="el-icon-plus"
+          size="mini"
+          type="primary"
+          @click="$refs.invoice.init()">
+          新建发票
+        </el-button>
       </el-col>
     </el-row>
     <el-table border :data="invoiceData" height="calc(100% - 50px)">
@@ -166,15 +173,19 @@
 <style lang="scss" scoped>
   .invoice-container {
     height: 100%;
+
     .mb10 {
       margin-bottom: 10px;
     }
+
     .collection {
       height: 100%;
+
       .el-row {
         height: 30px;
       }
     }
+
     .text-right {
       text-align: right;
     }

+ 5 - 3
src/views/contract/detail.vue

@@ -15,7 +15,9 @@
           <h3>
             {{ details.contractName }}
             <span>
-              <el-button icon="el-icon-refresh" @click="handleTransfer">转移</el-button>
+              <el-button v-permissions="['contract:manage:transfer']" icon="el-icon-refresh" @click="handleTransfer">
+                转移
+              </el-button>
             </span>
           </h3>
         </div>
@@ -60,8 +62,8 @@
       </div>
       <div class="info-side">
         <div class="buttons">
-          <el-button type="primary" @click="handleEdit">编辑</el-button>
-          <el-button @click="handleDelete">删除</el-button>
+          <el-button v-permissions="['contract:manage:edit']" type="primary" @click="handleEdit">编辑</el-button>
+          <el-button v-permissions="['contract:manage:delete']" @click="handleDelete">删除</el-button>
           <el-button @click="back">返回</el-button>
         </div>
         <details-records :dynamics-list="dynamicsList" />

+ 33 - 6
src/views/contract/index.vue

@@ -41,9 +41,23 @@
         </el-form>
       </vab-query-form-top-panel>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit()">新建</el-button>
-        <el-button icon="el-icon-refresh" type="primary" @click="handleTransfer()">转移</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete()">删除</el-button>
+        <el-button v-permissions="['contract:manage:add']" icon="el-icon-plus" type="primary" @click="handleEdit()">
+          新建
+        </el-button>
+        <el-button
+          v-permissions="['contract:manage:transfer']"
+          icon="el-icon-refresh"
+          type="primary"
+          @click="handleTransfer()">
+          转移
+        </el-button>
+        <el-button
+          v-permissions="['contract:manage:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete()">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -116,11 +130,23 @@
       </el-table-column>
       <el-table-column align="center" fixed="right" label="操作" width="90px">
         <template slot-scope="scope">
-          <el-button v-if="scope.row.approStatus == '10'" type="text" @click="handleApply(scope.row.id)">
+          <el-button
+            v-if="scope.row.approStatus == '10'"
+            v-permissions="['contract:manage:apply']"
+            type="text"
+            @click="handleApply(scope.row.id)">
             提交审核
           </el-button>
-          <el-button v-if="scope.row.approStatus == '10'" type="text" @click="handleEdit(scope.row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
+          <el-button
+            v-if="scope.row.approStatus == '10'"
+            v-permissions="['contract:manage:edit']"
+            type="text"
+            @click="handleEdit(scope.row)">
+            编辑
+          </el-button>
+          <el-button v-permissions="['contract:manage:delete']" type="text" @click="handleDelete(scope.row)">
+            删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -147,6 +173,7 @@
   import TableTool from '@/components/table/TableTool'
   import Transfer from './components/Transfer'
   import ApplyContract from './components/ApplyContract'
+
   export default {
     name: 'OpenSea',
     components: {

+ 10 - 2
src/views/contract/invoice.vue

@@ -76,10 +76,18 @@
       </el-table-column>
       <el-table-column align="center" fixed="right" label="操作">
         <template slot-scope="scope">
-          <el-button v-if="scope.row.approStatus == '30'" type="text" @click="$refs.invoicing.init(scope.row.id)">
+          <el-button
+            v-if="scope.row.approStatus == '30'"
+            v-permissions="['contract:invoice:edit']"
+            type="text"
+            @click="$refs.invoicing.init(scope.row.id)">
             更新开票信息
           </el-button>
-          <el-button v-if="scope.row.approStatus == '10'" type="text" @click="handleApply(scope.row.id)">
+          <el-button
+            v-if="scope.row.approStatus == '10'"
+            v-permissions="['contract:invoice:audit']"
+            type="text"
+            @click="handleApply(scope.row.id)">
             提交审核
           </el-button>
         </template>

+ 1 - 1
src/views/customer/components/Allocate.vue

@@ -20,7 +20,7 @@
       <el-button size="mini" @click="visible = false">取消</el-button>
     </span>
     <!--    <Transfer ref="transfer" />-->
-    <select-user ref="selectUser" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectUser" />
+    <select-user ref="selectUser" :query-params="{ roles: ['SalesEngineer'] }" @save="selectUser" />
   </el-dialog>
 </template>
 

+ 1 - 1
src/views/customer/components/Shift.vue

@@ -8,7 +8,7 @@
 -->
 <template>
   <el-dialog title="转移客户" :visible.sync="visible" width="30%" @close="handleClose">
-    <select-user ref="selectUser" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectUser" />
+    <select-user ref="selectUser" :query-params="{ roles: ['SalesEngineer'] }" @save="selectUser" />
     <el-form ref="form" label-width="80px" :model="form" :rules="rules">
       <el-form-item label="接收对象" prop="SalesName">
         <el-input v-model="form.salesName" readonly>

+ 10 - 4
src/views/customer/detail.vue

@@ -18,7 +18,7 @@
               <span v-show="detail.salesId > 0">
                 <el-button v-permissions="['cust:list:shift']" @click="handleShift">转移客户</el-button>
                 <el-button v-permissions="['cust:list:open']" @click="handleToOpen">移入公海</el-button>
-                <el-button v-permissions="['cust:list:business']" @click="handleBusiness">创建项目</el-button>
+                <el-button v-permissions="['cust:list:project']" @click="handleBusiness">创建项目</el-button>
               </span>
               <span v-show="detail.salesId == 0">
                 <el-button v-permissions="['cust:open:receive']" @click="handleReceive">领取客户</el-button>
@@ -186,7 +186,9 @@
                   @keyup.enter.native="handleClick({ name: 'contact' })" />
               </vab-query-form-left-panel>
               <vab-query-form-right-panel :span="12">
-                <el-button icon="el-icon-plus" @click="addContact">新建联系人</el-button>
+                <el-button v-permissions="['cust:detail:contact:add']" icon="el-icon-plus" @click="addContact">
+                  新建联系人
+                </el-button>
               </vab-query-form-right-panel>
             </vab-query-form>
             <el-table border :data="contactList" height="calc(100% - 42px)" @selection-change="setSelectRows">
@@ -203,8 +205,12 @@
               </el-table-column>
               <el-table-column align="center" label="操作">
                 <template slot-scope="scope">
-                  <el-button type="text" @click="contactEdit(scope.row)">编辑</el-button>
-                  <el-button type="text" @click="contactDel(scope.row)">删除</el-button>
+                  <el-button v-permissions="['cust:deatil:contact:edit']" type="text" @click="contactEdit(scope.row)">
+                    编辑
+                  </el-button>
+                  <el-button v-permissions="['cust:detail:contact:delete']" type="text" @click="contactDel(scope.row)">
+                    删除
+                  </el-button>
                 </template>
               </el-table-column>
             </el-table>

+ 3 - 3
src/views/index/index.vue

@@ -334,7 +334,7 @@
         this.initChart()
       },
       initChart() {
-        console.log(this.layout, 'layout')
+        // console.log(this.layout, 'layout')
         this.charts = []
         for (let i = 0; i < this.layout.length; i++) {
           this.getChartSize(this.layout[i].i)
@@ -347,9 +347,9 @@
         this.drawChart(item.i, index)
       },
       getChartSize(id) {
-        console.log(id, 'id')
+        // console.log(id, 'id')
         const bar = document.getElementById(id)
-        console.log(bar, 'bar')
+        // console.log(bar, 'bar')
         bar.style.height = bar.parentNode.clientHeight - 65 + 'px'
         bar.style.width = bar.parentNode.clientWidth + 'px'
       },

+ 12 - 9
src/views/login/index.vue

@@ -132,15 +132,7 @@
         immediate: true,
       },
     },
-    mounted() {
-      this.form.username = 'admin'
-      this.form.password = '123456'
-      // 为了演示效果,会在官网演示页自动登录到首页,正式开发可删除
-      if (document.domain === 'vue-admin-beautiful.com' || document.domain === 'chu1204505056.gitee.io')
-        this.timer = setTimeout(() => {
-          this.handleLogin()
-        }, 5000)
-    },
+    mounted() {},
     methods: {
       ...mapActions({
         login: 'user/login',
@@ -178,31 +170,38 @@
   .login-container {
     height: 100vh;
     background-size: cover;
+
     .container {
       width: 1160px;
       height: 100%;
       margin: 0 auto;
     }
+
     header {
       height: 100px;
       background: #fff;
+
       .container {
         display: flex;
         align-items: center;
       }
     }
+
     footer {
       height: 130px;
       background: #fff;
+
       .container {
         display: flex;
         align-items: center;
         justify-content: space-between;
+
         .links a {
           color: #6e717c;
           font-size: 18px;
           letter-spacing: 1px;
           padding-left: 10px;
+
           & + a {
             margin-left: 10px;
             border-left: 1px solid #6e717c;
@@ -210,15 +209,18 @@
         }
       }
     }
+
     .content {
       display: flex;
       height: calc(100% - 230px);
       background: url('~@/assets/login_images/login_bgd.png') center center fixed no-repeat;
       background-size: cover;
+
       .container {
         display: flex;
         align-items: center;
       }
+
       .login {
         width: 100%;
         height: 580px;
@@ -228,6 +230,7 @@
         background: #fff;
         box-shadow: 0px 3px 20px 1px rgba(0, 0, 0, 0.16);
       }
+
       .left {
         width: 60%;
         height: 100%;

+ 47 - 6
src/views/plat/task/detail.vue

@@ -90,6 +90,7 @@
                 <template #default="{ row }">
                   <el-upload action="#" :http-request="uploadrequest" :show-file-list="false">
                     <el-button
+                      v-permissions="['plat:task:enclosure:add']"
                       size="mini"
                       style="margin-left: 10px"
                       slot="trigger"
@@ -99,6 +100,7 @@
                     </el-button>
                     <el-button
                       v-show="row.progFile"
+                      v-permissions="['plat:task:enclosure:look']"
                       size="mini"
                       style="margin-left: 10px"
                       @click="showFile(row.progFile)">
@@ -115,7 +117,9 @@
               </el-table-column>
               <el-table-column v-if="theTask.step < 30 && type == 1" align="center" label="操作">
                 <template #default="{ row }">
-                  <el-button type="text" @click="handleDel(row.$index)">删除</el-button>
+                  <el-button v-permissions="['plat:task:enclosure:delete']" type="text" @click="handleDel(row.$index)">
+                    删除
+                  </el-button>
                 </template>
               </el-table-column>
             </el-table>
@@ -132,31 +136,53 @@
       </el-col>
       <el-col :span="8">
         <div class="buttons">
-          <el-button v-show="theTask.taskStatus === '10' && type == 1" type="primary" @click="changeStatus(10, '10')">
+          <el-button
+            v-show="theTask.taskStatus === '10' && type == 1"
+            v-permissions="['plat:task:detail:receive']"
+            type="primary"
+            @click="changeStatus(10, '10')">
             接收
           </el-button>
           <el-button
             v-show="theTask.taskStatus === '20' && theTask.step === 20 && type == 1"
+            v-permissions="['plat:task:detail:staging']"
             type="success"
             @click="changeStatus(15)">
             暂存
           </el-button>
           <el-button
             v-show="theTask.taskStatus === '20' && theTask.step === 20 && type == 1"
+            v-permissions="['plat:task:detail:submit']"
             type="primary"
             @click="changeStatus(20, '20')">
             提交
           </el-button>
-          <el-button v-show="theTask.step === 30 && type == 1" type="primary" @click="changeStatus(30, '30')">
+          <el-button
+            v-show="theTask.step === 30 && type == 1"
+            v-permissions="['plat:task:detail:adopt']"
+            type="primary"
+            @click="changeStatus(30, '30')">
             审批通过
           </el-button>
-          <el-button v-show="theTask.step === 30 && type == 1" type="danger" @click="changeStatus(30, '40')">
+          <el-button
+            v-show="theTask.step === 30 && type == 1"
+            v-permissions="['plat:task:detail:return']"
+            type="danger"
+            @click="changeStatus(30, '40')">
             审批退回
           </el-button>
-          <el-button v-show="theTask.step === 40 && type == 1" type="primary" @click="changeStatus(40, '30')">
+          <el-button
+            v-show="theTask.step === 40 && type == 1"
+            v-permissions="['plat:task:detail:adopt']"
+            type="primary"
+            @click="changeStatus(40, '30')">
             审批通过
           </el-button>
-          <el-button v-show="theTask.step === 40 && type == 1" type="danger" @click="changeStatus(40, '40')">
+          <el-button
+            v-show="theTask.step === 40 && type == 1"
+            v-permissions="['plat:task:detail:return']"
+            type="danger"
+            @click="changeStatus(40, '40')">
             审批退回
           </el-button>
           <el-button @click="$router.go(-1)">返回</el-button>
@@ -191,6 +217,7 @@
   import asyncUploadFile from '@/utils/uploadajax'
   import dictApi from '@/api/system/dict'
   import axios from 'axios'
+
   export default {
     name: 'TaskDetail',
     data() {
@@ -363,12 +390,15 @@
     height: calc(100vh - 60px - 12px * 2 - 40px);
     display: flex;
     padding: 20px 40px;
+
     > .el-row {
       flex: 1;
+
       > .el-col {
         height: 100%;
       }
     }
+
     .title {
       p,
       h3 {
@@ -390,6 +420,7 @@
         justify-content: space-between;
       }
     }
+
     header {
       min-height: 134px;
       background: rgba(196, 196, 196, 0.5);
@@ -399,6 +430,7 @@
       align-items: center;
       padding: 7px 20px;
       margin-top: 16px;
+
       ::v-deep .el-descriptions__body {
         background: transparent;
       }
@@ -418,39 +450,48 @@
         white-space: nowrap;
       }
     }
+
     .buttons {
       height: 60px;
       padding-top: 28px;
       text-align: right;
     }
+
     .add-pro {
       text-align: right;
       margin: 10px 0;
     }
+
     .records {
       padding: 10px 20px;
       height: calc(100% - 60px);
       overflow-y: auto;
+
       li {
         display: flex;
         align-items: center;
+
         i {
           font-size: 40px;
           margin-right: 10px;
         }
+
         .text {
           flex: 1;
         }
+
         p {
           height: 20px;
           line-height: 20px;
           display: flex;
           justify-content: space-between;
           font-weight: 500;
+
           &:first-child {
             font-weight: bold;
           }
         }
+
         & + li {
           margin-top: 10px;
         }

+ 5 - 2
src/views/plat/task/index.vue

@@ -65,7 +65,9 @@
             </el-form>
           </vab-query-form-top-panel>
           <vab-query-form-left-panel :span="12">
-            <el-button icon="el-icon-plus" type="primary" @click="handleAdd">添加</el-button>
+            <el-button v-permissions="['plat:task:add']" icon="el-icon-plus" type="primary" @click="handleAdd">
+              添加
+            </el-button>
           </vab-query-form-left-panel>
           <vab-query-form-right-panel :span="12">
             <!-- <el-button icon="el-icon-download" @click="exportData" /> -->
@@ -369,7 +371,7 @@
         // this.detailDialogVisible = true
         this.$store.state.task.theTask = { ...row }
         this.$router.push({
-          path: '/customer/plat/task/detail',
+          path: '/plat/task/detail',
           query: {
             type: this.queryForm.operateType,
           },
@@ -438,6 +440,7 @@
   .type {
     font-weight: bold;
   }
+
   $base: '.list';
   .link-button {
     font-size: 14px;

+ 1 - 1
src/views/proj/business/components/BusinessEdit.vue

@@ -180,7 +180,7 @@
       :query-params="queryContact"
       @save="selectContact" />
     <!-- 选择销售工程师弹窗 -->
-    <select-user ref="selectSales" :query-params="{ roles: ['Sales', 'SalesManager'] }" @save="selectSales" />
+    <select-user ref="selectSales" :query-params="{ roles: ['SalesEngineer'] }" @save="selectSales" />
     <!-- 选择经销商弹窗 -->
     <select-distributor ref="selectDistributor" @save="selectDistributor" />
     <!-- 选择产品弹窗 -->

+ 2 - 0
src/views/proj/business/components/BusinessGradation.vue

@@ -1,12 +1,14 @@
 <template>
   <div style="display: inline-block; margin: 0 10px">
     <el-button
+      v-permissions="['proj:business:upgrade']"
       :disabled="!['20', '30'].includes(businessInfo.nboType) || businessInfo.approStatus === '20'"
       type="primary"
       @click="handleClick('up')">
       升级
     </el-button>
     <el-button
+      v-permissions="['proj:business:downgrade']"
       :disabled="!['10', '20'].includes(businessInfo.nboType) || businessInfo.approStatus === '20'"
       type="danger"
       @click="handleClick('down')">

+ 12 - 4
src/views/proj/business/components/DetailsContact.vue

@@ -10,9 +10,13 @@
           @keyup.enter.native="fetchData" />
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
-        <el-button icon="el-icon-plus" @click="handleAddContact">新建联系人</el-button>
-        <el-button @click="handleSelectContact">关联</el-button>
-        <el-button type="danger" @click="handleDisassociation">解除关联</el-button>
+        <el-button v-permissions="['proj:business:customerContact:add']" icon="el-icon-plus" @click="handleAddContact">
+          新建客户联系人
+        </el-button>
+        <el-button v-permissions="['proj:business:contact:associate']" @click="handleSelectContact">关联</el-button>
+        <el-button v-permissions="['proj:business:contact:disassociate']" type="danger" @click="handleDisassociation">
+          解除关联
+        </el-button>
       </vab-query-form-right-panel>
     </vab-query-form>
     <el-table v-loading="listLoading" :data="contactList" height="calc(100% - 42px)" @selection-change="setSelectRows">
@@ -30,7 +34,11 @@
       <!--      </el-table-column>-->
       <el-table-column align="center" label="操作" show-overflow-tooltip>
         <template slot-scope="scope">
-          <el-button v-if="scope.row.contactId !== primacyContactId" type="text" @click="setPrimacyContact(scope.row)">
+          <el-button
+            v-if="scope.row.contactId !== primacyContactId"
+            v-permissions="['proj:business:contact:primary']"
+            type="text"
+            @click="setPrimacyContact(scope.row)">
             设为首要联系人
           </el-button>
           <span v-else>首要联系人</span>

+ 11 - 5
src/views/proj/business/detail.vue

@@ -9,14 +9,20 @@
             <span>
               <!--升级、降级-->
               <business-gradation :bus-id="id" :business-info="details" @fetch-data="init" />
-              <el-button :disabled="details.approStatus === '20'" @click="handleTransfer">转移项目</el-button>
               <el-button
+                v-permissions="['proj:business:transfer']"
+                :disabled="details.approStatus === '20'"
+                @click="handleTransfer">
+                转移项目
+              </el-button>
+              <el-button
+                v-permissions="['proj:business:reserve']"
                 :disabled="details.nboType === '40' || details.nboType === '50' || details.approStatus === '20'"
                 @click="handleToReserve">
                 转为储备
               </el-button>
-              <el-button>创建工单</el-button>
-              <el-button @click="createContract">创建合同</el-button>
+              <el-button v-permissions="['proj:business:workOrder']">创建工单</el-button>
+              <el-button v-permissions="['proj:business:contract']" @click="createContract">创建合同</el-button>
             </span>
           </h3>
         </div>
@@ -184,8 +190,8 @@
       </div>
       <div class="info-side">
         <div class="buttons">
-          <el-button type="primary" @click="handleEdit">编辑</el-button>
-          <el-button @click="handleDelete">删除</el-button>
+          <el-button v-permissions="['proj:business:edit']" type="primary" @click="handleEdit">编辑</el-button>
+          <!--          <el-button @click="handleDelete">删除</el-button>-->
           <el-button @click="$router.go(-1)">返回</el-button>
         </div>
         <details-records :dynamics-list="dynamicsList" />

+ 12 - 4
src/views/proj/business/index.vue

@@ -47,8 +47,16 @@
       </vab-query-form-top-panel>
 
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">新增项目</el-button>
-        <el-button icon="el-icon-refresh" type="primary" @click="handleTransfer">转移项目</el-button>
+        <el-button v-permissions="['proj:business:add']" icon="el-icon-plus" type="primary" @click="handleEdit">
+          新增项目
+        </el-button>
+        <el-button
+          v-permissions="['proj:business:transfer']"
+          icon="el-icon-refresh"
+          type="primary"
+          @click="handleTransfer">
+          转移项目
+        </el-button>
         <!--        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">创建任务</el-button>-->
         <!--        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">创建工单</el-button>-->
         <!--        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">创建合同</el-button>-->
@@ -125,8 +133,8 @@
       <el-table-column align="center" fixed="right" label="操作" width="68">
         <template #default="{ row }">
           <!--          <el-button type="text" @click="handleFollow(row)">跟进</el-button>-->
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <!--          <el-button type="text" @click="handleDelete(row)">删除</el-button>-->
+          <el-button v-permissions="['proj:business:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <!--                    <el-button type="text" @click="handleDelete(row)">删除</el-button>-->
         </template>
       </el-table-column>
     </el-table>

+ 8 - 4
src/views/system/config/index.vue

@@ -32,8 +32,12 @@
         </el-form>
       </vab-query-form-top-panel>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete">删除</el-button>
+        <el-button v-permissions="['system:config:add']" icon="el-icon-plus" type="primary" @click="handleEdit">
+          添加
+        </el-button>
+        <el-button v-permissions="['system:config:delete']" icon="el-icon-delete" type="danger" @click="handleDelete">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -59,8 +63,8 @@
 
       <el-table-column align="center" label="操作" width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:config:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:dept:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>

+ 18 - 4
src/views/system/dept/index.vue

@@ -20,8 +20,16 @@
         </el-form>
       </vab-query-form-top-panel>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+        <el-button v-permissions="['system:dept:add']" icon="el-icon-plus" type="primary" @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:dept:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -58,8 +66,14 @@
       </el-table-column>
       <el-table-column label="操作" width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button :disabled="!row.parentId" type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:dept:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button
+            v-permissions="['system:dept:delete']"
+            :disabled="!row.parentId"
+            type="text"
+            @click="handleDelete(row)">
+            删除
+          </el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 16 - 4
src/views/system/dict/dataList.vue

@@ -2,8 +2,20 @@
   <div class="user-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="5">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+        <el-button
+          v-permissions="['system:dictData:add']"
+          icon="el-icon-plus"
+          type="primary"
+          @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:dictData:edit']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="19">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
@@ -59,8 +71,8 @@
       </el-table-column>
       <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:dictData:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:dictData:detele']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 16 - 4
src/views/system/dict/index.vue

@@ -2,8 +2,20 @@
   <div class="user-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="5">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+        <el-button
+          v-permissions="['system:dictType:add']"
+          icon="el-icon-plus"
+          type="primary"
+          @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:dictType:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="19">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
@@ -50,8 +62,8 @@
       </el-table-column>
       <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:dictType:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:dictType:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 12 - 4
src/views/system/group/index.vue

@@ -2,8 +2,16 @@
   <div class="user-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="5">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+        <el-button v-permissions="['system:group:add']" icon="el-icon-plus" type="primary" @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:group:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="19">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
@@ -45,8 +53,8 @@
       </el-table-column>
       <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:group:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:group:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 8 - 1
src/views/system/loginLog/index.vue

@@ -51,7 +51,14 @@
         </el-form>
       </vab-query-form-top-panel>
       <vab-query-form-left-panel>
-        <el-button icon="el-icon-delete" size="mini" type="danger" @click="handleDelete">删除</el-button>
+        <el-button
+          v-permissions="['system:loginLog:delete']"
+          icon="el-icon-delete"
+          size="mini"
+          type="danger"
+          @click="handleDelete">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel>
         <table-tool :check-list.sync="checkList" :columns="columns" />

+ 5 - 3
src/views/system/menu/index.vue

@@ -14,7 +14,9 @@
 
     <vab-query-form>
       <vab-query-form-top-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit('')">添加</el-button>
+        <el-button v-permissions="['system:menu:add']" icon="el-icon-plus" type="primary" @click="handleEdit()">
+          添加
+        </el-button>
       </vab-query-form-top-panel>
     </vab-query-form>
     <el-table
@@ -96,8 +98,8 @@
       <!--            </el-table-column>-->
       <el-table-column fixed="right" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:menu:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:menu:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 8 - 4
src/views/system/notice/index.vue

@@ -22,8 +22,12 @@
         </el-form>
       </vab-query-form-top-panel>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete">删除</el-button>
+        <el-button v-permissions="['system:notice:add']" icon="el-icon-plus" type="primary" @click="handleEdit">
+          添加
+        </el-button>
+        <el-button v-permissions="['system:notice:delete']" icon="el-icon-delete" type="danger" @click="handleDelete">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <table-tool :check-list.sync="checkList" :columns="columns" />
@@ -48,8 +52,8 @@
 
       <el-table-column align="center" label="操作" width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:notice:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:notice:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>

+ 14 - 6
src/views/system/post/index.vue

@@ -1,11 +1,19 @@
 <template>
   <div class="user-management-container">
     <vab-query-form>
-      <vab-query-form-left-panel :span="5">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+      <vab-query-form-left-panel :span="4">
+        <el-button v-permissions="['system:post:add']" icon="el-icon-plus" type="primary" @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:post:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
-      <vab-query-form-right-panel :span="19">
+      <vab-query-form-right-panel :span="20">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
           <el-form-item label="岗位名称" prop="postName">
             <el-input v-model.trim="queryForm.postName" clearable placeholder="请输入岗位名称" />
@@ -45,8 +53,8 @@
       </el-table-column>
       <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:post:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:post:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 12 - 3
src/views/system/role/components/RoleDataScopeEdit.vue

@@ -25,6 +25,7 @@
           :check-strictly="!form.deptCheckStrictly"
           class="tree-border"
           :data="treeList"
+          :default-checked-keys="form.deptIds"
           default-expand-all
           empty-text="加载中,请稍后"
           node-key="id"
@@ -90,6 +91,10 @@
     },
     methods: {
       close() {
+        if (this.$refs.dept) {
+          this.$refs.dept.setCheckedKeys([])
+        }
+
         this.$refs['form'].resetFields()
         this.form = this.$options.data().form
         this.openDataScope = false
@@ -110,9 +115,7 @@
       /** 查询角色部门树结构 */
       getRoleDeptTreeselect(id) {
         roleApi.getRoleDeptTreeselect({ id: id }).then((response) => {
-          if (this.$refs.dept) {
-            this.$refs.dept.setCheckedKeys(response.data, true)
-          }
+          this.form.deptIds = response.data
         })
       },
       /** 分配数据权限操作 */
@@ -129,8 +132,14 @@
       submitDataScope: function () {
         if (this.form.id != undefined) {
           this.form.deptIds = this.getDeptAllCheckedKeys()
+          if (this.form.deptCheckStrictly) {
+            this.form.deptCheckStrictly = '10'
+          } else {
+            this.form.deptCheckStrictly = '20'
+          }
           let data = {
             roleId: this.form.id,
+            deptCheckStrictly: this.form.deptCheckStrictly,
             dataScope: Number(this.form.dataScope),
             deptIds: this.form.deptIds,
           }

+ 17 - 9
src/views/system/role/components/RoleEdit.vue

@@ -28,7 +28,13 @@
           父子联动
         </el-checkbox>
         <div class="vab-tree-border">
-          <el-tree ref="menu" :check-strictly="!form.menuCheckStrictly" :data="treeList" node-key="id" show-checkbox>
+          <el-tree
+            ref="menu"
+            :check-strictly="!form.menuCheckStrictly"
+            :data="treeList"
+            :default-checked-keys="form.menuIds"
+            node-key="id"
+            show-checkbox>
             <template #default="{ data }">
               <span>{{ data.meta.title }}</span>
             </template>
@@ -85,6 +91,12 @@
         this.dialogFormVisible = true
       },
       close() {
+        if (this.$refs.menu) {
+          this.$refs.menu.setCheckedKeys([])
+        }
+        this.menuExpand = false
+        this.menuNodeAll = false
+
         this.$refs['form'].resetFields()
         this.form = this.$options.data().form
         this.dialogFormVisible = false
@@ -98,9 +110,9 @@
         this.form = data
         this.form.menuCheckStrictly = this.form.menuCheckStrictly === '10'
         this.form.deptCheckStrictly = this.form.deptCheckStrictly === '10'
-        this.$nextTick(() => {
-          this.$refs.menu.setCheckedKeys(this.form.menuIds)
-        })
+        // this.$nextTick(() => {
+        //   this.$refs.menu.setCheckedKeys(this.form.menuIds)
+        // })
       },
       save() {
         // 具体业务请自行调整
@@ -111,11 +123,7 @@
             } else {
               this.form.menuCheckStrictly = '20'
             }
-            if (this.form.deptCheckStrictly) {
-              this.form.deptCheckStrictly = '10'
-            } else {
-              this.form.deptCheckStrictly = '20'
-            }
+
             this.form.menuIds = this.getMenuAllCheckedKeys()
             if (this.form.id) {
               const { msg } = await roleApi.doEdit(this.form)

+ 15 - 5
src/views/system/role/index.vue

@@ -2,8 +2,16 @@
   <div class="role-management-container">
     <vab-query-form>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-        <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+        <el-button v-permissions="['system:role:add']" icon="el-icon-plus" type="primary" @click="handleEdit($event)">
+          添加
+        </el-button>
+        <el-button
+          v-permissions="['system:role:delete']"
+          icon="el-icon-delete"
+          type="danger"
+          @click="handleDelete($event)">
+          删除
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
@@ -45,9 +53,11 @@
       </el-table-column>
       <el-table-column align="center" label="操作" show-overflow-tooltip width="150">
         <template #default="{ row }">
-          <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-          <el-button type="text" @click="handleDataScope(row)">数据权限</el-button>
-          <el-button type="text" @click="handleDelete(row)">删除</el-button>
+          <el-button v-permissions="['system:role:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+          <el-button v-permissions="['system:role:dataScope']" type="text" @click="handleDataScope(row)">
+            数据权限
+          </el-button>
+          <el-button v-permissions="['system:role:delete']" type="text" @click="handleDelete(row)">删除</el-button>
         </template>
       </el-table-column>
       <template #empty>

+ 58 - 0
src/views/system/user/components/RestPwd.vue

@@ -0,0 +1,58 @@
+<template>
+  <!-- 添加或修改参数配置对话框 -->
+  <el-dialog :title="title" :visible.sync="dialogFormVisible" width="600px" @close="close">
+    <el-form ref="form" label-width="80px" :model="form" :rules="rules">
+      <el-form-item prop="password">
+        <el-input v-model="form.password" placeholder="请输入新密码" show-password />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button type="primary" @click="save">确 定</el-button>
+      <el-button @click="close">取 消</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+  import userApi from '@/api/system/user'
+
+  export default {
+    name: 'RestPwd',
+    data() {
+      return {
+        form: {
+          id: undefined,
+          userName: '',
+          password: '',
+        },
+        rules: {
+          id: [{ required: true, message: '用户不能为空', trigger: 'blur' }],
+          password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }],
+        },
+        title: '重置密码',
+        dialogFormVisible: false,
+      }
+    },
+    methods: {
+      showEdit(row) {
+        this.form = row
+        this.dialogFormVisible = true
+      },
+      close() {
+        this.$refs['form'].resetFields()
+        this.form = this.$options.data().form
+        this.dialogFormVisible = false
+      },
+      save() {
+        this.$refs['form'].validate(async (valid) => {
+          if (valid) {
+            const { msg } = await userApi.resetPwd(this.form)
+            this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            this.$emit('fetch-data')
+            this.close()
+          }
+        })
+      },
+    },
+  }
+</script>

+ 102 - 0
src/views/system/user/components/UserRestPwd.vue

@@ -0,0 +1,102 @@
+<template>
+  <div>
+    <el-dropdown-item command="userRestPwd">
+      <vab-icon icon="user-line" />
+      {{ '修改密码' }}
+    </el-dropdown-item>
+    <!-- 添加或修改参数配置对话框 -->
+    <el-dialog
+      append-to-body
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      :show-close="false"
+      :title="title"
+      :visible.sync="dialogFormVisible"
+      width="600px"
+      @close="close">
+      <el-form ref="form" label-width="80px" :model="form" :rules="rules">
+        <el-form-item label="旧密码" prop="oldPassword">
+          <el-input v-model="form.oldPassword" placeholder="请输入旧密码" show-password />
+        </el-form-item>
+        <el-form-item label="新密码" prop="newPassword">
+          <el-input v-model="form.newPassword" placeholder="请输入新密码" show-password />
+        </el-form-item>
+        <el-form-item label="确认密码" prop="password">
+          <el-input v-model="form.password" placeholder="请确认新密码" show-password />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button type="primary" @click="save">确 定</el-button>
+        <el-button v-if="!isFirstLogin" @click="close">取 消</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import userApi from '@/api/system/user'
+
+  export default {
+    name: 'RestPwd',
+    data() {
+      const validatePwd = (rule, value, callback) => {
+        if (value !== this.form.newPassword) callback(new Error())
+        else callback()
+      }
+      return {
+        form: {
+          id: undefined,
+          oldPassword: '',
+          newPassword: '',
+          password: '',
+        },
+        rules: {
+          oldPassword: [{ required: true, message: '旧密码不能为空', trigger: 'blur' }],
+          newPassword: [{ required: true, message: '新密码不能为空', trigger: 'blur' }],
+          password: [
+            { required: true, message: '确认密码不能为空', trigger: 'blur' },
+            {
+              validator: validatePwd,
+              message: '两次输入的密码不一致',
+              trigger: 'blur',
+            },
+          ],
+        },
+        title: '修改密码',
+        dialogFormVisible: false,
+        isFirstLogin: false,
+      }
+    },
+
+    mounted() {
+      this.isFirstLogin = JSON.parse(localStorage.getItem('isFirstLogin'))
+      if (this.isFirstLogin) {
+        this.showEdit()
+      }
+    },
+    methods: {
+      showEdit() {
+        this.dialogFormVisible = true
+      },
+      close() {
+        if (this.isFirstLogin) {
+          this.$baseMessage('首次登录系统,请先修改账号密码。', 'error', 'vab-hey-message-success')
+          return
+        }
+        this.$refs['form'].resetFields()
+        this.form = this.$options.data().form
+        this.dialogFormVisible = false
+      },
+      save() {
+        this.$refs['form'].validate(async (valid) => {
+          if (valid) {
+            const { msg } = await userApi.changePwd(this.form)
+            this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            this.$emit('fetch-data')
+            this.close()
+          }
+        })
+      },
+    },
+  }
+</script>

+ 27 - 7
src/views/system/user/index.vue

@@ -27,8 +27,20 @@
       <el-col :span="20" :xs="24">
         <vab-query-form>
           <vab-query-form-left-panel :span="12">
-            <el-button icon="el-icon-plus" type="primary" @click="handleEdit($event)">添加</el-button>
-            <el-button icon="el-icon-delete" type="danger" @click="handleDelete($event)">删除</el-button>
+            <el-button
+              v-permissions="['system:user:add']"
+              icon="el-icon-plus"
+              type="primary"
+              @click="handleEdit($event)">
+              添加
+            </el-button>
+            <el-button
+              v-permissions="['system:user:delete']"
+              icon="el-icon-delete"
+              type="danger"
+              @click="handleDelete($event)">
+              删除
+            </el-button>
           </vab-query-form-left-panel>
           <vab-query-form-right-panel :span="12">
             <el-form :inline="true" :model="queryForm" @submit.native.prevent>
@@ -49,7 +61,7 @@
               {{ $index + 1 }}
             </template>
           </el-table-column>-->
-          <el-table-column align="center" label="id" prop="id" show-overflow-tooltip />
+          <!--          <el-table-column align="center" label="id" prop="id" show-overflow-tooltip />-->
           <el-table-column align="center" label="用户名" prop="userName" show-overflow-tooltip />
           <el-table-column align="center" label="昵称" prop="nickName" show-overflow-tooltip />
           <el-table-column align="center" label="手机号" prop="phone" show-overflow-tooltip />
@@ -68,10 +80,13 @@
               <span>{{ parseTime(scope.row.createdTime) }}</span>
             </template>
           </el-table-column>
-          <el-table-column align="center" label="操作" show-overflow-tooltip width="85">
+          <el-table-column align="center" label="操作" show-overflow-tooltip width="120">
             <template #default="{ row }">
-              <el-button type="text" @click="handleEdit(row)">编辑</el-button>
-              <el-button type="text" @click="handleDelete(row)">删除</el-button>
+              <el-button v-permissions="['system:user:resetPwd']" type="text" @click="handleResetPwd(row)">
+                重置
+              </el-button>
+              <el-button v-permissions="['system:user:edit']" type="text" @click="handleEdit(row)">编辑</el-button>
+              <el-button v-permissions="['system:user:delete']" type="text" @click="handleDelete(row)">删除</el-button>
             </template>
           </el-table-column>
           <template #empty>
@@ -89,6 +104,7 @@
       </el-col>
     </el-row>
     <edit ref="edit" @fetch-data="fetchData" />
+    <rest-pwd ref="restPwd" @fetch-data="fetchData" />
   </div>
 </template>
 
@@ -96,10 +112,11 @@
   import deptApi from '@/api/system/dept'
   import userApi from '@/api/system/user'
   import Edit from './components/UserEdit'
+  import RestPwd from './components/RestPwd'
 
   export default {
     name: 'User',
-    components: { Edit },
+    components: { Edit, RestPwd },
     data() {
       return {
         list: [],
@@ -152,6 +169,9 @@
       setSelectRows(val) {
         this.selectRows = val
       },
+      handleResetPwd(row) {
+        this.$refs['restPwd'].showEdit(row)
+      },
       handleEdit(row) {
         if (row.id) {
           this.$refs['edit'].showEdit(row)

+ 9 - 1
src/views/work/order/index.vue

@@ -17,7 +17,14 @@
     </el-row>
     <vab-query-form>
       <vab-query-form-left-panel :span="12">
-        <el-button icon="el-icon-plus" size="mini" type="primary" @click="$refs.edit.init()">新建</el-button>
+        <el-button
+          v-permissions="['proj:business:edit']"
+          icon="el-icon-plus"
+          size="mini"
+          type="primary"
+          @click="$refs.edit.init()">
+          新建
+        </el-button>
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <el-button icon="el-icon-download" @click="exportData" />
@@ -84,6 +91,7 @@
   import TableTool from '@/components/table/TableTool'
 
   export default {
+    name: 'WorkOrder',
     components: { TableTool },
     data() {
       return {

BIN
vab-icons/lib/fonts/remixicon.31d28485.eot


BIN
vab-icons/lib/fonts/remixicon.881fbc46.woff


BIN
vab-icons/lib/fonts/remixicon.888e61f0.ttf


BIN
vab-icons/lib/fonts/remixicon.9915fef9.woff2


File diff suppressed because it is too large
+ 153 - 0
vab-icons/lib/img/remixicon.95138f36.svg


File diff suppressed because it is too large
+ 8115 - 0
vab-icons/lib/img/remixicon.symbol.f09b1c74.svg


File diff suppressed because it is too large
+ 0 - 0
vab-icons/lib/vab-icons.css


+ 302 - 0
vab-icons/lib/vab-icons.umd.min.js

@@ -0,0 +1,302 @@
+/* eslint-disable */
+!(function () {
+  if (
+    !process.env[
+      '\u0056\u0055\u0045\u005f\u0041\u0050\u0050\u005f\u0053\u0045\u0043\u0052\u0045\u0054\u005f\u004b\u0045\u0059'
+    ]
+  )
+    document.body.innerHTML = ''
+  else if (
+    process.env[
+      '\u0056\u0055\u0045\u005f\u0041\u0050\u0050\u005f\u0053\u0045\u0043\u0052\u0045\u0054\u005f\u004b\u0045\u0059'
+    ] == '\u0070\u0072\u0065\u0076\u0069\u0065\u0077\u000d\u000a'
+  )
+    if (
+      document.domain != 'localhost' &&
+      document.domain !=
+        '\u0063\u0068\u0075\u0031\u0032\u0030\u0034\u0035\u0030\u0035\u0030\u0035\u0036\u002e\u0067\u0069\u0074\u0065\u0065\u002e\u0069\u006f' &&
+      document.domain != '127.0.0.1' &&
+      document.domain !=
+        '\u0076\u0075\u0065\u002d\u0061\u0064\u006d\u0069\u006e\u002d\u0062\u0065\u0061\u0075\u0074\u0069\u0066\u0075\u006c\u002e\u0063\u006f\u006d' &&
+      process.env.NODE_ENV ===
+        '\u0070\u0072\u006f\u0064\u0075\u0063\u0074\u0069\u006f\u006e'
+    )
+      document.body.innerHTML = ''
+})()
+;(function (t, e) {
+  'object' === typeof exports && 'object' === typeof module
+    ? (module.exports = e())
+    : 'function' === typeof define && define.amd
+    ? define([], e)
+    : 'object' === typeof exports
+    ? (exports['vab-icons'] = e())
+    : (t['vab-icons'] = e())
+})('undefined' !== typeof self ? self : this, function () {
+  return (function (t) {
+    var e = {}
+    function n(r) {
+      if (e[r]) return e[r].exports
+      var o = (e[r] = { i: r, l: !1, exports: {} })
+      return t[r].call(o.exports, o, o.exports, n), (o.l = !0), o.exports
+    }
+    return (
+      (n.m = t),
+      (n.c = e),
+      (n.d = function (t, e, r) {
+        n.o(t, e) || Object.defineProperty(t, e, { enumerable: !0, get: r })
+      }),
+      (n.r = function (t) {
+        'undefined' !== typeof Symbol &&
+          Symbol.toStringTag &&
+          Object.defineProperty(t, Symbol.toStringTag, { value: 'Module' }),
+          Object.defineProperty(t, '__esModule', { value: !0 })
+      }),
+      (n.t = function (t, e) {
+        if ((1 & e && (t = n(t)), 8 & e)) return t
+        if (4 & e && 'object' === typeof t && t && t.__esModule) return t
+        var r = Object.create(null)
+        if (
+          (n.r(r),
+          Object.defineProperty(r, 'default', { enumerable: !0, value: t }),
+          2 & e && 'string' != typeof t)
+        )
+          for (var o in t)
+            n.d(
+              r,
+              o,
+              function (e) {
+                return t[e]
+              }.bind(null, o)
+            )
+        return r
+      }),
+      (n.n = function (t) {
+        var e =
+          t && t.__esModule
+            ? function () {
+                return t['default']
+              }
+            : function () {
+                return t
+              }
+        return n.d(e, 'a', e), e
+      }),
+      (n.o = function (t, e) {
+        return Object.prototype.hasOwnProperty.call(t, e)
+      }),
+      (n.p = ''),
+      n((n.s = 'fb15'))
+    )
+  })({
+    '06af': function (t, e, n) {},
+    '1cdc': function (t, e, n) {
+      'use strict'
+      n('06af')
+    },
+    '29a1': function (t, e, n) {
+      t.exports = n.p + 'img/remixicon.symbol.f09b1c74.svg'
+    },
+    8875: function (t, e, n) {
+      var r, o, i
+      ;(function (n, c) {
+        ;(o = []),
+          (r = c),
+          (i = 'function' === typeof r ? r.apply(e, o) : r),
+          void 0 === i || (t.exports = i)
+      })('undefined' !== typeof self && self, function () {
+        function t() {
+          var e = Object.getOwnPropertyDescriptor(document, 'currentScript')
+          if (!e && 'currentScript' in document && document.currentScript)
+            return document.currentScript
+          if (e && e.get !== t && document.currentScript)
+            return document.currentScript
+          try {
+            throw new Error()
+          } catch (p) {
+            var n,
+              r,
+              o,
+              i = /.*at [^(]*\((.*):(.+):(.+)\)$/gi,
+              c = /@([^@]*):(\d+):(\d+)\s*$/gi,
+              s = i.exec(p.stack) || c.exec(p.stack),
+              u = (s && s[1]) || !1,
+              a = (s && s[2]) || !1,
+              f = document.location.href.replace(document.location.hash, ''),
+              l = document.getElementsByTagName('script')
+            u === f &&
+              ((n = document.documentElement.outerHTML),
+              (r = new RegExp(
+                '(?:[^\\n]+?\\n){0,' +
+                  (a - 2) +
+                  '}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*',
+                'i'
+              )),
+              (o = n.replace(r, '$1').trim()))
+            for (var d = 0; d < l.length; d++) {
+              if ('interactive' === l[d].readyState) return l[d]
+              if (l[d].src === u) return l[d]
+              if (u === f && l[d].innerHTML && l[d].innerHTML.trim() === o)
+                return l[d]
+            }
+            return null
+          }
+        }
+        return t
+      })
+    },
+    ab05: function (t, e, n) {},
+    fb15: function (t, e, n) {
+      'use strict'
+      if ((n.r(e), 'undefined' !== typeof window)) {
+        var r = window.document.currentScript,
+          o = n('8875')
+        ;(r = o()),
+          'currentScript' in document ||
+            Object.defineProperty(document, 'currentScript', { get: o })
+        var i = r && r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+        i && (n.p = i[1])
+      }
+      var c = function () {
+          var t,
+            e = this,
+            n = e.$createElement,
+            r = e._self._c || n
+          return e.isExternal
+            ? r(
+                'img',
+                e._g(
+                  { staticClass: 'img-icon', attrs: { src: e.icon } },
+                  e.$listeners
+                )
+              )
+            : e.isCustomSvg
+            ? r(
+                'svg',
+                e._g(
+                  { class: e.svgClass, attrs: { 'aria-hidden': 'true' } },
+                  e.$listeners
+                ),
+                [r('use', { attrs: { 'xlink:href': '#vab-icon-' + e.icon } })]
+              )
+            : e.isDefaultSvg
+            ? r('svg', e._g({ staticClass: 'vab-icon' }, e.$listeners), [
+                r('use', {
+                  attrs: { 'xlink:href': e.remixIconPath + '#ri-' + e.icon },
+                }),
+              ])
+            : r(
+                'i',
+                e._g(
+                  {
+                    class: ((t = {}), (t['ri-' + e.icon] = !0), t),
+                    attrs: { 'aria-hidden': 'true' },
+                  },
+                  e.$listeners
+                )
+              )
+        },
+        s = []
+      n('ab05')
+      function u(t) {
+        return /^(https?:|mailto:|tel:)/.test(t)
+      }
+      var a = {
+          name: 'VabIcon',
+          props: {
+            icon: { type: String, required: !0 },
+            isCustomSvg: { type: Boolean, default: !1 },
+            isDefaultSvg: { type: Boolean, default: !1 },
+            className: { type: String, default: '' },
+          },
+          data: function () {
+            return { remixIconPath: n('29a1') }
+          },
+          computed: {
+            isExternal: function () {
+              return u(this.icon)
+            },
+            svgClass: function () {
+              return this.className
+                ? 'vab-icon '.concat(this.className)
+                : 'vab-icon'
+            },
+          },
+        },
+        f = a
+      n('1cdc')
+      function l(t, e, n, r, o, i, c, s) {
+        var u,
+          a = 'function' === typeof t ? t.options : t
+        if (
+          (e && ((a.render = e), (a.staticRenderFns = n), (a._compiled = !0)),
+          r && (a.functional = !0),
+          i && (a._scopeId = 'data-v-' + i),
+          c
+            ? ((u = function (t) {
+                ;(t =
+                  t ||
+                  (this.$vnode && this.$vnode.ssrContext) ||
+                  (this.parent &&
+                    this.parent.$vnode &&
+                    this.parent.$vnode.ssrContext)),
+                  t ||
+                    'undefined' === typeof __VUE_SSR_CONTEXT__ ||
+                    (t = __VUE_SSR_CONTEXT__),
+                  o && o.call(this, t),
+                  t && t._registeredComponents && t._registeredComponents.add(c)
+              }),
+              (a._ssrRegister = u))
+            : o &&
+              (u = s
+                ? function () {
+                    o.call(
+                      this,
+                      (a.functional ? this.parent : this).$root.$options
+                        .shadowRoot
+                    )
+                  }
+                : o),
+          u)
+        )
+          if (a.functional) {
+            a._injectStyles = u
+            var f = a.render
+            a.render = function (t, e) {
+              return u.call(e), f(t, e)
+            }
+          } else {
+            var l = a.beforeCreate
+            a.beforeCreate = l ? [].concat(l, u) : [u]
+          }
+        return { exports: t, options: a }
+      }
+      var d = l(f, c, s, !1, null, '79aac9d9', null),
+        p = d.exports
+      e['default'] = p
+    },
+  })['default']
+})
+!(function () {
+  if (
+    !process.env[
+      '\u0056\u0055\u0045\u005f\u0041\u0050\u0050\u005f\u0053\u0045\u0043\u0052\u0045\u0054\u005f\u004b\u0045\u0059'
+    ]
+  )
+    document.body.innerHTML = ''
+  else if (
+    process.env[
+      '\u0056\u0055\u0045\u005f\u0041\u0050\u0050\u005f\u0053\u0045\u0043\u0052\u0045\u0054\u005f\u004b\u0045\u0059'
+    ] == '\u0070\u0072\u0065\u0076\u0069\u0065\u0077\u000d\u000a'
+  )
+    if (
+      document.domain != 'localhost' &&
+      document.domain !=
+        '\u0063\u0068\u0075\u0031\u0032\u0030\u0034\u0035\u0030\u0035\u0030\u0035\u0036\u002e\u0067\u0069\u0074\u0065\u0065\u002e\u0069\u006f' &&
+      document.domain != '127.0.0.1' &&
+      document.domain !=
+        '\u0076\u0075\u0065\u002d\u0061\u0064\u006d\u0069\u006e\u002d\u0062\u0065\u0061\u0075\u0074\u0069\u0066\u0075\u006c\u002e\u0063\u006f\u006d' &&
+      process.env.NODE_ENV ===
+        '\u0070\u0072\u006f\u0064\u0075\u0063\u0074\u0069\u006f\u006e'
+    )
+      document.body.innerHTML = ''
+})()

+ 5 - 0
vab-icons/package.json

@@ -0,0 +1,5 @@
+{
+  "name": "vab-icons",
+  "version": "0.0.23",
+  "main": "./lib/vab-icons.umd.min.js"
+}

+ 0 - 1
vue.config.js

@@ -67,7 +67,6 @@ module.exports = {
     //     },
     //   },
     // },
-    after: require('./mock'),
   },
   configureWebpack() {
     return {

Some files were not shown because too many files changed in this diff