treeList.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <div class="treeList">
  3. <div class="title commons-title">
  4. {{ title }}
  5. </div>
  6. <div class="search">
  7. <el-input v-model="search" placeholder="请输入搜索内容" clearable @clear="search = ''" @keyup.enter="searchChange"></el-input>
  8. <!-- <el-button type="primary" @click="searchChange">搜索</el-button> -->
  9. <el-button type="primary" plain @click="add({ id: 0 })">
  10. <el-icon :size="20">
  11. <Plus />
  12. </el-icon>
  13. </el-button>
  14. </div>
  15. <div class="box">
  16. <!-- default-expand-all 默认展开 -->
  17. <el-tree :data="data" ref="tree" node-key="id" @node-click="treeChange" :expand-on-click-node="false" :filter-node-method="filterNode"
  18. :current-node-key="1">
  19. <template #default="{ node, data }">
  20. <div class="custom-tree-node">
  21. <div style="flex: 1">{{ node.label }}</div>
  22. <!-- v-show="activeNode == data.id" -->
  23. <div class="icon-warp" style="float: right; width: 71px; margin-left: 10px" v-if="node.label != '全部'">
  24. <el-icon :size="17" @click.stop="() => edit(node, data)">
  25. <Edit />
  26. </el-icon>
  27. <el-icon :size="17" style="margin-left: 10px" @click.stop="() => add(data)">
  28. <Plus />
  29. </el-icon>
  30. <el-icon :size="17" style="margin-left: 10px" @click.stop="() => del(data)">
  31. <Delete />
  32. </el-icon>
  33. </div>
  34. </div>
  35. </template>
  36. </el-tree>
  37. </div>
  38. <el-dialog :title="treeModalType == 'add' ? '添加分类' : '编辑分类'" v-model="treeModal" width="400" v-loading="loading">
  39. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
  40. </byForm>
  41. <template #footer>
  42. <el-button @click="treeModal = false" size="large">取 消</el-button>
  43. <el-button type="primary" v-no-double-click="submitForm" size="large" :loading="submitLoading">
  44. 确 定
  45. </el-button>
  46. </template>
  47. </el-dialog>
  48. </div>
  49. </template>
  50. <script setup>
  51. import { toRaw } from "vue";
  52. import { ElMessage, ElMessageBox } from "element-plus";
  53. import byForm from "@/components/byForm/index";
  54. const props = defineProps({
  55. title: {
  56. type: String,
  57. default: "分类",
  58. },
  59. submitType: {
  60. type: String,
  61. default: "1", //默认产品
  62. },
  63. data: {
  64. type: Array,
  65. default: [],
  66. },
  67. });
  68. const search = ref("");
  69. const emit = defineEmits(["update:modelValue"]);
  70. const { proxy } = getCurrentInstance();
  71. let activeNode = ref("1");
  72. const treeChange = (e, data) => {
  73. let el = document.getElementsByClassName("el-tree")[0].firstElementChild;
  74. console.log(el);
  75. if (e.id != 1) {
  76. //删除el的is-current class name
  77. el.classList.remove("is-current");
  78. }
  79. activeNode.value = e.id;
  80. if (proxy.type == "radio") {
  81. emit("update:modelValue", e.id);
  82. emit("change", e);
  83. } else {
  84. emit("change", e);
  85. }
  86. };
  87. // const filterNode = (value, data, node) => {
  88. // if (!value) return true;
  89. // return data.label.indexOf(value) !== -1;
  90. // };
  91. const getParents = (node, name, key) => {
  92. if (node.parent && node.parent.data[key]) {
  93. name += node.parent.data[key];
  94. return getParents(node.parent, name, key);
  95. }
  96. return name;
  97. };
  98. // 以下可实现搜索显示子节点
  99. const filterNode = (value, data, node) => {
  100. let names = getParents(node, node.data.label, "label");
  101. let isName = names.indexOf(value) !== -1;
  102. return !value || isName ? true : false;
  103. };
  104. const searchChange = () => {
  105. proxy.$refs.tree.filter(search.value);
  106. };
  107. const byform = ref(null);
  108. const treeListData = ref([]);
  109. let treeModal = ref(false);
  110. let submitLoading = ref(false);
  111. let treeModalType = ref("add");
  112. let currentNode = reactive({
  113. id: "",
  114. });
  115. let formData = reactive({
  116. data: {
  117. name: "",
  118. parentId: "",
  119. definition: props.submitType,
  120. },
  121. });
  122. const formOption = reactive({
  123. inline: true,
  124. labelWidth: 100,
  125. itemWidth: 100,
  126. rules: [],
  127. });
  128. let rules = ref({
  129. name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
  130. });
  131. const formConfig = computed(() => {
  132. return [
  133. {
  134. type: "input",
  135. prop: "name",
  136. label: "分类名称",
  137. required: true,
  138. },
  139. ];
  140. });
  141. const add = (data) => {
  142. treeModal.value = true;
  143. treeModalType.value = "add";
  144. formData.data = {
  145. name: "",
  146. parentId: "",
  147. definition: props.submitType,
  148. };
  149. formData.data.parentId = data.id;
  150. };
  151. const edit = (node, data) => {
  152. treeModal.value = true;
  153. treeModalType.value = "edit";
  154. formData.data = {
  155. name: data.label,
  156. id: data.id,
  157. definition: props.submitType,
  158. };
  159. };
  160. const del = (data) => {
  161. ElMessageBox.confirm("此操作将永久删除该数据, 是否继续?", "提示", {
  162. confirmButtonText: "确定",
  163. cancelButtonText: "取消",
  164. type: "warning",
  165. }).then(() => {
  166. // 删除
  167. proxy
  168. .post("/productClassify/delete", {
  169. id: data.id,
  170. })
  171. .then((res) => {
  172. ElMessage({
  173. message: "删除成功",
  174. type: "success",
  175. });
  176. getTreeList();
  177. });
  178. });
  179. };
  180. const submitForm = () => {
  181. byform.value.handleSubmit((valid) => {
  182. submitLoading.value = true;
  183. proxy.post("/productClassify/" + treeModalType.value, formData.data).then(
  184. (res) => {
  185. ElMessage({
  186. message: treeModalType.value == "add" ? "添加成功" : "编辑成功",
  187. type: "success",
  188. });
  189. getTreeList();
  190. treeModal.value = false;
  191. submitLoading.value = false;
  192. },
  193. (err) => {
  194. submitLoading.value = false;
  195. }
  196. );
  197. });
  198. };
  199. const getTreeList = () => {
  200. emit("changeTreeList");
  201. // proxy
  202. // .post("/productClassify/tree", {
  203. // parentId: "",
  204. // name: "",
  205. // definition: props.submitType,
  206. // })
  207. // .then((message) => {
  208. // treeListData.value = message;
  209. // });
  210. };
  211. // getTreeList();
  212. const handleMouseOver = (data) => {
  213. console.log(data, "sss");
  214. // currentNode.id = toRaw(data).id;
  215. };
  216. //为class为el-tree的第一个子元素添加一个is-current
  217. const addClass = () => {
  218. let el = document.getElementsByClassName("el-tree")[0].firstElementChild;
  219. if (proxy.data.length > 0) {
  220. el.classList.add("is-current");
  221. } else {
  222. setTimeout(() => {
  223. addClass();
  224. }, 300);
  225. }
  226. };
  227. onMounted(() => {
  228. addClass();
  229. });
  230. </script>
  231. <style lang="scss">
  232. .custom-tree-node {
  233. flex: 1;
  234. display: flex;
  235. align-items: center;
  236. justify-content: space-between;
  237. font-size: 14px;
  238. padding-right: 8px;
  239. }
  240. .custom-tree-node:hover {
  241. .icon-warp {
  242. display: block !important;
  243. }
  244. }
  245. .treeList {
  246. display: block;
  247. height: 100%;
  248. background: #fff;
  249. padding: 20px;
  250. height: calc(100vh - 140px);
  251. .search {
  252. margin-bottom: 20px;
  253. .el-input {
  254. width: calc(100% - 70px);
  255. margin-right: 10px;
  256. text-align: center;
  257. }
  258. }
  259. // .searh,.title,.box{
  260. // padding-left:20px ;
  261. // }
  262. .box {
  263. padding-right: 0px;
  264. height: calc(100vh - 270px);
  265. overflow-y: auto;
  266. overflow-x: auto;
  267. .el-tree {
  268. .el-tree-node__content {
  269. width: min-content;
  270. min-width: 260px;
  271. }
  272. .el-tree-node > .el-tree-node__children {
  273. overflow: visible;
  274. }
  275. }
  276. }
  277. }
  278. </style>