lyh
2025-03-14 9737ae6cbdf64098554dc99e743a52669adb8138
Revert "1、设备类管理页面完成增删改查功能"

This reverts commit bc55e59f49229ffa77d2b32dd9fd0a9b6049b9b8.
已添加9个文件
已修改19个文件
已删除1个文件
2917 ■■■■ 文件已修改
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 207 ●●●● 补丁 | 查看 | 原始文档 | 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 746 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue 275 ●●●● 补丁 | 查看 | 原始文档 | 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,30 +51,32 @@
  appointCurrentDocumentVersionApi: fileId => putAction(`/nc/file/assign/version/${fileId}`),
  // æ–‡æ¡£æ¯”对
  fileCompareApi: fileIdArray => getAction(`/nc/file/comparison/${fileIdArray[0]}/${fileIdArray[1]}`),
  // èŽ·å–æ‰€æœ‰éƒ¨é—¨åˆ—è¡¨
  getAllDepartmentsListApi: () => getAction('/ucenter/depart/list/all'),
  // èŽ·å–æ‰€æœ‰ç”¨æˆ·åˆ—è¡¨
  // æƒé™é…ç½®å¼¹çª—中获取所有车间列表
  getAllDepartmentsListApi: () => getAction('/mdc/mdcProduction/queryTreeListByConfig'),
  // æƒé™é…ç½®å¼¹çª—中获取所有用户列表
  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 }),
  //-------------------------设备结构树------------------------------------------------
  // èŽ·å–è®¾å¤‡æ ‘
