1、设备类管理页面完成增删改查功能
2、产品结构树工序及工步层级引入设备类概念由系统参数配置决定是否展示,若设备类存在时则NC文档挂载在设备类下不存在时则按照对应工序或工步层级下
3、产品结构树工序及工步层级的刀具列表实现增删改查功能
4、新增设备类管理页面并完成布局
5、产品结构树接口调整,产品结构树节点实体信息通过点击后调取接口获取
6、产品结构树搜素输入框增加防抖机制,避免每次输入都重新计算消耗性能使页面卡顿
7、新增工序及工步层级的刀具列表并添加系统权限
8、用户管理页面移除新增用户时的密码校验
9、产品结构树各层级属性信息展示由每行3列调整为每行4列
10、产品结构树页面在工序和工步层级实现对设备类的增删改查功能
已添加1个文件
已修改19个文件
已删除9个文件
2921 ■■■■ 文件已修改
src/api/dnc.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/DeviceCustomTypeManagement.vue 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/ProductStructure.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue 209 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue 754 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue 269 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/TableContextMenu.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/UserModal.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/dnc.js
@@ -15,7 +15,7 @@
  // èŽ·å–äº§å“ç»“æž„æ ‘
  getProductStructureTreeApi: () => getAction('/nc/product/getTree'),
  // èŽ·å–äº§å“ç»“æž„æ ‘èŠ‚ç‚¹å®žä½“ä¿¡æ¯
  getProductStructureTreeNodeEntityApi: params => getAction('/nc/product/getTreeById', params),
  getProductStructureTreeNodeEntityApi:params=> getAction('/nc/product/getTreeById',params),
  // èŽ·å–æ‰€æœ‰è®¾å¤‡çš„åˆ—è¡¨
  getAllDeviceListApi: (type) => getAction('/nc/device/list/all'),
  // å¯¼å…¥NC程序/文档
@@ -51,32 +51,30 @@
  appointCurrentDocumentVersionApi: fileId => putAction(`/nc/file/assign/version/${fileId}`),
  // æ–‡æ¡£æ¯”对
  fileCompareApi: fileIdArray => getAction(`/nc/file/comparison/${fileIdArray[0]}/${fileIdArray[1]}`),
  // æƒé™é…ç½®å¼¹çª—中获取所有车间列表
  getAllDepartmentsListApi: () => getAction('/mdc/mdcProduction/queryTreeListByConfig'),
  // æƒé™é…ç½®å¼¹çª—中获取所有用户列表
  // èŽ·å–æ‰€æœ‰éƒ¨é—¨åˆ—è¡¨
  getAllDepartmentsListApi: () => getAction('/ucenter/depart/list/all'),
  // èŽ·å–æ‰€æœ‰ç”¨æˆ·åˆ—è¡¨
  getAllUsersListApi: () => getAction('/sys/user/list'),
  // æƒé™é…ç½®å¼¹çª—中获取有权限的部门列表
  // èŽ·å–æœ‰æƒé™çš„éƒ¨é—¨åˆ—è¡¨
  getHasPermissionDepartApi: ({ type, id }) => getAction(`/nc/product/get/perm/depart/${type}/${id}`),
  // æƒé™é…ç½®å¼¹çª—中获取有权限的用户列表
  // èŽ·å–æœ‰æƒé™çš„ç”¨æˆ·åˆ—è¡¨
  getHasPermissionUserApi: ({ type, id }) => getAction(`/nc/product/get/perm/user/${type}/${id}`),
  // æƒé™é…ç½®å¼¹çª—中分配部门权限
  // åˆ†é…éƒ¨é—¨æƒé™
  assignPermissionToDepart: ({ treeNodeType, treeNodeId, isAssignSonNode, departIdArray }) => {
    return postAction(`/nc/product/assign/add/department/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, departIdArray)
  },
  // æƒé™é…ç½®å¼¹çª—中移除部门权限
  // ç§»é™¤éƒ¨é—¨æƒé™
  removePermissionFromDepart: ({ treeNodeType, treeNodeId, isAssignSonNode, departIdArray }) => {
    return postAction(`/nc/product/assign/remove/department/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, departIdArray)
  },
  // æƒé™é…ç½®å¼¹çª—中分配用戶权限
  // åˆ†é…ç”¨æˆ¶æƒé™
  assignPermissionToUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
    return postAction(`/nc/product/assign/add/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
  },
  // æƒé™é…ç½®å¼¹çª—中移除用户权限
  // ç§»é™¤ç”¨æˆ·æƒé™
  removePermissionFromUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
    return postAction(`/nc/product/assign/remove/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
  },
  // é€šè¿‡è½¦é—´ID获取设备类列表
  getDeviceCustomTypeListByProductionIdApi: productionId => getAction('/nc/deviceManagement/getDeviceManagementListByProductionId', { productionId }),
  //-------------------------设备结构树------------------------------------------------
  // èŽ·å–è®¾å¤‡æ ‘
