产品结构树:
1、实现文档功能的删除功能
设备结构树:
1、实现获取对应设备的已发送的NC程序列表
2、实现设备层级导入NC程序功能
3、实现设备关联的已发送NC程序功能的删除功能
已重命名7个文件
已添加13个文件
已修改8个文件
1773 ■■■■■ 文件已修改
src/api/dnc.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/Production.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/DeviceStructure.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Device/DeviceInfo.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMain.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainTop.vue 377 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTreeContextMenu.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Document/NcDocumentTableList.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Document/OtherDocumentTableList.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/HasReceivedDocumentTableList.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/HasSentDocumentTableList.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Workshop/WorkshopInfo.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/OtherDocumentTableList.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue 96 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/DocumentBatchDeleteModal.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/DocumentInfo.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/DocumentModal.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/DocumentModalForm.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/DocumentVersionTableList.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/FileCompareModal.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/FilePreview.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/ImportFileModal.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/SelectFileCompareModal.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/TableContextMenu.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/dnc.js
@@ -27,6 +27,8 @@
  assignDocumentToDeviceApi: params => postAction('/nc/activit/assign/file/apply', params),
  // ä¸‹è½½æ–‡æ¡£
  downloadDocumentApi: ({ docId, docName }) => downloadFile(`/nc/doc/download/${docId}`, docName),
  // åˆ é™¤æ–‡æ¡£
  deleteDocumentApi: docId => deleteAction(`/nc/doc/delete?id=${docId}`),
  // æ–‡æ¡£å‡ºåº“
  documentOutboundApi: ({ docId, docName }) => requestGetDownLoad(`/nc/doc/pull/${docId}`, docName),
  // æ–‡æ¡£å–消出库