@@ -90,5 +92,8 @@
  // ç§»é™¤ç”¨æˆ·æƒé™
  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
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,189 @@
<template>
  <a-card :bordered="false">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="4" :sm="4">
            <a-form-item label="车间">
              <a-select v-model="queryParam.productionId" placeholder="请选择车间">
                <a-select-option v-for="item in workshopTreeData" :key="item.id">
                  {{ item.productionName }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4">
            <a-form-item label="设备类名称">
              <a-input placeholder="请输入设备类名称" v-model="queryParam.deviceManagementName"></a-input>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4">
            <a-space>
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="primary" @click="searchReset" icon="reload">重置</a-button>
            </a-space>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
    <div class="table-operator" style="border-top: 5px">
      <a-button @click="handleAdd" type="primary" icon="plus">添加设备类</a-button>
      <!--      <a-button type="primary" icon="download" @click="handleExportXls('设备类信息')">导出</a-button>-->
      <a-dropdown v-if="selectedRowKeys.length > 0">
        <a-menu slot="overlay" @click="handleMenuClick">
          <a-menu-item key="1">
            <a-icon type="delete" @click="batchDel"/>
            åˆ é™¤
          </a-menu-item>
        </a-menu>
        <a-button style="margin-left: 8px">
          æ‰¹é‡æ“ä½œ
          <a-icon type="down"/>
        </a-button>
      </a-dropdown>
    </div>
    <!-- table区域-begin -->
    <div>
      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
        <i class="anticon anticon-info-circle ant-alert-icon"></i>已选择&nbsp;<a style="font-weight: 600">{{
          selectedRowKeys.length
        }}</a>项&nbsp;&nbsp;
        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
      </div>
      <a-table
        ref="table"
        bordered
        size="middle"
        rowKey="id"
        :scroll="{y:465}"
        :columns="columns"
        :dataSource="dataSource"
        :pagination="ipagination"
        :loading="loading"
        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
        @change="handleTableChange">
        <template slot="action" slot-scope="text, record">
          <a @click="handleEdit(record)">编辑</a>
          <a-divider type="vertical"/>
          <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
            <a>删除</a>
          </a-popconfirm>
        </template>
      </a-table>
    </div>
    <!-- table区域-end -->
    <DeviceCustomTypeManagementModal ref="modalForm" :workshopTreeData="workshopTreeData" @ok="loadData"/>
  </a-card>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import dncApi from '@/api/dnc'
import DeviceCustomTypeManagementModal
  from '@views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue'
export default {
  name: 'DeviceCustomTypeManagement',
  mixins: [JeecgListMixin],
  components: {
    DeviceCustomTypeManagementModal
  },
  data() {
    return {
      columns: [
        {
          title: '#',
          dataIndex: '',
          key: 'rowIndex',
          width: 60,
          align: 'center',
          customRender: function(t, r, index) {
            return parseInt(index) + 1
          }
        },
        {
          title: '车间',
          align: 'center',
          width: 200,
          dataIndex: 'productionId_dictText'
        },
        {
          title: '设备类',
          align: 'center',
          width: 200,
          dataIndex: 'deviceManagementCode'
        },
        {
          title: '设备类名称',
          align: 'center',
          width: 200,
          dataIndex: 'deviceManagementName'
        },
        {
          title: '设备组编号',
          align: 'center',
          dataIndex: 'equipmentIds',
          width: 400,
          ellipsis: true
        },
        {
          title: '操作',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' },
          align: 'center',
          width: 80
        }
      ],
      url: {
        list: '/nc/deviceManagement/query',
        delete: '/nc/deviceManagement/delete',
        deleteBatch: '/nc/deviceManagement/deleteBatch'
      },
      workshopTreeData: []
    }
  },
  created() {
    this.getWorkshopListByApi()
  },
  methods: {
    // è°ƒç”¨æŽ¥å£èŽ·å–æŸ¥è¯¢åŒºåŸŸè½¦é—´æ ‘åˆ—è¡¨
    getWorkshopListByApi() {
      dncApi.getHasPermissionWorkshopTreeApi()
        .then(res => {
          if (res.success) {
            this.workshopTreeData = res.result
          }
        })
    },
    handleAdd: function() {
      this.$refs.modalForm.add()
      this.$refs.modalForm.title = '新增'
      this.$refs.modalForm.disabledEdit = false
    },
    handleEdit: function(record) {
      this.$refs.modalForm.edit(record)
      this.$refs.modalForm.title = '编辑'
      this.$refs.modalForm.disabledEdit = true
    },
    handleMenuClick(e) {
      if (e.key == 1) {
        this.batchDel()
      }
    }
  }
}
</script>
src/views/dnc/base/ProductStructure.vue
@@ -11,30 +11,35 @@
    <!--导入文件公共弹窗-->
    <ImportFileModal/>
    <!--新增或编辑设备类公共弹窗-->
    <DeviceCustomTypeModal/>
  </a-card>
</template>
<script>
  import ProductStructureTree from './modules/ProductStructure/ProductStructureTree'
  import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
  import ImportFileModal from '../common/ImportFileModal'
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'
  export default {
    name: 'ProductStructure',
    components: {
      ProductStructureTree,
      ProductStructureMain,
      ImportFileModal
    },
    data() {
      return {}
    },
    methods: {}
  }
export default {
  name: 'ProductStructure',
  components: {
    DeviceCustomTypeModal,
    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
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,223 @@
<template>
  <a-modal
    :title="title"
    :width="700"
    @cancel="close"
    :visible="visible"
    :footer="null"
    style="height: 100%;overflow: auto;padding-bottom: 53px;">
    <a-spin :spinning="confirmLoading">
      <a-form-model ref="form" :form="form" :model="model" :rules="validatorRules" :labelCol="labelCol"
                    :wrapperCol="wrapperCol">
        <a-row :gutter="24">
          <a-col :span="12">
            <a-form-model-item label="车间分配" prop="productionId">
              <a-select v-model="model.productionId" placeholder="请选择车间" @change="handleSelectChange"
                        :disabled="disabledEdit">
                <a-select-option v-for="item in workshopTreeData" :key="item.id">
                  {{ item.productionName }}
                </a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="设备类" prop="deviceManagementCode">
              <a-input allow-clear placeholder="请输入设备类" :readOnly="disabledEdit"
                       v-model="model.deviceManagementCode"/>
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="24">
          <a-col :span="12">
            <a-form-model-item label="设备类名称" prop="deviceManagementName">
              <a-input allow-clear placeholder="请输入设备类名称" :readOnly="disabledEdit"
                       v-model="model.deviceManagementName"/>
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="24">
          <a-col :span="24">
            <a-form-model-item label="设备组编号" :labelCol="labelColLong" :wrapperCol="wrapperColLong"
                               prop="equipmentIds">
              <a-input-search v-model="model.equipmentIds" :disabled="!model.productionId" @search="deviceSearch"
                              enter-button :placeholder='!model.productionId?"请选择车间":"请选择设备组编号"'/>
            </a-form-model-item>
          </a-col>
        </a-row>
      </a-form-model>
    </a-spin>
    <div class="drawer-bottom-button">
      <a-space>
        <a-button @click="close">取消</a-button>
        <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">提交</a-button>
      </a-space>
    </div>
    <workshop-device-list-modal :productionId="model.productionId" ref="deviceListModel"
                                @sendSelectedRowKeys="getDeviceRowKeys"/>
  </a-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import WorkshopDeviceListModal from '@views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue'
export default {
  name: 'DeviceCustomTypeManagementModal',
  components: { WorkshopDeviceListModal },
  props: {
    workshopTreeData: {
      type: Array
    }
  },
  data() {
    return {
      title: '',
      form: this.$form.createForm(this),
      validatorRules: {
        productionId: [
          {
            required: true, message: '请选择车间!'
          }
        ],
        deviceManagementCode: [
          {
            required: true, message: '请输入设备类!'
          }
        ],
        deviceManagementName: [
          {
            required: true, message: '请输入设备类名称!'
          }
        ],
        equipmentIds: [
          {
            required: true, message: '请选择设备编号!'
          }
        ]
      },
      visible: false,
      disabledEdit: false,
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 14 }
      },
      labelColLong: {
        xs: { span: 24 },
        sm: { span: 4 }
      },
      wrapperColLong: {
        xs: { span: 24 },
        sm: { span: 19 }
      },
      confirmLoading: false,
      url: {
        add: '/nc/deviceManagement/add',
        edit: '/nc/deviceManagement/edit'
      }
    }
  },
  methods: {
    // è½¦é—´é€‰æ‹©å™¨å€¼å‘生改变时触发清空已选择的设备编号组
    handleSelectChange() {
      if (this.model.equipmentIds) delete this.model.equipmentIds
    },
    /**
     * å½“设备选择完成后提交将已选择的设备编号列表以逗号隔开拆分到参数中
     * @param selectedRowKeys
     */
    getDeviceRowKeys(selectedRowKeys) {
      if (selectedRowKeys.length === 0) return
      this.$set(this.model, 'equipmentIds', selectedRowKeys.join(','))
      this.$refs.form.clearValidate()
    },
    deviceSearch() {
      this.$refs.deviceListModel.openPage()
      this.$refs.deviceListModel.title = '选择设备'
      this.$refs.deviceListModel.disableSubmit = false
    },
    add() {
      this.edit({})
    },
    edit(record) {
      this.visible = true
      this.model = Object.assign({}, record)
    },
    handleSubmit() {
      const that = this
      // è§¦å‘表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          let apiUrl, method
          if (!this.model.id) {
            apiUrl = this.url.add
            method = 'post'
          } else {
            apiUrl = this.url.edit
            method = 'put'
          }
          httpAction(apiUrl, this.model, method)
            .then((res) => {
              if (res.success) {
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
                that.$emit('ok')
                that.close()
              } else {
                that.$notification.warning({
                  message: '消息',
                  description: res.message
                })
              }
            })
            .finally(() => {
              that.confirmLoading = false
            })
        } else {
          return false
        }
      })
    },
    close() {
      this.$emit('close')
      this.visible = false
      this.$refs.form.clearValidate()
    }
  }
}
</script>
<style scoped>
.drawer-bottom-button {
  position: absolute;
  bottom: -40px;
  width: 100%;
  border-top: 1px solid #e8e8e8;
  padding: 10px 16px;
  text-align: right;
  left: 0;
  background: #fff;
  border-radius: 0 0 2px 2px;
}
</style>
src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,125 @@
<template>
  <a-modal :title="title" :width="1000" :visible="visible" :maskClosable="false" @ok="handleOk" @cancel="close"
           cancelText="关闭">
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="8" :sm="8">
            <a-form-item label="设备编号">
              <a-input placeholder="请输入设备编号" v-model="queryParam.equipmentId"/>
            </a-form-item>
          </a-col>
          <a-col :md="8" :sm="8">
            <a-form-item label="设备名称">
              <a-input placeholder="请输入设备名称" v-model="queryParam.equipmentName"/>
            </a-form-item>
          </a-col>
          <a-col :md="3" :sm="3">
            <a-space>
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="primary" @click="searchReset" icon="reload">重置</a-button>
            </a-space>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- table区域-begin -->
    <a-table ref="table" size="middle" bordered rowKey="equipmentId" :scroll="{y: 300}" :columns="columns"
             :dataSource="dataSource" :pagination="ipagination" :loading="loading"
             :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type:'checkbox'}"
             @change="handleTableChange">
    </a-table>
    <!-- table区域-end -->
  </a-modal>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