@@ -92,8 +90,5 @@
  // ç§»é™¤ç”¨æˆ·æƒé™
  removeDeviceTreePermissionFromUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
    return postAction(`/nc/device/assign/remove/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
  },
  //-------------------------设备类管理------------------------------------------------
  // èŽ·å–æœ‰æƒé™çš„è½¦é—´æ ‘åˆ—è¡¨
  getHasPermissionWorkshopTreeApi: () => getAction('/nc/deviceManagement/getProductionIdsByUserId')
  }
}
src/views/dnc/base/DeviceCustomTypeManagement.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/ProductStructure.vue
@@ -11,35 +11,30 @@
    <!--导入文件公共弹窗-->
    <ImportFileModal/>
    <!--新增或编辑设备类公共弹窗-->
    <DeviceCustomTypeModal/>
  </a-card>
</template>
<script>
import ProductStructureTree from './modules/ProductStructure/ProductStructureTree'
import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
import ImportFileModal from '../common/ImportFileModal'
import DeviceCustomTypeModal from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
  import ProductStructureTree from './modules/ProductStructure/ProductStructureTree'
  import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
  import ImportFileModal from '../common/ImportFileModal'
export default {
  name: 'ProductStructure',
  components: {
    DeviceCustomTypeModal,
    ProductStructureTree,
    ProductStructureMain,
    ImportFileModal
  },
  data() {
    return {}
  },
  methods: {}
}
  export default {
    name: 'ProductStructure',
    components: {
      ProductStructureTree,
      ProductStructureMain,
      ImportFileModal
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped lang="less">
/deep/ .ant-card-body {
  padding: 8px;
}
  /deep/ .ant-card-body {
    padding: 8px;
  }
</style>
src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
@@ -1,6 +1,6 @@
<template>
  <div style="height: 100%">
    <a-tabs style="height: 100%" v-model="activeTabKey" @change="handleTabChange">
  <div>
    <a-tabs v-model="activeTabKey" @change="handleTabChange">
      <a-tab-pane :key="1" tab="设备属性" v-if="currentTreeNodeInfo.type===2&&!currentDocumentInfo.docId">
        <DeviceInfo :currentLevelDetails="currentTreeNodeInfo.entity" :size="containerSize"/>
      </a-tab-pane>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue
@@ -82,7 +82,6 @@
      getTreeDataByApi() {
        this.loading = true
        this.cardLoading = true
        this.treeDataSource = []
        dncApi.getDeviceTreeDataApi()
          .then(res => {
            if (res.success) {
src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue
@@ -1,6 +1,6 @@
<template>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="名称" :span="2">{{currentLevelDetails.componentName}}</a-descriptions-item>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="名称">{{currentLevelDetails.componentName}}</a-descriptions-item>
    <a-descriptions-item label="代号">{{currentLevelDetails.componentCode}}</a-descriptions-item>
    <a-descriptions-item label="型号    ">{{currentLevelDetails.componentModel}}</a-descriptions-item>
    <a-descriptions-item label="物料编码">{{currentLevelDetails.materielCode}}</a-descriptions-item>
@@ -10,12 +10,12 @@
    <a-descriptions-item label="生产类型">{{currentLevelDetails.produceType}}</a-descriptions-item>
    <a-descriptions-item label="处理类型    ">{{currentLevelDetails.processType}}</a-descriptions-item>
    <a-descriptions-item label="结构类型    ">{{currentLevelDetails.structureType}}</a-descriptions-item>
    <a-descriptions-item label="重量" >{{currentLevelDetails.componentWeight}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
    <a-descriptions-item label="重量" :span="2">{{currentLevelDetails.componentWeight}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createName}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateName}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="刀具名称">{{currentLevelDetails.cutterName}}</a-descriptions-item>
    <a-descriptions-item label="刀具编号">{{currentLevelDetails.cutterCode}}</a-descriptions-item>
    <a-descriptions-item label="刀具类型">{{currentLevelDetails.cutterType}}</a-descriptions-item>
    <a-descriptions-item label="额定寿命">{{currentLevelDetails.lifetime}}</a-descriptions-item>
    <a-descriptions-item label="刀位">{{currentLevelDetails.cutterSpacing}}</a-descriptions-item>
    <a-descriptions-item label="数量">{{currentLevelDetails.quantity}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
export default {
  name: 'CutterInfo',
  components: {},
  props: {
    currentLevelDetails: {
      type: Object
    },
    size: {
      type: String
    }
  },
  data() {
    return {}
  },
  methods: {}
}
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
@@ -1,5 +1,5 @@
<template>
  <div style="flex: 1">
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange">
src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue
@@ -1,6 +1,6 @@
<template>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="零件名称" :span="2">{{currentLevelDetails.partsName}}</a-descriptions-item>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="零件名称">{{currentLevelDetails.partsName}}</a-descriptions-item>
    <a-descriptions-item label="零件代号">{{currentLevelDetails.partsCode}}</a-descriptions-item>
    <a-descriptions-item label="零件型号    ">{{currentLevelDetails.partsModel}}</a-descriptions-item>
    <a-descriptions-item label="物料编码">{{currentLevelDetails.materielCode}}</a-descriptions-item>
@@ -10,12 +10,12 @@
    <a-descriptions-item label="生产类型">{{currentLevelDetails.produceType}}</a-descriptions-item>
    <a-descriptions-item label="处理类型    ">{{currentLevelDetails.processType}}</a-descriptions-item>
    <a-descriptions-item label="结构类型    ">{{currentLevelDetails.structureType}}</a-descriptions-item>
    <a-descriptions-item label="重量">{{currentLevelDetails.partsWeight}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
    <a-descriptions-item label="重量" :span="2">{{currentLevelDetails.partsWeight}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createName}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateName}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
@@ -27,123 +27,124 @@
</template>
<script>
import dncApi from '@/api/dnc'
import DepartPermissionTransfer from './DepartPermissionTransfer'
import UserPermissionTransfer from './UserPermissionTransfer'
  import dncApi from '@/api/dnc'
  import DepartPermissionTransfer from './DepartPermissionTransfer'
  import UserPermissionTransfer from './UserPermissionTransfer'
  import { queryProductionTreeList } from '@/api/api'
export default {
  name: 'AssignPermissionModal',
  components: { UserPermissionTransfer, DepartPermissionTransfer },
  props: {
    currentTreeNodeInfo: {
      type: Object
    }
  },
  data() {
    return {
      visible: false,
      title: '',
      isAssignSonNode: true,
      activeTabKey: 1,
      allDepartmentsList: [],
      allUsersList: [],
      allTreeKeys: [],
      hasLoadedDataTabKeyArray: []
    }
  },
  watch: {
    visible: {
      handler(value) {
        if (value) {
          this.activeTabKey = 1
          this.isAssignSonNode = true
          this.getAllDepartmentsListByApi()
  export default {
    name: 'AssignPermissionModal',
    components: { UserPermissionTransfer, DepartPermissionTransfer },
    props: {
      currentTreeNodeInfo: {
        type: Object
      }
    },
    data() {
      return {
        visible: false,
        title: '',
        isAssignSonNode: true,
        activeTabKey: 1,
        allDepartmentsList: [],
        allUsersList: [],
        allTreeKeys: [],
        hasLoadedDataTabKeyArray: []
      }
    },
    watch: {
      visible: {
        handler(value) {
          if (value) {
            this.activeTabKey = 1
            this.isAssignSonNode = true
            this.getAllDepartmentsListByApi()
          }
        }
      },
      activeTabKey: {
        handler(value) {
          if (this.hasLoadedDataTabKeyArray.includes(value)) return
          if (value === 2) this.getAllUsersListByApi()
          this.hasLoadedDataTabKeyArray.push(value)
        }
      }
    },
    activeTabKey: {
      handler(value) {
        if (this.hasLoadedDataTabKeyArray.includes(value)) return
        if (value === 2) this.getAllUsersListByApi()
        this.hasLoadedDataTabKeyArray.push(value)
      }
    }
  },
  created() {
    this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
  },
  methods: {
    // ç‚¹å‡»æ ‘节点右键菜单权限配置按钮后触发
    handleAssignPermission() {
      this.visible = true
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      // ç‚¹å‡»æ ‘节点右键菜单权限配置按钮后触发
      handleAssignPermission() {
        this.visible = true
      },
    // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰è½¦é—´åˆ—è¡¨
    getAllDepartmentsListByApi() {
      this.allTreeKeys = []
      dncApi.getAllDepartmentsListApi()
        .then(res => {
          if (res.success) {
            this.allDepartmentsList = res.result
            this.generateList(this.allDepartmentsList)
            this.$nextTick(() => {
              this.$refs.departPermissionTransferRef.getHasPermissionDepartByApi()
              this.$refs.departPermissionTransferRef.expandedKeys = this.allTreeKeys
              this.$refs.departPermissionTransferRef.flatten(JSON.parse(JSON.stringify(this.allDepartmentsList)))
            })
            // åªæœ‰ä¸Šæ¬¡é€€å‡ºæ—¶åœ¨è½¦é—´åˆ†é…tab界面才会进入此判断
            // è‹¥ä¸Šæ¬¡é€€å‡ºæ—¶åœ¨ç”¨æˆ·åˆ†é…tab界面则再次进入时key由2变为1时会触发watch监测activeTabKey变化则会将key:1加入hasLoadedDataTabKeyArray,因此无需再次加入key:1
            if (!this.hasLoadedDataTabKeyArray.includes(this.activeTabKey)) this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
          }
        })
    },
      // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰è½¦é—´åˆ—è¡¨
      getAllDepartmentsListByApi() {
        this.allTreeKeys = []
        queryProductionTreeList()
          .then(res => {
            if (res.success) {
              this.allDepartmentsList = res.result
              this.generateList(this.allDepartmentsList)
              this.$nextTick(() => {
                this.$refs.departPermissionTransferRef.getHasPermissionDepartByApi()
                this.$refs.departPermissionTransferRef.expandedKeys = this.allTreeKeys
                this.$refs.departPermissionTransferRef.flatten(JSON.parse(JSON.stringify(this.allDepartmentsList)))
              })
              // åªæœ‰ä¸Šæ¬¡é€€å‡ºæ—¶åœ¨è½¦é—´åˆ†é…tab界面才会进入此判断
              // è‹¥ä¸Šæ¬¡é€€å‡ºæ—¶åœ¨ç”¨æˆ·åˆ†é…tab界面则再次进入时key由2变为1时会触发watch监测activeTabKey变化则会将key:1加入hasLoadedDataTabKeyArray,因此无需再次加入key:1
              if (!this.hasLoadedDataTabKeyArray.includes(this.activeTabKey)) this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
            }
          })
      },
    /**
     * é€’归获得所有树节点key
     * @param data
     */
    generateList(data) {
      for (let i = 0; i < data.length; i++) {
        const node = data[i]
        const key = node.key
        this.allTreeKeys.push(key)
        if (node.children) this.generateList(node.children)
      }
    },
    // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰ç”¨æˆ·åˆ—è¡¨
    getAllUsersListByApi() {
      dncApi.getAllUsersListApi()
        .then(res => {
          if (res.success) {
            this.allUsersList = res.result.records
            this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
          }
        })
    },
    setAdminDisabled() {
      this.allUsersList = this.allUsersList.map(item => {
        return {
          ...item,
          disabled: item.username === 'admin'
      /**
       * é€’归获得所有树节点key
       * @param data
       */
      generateList(data) {
        for (let i = 0; i < data.length; i++) {
          const node = data[i]
          const key = node.key
          this.allTreeKeys.push(key)
          if (node.children) this.generateList(node.children)
        }
      })
    },
      },
    handleModalClose() {
      this.visible = false
      this.hasLoadedDataTabKeyArray = []
    },
      // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰ç”¨æˆ·åˆ—è¡¨
      getAllUsersListByApi() {
        dncApi.getAllUsersListApi()
          .then(res => {
            if (res.success) {
              this.allUsersList = res.result.records
              this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
            }
          })
      },
    triggerCorrespondingMethod({ methodName, modalTitle }) {
      if (this[methodName]) {
        this[methodName]()
        this.title = modalTitle
      setAdminDisabled() {
        this.allUsersList = this.allUsersList.map(item => {
          return {
            ...item,
            disabled: item.username === 'admin'
          }
        })
      },
      handleModalClose() {
        this.visible = false
        this.hasLoadedDataTabKeyArray = []
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) {
          this[methodName]()
          this.title = modalTitle
        }
      }
    }
  }
}
</script>
<style scoped>
src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue
@@ -1,19 +1,19 @@
<template>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="工序名称" :span="2">{{currentLevelDetails.processName}}</a-descriptions-item>
    <a-descriptions-item label="工序号" :span="2">{{currentLevelDetails.processCode}}</a-descriptions-item>
    <a-descriptions-item label="工艺编号" :span="2">{{currentLevelDetails.craftNo}}</a-descriptions-item>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="工序名称">{{currentLevelDetails.processName}}</a-descriptions-item>
    <a-descriptions-item label="工序号">{{currentLevelDetails.processCode}}</a-descriptions-item>
    <a-descriptions-item label="工艺编号    ">{{currentLevelDetails.craftNo}}</a-descriptions-item>
    <a-descriptions-item label="工序类型">{{currentLevelDetails.processType}}</a-descriptions-item>
    <a-descriptions-item label="加工设备型号">{{currentLevelDetails.processingEquipmentModel}}</a-descriptions-item>
    <a-descriptions-item label="加工设备类型">{{currentLevelDetails.processingEquipmentOs}}</a-descriptions-item>
    <a-descriptions-item label="加工设备编号">{{currentLevelDetails.processingEquipmentCode}}</a-descriptions-item>
    <a-descriptions-item label="工装编号">{{currentLevelDetails.assembleStep}}</a-descriptions-item>
    <a-descriptions-item label="工装名称">{{currentLevelDetails.assembleName}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
    <a-descriptions-item label="工装名称    ">{{currentLevelDetails.assembleName}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createName}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateName}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
@@ -122,6 +122,7 @@
    created() {
      //备份model原始值
      this.modelDefault = JSON.parse(JSON.stringify(this.model))
      this.$bus.$on('sendAllDeviceList', deviceList => this.deviceList = deviceList)
    },
    methods: {
      add(params) {
src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue
@@ -1,5 +1,5 @@
<template>
  <a-descriptions bordered :size="size" :column="4">
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="工步名称">{{currentLevelDetails.stepName}}</a-descriptions-item>
    <a-descriptions-item label="工步号">{{currentLevelDetails.stepCode}}</a-descriptions-item>
    <a-descriptions-item label="工步类型">{{currentLevelDetails.stepType}}</a-descriptions-item>
@@ -7,12 +7,12 @@
    <a-descriptions-item label="加工设备类型">{{currentLevelDetails.processingEquipmentOs}}</a-descriptions-item>
    <a-descriptions-item label="加工设备编号">{{currentLevelDetails.deviceNo}}</a-descriptions-item>
    <a-descriptions-item label="工装编号">{{currentLevelDetails.assembleStep}}</a-descriptions-item>
    <a-descriptions-item label="工装名称">{{currentLevelDetails.assembleName}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
    <a-descriptions-item label="工装名称    " :span="2">{{currentLevelDetails.assembleName}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createName}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateName}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
@@ -1,12 +1,12 @@
<template>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="名称" :span="2">{{currentLevelDetails.productName}}</a-descriptions-item>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="名称">{{currentLevelDetails.productName}}</a-descriptions-item>
    <a-descriptions-item label="型号">{{currentLevelDetails.productModel}}</a-descriptions-item>
    <a-descriptions-item label="代码    ">{{currentLevelDetails.productNo}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createName}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateName}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
  </a-descriptions>
</template>
src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue
@@ -1,12 +1,12 @@
<template>
  <div style="height: 100%;max-height: 748px">
    <!--产品结构树右侧顶部区域-->
    <div style="height: 55%;overflow: hidden">
    <div style="height: 45%;overflow: hidden">
      <ProductStructureMainTop :size="tabContainerSize"/>
    </div>
    <!--产品结构树右侧底部区域-->
    <div style="height: 45%;overflow: hidden">
    <div style="height: 55%;overflow: hidden">
      <ProductStructureMainBottom :size="tabContainerSize"/>
    </div>
  </div>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
@@ -1,7 +1,6 @@
<template>
  <div v-if="+currentLevelInfo.type!==4" style="height: 100%">
    <a-tabs style="height: 100%" v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0"
            @change="handleTabChange">
  <div v-if="currentLevelInfo.type!==4">
    <a-tabs v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0" @change="handleTabChange">
      <a-tab-pane :key="1" tab="属性信息" v-if="+currentLevelInfo.type===1">
        <ProductInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      </a-tab-pane>
@@ -22,10 +21,8 @@
        <ProcessStepInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      </a-tab-pane>
      <!--系统参数配置中若参数为1时才展示对应层级的刀具列表-->
      <a-tab-pane :key="2" tab="刀具列表"
                  v-if="+currentLevelInfo.type===5&&isProcessHasCutterList||+currentLevelInfo.type===6&&isProcessStepHasCutterList">
        <CutterTableList ref="cutterTableListRef" :currentLevelInfo="currentLevelInfo" :size="containerSize"/>
      <a-tab-pane :key="2" tab="刀具信息" v-if="+currentLevelInfo.type===5||+currentLevelInfo.type===6">
        <CutterInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      </a-tab-pane>
      <template v-if="currentLevelInfo.hasOwnProperty('attributionType')">
@@ -60,19 +57,19 @@
import ComponentInfo from './Component/ComponentInfo'
import PartInfo from './Part/PartInfo'
import ProcessInfo from './Process/ProcessInfo'
import ProcessStepInfo from './ProcessStep/ProcessStepInfo'
import CutterTableList from './Cutter/CutterTableList'
import DocumentInfo from '../../../common/DocumentInfo'
import DocumentVersionTableList from '../../../common/DocumentVersionTableList'
import UseDocumentEquipmentTableList from './Document/UseNcDocumentEquipmentTableList'
import ProcessStepInfo from './ProcessStep/ProcessStepInfo'
import FilePreview from '../../../common/FilePreview'
import TableContextMenu from '../../../common/TableContextMenu'
import { getAction } from '@/api/manage'
import CutterInfo from '@views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue'
import dncApi from '@/api/dnc'
export default {
  name: 'ProductStructureMainBottom',
  components: {
    CutterTableList,
    CutterInfo,
    TableContextMenu,
    FilePreview,
    ProcessStepInfo,
@@ -88,8 +85,6 @@
    return {
      activeTabKey: 1,
      containerSize: 'small',
      isProcessHasCutterList: false,
      isProcessStepHasCutterList: false,
      currentLevelInfo: {},
      currentRightClickedTableRowInfo: {},
      hasLoadedDataTabKeyArray: []
@@ -99,47 +94,30 @@
    this.$bus.$on('sendCurrentClickedDocumentInfo', this.receiveCurrentLevelInfo)
    this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentLevelInfo)
    this.$bus.$on('reloadMainBottomTableData', this.reloadMainBottomTableData)
    this.getCutterListDisplayPermission('dnc_cutter_process', 'isProcessHasCutterList')
    this.getCutterListDisplayPermission('dnc_cutter_step', 'isProcessStepHasCutterList')
  },
  methods: {
    /**
     * èŽ·å–åˆ€å…·åˆ—è¡¨åœ¨å·¥åºå’Œå·¥æ­¥å±‚çº§çš„å±•ç¤ºæƒé™
     * @param settingKey å„层级展示权限key
     * @param dataProperty ç»„ä»¶data中的属性值用来控制是否展示
     */
    getCutterListDisplayPermission(settingKey, dataProperty) {
      getAction(`/system/sysParams/query/by/settingKey?settingKey=${settingKey}`).then(res => {
        if (res.success) {
          this[dataProperty] = res.result.settingValue === '1'
        }
      })
    },
    /**
     * æŽ¥æ”¶æ ‘组件以及表格传来的当前选中或点击的项信息
     * @param levelInfo å½“前层级信息
     */
    receiveCurrentLevelInfo(levelInfo) {
      this.currentLevelInfo = levelInfo
      const { id, type } = levelInfo
      dncApi.getProductStructureTreeNodeEntityApi({ id, type })
        .then(res => {
          if (res.success) {
            console.log('res-------------', res)
            this.currentLevelInfo = Object.assign(levelInfo, { entity: res.result[0] })
          }
        })
      this.activeTabKey = 1
      this.hasLoadedDataTabKeyArray = []
    },
    /**
     * tab栏切换时触发
     * @param activeTabKey å½“前激活的tabKey
     */
    handleTabChange(activeTabKey) {
      if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
        switch (activeTabKey) {
          case 2:
            if (this.currentLevelInfo.hasOwnProperty('attributionType')) {
              console.log('ref', this.$refs.filePreviewRef)
              this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
            } else {
              this.$nextTick(() => this.$refs.cutterTableListRef.setQueryParamAndLoadData(1))
            }
            this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
            break
          case 3:
            this.$nextTick(() => this.$refs.documentVersionTableRef.loadData())
@@ -194,6 +172,6 @@
}
/deep/ .ant-tabs-tabpane {
  overflow: hidden auto;
  overflow: auto;
}
</style>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
@@ -1,18 +1,10 @@
<template>
  <div v-if="+currentTreeNodeInfo.type!==4">
  <div v-if="currentTreeNodeInfo.type!==4">
    <a-tabs v-model="activeTabKey" @contextmenu.native="e=>e.preventDefault()" @change="handleTabChange"
            v-if="Object.keys(currentTreeNodeInfo).length!==0">
      <a-tab-pane :key="1" tab="NC管理" v-if="+currentTreeNodeInfo.type===5||+currentTreeNodeInfo.type===6">
        <div style="display: flex;">
          <!--系统参数配置中若参数为1时才展示对应层级的设备类列表-->
          <DeviceCustomTypeTableList
            v-if="+currentTreeNodeInfo.type===5&&isProcessHasDeviceTypeList||+currentTreeNodeInfo.type===6&&isProcessStepHasDeviceTypeList"
            ref="deviceCustomTypeTableList" :currentTreeNodeInfo="currentTreeNodeInfo"
            @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
          <NcDocumentTableList ref="ncDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
                               @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
        </div>
      <a-tab-pane :key="1" tab="NC文档" v-if="currentTreeNodeInfo.type===5||currentTreeNodeInfo.type===6">
        <NcDocumentTableList ref="ncDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
                             @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
      </a-tab-pane>
      <a-tab-pane :key="2" tab="其他文档">
@@ -29,426 +21,398 @@
</template>
<script>
import dncApi from '@/api/dnc'
import NcDocumentTableList from './Document/NcDocumentTableList'
import OtherDocumentTableList from './Document/OtherDocumentTableList'
import TableContextMenu from '../../../common/TableContextMenu'
import DocumentBatchDeleteModal from '../../../common/DocumentBatchDeleteModal'
import DeviceCustomTypeTableList
  from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue'
import { getAction } from '@api/manage'
  import dncApi from '@/api/dnc'
  import NcDocumentTableList from './Document/NcDocumentTableList'
  import OtherDocumentTableList from './Document/OtherDocumentTableList'
  import TableContextMenu from '../../../common/TableContextMenu'
  import DocumentBatchDeleteModal from '../../../common/DocumentBatchDeleteModal'
export default {
  name: 'ProductStructureMainTop',
  components: {
    DeviceCustomTypeTableList,
    DocumentBatchDeleteModal,
    TableContextMenu,
    OtherDocumentTableList,
    NcDocumentTableList
  },
  data() {
    return {
      activeTabKey: 2,
      tableContainerSize: 'small',
      isProcessHasDeviceTypeList: false,
      isProcessStepHasDeviceTypeList: false,
      currentRightClickedTableRowInfo: {},
      currentTreeNodeInfo: {},
      hasLoadedDataTabKeyArray: []
    }
  },
  created() {
    this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
    this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    this.getDeviceTypeListDisplayPermission('dnc_device_type_process', 'isProcessHasDeviceTypeList')
    this.getDeviceTypeListDisplayPermission('dnc_device_type_step', 'isProcessStepHasDeviceTypeList')
  },
  methods: {
    /**
     * èŽ·å–è®¾å¤‡ç±»åž‹åˆ—è¡¨åœ¨å·¥åºå’Œå·¥æ­¥å±‚çº§çš„å±•ç¤ºæƒé™
     * @param settingKey å„层级展示权限key
     * @param dataProperty ç»„ä»¶data中的属性值用来控制是否展示
     */
    getDeviceTypeListDisplayPermission(settingKey, dataProperty) {
      getAction(`/system/sysParams/query/by/settingKey?settingKey=${settingKey}`).then(res => {
        if (res.success) {
          this[dataProperty] = res.result.settingValue === '1'
  export default {
    name: 'ProductStructureMainTop',
    components: { DocumentBatchDeleteModal, TableContextMenu, OtherDocumentTableList, NcDocumentTableList },
    data() {
      return {
        activeTabKey: 2,
        tableContainerSize: 'small',
        currentRightClickedTableRowInfo: {},
        currentTreeNodeInfo: {},
        hasLoadedDataTabKeyArray: []
      }
    },
    created() {
      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
      this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      /**
       * æŽ§åˆ¶å³é”®èœå•开启
       * @param record å½“前表格行信息
       */
      handleTableContextMenuOpen(record) {
        this.currentRightClickedTableRowInfo = Object.assign({}, record)
        console.log('currentRightClickedTableRowInfo', this.currentRightClickedTableRowInfo)
        this.$refs.tableContextMenuRef.currentMenuLevel = record.param
        this.$refs.tableContextMenuRef.menuStyle.top = event.clientY + 'px'
        this.$refs.tableContextMenuRef.menuStyle.left = event.clientX + 'px'
        this.$refs.tableContextMenuRef.menuVisible = true
        document.body.addEventListener('click', this.handleMenuClose)
      },
      /**
       * æŽ¥æ”¶æ ‘组件传来的当前选中的树节点信息
       * @param treeNodeInfo æ ‘节点信息
       */
      receiveCurrentTreeNodeInfo(treeNodeInfo) {
        // ä»Žæ ‘组件接受树节点信息后从父组件流入子组件
        this.currentTreeNodeInfo = treeNodeInfo
        // æ¸…空上一节点已经加载过得文档列表tabKey
        this.hasLoadedDataTabKeyArray = []
        if (treeNodeInfo.type === 5 || treeNodeInfo.type === 6) {
          this.activeTabKey = 1
          this.$nextTick(() => {
            if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
          })
        } else {
          this.activeTabKey = 2
          this.$nextTick(() => {
            if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
          })
        }
      })
    },
        this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
      },
    /**
     * æŽ¥æ”¶æ ‘组件传来的当前选中的树节点信息
     * @param treeNodeInfo æ ‘节点信息
     */
    receiveCurrentTreeNodeInfo(treeNodeInfo) {
      console.log('treeNodeInfo', treeNodeInfo)
      // ä»Žæ ‘组件接受树节点信息后从父组件流入子组件
      this.currentTreeNodeInfo = treeNodeInfo
      // æ¸…空上一节点已经加载过得文档列表tabKey
      this.hasLoadedDataTabKeyArray = []
      if (+treeNodeInfo.type === 5 || +treeNodeInfo.type === 6) {
        this.activeTabKey = 1
        this.$nextTick(() => {
          if (this.$refs.deviceCustomTypeTableList) this.$refs.deviceCustomTypeTableList.setQueryParamAndLoadData()
          else if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
        })
      } else {
        this.activeTabKey = 2
        this.$nextTick(() => {
      /**
       * tab栏切换时触发
       * @param activeTabKey åˆ‡æ¢åŽçš„tabKey
       */
      handleTabChange(activeTabKey) {
        if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
          this.$nextTick(() => {
            if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
          })
          // é˜»æ­¢æŽ¥å£åœ¨åŒä¸€æ–‡æ¡£ä¸€æ¬¡ç‚¹å‡»å†…多次触发
          this.hasLoadedDataTabKeyArray.push(activeTabKey)
        }
      },
      /**
       * æ–‡æ¡£ä»¥åŠNC程序导入/出库/入库成功后触发重新加载文档列表
       * @param docClassCode æ–‡æ¡£ç±»åˆ«
       * @param attributionId èŠ‚ç‚¹Id
       */
      reloadDocumentListData({ docClassCode, attributionId }) {
        // å¦‚果上传的文档不是所属于当前所展示节点的文档则不重新获取文档列表
        if (this.currentTreeNodeInfo.id !== attributionId) return
        if (docClassCode === 'NC') {
          if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
        } else {
          if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
        })
      }
      this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
    },
        }
      },
    /**
     * æŽ§åˆ¶å³é”®èœå•开启
     * @param record å½“前表格行信息
     */
    handleTableContextMenuOpen(record) {
      this.currentRightClickedTableRowInfo = Object.assign({}, record)
      console.log('currentRightClickedTableRowInfo', this.currentRightClickedTableRowInfo)
      this.$refs.tableContextMenuRef.currentMenuLevel = record.param
      this.$refs.tableContextMenuRef.menuStyle.top = event.clientY + 'px'
      this.$refs.tableContextMenuRef.menuStyle.left = event.clientX + 'px'
      this.$refs.tableContextMenuRef.menuVisible = true
      document.body.addEventListener('click', this.handleMenuClose)
    },
    /**
     * tab栏切换时触发
     * @param activeTabKey åˆ‡æ¢åŽçš„tabKey
     */
    handleTabChange(activeTabKey) {
      if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
        this.$nextTick(() => {
          if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
        })
        // é˜»æ­¢æŽ¥å£åœ¨åŒä¸€æ–‡æ¡£ä¸€æ¬¡ç‚¹å‡»å†…多次触发
        this.hasLoadedDataTabKeyArray.push(activeTabKey)
      }
    },
    /**
     * æ–‡æ¡£ä»¥åŠNC程序导入/出库/入库成功后触发重新加载文档列表
     * @param docClassCode æ–‡æ¡£ç±»åˆ«
     * @param attributionId èŠ‚ç‚¹Id
     */
    reloadDocumentListData({ docClassCode, attributionId }) {
      // å¦‚果上传的文档不是所属于当前所展示节点的文档则不重新获取文档列表
      if (this.currentTreeNodeInfo.id !== attributionId) return
      if (docClassCode === 'NC') {
        if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
      } else {
        if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
      }
    },
    // ä¸‹è½½å½“前右键选中文档
    handleDownload() {
      const that = this
      const { docId, docName } = this.currentRightClickedTableRowInfo
      dncApi.downloadDocumentApi({ docId, docName })
        .then(res => {
          if (res && !res.success) {
      // ä¸‹è½½å½“前右键选中文档
      handleDownload() {
        const that = this
        const { docId, docName } = this.currentRightClickedTableRowInfo
        dncApi.downloadDocumentApi({ docId, docName })
          .then(res => {
            if (res && !res.success) {
              that.$notification.error({
                message: '消息',
                description: res.message
              })
            }
          })
          .catch(err => {
            that.$notification.error({
              message: '消息',
              description: res.message
              description: err.message
            })
          })
      },
      // åˆ é™¤å½“前右键选中文档
      handleDelete() {
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        const that = this
        that.$confirm({
          title: '提示',
          content: `删除后不可取消,确认删除吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.deleteDocumentApi(docId)
              .then((res) => {
                if (res.success) {
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                  that.reloadDocumentListData({ docClassCode: param, attributionId })
                } else {
                  that.$notification.warning({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
        .catch(err => {
          that.$notification.error({
            message: '消息',
            description: err.message
          })
      },
      /**
       * ç‚¹å‡»æ‰¹é‡åˆ é™¤åŽå‡ºçŽ°å¼¹çª—
       * @param modalTitle å¼¹çª—标题
       */
      handleBatchRemove(modalTitle) {
        if (!this.$refs.documentBatchDeleteModalRef) return
        this.$refs.documentBatchDeleteModalRef.title = modalTitle
        this.$refs.documentBatchDeleteModalRef.visible = true
      },
      /**
       * å‡ºåº“当前右键选中文档
       * @param menuLabel
       */
      handlePull(menuLabel) {
        const that = this
        const { docId, docName, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentOutboundApi({ docId, docName })
              .then(res => {
                console.log('res------------------', res)
                if (res.success) {
                  that.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: `${menuLabel}成功`
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
    },
      },
    // åˆ é™¤å½“前右键选中文档
    handleDelete() {
      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
      const that = this
      that.$confirm({
        title: '提示',
        content: `删除后不可取消,确认删除吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.deleteDocumentApi(docId)
            .then((res) => {
              if (res.success) {
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
                that.reloadDocumentListData({ docClassCode: param, attributionId })
              } else {
                that.$notification.warning({
                  message: '消息',
                  description: res.message
                })
              }
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel: () => {
          that.$destroyAll()
        }
      })
    },
    /**
     * ç‚¹å‡»æ‰¹é‡åˆ é™¤åŽå‡ºçŽ°å¼¹çª—
     * @param modalTitle å¼¹çª—标题
     */
    handleBatchRemove(modalTitle) {
      if (!this.$refs.documentBatchDeleteModalRef) return
      this.$refs.documentBatchDeleteModalRef.title = modalTitle
      this.$refs.documentBatchDeleteModalRef.visible = true
    },
    /**
     * å‡ºåº“当前右键选中文档
     * @param menuLabel
     */
    handlePull(menuLabel) {
      const that = this
      const { docId, docName, param, attributionId } = this.currentRightClickedTableRowInfo
      that.$confirm({
        title: '提示',
        content: `确认${menuLabel}吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.documentOutboundApi({ docId, docName })
            .then(res => {
              console.log('res------------------', res)
              if (res.success) {
                that.reloadDocumentListData({ docClassCode: param, attributionId })
                that.$notification.success({
                  message: '消息',
                  description: `${menuLabel}成功`
                })
              } else {
      /**
       * å–消出库当前右键选中文档
       * @param menuLabel
       */
      handleCancelPull(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentCancelOutboundApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: res.message
                  description: err.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel: () => {
          that.$destroyAll()
        }
      })
    },
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
    /**
     * å–消出库当前右键选中文档
     * @param menuLabel
     */
    handleCancelPull(menuLabel) {
      const that = this
      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
      that.$confirm({
        title: '提示',
        content: `确认${menuLabel}吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.documentCancelOutboundApi(docId)
            .then(res => {
              if (res.success) {
                this.reloadDocumentListData({ docClassCode: param, attributionId })
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
              } else {
      /**
       * å‘布当前右键选中文档
       * @param menuLabel
       */
      handlePublish(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentPublishApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  this.$bus.$emit('reloadMainBottomTableData', 'documentVersion')
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: res.message
                  description: err.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel() {
          that.$destroyAll()
        }
      })
    },
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
    /**
     * å‘布当前右键选中文档
     * @param menuLabel
     */
    handlePublish(menuLabel) {
      const that = this
      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
      that.$confirm({
        title: '提示',
        content: `确认${menuLabel}吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.documentPublishApi(docId)
            .then(res => {
              if (res.success) {
                this.reloadDocumentListData({ docClassCode: param, attributionId })
                this.$bus.$emit('reloadMainBottomTableData', 'documentVersion')
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
              } else {
      /**
       * é‡æ–°å‘布当前右键选中文档并重新发布退回上一文档版本
       * @param menuLabel
       */
      handleRepublish(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentRepublishApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: res.message
                  description: err.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel() {
          that.$destroyAll()
        }
      })
    },
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
    /**
     * é‡æ–°å‘布当前右键选中文档并重新发布退回上一文档版本
     * @param menuLabel
     */
    handleRepublish(menuLabel) {
      const that = this
      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
      that.$confirm({
        title: '提示',
        content: `确认${menuLabel}吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.documentRepublishApi(docId)
            .then(res => {
              if (res.success) {
                this.reloadDocumentListData({ docClassCode: param, attributionId })
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
              } else {
      /**
       * é‡å½’档当前右键选中文档且后续无法继续发布或归档
       * @param menuLabel
       */
      handlePigeonhole(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `${menuLabel}后不可取消,确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentPigeonholeApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: res.message
                  description: err.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel() {
          that.$destroyAll()
        }
      })
    },
    /**
     * é‡å½’档当前右键选中文档且后续无法继续发布或归档
     * @param menuLabel
     */
    handlePigeonhole(menuLabel) {
      const that = this
      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
      that.$confirm({
        title: '提示',
        content: `${menuLabel}后不可取消,确认${menuLabel}吗?`,
        okText: '确认',
        cancelText: '取消',
        onOk: () => {
          dncApi.documentPigeonholeApi(docId)
            .then(res => {
              if (res.success) {
                this.reloadDocumentListData({ docClassCode: param, attributionId })
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
              } else {
                that.$notification.error({
                  message: '消息',
                  description: res.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              .finally(() => {
                that.$destroyAll()
              })
            })
            .finally(() => {
              that.$destroyAll()
            })
        },
        onCancel() {
          that.$destroyAll()
        }
      })
    },
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
    // æŽ§åˆ¶å³é”®èœå•关闭
    handleMenuClose() {
      this.$refs.tableContextMenuRef.menuVisible = false
      document.body.removeEventListener('click', this.handleMenuClose)
    },
      // æŽ§åˆ¶å³é”®èœå•关闭
      handleMenuClose() {
        this.$refs.tableContextMenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleMenuClose)
      },
    triggerCorrespondingMethod({ methodName, modalTitle }) {
      if (this[methodName]) this[methodName](modalTitle)
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) this[methodName](modalTitle)
      }
    }
  }
}
</script>
<style scoped>
/deep/ .ant-table-tbody .ant-table-row {
  cursor: pointer;
}
  /deep/ .ant-table-tbody .ant-table-row {
    cursor: pointer;
  }
</style>
src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue
@@ -2,26 +2,24 @@
  <a-card class="tree_con" :loading="cardLoading" :bordered="false" @contextmenu.native="e=>e.preventDefault()">
    <a-spin :spinning="loading">
      <div style="display: flex;flex-direction: column;height: 100%">
        <div style="display: flex;justify-content: space-between">
        <div style="display: flex">
          <a-input placeholder="输入关键字进行搜索" allowClear v-model="searchInput"
                   @change="handleSearchInputChange"/>
          <a-tooltip title="刷新">
            <a-button icon="reload" @click="getTreeDataByApi" style="width: 18%;margin-left: 8px"></a-button>
          </a-tooltip>
          <a-button type="primary" v-has="'product_add'" icon="plus" style="margin-left: 8px"
          <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-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>
        <!--产品结构树-->
@@ -29,9 +27,9 @@
          <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, key:treeKey,type}">
            <template slot="title" slot-scope="{ label, parentId, entity, key:treeKey,type}">
              <ProductStructureTreeContextMenu ref="contextMenuRef"
                                               :treeParams="{label,treeKey,searchValue,type}"/>
                                               :treeParams="{label,treeKey,searchValue,type,entity}"/>
            </template>
            <a-icon slot="switcherIcon" type="down"/>
@@ -75,12 +73,10 @@
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'
export default {
  name: 'ProductStructureTree',
  components: {
    DeviceCustomTypeModal,
    AssignPermissionModal,
    ProcessStepModal,
    ProcessModal,
@@ -104,6 +100,7 @@
      autoExpandParent: true,
      checkStrictly: true,
      allTreeKeys: [],
      currentSelected: {},
      rightClickSelected: {},
      url: {
        delete: '/nc/product/delete'
@@ -118,10 +115,10 @@
    getTreeDataByApi() {
      this.loading = true
      this.cardLoading = true
      this.treeDataSource = []
      dncApi.getProductStructureTreeApi()
        .then(res => {
          if (res.success) {
            console.log('res=================', res)
            this.dataList = []
            this.allTreeKeys = []
            this.treeDataSource = res.result
@@ -143,62 +140,22 @@
     * @param {node} node èŠ‚ç‚¹å¯¹è±¡
     */
    handleTreeSelect(selectedKeys, { node }) {
      const that = this
      let record = node.dataRef
      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
            })
          }
        })
      this.currentSelected = Object.assign({}, record)
      // å‘右侧父级组件发送当前选中树节点信息
      this.$bus.$emit('sendCurrentTreeNodeInfo', this.currentSelected)
      if (selectedKeys.length === 0) return
      this.selectedKeys = selectedKeys
    },
    /**
     * æ ‘节点右键单击节点时触发
     * @param event äº‹ä»¶å¯¹è±¡
     * @param node èŠ‚ç‚¹å¯¹è±¡
     */
    handleTreeRightClick({ node }) {
      const that = this
    handleTreeRightClick({ event, node }) {
      const record = node.dataRef
      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
            })
          }
        })
      this.rightClickSelected = Object.assign({}, record)
    },
    // æ ‘节点右键单击菜单中删除按钮时触发
@@ -259,18 +216,8 @@
      this.autoExpandParent = false
    },
    // è¾“入查询内容变化时触发(增加防抖机制)
    /* è¾“入查询内容变化时触发 */
    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
@@ -290,6 +237,7 @@
        expandedKeys = this.beforeSearchExpandedKeys
        autoExpandParent = false
      }
      Object.assign(this, {
        expandedKeys,
        searchValue: search,
@@ -344,7 +292,7 @@
     * @param treeNode
     */
    setTreeNodeIcon(treeNode) {
      switch (+treeNode.type) {
      switch (treeNode.type) {
        case 1:
          treeNode.slots = { icon: 'product' }
          break
src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue
@@ -1,20 +1,14 @@
<template>
  <a-dropdown :trigger="['contextmenu']">
    <span v-if="treeParams.label.indexOf(treeParams.searchValue) > -1">{{
        treeParams.label.substr(0, treeParams.label.indexOf(treeParams.searchValue))
      }}<span
        class="replaceSearch">{{
          treeParams.searchValue
        }}</span>{{
        treeParams.label.substr(treeParams.label.indexOf(treeParams.searchValue) + treeParams.searchValue.length)
      }}</span>
    <span v-if="treeParams.label.indexOf(treeParams.searchValue) > -1">{{ treeParams.label.substr(0, treeParams.label.indexOf(treeParams.searchValue)) }}<span
      class="replaceSearch">{{ treeParams.searchValue }}</span>{{ treeParams.label.substr(treeParams.label.indexOf(treeParams.searchValue) + treeParams.searchValue.length) }}</span>
    <span v-else>{{ treeParams.label }}</span>
    <template #overlay>
      <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeParams.treeKey, menuKey)"
              @contextmenu="event=>event.preventDefault()">
        <a-menu-item v-for="item in defaultContextMenuList[getCurrentMenuLevel]" :key="item.code" v-has="item.code">
          <a-icon :type="item.icon"/>
          {{ item.label }}
          {{item.label}}
        </a-menu-item>
      </a-menu>
    </template>
@@ -22,144 +16,141 @@
</template>
<script>
export default {
  name: 'ProductStructureTreeContextMenu',
  components: {},
  props: {
    treeParams: {
      type: Object
    }
  },
  data() {
    return {
      defaultContextMenuList: {
        //产品
        product: [
          { label: '添加产品', code: 'product_add', icon: 'plus', isCommonMethod: false },
          { label: '添加部件', code: 'product_add_child', icon: 'plus', isCommonMethod: false },
          { label: '编辑产品信息', code: 'product_edit', icon: 'edit', isCommonMethod: false },
          // {  label: '导出文档', code: 'product_export', icon: 'export', isCommonMethod: true },
          { label: '导入其他文档', code: 'product_import', icon: 'import', isCommonMethod: true },
          { label: '删除', code: 'product_delete', icon: 'delete', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ],
        //部件
        component: [
          { label: '添加子部件', code: 'component_add', icon: 'plus', isCommonMethod: false },
          { label: '添加零件', code: 'component_add_child', icon: 'plus', isCommonMethod: false },
          { label: '创建工序', code: 'component_add_relative', icon: 'plus', isCommonMethod: false },
          { label: '编辑部件信息', code: 'component_edit', icon: 'edit', isCommonMethod: false },
          // {  label: '导出文档', code: 'component_export', icon: 'export', isCommonMethod: true },
          { label: '导入其他文档', code: 'component_import', icon: 'import', isCommonMethod: true },
          { label: '删除', code: 'component_delete', icon: 'delete', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ],
        //零件
        part: [
          { label: '添加零件', code: 'parts_add', icon: 'plus', isCommonMethod: false },
          { label: '创建工艺规程版本', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
          // { label: '创建工序', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
          { label: '编辑零件信息', code: 'parts_edit', icon: 'edit', isCommonMethod: false },
          // {  label: '导出文档', code: 'parts_export', icon: 'export', isCommonMethod: true },
          { label: '导入其他文档', code: 'parts_import', icon: 'import', isCommonMethod: true },
          { label: '删除', code: 'parts_delete', icon: 'delete', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ],
        //工艺规程版本
        processSpecVersion: [
          { label: '创建工艺规程版本', code: 'version_add', icon: 'plus', isCommonMethod: false },
          { label: '创建工序', code: 'version_add_child', icon: 'plus', isCommonMethod: false },
          { label: '编辑工艺规程版本信息', code: 'version_edit', icon: 'edit', isCommonMethod: false },
          { label: '删除', code: 'version_delete', icon: 'delete', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ],
        //工序
        process: [
          { label: '创建工序', code: 'process_add', icon: 'plus', isCommonMethod: false },
          { label: '创建工步', code: 'process_add_child', icon: 'plus', isCommonMethod: false },
          { label: '添加设备类', code: 'process_add_type', icon: 'plus', isCommonMethod: true },
          { label: '编辑工序信息', code: 'process_edit', icon: 'edit', isCommonMethod: false },
          { label: '删除', code: 'process_delete', icon: 'delete', isCommonMethod: true },
          // {  label: '导出NC程序', code: 'process_export', icon: 'export', isCommonMethod: true },
          { label: '导入NC程序', code: 'process_import', icon: 'import', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ],
        //工步
        processStep: [
          { label: '创建工步', code: 'processStep_add', icon: 'plus', isCommonMethod: false },
          { label: '编辑工步信息', code: 'processStep_edit', icon: 'edit', isCommonMethod: false },
          { label: '添加设备类', code: 'processStep_add_type', icon: 'plus', isCommonMethod: true },
          { label: '删除', code: 'processStep_delete', icon: 'delete', isCommonMethod: true },
          // {  label: '导出NC程序', code: 'processStep_export', icon: 'import', isCommonMethod: true },
          { label: '导入NC程序', code: 'processStep_import', icon: 'import', isCommonMethod: true },
          { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
        ]
      }
    }
  },
  computed: {
    getCurrentMenuLevel() {
      switch (+this.treeParams.type) {
        case 1:
          return 'product'
        case 2:
          return 'component'
        case 3:
          return 'part'
        case 4:
          return 'processSpecVersion'
        case 5:
          return 'process'
        case 6:
          return 'processStep'
  export default {
    name: 'ProductStructureTreeContextMenu',
    components: {},
    props: {
      treeParams: {
        type: Object
      }
    },
    getCurrentDocClassCode() {
      switch (+this.treeParams.type) {
        case 1:
          return 'OTHER'
        case 2:
          return 'OTHER'
        case 3:
          return 'OTHER'
        case 5:
          return 'NC'
        case 6:
          return 'NC'
    data() {
      return {
        defaultContextMenuList: {
          //产品
          product: [
            { label: '添加产品', code: 'product_add', icon: 'plus', isCommonMethod: false },
            { label: '添加部件', code: 'product_add_child', icon: 'plus', isCommonMethod: false },
            { label: '编辑产品信息', code: 'product_edit', icon: 'edit', isCommonMethod: false },
            // {  label: '导出文档', code: 'product_export', icon: 'export', isCommonMethod: true },
            { label: '导入其他文档', code: 'product_import', icon: 'import', isCommonMethod: true },
            { label: '删除', code: 'product_delete', icon: 'delete', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //部件
          component: [
            { label: '添加子部件', code: 'component_add', icon: 'plus', isCommonMethod: false },
            { label: '添加零件', code: 'component_add_child', icon: 'plus', isCommonMethod: false },
            { label: '创建工序', code: 'component_add_relative', icon: 'plus', isCommonMethod: false },
            { label: '编辑部件信息', code: 'component_edit', icon: 'edit', isCommonMethod: false },
            // {  label: '导出文档', code: 'component_export', icon: 'export', isCommonMethod: true },
            { label: '导入其他文档', code: 'component_import', icon: 'import', isCommonMethod: true },
            { label: '删除', code: 'component_delete', icon: 'delete', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //零件
          part: [
            { label: '添加零件', code: 'parts_add', icon: 'plus', isCommonMethod: false },
            { label: '创建工艺规程版本', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
            // { label: '创建工序', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
            { label: '编辑零件信息', code: 'parts_edit', icon: 'edit', isCommonMethod: false },
            // {  label: '导出文档', code: 'parts_export', icon: 'export', isCommonMethod: true },
            { label: '导入其他文档', code: 'parts_import', icon: 'import', isCommonMethod: true },
            { label: '删除', code: 'parts_delete', icon: 'delete', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //工艺规程版本
          processSpecVersion: [
            { label: '创建工艺规程版本', code: 'version_add', icon: 'plus', isCommonMethod: false },
            { label: '创建工序', code: 'version_add_child', icon: 'plus', isCommonMethod: false },
            { label: '编辑工艺规程版本信息', code: 'version_edit', icon: 'edit', isCommonMethod: false },
            { label: '删除', code: 'version_delete', icon: 'delete', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //工序
          process: [
            { label: '创建工序', code: 'process_add', icon: 'plus', isCommonMethod: false },
            { label: '创建工步', code: 'process_add_child', icon: 'plus', isCommonMethod: false },
            { label: '编辑工序信息', code: 'process_edit', icon: 'edit', isCommonMethod: false },
            { label: '删除', code: 'process_delete', icon: 'delete', isCommonMethod: true },
            // {  label: '导出NC程序', code: 'process_export', icon: 'export', isCommonMethod: true },
            { label: '导入NC程序', code: 'process_import', icon: 'import', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //工步
          processStep: [
            { label: '创建工步', code: 'processStep_add', icon: 'plus', isCommonMethod: false },
            { label: '编辑工步信息', code: 'processStep_edit', icon: 'edit', isCommonMethod: false },
            { label: '删除', code: 'processStep_delete', icon: 'delete', isCommonMethod: true },
            // {  label: '导出NC程序', code: 'processStep_export', icon: 'import', isCommonMethod: true },
            { label: '导入NC程序', code: 'processStep_import', icon: 'import', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ]
        }
      }
    }
  },
  methods: {
    onContextMenuClick(treeKey, menuKey) {
      const level = this.getCurrentMenuLevel
      const param = this.getCurrentDocClassCode
      console.log('level---------------------', level)
      console.log('param---------------------', param)
      const treeNodeInfo = Object.assign({}, this.treeParams, { param })
      console.log('treeNodeInfo******************', treeNodeInfo)
      const menuKeyArray = menuKey.split('_')
      const isCommonMethod = this.defaultContextMenuList[level].find(item => item.code === menuKey).isCommonMethod
      // product_add => handleAdd è§¦å‘对应组件事件
      let methodName
      // åˆ¤æ–­æ˜¯å¦ä¸ºå…¬å…±æ–¹æ³•,如果为公共方法则截取专有属性product/component/part/process等字段
      if (isCommonMethod) {
        methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).slice(1).join('')
      } else {
        methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).join('')
    },
    computed: {
      getCurrentMenuLevel() {
        switch (this.treeParams.type) {
          case 1:
            return 'product'
          case 2:
            return 'component'
          case 3:
            return 'part'
          case 4:
            return 'processSpecVersion'
          case 5:
            return 'process'
          case 6:
            return 'processStep'
        }
      },
      getCurrentDocClassCode() {
        switch (this.treeParams.type) {
          case 1:
            return 'OTHER'
          case 2:
            return 'OTHER'
          case 3:
            return 'OTHER'
          case 5:
            return 'NC'
          case 6:
            return 'NC'
        }
      }
      console.log('methodName', methodName)
      const modalTitle = this.defaultContextMenuList[level].find(item => item.code === menuKey).label
      this.$bus.$emit('treeMenuItemMethodTrigger', { methodName, modalTitle, treeNodeInfo })
    },
    methods: {
      onContextMenuClick(treeKey, menuKey) {
        const level = this.getCurrentMenuLevel
        const param = this.getCurrentDocClassCode
        console.log('level---------------------', level)
        console.log('param---------------------', param)
        const treeNodeInfo = Object.assign({}, this.treeParams, { param })
        console.log('treeNodeInfo******************', treeNodeInfo)
        const menuKeyArray = menuKey.split('_')
        const isCommonMethod = this.defaultContextMenuList[level].find(item => item.code === menuKey).isCommonMethod
        // product_add => handleAdd è§¦å‘对应组件事件
        let methodName
        // åˆ¤æ–­æ˜¯å¦ä¸ºå…¬å…±æ–¹æ³•,如果为公共方法则截取专有属性product/component/part/process等字段
        if (isCommonMethod) {
          methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).slice(1).join('')
        } else {
          methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).join('')
        }
        const modalTitle = this.defaultContextMenuList[level].find(item => item.code === menuKey).label
        this.$bus.$emit('treeMenuItemMethodTrigger', { methodName, modalTitle, treeNodeInfo })
      }
    }
  }
}
</script>
<style scoped>
.replaceSearch {
  color: #40a9ff;
  font-weight: bold;
  background-color: rgb(204, 204, 204);
}
  .replaceSearch {
    color: #40a9ff;
    font-weight: bold;
    background-color: rgb(204, 204, 204);
  }
</style>
src/views/dnc/common/TableContextMenu.vue
@@ -41,12 +41,6 @@
        },
        currentMenuLevel: '',
        defaultContextMenuList: {
          //设备类
          deviceCustomType:[
            { label: '编辑设备类信息', code: 'type_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
            { label: '删除', code: 'type_delete', subMenu: [], icon: 'delete', isCommonMethod: false },
            { label: '导入NC程序', code: 'type_document_import', subMenu: [], icon: 'import', isCommonMethod: true },
          ],
          //NC文档
          NC: [
            { label: '编辑文档信息', code: 'document_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
src/views/system/modules/UserModal.vue
@@ -376,12 +376,11 @@
        validatorRules: {
          username: [{ required: true, message: '请输入用户账号!' },
            { validator: this.validateUsername }],
          password: [
          //   {
          //   required: true,
          //   pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
          //   message: '密码由8位数字、大小写字母和特殊符号组成!'
          // },
          password: [{
            required: true,
            pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
            message: '密码由8位数字、大小写字母和特殊符号组成!'
          },
            { validator: this.validateToNextPassword, trigger: 'change' }],
          confirmpassword: [{ required: true, message: '请重新输入登录密码!' },
            { validator: this.compareToFirstPassword }],