Browse Source

修改分配菜单树状表格和多选联动

ljh 2 years ago
parent
commit
6dd759f317

+ 91 - 0
chuanyi-admin/src/mixin/multipleChoice.js

@@ -0,0 +1,91 @@
+import { getJsonParents } from '@/utils/findParents.js'
+export default {
+  // data() {
+  //     return {
+  //         // selectData: [],
+  //         // multiple: null,
+  //     }
+  // },
+  methods: {
+    select(selection, row) {
+      if (selection.some(el => { return row.id === el.id })) {
+        console.log(selection)
+        this.childrenRecursiveChange(row, true)
+      } else {
+        this.childrenRecursiveChange(row, false)
+        this.parentsRecursiveChange(selection, row, false)
+        // if (row.children) {
+        //   row.children.map(j => {
+        //     this.toggleSelection(j, false)
+        //   })
+        // }
+        // let parentIds = getJsonParents(this.menuList, row.id);
+        // selection.map(el => {
+        //   if (el.id == parentIds[parentIds.length - 1]) {
+        //     this.toggleSelection(el, false);
+        //   }
+        // })
+      }
+    },
+    childrenRecursiveChange(row, status) {
+      if (row.children) {
+        row.children.map(j => {
+          this.toggleSelection(j, status)
+          if (j.children) this.childrenRecursiveChange(j, status)
+        })
+      }
+    },
+    parentsRecursiveChange(selection, row, status) {
+      const parentIds = getJsonParents(this.menuList, row.id)
+      if (parentIds && parentIds.length) {
+        selection.map(el => {
+          if (parentIds.includes(el.id)) {
+            this.toggleSelection(el, status)
+          }
+        })
+      }
+    },
+    selectAll(selection) {
+      // tabledata第一层只要有在selection里面就是全选
+      const isSelect = selection.some(el => {
+        const tableDataIds = this.menuList.map(j => j.id)
+        return tableDataIds.includes(el.id)
+      })
+      // tableDate第一层只要有不在selection里面就是全不选
+      const isCancel = !this.menuList.every(el => {
+        const selectIds = selection.map(j => j.id)
+        return selectIds.includes(el.id)
+      })
+      if (isSelect) {
+        selection.map(el => {
+          this.childrenRecursiveChange(el, true)
+          // if (el.children) {
+          //   el.children.map(j => {
+          //     this.toggleSelection(j, true)
+          //   })
+          // }
+        })
+      }
+      if (isCancel) {
+        this.menuList.map(el => {
+          this.childrenRecursiveChange(el, false)
+          // if (el.children) {
+          //   el.children.map(j => {
+          //     this.toggleSelection(j, false)
+          //   })
+          // }
+        })
+      }
+    },
+    toggleSelection(row, select) {
+      if (row) {
+        this.$nextTick(() => {
+          this.$refs.roleTable && this.$refs.roleTable.toggleRowSelection(row, select)
+        })
+      }
+    },
+    cancelAll() {
+      this.$refs.roleTable.clearSelection()
+    }
+  }
+}

+ 43 - 0
chuanyi-admin/src/utils/findParents.js

@@ -0,0 +1,43 @@
+function findParentNodeId(jsonData, nodeId) {
+  let result
+  if (!jsonData || !jsonData.children) {
+    return result
+  }
+  for (let i = 0; i < jsonData.children.length; i++) {
+    const item = jsonData.children[i]
+    if (item.id === nodeId) {
+      result = jsonData.id
+      return result
+    } else if (item.children && item.children.length > 0) {
+      result = findParentNodeId(item, nodeId)
+      if (result) {
+        return result
+      }
+    }
+  }
+  return result
+}
+/**
+ * 最终形态
+ */
+export function getJsonParents(array, nodeId) {
+  const str = []
+  if (!array || array.length === 0) return null
+  for (let i = 0; i < array.length; i++) {
+    const parentId = findParentNodeId(array[i], nodeId)
+    if (!parentId) continue
+    else {
+      handler(array[i], nodeId)
+    }
+    return str
+  }
+  function handler(json, nodeId) {
+    const parentId = findParentNodeId(json, nodeId)
+    if (parentId) {
+      str.unshift(parentId)
+      handler(json, parentId)
+    } else {
+      return
+    }
+  }
+}