export default {
  name: 'WorkshopDeviceListModal',
  mixins: [JeecgListMixin],
  components: {},
  props: {
    productionId: {
      type: String
    }
  },
  data() {
    return {
      title: '',
      visible: false,
      disableMixinCreated: true,
      columns: [
        {
          title: '设备编号',
          align: 'center',
          dataIndex: 'equipmentId'
        },
        {
          title: '设备名称',
          align: 'center',
          dataIndex: 'equipmentName'
        },
        {
          title: '设备型号',
          align: 'center',
          dataIndex: 'equipmentModel'
        },
        {
          title: '机床IP',
          align: 'center',
          dataIndex: 'equipmentIp'
        },
        {
          title: '驱动类型',
          align: 'center',
          dataIndex: 'driveType'
        },
        {
          title: '端口',
          align: 'center',
          dataIndex: 'dataPort'
        },
        {
          title: '数控系统',
          align: 'center',
          dataIndex: 'controlSystem'
        }
      ],
      url: {
        list: '/nc/deviceManagement/getEquipmentListByProductionId'
      }
    }
  },
  methods: {
    openPage() {
      this.visible = true
      this.onClearSelected()
      this.dataSource = []
      this.queryParam = Object.assign({}, { productionId: this.productionId })
      this.loadData()
    },
    searchQuery() {
      this.loadData()
      this.onClearSelected()
    },
    searchReset() {
      this.queryParam = Object.assign({}, { productionId: this.productionId })
      this.loadData()
      this.onClearSelected()
    },
    close() {
      this.$emit('close')
      this.visible = false
    },
    handleOk() {
      this.$emit('sendSelectedRowKeys', this.selectedRowKeys)
      this.close()
    }
  }
}
</script>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
@@ -1,6 +1,6 @@
<template>
  <div>
    <a-tabs v-model="activeTabKey" @change="handleTabChange">
  <div style="height: 100%">
    <a-tabs style="height: 100%" 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,6 +82,7 @@
      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">
    <a-descriptions-item label="名称">{{currentLevelDetails.componentName}}</a-descriptions-item>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="名称" :span="2">{{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="重量" :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-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>
</template>
src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue
ÎļþÒÑɾ³ý
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    :maskClosable="false"
    @ok="handleOk"
    @cancel="handleCancel"
    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
    cancelText="关闭">
    <CutterModalForm ref="realForm" @ok="submitCallback" :disableSubmit="disableSubmit"/>
  </j-modal>
</template>
<script>
import CutterModalForm from './CutterModalForm.vue'
export default {
  name: 'CutterModal',
  components: {
    CutterModalForm
  },
  props: {
    currentTreeNodeInfo: {
      type: Object
    }
  },
  data() {
    return {
      title: '',
      width: 700,
      visible: false,
      disableSubmit: false
    }
  },
  methods: {
    // æ·»åŠ æ‰€ç”¨åˆ€å…·
    handleCutterAdd() {
      const { id, type } = this.currentTreeNodeInfo
      this.visible = true
      this.$nextTick(() => {
        if (this.$refs.realForm) {
          this.$refs.realForm.add({
            attributionId: id,
            attributionType: type
          })
        }
      })
    },
    // ç¼–辑刀具信息
    handleCutterEdit(record) {
      this.visible = true
      this.$nextTick(() => {
        if (this.$refs.realForm) {
          this.$refs.realForm.edit({ ...record })
        }
      })
    },
    handleOk() {
      this.$refs.realForm.submitForm()
    },
    submitCallback() {
      this.$emit('submitSuccess')
      this.visible = false
    },
    handleCancel() {
      this.$emit('close')
      this.visible = false
    }
  }
}
</script>
src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
<template>
  <a-spin :spinning="confirmLoading">
    <a-form-model ref="form" :model="model" :rules="validatorRules" :labelCol="labelCol" :wrapperCol="wrapperCol">
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="刀具编号" prop="cutterCode">
            <a-input v-model="model.cutterCode" placeholder="请输入刀具编号" :readOnly="disableSubmit"/>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="刀具名称" prop="cutterName">
            <a-input v-model="model.cutterName" placeholder="请输入刀具名称" :readOnly="disableSubmit"/>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="刀具类型">
            <j-dict-select-tag v-model="model.cutterType" placeholder="请选择刀具类型" dictCode="cutter_type"
                               :disabled="disableSubmit"/>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="额定寿命">
            <a-input-number v-model="model.lifetime" :min="0" placeholder="请输入额定寿命" style="width: 100%"
                            :disabled="disableSubmit"/>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="刀位">
            <a-input v-model="model.cutterSpacing" placeholder="请输入刀位" :readOnly="disableSubmit"/>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="刀具数量">
            <a-input-number v-model="model.quantity" placeholder="请输入刀具数量" :min="1" style="width: 100%"
                            :disabled="disableSubmit"/>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="24">
          <a-form-model-item label="描述" :labelCol="labelColLong" :wrapperCol="wrapperColLong">
            <a-textarea v-model="model.description" placeholder="请输入描述" :readOnly="disableSubmit"/>
          </a-form-model-item>
        </a-col>
      </a-row>
    </a-form-model>
  </a-spin>
</template>
<script>
import { httpAction } from '@/api/manage'
export default {
  name: 'CutterModalForm',
  components: {},
  props: {
    disableSubmit: {
      type: Boolean
    }
  },
  data() {
    return {
      model: {
        quantity: 1
      },
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 14 }
      },
      labelColLong: {
        xs: { span: 24 },
        sm: { span: 4 }
      },
      wrapperColLong: {
        xs: { span: 24 },
        sm: { span: 19 }
      },
      confirmLoading: false,
      validatorRules: {
        cutterCode: [
          { required: true, message: '请输入刀具编号!' }
        ],
        cutterName: [
          { required: true, message: '请输入刀具名称!' }
        ]
      },
      url: {
        add: '/nc/cutter/add',
        edit: '/nc/cutter/edit'
      }
    }
  },
  created() {
    //备份model原始值
    this.modelDefault = JSON.parse(JSON.stringify(this.model))
  },
  methods: {
    add(params) {
      this.edit({ ...this.modelDefault, ...params })
    },
    edit(record) {
      this.model = Object.assign({}, record)
      console.log('model', this.model)
    },
    submitForm() {
      const that = this
      // è§¦å‘表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          let httpUrl, method
          if (!this.model.id) {
            httpUrl = this.url.add
            method = 'post'
          } else {
            httpUrl = this.url.edit
            method = 'put'
          }
          httpAction(httpUrl, this.model, method).then((res) => {
            if (res.success) {
              that.$notification.success({
                message: '消息',
                description: res.message
              })
              that.$emit('ok')
            } else {
              that.$notification.warning({
                message: '消息',
                description: res.message
              })
            }
          }).finally(() => {
            that.confirmLoading = false
          })
        }
      })
    }
  }
}
</script>
src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,153 @@
<template>
  <div>
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="5" :sm="5">
            <a-form-item label="刀具编号">
              <a-input placeholder="请输入刀具编号" v-model="queryParam.cutterCode" allow-clear/>
            </a-form-item>
          </a-col>
          <a-col :md="5" :sm="5">
            <a-form-item label="刀具名称">
              <a-input placeholder="请输入刀具名称" v-model="queryParam.cutterName" allow-clear/>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4">
            <a-space>
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="primary" @click="handleAdd" icon="plus" v-has="'cutter_add'">新增</a-button>
              <a-button type="primary" @click="handleExportXls('刀具列表')" icon="export">导出</a-button>
              <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader"
                        :action="importExcelUrl" @change="handleImportExcel">
                <a-button type="primary" icon="import">导入</a-button>
              </a-upload>
            </a-space>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination" :size="size" rowKey="id"
             @change="handleTableChange" :scroll="{y:189}">
      <template slot="action" slot-scope="text, record">
        <a @click="handleEdit(record)">编辑</a>
        <a-divider type="vertical"/>
        <a-dropdown>
          <a class="ant-dropdown-link">
            æ›´å¤š
            <a-icon type="down"/>
          </a>
          <a-menu slot="overlay">
            <a-menu-item>
              <a href="javascript:;" @click="handleDetail(record)">详情</a>
            </a-menu-item>
            <a-menu-item>
              <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
                <a>删除</a>
              </a-popconfirm>
            </a-menu-item>
          </a-menu>
        </a-dropdown>
      </template>
    </a-table>
    <CutterModal ref="cutterModalRef" :currentTreeNodeInfo="currentLevelInfo" @submitSuccess="loadData"/>
  </div>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import CutterModal from '@views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue'
