list(array)<-->tree

1.list–>tree

let lists = [
 { "id": "ckb696kne0001lj3dejycrvew","ip": "192.188.1.112", "parentIp": null },
 { "id": "ckb698ybv0002lj3d19qp8a40", "ip": "172.21.45.97", "parentIp": "192.188.1.112"},
 { "id": "ckb699pvf0005lj3da9uqxgoy", "ip": "192.188.1.108","parentIp": "192.188.1.112" },
 { "id": "ckb69b1070009lj3d1o39j8uc", "ip": "192.188.1.111", "parentIp": "192.188.1.108" },
 { "id": "ckb69bpoh0012lj3dfq7d2ns4","ip": "192.188.1.109", "parentIp": "192.188.1.111"},
 { "id": "ckb69clw90014lj3doet59ntt",  "ip": "128.0.3.7","parentIp": "192.188.1.108" },
 {  "id": "ckb69d7680015lj3dss5fhoo9", "ip": "128.0.3.8", "parentIp": "128.0.3.7"},
 {  "id": "ckcwpe75300151bkf4fourifa", "ip": "192.168.1.33", "parentIp": "128.0.3.7" }
]

function listToTree(list, parentIp) {
  return list
    .filter(item => item.parentIp === parentIp)
    .map(item => ({
      ...item,
      children: this.listToTree(list, item.ip)
    }))
}

const res = listToTree(lists, null)
console.log(res)

'res--result':

[{}]
0:
	children: Array(2)
		0: {id: "ckb698ybv0002lj3d19qp8a40", ip: "172.21.45.97", parentIp: "192.188.1.112", children: Array(0)}
		1: {id: "ckb699pvf0005lj3da9uqxgoy", ip: "192.188.1.108", parentIp: "192.188.1.112", children: Array(2)}
		length: 2
		[[Prototype]]: Array(0)
	id: "ckb696kne0001lj3dejycrvew"
	ip: "192.188.1.112"
	parentIp: null

	[[Prototype]]: Object
  length: 1
[[Prototype]]: Array(0)

-----------------------------------------------------------------------------------------------------
//上面结果展开:
[{}]
0:
	children: Array(2)
		0:
			children: Array(0)
				length: 0
				[[Prototype]]: Array(0)
				id: "ckb698ybv0002lj3d19qp8a40"
				ip: "172.21.45.97"
				parentIp: "192.188.1.112"
				[[Prototype]]: Object
		1:
			children: Array(2)
				0:
					children: Array(1)
						0: {id: "ckb69bpoh0012lj3dfq7d2ns4", ip: "192.188.1.109", parentIp: "192.188.1.111", children: Array(0)}
						  length: 1
						[[Prototype]]: Array(0)
						id: "ckb69b1070009lj3d1o39j8uc"
						ip: "192.188.1.111"
						parentIp: "192.188.1.108"
						[[Prototype]]: Object
				1:
					children: Array(2)
						0: {id: "ckb69d7680015lj3dss5fhoo9", ip: "128.0.3.8", parentIp: "128.0.3.7", children: Array(0)}
						1: {id: "ckcwpe75300151bkf4fourifa", ip: "192.168.1.33", parentIp: "128.0.3.7", children: Array(0)}
						  length: 2
						[[Prototype]]: Array(0)
						id: "ckb69clw90014lj3doet59ntt"
						ip: "128.0.3.7"
						parentIp: "192.188.1.108"
						[[Prototype]]: Object
				  length: 2
				[[Prototype]]: Array(0)
				id: "ckb699pvf0005lj3da9uqxgoy"
				ip: "192.188.1.108"
				parentIp: "192.188.1.112"
				[[Prototype]]: Object
		length: 2
		[[Prototype]]: Array(0)
		id: "ckb696kne0001lj3dejycrvew"
		ip: "192.188.1.112"
		parentIp: null
		[[Prototype]]: Object
  length: 1