+ 16 - 249
chuanyi-admin/src/views/system/role/user-menu.vue

@@ -28,6 +28,9 @@
       border
       stripe
       header-row-class-name="headBackground"
+      :tree-props="{ children: 'children' }"
+      @select="select"
+      @select-all="selectAll"
       @selection-change="handelDelDist"
     >
       <el-table-column type="selection" width="55" align="center" />
@@ -46,65 +49,26 @@
       </el-table-column>
     </el-table>
 
-    <el-dialog title="添加菜单权限" :visible.sync="dialogVisible" width="800px" :close-on-click-modal="false">
-      <el-row class="czBtns">
-        <el-col>
-          <el-button type="primary" plain icon="el-icon-plus" size="mini" :disabled="distribution" @click="handleDel">
-            批量分配</el-button>
-        </el-col>
-      </el-row>
-      <el-table
-        ref="distTable"
-        v-loading="distLoading"
-        :data="addMenuList"
-        row-key="id"
-        border
-        stripe
-        header-row-class-name="headBackground"
-        :expand-row-keys="defaultExpend"
-        @selection-change="handelAddDist"
-        @select="select"
-        @select-all="selectAll"
-      >
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="菜单名称" prop="menuName" header-align="center" show-overflow-tooltip />
-        <el-table-column label="菜单图标" prop="menuIcon" align="center" show-overflow-tooltip />
-        <el-table-column label="菜单路径" prop="menuUrl" align="center" show-overflow-tooltip />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template slot-scope="scope">
-            <el-button
-              type="primary"
-              plain
-              icon="el-icon-circle-plus"
-              size="mini"
-              :disabled="!distribution"
-              @click="addMenu(scope.row.id, $event)"
-            >分配菜单
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-dialog>
+    <userMenuSelect ref="select" @handelUpdate="getList" />
   </div>
 </template>
 
 <script>