export default {
  name: 'CutterTableList',
  components: { CutterModal },
  mixins: [JeecgListMixin],
  props: {
    currentLevelInfo: {
      type: Object
    },
    size: {
      type: String
    }
  },
  data() {
    return {
      disableMixinCreated: true,
      columns: [
        {
          title: '序号',
          dataIndex: 'rowIndex',
          key: 'rowIndex',
          width: 65,
          align: 'center',
          customRender: function(t, r, index) {
            return parseInt(index) + 1
          }
        },
        { title: '刀具编号', dataIndex: 'cutterCode', align: 'center' },
        { title: '刀具名称', dataIndex: 'cutterName', align: 'center' },
        { title: '刀具类型', dataIndex: 'cutterType_dictText', align: 'center' },
        { title: '额定寿命', dataIndex: 'lifetime', width: 150, align: 'center' },
        { title: '刀位', dataIndex: 'cutterSpacing', width: 150, align: 'center' },
        { title: '刀具数量', dataIndex: 'quantity', width: 150, align: 'center' },
        { title: '操作', dataIndex: 'action', scopedSlots: { customRender: 'action' }, align: 'center', width: 150 }
      ],
      url: {
        list: '/nc/cutter/getByBusinessId',
        delete: '/nc/cutter/delete',
        exportXlsUrl: '/nc/cutter/exportXls',
        importExcelUrl: '/nc/cutter/importExcel'
      }
    }
  },
  computed: {
    importExcelUrl: function() {
      return `${window._CONFIG['domianURL']}${this.url.importExcelUrl}`
    }
  },
  methods: {
    setQueryParamAndLoadData(pageNo = 1) {
      const { id, type } = this.currentLevelInfo
      this.queryParam = Object.assign({}, { attributionId: id, attributionType: type })
      this.loadData(pageNo)
    },
    handleAdd() {
      if (!this.$refs.cutterModalRef) return
      this.$refs.cutterModalRef.title = '添加刀具'
      this.$refs.cutterModalRef.disableSubmit = false
      this.$refs.cutterModalRef.handleCutterAdd()
    },
    /**
     * ç¼–辑表格行信息
     * @param record è¡¨æ ¼è¡Œä¿¡æ¯
     */
    handleEdit(record) {
      if (!this.$refs.cutterModalRef) return
      this.$refs.cutterModalRef.title = '编辑刀具信息'
      this.$refs.cutterModalRef.disableSubmit = false
      this.$refs.cutterModalRef.handleCutterEdit(record)
    },
    /**
     * æŸ¥çœ‹è¡¨æ ¼å®Œæ•´è¡Œä¿¡æ¯
     * @param record è¡¨æ ¼è¡Œä¿¡æ¯
     */
    handleDetail: function(record) {
      if (!this.$refs.cutterModalRef) return
      this.$refs.cutterModalRef.title = '刀具详情'
      this.$refs.cutterModalRef.disableSubmit = true
      this.$refs.cutterModalRef.handleCutterEdit(record)
    }
  }
}
</script>
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    :maskClosable="false"
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <DeviceCustomTypeModalForm ref="realForm" @ok="handleCancel"/>
  </j-modal>
