DNC产品结构树合并至MDC,已初步完成页面布局,现正在完善各个功能弹窗逻辑
已添加25个文件
已修改1个文件
2809 ■■■■■ 文件已修改
src/main.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/ProductStructure.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Component/ComponentModal.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Component/ComponentModalForm.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/DocumentInfo.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/DocumentVersionTableList.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/OtherDocumentTableList.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/UseDocumentEquipmentTableList.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessModal.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Process/ProcessTableList.vue 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Product/ProductModal.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Product/ProductModalForm.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/ImportFileModal.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/ProductStructureTree.vue 644 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/TableContextMenu.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/modules/ProductStructureTree/ProductStructureTreeContextMenu.vue 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js
@@ -80,6 +80,9 @@
  new Vue({
    router,
    store,
    beforeCreate() {
      Vue.prototype.$bus = new Vue()
    },
    mounted () {
      store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true))
      store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme))
src/views/dnc/base/ProductStructure.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
<template>
  <a-card :bordered="false">
    <a-row type="flex" :gutter="16">
      <a-col :md="5">
        <ProductStructureTree/>
      </a-col>
      <a-col :md="19">
        <ProductStructureMain/>
      </a-col>
    </a-row>
  </a-card>
</template>
<script>
  import ProductStructureTree from '../common/ProductStructureTree'
  import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
  export default {
    name: 'ProductStructure',
    components: {
      ProductStructureTree,
      ProductStructureMain
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped lang="less">
  /deep/ .ant-card-body {
    padding: 8px;
  }
</style>
src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="部件名称">{{currentLevelDetails.componentName}}</a-descriptions-item>
    <a-descriptions-item label="部件代号">{{currentLevelDetails.componentCode}}</a-descriptions-item>
    <a-descriptions-item label="部件型号    ">{{currentLevelDetails.componentModel}}</a-descriptions-item>
    <a-descriptions-item label="物料编码">{{currentLevelDetails.materielCode}}</a-descriptions-item>
    <a-descriptions-item label="材料">{{currentLevelDetails.materielDesp}}</a-descriptions-item>
    <a-descriptions-item label="规格    ">{{currentLevelDetails.componentScale}}</a-descriptions-item>
    <a-descriptions-item label="装配类型">{{currentLevelDetails.assembleType}}</a-descriptions-item>
    <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.createUser_dicText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateUser_dicText}}</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: 'ComponentInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Component/ComponentModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    :maskClosable="false"
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <ComponentModalForm ref="realForm" @ok="submitCallback"/>
  </j-modal>
</template>
<script>
  import ComponentModalForm from './ComponentModalForm.vue'
  export default {
    name: 'ComponentModal',
    components: {
      ComponentModalForm
    },
    props: {
      currentTreeNodeInfo: {
        type: Object
      }
    },
    data() {
      return {
        title: '',
        width: 700,
        visible: false
      }
    },
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      /**
       * æ·»åŠ å½“å‰äº§å“éƒ¨ä»¶
       * @param modalTitle
       */
      handleProductAddChild(modalTitle) {
        this.title = modalTitle
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.add()
        })
      },
      /**
       * æ·»åŠ å½“å‰éƒ¨ä»¶çš„å­éƒ¨ä»¶
       * @param modalTitle
       */
      handleComponentAdd(modalTitle) {
        this.title = modalTitle
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.add()
        })
      },
      handleComponentEdit(modalTitle) {
        this.title = modalTitle
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.edit(this.currentTreeNodeInfo.entity)
        })
      },
      handleOk() {
        this.$refs.realForm.submitForm()
      },
      submitCallback() {
        this.$emit('ok')
        this.visible = false
      },
      handleCancel() {
        this.$emit('close')
        this.visible = false
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        console.log('methodName', methodName)
        console.log('modalTitle', modalTitle)
        if (this[methodName]) this[methodName](modalTitle)
      }
    }
  }
</script>
src/views/dnc/base/modules/ProductStructure/Component/ComponentModalForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,174 @@
<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="componentName">
            <a-input v-model="model.componentName" placeholder="请输入部件名称"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="代号" prop="componentCode">
            <a-input v-model="model.componentCode" placeholder="请输入代号"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="部件型号">
            <a-input v-model="model.componentModel" placeholder="请输入部件型号"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="规格">
            <a-input v-model="model.productName" placeholder="请输入规格"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="装配类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.assembleType" placeholder="请输入装配类型"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="重量">
            <a-input v-model="model.componentWeight" placeholder="请输入重量"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="物料编码">
            <a-input v-model="model.materielCode" placeholder="请输入物料编码"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="结构类型">
            <a-input v-model="model.structureType" placeholder="请输入结构类型"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="处理类型">
            <a-input v-model="model.processType" placeholder="请输入处理类型"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="生产类型">
            <a-input v-model="model.produceType" placeholder="请输入生产类型"></a-input>
          </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="请输入描述"></a-textarea>
          </a-form-model-item>
        </a-col>
      </a-row>
    </a-form-model>
  </a-spin>
