UNPKG

song-ui-u

Version:

vue3 + js的PC前端组件库

1 lines 10.9 kB
{"version":3,"file":"index.vue.cjs","sources":["../../../../../packages/components/vTree/src/index.vue"],"sourcesContent":["<script setup>\r\nimport { ref, computed } from \"vue\";\r\nimport { useNamespace } from \"@ui-library/hook\";\r\nimport { XIcon, XCheckbox, XRadio } from \"@ui-library/components\";\r\nimport { PlusSquare, MinusSquare } from \"song-ui-pro-icon\";\r\n\r\nconst ns = useNamespace(\"vtree\");\r\n\r\ndefineOptions({\r\n name: \"x-vtree\",\r\n});\r\n\r\nconst props = defineProps({\r\n data: {\r\n type: Array,\r\n required: true,\r\n default: () => [],\r\n },\r\n selectionMode: {\r\n type: String,\r\n default: \"single\",\r\n validator: (value) => [\"single\", \"multiple\"].includes(value),\r\n },\r\n\r\n // label\r\n label: {\r\n type: String,\r\n default: \"label\",\r\n },\r\n // value\r\n // value: {\r\n // type: String,\r\n // default: \"id\",\r\n // },\r\n});\r\n\r\nconst emits = defineEmits([\"change\", \"expand\", \"collapse\"]);\r\n\r\nconst islabel = computed(() => props.label);\r\n// const isvalue = computed(() => props.value);\r\n\r\nconst container = ref(null);\r\nconst scrollTop = ref(0);\r\nconst itemHeight = 30;\r\nconst visibleCount = 10;\r\n\r\n// 扁平化树结构\r\nconst flatTree = computed(() => {\r\n const result = [];\r\n function traverse(node, depth = 0) {\r\n if (!node) return;\r\n\r\n // 确保节点有 expanded 属性\r\n if (node.expanded === undefined) {\r\n node.expanded = false;\r\n }\r\n\r\n node.depth = depth;\r\n result.push(node);\r\n\r\n if (node.children && node.expanded) {\r\n node.children.forEach((child) => traverse(child, depth + 1));\r\n }\r\n }\r\n\r\n props.data.forEach((node) => traverse(node));\r\n return result;\r\n});\r\n\r\nconst totalHeight = computed(() => flatTree.value.length * itemHeight);\r\n\r\nconst visibleNodes = computed(() => {\r\n // 根据滚动位置计算起始索引:\r\n // scrollTop.value 是当前滚动的像素值\r\n // itemHeight 是每个节点的高度(30px)\r\n // 除法结果向下取整,得到应该从第几个节点开始显示\r\n const start = Math.floor(scrollTop.value / itemHeight);\r\n\r\n // 计算结束索引:\r\n // start + visibleCount 是理论上需要显示的节点数量\r\n // 使用 Math.min 确保不会超出实际节点总数\r\n const end = Math.min(start + visibleCount, flatTree.value.length);\r\n\r\n // 从扁平化的树结构中截取需要显示的部分\r\n\r\n return flatTree.value.slice(start, end);\r\n});\r\n\r\nconst getNodeStyle = (index) => ({\r\n position: \"absolute\",\r\n top: `${scrollTop.value + index * itemHeight}px`,\r\n});\r\n\r\nconst handleScroll = () => {\r\n if (container.value) {\r\n scrollTop.value = container.value.scrollTop;\r\n }\r\n};\r\n\r\nconst selectedNodes = ref([]); // 对于多选\r\nconst selectedNode = ref(null); // 对于单选\r\n\r\nconst toggleNode = (node) => {\r\n if (props.selectionMode === \"single\") {\r\n selectedNode.value = node.id; // 选中\r\n emits(\"change\", selectedNode.value);\r\n } else if (props.selectionMode === \"multiple\") {\r\n const index = selectedNodes.value.indexOf(node.id);\r\n if (index > -1) {\r\n selectedNodes.value.splice(index, 1); // 取消选中\r\n if (node.children && node.expanded) {\r\n deselectChildren(node.children); // 取消选中子节点\r\n }\r\n } else {\r\n selectedNodes.value.push(node.id); // 选中\r\n if (node.children && node.expanded) {\r\n selectChildren(node.children); // 选中子节点\r\n }\r\n }\r\n emits(\"change\", selectedNodes.value);\r\n }\r\n};\r\n\r\nconst selectChildren = (children) => {\r\n children.forEach((child) => {\r\n if (!selectedNodes.value.includes(child.id)) {\r\n selectedNodes.value.push(child.id);\r\n }\r\n if (child.children && child.expanded) {\r\n selectChildren(child.children);\r\n }\r\n });\r\n};\r\n\r\nconst deselectChildren = (children) => {\r\n children.forEach((child) => {\r\n const index = selectedNodes.value.indexOf(child.id);\r\n if (index > -1) {\r\n selectedNodes.value.splice(index, 1);\r\n }\r\n if (child.children && child.expanded) {\r\n deselectChildren(child.children);\r\n }\r\n });\r\n};\r\n\r\nconst isSelected = (node) => {\r\n if (props.selectionMode === \"single\") {\r\n return selectedNode.value === node.id;\r\n } else if (props.selectionMode === \"multiple\") {\r\n return selectedNodes.value.includes(node.id);\r\n }\r\n return false;\r\n};\r\n\r\nconst toggleExpand = (node) => {\r\n if (!node.children) return;\r\n\r\n if (node.expanded) {\r\n emits(\"collapse\", node);\r\n } else {\r\n emits(\"expand\", node);\r\n }\r\n\r\n node.expanded = !node.expanded;\r\n};\r\n</script>\r\n\r\n<template>\r\n <div :class=\"ns.b()\" @scroll=\"handleScroll\" ref=\"container\">\r\n <div :style=\"{ height: totalHeight + 'px' }\" :class=\"ns.e('spacer')\"></div>\r\n <div\r\n v-for=\"(node, index) in visibleNodes\"\r\n :key=\"node.id\"\r\n :style=\"getNodeStyle(index)\"\r\n :class=\"[ns.e('node'), ns.is('selected', isSelected(node))]\"\r\n @click.stop=\"toggleNode(node)\"\r\n >\r\n <span\r\n :class=\"ns.e('node-inner')\"\r\n :style=\"{ paddingLeft: `${node.depth * 20}px` }\"\r\n >\r\n <span\r\n v-if=\"node.children\"\r\n :class=\"ns.e('expand-icon')\"\r\n @click.stop=\"toggleExpand(node)\"\r\n >\r\n <XIcon v-if=\"node.expanded\" color=\"#abb1bf\">\r\n <MinusSquare />\r\n </XIcon>\r\n <XIcon v-else color=\"#abb1bf\">\r\n <PlusSquare />\r\n </XIcon>\r\n </span>\r\n <XCheckbox\r\n size=\"small\"\r\n v-if=\"props.selectionMode === 'multiple'\"\r\n :checked=\"isSelected(node)\"\r\n @click.stop=\"toggleNode(node)\"\r\n >\r\n {{ node[islabel] }}\r\n </XCheckbox>\r\n <XRadio\r\n type=\"radio\"\r\n size=\"small\"\r\n v-else\r\n :name=\"props.selectionMode\"\r\n :value=\"node.id\"\r\n :checked=\"isSelected(node)\"\r\n @click.stop=\"toggleNode(node)\"\r\n >\r\n {{ node[islabel] }}\r\n </XRadio>\r\n </span>\r\n </div>\r\n </div>\r\n</template>\r\n"],"names":["useNamespace","computed","ref"],"mappings":"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"}