</template>
<script>
import DeviceCustomTypeModalForm from './DeviceCustomTypeModalForm'
export default {
  name: 'DeviceCustomTypeModal',
  components: {
    DeviceCustomTypeModalForm
  },
  data() {
    return {
      title: '',
      width: 700,
      visible: false
    }
  },
  created() {
    this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
  },
  methods: {
    // ç‚¹å‡»æ·»åŠ è®¾å¤‡ç±»æ–°å¢žå·¥åºæˆ–å·¥æ­¥ä¸‹è®¾å¤‡ç±»
    handleAddType(treeNodeInfo) {
      this.visible = true
      const { treeKey, type } = treeNodeInfo
      console.log('treeNodeInfo', treeNodeInfo)
      this.$nextTick(() => {
        if (this.$refs.realForm) {
          this.$refs.realForm.add({
            attributionId: treeKey,
            attributionType: type
          })
          this.$refs.realForm.getWorkshopListByApi()
        }
      })
    },
    // ç¼–辑设备类信息
    handleTypeEdit(_, tableRowInfo) {
      this.visible = true
      this.$nextTick(() => {
        if (this.$refs.realForm) {
          this.$refs.realForm.getWorkshopListByApi()
          this.$refs.realForm.handleProductionChange()
          this.$refs.realForm.edit({ ...tableRowInfo })
        }
      })
    },
    handleCancel() {
      this.visible = false
    },
    handleOk() {
      this.$refs.realForm.submitForm()
    },
    triggerCorrespondingMethod({ methodName, modalTitle, treeNodeInfo, tableRowInfo }) {
      console.log('触发右键菜单')
      if (this[methodName]) {
        this.title = modalTitle
        this[methodName](treeNodeInfo, tableRowInfo)
      }
    }
  }
}
</script>
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
<template>
  <a-spin :spinning="confirmLoading">
    <a-form-model ref="form" :model="model" :rules="validatorRules" :labelCol="labelCol" :wrapperCol="wrapperCol">
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="车间" prop="productionId">
            <a-select v-model="model.productionId" placeholder="请选择车间" @change="handleProductionChange">
              <a-select-option v-for="item in workshopTreeData" :key="item.id">
                {{ item.productionName }}
              </a-select-option>
            </a-select>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="设备类" prop="deviceManagementId">
            <a-select v-model="model.deviceManagementId" placeholder="请选择设备类" :disabled="!model.productionId"
                      @change="handleCodeSelectChange">
              <a-select-option v-for="item in deviceCustomTypeList" :key="item.id">
                {{ item.deviceManagementCode }}
              </a-select-option>
            </a-select>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="设备类名称">
            <a-input v-model="model.deviceManagementId_dictText" placeholder="请选择设备类" readOnly/>
          </a-form-model-item>
        </a-col>
      </a-row>
    </a-form-model>
  </a-spin>