</template>
<script>
  import { httpAction, getAction } from '@/api/manage'
  export default {
    name: 'ComponentModalForm',
    components: {},
    data() {
      return {
        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,
        validatorRules: {
          componentName: [
            { required: true, message: '请输入部件名称!' }
          ],
          componentCode: [
            { required: true, message: '请输入代号!' }
          ]
        },
        url: {
          add: '/mdc/mdcPartProcessInfo/add',
          edit: '/mdc/mdcPartProcessInfo/edit'
        }
      }
    },
    computed: {
      formDisabled() {
        return this.disabled
      }
    },
    created() {
      //备份model原始值
      this.modelDefault = JSON.parse(JSON.stringify(this.model))
    },
    methods: {
      add() {
        this.edit(this.modelDefault)
      },
      edit(record) {
        this.model = Object.assign({}, record)
        console.log('model', this.model)
        this.visible = true
      },
      submitForm() {
        const that = this
        // è§¦å‘表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true
            let httpUrl = ''
            let method = 'post'
            if (!this.model.id) {
              httpUrl += this.url.add
            } else {
              httpUrl += this.url.edit
            }
            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/Document/DocumentInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
<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}}</a-descriptions-item>
    <a-descriptions-item label="系统指定版本">{{currentLevelDetails.publishVersion}}</a-descriptions-item>
    <a-descriptions-item label="出库状态">{{currentLevelDetails.pullStatus}}</a-descriptions-item>
    <a-descriptions-item label="出库人" :span="2">{{currentLevelDetails.pullUser}}</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/base/modules/ProductStructure/Document/DocumentVersionTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
<template>
  <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false">
  </a-table>
</template>
<script>
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  export default {
    name: 'DocumentVersionTableList',
    mixins: [JeecgListMixin],
    components: {},
    data() {
      return {
        columns: [
          {
            title: '序号',
            dataIndex: 'rowIndex',
            key: 'rowIndex',
            width: 65,
            align: 'center',
            customRender: function(t, r, index) {
              return parseInt(index) + 1
            }
          },
          { title: '文件名称', dataIndex: 'fileName', align: 'center' },
          { title: '版本号', dataIndex: 'docVersion', align: 'center' },
          { title: '文件大小', dataIndex: 'fileSize', align: 'center' }
        ],
        url: {
          list: ''
        }
      }
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,199 @@
<template>
  <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
           :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId">
  </a-table>
</template>
<script>
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  export default {
    name: 'NcDocumentTableList',
    components: {},
    mixins: [JeecgListMixin],
    props: {
      size: {
        type: String
      }
    },
    data() {
      return {
        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', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [
          {
            'docId': '1876099281127645185',
            'docName': 'avatar2.jpg',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'jpg',
            'docStatus': 1,
            'publishFileId': '1876099281458995202',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 10:51:40',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          },
          {
            'docId': '1876114720452943873',
            'docName': 'color.less',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'less',
            'docStatus': 1,
            'publishFileId': '1876114720582967297',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 11:53:01',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          },
          {
            'docId': '1876114736512933889',
            'docName': 'index.html',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'html',
            'docStatus': 1,
            'publishFileId': '1876114736705871874',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 11:53:05',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          },
          {
            'docId': '1876114746621206529',
            'docName': 'logo.png',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'png',
            'docStatus': 1,
            'publishFileId': '1876114746818338818',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 11:53:07',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          },
          {
            'docId': '1876114758923100161',
            'docName': 'lxzn.png',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'png',
            'docStatus': 1,
            'publishFileId': '1876114759111843842',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 11:53:10',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          },
          {
            'docId': '1876114776241381377',
            'docName': 'v2.js',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'js',
            'docStatus': 1,
            'publishFileId': '1876114776438513666',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2025-01-06 11:53:14',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 5,
            'attributionId': '1868504592315248641',
            'classificationId': '1257965381181095938',
            'syncStatus': null
          }
        ],
        url: {
          list: ''
        }
      }
    },
    methods: {
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.$emit('handleTableContextMenuOpen', { ...record, param: 'document' })
            },
            click: () => {
              this.$bus.$emit('sendCurrentLevelInfo', record)
            }
          }
        }
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Document/OtherDocumentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
<template>
  <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
           :scroll="{y:189}" :customRow="customRow" :size="size">
  </a-table>
</template>
<script>
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  export default {
    name: 'OtherDocumentTableList',
    components: {},
    mixins: [JeecgListMixin],
    props: {
      size: {
        type: String
      }
    },
    data() {
      return {
        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', align: 'center' },
          { title: '状  æ€', dataIndex: 'docStatus', align: 'center' },
          { title: '系统指定版本', dataIndex: 'publishVersion', align: 'center' },
          { title: '上传时间', dataIndex: 'createTime', align: 'center' }
        ],
        dataSource: [
          {
            'docId': '1868943615190044674',
            'docName': '测试.nc',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'nc',
            'docStatus': 1,
            'publishFileId': '1868943615454285825',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2024-12-17 16:57:36',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 1,
            'attributionId': '1326377675659276290',
            'classificationId': '1257965467827027969',
            'syncStatus': null
          },
          {
            'docId': '1868946627732103170',
            'docName': 'nacos-config.sh',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'sh',
            'docStatus': 1,
            'publishFileId': '1868946628004732930',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2024-12-17 17:09:34',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 1,
            'attributionId': '1326377675659276290',
            'classificationId': '1257965467827027969',
            'syncStatus': null
          },
          {
            'docId': '1868947564353740801',
            'docName': 'dir.sql',
            'docAlias': null,
            'docCode': null,
            'docSuffix': 'sql',
            'docStatus': 1,
            'publishFileId': '1868947564487958530',
            'publishVersion': 'a.1',
            'description': null,
            'createTime': '2024-12-17 17:13:17',
            'updateTime': null,
            'createUser': '1254966905669160962',
            'updateUser': null,
            'docClassCode': null,
            'pullStatus': 1,
            'pullUser': null,
            'attributionType': 1,
            'attributionId': '1326377675659276290',
            'classificationId': '1257965467827027969',
            'syncStatus': null
          }
        ],
        url: {
          list: ''
        }
      }
    },
    methods: {
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.$emit('handleTableContextMenuOpen', { ...record, param: 'document' })
            },
            click: () => {
              this.$bus.$emit('sendCurrentLevelInfo', record)
            }
          }
        }
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Document/UseDocumentEquipmentTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
<template>
  <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false">
  </a-table>
</template>
<script>
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  export default {
    name: 'UseDocumentEquipmentTableList',
    components: {},
    mixins: [JeecgListMixin],
    data() {
      return {
        columns: [
          {
            title: '序号',
            dataIndex: 'rowIndex',
            key: 'rowIndex',
            width: 65,
            align: 'center',
            customRender: function(t, r, index) {
              return parseInt(index) + 1
            }
          },
          { title: '设备名称', dataIndex: 'deviceName', align: 'center' },
          { title: '设备编号', dataIndex: 'deviceNo', align: 'center' },
          { title: '设备型号', dataIndex: 'deviceModel', align: 'center' },
          { title: '所属部门', dataIndex: 'departName', align: 'center' },
          { title: '设备分组', dataIndex: 'groupName', align: 'center' },
          { title: '控制系统', dataIndex: 'controlSystem', align: 'center' }
        ],
        url: {
          list: ''
        }
      }
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="零件名称">{{currentLevelDetails.partsName}}</a-descriptions-item>
    <a-descriptions-item label="零件代号">{{currentLevelDetails.partsCode}}</a-descriptions-item>
    <a-descriptions-item label="零件型号    ">{{currentLevelDetails.partsModel}}</a-descriptions-item>
    <a-descriptions-item label="物料编码">{{currentLevelDetails.materielCode}}</a-descriptions-item>
    <a-descriptions-item label="材料">{{currentLevelDetails.materielDesp}}</a-descriptions-item>
    <a-descriptions-item label="规格    ">{{currentLevelDetails.partsScale}}</a-descriptions-item>
    <a-descriptions-item label="装配类型">{{currentLevelDetails.assembleType}}</a-descriptions-item>
    <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.createUser_dicText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateUser_dicText}}</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: 'PartInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="工序名称">{{currentLevelDetails.processName|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="工序号">{{currentLevelDetails.processCode|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="工艺编号    ">{{currentLevelDetails.craftNo|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="工序类型">{{currentLevelDetails.processType|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="加工设备型号">{{currentLevelDetails.processingEquipmentModel|isValueNull}}
    </a-descriptions-item>
    <a-descriptions-item label="加工设备类型">{{currentLevelDetails.processingEquipmentOs|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="加工设备编号">{{currentLevelDetails.processingEquipmentCode|isValueNull}}
    </a-descriptions-item>
    <a-descriptions-item label="工装编号">{{currentLevelDetails.assembleStep|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="工装名称    ">{{currentLevelDetails.assembleName|isValueNull}}</a-descriptions-item>
    <a-descriptions-item label="描述" :span="3">{{currentLevelDetails.description|isValueNull}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
  export default {
    name: 'ProcessInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    filters: {
      isValueNull(value) {
        return !value || value == null ? '' : value
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Process/ProcessModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    :maskClosable="false"
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <ProcessModalForm ref="realForm" @ok="submitCallback"/>
  </j-modal>
</template>
<script>
  import ProcessModalForm from './ProcessModalForm.vue'
  export default {
    name: 'ProcessModal',
    components: {
      ProcessModalForm
    },
    data() {
      return {
        title: '',
        width: 700,
        visible: false
      }
    },
    methods: {
      add() {
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.add()
        })
      },
      edit(record) {
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.edit(record)
        })
      },
      handleOk() {
        this.$refs.realForm.submitForm()
      },
      submitCallback() {
        this.$emit('ok')
        this.visible = false
      },
      handleCancel() {
        this.$emit('close')
        this.visible = false
      }
    }
  }
</script>
src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,196 @@
<template>
  <a-spin :spinning="confirmLoading">
    <a-form-model ref="form" :model="model" :rules="validatorRules">
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="工序号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="processCode">
            <a-input v-model="model.processCode" placeholder="请输入工序号"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="工序名称" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="processName">
            <a-input v-model="model.processName" placeholder="请输入工序名称"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="24">
          <a-form-model-item label="加工设备编号" :labelCol="labelColLong" :wrapperCol="wrapperColLong">
            <a-select v-model="model.processingEquipmentCode" placeholder="请选择加工设备编号"></a-select>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="工艺编号" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.craftNo" placeholder="请输入工艺编号"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="工艺规程版本" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.craftVersion" placeholder="请输入工艺规程版本"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="工序类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.processType" placeholder="请输入工序类型"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="工序描述" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.description" placeholder="请输入工序描述"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="12">
          <a-form-model-item label="工装编号" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.assembleStep" placeholder="请输入工装编号"></a-input>
          </a-form-model-item>
        </a-col>
        <a-col :span="12">
          <a-form-model-item label="工装名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input v-model="model.assembleName" placeholder="请输入工装名称"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
    </a-form-model>
    <select-device-drawer ref="selectDeviceDrawer" @selectFinished="selectOK" :title="'选择设备'"/>
  </a-spin>
</template>
<script>
  import { httpAction, getAction } from '@/api/manage'
  import SelectDeviceDrawer from '@/views/system/modules/SelectDeviceDrawer'
  export default {
    name: 'ProcessModalForm',
    components: { SelectDeviceDrawer },
    data() {
      return {
        model: {
          passCount: 0
        },
        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: {
          equipmentIds: [
            { required: true, message: '请选择设备!' }
          ],
          partId: [
            { required: true, message: '请输入零件号!' }
          ],
          standardProcessLong: [
            { required: true, message: '请输入标准加工工时(min)!' }
          ],
          processCount: [
            { required: true, message: '请输入加工零件数量!' }
          ],
          passCount: [
            { required: true, message: '请输入合格零件数量!' }
          ],
          theDate: [
            { required: true, message: '请选择日期!' }
          ]
        },
        url: {
          add: '/mdc/mdcPartProcessInfo/add',
          edit: '/mdc/mdcPartProcessInfo/edit'
        }
      }
    },
    computed: {
      formDisabled() {
        return this.disabled
      }
    },
    created() {
      //备份model原始值
      this.modelDefault = JSON.parse(JSON.stringify(this.model))
    },
    methods: {
      add() {
        this.edit(this.modelDefault)
      },
      edit(record) {
        this.model = Object.assign({}, { equipmentIds: record.equipmentId }, record)
        console.log('model', this.model)
        this.visible = true
      },
      inputNumberChange() {
        if (this.model.standardProcessLong && this.model.processCount) {
          this.model.totalProcessLong = this.model.standardProcessLong * this.model.processCount
        }
      },
      submitForm() {
        const that = this
        // è§¦å‘表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true
            let httpUrl = ''
            let method = 'post'
            if (!this.model.id) {
              httpUrl += this.url.add
            } else {
              httpUrl += this.url.edit
            }
            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
            })
          }
        })
      },
      deviceSearch() {
        this.$refs.selectDeviceDrawer.visible = true
        this.$refs.selectDeviceDrawer.selectedRowKeys = []
        this.$refs.selectDeviceDrawer.selectedRows = []
        this.$refs.selectDeviceDrawer.checkedKeys = this.model.equipmentIds ? this.model.equipmentIds.split(',') : []
      },
      /**
       * é€‰æ‹©å·²æœ‰è®¾å¤‡åŽç‚¹å‡»ç¡®å®šæ—¶è§¦å‘
       * @param data å·²é€‰æ‹©çš„设备
       */
      selectOK(data) {
        this.$set(this.model, 'equipmentIds', data.join(','))
        if (this.model.equipmentIds) this.$refs.form.clearValidate('equipmentIds')
      }
    }
  }
</script>
src/views/dnc/base/modules/ProductStructure/Process/ProcessTableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,248 @@
<template>
  <div>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false"
             :scroll="{y:227}" :customRow="customRow" :size="size" rowKey="processId">
    </a-table>
    <ProcessModal ref="modalForm" @ok="modalFormOk"/>
    <ImportFileModal ref="importFileModal"/>
  </div>
</template>
<script>
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import ProcessModal from './ProcessModal'
  import ImportFileModal from '../../../../common/ImportFileModal'
  export default {
    name: 'ProcessTableList',
    components: { ImportFileModal, ProcessModal },
    mixins: [JeecgListMixin],
    props: {
      size: {
        type: String
      }
    },
    data() {
      return {
        columns: [
          {
            title: '工序号',
            dataIndex: 'processCode',
            align: 'center',
            sorter: (a, b) => a.processNo - b.processNo,
            sortDirections: ['descend', 'ascend']
          },
          {
            title: '工序编号',
            dataIndex: 'craftNo',
            align: 'center',
            sorter: (a, b) => a.processId - b.processId,
            sortDirections: ['descend', 'ascend']
          },
          {
            title: '工序名称',
            dataIndex: 'processName',
            align: 'center',
            sorter: (a, b) => a.processName.length - b.processName.length,
            sortDirections: ['descend', 'ascend']
          }
        ],
        dataSource: [
          {
            'processId': '1327516286572163080',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': null,
            'processCode': '1',
            'craftNo': null,
            'craftVersion': null,
            'processType': null,
            'processingEquipmentModel': null,
            'processingEquipmentCode': null,
            'assembleStep': null,
            'assembleName': null,
            'description': null
          },
          {
            'processId': '1701841077007798274',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': '2113',
            'processCode': '111',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          },
          {
            'processId': '1875082575626289153',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': '333',
            'processCode': '3213',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          },
          {
            'processId': '1875082597210177537',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': '123',
            'processCode': 'sd',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          },
          {
            'processId': '1875082616835325954',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': 'dadas',
            'processCode': 'sadsa',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          },
          {
            'processId': '1875082638553432066',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': '1213',
            'processCode': 'das',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          },
          {
            'processId': '1875082668072943617',
            'productId': '1326377675659276290',
            'componentId': '1327516286505054210',
            'partsId': null,
            'processName': 'zxccz',
            'processCode': 'asdasda',
            'craftNo': '',
            'craftVersion': '',
            'processType': 0,
            'processingEquipmentModel': '',
            'processingEquipmentCode': '',
            'assembleStep': '',
            'assembleName': '',
            'description': ''
          }
        ],
        currentRowInfo: {},
        url: {
          list: '',
          add: '',
          edit: '',
          delete: ''
        }
      }
    },
    created() {
      this.$bus.$on('menuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      /**
       * è‡ªå®šä¹‰è¡¨æ ¼è¡ŒåŠŸèƒ½
       * @param record è¡¨æ ¼è¡Œä¿¡æ¯
       * @returns {{on: {contextmenu: on.contextmenu, click: on.click}}} è¿”回事件方法对象
       */
      customRow(record) {
        return {
          on: {
            contextmenu: event => {
              event.preventDefault()
              this.currentRowInfo = Object.assign({}, record)
              this.$emit('handleTableContextMenuOpen', { objectId: record.processId, param: 'process' })
            },
            click: () => {
              this.$bus.$emit('sendCurrentLevelInfo', record)
            }
          }
        }
      },
      /**
       * ç‚¹å‡»åˆ›å»ºå·¥åºèœå•时触发
       * @param modalTitle
       */
      handleProcessAdd(modalTitle) {
        this.$refs.modalForm.add()
        this.$refs.modalForm.title = modalTitle
      },
      /**
       * ç‚¹å‡»ç¼–辑工序菜单时触发
       * @param modalTitle
       */
      handleProcessEdit(modalTitle) {
        this.$refs.modalForm.edit(this.currentRowInfo)
        this.$refs.modalForm.title = modalTitle
      },
      /**
       *  ç‚¹å‡»åˆ é™¤æ—¶è§¦å‘
       */
      handleProcessDelete() {
        this.$confirm({
          title: '提示',
          content: '确认删除此条记录吗?',
          okText: '确认',
          okType: 'danger',
          cancelText: '取消',
          onOk: () => {
            this.handleDelete(this.currentRowInfo.processId)
          }
        })
      },
      handleProcessImport(modalTitle) {
        this.$refs.importFileModal.visible = true
        this.$refs.importFileModal.title = modalTitle
      },
      triggerCorrespondingMethod({ methodName, level, modalTitle }) {
        if (level === 'process') this[methodName](modalTitle)
      }
    }
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<template>
    <div>
    </div>
</template>
<script>
  export default {
    name: 'ProcessStepInfo',
    components: {},
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
<template>
  <a-descriptions bordered :size="size">
    <a-descriptions-item label="产品名称">{{currentLevelDetails.productName}}</a-descriptions-item>
    <a-descriptions-item label="产品型号">{{currentLevelDetails.productModel}}</a-descriptions-item>
    <a-descriptions-item label="产品代码    ">{{currentLevelDetails.productNo}}</a-descriptions-item>
    <a-descriptions-item label="创建人">{{currentLevelDetails.createUser_dicText}}</a-descriptions-item>
    <a-descriptions-item label="创建时间" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
    <a-descriptions-item label="修改人">{{currentLevelDetails.updateUser_dicText}}</a-descriptions-item>
    <a-descriptions-item label="修改时间" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
  </a-descriptions>
</template>
<script>
  export default {
    name: 'ProductInfo',
    components: {},
    props: {
      currentLevelDetails: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {}
    },
    methods: {}
  }
</script>
<style scoped>
</style>
src/views/dnc/base/modules/ProductStructure/Product/ProductModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    :maskClosable="false"
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <ProductModalForm ref="realForm" @ok="submitCallback"/>
  </j-modal>
</template>
<script>
  import ProductModalForm from './ProductModalForm.vue'
  export default {
    name: 'ProductModal',
    components: {
      ProductModalForm
    },
    props: {
      currentTreeNodeInfo: {
        type: Object
      }
    },
    data() {
      return {
        title: '',
        width: 500,
        visible: false
      }
    },
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      handleProductAdd(modalTitle) {
        this.title = modalTitle
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.add()
        })
      },
      handleProductEdit(modalTitle) {
        this.title = modalTitle
        this.visible = true
        this.$nextTick(() => {
          this.$refs.realForm.edit(this.currentTreeNodeInfo.entity)
        })
      },
      handleOk() {
        this.$refs.realForm.submitForm()
      },
      submitCallback() {
        this.$emit('ok')
        this.visible = false
      },
      handleCancel() {
        this.$emit('close')
        this.visible = false
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) this[methodName](modalTitle)
      }
    }
  }
</script>
src/views/dnc/base/modules/ProductStructure/Product/ProductModalForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
<template>
  <a-spin :spinning="confirmLoading">
    <a-form-model ref="form" :model="model" :rules="validatorRules" :labelCol="labelColLong"
                  :wrapperCol="wrapperColLong">
      <a-row>
        <a-col :span="24">
          <a-form-model-item label="产品名称" prop="productName">
            <a-input v-model="model.productName" placeholder="请输入产品名称"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="24">
          <a-form-model-item label="产品代号" prop="productNo">
            <a-input v-model="model.productNo" placeholder="请输入产品代号"></a-input>
          </a-form-model-item>
        </a-col>
      </a-row>
      <a-row>
        <a-col :span="24">
          <a-form-model-item label="产品型号">
            <a-textarea v-model="model.productModel" placeholder="请输入产品型号"></a-textarea>
          </a-form-model-item>
        </a-col>
      </a-row>
    </a-form-model>
  </a-spin>
</template>
<script>
  import { httpAction, getAction } from '@/api/manage'
  export default {
    name: 'ProductModalForm',
    components: {},
    data() {
      return {
        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,
        validatorRules: {
          productName: [
            { required: true, message: '请输入产品名称!' }
          ],
          productNo: [
            { required: true, message: '请输入产品代号!' }
          ],
        },
        url: {
          add: '/mdc/mdcPartProcessInfo/add',
          edit: '/mdc/mdcPartProcessInfo/edit'
        }
      }
    },
    computed: {
      formDisabled() {
        return this.disabled
      }
    },
    created() {
      //备份model原始值
      this.modelDefault = JSON.parse(JSON.stringify(this.model))
    },
    methods: {
      add() {
        this.edit(this.modelDefault)
      },
      edit(record) {
        this.model = Object.assign({}, record)
        console.log('model', this.model)
        this.visible = true
      },
      submitForm() {
        const that = this
        // è§¦å‘表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true
            let httpUrl = ''
            let method = 'post'
            if (!this.model.id) {
              httpUrl += this.url.add
            } else {
              httpUrl += this.url.edit
            }
            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/ProductStructureMain.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
<template>
  <div style="height: 100%;max-height: 748px">
    <!--产品结构树右侧顶部区域-->
    <div style="height: 45%;overflow: hidden">
      <ProductStructureMainTop :size="tabContainerSize"/>
    </div>
    <!--产品结构树右侧底部区域-->
    <div style="height: 55%;overflow: hidden">
      <ProductStructureMainBottom :size="tabContainerSize"/>
    </div>
  </div>
</template>
<script>
  import ProductStructureMainTop from './ProductStructureMainTop'
  import ProductStructureMainBottom from './ProductStructureMainBottom'
  export default {
    name: 'ProductStructureMain',
    components: {
      ProductStructureMainTop,
      ProductStructureMainBottom
    },
    data() {
      return {
        tabContainerSize: 'small'
      }
    },
    methods: {}
  }
</script>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
<template>
  <a-tabs style="height: 100%" v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0">
    <a-tab-pane :key="1" tab="产品属性" v-if="currentLevelInfo.type===1">
      <ProductInfo :currentLevelDetails="currentLevelInfo.entity" :size="descriptionsContainerSize"/>
    </a-tab-pane>
    <a-tab-pane :key="1" tab="部件属性" v-if="currentLevelInfo.type===2">
      <ComponentInfo :currentLevelDetails="currentLevelInfo.entity" :size="descriptionsContainerSize"/>
    </a-tab-pane>
    <a-tab-pane :key="1" tab="零件属性" v-if="currentLevelInfo.type===3">
      <PartInfo :currentLevelDetails="currentLevelInfo.entity" :size="descriptionsContainerSize"/>
    </a-tab-pane>
    <a-tab-pane :key="1" tab="工序属性" v-if="currentLevelInfo.hasOwnProperty('processType')">
      <ProcessInfo :currentLevelDetails="currentLevelInfo" :size="descriptionsContainerSize"/>
    </a-tab-pane>
    <template v-if="currentLevelInfo.hasOwnProperty('attributionType')">
      <a-tab-pane :key="1" tab="文档属性">
        <DocumentInfo :currentLevelDetails="currentLevelInfo" :size="descriptionsContainerSize"/>
      </a-tab-pane>
      <a-tab-pane :key="2" tab="预览">
      </a-tab-pane>
      <a-tab-pane :key="3" tab="文档版本">
        <DocumentVersionTableList/>
      </a-tab-pane>
      <a-tab-pane :key="4" tab="使用设备" v-if="currentLevelInfo.attributionType===5">
        <UseDocumentEquipmentTableList/>
      </a-tab-pane>
    </template>
  </a-tabs>
</template>
<script>
  import ProductInfo from './Product/ProductInfo'
  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 UseDocumentEquipmentTableList from './Document/UseDocumentEquipmentTableList'
  export default {
    name: 'ProductStructureMainBottom',
    components: {
      UseDocumentEquipmentTableList,
      DocumentVersionTableList,
      DocumentInfo,
      ProcessInfo,
      PartInfo,
      ProductInfo,
      ComponentInfo
    },
    data() {
      return {
        activeTabKey: 1,
        descriptionsContainerSize: 'small',
        currentLevelInfo: {}
      }
    },
    created() {
      this.$bus.$on('sendCurrentLevelInfo', this.receiveCurrentLevelInfo)
      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentLevelInfo)
    },
    methods: {
      /**
       * æŽ¥æ”¶æ ‘组件以及表格传来的当前选中或点击的项信息
       * @param levelInfo
       */
      receiveCurrentLevelInfo(levelInfo) {
        this.currentLevelInfo = levelInfo
        if (levelInfo.attributionType) this.activeTabKey = 1
      }
    }
  }
</script>
<style scoped>
  /deep/ .ant-tabs-content {
    height: calc(100% - 65px);
  }
  /deep/ .ant-tabs-tabpane {
    overflow: auto;
  }
</style>
src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
<template>
  <a-tabs v-model="activeTabKey" @contextmenu.native="e=>e.preventDefault()"
          v-if="Object.keys(currentTreeNodeInfo).length!==0">
    <a-tab-pane :key="1" tab="NC文档" v-if="currentTreeNodeInfo.type!==1">
      <NcDocumentTableList @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
    </a-tab-pane>
    <a-tab-pane :key="2" tab="其他文档">
      <OtherDocumentTableList @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
    </a-tab-pane>
    <TableContextMenu :currentTableRowInfo="currentTableRowInfo" ref="tableContextMenuRef"/>
  </a-tabs>
</template>
<script>
  import ProcessTableList from './Process/ProcessTableList'
  import NcDocumentTableList from './Document/NcDocumentTableList'
  import OtherDocumentTableList from './Document/OtherDocumentTableList'
  import TableContextMenu from '../../../common/TableContextMenu'
  export default {
    name: 'ProductStructureMainTop',
    components: { TableContextMenu, OtherDocumentTableList, NcDocumentTableList, ProcessTableList },
    data() {
      return {
        activeTabKey: '1',
        tableContainerSize: 'small',
        currentTableRowInfo: {},
        currentTreeNodeInfo: {}
      }
    },
    created() {
      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
    },
    methods: {
      /**
       * æŽ§åˆ¶å³é”®èœå•开启
       * @param record å½“前表格行信息
       */
      handleTableContextMenuOpen(record) {
        this.currentTableRowInfo = 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)
      },
      /**
       * æŽ¥æ”¶æ ‘组件传来的当前选中的树节点信息
       * @param treeNodeInfo
       */
      receiveCurrentTreeNodeInfo(treeNodeInfo) {
        // ä»Žæ ‘组件接受树节点信息后从父组件流入子组件
        this.currentTreeNodeInfo = treeNodeInfo
        if (treeNodeInfo.type !== 1) this.activeTabKey = 1
        else this.activeTabKey = 2
      },
      /**
       * æŽ§åˆ¶å³é”®èœå•点击关闭
       */
      handleMenuClose() {
        this.$refs.tableContextMenuRef.menuVisible = false
        document.body.removeEventListener('click', this.handleMenuClose)
      }
    }
  }
</script>
<style scoped>
  /deep/ .ant-table-tbody .ant-table-row {
    cursor: pointer;
  }
</style>
src/views/dnc/common/ImportFileModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
<template>
  <a-modal :title="title" :visible="visible" @cancel="handleModalClose" :maskClosable="false">
    <a-upload :multiple="true" :file-list="fileList" :remove="handleRemove" :before-upload="beforeUpload">
      <a-button type="primary">
        <a-icon type="import"/>
        é€‰å–文件
      </a-button>
    </a-upload>
    <div style="margin-top: 16px">已选择{{fileList.length}}个文件</div>
    <template slot="footer">
      <a-button @click="handleModalClose">取消</a-button>
      <a-button
        id="custom-upload-button"
        type="primary"
        :disabled="fileList.length === 0"
        :loading="uploading"
        @click="handleUpload"
      >
        {{ uploading ? '上传中...' : '上传至服务器' }}
      </a-button>
    </template>
  </a-modal>
</template>
<script>
  export default {
    name: 'ImportFileModal',
    components: {},
    data() {
      return {
        visible: false,
        title: '',
        fileList: [],
        uploading: false
      }
    },
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      handleImport(modalTitle) {
        this.handleModalOpen(modalTitle)
      },
      handleRemove(file) {
        const index = this.fileList.indexOf(file)
        const newFileList = this.fileList.slice()
        newFileList.splice(index, 1)
        this.fileList = newFileList
      },
      beforeUpload(file) {
        this.fileList = [...this.fileList, file]
        return false
      },
      handleUpload() {
        const { fileList } = this
        const formData = new FormData()
        fileList.forEach(file => {
          formData.append('files[]', file)
        })
        this.uploading = true
        // You can use any AJAX library you like
        request({
          url: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
          method: 'post',
          processData: false,
          data: formData,
          success: () => {
            this.fileList = []
            this.uploading = false
            this.$message.success('upload successfully.')
          },
          error: () => {
            this.uploading = false
            this.$message.error('upload failed.')
          }
        })
      },
      /**
       * æŽ§åˆ¶æ–‡ä»¶ä¸Šä¼ çª—口开启并设置窗口标题
       * @param modalTitle çª—口标题
       */
      handleModalOpen(modalTitle) {
        this.title = modalTitle
        this.visible = true
      },
      /**
       * æŽ§åˆ¶æ–‡ä»¶ä¸Šä¼ çª—口关闭并清空文件列表
       */
      handleModalClose() {
        this.visible = false
        this.fileList = []
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) this[methodName](modalTitle)
      }
    }
  }
