zhaowei
9 天以前 86f0166e2a759e6ec2c34b0dd0b388bafa80cedd
src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue
@@ -1,35 +1,37 @@
<template>
  <a-card class="tree_con" :loading="cardLoading" :bordered="false" @contextmenu.native="e=>e.preventDefault()">
  <a-card class="tree_con" :loading="cardLoading" :bordered="false" @contextmenu.native.stop="openBaseContextMenu">
    <a-spin :spinning="loading">
      <div style="display: flex;flex-direction: column;height: 100%">
        <div style="display: flex">
        <div style="display: flex;justify-content: space-between">
          <a-input placeholder="输入关键字进行搜索" allowClear v-model="searchInput"
                   @change="handleSearchInputChange"/>
          <a-dropdown :trigger="['click']" placement="bottomCenter" style="margin: 0 8px">
            <a-menu slot="overlay">
              <a-menu-item key="1" @click="expandedKeys = allTreeKeys">展开所有</a-menu-item>
              <a-menu-item key="2" @click="expandedKeys = ['-1']">合并所有</a-menu-item>
              <a-menu-item key="3" @click="getTreeDataByApi">刷新</a-menu-item>
            </a-menu>
            <a-button>
              <a-icon type="bars"/>
            </a-button>
          </a-dropdown>
          <a-button type="primary" v-has="'product_add'"
                    @click="$refs.productModalFormRef.triggerCorrespondingMethod({modalTitle:'添加产品',methodName:'handleProductAdd'})">
            <a-icon type="plus"></a-icon>
            产品
          </a-button>
          <!--          <a-tooltip title="刷新">-->
          <!--            <a-button icon="reload" @click="handleTreeReload" style="width: 18%;margin-left: 8px"></a-button>-->
          <!--          </a-tooltip>-->
          <!--          <a-button type="primary" v-has="'product_add'" icon="plus" style="margin-left: 8px"-->
          <!--                    @click="$refs.productModalFormRef.triggerCorrespondingMethod({modalTitle:'添加产品',methodName:'handleProductAdd'})">-->
          <!--            产品-->
          <!--          </a-button>-->
          <!--          <a-dropdown :trigger="['click']" placement="bottomCenter" style="margin: 0 8px">-->
          <!--            <a-menu slot="overlay">-->
          <!--              <a-menu-item key="1" @click="expandedKeys = allTreeKeys">展开所有</a-menu-item>-->
          <!--              <a-menu-item key="2" @click="expandedKeys = ['-1']">合并所有</a-menu-item>-->
          <!--              <a-menu-item key="3" @click="getTreeDataByApi">刷新</a-menu-item>-->
          <!--            </a-menu>-->
          <!--            <a-button>-->
          <!--              <a-icon type="bars"/>-->
          <!--            </a-button>-->
          <!--          </a-dropdown>-->
        </div>
        <!--产品结构树-->
        <div style="flex: 1;overflow:auto;margin-top: 10px">
        <div id="tree-container" style="flex: 1;overflow:auto;margin-top: 10px">
          <a-tree blockNode show-icon :expandedKeys.sync="expandedKeys"
                  :selectedKeys="selectedKeys" :treeData="treeDataSource" :autoExpandParent="autoExpandParent"
                  @select="handleTreeSelect" @expand="handleTreeExpand" @rightClick="handleTreeRightClick">
            <template slot="title" slot-scope="{ label, parentId, entity, key:treeKey,type}">
            <template slot="title" slot-scope="{ label, parentId, key:treeKey,type}">
              <ProductStructureTreeContextMenu ref="contextMenuRef"
                                               :treeParams="{label,treeKey,searchValue,type,entity}"/>
                                               :treeParams="{label,treeKey,searchValue,type}"/>
            </template>
            <a-icon slot="switcherIcon" type="down"/>
@@ -59,6 +61,19 @@
    <ProcessStepModal :currentTreeNodeInfo="rightClickSelected" @submitSuccess="modalFormSubmitSuccess"/>
    <!--权限配置弹窗-->
    <AssignPermissionModal :currentTreeNodeInfo="rightClickSelected" @submitSuccess="modalFormSubmitSuccess"/>
    <!--检索电子模板弹窗-->
    <NcDocumentSearchModal :currentDocumentInfo="rightClickSelected" @submitSuccess="modalFormSubmitSuccess"/>
    <!--检索NC文件弹窗-->
    <NcDocumentSearchNcModal :currentDocumentInfo="rightClickSelected" @searchTreeNode="searchTreeNode"
                             @submitSuccess="modalFormSubmitSuccess"/>
    <!--引用部件-->
    <NcComponentBorrowModal :currentBorrowInfo="rightClickSelected" @submitSuccess="modalFormSubmitSuccess"/>
    <!--产品结构树基本右键菜单(空白处触发)-->
    <ProductStructureBaseContextMenu ref="baseContextmenuRef"/>
    <div class="full-screen-container" v-if="fullScreenSpinning">
      <a-spin :spinning="fullScreenSpinning" size="large" tip="NC文件检索中..."/>
    </div>
  </a-card>