[[Prototype]]: Array(0)




2.tree–>list

//使用上面生成的tree数据
treeToArray(list, newArr) {
  list.forEach(item => {
    const { children } = item
    if (children) {
      delete item.children
      if (children.length) {
        newArr.push(item)
        return this.treeToArray(children, newArr)
      }
    }
    newArr.push(item)
  })
  return newArr
}

const res = this.listToTree(this.refss, null)
const rrs = this.treeToArray(res, [])
console.log(rrs)

'rrs--result':

[{}, {}, {}, {}, {}, {}, {}, {}]
0: {id: "ckb696kne0001lj3dejycrvew", ip: "192.188.1.112", parentIp: null}
1: {id: "ckb698ybv0002lj3d19qp8a40", ip: "172.21.45.97", parentIp: "192.188.1.112"}
2: {id: "ckb699pvf0005lj3da9uqxgoy", ip: "192.188.1.108", parentIp: "192.188.1.112"}
3: {id: "ckb69b1070009lj3d1o39j8uc", ip: "192.188.1.111", parentIp: "192.188.1.108"}
4: {id: "ckb69bpoh0012lj3dfq7d2ns4", ip: "192.188.1.109", parentIp: "192.188.1.111"}
5: {id: "ckb69clw90014lj3doet59ntt", ip: "128.0.3.7", parentIp: "192.188.1.108"}
6: {id: "ckb69d7680015lj3dss5fhoo9", ip: "128.0.3.8", parentIp: "128.0.3.7"}
7: {id: "ckcwpe75300151bkf4fourifa", ip: "192.168.1.33", parentIp: "128.0.3.7"}
length: 8
[[Prototype]]: Array(0)

注:1.list<–>tree 2. 菜单tree

附:

<!--
  FilePath: \src\views\license\license-dialog.vue
  Project: HolliTrust
  CreatedAt: 2021-04-12 10:05:27
  CreatedBy: ylx (<1415023245@qq.com>)
  Copyright: (c) 2021
  Task: #1
  新增授权弹框
