vue2+el-tree之3.0 添加编辑都可以!!

文章详细描述了一个Vue组件,用于角色权限管理的编辑页面,包含角色码输入、级联菜单选择(Cascader)以及数据的回显、保存和验证功能。组件通过API与后端交互,支持角色权限的添加和编辑操作。
摘要由CSDN通过智能技术生成
<template>
  <el-dialog
    :title="title"
    :visible.sync="dialogFormVisible"
    width="800px"
    @close="close"
  >
    <el-form ref="form" label-width="80px" :model="form" :rules="rules">
      <el-form-item label="角色码" prop="name">
        <el-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="菜单">
        <div class="vab-tree-border">
          <el-cascader
           ref="cascader"
            v-model="selectedList"
            collapse-tags
            :disabled="form.id === 1 ? true : false"
            :options="list"
            :props="{
              multiple: true,
              value: 'id',
              label: 'name',
              children: 'children',
              emitPath: false,
            }"
            size="medium"
            :style="{ width: '100%' }"
            @change="change"
          />
        </div>
      </el-form-item>
      <!-- <el-form-item label="按钮权限">
				<el-checkbox-group v-model="form.btnRolesCheckedList">
					<el-checkbox v-for="item in btnRoles" :key="item.value" :label="item.value">
						{{ item.lable }}
					</el-checkbox>
				</el-checkbox-group>
			</el-form-item> -->
    </el-form>
    <template #footer>
      <el-button @click="close">取 消</el-button>
      <el-button type="primary" @click="save">确 定</el-button>
    </template>
  </el-dialog>
</template>