</template>
<script>
import { httpAction } from '@/api/manage'
import dncApi from '@/api/dnc'
export default {
  name: 'DeviceCustomTypeModalForm',
  components: {},
  data() {
    return {
      model: {},
      workshopTreeData: [],
      deviceCustomTypeList: [],
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 17 }
      },
      confirmLoading: false,
      validatorRules: {
        productionId: [
          { required: true, message: '请选择车间!' }
        ],
        deviceManagementId: [
          { required: true, message: '请选择设备类!' }
        ]
      },
      url: {
        add: '/nc/deviceType/add',
        edit: '/nc/deviceType/edit'
      }
    }
  },
  created() {
    //备份model原始值
    this.modelDefault = JSON.parse(JSON.stringify(this.model))
  },
  methods: {
    // è°ƒç”¨æŽ¥å£èŽ·å–æŸ¥è¯¢åŒºåŸŸè½¦é—´æ ‘åˆ—è¡¨
    getWorkshopListByApi() {
      dncApi.getHasPermissionWorkshopTreeApi()
        .then(res => {
          if (res.success) this.workshopTreeData = res.result
        })
    },
    // è½¦é—´é€‰æ‹©æ”¹å˜åŽæ¸…空设备类选择并重新获取设备类列表
    handleProductionChange() {
      if (this.model.deviceManagementId) delete this.model.deviceManagementId
      if (this.model.deviceManagementId_dictText) delete this.model.deviceManagementId_dictText
      dncApi.getDeviceCustomTypeListByProductionIdApi(this.model.productionId)
        .then(res => {
          if (res.success) this.deviceCustomTypeList = res.result
        })
    },
    /**
     * è®¾å¤‡ç±»é€‰æ‹©æ”¹å˜åŽè§¦å‘填充设备类对应设备类名称
     * @param value
     */
    handleCodeSelectChange(value) {
      this.$set(this.model, 'deviceManagementId_dictText', this.deviceCustomTypeList.find(item => item.id === value).deviceManagementName)
    },
    add(params) {
      this.edit({ ...this.modelDefault, ...params })
    },
    edit(record) {
      this.model = Object.assign({}, record)
    },
    submitForm() {
      const that = this
      // è§¦å‘表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          let httpUrl, method
          if (!this.model.id) {
            httpUrl = that.url.add
            method = 'post'
          } else {
            httpUrl = that.url.edit
            method = 'put'
          }
          httpAction(httpUrl, that.model, method)
            .then((res) => {
              if (res.success) {
                that.$notification.success({
                  message: '消息',
                  description: res.message
                })
                that.$bus.$emit('deviceCustomTypeAddSubmitSuccess')
                that.$emit('ok')
              } else {
                that.$notification.warning({
                  message: '消息',
                  description: res.message
                })
              }
            })
            .finally(() => {
              that.confirmLoading = false
            })
        }
      })
    }
  }
}
</script>
src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
<template>
  <div style="flex: 0.25;margin-right: 10px">
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="id" @change="handleTableChange">
    </a-table>
  </div>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import DeviceCustomTypeModal from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