-->
<template>
  <edit-dialog
    @cancel="cancel"
    @ok="ok"
    max-width="1000"
    scrollable
    v-model="value"
  >
    <vee-ob ref="ob">
      <form-flex>
        <v-row>
          <v-col
            cols="12"
            sm="3"
          >
            <vee
              :rules="{required:true}"
              v-slot="{ errors }"
            >
              <v-select
                :error-messages="errors"
                :items="productNames"
                :label="$t('schema.license.product')"
                v-model="currentModel.product"
              ></v-select>
            </vee>
          </v-col>
          <v-col
            cols="12"
            sm="3"
          >
            <vee
              :rules="{required:true}"
              v-slot="{ errors }"
            >
              <v-select
                :error-messages="errors"
                :items="versions"
                :label="$t('schema.license.productVersion')"
                v-model="currentModel.version"
              ></v-select>
            </vee>
          </v-col>
          <v-col
            cols="12"
            sm="3"
          >
            <date-time-picker
              :date="currentModel.expirationDate"
              :disabled="disabled"
            ></date-time-picker>
          </v-col>
          <v-col
            cols="12"
            sm="3"
          >
            <v-checkbox
              :label="$t('schema.license.valid')"
              hide-details
              v-model="currentModel.authType"
            ></v-checkbox>
          </v-col>
          <v-col
            class="num"
            cols="12"
            sm="6"
          >
            <v-text-field
              :label="$t('schema.license.projectName')"
              hide-details
              v-model="currentModel.projectName"
            ></v-text-field>
          </v-col>
          <v-col
            class="num"
            cols="12"
            sm="6"
          >
            <v-text-field
              :label="$t('schema.license.projectNumber')"
              hide-details
              v-model="currentModel.projectNumber"
            ></v-text-field>
          </v-col>
          <v-col
            class="num"
            cols="12"
            sm="6"
          >
            <vee
              :rules="{required:true}"
              v-slot="{ errors }"
            >
              <v-text-field
                :error-messages="errors"
                :label="$t('schema.license.customerCompanyName')"
                hide-details
                v-model="currentModel.customerCompanyName"
              ></v-text-field>
            </vee>
          </v-col>
          <v-col
            class="num"
            cols="12"
            sm="6"
          >
            <v-text-field
              :label="$t('schema.license.contractNumber')"
              hide-details
              v-model="currentModel.contractNumber"
            ></v-text-field>
          </v-col>
          <v-col cols="12">
            <vee
              :rules="{required:true, max: 128}"
              v-slot="{ errors }"
            >
              <v-textarea
                :error-messages="errors"
                :label="$t('schema.license.customerUuid')"
                :rows="1"
                auto-grow
                v-model="currentModel.customerUuid"
              ></v-textarea>
            </vee>
          </v-col>
          <v-col
            :key="i"
            class="my-n4"
            cols="12"
            v-for="(item,i) in groupLabels"
          >
            <div>{{item}}</div>
            <v-row class="pl-4 my-n2">
              <v-col
                :key="n"
                :style="{display: (item !== k.groupLabel ? 'none' : 'block')}"
                cols="4"
                v-for="(k,n) in productRestrictions"
              >
                <div
                  class="d-flex align-end"
                  v-if="item === k.groupLabel"
                >
                  <!-- <span>{{k.fieldLabel}}</span> -->
                  <vee
                    rules="numeric"
                    v-if="k.fieldType === 'NUMBER'"
                    v-slot="{ errors }"
                  >
                    <v-text-field
                      :error-messages="errors"
                      :label="k.fieldLabel"
                      class="field-label"
                      min="0"
                      persistent-hint
                      placeholder="0"
                      style="width:20px"
                      type="number"
                      v-model.number="k.fieldValue"
                    ></v-text-field>
                  </vee>
                  <v-checkbox
                    :label="k.fieldLabel"
                    hide-details
                    v-else
                    v-model="k.fieldValue"
                  ></v-checkbox>
                </div>
              </v-col>
            </v-row>
          </v-col>
          <v-col>
            <p>菜单授权</p>
            <v-row>
              <v-col class="menu pa-0">
                <v-treeview
                  :items="menus"
                  dense
                  open-all
                  selectable
                  selected-color="#1976d2"
                  v-model="menusValues"
                ></v-treeview>
              </v-col>
            </v-row>
          </v-col>

          <v-col cols="12">
            <v-text-field
              :label="$t('schema.license.remark')"
              hide-details
              v-model="currentModel.remark"
            ></v-text-field>
          </v-col>
        </v-row>
      </form-flex>
    </vee-ob>
  </edit-dialog>
</template>

<script>
import { editDialog } from '@c/dialogs'
import { formFlex } from '@c/forms'
import dateTimePicker from './date-time-picker'
import { format } from 'date-fns'
import { error } from '@utils/message'
import { create } from '@api/license'
import { find } from 'lodash'

