| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- <template>
- <!-- -->
- <!-- element-loading-text="拼命加载中……" -->
- <el-tree
- v-loading="props.loading"
- element-loading-background="#ffffff"
- element-loading-custom-class="loading_icon"
- :element-loading-spinner="elIconLoading"
- style="max-width: 600px"
- :data="filterTreeData"
- :props="defaultProps"
- :node-key="props.nodeKey"
- :expand-on-click-node="false"
- @node-click="handleNodeClick"
- :show-checkbox="props.showCheckBox"
- @check="HandleChecked"
- :check-on-click-leaf="false"
-
- :default-expand-all="defaultExpandAll"
- :default-checked-keys="props.defaultCheckedKeys"
- ref="treeRef"
- >
- <template #default="{ node, data }">
- <div class="custom-tree-node">
- <template v-if="editItemKey == data.id">
- <el-input @click="$event.stopPropagation()" class="edit_input" v-model="editTaskName" />
- </template>
- <span v-else>{{ node.label }}</span>
- <div class="operation">
- <!-- 展示操作栏 -->
- <template v-if="props.operation == 'all' &&
- (!props.operationFlagKey || props.operationFlagKey && data?.[props.operationFlagKey])">
-
- <!-- 展示修改确认操作 -->
- <template v-if="editItemKey == data.id">
- <el-icon style="margin-left: 5px;" @click="HandleEditConfirm($event,node,data)"><Check /></el-icon>
- </template>
- <!-- 展示 ... 和 新增 -->
- <template v-else>
- <el-icon v-if="(node?.level < props.maxLevel) && props.showAddOperation"
- @click="HandleAddSubItem($event,node,data)"
- style="color:#666666"><Plus />
- </el-icon>
- <el-popover
- :visible="popVisible && popOperationKey==data.id"
- placement="bottom"
- popper-class="pop_operation"
- style="min-width: auto !important;width: auto !important;"
- >
- <span @click="HandleRenameSubItm(node,data)">重命名</span>
- <span class="delete" @click="HandleDeleteSubItm(node,data)">删除</span>
- <template #reference>
- <el-icon style="transform: rotate(90deg);color:#666666;"
- @click="OpenMorePop($event,node, data)"><MoreFilled /></el-icon>
- </template>
- </el-popover>
- </template>
- </template>
- <!-- 展示关闭操作 -->
- <el-icon v-else-if="props.operation == 'close' &&
- (!props.operationFlagKey || props.operationFlagKey && data?.[props.operationFlagKey])"
- style="color:#666666"
- @click="HandleDelete(node, data)"><CircleClose /></el-icon>
- </div>
- </div>
- </template>
- </el-tree>
- </template>
- <script setup lang="ts">
- import { computed, ref} from 'vue'
- import {
- extractArrayObjectNode,deepSort,addNodeKeyValOfArrayObject
- } from '@/utils/commonFunctions.ts'
- const props = defineProps({
- defaultCheckedKeys:{
- type:Array,
- },
- loading:{
- type:Boolean,
- default:false
- },
- defaultTreeData:{
- type:Array<{
- label:String,
- id?:[String,null,number],
- children?:[] | null
- }>,
- },
- defaultExpandAll:{
- type:Boolean,
- default:false
- },
- showCheckBox:{
- type:Boolean,
- default:false
- },
- operation:{
- type:String, // 'all'|'close'|'none'
- default:'all'
- },
- showAddOperation:{
- type:Boolean,
- default:true,
- },
- operationFlagKey:{ //配合 operation 使用
- type:String, // 控制 操作显隐的键 的 变量名
- // 键的值 0 --无操作, 1 有操作
- },
- maxLevel:{
- type:Number,
- default:2
- },
- nodeKey:{
- type:String,
- default:'id'
- },
- sortMsg:{
- type:{
- sortKey:String,
- childrenKey:String
- },
- default:()=>{
- return {
- sortKey:'code',
- childrenKey:'children'
- }
- }
- },
- nodeDisabled:{
- type:Boolean,
- default:false
- }
- })
- const emit = defineEmits([
- 'openAddSubItmForm','updateTreeName','deleteTreeNode',
- 'changeCurrentSubTreeKey','updateSelectedTreeNode'
- ])
- const filterTreeData = computed(()=>{
- if(props.nodeDisabled){
- // disabled:true
- // 给节点添加 属性
- let list = JSON.parse(JSON.stringify(props.defaultTreeData))
- addNodeKeyValOfArrayObject(list,'disabled',props.nodeDisabled)
- return list
- }else{
- return props.defaultTreeData
- }
- })
- const elIconLoading = ref(`
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" ><path fill="currentColor" d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32m0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32m448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32m-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32M195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248m452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248M828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0m-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0"></path></svg>`)
- const defaultProps = ref({
- children: 'children',
- label: 'label',
- class:'custom_tree'
- })
- const editItemKey = defineModel('editItemKey') // 修改操作 选中的树节点key
- const editTaskName = defineModel('editTaskName')
- const popVisible = ref(false)
- const popOperationKey = ref() //更多操作 选中的树节点key
- const treeRef = defineModel('treeRef')
- const currentSelectedSubTarget = ref<any[]>([]) //已选指标
- const HandleEditConfirm = (e,node,data)=>{
- e.stopPropagation()
- // 调用接口传递修改的值
- editItemKey.value = ''
- emit('updateTreeName',{label:editTaskName.value,id:data.id})
- }
- const HandleChecked = (aimNode,selectedStatus)=>{
- console.log('点击节点复选框后触发的值',selectedStatus)
- currentSelectedSubTarget.value = extractArrayObjectNode(props.defaultTreeData,props.nodeKey,selectedStatus.checkedKeys)
- console.log('执行结果',currentSelectedSubTarget.value)
- // 递归排序
- currentSelectedSubTarget.value = deepSort(currentSelectedSubTarget.value,props.sortMsg.sortKey,props.sortMsg.childrenKey)
- // 这个数据在传递之前要进行过滤排序
- emit('updateSelectedTreeNode',currentSelectedSubTarget.value)
- }
- const handleNodeClick = (data,node) => {
- console.log('节点点击了',data)
- console.log('节点点击了node',node)
- emit('changeCurrentSubTreeKey',{data,node})
- }
- const HandleAddSubItem = ( e, node, data)=>{
- console.log('当前节点',node)
- console.log('当前数据',data)
- e.stopPropagation()
- emit('openAddSubItmForm', {data,node})
- }
- const HandleRenameSubItm = (node,data)=>{
- console.log('修改的节点')
- popVisible.value = false
- popOperationKey.value = ''
- editItemKey.value = data.id
- editTaskName.value = node.label
- }
- const HandleDeleteSubItm = (node,data)=>{
- console.log('删除子元素',node,data)
- emit('deleteTreeNode',{node,id:data.id})
- popVisible.value = false
- }
- const OpenMorePop = (e,node,data)=>{
- console.log('打开更多pop',node,data)
- e.stopPropagation()
- popVisible.value = !popVisible.value
- popOperationKey.value = data.id
- }
- const HandleDelete = (node,data)=>{
- console.log('删除对应类型下的指标',node,data)
- emit('deleteTreeNode',{node,id:data.id})
- }
- </script>
- <style lang="scss" scoped>
- .custom-tree-node {
- // border:solid red 1px;
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 14px;
- padding-right: 12px;
- line-height: 1;
- .edit_input{
- flex:1 0;
- :deep(.el-input__wrapper){
- height: 28px;
- }
- }
- .operation{
- display: flex;
- gap:10px;
- }
- }
- :deep(.loading_icon){
- .el-loading-spinner{
- color:#2e64fa;
- .el-loading-text{
- color:#2e64fa;
- }
- }
- }
- </style>
- <style lang="scss">
- .custom_tree > .el-tree-node__content{
- // border:solid red 1px;
- height: 28px !important;
- }
- .custom_tree.is-current > .el-tree-node__content{
- background-color: #E3EEFF !important;
- color:#2E64FA;
- }
- .pop_operation.el-popper.is-light{
- width:auto !important;
- min-width: auto !important;
- padding:6px;
- font-size: 12px ;
- display: flex;
- flex-direction: column;
- gap: 10px;
- .delete{
- color:#F56C6C;
- }
- >span{
- &:hover{
- cursor: pointer;
- }
- }
- }
- </style>
|