-import { getMenuListByRoleId, getMenuListTree, distributionMenu, delDistributionMenu } from '@/api/system/role'
+import { getMenuListByRoleId, delDistributionMenu } from '@/api/system/role'
+import userMenuSelect from './user-menuSelect.vue'
+import multipleChoice from '@/mixin/multipleChoice'
 export default {
   name: 'UserMenu',
+  components: {
+    userMenuSelect
+  },
+  mixins: [multipleChoice],
   data() {
     return {
       // 遮罩层
       loading: true,
-      // 弹出框表格加载状态
-      distLoading: true,
       // 角色ID
       roleId: null,
-      // 分配菜单参数
-      distObj: {
-        id: this.$route.params.userId,
-        menuList: []
-      },
       // 取消分配菜单参数
       delDistObj: {
         id: this.$route.params.userId,
@@ -113,17 +77,7 @@ export default {
       // 用户表格数据
       menuList: [],
       // 禁用取消分配
-      celDistribution: true,
-      // 弹出框
-      dialogVisible: false,
-      // 分配菜单表格
-      addMenuList: [],
-      // 禁用分配
-      distribution: true,
-      // 全选按钮选中所有节点
-      isSelectAll: false,
-      // 默认展开行
-      defaultExpend: []
+      celDistribution: true
     }
   },
   created() {
@@ -139,79 +93,26 @@ export default {
         if (res.code === 200) {
           const data = res.data
           this.menuList = this.$utils.toArrayTree(data)
+          this.selectData = this.menuList
+          this.multiple = 'roleTable'
           this.loading = false
         }
       })
     },
-    /** 所有菜单树信息 */
-    getMenuListTree() {
-      getMenuListTree().then(res => {
-        const data = res.data
-        data.forEach(item => {
-          item.isSelect = false
-        })
-        this.addMenuList = data
-        this.distLoading = false
-        this.$nextTick(() => {
-          this.defaultExpend = []
-        })
-      })
-    },
     /** 返回按钮 */
     handleClose() {
       this.$router.push('/system/role')
     },
     /** 添加菜单 */
     handelAdd() {
-      this.dialogVisible = true
-      this.getMenuListTree()
-    },
-    /** 分配菜单多选 */
-    handelAddDist(selection) {
-      this.distObj.menuList = selection.map(item => { return { id: item.id } })
-      this.distribution = !selection.length
+      this.$refs.select.show()
     },
     /** 取消分配菜单多选 */
     handelDelDist(selection) {
+      // console.log(selection);
       this.delDistObj.menuList = selection.map(item => { return { id: item.id } })
       this.celDistribution = !selection.length
     },
-    /** 分配按钮 */
-    addMenu(id, event) {
-      this.$resetBtn(event)
-      this.distObj.menuList = []
-      this.$confirm('您确定要分配该菜单吗?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        cancelButtonClass: 'btn_custom_cancel',
-        type: 'warning'
-      }).then(() => {
-        this.distObj.menuList.push({ id })
-        this.distributionMenu()
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '已取消操作'
-        })
-      })
-    },
-    /** 批量分配菜单按钮 */
-    handleDel(event) {
-      this.$resetBtn(event)
-      this.$confirm('您确定要批量分配选中的菜单吗?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        cancelButtonClass: 'btn_custom_cancel',
-        type: 'warning'
-      }).then(() => {
-        this.distributionMenu()
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '已取消操作'
-        })
-      })
-    },
     /** 取消分配按钮 */
     delMenu(id) {
       this.delDistObj.menuList = []
@@ -247,19 +148,6 @@ export default {
         })
       })
     },
-    /** 分配菜单请求 */
-    distributionMenu() {
-      distributionMenu(this.distObj).then(res => {
-        if (res.code === 200) {
-          this.$message({
-            type: 'success',
-            message: res.data
-          })
-          this.dialogVisible = false
-          this.getList()
-        }
-      })
-    },
     /** 取消分配菜单请求 */
     delDistributionMenu() {
       delDistributionMenu(this.delDistObj).then(res => {
@@ -272,127 +160,6 @@ export default {
           this.getList()
         }
       })
-    },
-    // 选中父节点时,子节点一起选中取消
-    select(selection, row) {
-      // 选中
-      if (
-        selection.some((el) => {
-          return row.id === el.id
-        })
-      ) {
-        // 选中行有children
-        if (row.children.length) {
-          // 全选children
-          this.setChildren(row.children, true)
-        } else {
-          this.findParentNode(this.addMenuList, selection, row)
-        }
-      } else {
-        // 反选
-        // 子节点有children全选中
-        if (row.children.length) {
-          this.setChildren(row.children, false)
-        } else {
-          // 反选子节点反选父节点
-          const parentRow = selection.find(item => {
-            return item.id === row.parentId
-          })
-          this.$nextTick(() => {
-            this.$refs.distTable.toggleRowSelection(parentRow, false)
-          })
-        }
-      }
-    },
-    findParentNode(data, selection, row) {
-      for (let i = 0; i < data.length; i++) {
-        this.setParentCheck(data[i], selection, row)
-        if (data[i].children) {
-          this.findParentNode(data[i].children, selection, row)
-        }
-      }
-    },
-    setParentCheck(item, selection, row) {
-      if (item.id === row.parentId) {
-        const selectIds = selection.filter(o => {
-          return item.id === o.parentId
-        })
-        if (item.children.length === 1) {
-          this.recursion(this.addMenuList, item)
-          return
-        }
-        item.children.forEach(j => {
-          selectIds.forEach(q => {
-            if (j.id === q.id) {
-              if (selectIds.length === item.children.length) {
-                this.$nextTick(() => {
-                  this.$refs.distTable.toggleRowSelection(item, true)
-                })
-              }
-            }
-          })
-        })
-      }
-    },
-    recursion(data, item) {
-      for (let i = 0; i < data.length; i++) {
-        if (item) {
-          if (data[i].id === item.parentId) {
-            this.$nextTick(() => {
-              this.$refs.distTable.toggleRowSelection(data[i], true)
-              this.$refs.distTable.toggleRowSelection(item, true)
-            })
-          }
-        }
-        if (data[i].children) {
-          this.recursion(data[i].children)
-        }
-      }
-    },
-    // 选择全部
-    selectAll(selection) {
-      // addMenuList第一层只要有在selection里面就是全选
-      const isSelect = selection.some((el) => {
-        const tableDataIds = this.addMenuList.map((j) => j.id)
-        return tableDataIds.includes(el.id)
-      })
-      // addMenuList第一层只要有不在selection里面就是全不选
-      const isCancel = !this.addMenuList.every((el) => {
-        const selectIds = selection.map((j) => j.id)
-        return selectIds.includes(el.id)
-      })
-      if (isSelect) {
-        selection.map((el) => {
-          if (el.children) {
-            // 解决子节点没有被勾选到
-            this.setChildren(el.children, true)
-          }
-        })
-      }
-      if (isCancel) {
-        this.addMenuList.map((el) => {
-          if (el.children) {
-            // 解决子节点没有被勾选到
-            this.setChildren(el.children, false)
-          }
-        })
-      }
-    },
-    setChildren(children, type) {
-      // 编辑多个子节点
-      children.map((j) => {
-        this.toggleSelection(j, type)
-        if (j.children) {
-          this.setChildren(j.children, type)
-        }
-      })
-    },
-    toggleSelection(row, select) {
-      if (row) {
-        this.$nextTick(() => {
-          this.$refs.distTable.toggleRowSelection(row, select)
-        })
-      }
     }
   }
 }

