美文网首页
vue3 tree树形穿梭框(封装组件)

vue3 tree树形穿梭框(封装组件)

作者: web30 | 来源:发表于2023-06-26 20:17 被阅读0次
效果图
代码
  • 子组件
// 封装组件
<template>
  <div class="treeTransfer">
    <!-- 左边 -->
    <div class="leftTree">
      <div class="list">
        <div class="left_lowline">
          <p class="left_title">用户列表</p>
        </div>
        <!-- 搜索 -->
        <div class="left_input">
          <el-input
            v-model="leftSearch"
            class="w-50 m-2"
            placeholder="搜索"
            clearable
            :prefix-icon="Search"
          />
        </div>
        <el-tree
          ref="treeRef"
          :data="props.fromData"
          show-checkbox
          :node-key="props.nodeKey"
          highlight-current
          :props="props.defaultProps"
          v-slot="{ node, data }"
        >
          <div>
            {{ data.corgName }} // 父节点
          </div>
          <div>
            {{ data.userName }}  // 子节点
          </div>
        </el-tree>
      </div>
    </div>
    <!-- 中间按钮 -->
    <div class="btnDiv">
      <div class="mg10" @click="toRight()">
        <el-button :icon="Right" circle />
      </div>
      <div class="mg10" @click="toLeft()">
        <el-button :icon="Back" circle />
      </div>
    </div>
    <!-- 右边 -->
    <div class="rightTree">
      <div class="list">
        <div class="left_lowline">
          <p class="left_title">已选列表</p>
        </div>
        <!-- 搜索 -->
        <div class="left_input">
          <el-input
            v-model="rightSearch"
            class="w-50 m-2"
            placeholder="搜索"
            clearable
            :prefix-icon="Search"
          />
        </div>

        <div
          class="right_item"
          :class="['item', { active: item.active }]"
          v-for="(item, index) in toData"
          :key="index"
          @click="checkNode(item)"
        >
          {{ item[props.defaultProps.label] }}
          <!-- 下拉框 -->
          <div>
            <el-select
              v-model="item.priority"
              class="m-2"
              placeholder="请选择"
              style="width: 100px"
            >
              <el-option
                v-for="item2 in options"
                :key="item2.value"
                :label="item2.label"
                :value="item2.value"
              />
            </el-select>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
//@ts-nocheck    解决ts类型报红
import { ref, onMounted } from 'vue';
import { Search } from '@element-plus/icons-vue';
import { useMainStore } from '@/store/index';
import { Right, Back } from '@element-plus/icons-vue';

const mainStore = useMainStore();
const props = defineProps(['nodeKey', 'fromData', 'toData', 'defaultProps']);

const leftSearch = ref('');
const rightSearch = ref('');
const options = [
  {
    value: '3',
    label: '高',
  },
  {
    value: '2',
    label: '中',
  },
  {
    value: '1',
    label: '低',
  },
];

// 定义emit
const emit = defineEmits(['checkVal']);
const treeRef = ref();

// 右侧数据
const toData = ref([]);

onMounted(() => {
  if (props.toData.length > 0) {
    toData.value = treeRef.value.getCheckedNodes(false, false);
    treeRef.value.setCheckedKeys([], false);
  }
});

// 去右边
const toRight = () => {
  const checkNodes = treeRef.value.getCheckedNodes(false, false);

  const newArr = toData.value.concat(checkNodes);
  let obj = {};
  let peon = newArr.reduce((cur, next) => {
    obj[next[props.nodeKey]]
      ? ''
      : (obj[next[props.nodeKey]] = true && cur.push(next));
    return cur;
  }, []); // 设置cur默认类型为数组,并且初始值为空的数组

  toData.value = peon;
  treeRef.value.setCheckedKeys([], false);
  checkVal();

  props.fromData.forEach((item: any) => {
    item.children.forEach((left: any) => {
      toData.value.forEach((right) => {
        if (left.userId == right.userId) {  // 已选的不可重复勾选
          left.disabled = true;
        }
      });
    });
  });
};
// 去左边
const toLeft = () => {
  for (var i = 0; i < toData.value.length; i++) {
    if (toData.value[i].active) {
      toData.value[i].active = false;
      toData.value.splice(i, 1);
      i -= 1;
    }
  }
  checkVal();

  props.fromData.forEach((item: any) => {
    item.children.forEach((left: any) => {
      left.disabled = false;
      toData.value.forEach((right) => {
        if (left.userId == right.userId) {
          left.disabled = true;
        }
      });
    });
  });
};
// 右侧item点击
const checkNode = (item: any) => {
  item.active = !item.active;
};
// 返回父组件
const checkVal = () => {
  emit('checkVal', toData.value);
};
</script>
  • 父组件
<div>
   <p class="select_meb">选择固定成员:</p>
            <div class="shuttle_frame">
              <tree-transfer
                ref="treeTransferRef"
                node-key="userId"
                :fromData="fromData"
                :toData="toData"
                :defaultProps="transferProps"
                @checkVal="checkVal"
              >
              </tree-transfer>
            </div>
            <!-- 底部按钮 -->
            <div class="modfiy_but">
              <el-button @click="saveModfiyManageMeb" type="primary"
                >确认</el-button
              >
              <el-button @click="cancelModfiyManage">取消</el-button>
            </div>
</div>
import { ref, onMounted } from 'vue';

let treeTransferRef = ref(); // 树形穿梭框
let fromData = ref([]); // 树形数据
let toData = ref([]); // 选中的ids数据
const transferProps = ref({
  label: 'userName',
  children: 'children',
  disabled: 'disabled',
});

// 子组件树形穿梭框返回
const checkVal = (val: any) => {
  toData.value = val;
};

// 获取左侧用户列表
async function getUserList() {
  let params = {
    userId: '',
  };
  const res = await getCompanyListById(params);
  if (res.code == 200) {
    if (res.data.result == 1) {
      fromData.value = res.data.returnMsg;
      // 根据返回数据处理.....
    } else {
      ElMessage.error(res.message);
    }
  }
}

********************************************************************
// 后端要求传参格式
[{"userId":"28586","priority":"2"},{"userId":"28588","priority":"3"}]

// 确认
function saveModfiyManageMeb() {
  let rightList: any[] = [];
  toData.value.forEach((element) => {
    let param = { userId: '', priority: '' }; 
    param.userId = element.userId;
    param.priority = element.priority;
    rightList.push(param);
  });
  var existUserStr = JSON.stringify(rightList);
  let params = {
    groupId: '',
    userDataStr: existUserStr,
  };
  saveAndModifyUserOfGroup(params).then((res) => {
    if (res.code == 200) {
      ElMessage.success('修改成功');
    } else {
      ElMessage.error(res.message);
    }
  });
}

参考了一位大佬的,当时忘记复制链接了。

相关文章

网友评论

      本文标题:vue3 tree树形穿梭框(封装组件)

      本文链接:https://www.haomeiwen.com/subject/axowydtx.html