<script>
  import { doEdit, getListMenus, getAllList, doAdd } from '@/api/roleManagement'
  // import {
  //   getList
  // } from '@/api/router'
  import { translateDataToTree, translateTreeToData } from '@/utils/index'

  export default {
    name: 'RoleManagementEdit',
    data() {
      return {
        form: {
          btnRolesCheckedList: [],
        },
        rules: {
          name: [
            {
              required: true,
              trigger: 'blur',
              message: '请输入角色码',
            },
          ],
        },
        title: '', //添加/编辑
        dialogFormVisible: false, //弹窗显示
        list: [], //返回数据-shuixngjiegou
        allListTest:[],
        defaultCheckedKeys: [], //回显选中状态
        // 存放选中的数据
        selectedList: [],
        /* btnRoles demo */
        btnRoles: [
          {
            lable: '读',
            value: 'read:system',
          },
          {
            lable: '写',
            value: 'write:system',
          },
          {
            lable: '删',
            value: 'delete:system',
          },
        ],
      }
    },
    watch: {},
    created() {
      this.getAll()
    },
    methods: {
      //父组件调用获取数据
      showEdit(row) {
        if (!row) {
          this.title = '添加'
          this.form = Object.assign({}, row)
          this.fetchData()
        } else {
          this.title = '编辑'
          this.form = Object.assign({}, row)
          this.fetchData()
        }
        this.dialogFormVisible = true
      },
      close() {
        this.selectedList = []
        this.$refs['form'].resetFields() //重置表单
        this.form = this.$options.data().form
        this.dialogFormVisible = false
      },
      //获取数据
      fetchData() {
        if (this.form.id == undefined) {
          this.form.id = ''
        }
        const params = 'id=' + this.form.id
        getListMenus(params).then((res) => {
          // this.list = res
          if (this.title == '添加') {
            // this.test()
          } else {
            //编辑-选中数据回显
            this.defaultCheckedKeys = []
            res.forEach((item) => {
              if (item.checked == true) {
                this.defaultCheckedKeys.push(item)
              }
            })
            // this.selectedList =[1,6,2,7,8,9,3,10]//级联需要数据结构
            console.log('再次打开', this.defaultCheckedKeys)
            this.test(this.defaultCheckedKeys)
          }
        })
      },
      getAll() {
        getAllList().then((res) => {
          this.list = translateDataToTree(res) //all菜单转树形结构
          this.allListTest=res
          console.log('allListTest',this.allListTest) //ok
        })
      },
      test(val) {
        //编辑
        if (val) {
          if (this.form.id === 1) {
            //超级管理员默认选中全部菜单
            // const uniqueArray = this.getIdsFromTree(this.list) //二维id数组
            this.selectedList = uniqueArray.flat()
            // console.log('test1',this.selectedList)
          } else {
            // let aa = translateDataToTree(this.defaultCheckedKeys) //选中部分
            // const uniqueArray = this.getIdsFromTree(aa) //二维id数组
            // this.selectedList = [...new Set(uniqueArray.flat())]
            let obj=this.uniqueIdsAndPids(this.defaultCheckedKeys)
            // let idArr =this.defaultCheckedKeys.map(({ id }) => id)//子id-ok
            // let parentIDArr =this.defaultCheckedKeys.map(({ parent_id }) => parent_id)//传父id-ok
            // const foundObjects = [... new Set([...idArr,...parentIDArr].filter(item => item !== 0))]
            // this.selectedList =foundObjects//对父级操作不成功
            this.selectedList =obj//ok
            console.log('foundObjects',obj); // 输出找到的id
          }
        }
      },
      uniqueIdsAndPids(keys) {
        const seenPids = new Set(); // 使用Set来存储已经出现过的parent_id
         const resultArray = []; // 结果数组
         for (const key of keys) {
           // 检查parent_id是否为0,如果是,则不处理
           if (key.parent_id === 0) continue;
           // 检查parent_id是否已经出现过
           if (!seenPids.has(key.parent_id)) {
             // 如果parent_id是第一次出现,则添加当前对象的parent_id到结果数组
             resultArray.push(key.parent_id);
             // 将这个parent_id标记为已出现过
             seenPids.add(key.parent_id);
             // seenIds.add(key.id);
           }
           resultArray.push(key.id);
         }
         return resultArray;
      },
      change(v){
             let changeList=this.findMatchingObjects(v, this.allListTest);
             this.form.menu_ids =this.uniqueIdsAndPids(changeList)
             // console.log(v,changeList,this.uniqueIdsAndPids(changeList));

      },
      //根据选中节点找到非树形结构总菜单所在对象
     findMatchingObjects(numbers, objects) {
       // 创建一个新数组来存储匹配的对象
       const matchingObjects = [];
       // 遍历数字数组
       numbers.forEach(number => {
         // 遍历对象数组以找到匹配的id
         objects.forEach(obj => {
           if (number === obj.id) {
             // 如果找到匹配的id,将其添加到匹配对象数组中
             matchingObjects.push(obj);
           }
         });
       });
       return matchingObjects;
     },
      //修改
      save() {
        this.$refs['form'].validate(async (valid) => {
          if (valid && this.selectedList.length !== 0) {
            if (this.title == '编辑') {
              const params = this.form.id
              // 使用 Set 去除重复的元素,并将结果转换为一维数组
              // const uniqueArray = [...new Set(this.selectedList.flat())]
              // 使用 Set 去除重复的元素,并且去掉等于0的值
              // this.form.menu_ids =[...new Set([...this.selectedList, ...parentIDArrSave].filter(item => item !== 0))]
              // console.log('params',params,this.form.menu_ids,this.selectedList); //ok2
              doEdit(params, this.form).then((res) => {
                this.$baseMessage('编辑成功', 'success')
                this.defaultCheckedKeys = translateTreeToData(
                  this.defaultCheckedKeys
                )
                this.title = '编辑'
                this.$emit('fetch-data')
              })
            }
            if (this.title == '添加') {
              this.form.menu_ids = this.selectedList.flat()
              doAdd(this.form).then((res) => {
                this.$baseMessage(res.message, 'success')
                this.title = '添加'
                this.$emit('fetch-data')
              })
            }
            this.close()
          }
        })
      },
      // 递归函数,用于获取树形结构二维id数组
      getIdsFromTree(array) {
        function traverse(node) {
          // 确保 node 对象存在 id 属性
          const ids = node.id !== undefined ? [node.id] : []
          // 检查 children 属性是否存在,并且是否为数组
          if (node.children && Array.isArray(node.children)) {
            // 递归遍历子节点,并将结果与当前节点的 id 合并
            node.children.forEach((child) => {
              // 递归调用 traverse 并解构返回值
              const [childId, ...childIds] = traverse(child)
              // 将子节点的 id 添加到当前节点的 ids 数组中
              ids.push(childId, ...childIds)
            })
          }
          // 返回当前节点的 ids 数组
          console.log('ids',ids)
          // return ids
        }
        // 遍历树的根节点,并对每个节点调用 traverse 函数
        return array.map((root) => traverse(root))
      },
      getCheckedNodes  (checkedNodes)  {
         // 根据 value 来找到对应的节点
               // 这里需要根据您的 options 数据结构来实现
               const checkedNodesList = this.list.reduce((acc, option) => {
                 // 这里需要递归地构建 checkedNodesList
                 // 以下代码仅为示例,您需要根据实际情况进行调整
                 if (value.includes(option.id)) {
                   acc.push({ ...option, children: [] }); // 假设 option 是一个对象,并且有 value 属性
                   if (option.children) {
                     option.children.forEach(child => {
                       if (value.includes(child.id)) {
                         acc.push({ ...child, children: [] });
                       }
                     });
                   }
                 }
                 return acc;
               }, []);
               return checkedNodesList;
             },
    }
  }
</script>

