杨磊
2025-05-26 96be59a64cc1d8fcaf1034e787717663c68df4a7
src/components/TreeMenu.vue
@@ -1,22 +1,94 @@
<template>
  <div class="tree-menu-box">
    <div class="flex">
      <div class="tree-menu">
      <div class="tree-menu" v-if="$route.name == 'landerModel'">
        <div class="topMenu">
          <span class="topMenu-title">{{ menuName }}</span>
          <div class="btnGroup" v-if="props.menuItem == 'model'">
            <el-icon class="icon1" @click="addBtn"><FolderAdd /></el-icon>
          <div
            class="btnGroup"
            v-if="$route.name == 'landerModel' || $route.name == 'systemUse'"
          >
            <el-dropdown>
              <el-icon class="icon1"><FolderAdd /></el-icon>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="addBtn('parent')"
                    >新建频道</el-dropdown-item
                  >
                  <el-dropdown-item
                    :disabled="selectData ? false : true"
                    @click="addBtn('child')"
                    >新建子频道</el-dropdown-item
                  >
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <el-icon class="icon2" @click="editBtn"><Edit /></el-icon>
            <el-icon class="icon3" @click="delBtn"><Delete /></el-icon>
          </div>
        </div>
        <div v-if="loadTree && $route.name == 'landerModel'">
          <el-tree
            ref="treeRef"
            :key="treeKey"
            :props="defaultProps"
            :highlight-current="true"
            @node-click="handleNodeClick"
            :current-node-key="currentNodeKey"
            node-key="key"
            :data="filteredData"
            :load="loadNode"
            :expand-on-click-node="false"
            lazy
          >
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <el-icon v-if="data.icon"
                  ><component :is="data.icon"
                /></el-icon>
                <span>{{ node.label }}</span>
              </span>
            </template>
          </el-tree>
        </div>
      </div>
      <div class="tree-menu" v-if="$route.name.includes('simulation')">
        <span class="topMenu-title">{{ menuName }}</span>
        <div
          class="btnGroup"
          v-if="$route.name == 'landerModel' || $route.name == 'systemUse'"
        >
          <el-dropdown>
            <el-icon class="icon1"><FolderAdd /></el-icon>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="addBtn('parent')"
                  >新建频道</el-dropdown-item
                >
                <el-dropdown-item
                  :disabled="selectData ? false : true"
                  @click="addBtn('child')"
                  >新建子频道</el-dropdown-item
                >
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <el-icon class="icon2" @click="editBtn"><Edit /></el-icon>
          <el-icon class="icon3" @click="delBtn"><Delete /></el-icon>
        </div>
        <el-tree
          ref="treeRef"
          :data="filteredData"
          :key="treeKey"
          :data="visualSimulationTreeData"
          :props="defaultProps"
          :filter-node-method="filterNode"
          node-key="key"
          :current-node-key="simulationKey"
          :filter-node-method="filterNode1"
          :highlight-current="true"
          default-expand-all
          @node-click="handleNodeClick"
          @node-click="systemClick"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
@@ -26,22 +98,18 @@
          </template>
        </el-tree>
      </div>
      <div class="tree-menu" v-if="props.menuItem == 'systemManage'">
        <div class="topMenu">
          <span class="topMenu-title">{{ systemMenuName }}</span>
          <div class="btnGroup">
            <el-icon class="icon1" @click="addBtn"><FolderAdd /></el-icon>
            <el-icon class="icon2" @click="editBtn"><Edit /></el-icon>
            <el-icon class="icon3" @click="delBtn"><Delete /></el-icon>
          </div>
        </div>
      <div class="tree-menu" v-if="seleStore.curTab == 'systemManage'">
        <el-tree
          ref="treeRef"
          :data="systemData"
          :data="systemManageTreeData"
          :props="defaultProps"
          :key="systemKey"
          :current-node-key="systemKey"
          node-key="key"
          :filter-node-method="filterNode1"
          default-expand-all
          @node-click="systemClick"
          :highlight-current="true"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