export default {
  components: { editDialog, dateTimePicker, formFlex },
  props: {
    value: {
      type: Boolean,
      default: false
    },
    model: {
      type: Object,
      default: () => {}
    },
    products: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      currentModel: {},
      versions: [],
      productNames: [],
      show: true,
      disabled: false,
      expirationDate: '',
      productRestrictions: [],
      product: { productRestrictions: [] },
      // fieldValue: '',
      menusValues: [],
      groupLabels: [],
      restrictions: [],
      menus: [
        {
          id: 1,
          name: '全景态势'
        },
        {
          id: 2,
          name: '威胁分析'
        },
        {
          id: 3,
          name: '告警管理',
          children: [
            { id: 4, name: '告警记录' },
            { id: 5, name: '告警规则' }
          ]
        },
        {
          id: 6,
          name: '事件管理',
          children: [
            { id: 7, name: '事件记录' },
            { id: 8, name: '事件规则' }
          ]
        },
        {
          id: 9,
          name: '设备管理',
          children: [{ id: 10, name: '设备列表' }]
        },
        {
          id: 11,
          name: '资产管理',
          children: [
            { id: 12, name: '资产列表' },
            { id: 13, name: '网络拓扑' },
            { id: 14, name: 'SNMP参数配置' }
          ]
        },
        {
          id: 26,
          name: '统计报表',
          children: [
            { id: 27, name: '统计分析' },
            { id: 28, name: '安全报表' }
          ]
        },
        {
          id: 15,
          name: '日志管理',
          children: [
            { id: 16, name: '采集器管理' },
            { id: 19, name: '数据源' },
            { id: 17, name: '日志解析' },
            { id: 18, name: '原始日志' }
          ]
        },
        {
          id: 20,
          name: '工控专家库',
          children: [
            { id: 21, name: '威胁分析规则' },
            { id: 22, name: '工控系统问题' },
            { id: 23, name: '网络应用问题' },
            { id: 25, name: '漏洞列表' }
          ]
        }
      ]
    }
  },
  watch: {
    model: {
      handler(val) {
        this.currentModel = JSON.parse(JSON.stringify(val))
      },
      immediate: true
    },
    'currentModel.authType': {
      handler(val) {
        if (val) {
          this.expirationDate = format(
            new Date('2099-01-01 00:00:00'),
            'yyyy-MM-dd HH:mm:ss'
          )
          this.disabled = true
        } else {
          this.disabled = false
        }
      },
      immediate: true
    },
    'currentModel.product': {
      handler(val) {
        this.versions = this.products
          .filter(item => item.name == val)
          .map(item => item.version)
        this.currentModel.version = this.versions[0]
        this.product = find(this.products, {
          name: val,
          version: this.currentModel.version
        })
        this.productRestrictions = this.product.productRestrictions
        this.groupLabels = []
        if (this.productRestrictions.length) {
          this.productRestrictions.forEach(item => {
            item.fieldValue = ''
          })
          this.groupLabels = [
            ...new Set(
              this.productRestrictions.map(item => {
                return item.groupLabel
              })
            )
          ]
        }
      }
    },
    'currentModel.version': {
      handler(val) {
        this.product = find(this.products, {
          name: this.currentModel.product,
          version: val
        })
        this.productRestrictions = this.product.productRestrictions
        this.groupLabels = []
        if (this.productRestrictions.length) {
          this.productRestrictions.forEach(item => {
            item.fieldValue = ''
          })
          this.groupLabels = [
            ...new Set(
              this.productRestrictions.map(item => {
                return item.groupLabel
              })
            )
          ]
        }
      }
    }
  },
  methods: {
    async ok() {
      // console.log(this.menusValues)
      const valid = await this.$refs.ob.validate()
      if (!valid) {
        return
      }
      //截止日期为空判断
      if (
        this.currentModel.expirationDate.time === null &&
        this.currentModel.authType === false
      ) {
        error(this.$t('schema.license.expirationDateEmpty'))
        return
      } else {
        //填写具体日期
        if (
          this.currentModel.authType === false &&
          this.currentModel.expirationDate.time !== null
        ) {
          this.expirationDate = format(
            new Date(this.currentModel.expirationDate.time),
            'yyyy-MM-dd HH:mm:ss'
          )
        }
        //截止日期不能小于等于当前时间
        const expirationDates = +new Date(this.expirationDate)
        const currentTime = +new Date()
        if (currentTime >= expirationDates) {
          error(this.$t('schema.license.validMessage'))
          return
        }
      }
      this.restrictions = this.productRestrictions.map(item => {
        let { fieldValue, id: productRestrictionId } = item
        fieldValue = '' + fieldValue
        return { fieldValue, productRestrictionId }
      })
      // 组装数据
      const {
        projectName,
        projectNumber,
        customerCompanyName,
        contractNumber,
        customerUuid,
        remark
      } = this.currentModel
      let data = {
        productId: this.product.id,
        projectName,
        projectNumber,
        customerCompanyName,
        contractNumber,
        customerUuid,
        restrictions: this.restrictions,
        expirationDate: new Date(this.expirationDate).toISOString(),
        remark
      }
      // 创建授权数据请求
      try {
        const licenId = await create(data)
        const licenseid = licenId.id
        this.$emit('input', false)
        this.$emit('changed', licenseid)
      } catch {
        error()
      }
    },
    cancel() {
      this.$emit('input', false)
    }
  },
  created() {
    this.productNames = this.products.map(item => {
      return item.name
    })
    this.currentModel.product = this.productNames[0]
  }
}
</script>

