IndexPage.vue 4.58 KB
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { cloneDeep, isEmpty } from 'src/common/utils';
import nestedDraggable from './infra/nested.vue';

const data = [
  {
    name: 'task 1',
    show: true,
    tasks: [
      {
        name: 'task 2',
        show: true,
        tasks: [],
      },
    ],
    key: '1',
  },
  {
    name: 'task 3',
    show: true,
    tasks: [
      {
        name: 'task 4',
        show: true,
        tasks: [],
      },
    ],
    key: '2',
  },
  {
    name: 'task 5',
    show: true,
    tasks: [],
    key: '3',
  },
];

const state = reactive({
  list: [] as any[],
  originalData: [] as any[],
});

onMounted(() => {
  state.originalData = cloneDeep(data);

  handleData(data);
  state.list = data;
});

function handleData(data: any, key = 'tasks', before = 0) {
  let index = 0;
  data.map((item: any) => {
    let indexstr;
    if (before) {
      indexstr = before + '-' + String(index);
    } else {
      indexstr = String(index);
    }

    item['test_index'] = indexstr;
    index++;

    if (!isEmpty(item[key])) {
      handleData(item[key], key, item['test_index']);
    } else {
      item[key] = [];
    }
  });
}

function viewData() {
  console.log('查看 >>>>', state.list);
}

function onReset() {
  const data = cloneDeep(state.originalData);
  handleData(data);
  state.list = data;
}

// 拖拽结束
function dragEnd() {
  handleData(state.list);
  console.log('拖拽结束2', state.list);
}

function onAdd() {
  let obj: any = {
    name: null,
    tasks: [],
    key: Date.now(),
  };
  state.list.push(obj);
  handleData(state.list);
}

// 删除
function delItem(data: any) {
  console.log('删除', data);
  data['test_delete'] = true;
  let res = handelDel(state.list);

  handleData(res);
  state.list = res;
}

function handelDel(listdata: any[]) {
  const chiledKey = 'tasks';
  let newArr = [] as any[];
  listdata.map((item) => {
    if (!isEmpty(item[chiledKey])) {
      item[chiledKey] = handelDel(item[chiledKey]);
    }
    if (!item['test_delete']) {
      newArr.push(item);
    }
  });
  return newArr;
}

// 同级添加
function addItem(data: any) {
  console.log('同级添加', data);

  const key = 'tasks';
  const indexList = data['test_index'].split('-');

  let re: any;
  for (let i = 0; i < indexList.length; i++) {
    const item = indexList[i];
    if (i === 0) {
      re = getTarget(state.list, Number(item));
    } else {
      re = getTarget(re.target[key], Number(item));
    }
  }

  let obj: any = {
    name: null,
    show: true,
    key: Date.now(),
  };
  obj[key] = [];

  re.parent.push(obj);
  handleData(state.list);
}

// 子级添加
function addNest(data: any) {
  const key = 'tasks';
  console.log('子级添加', data);
  const indexList = data['test_index'].split('-');

  let re: any;
  for (let i = 0; i < indexList.length; i++) {
    const item = indexList[i];
    if (i === 0) {
      re = getTarget(state.list, Number(item));
    } else {
      re = getTarget(re.target[key], Number(item));
    }
  }

  let obj: any = {
    name: null,
    show: true,
    key: Date.now(),
  };
  obj[key] = [];

  re.target[key].push(obj);
  handleData(state.list);
}

function getTarget(list: any, index: number) {
  const target = list[index];
  const parent = list;
  return { target, parent };
}

function getParamData() {
  //
  let data = cloneDeep(state.list);
  let res = delTestKey(data);
  console.log('原来的格式', res);
}

function delTestKey(listdata: any[], delKey = 'test_index') {
  const chiledKey = 'tasks';
  return listdata.map((item: any) => {
    if (!isEmpty(item[chiledKey])) {
      item[chiledKey] = delTestKey(item[chiledKey], delKey);
    }

    delete item[delKey];
    return item;
  });
}
</script>
<template>
  <div class="box">
    <div class="actions">
      <q-btn color="primary" label="查看" @click="viewData" />
      <q-btn color="primary" label="原来的格式" @click="getParamData" />
      <q-btn color="primary" label="重置" @click="onReset" />
      <q-btn color="primary" label="添加" @click="onAdd" />
    </div>
    <div class="tree-box">
      <nested-draggable
        :tasks="state.list"
        @onEnd="dragEnd"
        @addItem="addItem"
        @addNest="addNest"
        @delItem="delItem"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.actions {
  padding: 10px;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  column-gap: 10px;
}
.tree-box {
  // width: 600px;
  height: 500px;
  box-sizing: border-box;
  // border: 1px solid brown;
  overflow: auto;
  > :nth-child(1) {
    // padding-right: 10px;
  }
}
</style>