</script>
<style scoped lang="less">
  /deep/ .ant-btn-primary#custom-upload-button {
    color: #fff;
    background-color: #67C23A;
    border-color: #67C23A;
    &[disabled] {
      color: rgba(0, 0, 0, 0.25);
      background-color: #f5f5f5;
      border-color: #d9d9d9;
    }
  }
</style>
src/views/dnc/common/ProductStructureTree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,644 @@
<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="queryTreeData">刷新</a-menu-item>
            </a-menu>
            <a-button>
              <a-icon type="bars"/>
            </a-button>
          </a-dropdown>
          <a-button type="primary" @click="$refs.productModalFormRef.handleProductAdd('添加产品')">
            <a-icon type="plus"></a-icon>
            äº§å“
          </a-button>
        </div>
        <!--产品结构树-->
        <div style="flex: 1;overflow:auto;margin-top: 10px">
          <a-tree ref="tree" show-icon :checkStrictly="checkStrictly" :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}">
              <ProductStructureTreeContextMenu ref="contextMenuRef"
                                               :treeParams="{label,treeKey,searchValue,type,entity}"/>
            </template>
            <a-icon slot="switcherIcon" type="down"/>
            <a-icon slot="product" type="shopping"/>
            <a-icon slot="component" type="camera"/>
            <a-icon slot="part" type="hdd"/>
          </a-tree>
        </div>
      </div>
    </a-spin>
    <!--产品弹窗-->
    <ProductModal ref="productModalFormRef" :currentTreeNodeInfo="rightClickSelected"/>
    <!--零件弹窗-->
    <ComponentModal :currentTreeNodeInfo="rightClickSelected"/>
    <!--导入文件公共弹窗-->
    <ImportFileModal/>
  </a-card>