@@ -70,5 +72,9 @@
  // ç§»é™¤éƒ¨é—¨æƒé™
  removePermissionFromUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
    return postAction(`/nc/product/assign/remove/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
  }
  },
  //-------------------------设备结构树------------------------------------------------
  // åˆ é™¤æ–‡æ¡£
  deleteDeviceRelativeDocumentApi: ({ docId, attributionId }) => deleteAction(`doc/relative/delete/device/${docId}/${attributionId}`)
}
src/store/modules/Production.js
@@ -21,9 +21,9 @@
  actions: {
    // äº§çº¿æ ‘
      QueryProduction({ commit }) {
      QueryProduction({ commit },type='MDC') {
      return new Promise((resolve, reject) => {
        getAction("/mdc/mdcEquipment/queryTreeListByProduction").then(response => {
        getAction("/mdc/mdcEquipment/queryTreeListByProduction",{type}).then(response => {
          if(response.success){
            const result = response.result
            Vue.ls.set(SYS_PRODUCTION, result)
src/views/dnc/base/DeviceStructure.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
<template>
  <a-card :bordered="false">
    <a-row type="flex" :gutter="16">
      <a-col :md="5">
        <DeviceStructureTree/>
      </a-col>
      <a-col :md="19">
        <DeviceStructureMain/>
      </a-col>
    </a-row>
    <!--导入文件公共弹窗-->
    <ImportFileModal/>
  </a-card>
</template>
<script>
  import DeviceStructureTree from './modules/DeviceStructure/DeviceStructureTree'
  import DeviceStructureMain from './modules/DeviceStructure/DeviceStructureMain'
  import ImportFileModal from '../common/ImportFileModal'
  export default {
    name: 'DeviceStructure',
    components: {
      DeviceStructureTree,
      DeviceStructureMain,
      ImportFileModal
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped lang="less">
  /deep/ .ant-card-body {
    padding: 8px;
  }
</style>
src/views/dnc/base/modules/DeviceStructure/Device/DeviceInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="设备编号">{{currentLevelDetails.equipmentId}}</a-descriptions-item>
    <a-descriptions-item label="设备名称">{{currentLevelDetails.equipmentName}}</a-descriptions-item>
    <a-descriptions-item label="数控系统    ">{{currentLevelDetails.driveType}}</a-descriptions-item>
    <a-descriptions-item label="设备型号">{{currentLevelDetails.equipmentModel}}</a-descriptions-item>
    <a-descriptions-item label="链接IP">{{currentLevelDetails.equipmentIp}}</a-descriptions-item>
    <a-descriptions-item label="链接端口">{{currentLevelDetails.dataPort}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
  export default {
    name: 'DeviceInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMain.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
<template>
  <div style="height: 100%;max-height: 748px">
    <template v-if="+currentTreeNodeInfo.type===2">
      <div style="height: 100%;max-height: 748px">
        <!--产品结构树右侧顶部区域-->
        <div style="height: 45%;overflow: hidden">
          <DeviceStructureMainTop :size="containerSize" ref="mainTopRef" :currentTreeNodeInfo="currentTreeNodeInfo"/>
        </div>
        <!--产品结构树右侧底部区域-->
        <div style="height: 55%;overflow: hidden">
          <DeviceStructureMainBottom :size="containerSize" :currentTreeNodeInfo="currentTreeNodeInfo"/>
        </div>
      </div>
    </template>
    <template v-else>
      <a-tabs>
        <a-tab-pane :key="1" tab="车间属性">
          <WorkshopInfo :currentLevelDetails="currentTreeNodeInfo" :size="containerSize"/>
        </a-tab-pane>
      </a-tabs>
    </template>
  </div>
</template>
<script>
  import DeviceStructureMainTop from './DeviceStructureMainTop'
  import DeviceStructureMainBottom from './DeviceStructureMainBottom'
  import WorkshopInfo from './Workshop/WorkshopInfo'
  export default {
    name: 'DeviceStructureMain',
    components: {
      WorkshopInfo,
      DeviceStructureMainTop,
      DeviceStructureMainBottom
    },
    created() {
      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
    },
    data() {
      return {
        containerSize: 'small',
        currentTreeNodeInfo: {}
      }
    },
    methods: {
      /**
       * æŽ¥æ”¶æ ‘组件传来的当前选中的树节点信息
       * @param treeNodeInfo æ ‘节点信息
       */
      receiveCurrentTreeNodeInfo(treeNodeInfo) {
        // ä»Žæ ‘组件接受树节点信息后从父组件流入子组件
        this.currentTreeNodeInfo = treeNodeInfo
        if (treeNodeInfo.equipmentId) {
          this.$nextTick(() => {
            if (this.$refs.mainTopRef) this.$refs.mainTopRef.loadHasSentDocumentListData()
          })
        }
        console.log('currentTreeNodeInfo------------------', this.currentTreeNodeInfo)
      }
    }
  }
</script>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
<template>
  <a-tabs style="height: 100%" v-model="activeTabKey" @change="handleTabChange">
    <a-tab-pane :key="1" tab="设备属性" v-if="currentTreeNodeInfo.equipmentId">
      <DeviceInfo :currentLevelDetails="currentTreeNodeInfo.entity" :size="containerSize"/>
    </a-tab-pane>
    <template v-else>
      <a-tab-pane :key="1" tab="文档属性">
        <DocumentInfo :currentLevelDetails="currentDocumentInfo" :size="containerSize"/>
      </a-tab-pane>
      <a-tab-pane :key="2" tab="预览">
        <FilePreview ref="filePreviewRef" :currentDocumentInfo="currentDocumentInfo"/>
      </a-tab-pane>
      <a-tab-pane :key="3" tab="文档版本">
        <DocumentVersionTableList ref="documentVersionTableRef" :currentDocumentInfo="currentDocumentInfo"
                                  @handleTableContextMenuOpen="handleTableContextMenuOpen"
                                  @releaseFilePreviewApi="releaseFilePreviewApi"
                                  :size="containerSize"/>
      </a-tab-pane>
    </template>
    <TableContextMenu :tableRowInfo="currentRightClickedTableRowInfo" ref="tableContextMenuRef"/>
  </a-tabs>
</template>
<script>
  import DeviceInfo from './Device/DeviceInfo'
  import DocumentInfo from '../../../common/DocumentInfo'
  import FilePreview from '../../../common/FilePreview'
  import TableContextMenu from '../../../common/TableContextMenu'
  import DocumentVersionTableList from '../../../common/DocumentVersionTableList'
  export default {
    name: 'DeviceStructureMainBottom',
    components: {
      TableContextMenu,
      DeviceInfo,
      DocumentInfo,
      FilePreview,
      DocumentVersionTableList
    },
    props: {
      currentTreeNodeInfo: {
        type: Object
      }
    },
    data() {
      return {
        activeTabKey: 1,
        containerSize: 'small',
        currentDocumentInfo: {},
        currentRightClickedTableRowInfo: {},
        hasLoadedDataTabKeyArray: []
      }
    },
    created() {
      this.$bus.$on('sendCurrentClickedDocumentInfo', this.receiveCurrentDocumentInfo)
      this.$bus.$on('reloadMainBottomTableData', this.reloadMainBottomTableData)
    },
    methods: {
      /**
       * æŽ¥æ”¶è¡¨æ ¼ä¼ æ¥çš„当前选中或点击的项信息
       * @param documentInfo å½“前层级信息
       */
      receiveCurrentDocumentInfo(documentInfo) {
        this.currentDocumentInfo = documentInfo
        this.activeTabKey = 1
        this.hasLoadedDataTabKeyArray = []
      },
      handleTabChange(activeTabKey) {
        if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
          switch (activeTabKey) {
            case 2:
              this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
              break
            case 3:
              this.$nextTick(() => this.$refs.documentVersionTableRef.loadData())
              break
            case 4:
              this.$nextTick(() => this.$refs.useDocumentEquipmentTableRef.loadData())
              break
            default:
          }
          // é˜»æ­¢æŽ¥å£åœ¨åŒä¸€æ–‡æ¡£ä¸€æ¬¡ç‚¹å‡»å†…多次触发
          this.hasLoadedDataTabKeyArray.push(activeTabKey)
        }
      },
      // é‡Šæ”¾æ–‡ä»¶é¢„览接口
      releaseFilePreviewApi() {
        // å¦‚果已经预览过此文档,可在此文档当前版本发生改变后再次预览新版本内容
        if (this.hasLoadedDataTabKeyArray.includes(2)) this.hasLoadedDataTabKeyArray = this.hasLoadedDataTabKeyArray.filter(item => item !== 2)
      },
      /**
       * æŽ§åˆ¶å³é”®èœå•开启
       * @param record å½“前表格行信息
       */
      handleTableContextMenuOpen(record) {
        this.currentRightClickedTableRowInfo = Object.assign({}, record)
        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)
      },
      /**
       * æŽ§åˆ¶å³é”®èœå•点击关闭
       */
      handleMenuClose() {
        this.$refs.tableContextMenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleMenuClose)
      },
      reloadMainBottomTableData(tableName) {
        if (this.$refs[tableName + 'TableRef']) this.$refs[tableName + 'TableRef'].loadData()
      }
    }
  }
</script>
<style scoped>
  /deep/ .ant-tabs-content {
    height: calc(100% - 65px);
  }
  /deep/ .ant-tabs-tabpane {
    overflow: auto;
  }
</style>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainTop.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,377 @@
<template>
  <a-tabs v-model="activeTabKey" @contextmenu.native="e=>e.preventDefault()"
          v-if="Object.keys(currentTreeNodeInfo).length!==0">
    <a-tab-pane :key="1" tab="发送">
      <!--<NcDocumentTableList ref="ncDocumentTableListRef" />-->
      <HasSentDocumentTableList ref="hasSentDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
                                @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
    </a-tab-pane>
    <a-tab-pane :key="2" tab="接收">
      <!--<OtherDocumentTableList ref="otherDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"-->
      <!--@handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>-->
    </a-tab-pane>
    <TableContextMenu :tableRowInfo="currentRightClickedTableRowInfo" ref="tableContextMenuRef"/>
  </a-tabs>
</template>
<script>
  import dncApi from '@/api/dnc'
  import TableContextMenu from '../../../common/TableContextMenu'
  import HasSentDocumentTableList from './HasSentDocumentTableList'
  export default {
    name: 'DeviceStructureMainTop',
    components: { HasSentDocumentTableList, TableContextMenu },
    props: {
      currentTreeNodeInfo: {
        type: Object
      }
    },
    data() {
      return {
        activeTabKey: 1,
        tableContainerSize: 'small',
        currentRightClickedTableRowInfo: {}
      }
    },
    created() {
      this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      /**
       * æŽ§åˆ¶å³é”®èœå•开启
       * @param record å½“前表格行信息
       */
      handleTableContextMenuOpen(record) {
        this.currentRightClickedTableRowInfo = Object.assign({}, record)
        console.log('currentRightClickedTableRowInfo', this.currentRightClickedTableRowInfo)
        this.$refs.tableContextMenuRef.currentMenuLevel = record.param
        this.$refs.tableContextMenuRef.menuStyle.top = event.clientY + 'px'
        this.$refs.tableContextMenuRef.menuStyle.left = event.clientX + 'px'
        this.$refs.tableContextMenuRef.menuVisible = true
        document.body.addEventListener('click', this.handleMenuClose)
      },
      /**
       * å½“树组件选中设备层级节点时触发获取已发送文档列表
       * @param treeNodeInfo æ ‘节点信息
       */
      loadHasSentDocumentListData(treeNodeInfo) {
        this.$nextTick(() => {
          if (this.$refs.hasSentDocumentTableListRef) this.$refs.hasSentDocumentTableListRef.loadData(1)
        })
      },
      /**
       * æ–‡æ¡£ä»¥åŠNC程序导入/出库/入库/删除成功后触发重新加载文档列表
       * @param docClassCode æ–‡æ¡£ç±»åˆ«
       * @param attributionId èŠ‚ç‚¹Id
       */
      reloadDocumentListData({ docClassCode, attributionId }) {
        // å¦‚果上传的文档不是所属于当前所展示节点的文档则不重新获取文档列表
        if (this.currentTreeNodeInfo.key !== attributionId) return
        if (docClassCode === 'SEND') {
          if (this.$refs.hasSentDocumentTableListRef) this.$refs.hasSentDocumentTableListRef.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 => {
            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.deleteDeviceRelativeDocumentApi({ docId, attributionId })
              .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) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: `${menuLabel}成功`
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
      },
      /**
       * å‘布当前右键选中文档
       * @param menuLabel
       */
      handleCancelPull(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentCancelOutboundApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .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 => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .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 => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
      },
      /**
       * é‡å½’档当前右键选中文档且后续无法继续发布或归档
       * @param menuLabel
       */
      handlePigeonhole(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        that.$confirm({
          title: '提示',
          content: `${menuLabel}后不可取消,确认${menuLabel}吗?`,
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            dncApi.documentPigeonholeApi(docId)
              .then(res => {
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.error({
                    message: '消息',
                    description: res.message
                  })
                }
              })
              .catch(err => {
                that.$notification.error({
                  message: '消息',
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
      },
      // æŽ§åˆ¶å³é”®èœå•关闭
      handleMenuClose() {
        this.$refs.tableContextMenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleMenuClose)
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) this[methodName](modalTitle)
      }
    }
  }
</script>
<style scoped>
  /deep/ .ant-table-tbody .ant-table-row {
    cursor: pointer;
  }
</style>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,295 @@
<template>
  <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">
          <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>
        </div>
        <!--设备结构树-->
        <div style="flex: 1;overflow:auto;margin-top: 10px">
          <a-tree blockNode show-icon :expandedKeys.sync="expandedKeys"
                  :selectedKeys="selectedKeys" :treeData="treeDataSource" :autoExpandParent="autoExpandParent"
                  @select="handleTreeSelect" @expand="handleTreeExpand" @rightClick="handleTreeRightClick">
            <template slot="title" slot-scope="{ title, parentId, entity, key:treeKey,equipmentId}">
              <DeviceStructureTreeContextMenu ref="contextMenuRef"
                                              :treeParams="{title,treeKey,searchValue,equipmentId,entity}"/>
            </template>
            <a-icon slot="switcherIcon" type="down"/>
            <a-icon slot="workshop" type="bank"/>
            <a-icon slot="device" type="laptop"/>
          </a-tree>
        </div>
      </div>
    </a-spin>
  </a-card>
</template>
<script>
  import { mapActions } from 'vuex'
  import { deleteAction } from '@/api/manage'
  import DeviceStructureTreeContextMenu from './DeviceStructureTreeContextMenu'
  export default {
    name: 'DeviceStructureTree',
    components: {
      DeviceStructureTreeContextMenu
    },
    data() {
      return {
        searchInput: '',
        cardLoading: false,
        loading: false,
        treeDataSource: [],
        selectedKeys: [],
        expandedKeys: [],
        searchValue: '',
        dataList: [],
        autoExpandParent: true,
        checkStrictly: true,
        allTreeKeys: [],
        currentSelected: {},
        rightClickSelected: {},
        url: {
          delete: '/nc/product/delete'
        }
      }
    },
    created() {
      this.getTreeDataByApi()
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      ...mapActions(['QueryProduction']),
      getTreeDataByApi() {
        this.loading = true
        this.cardLoading = true
        this.QueryProduction('DNC').then(res => {
          if (res.success) {
            this.dataList = []
            this.allTreeKeys = []
            this.treeDataSource = res.result
            this.generateList(this.treeDataSource)
            this.expandedKeys = this.allTreeKeys
            this.$bus.$emit('sendCurrentTreeNodeInfo', this.treeDataSource[0])
          } else {
            this.$message.warn(res.message)
          }
        }).finally(() => {
          this.loading = false
          this.cardLoading = false
        })
      },
      /**
       * æ ‘节点选中时触发
       * @param selectedKeys é€‰ä¸­èŠ‚ç‚¹key
       * @param {node} node èŠ‚ç‚¹å¯¹è±¡
       */
      handleTreeSelect(selectedKeys, { node }) {
        let record = node.dataRef
        this.currentSelected = Object.assign({}, record)
        this.selectedKeys = selectedKeys
        // å‘右侧父级组件发送当前选中树节点信息
        this.$bus.$emit('sendCurrentTreeNodeInfo', this.currentSelected)
      },
      /**
       * æ ‘节点右键单击节点时触发
       * @param event äº‹ä»¶å¯¹è±¡
       * @param node èŠ‚ç‚¹å¯¹è±¡
       */
      handleTreeRightClick({ event, node }) {
        const record = node.dataRef
        this.rightClickSelected = Object.assign({}, record)
      },
      // æ ‘节点右键单击菜单中删除按钮时触发
      handleDelete() {
        this.$confirm({
          title: '提示',
          content: '确认删除此条记录吗?',
          okText: '确认',
          okType: 'danger',
          cancelText: '取消',
          onOk: () => {
            console.log('this.rightClickSelected.id', this.rightClickSelected.id)
            if (!this.url.delete) {
              this.$message.error('请设置url.delete属性!')
              return
            }
            const that = this
            deleteAction(that.url.delete, { id: this.rightClickSelected.id })
              .then((res) => {
                if (res.success) {
                  that.getTreeDataByApi()
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.warning({
                    message: '消息',
                    description: res.message
                  })
                }
              })
          }
        })
      },
      /**
       * è‡ªåŠ¨å±•å¼€æ·»åŠ ä¸‹çº§èŠ‚ç‚¹çš„çˆ¶èŠ‚ç‚¹
       */
      modalFormSubmitSuccess(isAddNextLevel) {
        // åˆ¤æ–­æ˜¯å¦ä¸ºæ·»åŠ ä¸‹çº§å¹¶ä¸”åˆ¤æ–­çˆ¶èŠ‚ç‚¹æ˜¯å¦å±•å¼€
        if (isAddNextLevel && !this.expandedKeys.includes(this.rightClickSelected.id)) this.expandedKeys.push(this.rightClickSelected.id)
        this.getTreeDataByApi()
      },
      /**
       * æ ‘节点展开合并时触发
       * @param expandedKeys å±•开项key
       */
      handleTreeExpand(expandedKeys) {
        this.expandedKeys = expandedKeys
        this.autoExpandParent = false
      },
      /* è¾“入查询内容变化时触发 */
      handleSearchInputChange() {
        let search = this.searchInput
        let expandedKeys = this.dataList
          .map(item => {
            if (item.title != null) {
              if (item.title.indexOf(search) > -1) {
                return this.getParentKey(item.key, this.treeDataSource)
              }
              return null
            }
          })
          .filter((item, i, self) => item && self.indexOf(item) === i)
        Object.assign(this, {
          expandedKeys,
          searchValue: search,
          autoExpandParent: true
        })
      },
      /**
       * é€’归获得输入项的父级key
       * @param key å­é¡¹key
       * @param tree å­é¡¹
       */
      getParentKey(key, tree) {
        let parentKey
        for (let i = 0; i < tree.length; i++) {
          const node = tree[i]
          if (node.children) {
            if (node.children.some(item => item.key === key)) {
              parentKey = node.key
            } else if (
              this.getParentKey(key, node.children)) {
              parentKey = this.getParentKey(key, node.children)
            }
          }
        }
        return parentKey
      },
      /**
       * é€’归获得所有树节点key
       * @param data
       */
      generateList(data) {
        for (let i = 0; i < data.length; i++) {
          const node = data[i]
          const key = node.key
          const title = node.title
          this.dataList.push({ key, title })
          this.allTreeKeys.push(key)
          this.setTreeNodeIcon(node)
          if (node.children) this.generateList(node.children)
        }
      },
      triggerCorrespondingMethod({ methodName }) {
        if (this[methodName]) this[methodName]()
      },
      /**
       * è®¾ç½®æ ‘节点图标
       * @param treeNode
       */
      setTreeNodeIcon(treeNode) {
        if (!treeNode.equipmentId) {
          treeNode.slots = { icon: 'workshop' }
        } else {
          treeNode.slots = { icon: 'device' }
        }
      }
    }
  }
</script>
<style lang="less" scoped>
  /deep/ .ant-card-body {
    padding: 0 12px 0 0;
  }
  /deep/ .ant-card-body, /deep/ .ant-spin-nested-loading, /deep/ .ant-spin-container {
    height: 100%;
  }
  /deep/ .ant-tree-title, .ant-tree-title .ant-dropdown-trigger {
    display: inline-block;
    width: calc(100% - 24px) !important;
  }
  ::-webkit-scrollbar {
    width: 8px;
  }
  @media screen and (min-width: 1920px) {
    .tree_con {
      height: 748px !important;
    }
  }
  @media screen and (min-width: 1680px) and (max-width: 1920px) {
    .tree_con {
      height: 748px !important;
    }
  }
  @media screen and (min-width: 1400px) and (max-width: 1680px) {
    .tree_con {
      height: 600px !important;
    }
  }
  @media screen and (min-width: 1280px) and (max-width: 1400px) {
    .tree_con {
      height: 501px !important;
    }
  }
  @media screen and (max-width: 1280px) {
    .tree_con {
      height: 501px !important;
    }
  }
</style>
src/views/dnc/base/modules/DeviceStructure/DeviceStructureTreeContextMenu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
<template>
  <a-dropdown :trigger="['contextmenu']">
    <span v-if="treeParams.title.indexOf(treeParams.searchValue) > -1">{{ treeParams.title.substr(0, treeParams.title.indexOf(treeParams.searchValue)) }}<span
      class="replaceSearch">{{ treeParams.searchValue }}</span>{{ treeParams.title.substr(treeParams.title.indexOf(treeParams.searchValue) + treeParams.searchValue.length) }}</span>
    <span v-else>{{ treeParams.title }}</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}}
        </a-menu-item>
      </a-menu>
    </template>
  </a-dropdown>
</template>
<script>
  export default {
    name: 'DeviceStructureTreeContextMenu',
    components: {},
    props: {
      treeParams: {
        type: Object
      }
    },
    data() {
      return {
        defaultContextMenuList: {
          //车间
          workshop: [
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //设备
          device: [
            { label: '导入NC文档', code: 'device_import', icon: 'import', isCommonMethod: true },
            { label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ]
        }
      }
    },
    computed: {
      getCurrentMenuLevel() {
        if (!this.treeParams.equipmentId) return 'workshop'
        else return 'device'
      }
    },
    methods: {
      onContextMenuClick(treeKey, menuKey) {
        const level = this.getCurrentMenuLevel
        const treeNodeInfo = Object.assign({}, this.treeParams)
        if (treeNodeInfo.equipmentId) treeNodeInfo.type = 4
        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)
        console.log('treeParams------------------------------------', this.treeParams)
        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);
  }
</style>
src/views/dnc/base/modules/DeviceStructure/Document/NcDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
<template>
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange"/>
    <DocumentModal ref="modalForm" @ok="modalFormOk"/>
  </div>
</template>
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from '../../../../common/DocumentModal'
  export default {
    name: 'NcDocumentTableList',
    components: {  DocumentModal },
    mixins: [JeecgListMixin],
    props: {
      currentTreeNodeInfo: {
        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: 'docName', align: 'center' },
          { title: '代码版本', dataIndex: 'docAlias', align: 'center' },
          { title: '出库状态', dataIndex: 'pullStatus_dictText', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus_dictText', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [],
        currentRightClickedDocumentInfo: {},
        currentClickedDocumentInfo: {},
        url: {
          list: '/nc/doc/find/page'
        }
      }
    },
    created() {
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      loadData(arg) {
        if (!this.url.list) {
          this.$message.error('请设置url.list属性!')
          return
        }
        //加载数据 è‹¥ä¼ å…¥å‚æ•°1则加载第一页的内容
        if (arg === 1) this.ipagination.current = 1
        var params = this.getQueryParams()//查询条件
        params.attributionId = this.currentTreeNodeInfo.id
        params.attributionType = this.currentTreeNodeInfo.type
        params.docClassCode = 'NC'
        if (!params) return false
        this.dataSource = []
        this.loading = true
        getAction(this.url.list + `/${this.ipagination.current}/${this.ipagination.pageSize}`, params).then((res) => {
          if (res.success) {
            this.dataSource = res.result.records
            if (res.result.total) {
              this.ipagination.total = res.result.total
            } else {
              this.ipagination.total = 0
            }
          } else {
            this.$message.warning(res.message)
          }
        }).finally(() => {
          this.loading = false
        })
      },
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.currentRightClickedDocumentInfo = Object.assign({ param: 'NC' }, record)
              this.$emit('handleTableContextMenuOpen', this.currentRightClickedDocumentInfo)
            },
            click: () => {
              if (this.currentClickedDocumentInfo.docId === record.docId) return
              this.currentClickedDocumentInfo = Object.assign({}, record)
              this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
            }
          }
        }
      },
      handleDocumentEdit(record, modalTitle) {
        this.$refs.modalForm.edit(record)
        this.$refs.modalForm.title = modalTitle
      },
      handleDocumentAssign(record, modalTitle) {
        this.$refs.documentAssignModalRef.title = modalTitle
        this.$refs.documentAssignModalRef.visible = true
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName]) this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/DeviceStructure/Document/OtherDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
<template>
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange">
    </a-table>
    <DocumentModal ref="modalForm" @ok="modalFormOk"/>
  </div>
</template>
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from '../../../../common/DocumentModal'
  export default {
    name: 'OtherDocumentTableList',
    components: { DocumentModal },
    mixins: [JeecgListMixin],
    props: {
      currentTreeNodeInfo: {
        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: 'docName', align: 'center' },
          { title: '设备编号', dataIndex: 'docCode', align: 'center' },
          { title: '出库状态', dataIndex: 'pullStatus_dictText', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus_dictText', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [],
        currentDocumentInfo: {},
        url: {
          list: '/nc/doc/find/page'
        }
      }
    },
    created() {
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      loadData(arg) {
        if (!this.url.list) {
          this.$message.error('请设置url.list属性!')
          return
        }
        //加载数据 è‹¥ä¼ å…¥å‚æ•°1则加载第一页的内容
        if (arg === 1) this.ipagination.current = 1
        var params = this.getQueryParams()//查询条件
        params.attributionId = this.currentTreeNodeInfo.id
        params.attributionType = this.currentTreeNodeInfo.type
        params.docClassCode = 'OTHER'
        if (!params) return false
        this.dataSource = []
        this.loading = true
        getAction(this.url.list + `/${this.ipagination.current}/${this.ipagination.pageSize}`, params).then((res) => {
          if (res.success) {
            this.dataSource = res.result.records
            if (res.result.total) {
              this.ipagination.total = res.result.total
            } else {
              this.ipagination.total = 0
            }
          } else {
            this.$message.warning(res.message)
          }
        }).finally(() => {
          this.loading = false
        })
      },
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.$emit('handleTableContextMenuOpen', { ...record, param: 'OTHER' })
            },
            click: () => {
              if (this.currentDocumentInfo.docId === record.docId) return
              this.currentDocumentInfo = Object.assign({}, record)
              this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
            }
          }
        }
      },
      handleDocumentEdit(record, modalTitle) {
        this.$refs.modalForm.edit(record)
        this.$refs.modalForm.title = modalTitle
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName] && tableRowInfo.attributionType === 1) this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/DeviceStructure/HasReceivedDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
<template>
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange">
    </a-table>
    <DocumentModal ref="modalForm" @ok="modalFormOk"/>
  </div>
</template>
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from '../../../common/DocumentModal.vue'
  export default {
    name: 'HasSentDocumentTableList',
    components: { DocumentModal },
    mixins: [JeecgListMixin],
    props: {
      currentTreeNodeInfo: {
        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: 'docName', align: 'center' },
          { title: '代码版本', dataIndex: 'docAlias', align: 'center' },
          { title: '出库状态', dataIndex: 'pullStatus_dictText', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus_dictText', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [],
        currentRightClickedDocumentInfo: {},
        currentClickedDocumentInfo: {},
        url: {
          list: '/nc/doc/find/page/device'
        }
      }
    },
    created() {
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      loadData(arg) {
        if (!this.url.list) {
          this.$message.error('请设置url.list属性!')
          return
        }
        //加载数据 è‹¥ä¼ å…¥å‚æ•°1则加载第一页的内容
        if (arg === 1) this.ipagination.current = 1
        var params = this.getQueryParams()//查询条件
        console.log('currentTreeNodeInfo', this.currentTreeNodeInfo)
        params.attributionId = this.currentTreeNodeInfo.key
        params.attributionType = 4
        params.docClassCode = 'SEND'
        if (!params) return false
        this.dataSource = []
        this.loading = true
        getAction(this.url.list + `/${this.ipagination.current}/${this.ipagination.pageSize}`, params).then((res) => {
          if (res.success) {
            this.dataSource = res.result.records
            if (res.result.total) {
              this.ipagination.total = res.result.total
            } else {
              this.ipagination.total = 0
            }
          } else {
            this.$message.warning(res.message)
          }
        }).finally(() => {
          this.loading = false
        })
      },
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.currentRightClickedDocumentInfo = Object.assign({ param: 'SEND' }, record)
              this.$emit('handleTableContextMenuOpen', this.currentRightClickedDocumentInfo)
            },
            click: () => {
              if (this.currentClickedDocumentInfo.docId === record.docId) return
              this.currentClickedDocumentInfo = Object.assign({}, record)
              this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
            }
          }
        }
      },
      handleDocumentEdit(record, modalTitle) {
        this.$refs.modalForm.edit(record)
        this.$refs.modalForm.title = modalTitle
      },
      handleDocumentAssign(record, modalTitle) {
        this.$refs.documentAssignModalRef.title = modalTitle
        this.$refs.documentAssignModalRef.visible = true
      },
      handleDelete() {
        // æ­¤å¤„函数为屏蔽mixins中的同名函数,通用函数写在父级中
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName] && tableRowInfo.param === 'SEND') this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/DeviceStructure/HasSentDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
<template>
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange">
    </a-table>
    <DocumentModal ref="modalForm" @ok="modalFormOk"/>
  </div>
</template>
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from '../../../common/DocumentModal.vue'
  export default {
    name: 'HasSentDocumentTableList',
    components: { DocumentModal },
    mixins: [JeecgListMixin],
    props: {
      currentTreeNodeInfo: {
        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: 'docName', align: 'center' },
          { title: '代码版本', dataIndex: 'docAlias', align: 'center' },
          { title: '出库状态', dataIndex: 'pullStatus_dictText', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus_dictText', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [],
        currentRightClickedDocumentInfo: {},
        currentClickedDocumentInfo: {},
        url: {
          list: '/nc/doc/find/page/device'
        }
      }
    },
    created() {
      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      loadData(arg) {
        if (!this.url.list) {
          this.$message.error('请设置url.list属性!')
          return
        }
        //加载数据 è‹¥ä¼ å…¥å‚æ•°1则加载第一页的内容
        if (arg === 1) this.ipagination.current = 1
        var params = this.getQueryParams()//查询条件
        console.log('currentTreeNodeInfo', this.currentTreeNodeInfo)
        params.attributionId = this.currentTreeNodeInfo.key
        params.attributionType = 4
        params.docClassCode = 'SEND'
        if (!params) return false
        this.dataSource = []
        this.loading = true
        getAction(this.url.list + `/${this.ipagination.current}/${this.ipagination.pageSize}`, params).then((res) => {
          if (res.success) {
            this.dataSource = res.result.records
            if (res.result.total) {
              this.ipagination.total = res.result.total
            } else {
              this.ipagination.total = 0
            }
          } else {
            this.$message.warning(res.message)
          }
        }).finally(() => {
          this.loading = false
        })
      },
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.currentRightClickedDocumentInfo = Object.assign({ param: 'SEND' }, record)
              this.$emit('handleTableContextMenuOpen', this.currentRightClickedDocumentInfo)
            },
            click: () => {
              if (this.currentClickedDocumentInfo.docId === record.docId) return
              this.currentClickedDocumentInfo = Object.assign({}, record)
              this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
            }
          }
        }
      },
      handleDocumentEdit(record, modalTitle) {
        this.$refs.modalForm.edit(record)
        this.$refs.modalForm.title = modalTitle
      },
      handleDocumentAssign(record, modalTitle) {
        this.$refs.documentAssignModalRef.title = modalTitle
        this.$refs.documentAssignModalRef.visible = true
      },
      handleDelete() {
        // æ­¤å¤„函数为屏蔽mixins中的同名函数,通用函数写在父级中
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName] && tableRowInfo.param === 'SEND') this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/DeviceStructure/Workshop/WorkshopInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="车间名称">{{currentLevelDetails.title}}</a-descriptions-item>
    <a-descriptions-item label="备注">{{currentLevelDetails.memo}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
  export default {
    name: 'WorkshopInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
@@ -15,7 +15,7 @@
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from './DocumentModal'
  import DocumentModal from '../../../../common/DocumentModal'
  import NcDocumentAssignModal from './NcDocumentAssignModal'
  export default {
@@ -121,8 +121,12 @@
        this.$refs.documentAssignModalRef.visible = true
      },
      handleDelete() {
        // æ­¤å¤„函数为屏蔽mixins中的同名函数,通用函数写在父级中
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName]) this[methodName](tableRowInfo, modalTitle)
        if (this[methodName] && tableRowInfo.param === 'NC') this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
src/views/dnc/base/modules/ProductStructure/Document/OtherDocumentTableList.vue
@@ -12,7 +12,7 @@
<script>
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from './DocumentModal'
  import DocumentModal from '../../../../common/DocumentModal'
  export default {
    name: 'OtherDocumentTableList',
@@ -110,8 +110,12 @@
        this.$refs.modalForm.title = modalTitle
      },
      handleDelete() {
        // æ­¤å¤„函数为屏蔽mixins中的同名函数,通用函数写在父级中
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle, tableRowInfo }) {
        if (this[methodName] && tableRowInfo.attributionType === 1) this[methodName](tableRowInfo, modalTitle)
        if (this[methodName] && tableRowInfo.param === 'OTHER') this[methodName](tableRowInfo, modalTitle)
      }
    }
  }
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
@@ -52,11 +52,11 @@
  import ComponentInfo from './Component/ComponentInfo'
  import PartInfo from './Part/PartInfo'
  import ProcessInfo from './Process/ProcessInfo'
  import DocumentInfo from './Document/DocumentInfo'
  import DocumentVersionTableList from './Document/DocumentVersionTableList'
  import DocumentInfo from '../../../common/DocumentInfo'
  import DocumentVersionTableList from '../../../common/DocumentVersionTableList'
  import UseDocumentEquipmentTableList from './Document/UseNcDocumentEquipmentTableList'
  import ProcessStepInfo from './ProcessStep/ProcessStepInfo'
  import FilePreview from './Document/FilePreview'
  import FilePreview from '../../../common/FilePreview'
  import TableContextMenu from '../../../common/TableContextMenu'
  export default {
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
@@ -86,9 +86,7 @@
        }
      },
      /**
       * ç‚¹å‡»ä¸‹è½½æ—¶è§¦å‘下载当前文档
       */
      // ä¸‹è½½å½“前右键选中文档
      handleDownload() {
        const that = this
        const { docId, docName } = this.currentRightClickedTableRowInfo
@@ -109,14 +107,49 @@
          })
      },
      // åˆ é™¤å½“前右键选中文档
      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
        this.$confirm({
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
@@ -126,7 +159,7 @@
              .then(res => {
                console.log('res------------------', res)
                if (res.success) {
                  this.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.reloadDocumentListData({ docClassCode: param, attributionId })
                  that.$notification.success({
                    message: '消息',
                    description: `${menuLabel}成功`
@@ -144,18 +177,24 @@
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel: () => {
            that.$destroyAll()
          }
        })
      },
      /**
       * ç‚¹å‡»å–消出库时触发当前文档取消出库
       * å–消出库当前右键选中文档
       * @param menuLabel
       */
      handleCancelPull(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        this.$confirm({
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
@@ -182,19 +221,24 @@
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
      /**
       * ç‚¹å‡»å‘布时触发当前文档发布
       * å‘布当前右键选中文档
       * @param menuLabel
       */
      handlePublish(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        this.$confirm({
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
@@ -222,18 +266,24 @@
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
      /**
       * ç‚¹å‡»é‡æ–°å‘布时触发当前文档重新发布退回上一版本
       * é‡æ–°å‘布当前右键选中文档并重新发布退回上一文档版本
       * @param menuLabel
       */
      handleRepublish(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        this.$confirm({
        that.$confirm({
          title: '提示',
          content: `确认${menuLabel}吗?`,
          okText: '确认',
@@ -260,18 +310,24 @@
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
      /**
       * ç‚¹å‡»å½’档时触发当前文档归档且后续无法继续发布或归档
       * é‡å½’档当前右键选中文档且后续无法继续发布或归档
       * @param menuLabel
       */
      handlePigeonhole(menuLabel) {
        const that = this
        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
        this.$confirm({
        that.$confirm({
          title: '提示',
          content: `${menuLabel}后不可取消,确认${menuLabel}吗?`,
          okText: '确认',
@@ -298,13 +354,17 @@
                  description: err.message
                })
              })
              .finally(() => {
                that.$destroyAll()
              })
          },
          onCancel() {
            that.$destroyAll()
          }
        })
      },
      /**
       * æŽ§åˆ¶å³é”®èœå•点击关闭
       */
      // æŽ§åˆ¶å³é”®èœå•关闭
      handleMenuClose() {
        this.$refs.tableContextMenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleMenuClose)
src/views/dnc/common/DocumentBatchDeleteModal.vue
src/views/dnc/common/DocumentInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="文档名称">{{currentLevelDetails.docName}}</a-descriptions-item>
    <a-descriptions-item label="代码版本">{{currentLevelDetails.docAlias}}</a-descriptions-item>
    <a-descriptions-item label="设备编号    ">{{currentLevelDetails.docCode}}</a-descriptions-item>
    <a-descriptions-item label="文档后缀">{{currentLevelDetails.docSuffix}}</a-descriptions-item>
    <a-descriptions-item label="文档状态">{{currentLevelDetails.docStatus_dictText}}</a-descriptions-item>
    <a-descriptions-item label="系统指定版本">{{currentLevelDetails.publishVersion}}</a-descriptions-item>
    <a-descriptions-item label="出库状态">{{currentLevelDetails.pullStatus_dictText}}</a-descriptions-item>
    <a-descriptions-item label="出库人" :span="2">{{currentLevelDetails.pullUser_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
  export default {
    name: 'DocumentInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/common/DocumentModal.vue
src/views/dnc/common/DocumentModalForm.vue
src/views/dnc/common/DocumentVersionTableList.vue
src/views/dnc/common/FileCompareModal.vue
src/views/dnc/common/FilePreview.vue
src/views/dnc/common/ImportFileModal.vue
@@ -59,12 +59,14 @@
        if (treeNodeInfo) {
          attributionId = treeNodeInfo.treeKey
          attributionType = treeNodeInfo.type
          if (attributionType === 5 || attributionType === 6) docClassCode = 'NC'
          else if (attributionType === 4) docClassCode = 'SEND'
          else docClassCode = 'OTHER'
        } else {
          attributionId = tableRowInfo.attributionId
          attributionType = tableRowInfo.attributionType
          docClassCode = tableRowInfo.param
        }
        if (attributionType === 5 || attributionType === 6) docClassCode = 'NC'
        else docClassCode = 'OTHER'
        this.uploadParams = Object.assign({}, { attributionId, attributionType, docClassCode })
        this.visible = true
      },
@@ -97,9 +99,7 @@
        return false
      },
      /**
       * ç‚¹å‡»ä¸Šä¼ è‡³æœåŠ¡å™¨æŒ‰é’®æ—¶è§¦å‘
       */
      // ç‚¹å‡»ä¸Šä¼ è‡³æœåŠ¡å™¨æŒ‰é’®æ—¶è§¦å‘
      handleUpload() {
        const { fileList, $notification, isUploadMultiple, uploadParams, $bus, handleModalClose } = this
        this.uploading = true
@@ -171,9 +171,7 @@
        this.fileList = newFileList
      },
      /**
       * æŽ§åˆ¶æ–‡ä»¶ä¸Šä¼ çª—口关闭并清空文件列表
       */
      // æŽ§åˆ¶æ–‡ä»¶ä¸Šä¼ çª—口关闭并清空文件列表
      handleModalClose() {
        this.visible = false
        this.fileList = []
src/views/dnc/common/SelectFileCompareModal.vue
src/views/dnc/common/TableContextMenu.vue
@@ -81,6 +81,25 @@
              icon: 'hourglass'
            }
          ],
          SEND: [
            { label: '编辑文档信息', code: 'document_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
            { label: '导入NC程序', code: 'document_import', subMenu: [], icon: 'import', isCommonMethod: true },
            { label: '下载', code: 'document_download', subMenu: [], icon: 'download', isCommonMethod: true },
            { label: '删除', code: 'document_delete', subMenu: [], icon: 'delete', isCommonMethod: true },
            { label: '批量删除', code: 'document_batch_remove', subMenu: [], icon: 'delete', isCommonMethod: false },
            {
              label: '生命周期',
              subMenu: [
                { label: '出库', code: 'document_pull', icon: 'export', isCommonMethod: true },
                { label: '取消出库', code: 'document_cancel_pull', icon: 'stop', isCommonMethod: true },
                { label: '入库', code: 'document_push', icon: 'import', isCommonMethod: true },
                { label: '发布', code: 'document_publish', icon: 'flag', isCommonMethod: true },
                { label: '重新发布', code: 'document_republish', icon: 'reload', isCommonMethod: true },
                { label: '归档', code: 'document_pigeonhole', icon: 'database', isCommonMethod: true }
              ],
              icon: 'hourglass'
            }
          ],
          //文件
          file: [
            { label: '指定当前版本', code: 'file_assign', subMenu: [], icon: 'highlight', isCommonMethod: false },//文件-指定当前版本