treeList.vue 7.5 KB

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