</template>
<script>
  import { deleteAction } from '@/api/manage'
  import { mapActions } from 'vuex'
  import ProductStructureTreeContextMenu from './modules/ProductStructureTree/ProductStructureTreeContextMenu'
  import ProductModal from '../base/modules/ProductStructure/Product/ProductModal'
  import ImportFileModal from './ImportFileModal'
  import ComponentModal from '../base/modules/ProductStructure/Component/ComponentModal'
  export default {
    name: 'ProductStructureTree',
    components: {
      ComponentModal,
      ImportFileModal,
      ProductModal,
      ProductStructureTreeContextMenu
    },
    data() {
      return {
        searchInput: '',
        cardLoading: false,
        loading: false,
        treeDataSource: [],
        selectedKeys: [],
        expandedKeys: [],
        searchValue: '',
        dataList: [],
        autoExpandParent: true,
        checkStrictly: true,
        allTreeKeys: [],
        currentSelected: {},
        rightClickSelected: {},
        url: {
          delete: ''
        }
      }
    },
    created() {
      this.queryTreeData()
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      ...mapActions(['QueryProduction']),
      queryTreeData() {
        this.loading = true
        this.cardLoading = true
        this.QueryProduction().then(res => {
          if (res.success) {
            this.dataList = []
            this.allTreeKeys = []
            // this.treeDataSource = res.result
            this.treeDataSource = [
              {
                'id': '1869253349344432129',
                'label': '[让外人]测试',
                'iconClass': '',
                'parentId': '1869253349344432129',
                'children': [
                  {
                    'id': '1869254044432879617',
                    'label': '[378]qgwqg',
                    'iconClass': '',
                    'parentId': '1869253349344432129',
                    'children': [
                      {
                        'id': '1869260302133137410',
                        'label': '[ggjuk]谔谔去',
                        'iconClass': '',
                        'parentId': '1869254044432879617',
                        'children': [
                          {
                            'id': '1869294654070075393',
                            'label': '[8989]qwfq',
                            'iconClass': '',
                            'parentId': '1869260302133137410',
                            'children': null,
                            'type': 2,
                            'entity': {
                              'componentId': '1869294654070075393',
                              'parentId': '1869260302133137410',
                              'productId': '1869253349344432129',
                              'componentName': 'qwfq',
                              'materielCode': '',
                              'materielDesp': '',
                              'componentModel': '',
                              'componentScale': '',
                              'componentWeight': null,
                              'rankLevel': 3,
                              'assembleType': null,
                              'produceType': null,
                              'processType': null,
                              'structureType': null,
                              'componentCode': '8989',
                              'componentStatus': 1,
                              'description': '',
                              'createTime': '2024-12-18 16:12:30',
                              'updateTime': null,
                              'createUser': '1254966905669160962',
                              'updateUser': ''
                            },
                            'leaf': false,
                            'rfield': '1869253349344432129'
                          },
                          {
                            'id': '1869294701801254913',
                            'label': '[888]7878',
                            'iconClass': '',
                            'parentId': '1869260302133137410',
                            'children': null,
                            'type': 2,
                            'entity': {
                              'componentId': '1869294701801254913',
                              'parentId': '1869260302133137410',
                              'productId': '1869253349344432129',
                              'componentName': '7878',
                              'materielCode': '',
                              'materielDesp': '',
                              'componentModel': '',
                              'componentScale': '',
                              'componentWeight': null,
                              'rankLevel': 3,
                              'assembleType': null,
                              'produceType': null,
                              'processType': null,
                              'structureType': null,
                              'componentCode': '888',
                              'componentStatus': 1,
                              'description': '',
                              'createTime': '2024-12-18 16:12:41',
                              'updateTime': null,
                              'createUser': '1254966905669160962',
                              'updateUser': ''
                            },
                            'leaf': false,
                            'rfield': '1869253349344432129'
                          },
                          {
                            'id': '1869294780935188482',
                            'label': '[6855]ww',
                            'iconClass': '',
                            'parentId': '1869260302133137410',
                            'children': null,
                            'type': 2,
                            'entity': {
                              'componentId': '1869294780935188482',
                              'parentId': '1869260302133137410',
                              'productId': '1869253349344432129',
                              'componentName': 'ww',
                              'materielCode': '',
                              'materielDesp': '',
                              'componentModel': '',
                              'componentScale': '',
                              'componentWeight': null,
                              'rankLevel': 3,
                              'assembleType': null,
                              'produceType': null,
                              'processType': null,
                              'structureType': null,
                              'componentCode': '6855',
                              'componentStatus': 1,
                              'description': '',
                              'createTime': '2024-12-18 16:13:00',
                              'updateTime': null,
                              'createUser': '1254966905669160962',
                              'updateUser': ''
                            },
                            'leaf': false,
                            'rfield': '1869253349344432129'
                          },
                          {
                            'id': '1876199480437153794',
                            'label': '[354]zzzzzzzzzzzzzzzzz',
                            'iconClass': '',
                            'parentId': '1869260302133137410',
                            'children': null,
                            'type': 3,
                            'entity': {
                              'partsId': '1876199480437153794',
                              'partsName': 'zzzzzzzzzzzzzzzzz',
                              'productId': '1869253349344432129',
                              'componentId': '1869260302133137410',
                              'materielCode': '',
                              'materielDesp': '',
                              'partsModel': '',
                              'partsScale': '',
                              'partsWeight': null,
                              'assembleType': null,
                              'produceType': null,
                              'processType': null,
                              'structureType': null,
                              'partsCode': '354',
                              'partsStatus': 1,
                              'description': '',
                              'createTime': '2025-01-06 17:29:49',
                              'updateTime': null,
                              'createUser': '1254966905669160962',
                              'updateUser': ''
                            },
                            'leaf': false,
                            'rfield': '1869260302133137410'
                          }
                        ],
                        'type': 2,
                        'entity': {
                          'componentId': '1869260302133137410',
                          'parentId': '1869254044432879617',
                          'productId': '1869253349344432129',
                          'componentName': '谔谔去',
                          'materielCode': '',
                          'materielDesp': '',
                          'componentModel': '',
                          'componentScale': '',
                          'componentWeight': null,
                          'rankLevel': 2,
                          'assembleType': null,
                          'produceType': null,
                          'processType': null,
                          'structureType': null,
                          'componentCode': 'ggjuk',
                          'componentStatus': 1,
                          'description': '',
                          'createTime': '2024-12-18 13:56:00',
                          'updateTime': null,
                          'createUser': '1254966905669160962',
                          'updateUser': ''
                        },
                        'leaf': false,
                        'rfield': '1869253349344432129'
                      }
                    ],
                    'type': 2,
                    'entity': {
                      'componentId': '1869254044432879617',
                      'parentId': null,
                      'productId': '1869253349344432129',
                      'componentName': 'qgwqg',
                      'materielCode': '',
                      'materielDesp': '',
                      'componentModel': '',
                      'componentScale': '',
                      'componentWeight': null,
                      'rankLevel': 1,
                      'assembleType': null,
                      'produceType': null,
                      'processType': null,
                      'structureType': null,
                      'componentCode': '378',
                      'componentStatus': 1,
                      'description': '88',
                      'createTime': '2022-12-18 13:32:48',
                      'updateTime': '2024-12-18 13:32:48',
                      'createUser': '1254966905669160962',
                      'updateUser': '1254966905669160962'
                    },
                    'leaf': false,
                    'rfield': '1869253349344432129'
                  },
                  {
                    'id': '1869253419041181697',
                    'label': '[876]为全国前五给',
                    'iconClass': '',
                    'parentId': '1869253349344432129',
                    'children': null,
                    'type': 2,
                    'entity': {
                      'componentId': '1869253419041181697',
                      'parentId': null,
                      'productId': '1869253349344432129',
                      'componentName': '为全国前五给',
                      'materielCode': '',
                      'materielDesp': '',
                      'componentModel': '56',
                      'componentScale': '',
                      'componentWeight': null,
                      'rankLevel': 1,
                      'assembleType': null,
                      'produceType': null,
                      'processType': null,
                      'structureType': null,
                      'componentCode': '876',
                      'componentStatus': 1,
                      'description': '',
                      'createTime': '2024-12-18 13:28:39',
                      'updateTime': '2024-12-18 14:03:55',
                      'createUser': '1254966905669160962',
                      'updateUser': '1254966905669160962'
                    },
                    'leaf': false,
                    'rfield': '1869253349344432129'
                  },
                  {
                    'id': '1869294861876867073',
                    'label': '[777]he',
                    'iconClass': '',
                    'parentId': '1869253349344432129',
                    'children': [
                      {
                        'id': '1876087437913108481',
                        'label': '[ddd]和维护',
                        'iconClass': '',
                        'parentId': '1869294861876867073',
                        'children': null,
                        'type': 2,
                        'entity': {
                          'componentId': '1876087437913108481',
                          'parentId': '1869294861876867073',
                          'productId': '1869253349344432129',
                          'componentName': '和维护',
                          'materielCode': '',
                          'materielDesp': '',
                          'componentModel': '',
                          'componentScale': '',
                          'componentWeight': null,
                          'rankLevel': 2,
                          'assembleType': null,
                          'produceType': null,
                          'processType': null,
                          'structureType': null,
                          'componentCode': 'ddd',
                          'componentStatus': 1,
                          'description': '',
                          'createTime': '2025-01-06 10:04:36',
                          'updateTime': null,
                          'createUser': '1254966905669160962',
                          'updateUser': ''
                        },
                        'leaf': false,
                        'rfield': '1869253349344432129'
                      }
                    ],
                    'type': 2,
                    'entity': {
                      'componentId': '1869294861876867073',
                      'parentId': null,
                      'productId': '1869253349344432129',
                      'componentName': 'he',
                      'materielCode': '',
                      'materielDesp': '',
                      'componentModel': '',
                      'componentScale': '',
                      'componentWeight': null,
                      'rankLevel': 1,
                      'assembleType': null,
                      'produceType': null,
                      'processType': null,
                      'structureType': null,
                      'componentCode': '777',
                      'componentStatus': 1,
                      'description': '',
                      'createTime': '2024-12-18 16:13:20',
                      'updateTime': null,
                      'createUser': '1254966905669160962',
                      'updateUser': ''
                    },
                    'leaf': false,
                    'rfield': '1869253349344432129'
                  }
                ],
                'type': 1,
                'entity': {
                  'productId': '1869253349344432129',
                  'productNo': '让外人',
                  'productModel': '',
                  'productName': '测试',
                  'productStatus': 1,
                  'createTime': '2024-12-18 13:28:22',
                  'updateTime': null,
                  'createUser': '1254966905669160962',
                  'updateUser': null
                },
                'leaf': false,
                'rfield': null
              }
            ]
            this.generateList(this.treeDataSource)
            // this.expandedKeys = this.allTreeKeys
            this.expandedKeys = [this.treeDataSource[0].id]
            console.log('treeDataSource', this.treeDataSource)
          } 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.queryTreeData()
                  that.$notification.success({
                    message: '消息',
                    description: res.message
                  })
                } else {
                  that.$notification.warning({
                    message: '消息',
                    description: res.message
                  })
                }
              })
          }
        })
      },
      /**
       * æ ‘节点展开合并时触发
       * @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++) {
          data[i].key = data[i].id
          const node = data[i]
          const key = node.id
          const title = node.label
          this.dataList.push({ key, title })
          this.allTreeKeys.push(key)
          this.setTreeNodeIcon(node)
          if (node.children) this.generateList(node.children)
        }
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) this[methodName](modalTitle)
      },
      /**
       * è®¾ç½®æ ‘节点图标
       * @param treeNode
       */
      setTreeNodeIcon(treeNode) {
        switch (treeNode.type) {
          case 1:
            treeNode.slots = { icon: 'product' }
            break
          case 2:
            treeNode.slots = { icon: 'component' }
            break
          case 3:
            treeNode.slots = { icon: 'part' }
            break
          default:
        }
      }
    }
  }