+ 404 - 0
chuanyi-admin/src/views/system/role/user-menu2.vue

@@ -0,0 +1,404 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="10" class="mb8 czBtns">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handelAdd">添加菜单权限</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete-solid"
+          size="mini"
+          :disabled="celDistribution"
+          @click="handleDelMenus"
+        >批量取消
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-back" size="mini" @click="handleClose">返回</el-button>
+      </el-col>
+    </el-row>
+
+    <el-table
+      ref="roleTable"
+      v-loading="loading"
+      :data="menuList"
+      row-key="id"
+      border
+      stripe
+      header-row-class-name="headBackground"
+      @selection-change="handelDelDist"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="菜单名称" prop="menuName" header-align="center" show-overflow-tooltip />
+      <el-table-column label="菜单图标" prop="menuIcon" align="center" show-overflow-tooltip />
+      <el-table-column label="菜单路径" prop="menuUrl" align="center" show-overflow-tooltip />
+      <el-table-column label="更新时间" prop="updateTime" align="center" show-overflow-tooltip />
+      <el-table-column label="创建时间" prop="createTime" align="center" show-overflow-tooltip />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button type="text" size="mini" :disabled="!celDistribution" @click="delMenu(scope.row.id)"><i
+            class="el-icon-circle-close celBtn"
+          /><span>取消分配</span>
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-dialog title="添加菜单权限" :visible.sync="dialogVisible" width="800px" :close-on-click-modal="false">
+      <el-row class="czBtns">
+        <el-col>
+          <el-button type="primary" plain icon="el-icon-plus" size="mini" :disabled="distribution" @click="handleDel">
+            批量分配</el-button>
+        </el-col>
+      </el-row>
+      <el-table
+        ref="distTable"
+        v-loading="distLoading"
+        :data="addMenuList"
+        row-key="id"
+        border
+        stripe
+        header-row-class-name="headBackground"
+        :expand-row-keys="defaultExpend"
+        @selection-change="handelAddDist"
+        @select="select"
+        @select-all="selectAll"
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="菜单名称" prop="menuName" header-align="center" show-overflow-tooltip />
+        <el-table-column label="菜单图标" prop="menuIcon" align="center" show-overflow-tooltip />
+        <el-table-column label="菜单路径" prop="menuUrl" align="center" show-overflow-tooltip />
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-circle-plus"
+              size="mini"
+              :disabled="!distribution"
+              @click="addMenu(scope.row.id, $event)"
+            >分配菜单
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getMenuListByRoleId, getMenuListTree, distributionMenu, delDistributionMenu } from '@/api/system/role'
+export default {
+  name: 'UserMenu',
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 弹出框表格加载状态
+      distLoading: true,
+      // 角色ID
+      roleId: null,
+      // 分配菜单参数
+      distObj: {
+        id: this.$route.params.userId,
+        menuList: []
+      },
+      // 取消分配菜单参数
+      delDistObj: {
+        id: this.$route.params.userId,
+        menuList: []
+      },
+      // 用户表格数据
+      menuList: [],
+      // 禁用取消分配
+      celDistribution: true,
+      // 弹出框
+      dialogVisible: false,
+      // 分配菜单表格
+      addMenuList: [],
+      // 禁用分配
+      distribution: true,
+      // 全选按钮选中所有节点
+      isSelectAll: false,
+      // 默认展开行
+      defaultExpend: []
+    }
+  },
+  created() {
+    this.roleId = this.$route.params.userId
+    this.getList()
+  },
+  methods: {
+    /** 查询用户拥有的菜单列表 */
+    getList() {
+      const roleList = []
+      roleList.push({ id: Number(this.$route.params.userId) })
+      getMenuListByRoleId({ roleList }).then(res => {
+        if (res.code === 200) {
+          const data = res.data
+          this.menuList = this.$utils.toArrayTree(data)
+          this.loading = false
+        }
+      })
+    },
+    /** 所有菜单树信息 */
+    getMenuListTree() {
+      getMenuListTree().then(res => {
+        const data = res.data
+        data.forEach(item => {
+          item.isSelect = false
+        })
+        this.addMenuList = data
+        console.log(this.addMenuList)
+        this.distLoading = false
+        this.$nextTick(() => {
+          this.defaultExpend = []
+        })
+      })
+    },
+    /** 返回按钮 */
+    handleClose() {
+      this.$router.push('/system/role')
+    },
+    /** 添加菜单 */
+    handelAdd() {
+      this.dialogVisible = true
+      this.getMenuListTree()
+    },
+    /** 分配菜单多选 */
+    handelAddDist(selection) {
+      this.distObj.menuList = selection.map(item => { return { id: item.id } })
+      this.distribution = !selection.length
+    },
+    /** 取消分配菜单多选 */
+    handelDelDist(selection) {
+      this.delDistObj.menuList = selection.map(item => { return { id: item.id } })
+      this.celDistribution = !selection.length
+    },
+    /** 分配按钮 */
+    addMenu(id, event) {
+      this.$resetBtn(event)
+      this.distObj.menuList = []
+      this.$confirm('您确定要分配该菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.distObj.menuList.push({ id })
+        this.distributionMenu()
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 批量分配菜单按钮 */
+    handleDel(event) {
+      this.$resetBtn(event)
+      this.$confirm('您确定要批量分配选中的菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.distributionMenu()
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 取消分配按钮 */
+    delMenu(id) {
+      this.delDistObj.menuList = []
+      this.$confirm('您确定要取消分配该菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.delDistObj.menuList.push({ id })
+        this.delDistributionMenu()
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 批量取消分配菜单按钮 */
+    handleDelMenus() {
+      this.$confirm('您确定要批量取消选中的菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.delDistributionMenu()
+      }).catch(() => {
+        this.$refs.roleTable.clearSelection()
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 分配菜单请求 */
+    distributionMenu() {
+      distributionMenu(this.distObj).then(res => {
+        if (res.code === 200) {
+          this.$message({
+            type: 'success',
+            message: res.data
+          })
+          this.dialogVisible = false
+          this.getList()
+        }
+      })
+    },
+    /** 取消分配菜单请求 */
+    delDistributionMenu() {
+      delDistributionMenu(this.delDistObj).then(res => {
+        if (res.code === 200) {
+          this.$message({
+            type: 'success',
+            message: '取消成功'
+          })
+          this.dialogVisible = false
+          this.getList()
+        }
+      })
+    },
+    // 选中父节点时,子节点一起选中取消
+    select(selection, row) {
+      // 选中
+      if (
+        selection.some((el) => {
+          return row.id === el.id
+        })
+      ) {
+        // 选中行有children
+        if (row.children.length) {
+          // 全选children
+          this.setChildren(row.children, true)
+        } else {
+          this.findParentNode(this.addMenuList, selection, row)
+        }
+      } else {
+        // 反选
+        // 子节点有children全选中
+        if (row.children.length) {
+          this.setChildren(row.children, false)
+        } else {
+          // 反选子节点反选父节点
+          const parentRow = selection.find(item => {
+            return item.id === row.parentId
+          })
+          this.$nextTick(() => {
+            this.$refs.distTable.toggleRowSelection(parentRow, false)
+          })
+        }
+      }
+    },
+    findParentNode(data, selection, row) {
+      for (let i = 0; i < data.length; i++) {
+        this.setParentCheck(data[i], selection, row)
+        if (data[i].children) {
+          this.findParentNode(data[i].children, selection, row)
+        }
+      }
+    },
+    setParentCheck(item, selection, row) {
+      if (item.id === row.parentId) {
+        const selectIds = selection.filter(o => {
+          return item.id === o.parentId
+        })
+        if (item.children.length === 1) {
+          this.recursion(this.addMenuList, item)
+          return
+        }
+        item.children.forEach(j => {
+          selectIds.forEach(q => {
+            if (j.id === q.id) {
+              if (selectIds.length === item.children.length) {
+                this.$nextTick(() => {
+                  this.$refs.distTable.toggleRowSelection(item, true)
+                })
+              }
+            }
+          })
+        })
+      }
+    },
+    recursion(data, item) {
+      for (let i = 0; i < data.length; i++) {
+        if (item) {
+          if (data[i].id === item.parentId) {
+            this.$nextTick(() => {
+              this.$refs.distTable.toggleRowSelection(data[i], true)
+              this.$refs.distTable.toggleRowSelection(item, true)
+            })
+          }
+        }
+        if (data[i].children) {
+          this.recursion(data[i].children)
+        }
+      }
+    },
+    // 选择全部
+    selectAll(selection) {
+      // addMenuList第一层只要有在selection里面就是全选
+      const isSelect = selection.some((el) => {
+        const tableDataIds = this.addMenuList.map((j) => j.id)
+        return tableDataIds.includes(el.id)
+      })
+      // addMenuList第一层只要有不在selection里面就是全不选
+      const isCancel = !this.addMenuList.every((el) => {
+        const selectIds = selection.map((j) => j.id)
+        return selectIds.includes(el.id)
+      })
+      if (isSelect) {
+        selection.map((el) => {
+          if (el.children) {
+            // 解决子节点没有被勾选到
+            this.setChildren(el.children, true)
+          }
+        })
+      }
+      if (isCancel) {
+        this.addMenuList.map((el) => {
+          if (el.children) {
+            // 解决子节点没有被勾选到
+            this.setChildren(el.children, false)
+          }
+        })
+      }
+    },
+    setChildren(children, type) {
+      // 编辑多个子节点
+      children.map((j) => {
+        this.toggleSelection(j, type)
+        if (j.children) {
+          this.setChildren(j.children, type)
+        }
+      })
+    },
+    toggleSelection(row, select) {
+      if (row) {
+        this.$nextTick(() => {
+          this.$refs.distTable.toggleRowSelection(row, select)
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 167 - 0
chuanyi-admin/src/views/system/role/user-menuSelect.vue

@@ -0,0 +1,167 @@
+<template>
+  <!-- 授权用户 -->
+  <el-dialog title="添加菜单权限" :visible.sync="dialogVisible" width="800px" :close-on-click-modal="false">
+    <el-row class="czBtns">
+      <el-col>
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          :disabled="distribution"
+          @click="handleDel"
+        >
+          批量分配</el-button>
+      </el-col>
+    </el-row>
+    <el-table
+      ref="distTable"
+      v-loading="distLoading"
+      :data="addMenuList"
+      row-key="id"
+      border
+      stripe
+      header-row-class-name="headBackground"
+      @selection-change="handelAddDist"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="菜单名称" prop="menuName" header-align="center" show-overflow-tooltip />
+      <el-table-column label="菜单图标" prop="menuIcon" align="center" show-overflow-tooltip />
+      <el-table-column label="菜单路径" prop="menuUrl" align="center" show-overflow-tooltip />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-circle-plus"
+            size="mini"
+            :disabled="!distribution"
+            @click="addMenu(scope.row.id, $event)"
+          >分配菜单
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-dialog>
+</template>
+
+<script>
+import { getMenuListTree, distributionMenu } from '@/api/system/role'
+// import multipleChoice from '@/mixin/multipleChoice'
+export default {
+  // mixins: [multipleChoice],
+  data() {
+    return {
+      // 弹出框
+      dialogVisible: false,
+      // 弹出框表格加载状态
+      distLoading: true,
+      // 分配菜单参数
+      distObj: {
+        id: this.$route.params.userId,
+        menuList: []
+      },
+      // 禁用分配
+      distribution: true,
+      // 分配菜单表格
+      addMenuList: [],
+      selectFlag: false
+    }
+  },
+  created() {
+
+  },
+  methods: {
+    /** 显示弹框 */
+    show() {
+      this.dialogVisible = true
+      this.getMenuListTree()
+    },
+    /** 所有菜单树信息 */
+    getMenuListTree() {
+      getMenuListTree().then(res => {
+        const data = res.data
+        this.addMenuList = data
+        // this.selectData = this.addMenuList
+        // this.multiple = 'distTable'
+        this.distLoading = false
+      })
+    },
+    /** 分配菜单多选 */
+    handelAddDist(selection) {
+      // console.log(selection);
+      this.distObj.menuList = selection.map(item => { return { id: item.id } })
+      this.distribution = !selection.length
+    },
+    /** 分配按钮 */
+    addMenu(id, event) {
+      this.$resetBtn(event)
+      this.distObj.menuList = []
+      this.$confirm('您确定要分配该菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.distObj.menuList.push({ id })
+        this.distributionMenu()
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 批量分配菜单按钮 */
+    handleDel(event) {
+      this.$resetBtn(event)
+      this.$confirm('您确定要批量分配选中的菜单吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        cancelButtonClass: 'btn_custom_cancel',
+        type: 'warning'
+      }).then(() => {
+        this.distributionMenu()
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消操作'
+        })
+      })
+    },
+    /** 分配菜单请求 */
+    distributionMenu() {
+      distributionMenu(this.distObj).then(res => {
+        if (res.code === 200) {
+          this.$message({
+            type: 'success',
+            message: '分配菜单成功'
+          })
+          this.dialogVisible = false
+          this.$emit('handelUpdate')
+        }
+      })
+    }
+  }
+  // watch: {
+  //   //弹出框表格数据刷新滚动条置顶
+  //   userList: {
+  //     handler () {
+  //       this.$nextTick(() => {
+  //         // 滚动到顶部
+  //         this.$refs.table.bodyWrapper.scrollTop = 0;
+  //       });
+  //     },
+  //     deep: true,
+  //     immediate: true,
+  //   }
+  // }
+}
+</script>
+
+<style lang="scss" scoped>
+.el-dialog {
+    height: 78vh;
+    overflow: auto;
+}
+</style>