index.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <template>
  2. <el-container class="is-vertical">
  3. <sc-page-header @add="table_add()"></sc-page-header>
  4. <el-container class="menu-container">
  5. <el-aside width="310px">
  6. <el-header>
  7. <el-input v-model="filterText" clearable placeholder="输入关键字进行过滤"></el-input>
  8. </el-header>
  9. <el-main class="nopadding">
  10. <el-scrollbar>
  11. <el-tree ref="treeRef" node-key="id" :data="menuTree" :current-node-key="currentId" highlight-current :expand-on-click-node="false" check-strictly :filter-node-method="filterNode" @node-click="data => nodeClick(data)">
  12. <template #default="{ data }">
  13. <span :id="data.id" :title="data.title" class="custom-tree-node">
  14. <vxe-text-ellipsis :content="data.title"></vxe-text-ellipsis>
  15. <el-button-group class="do">
  16. <el-button icon="el-icon-plus" size="small" @click.stop="table_add(data)"></el-button>
  17. <el-button icon="el-icon-delete" size="small" @click.stop="table_del(data)"></el-button>
  18. </el-button-group>
  19. </span>
  20. </template>
  21. </el-tree>
  22. </el-scrollbar>
  23. </el-main>
  24. </el-aside>
  25. <el-main class="nopadding">
  26. <template v-if="!dialog">
  27. <el-empty class="do" description="请选择左侧菜单/按钮后操作" :image-size="100"></el-empty>
  28. <el-empty class="media-do" description="请选择上侧菜单/按钮后操作" :image-size="100"></el-empty>
  29. </template>
  30. <menu-form v-else ref="menuFormRef" :menuTree="menuTree" @success="menuSuccess"></menu-form>
  31. </el-main>
  32. </el-container>
  33. </el-container>
  34. </template>
  35. <script setup>
  36. import XEUtils from "xe-utils";
  37. import API from "@/api";
  38. import menuForm from "./detail";
  39. const filterText = ref("");
  40. const menuTree = ref([]);
  41. const currentId = ref(null);
  42. const treeRef = ref();
  43. watch(() => filterText.value, value => treeRef.value.filter(value));
  44. const filterNode = (value, data) => {
  45. if (!value) return true;
  46. return data.title.includes(value);
  47. }
  48. const dialog = ref(false);
  49. const menuFormRef = ref();
  50. const nodeClick = data => {
  51. currentId.value = data.id;
  52. dialog.value = true;
  53. nextTick(() => menuFormRef.value?.setData(data, "edit"));
  54. }
  55. const table_add = (data = {}) => {
  56. dialog.value = true;
  57. nextTick(() => menuFormRef.value?.setData(data));
  58. }
  59. const table_del = ({ id }) => {
  60. ElMessageBox.confirm("是否确认删除该菜单?", "删除警告", {
  61. type: "warning",
  62. confirmButtonText: "确定",
  63. cancelButtonText: "取消"
  64. }).then(() => {
  65. API.system.menu.del({ id }).then(() => {
  66. ElMessage.success("操作成功");
  67. if (currentId.value == id) {
  68. currentId.value = null;
  69. dialog.value = false;
  70. }
  71. fetchMenu();
  72. });
  73. }).catch(() => {});
  74. }
  75. const menuSuccess = id => {
  76. currentId.value = id;
  77. fetchMenu();
  78. }
  79. const fetchMenu = () => API.system.menu.get({ orderBy: "menuSort_asc" }).then(res => {
  80. menuTree.value = XEUtils.toArrayTree(res, { parentKey: "pid" });
  81. currentId.value && document.querySelector(".el-tree-node.is-current")?.scrollIntoView({ block: "center" });
  82. }).catch(() => menuTree.value = []);
  83. fetchMenu();
  84. </script>
  85. <style lang="scss" scoped>
  86. .menu-container {border-top: 1px solid var(--el-border-color-light);}
  87. .menu-container .el-aside {display: flex;flex-direction: column;}
  88. .menu-container .el-aside .el-main {padding-top: 15px;padding-left: 15px;}
  89. .menu-container .el-tree .custom-tree-node .do {display: none;}
  90. .menu-container .el-tree :deep(.el-tree-node__content):hover .do {display: flex;}
  91. .menu-container .media-do {display: none;}
  92. @media (max-width: 992px) {
  93. .aminui-main > .el-container > .el-container.menu-container {display: block;margin-top: 0;border: none;}
  94. .menu-container .el-aside {width: 100%;}
  95. .menu-container .el-aside .el-main {padding-bottom: 15px;}
  96. .menu-container .el-aside + .el-main {margin-top: 15px;}
  97. .menu-container .media-do {display: flex;}
  98. .menu-container .do {display: none;}
  99. }
  100. </style>