</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-node-content-wrapper {
    width: calc(100% - 24px);
  }
  /deep/ .ant-tree-title, .ant-tree-title .ant-dropdown-trigger {
    display: inline-block;
    width: calc(100% - 24px) !important;
  }
  .tree_con {
    overflow: hidden;
  }
  @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/common/TableContextMenu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
<template>
  <a-menu :style="menuStyle" @click="menuItemClick" v-if="menuVisible" mode="vertical">
    <template v-for="menuItem in defaultContextMenuList[currentMenuLevel]">
      <a-menu-item :key="menuItem.code" v-if="menuItem.show&&menuItem.subMenu.length===0">
        <a-icon :type="menuItem.icon"/>
        {{menuItem.label}}
      </a-menu-item>
      <a-sub-menu v-if="menuItem.subMenu.length>0">
        <span slot="title"><a-icon :type="menuItem.icon"/><span>{{menuItem.label}}</span></span>
        <a-menu-item v-for="subMenuItem in menuItem.subMenu" :key="subMenuItem.code" v-if="subMenuItem.show"
                     style="height: 32px;line-height: 32px">
          <a-icon :type="subMenuItem.icon"/>
          {{subMenuItem.label}}
        </a-menu-item>
      </a-sub-menu>
    </template>
  </a-menu>