<style lang="scss" scoped>
.num {
  padding-bottom: 35px;
}
.field-label {
  ::v-deep .v-input__slot {
    width: 80px;
  }
}
.menu {
  ::v-deep .v-treeview-node__children {
    display: flex;
    padding-left: 48px;
    .v-treeview-node__root {
      width: 150px;
      .v-treeview-node__level {
        width: 0px;
      }
    }
  }
}
</style>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现el-tree的双向内容滚动选中功能,可以通过以下步骤进行操作: 1. 在el-tree的配置项中设置highlightCurrent属性为true,这样在选中某个节点时,该节点会被高亮显示。 2. 在el-tree的样式中添加以下代码,来设置高亮显示时的样式: ```css .el-tree-node.is-highlight-current > .el-tree-node__content { background-color: #f5f7fa; /* 设置高亮背景色 */ } ``` 3. 在el-tree的mounted钩子函数中,监听树节点的点击事件,并获取点击的节点对应的dom元素。 ```javascript mounted() { this.$nextTick(() => { const treeEl = this.$el.querySelector('.el-tree') treeEl.addEventListener('click', this.handleTreeClick) }) }, methods: { handleTreeClick(event) { const target = event.target.closest('.el-tree-node') if (target) { // 处理节点选中逻辑 } } } ``` 4. 在处理节点选中逻辑时,需要将当前选中的节点滚动到可视区域内。可以通过以下代码实现: ```javascript const treeEl = this.$el.querySelector('.el-tree') const nodeRect = target.getBoundingClientRect() const treeRect = treeEl.getBoundingClientRect() if (nodeRect.bottom > treeRect.bottom) { treeEl.scrollTop = treeEl.scrollTop + nodeRect.bottom - treeRect.bottom } else if (nodeRect.top < treeRect.top) { treeEl.scrollTop = treeEl.scrollTop - treeRect.top + nodeRect.top } ``` 5. 同时,当树节点滚动时,也需要将当前可视区域内的节点高亮显示。可以通过以下代码实现: ```javascript const treeEl = this.$el.querySelector('.el-tree') const nodes = treeEl.querySelectorAll('.el-tree-node') const visibleNodes = Array.from(nodes).filter(node => { const nodeRect = node.getBoundingClientRect() const treeRect = treeEl.getBoundingClientRect() return nodeRect.bottom > treeRect.top && nodeRect.top < treeRect.bottom }) visibleNodes.forEach(node => { node.classList.add('is-highlight-current') }) ``` 6. 最后,还需要在节点取消选中时,将该节点的高亮样式移除。 ```javascript handleTreeClick(event) { const target = event.target.closest('.el-tree-node') if (target) { const selectedNodes = this.$refs.tree.getCheckedNodes() selectedNodes.forEach(node => { node.$el.classList.remove('is-highlight-current') }) target.classList.add('is-highlight-current') this.scrollIntoView(target) } } ``` 通过以上步骤,即可实现el-tree的双向内容滚动选中功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值