import { deleteAction } from '@api/manage'
export default {
  name: 'DeviceCustomTypeTableList',
  components: { DeviceCustomTypeModal },
  mixins: [JeecgListMixin],
  props: {
    currentTreeNodeInfo: {
      type: Object
    },
    size: {
      type: String
    }
  },
  data() {
    return {
      disableMixinCreated: true,
      columns: [
        // {
        //   title: '车间',
        //   dataIndex: 'productionId_dictText',
        //   align: 'center'
        // },
        {
          title: '设备类',
          dataIndex: 'deviceManagementCode_dictText',
          align: 'center'
        },
        {
          title: '设备类名称',
          dataIndex: 'deviceManagementId_dictText',
          align: 'center'
        }
      ],
      dataSource: [],
      currentRightClickedTypeInfo: {},
      currentClickedTypeInfo: {},
      url: {
        list: '/nc/deviceType/getByBusinessId',
        delete: '/nc/deviceType/delete'
      }
    }
  },
  watch: {
    currentTreeNodeInfo: {
      handler(value) {
        this.currentClickedTypeInfo = {}
      },
      immediate: true
    }
  },
  created() {
    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    this.$bus.$on('deviceCustomTypeAddSubmitSuccess', this.loadData)
  },
  methods: {
    setQueryParamAndLoadData() {
      console.log('currentLevelInfo', this.currentTreeNodeInfo)
      const { id, type } = this.currentTreeNodeInfo
      this.queryParam = Object.assign({}, { attributionId: id, attributionType: type })
      this.loadData()
    },
    customRow(record) {
      return {
        on: {
          contextmenu: event => {
            event.preventDefault()
            this.currentRightClickedTypeInfo = Object.assign({ param: 'deviceCustomType' }, record)
            this.$emit('handleTableContextMenuOpen', this.currentRightClickedTypeInfo)
          },
          click: () => {
            if (this.currentClickedTypeInfo.docId === record.docId) return
            this.currentClickedTypeInfo = Object.assign({}, record)
            // this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
          }
        }
      }
    },
    /**
     * è¡¨æ ¼åˆ†é¡µã€æŽ’序改变、筛选时触发
     * @param pagination åˆ†é¡µå™¨é€‰é¡¹
     * @param filters ç­›é€‰é€‰é¡¹
     * @param sorter æŽ’序选项
     */
    handleTableChange(pagination, filters, sorter) {
      if (sorter.order) {
        this.isorter.column = sorter.field
        this.isorter.order = sorter.order === 'ascend' ? 'asc' : 'desc'
      } else {
        this.isorter.column = 'createTime'
        this.isorter.order = 'desc'
      }
      for (let key in filters) {
        this.filters[key] = filters[key].join(',')
      }
      this.ipagination = pagination
      this.loadData()
    },
    /**
     * åˆ é™¤å·¥åºæˆ–工步层级添加的设备类
     * @param tableRowInfo
     */
    handleTypeDelete(tableRowInfo) {
      const { id } = tableRowInfo
      const { $confirm, url, loadData, $notification, $destroyAll } = this
      $confirm({
        title: '提示',
        content: '确认删除此条记录吗?',
        okText: '确认',
        okType: 'danger',
        cancelText: '取消',
        onOk: () => {
          if (!url.delete) {
            this.$message.error('请设置url.delete属性!')
            return
          }
          deleteAction(url.delete, { id: id })
            .then((res) => {
              if (res.success) {
                $notification.success({
                  message: '消息',
                  description: res.message
                })
                loadData()
              } else {
                $notification.warning({
                  message: '消息',
                  description: res.message
                })
              }
            })
            .finally(() => {
              $destroyAll()
            })
        },
        onCancel: () => {
          $destroyAll()
        }
      })
    },
    triggerCorrespondingMethod({ methodName, modalTitle, tableRowInfo }) {
      if (this[methodName] && tableRowInfo.param === 'deviceCustomType') this[methodName](tableRowInfo, modalTitle)
    }
  }
}
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
@@ -1,5 +1,5 @@
<template>
  <div>
  <div style="flex: 1">
    <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">
    <a-descriptions-item label="零件名称">{{currentLevelDetails.partsName}}</a-descriptions-item>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="零件名称" :span="2">{{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="重量" :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-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>
</template>
src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
@@ -27,124 +27,123 @@
</template>
<script>
  import dncApi from '@/api/dnc'
  import DepartPermissionTransfer from './DepartPermissionTransfer'
  import UserPermissionTransfer from './UserPermissionTransfer'
  import { queryProductionTreeList } from '@/api/api'
import dncApi from '@/api/dnc'
import DepartPermissionTransfer from './DepartPermissionTransfer'
import UserPermissionTransfer from './UserPermissionTransfer'
  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)
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()
        }
      }
    },
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    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
    },
    methods: {
      // ç‚¹å‡»æ ‘节点右键菜单权限配置按钮后触发
      handleAssignPermission() {
        this.visible = true
      },
      // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰è½¦é—´åˆ—è¡¨
      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'
    // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰è½¦é—´åˆ—è¡¨
    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)
          }
        })
      },
    },
      handleModalClose() {
        this.visible = false
        this.hasLoadedDataTabKeyArray = []
      },
    /**
     * é€’归获得所有树节点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)
      }
    },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) {
          this[methodName]()
          this.title = modalTitle
    // è°ƒç”¨æŽ¥å£èŽ·å–æ‰€æœ‰ç”¨æˆ·åˆ—è¡¨
    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'
        }
      })
    },
    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">
    <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 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-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.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-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>
</template>
src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
@@ -122,7 +122,6 @@
    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">
  <a-descriptions bordered :size="size" :column="4">
    <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="工装名称    " :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-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>
</template>
src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
@@ -1,12 +1,12 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="名称">{{currentLevelDetails.productName}}</a-descriptions-item>
  <a-descriptions bordered :size="size" :column="4">
    <a-descriptions-item label="名称" :span="2">{{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.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="创建人">{{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>
</template>
src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue
@@ -1,12 +1,12 @@
<template>
  <div style="height: 100%;max-height: 748px">
    <!--产品结构树右侧顶部区域-->
    <div style="height: 45%;overflow: hidden">
    <div style="height: 55%;overflow: hidden">
      <ProductStructureMainTop :size="tabContainerSize"/>
    </div>
    <!--产品结构树右侧底部区域-->
    <div style="height: 55%;overflow: hidden">
    <div style="height: 45%;overflow: hidden">
      <ProductStructureMainBottom :size="tabContainerSize"/>
    </div>
  </div>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
@@ -1,6 +1,7 @@
<template>
  <div v-if="currentLevelInfo.type!==4">
    <a-tabs v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0" @change="handleTabChange">
  <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">
      <a-tab-pane :key="1" tab="属性信息" v-if="+currentLevelInfo.type===1">
        <ProductInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      </a-tab-pane>
@@ -21,8 +22,10 @@
        <ProcessStepInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      </a-tab-pane>
      <a-tab-pane :key="2" tab="刀具信息" v-if="+currentLevelInfo.type===5||+currentLevelInfo.type===6">
        <CutterInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
      <!--系统参数配置中若参数为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>
      <template v-if="currentLevelInfo.hasOwnProperty('attributionType')">
@@ -57,19 +60,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 CutterInfo from '@views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue'
import dncApi from '@/api/dnc'
import { getAction } from '@/api/manage'
export default {
  name: 'ProductStructureMainBottom',
  components: {
    CutterInfo,
    CutterTableList,
    TableContextMenu,
    FilePreview,
    ProcessStepInfo,
@@ -85,6 +88,8 @@
    return {
      activeTabKey: 1,
      containerSize: 'small',
      isProcessHasCutterList: false,
      isProcessStepHasCutterList: false,
      currentLevelInfo: {},
      currentRightClickedTableRowInfo: {},
      hasLoadedDataTabKeyArray: []
@@ -94,30 +99,47 @@
    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) {
      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.currentLevelInfo = levelInfo
      this.activeTabKey = 1
      this.hasLoadedDataTabKeyArray = []
    },
    /**
     * tab栏切换时触发
     * @param activeTabKey å½“前激活的tabKey
     */
    handleTabChange(activeTabKey) {
      if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
        switch (activeTabKey) {
          case 2:
            this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
            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))
            }
            break
          case 3:
            this.$nextTick(() => this.$refs.documentVersionTableRef.loadData())