</template>
<script>
  export default {
    name: 'TableContextMenu',
    components: {},
    props: {
      currentTableRowInfo: {
        type: Object
      }
    },
    data() {
      return {
        menuVisible: false,
        menuStyle: {
          position: 'fixed',
          top: 0,
          left: 0,
          border: '1px solid #eee',
          boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
          zIndex: 999
        },
        currentMenuLevel: '',
        defaultContextMenuList: {
          //文档
          document: [
            { show: true, label: '编辑文档信息', code: 'document_edit', subMenu: [], icon: 'edit' },
            { show: true, label: '指派到设备', code: 'document_assign', subMenu: [], icon: 'cluster' },
            { show: false, label: '导出NC程序', code: 'document_export', subMenu: [], icon: 'export' },
            { show: true, label: '导入NC程序', code: 'document_import', subMenu: [], icon: 'import' },
            { show: true, label: '下载', code: 'document_download', subMenu: [], icon: 'download' },
            { show: true, label: '删除', code: 'document_delete', subMenu: [], icon: 'delete' },
            { show: true, label: '批量删除', code: 'document_batch_remove', subMenu: [], icon: 'delete' },
            {
              show: true,
              label: '生命周期',
              subMenu: [
                { show: true, label: '出库', code: 'document_pull', icon: 'export' },
                { show: true, label: '取消出库', code: 'document_cancel_pull', icon: 'stop' },
                { show: true, label: '入库', code: 'document_push', icon: 'import' },
                { show: true, label: '发布', code: 'document_publish', icon: 'flag' },
                { show: true, label: '重新发布', code: 'document_republish', icon: 'reload' },
                { show: true, label: '归档', code: 'document_pigeonhole', icon: 'database' }
              ],
              icon: 'delete'
            }
          ]
        }
      }
    },
    methods: {
      menuItemClick({ item, key }) {
        // process_add => handleProcessAdd è§¦å‘对应组件事件
        const methodName = 'handle' + key.split('_').map(item => item[0].toUpperCase() + item.slice(1)).join('')
        const modalTitle = this.defaultContextMenuList[this.currentMenuLevel].find(item => item.code === key).label
        console.log('key', key)
        this.$bus.$emit('menuItemMethodTrigger', { level: this.currentMenuLevel, methodName, modalTitle })
      }
    }
  }