<style lang="scss" scoped>
  .vab-tree-border {
    // height: 200px;
    height: auto;
    // padding: $base-padding;
    // overflow-y: auto;
    // border: 1px solid #dcdfe6;
    border-radius: $base-border-radius;
  }
</style>

父组件--就是看下调用,和级联没有关系

<template>
  <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>
      </vab-query-form-left-panel>
      <vab-query-form-right-panel :span="12">
        <el-form :inline="true" :model="queryForm" @submit.native.prevent>
          <el-form-item>
            <el-input v-model.trim="queryForm.name" clearable placeholder="请输入角色" />
          </el-form-item>
          <el-form-item>
            <el-button icon="el-icon-search" type="primary" @click="queryData">
              查询
            </el-button>
          </el-form-item>
        </el-form>
      </vab-query-form-right-panel>
    </vab-query-form>

    <el-table v-loading="listLoading" border :data="list" @selection-change="setSelectRows">
      <el-table-column align="center" show-overflow-tooltip type="selection" />
      <el-table-column align="center" label="序号" width="55">
        <template #default="{ $index }">
          {{ $index + 1 }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="id" prop="id" show-overflow-tooltip width="40px"/>
      <el-table-column align="center" label="角色码" prop="name" show-overflow-tooltip />
      <!-- <el-table-column align="center" label="按钮权限" show-overflow-tooltip>
        <template #default="{ row }">
          <el-tag v-for="(item, index) in row.btnRolesCheckedList" :key="index">
            {{
              {
                'read:system': '读',
                'write:system': '写',
                'delete:system': '删',
              }[item]
            }}
          </el-tag>
        </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>
        </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.page" :layout="layout" :page-size="queryForm.perPage"
      :total="total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
    <edit ref="edit" @fetch-data="fetchData" />
  </div>
</template>

<script>
  import {
    doDelete,
    getList,
    getAllList
  } from '@/api/roleManagement'
  import Edit from './components/RoleManagementEdit'

  export default {
    name: 'RoleManagement',
    components: {
      Edit
    },
    data() {
      return {
        list: [],
        listLoading: true,
        layout: 'total, sizes, prev, pager, next, jumper',
        total: 0,
        selectRows: '',
        queryForm: {
          page: 1,
          perPage: 10,
          name: '',
        },
      }
    },
    created() {
      this.fetchData()
    },
    methods: {
      setSelectRows(val) {
        this.selectRows = val
      },
      handleEdit(row) {
        if (row.id) {
          this.$refs['edit'].showEdit(row)
        } else {
          this.$refs['edit'].showEdit()
        }
      },
      handleDelete(row) {
        if (row.id) {
          this.$baseConfirm('你确定要删除当前项吗', null, async () => {
            const {
            	message
            } = await doDelete({
            	ids: row.id
            })
            // await doDelete({
            //   ids: row.id
            // }).then(() => {
            //   this.fetchData()
            // })
            this.$baseMessage(message, 'success', 'vab-hey-message-success')
            await this.fetchData()
          })
        } else {
          if (this.selectRows.length > 0) {
            const ids = this.selectRows.map((item) => item.id).join()
            // const ids = this.selectRows.map((item) => item.id).toString()
            // console.log( {
            //     ids: ids
            //   })
            // doDelete({
            // 	ids
            // }).then(() => {
            // 	this.fetchData()
            // })
            this.$baseConfirm('你确定要删除选中项吗', null, async() => {
              const {
                message
              } = await doDelete({
                ids
              })
              //  doDelete({
              //   ids: ids
              // })
              // .then(() => {
              //   // this.fetchData()
              //    this.$message.success('删除成功');
              // })
              this.$baseMessage(message, 'success', 'vab-hey-message-success')
              await this.fetchData()
            })
          } else {
            this.$baseMessage('未选中任何行', 'error', 'vab-hey-message-error')
          }
        }
      },
      handleSizeChange(val) {
        this.queryForm.perPage = val
        this.fetchData()
      },
      handleCurrentChange(val) {
        this.queryForm.page = val
        this.fetchData()
      },
      queryData() {
        this.queryForm.page = 1
        this.fetchData()
      },
      async fetchData() {
        this.listLoading = true
        let params = "page=" + this.queryForm.page + "&perPage=" + this.queryForm.perPage
        const {
          // data: { list, total },
          data,
          meta
        } = await getList(params)
        this.list = data
        this.total = meta.pagination.total
        this.listLoading = false
      },
      // fetchData(){
      // 	this.listLoading = true
      // 	 let params ="page=" + this.queryForm.page+ "&perPage=" + this.queryForm.perPage
      // 	 getList(params).then((res)=>{
      // 		  this.list = res
      // 			this.total = meta.pagination.total
      // 			    this.listLoading = false
      // 	 })
      // }
    },
  }
</script>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值