@@ -172,6 +194,6 @@
}
/deep/ .ant-tabs-tabpane {
  overflow: auto;
  overflow: hidden auto;
}
</style>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
@@ -1,10 +1,18 @@
<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">
        <NcDocumentTableList ref="ncDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
                             @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
      <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>
      <a-tab-pane :key="2" tab="其他文档">
@@ -21,398 +29,426 @@
</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 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'
  export default {
    name: 'ProductStructureMainTop',
    components: { DocumentBatchDeleteModal, TableContextMenu, OtherDocumentTableList, NcDocumentTableList },
    data() {
      return {
        activeTabKey: 2,
        tableContainerSize: 'small',
        currentRightClickedTableRowInfo: {},
        currentTreeNodeInfo: {},
        hasLoadedDataTabKeyArray: []
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'
        }
      })
    },
    /**
     * æŽ¥æ”¶æ ‘组件传来的当前选中的树节点信息
     * @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(() => {
          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)
      }
    },
    created() {
      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
      this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    /**
     * æ–‡æ¡£ä»¥åŠ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)
      }
    },
    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)
      },
      /**
       * 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) {
              that.$notification.error({
                message: '消息',
                description: res.message
              })
            }
          })
          .catch(err => {
    // ä¸‹è½½å½“前右键选中文档
    handleDownload() {
      const that = this
      const { docId, docName } = this.currentRightClickedTableRowInfo
      dncApi.downloadDocumentApi({ docId, docName })
        .then(res => {
          if (res && !res.success) {
            that.$notification.error({
              message: '消息',
              description: err.message
              description: res.message
            })
          }
        })
        .catch(err => {
          that.$notification.error({
            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()
          }
        })
      },
    },
      /**
       * ç‚¹å‡»æ‰¹é‡åˆ é™¤åŽå‡ºçŽ°å¼¹çª—
       * @param modalTitle å¼¹çª—标题
       */
      handleBatchRemove(modalTitle) {
        if (!this.$refs.documentBatchDeleteModalRef) return
        this.$refs.documentBatchDeleteModalRef.title = modalTitle
        this.$refs.documentBatchDeleteModalRef.visible = true
      },
    // åˆ é™¤å½“前右键选中文档
    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 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 => {
    /**
     * ç‚¹å‡»æ‰¹é‡åˆ é™¤åŽå‡ºçŽ°å¼¹çª—
     * @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: err.message
                  description: res.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 {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
    /**
     * å–消出库当前右键选中文档
     * @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: err.message
                  description: res.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 {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
    /**
     * å‘布当前右键选中文档
     * @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: err.message
                  description: res.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 {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
    /**
     * é‡æ–°å‘布当前右键选中文档并重新发布退回上一文档版本
     * @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: err.message
                  description: res.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
            })
            .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 => {
    /**
     * é‡å½’档当前右键选中文档且后续无法继续发布或归档
     * @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: err.message
                  description: res.message
                })
              }
            })
            .catch(err => {
              that.$notification.error({
                message: '消息',
                description: err.message
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
            })
            .finally(() => {
              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,24 +2,26 @@
  <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">
        <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'"
          <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"
                    @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>
        <!--产品结构树-->
@@ -27,9 +29,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, 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"/>
@@ -73,10 +75,12 @@
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,
@@ -100,7 +104,6 @@
      autoExpandParent: true,
      checkStrictly: true,
      allTreeKeys: [],
      currentSelected: {},
      rightClickSelected: {},
      url: {
        delete: '/nc/product/delete'
@@ -115,10 +118,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
@@ -140,22 +143,62 @@
     * @param {node} node èŠ‚ç‚¹å¯¹è±¡
     */
    handleTreeSelect(selectedKeys, { node }) {
      const that = this
      let record = node.dataRef
      this.currentSelected = Object.assign({}, record)
      // å‘右侧父级组件发送当前选中树节点信息
      this.$bus.$emit('sendCurrentTreeNodeInfo', this.currentSelected)
      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
    },
    /**
     * æ ‘节点右键单击节点时触发
     * @param event äº‹ä»¶å¯¹è±¡
     * @param node èŠ‚ç‚¹å¯¹è±¡
     */
    handleTreeRightClick({ event, node }) {
    handleTreeRightClick({ node }) {
      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
            })
          }
        })
    },
    // æ ‘节点右键单击菜单中删除按钮时触发
@@ -216,8 +259,18 @@
      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
@@ -237,7 +290,6 @@
        expandedKeys = this.beforeSearchExpandedKeys
        autoExpandParent = false
      }
      Object.assign(this, {
        expandedKeys,
        searchValue: search,
@@ -292,7 +344,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,14 +1,20 @@
<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>
@@ -16,141 +22,144 @@
</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_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 }
          ]
        }
      }
    },
    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'
        }
      }
    },
    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 })
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'
      }
    },
    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'
      }
    }
  },
  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('')
      }
      console.log('methodName', methodName)
      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,6 +41,12 @@
        },
        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,11 +376,12 @@
        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 }],