</template>
@@ -73,10 +88,19 @@
  import ProcessModal from './Process/ProcessModal'
  import ProcessStepModal from './ProcessStep/ProcessStepModal'
  import AssignPermissionModal from './Permission/AssignPermissionModal'
  import DeviceCustomTypeModal
    from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
  import ProductStructureBaseContextMenu
    from '@views/dnc/base/modules/ProductStructure/ProductStructureBaseContextMenu.vue'
  import NcDocumentSearchModal from '@views/dnc/base/modules/ProductStructure/Document/NcDocumentSearchModal.vue'
  import NcDocumentSearchNcModal from '@views/dnc/base/modules/ProductStructure/Document/NcDocumentSearchNcModal.vue'
  import NcComponentBorrowModal from '@views/dnc/base/modules/ProductStructure/Document/NcComponentBorrowModal.vue'
  export default {
    name: 'ProductStructureTree',
    components: {
      ProductStructureBaseContextMenu,
      DeviceCustomTypeModal,
      AssignPermissionModal,
      ProcessStepModal,
      ProcessModal,
@@ -84,7 +108,10 @@
      PartModal,
      ComponentModal,
      ProductModal,
      ProductStructureTreeContextMenu
      ProductStructureTreeContextMenu,
      NcDocumentSearchModal,
      NcDocumentSearchNcModal,
      NcComponentBorrowModal
    },
    data() {
      return {
@@ -100,8 +127,8 @@
        autoExpandParent: true,
        checkStrictly: true,
        allTreeKeys: [],
        currentSelected: {},
        rightClickSelected: {},
        fullScreenSpinning: false,
        url: {
          delete: '/nc/product/delete'
        }
@@ -110,23 +137,30 @@
    created() {
      this.getTreeDataByApi()
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
      this.$bus.$on('searchNcFinished', () => this.fullScreenSpinning = false)
    },
    beforeDestroy() {
      this.$bus.$off('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      // 调用接口获取树的数据
      getTreeDataByApi() {
        this.loading = true
        this.cardLoading = true
        dncApi.getProductStructureTreeApi().then(res => {
          if (res.success) {
            this.dataList = []
            this.allTreeKeys = []
            this.treeDataSource = res.list
            this.generateList(this.treeDataSource)
            // this.expandedKeys = this.allTreeKeys
            if (this.expandedKeys.length === 0) this.expandedKeys = this.beforeSearchExpandedKeys = [this.treeDataSource[0].id]
          } else {
            this.$message.warn(res.message)
          }
        }).finally(() => {
        this.treeDataSource = []
        dncApi.getProductStructureTreeApi()
          .then(res => {
            if (res.success) {
              this.dataList = []
              this.allTreeKeys = []
              this.treeDataSource = res.result
              this.generateList(this.treeDataSource)
              // this.expandedKeys = this.allTreeKeys
              if (this.expandedKeys.length === 0) this.expandedKeys = this.beforeSearchExpandedKeys = [this.treeDataSource[0].id]
            } else {
              this.$message.warn(res.message)
            }
          }).finally(() => {
          this.loading = false
          this.cardLoading = false
        })
@@ -135,24 +169,66 @@
      /**
       * 树节点选中时触发
       * @param selectedKeys 选中节点key
       * @param {node} node 节点对象
       * @param eventOrRecord  节点对象或者手动传入record
       */
      handleTreeSelect(selectedKeys, { node }) {
        let record = node.dataRef
        this.currentSelected = Object.assign({}, record)
      handleTreeSelect(selectedKeys, eventOrRecord) {
        const that = this
        let record = eventOrRecord.node ? eventOrRecord.node.dataRef : eventOrRecord
        const { id, type } = record
        dncApi.getProductStructureTreeNodeEntityApi({ id, type })
          .then(res => {
            if (res.success) {
              let currentSelectedNodeInfo
              if (res.result.length > 0) {
                currentSelectedNodeInfo = Object.assign({}, record, { entity: res.result[0] })
              } else {
                currentSelectedNodeInfo = {}
                that.$notification.warning({
                  message: '消息',
                  description: '暂无该节点详细信息'
                })
              }
              // 向右侧父级组件发送当前选中树节点信息
              this.$bus.$emit('sendCurrentTreeNodeInfo', currentSelectedNodeInfo)
            } else {
              that.$notification.error({
                message: '消息',
                description: res.message
              })
            }
          })
        if (selectedKeys.length === 0) return
        this.selectedKeys = selectedKeys
        // 向右侧父级组件发送当前选中树节点信息
        this.$bus.$emit('sendCurrentTreeNodeInfo', this.currentSelected)
      },
      /**
       * 树节点右键单击节点时触发
       * @param event 事件对象
       * @param node 节点对象
       */
      handleTreeRightClick({ event, node }) {
      handleTreeRightClick({ node }) {
        if (this.$refs.baseContextmenuRef) this.$refs.baseContextmenuRef.menuVisible = false
        const that = this
        const record = node.dataRef
        this.rightClickSelected = Object.assign({}, record)
        const { id, type } = record
        dncApi.getProductStructureTreeNodeEntityApi({ id, type })
          .then(res => {
            if (res.success) {
              if (res.result.length > 0) {
                that.rightClickSelected = Object.assign({}, record, { entity: res.result[0] })
              } else {
                that.rightClickSelected = {}
                that.$notification.warning({
                  message: '消息',
                  description: '暂无该节点详细信息'
                })
              }
            } else {
              that.$notification.error({
                message: '消息',
                description: res.message
              })
            }
          })
      },
      // 树节点右键单击菜单中删除按钮时触发
@@ -197,6 +273,7 @@
      /**
       * 自动展开添加下级节点的父节点
       * @param isAddNextLevel 是否需要展开下级
       */
      modalFormSubmitSuccess(isAddNextLevel) {
        // 判断是否为添加下级并且判断父节点是否展开
@@ -213,8 +290,36 @@
        this.autoExpandParent = false
      },
      /* 输入查询内容变化时触发 */
      /**
       * 检索NC文件弹窗中双击行记录后触发搜索NC文件对应树节点并模拟选中树节点查询对应设备类或NC文件
       * @param searchNcRecord 检索NC文件弹窗中双击获得的NC文件列表行记录
       */
      searchTreeNode(searchNcRecord) {
        this.fullScreenSpinning = true
        const { attributionId, nodeCode, nodeName, nodeId, docId } = searchNcRecord
        this.searchInput = `[${nodeCode}]${nodeName}`
        this.searchAndExpandTreeNode()
        const treeNodeRecord = Object.assign({
          autoClickedLevelInfo: {
            attributionId,
            docId
          }
        }, this.getTreeNodeRecord(nodeId, this.treeDataSource))
        this.handleTreeSelect([treeNodeRecord.id], treeNodeRecord)
      },
      // 输入查询内容变化时触发(增加防抖机制)
      handleSearchInputChange() {
        const that = this
        let timer
        if (timer) clearTimeout(timer)
        timer = setTimeout(function() {
          that.searchAndExpandTreeNode() // 加小括号调用函数
        }, 1000)
      },
      // 防抖函数中触发搜索并展开树节点
      searchAndExpandTreeNode() {
        let search = this.searchInput
        let expandedKeys
        let autoExpandParent
@@ -234,7 +339,6 @@
          expandedKeys = this.beforeSearchExpandedKeys
          autoExpandParent = false
        }
        Object.assign(this, {
          expandedKeys,
          searchValue: search,
@@ -264,6 +368,26 @@
      },
      /**
       * 递归获得输入项的record对象
       * @param key record对象key值
       * @param tree 树节点
       */
      getTreeNodeRecord(key, tree) {
        let treeNodeRecord
        for (let i = 0; i < tree.length; i++) {
          const node = tree[i]
          if (node.children) {
            if (node.children.findIndex(item => item.key === key) > -1) {
              treeNodeRecord = node.children.find(item => item.key === key)
            } else if (this.getTreeNodeRecord(key, node.children)) {
              treeNodeRecord = this.getTreeNodeRecord(key, node.children)
            }
          }
        }
        return treeNodeRecord
      },
      /**
       * 递归获得所有树节点key
       * @param data
       */
@@ -280,8 +404,17 @@
        }
      },
      triggerCorrespondingMethod({ methodName }) {
        if (this[methodName]) this[methodName]()
      /**
       * 树所在父元素的右键事件
       * @param event 事件对象
       */
      openBaseContextMenu(event) {
        event.preventDefault()
        if (event.target.id !== 'tree-container') return
        this.$refs.baseContextmenuRef.menuStyle.top = event.clientY + 'px'
        this.$refs.baseContextmenuRef.menuStyle.left = event.clientX + 'px'
        this.$refs.baseContextmenuRef.menuVisible = true
        document.body.addEventListener('click', this.handleBaseContextMenuClose)
      },
      /**
@@ -289,7 +422,7 @@
       * @param treeNode
       */
      setTreeNodeIcon(treeNode) {
        switch (treeNode.type) {
        switch (+treeNode.type) {
          case 1:
            treeNode.slots = { icon: 'product' }
            break
@@ -310,7 +443,23 @@
            break
          default:
        }
      },
      // 控制基础右键菜单关闭
      handleBaseContextMenuClose() {
        if (this.$refs.baseContextmenuRef) this.$refs.baseContextmenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleBaseContextMenuClose)
      },
      // 刷新重新获取树的数据
      handleTreeReload() {
        this.getTreeDataByApi()
      },
      triggerCorrespondingMethod({ methodName }) {
        if (this[methodName]) this[methodName]()
      }
    }
  }
</script>
@@ -333,6 +482,20 @@
    width: 8px;
  }
  .full-screen-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, .8);
    z-index: 9999;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  @media screen and (min-width: 1920px) {
    .tree_con {
      height: 748px !important;