</script>
<style scoped>
  /deep/ .ant-menu-item {
    height: 32px;
    line-height: 32px;
  }
</style>
src/views/dnc/common/modules/ProductStructureTree/ProductStructureTreeContextMenu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,118 @@
<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-else>{{ treeParams.label }}</span>
    <template #overlay>
      <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeParams.treeKey, menuKey)"
              @contextmenu="event=>event.preventDefault()">
        <template v-for="item in defaultContextMenuList[getCurrentMenuLevel]">
          <a-menu-item :key="item.code" v-if="item.show">
            <a-icon :type="item.icon"/>
            {{item.label}}
          </a-menu-item>
        </template>
      </a-menu>
    </template>
  </a-dropdown>
</template>
<script>
  export default {
    name: 'ProductStructureTreeContextMenu',
    components: {},
    props: {
      treeParams: {
        type: Object
      }
    },
    data() {
      return {
        defaultContextMenuList: {
          //产品
          product: [
            { show: true, label: '添加产品', code: 'product_add', icon: 'plus', isCommonMethod: false },
            { show: true, label: '添加部件', code: 'product_add_child', icon: 'plus', isCommonMethod: false },
            { show: true, label: '编辑产品信息', code: 'product_edit', icon: 'edit', isCommonMethod: false },
            { show: false, label: '导出文档', code: 'product_export', icon: 'export', isCommonMethod: true },
            { show: true, label: '导入其他文档', code: 'product_import', icon: 'import', isCommonMethod: true },
            { show: true, label: '删除', code: 'product_delete', icon: 'delete', isCommonMethod: true },
            { show: true, label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //部件
          component: [
            { show: true, label: '添加子部件', code: 'component_add', icon: 'plus', isCommonMethod: false },
            { show: true, label: '添加零件', code: 'component_add_child', icon: 'plus', isCommonMethod: false },
            { show: true, label: '创建工序', code: 'component_add_relative', icon: 'plus', isCommonMethod: false },
            { show: true, label: '编辑部件信息', code: 'component_edit', icon: 'edit', isCommonMethod: false },
            { show: false, label: '导出文档', code: 'component_export', icon: 'export', isCommonMethod: true },
            { show: true, label: '导入其他文档', code: 'component_import', icon: 'import', isCommonMethod: true },
            { show: true, label: '删除', code: 'component_delete', icon: 'delete', isCommonMethod: true },
            { show: true, label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //零件
          part: [
            { show: true, label: '添加零件', code: 'parts_add', icon: 'plus', isCommonMethod: false },
            { show: true, label: '创建工序', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
            { show: true, label: '编辑零件信息', code: 'parts_edit', icon: 'edit', isCommonMethod: false },
            { show: false, label: '导出文档', code: 'parts_export', icon: 'export', isCommonMethod: true },
            { show: true, label: '导入其他文档', code: 'parts_import', icon: 'import', isCommonMethod: true },
            { show: true, label: '删除', code: 'parts_delete', icon: 'delete', isCommonMethod: true },
            { show: true, label: '权限配置', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
          ],
          //工序
          process: [
            { show: true, label: '创建工序', code: 'process_add', icon: 'plus', isCommonMethod: false },
            { show: true, label: '编辑工序信息', code: 'process_edit', icon: 'edit', isCommonMethod: false },
            { show: true, label: '删除', code: 'process_delete', icon: 'delete', isCommonMethod: true },
            { show: false, label: '导出NC程序', code: 'process_export', icon: 'import', isCommonMethod: true },
            { show: true, label: '导入NC程序', code: 'process_import', icon: 'export', isCommonMethod: true }
          ]
        }
      }
    },
    computed: {
      getCurrentMenuLevel() {
        switch (this.treeParams.type) {
          case 1:
            return 'product'
          case 2:
            return 'component'
          case 3:
            return 'part'
          case 4:
            return 'process'
          case 5:
            return 'processStep'
        }
      }
    },
    methods: {
      onContextMenuClick(treeKey, menuKey) {
        const level = this.getCurrentMenuLevel
        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 })
      }
    }
  }
</script>
<style scoped>
  .replaceSearch {
    color: #40a9ff;
    font-weight: bold;
    background-color: rgb(204, 204, 204);
  }
</style>