@@ -61,7 +129,20 @@
  >
    <el-form :model="form" ref="formRef" :rules="formRules" label-width="140px">
      <el-form-item label="名称" prop="name">
        <el-input v-model="form.name" autocomplete="off" placeholder="请输入" style="width: 240px"/>
        <el-input
          v-model="form.name"
          autocomplete="off"
          placeholder="请输入"
          style="width: 240px"
        />
      </el-form-item>
      <el-form-item label="编码" prop="refCode">
        <el-input
          v-model="form.refCode"
          autocomplete="off"
          placeholder="请输入"
          style="width: 240px"
        />
      </el-form-item>
      <el-form-item label="描述">
        <el-input
@@ -83,22 +164,43 @@
</template>
<script setup lang="ts">
import { ref, reactive, defineProps, onMounted } from "vue";
import { useRouter } from "vue-router";
import type { FormInstance, FormRules} from "element-plus";
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  ref,
  reactive,
  defineProps,
  onMounted,
  inject,
  watch,
  nextTick,
} from "vue";
import { useRoute, useRouter } from "vue-router";
import type { FormInstance, FormRules } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { Document, FolderOpened } from "@element-plus/icons-vue";
import { fa } from "element-plus/es/locale";
const MG: any = inject("MG");
const toolClass: any = inject("toolClass");
import { curStoreInfo } from "@/store/index";
const seleStore = curStoreInfo();
const router = useRouter();
const treeRef = ref();
const loadTree = ref(false);
const treeRef = ref(null);
const curSelectNode = ref();
const props = defineProps<{
  menuItem: string;
  modelTreeData: any;
  storeInfo: any;
}>();
const menuName = ref("模型库");
const filteredData = ref();
const systemMenuName = ref("");
const systemData = ref();
const selectData = ref()
const currentNodeKey = ref(1);
const treeKey = ref(0);
const systemKey = ref(0);
const simulationKey = ref(0);
const systemData = ref([]);
const selectData = ref();
const createParent = ref(false);
interface TreeNode {
  label: string;
  path?: string;
@@ -108,61 +210,39 @@
const defaultProps = {
  children: "children",
  label: "label",
  isLeaf: "leaf",
  key: "key",
};
const modelTreeData = ref<TreeNode[]>([
  {
    label: "型号",
    icon: "FolderOpened",
    children: [
      {
        label: "着陆器模型库",
        path: "/model/landerModel",
        icon: "Document",
      },
      {
        label: "巡视器模型库",
        path: "/model/roverModel",
        icon: "Document",
      },
      {
        label: "飞跃器模型库",
        path: "/model/leapMachineModel",
        icon: "Document",
      },
    ],
  },
]);
const route = useRoute();
const visualSimulationTreeData = ref<TreeNode[]>([
  {
    label: "测试仿真",
    path: "/testSimulation",
    icon: "Document",
    key: 0,
  },
  {
    label: "实时仿真",
    path: "realTimeSimulation",
    icon: "Document",
    key: 1,
  },
  {
    label: "自主功能",
    path: "/autonomousFunction",
    icon: "Document",
    key: 2,
  },
]);
const systemManageTreeData = ref<TreeNode[]>([
  {
    key: 0,
    label: "机构用户",
    path: "/userManage",
    icon: "Document",
  },
  {
    label: "角色权限管理",
    path: "/roleManage",
    icon: "Document",
  },
  { key: 1, label: "角色权限管理", path: "/roleManage", icon: "Document" },
]);
const systemTreeData = ref<TreeNode[]>([
@@ -213,10 +293,11 @@
]);
const dialogFormVisible = ref(false);
const dialogTitle = ref()
const dialogTitle = ref();
const formRef = ref<FormInstance>();
const form = reactive({
  name: "",
  refCode: "",
  description: "",
});
@@ -227,22 +308,151 @@
  name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
});
onMounted(() => {
  console.log(props.menuItem, "123");
  if (props.menuItem == "model") {
    filteredData.value = modelTreeData.value;
    menuName.value = "模型库";
  } else if (props.menuItem == "simulation") {
    menuName.value = "可视化仿真";
    filteredData.value = visualSimulationTreeData.value;
  } else if (props.menuItem == "systemManage") {
    menuName.value = "系统管理";
    filteredData.value = systemManageTreeData.value;
  } else {
    filteredData.value = [];
watch(
  () => route,
  (newRoute) => {
    console.log("路由变化:", newRoute.path);
    // 处理路由变化逻辑
  },
  { deep: true }
);
watch(
  () => seleStore.curTab, // 监听 reactive 对象(默认深度监听)
  (newVal) => {
    if (newVal) {
      if (seleStore.curTab == "model") {
        menuName.value = "模型库";
      } else if (seleStore.curTab == "simulation") {
        menuName.value = "可视化仿真";
        filteredData.value = visualSimulationTreeData.value;
      } else if (seleStore.curTab == "systemManage") {
        menuName.value = "系统管理";
        filteredData.value = systemManageTreeData.value;
      } else {
        filteredData.value = [];
      }
      systemMenuName.value = systemManageTreeData.value[0].label;
    }
  }
  systemMenuName.value = systemManageTreeData.value[0].label;
);
onMounted(() => {
  console.log(route, "route.route");
});
watch(
  () => props.storeInfo, // 监听 reactive 对象(默认深度监听)
  (newVal) => {
    if (newVal) {
      loadTree.value = true;
    }
  }
);
const loadNode = async (node, resolve) => {
  if (node.level == 0) {
    const treeData = await getTableData(0);
    const list = treeData.filter((item) => item.data.refCode !== "testReport");
    const testReport = treeData.find(
      (item) => item.data.refCode === "testReport"
    );
    console.log(list, "list");
    console.log(testReport, "testReport");
    nextTick(() => {
      currentNodeKey.value = 0; // 确保节点已渲染
      seleStore.setChannelInfo(list[0]);
      seleStore.setTestReportChannel(testReport);
      selectData.value = list[0];
    });
    return resolve(list);
  }
  if (node.childNodes.length > 0) {
    return resolve([]);
  }
  // 显示加载状态
  node.loading = true;
  const childNodes = await getTableData(node.data.data);
  resolve(childNodes);
};
//处理树形结构
const handleTreeData = (datas: any[], parent, noTriggerSelect = false) => {
  let parentData = {};
  if (parent) {
    parentData = { ...parent, parent: null };
  } else {
    parentData = null;
  }
  const list = [];
  for (let i = 0; i < datas.length; i++) {
    const data = datas[i];
    const obj = {
      label: data.name,
      key: parentData ? parentData.key + "_" + i : i + "",
      namePath: parentData ? parentData.namePath + "\\" + data.name : data.name,
      icon: data.icon,
      data: data,
      parent: parentData,
      leaf: false,
      children: [],
    };
    if (data["children"] && data["children"].length) {
      obj.leaf = false;
      obj.children = handleTreeData(
        data["children"],
        {
          ...data,
          key: obj.key,
          namePath: obj.namePath,
        },
        i == 0 ? false : true // 如果有子数据处理,只有第一条数据需要展开和回调
      );
    } else {
      obj.leaf =
        !data["childrenChannelCount"] || data["childrenChannelCount"] == 0;
    }
    list.push(obj);
  }
  console.log(list, "list");
  return list;
};
const getTableData = async (path) => {
  const treeData = await toolClass.getCmsItem({
    path: path.idPath
      ? path.idPath
      : props.storeInfo.repositoryData.rootChannel.id,
    storeId: props.storeInfo.storeId,
    repositoryId: props.storeInfo.repositoryId,
    type: "\\",
    sort: {
      LinkOrder: "Asc",
    },
    paging: {
      Start: 0,
      Size: 50,
    },
    filters: {
      "SysType=": ["CmsChannel"],
    },
    fields: {
      ChildrenCount: [],
    },
  });
  if (treeData && treeData.datas.length > 0) {
    const fomartData = handleTreeData(
      treeData.datas,
      path ? path : null,
      false
    );
    seleStore.setChannelInfo(fomartData[0]);
    seleStore.setChannelList(fomartData);
    return fomartData;
  } else {
    return [];
  }
};
const filterNode = (value: string, data: TreeNode) => {
  if (!value) return true;
@@ -255,28 +465,90 @@
};
const handleNodeClick = (data: TreeNode) => {
  console.log(data, 12);
  selectData.value = data
  if (data.path) {
    systemMenuName.value = data.label;
    if (data.path == "/userManage") {
      systemData.value = systemTreeData.value;
    } else if (data.path == "/roleManage") {
      systemData.value = systemTreeData1.value;
    }
    router.push(data.path);
  }
  seleStore.setChannelInfo(data);
  selectData.value = data;
};
//添加目录
const addBtn = () => {
  dialogTitle.value = '添加'
const addBtn = (type) => {
  if (type == "child") {
    dialogTitle.value = "新建子频道";
    createParent.value = false;
  } else {
    dialogTitle.value = "新建频道";
    createParent.value = true;
  }
  dialogFormVisible.value = true;
};
const submitBtn = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      console.log(form.name, "fields");
      if (dialogTitle.value == "编辑") {
        const body = {
          accessPath: selectData.value.data.idPath,
          accessStoreId: selectData.value.data.storeId,
          accessRepositoryId: selectData.value.data.repositoryId,
          accessItemId: selectData.value.data.id,
          name: form.name, // form.name,
          description: form.description,
          refCode: form.refCode,
          state: selectData.value.data.state,
          icon: selectData.value.data.icon,
          type: selectData.value.data.type,
        };
        const updateCmsItem = await MG.dps5.UpdateCmsItem({
          updateList: [body],
        });
        if (updateCmsItem) {
          ElMessage({
            message: "编辑成功",
            type: "success",
          });
          dialogFormVisible.value = false;
          form.name = "";
          form.refCode = "";
          form.description = "";
          treeKey.value += 1;
        }
      } else {
        const body = {
          accessPath: createParent.value
            ? props.storeInfo.repositoryData.rootChannel.id
            : selectData.value.data.idPath,
          accessStoreId: props.storeInfo.storeId,
          accessRepositoryId: props.storeInfo.repositoryId,
          sysType: "CmsChannel",
          linkType: "Link",
          cmsItemRequest: {
            ...form,
            state: "Normal",
            type: "Normal",
            module: "",
            accessType: "Public",
          },
        };
        const newCmsItem = await MG.dps5.NewCmsItem(body);
        if (newCmsItem) {
          ElMessage({
            message: "添加成功",
            type: "success",
          });
          dialogFormVisible.value = false;
          form.name = "";
          form.refCode = "";
          form.description = "";
          treeKey.value += 1;
        } else {
          ElMessage({
            message: "添加失败",
            type: "error",
          });
        }
      }
    }
  });
};
@@ -286,33 +558,71 @@
  dialogFormVisible.value = false;
};
const editBtn =() =>{
  dialogTitle.value = '编辑'
  form.name = selectData.value.label
const editBtn = () => {
  dialogTitle.value = "编辑";
  form.name = selectData.value.label;
  form.refCode = selectData.value.data.refCode;
  form.description = selectData.value.data.description;
  dialogFormVisible.value = true;
};
}
const delBtn =()=>{
  ElMessageBox.confirm(
    '确定要删除选中的数据?',
    'Warning',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
const delBtn = () => {
  if (selectData.value.data.childrenCmsItemCount > 0) {
    ElMessage({
      message: "频道下还有其他资源,请先删除资源后重试!",
      type: "warning",
    });
    return false;
  }
  if (selectData.value.data.childrenChannelCount > 0) {
    ElMessage({
      message: "频道下还有子频道,请先删除子频道后重试!",
      type: "warning",
    });
    return false;
  }
  ElMessageBox.confirm("确定要删除选中的数据?", "删除频道", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      console.log()
      console.log(selectData.value, "selectData.value");
      let accessPath = "";
      let accessItemId = 0;
      if (!selectData.value.parent) {
        accessPath = props.storeInfo.repositoryData.rootChannel.id + "";
        accessItemId = props.storeInfo.repositoryData.rootChannel.id;
      } else {
        accessPath = selectData.value.parent.data.idPath;
        accessItemId = selectData.value.parent.data.id;
      }
      MG.dps5
        .DelCmsItemByList({
          accessPath,
          accessStoreId: selectData.value.data.storeId,
          accessRepositoryId: selectData.value.data.repositoryId,
          accessItemId,
          itemIds: [selectData.value.data.id],
        })
        .then((res) => {
          ElMessage({
            message: "删除成功",
            type: "success",
          });
          treeKey.value += 1;
        });
    })
    .catch(() => {
    })
}
    .catch(() => {});
};
const systemClick = (data: TreeNode) => {};
const systemClick = (data: TreeNode) => {
  curSelectNode.value = data;
  router.push({
    path: "/systemManage" + data.path,
  });
  console.log(curSelectNode.value, "curSelectNode");
};
</script>
<style lang="less" scoped>