From 9737ae6cbdf64098554dc99e743a52669adb8138 Mon Sep 17 00:00:00 2001
From: lyh <925863403@qq.com>
Date: 星期五, 14 三月 2025 10:27:15 +0800
Subject: [PATCH] Revert "1、设备类管理页面完成增删改查功能"

---
 src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue                |   14 
 src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue                   |    4 
 src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue |  167 +++
 src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue                   |    1 
 src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue  |  223 ++++
 src/views/system/modules/UserModal.vue                                                     |   11 
 src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue     |   80 +
 src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue          |  125 ++
 src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue                       |    4 
 src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue                 |   58 
 src/views/dnc/base/DeviceCustomTypeManagement.vue                                          |  189 +++
 src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue |  150 +++
 src/views/dnc/common/TableContextMenu.vue                                                  |    6 
 src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue                       |  106 +
 src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue            |  275 ++--
 src/views/dnc/base/ProductStructure.vue                                                    |   41 
 src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue               |    2 
 src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue                         |   77 +
 src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue                        |   20 
 src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue                        |   12 
 src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue                     |  153 +++
 src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue                    |   16 
 src/api/dnc.js                                                                             |   27 
 /dev/null                                                                                  |   34 
 src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue                    |  746 +++++++-------
 src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue                              |   16 
 src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue                         |    1 
 src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue                     |  152 +++
 src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue           |  207 ++--
 29 files changed, 2,167 insertions(+), 750 deletions(-)

diff --git a/src/api/dnc.js b/src/api/dnc.js
index ef1c3db..4875d2a 100644
--- a/src/api/dnc.js
+++ b/src/api/dnc.js
@@ -15,7 +15,7 @@
   // 鑾峰彇浜у搧缁撴瀯鏍�
   getProductStructureTreeApi: () => getAction('/nc/product/getTree'),
   // 鑾峰彇浜у搧缁撴瀯鏍戣妭鐐瑰疄浣撲俊鎭�
-  getProductStructureTreeNodeEntityApi:params=> getAction('/nc/product/getTreeById',params),
+  getProductStructureTreeNodeEntityApi: params => getAction('/nc/product/getTreeById', params),
   // 鑾峰彇鎵�鏈夎澶囩殑鍒楄〃
   getAllDeviceListApi: (type) => getAction('/nc/device/list/all'),
   // 瀵煎叆NC绋嬪簭/鏂囨。
@@ -51,30 +51,32 @@
   appointCurrentDocumentVersionApi: fileId => putAction(`/nc/file/assign/version/${fileId}`),
   // 鏂囨。姣斿
   fileCompareApi: fileIdArray => getAction(`/nc/file/comparison/${fileIdArray[0]}/${fileIdArray[1]}`),
-  // 鑾峰彇鎵�鏈夐儴闂ㄥ垪琛�
-  getAllDepartmentsListApi: () => getAction('/ucenter/depart/list/all'),
-  // 鑾峰彇鎵�鏈夌敤鎴峰垪琛�
+  // 鏉冮檺閰嶇疆寮圭獥涓幏鍙栨墍鏈夎溅闂村垪琛�
+  getAllDepartmentsListApi: () => getAction('/mdc/mdcProduction/queryTreeListByConfig'),
+  // 鏉冮檺閰嶇疆寮圭獥涓幏鍙栨墍鏈夌敤鎴峰垪琛�
   getAllUsersListApi: () => getAction('/sys/user/list'),
-  // 鑾峰彇鏈夋潈闄愮殑閮ㄩ棬鍒楄〃
+  // 鏉冮檺閰嶇疆寮圭獥涓幏鍙栨湁鏉冮檺鐨勯儴闂ㄥ垪琛�
   getHasPermissionDepartApi: ({ type, id }) => getAction(`/nc/product/get/perm/depart/${type}/${id}`),
-  // 鑾峰彇鏈夋潈闄愮殑鐢ㄦ埛鍒楄〃
+  // 鏉冮檺閰嶇疆寮圭獥涓幏鍙栨湁鏉冮檺鐨勭敤鎴峰垪琛�
   getHasPermissionUserApi: ({ type, id }) => getAction(`/nc/product/get/perm/user/${type}/${id}`),
-  // 鍒嗛厤閮ㄩ棬鏉冮檺
+  // 鏉冮檺閰嶇疆寮圭獥涓垎閰嶉儴闂ㄦ潈闄�
   assignPermissionToDepart: ({ treeNodeType, treeNodeId, isAssignSonNode, departIdArray }) => {
     return postAction(`/nc/product/assign/add/department/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, departIdArray)
   },
-  // 绉婚櫎閮ㄩ棬鏉冮檺
+  // 鏉冮檺閰嶇疆寮圭獥涓Щ闄ら儴闂ㄦ潈闄�
   removePermissionFromDepart: ({ treeNodeType, treeNodeId, isAssignSonNode, departIdArray }) => {
     return postAction(`/nc/product/assign/remove/department/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, departIdArray)
   },
-  // 鍒嗛厤鐢ㄦ埗鏉冮檺
+  // 鏉冮檺閰嶇疆寮圭獥涓垎閰嶇敤鎴舵潈闄�
   assignPermissionToUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
     return postAction(`/nc/product/assign/add/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
   },
-  // 绉婚櫎鐢ㄦ埛鏉冮檺
+  // 鏉冮檺閰嶇疆寮圭獥涓Щ闄ょ敤鎴锋潈闄�
   removePermissionFromUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
     return postAction(`/nc/product/assign/remove/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
   },
+  // 閫氳繃杞﹂棿ID鑾峰彇璁惧绫诲垪琛�
+  getDeviceCustomTypeListByProductionIdApi: productionId => getAction('/nc/deviceManagement/getDeviceManagementListByProductionId', { productionId }),
 
   //-------------------------璁惧缁撴瀯鏍�------------------------------------------------
   // 鑾峰彇璁惧鏍�
@@ -90,5 +92,8 @@
   // 绉婚櫎鐢ㄦ埛鏉冮檺
   removeDeviceTreePermissionFromUser: ({ treeNodeType, treeNodeId, isAssignSonNode, userIdArray }) => {
     return postAction(`/nc/device/assign/remove/user/${treeNodeType}/${treeNodeId}/${isAssignSonNode}`, userIdArray)
-  }
+  },
+  //-------------------------璁惧绫荤鐞�------------------------------------------------
+  // 鑾峰彇鏈夋潈闄愮殑杞﹂棿鏍戝垪琛�
+  getHasPermissionWorkshopTreeApi: () => getAction('/nc/deviceManagement/getProductionIdsByUserId')
 }
\ No newline at end of file
diff --git a/src/views/dnc/base/DeviceCustomTypeManagement.vue b/src/views/dnc/base/DeviceCustomTypeManagement.vue
new file mode 100644
index 0000000..10187b2
--- /dev/null
+++ b/src/views/dnc/base/DeviceCustomTypeManagement.vue
@@ -0,0 +1,189 @@
+<template>
+  <a-card :bordered="false">
+
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :md="4" :sm="4">
+            <a-form-item label="杞﹂棿">
+              <a-select v-model="queryParam.productionId" placeholder="璇烽�夋嫨杞﹂棿">
+                <a-select-option v-for="item in workshopTreeData" :key="item.id">
+                  {{ item.productionName }}
+                </a-select-option>
+              </a-select>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="4" :sm="4">
+            <a-form-item label="璁惧绫诲悕绉�">
+              <a-input placeholder="璇疯緭鍏ヨ澶囩被鍚嶇О" v-model="queryParam.deviceManagementName"></a-input>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="4" :sm="4">
+            <a-space>
+              <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload">閲嶇疆</a-button>
+            </a-space>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
+    <div class="table-operator" style="border-top: 5px">
+      <a-button @click="handleAdd" type="primary" icon="plus">娣诲姞璁惧绫�</a-button>
+      <!--      <a-button type="primary" icon="download" @click="handleExportXls('璁惧绫讳俊鎭�')">瀵煎嚭</a-button>-->
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay" @click="handleMenuClick">
+          <a-menu-item key="1">
+            <a-icon type="delete" @click="batchDel"/>
+            鍒犻櫎
+          </a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px">
+          鎵归噺鎿嶄綔
+          <a-icon type="down"/>
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table鍖哄煙-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i>宸查�夋嫨&nbsp;<a style="font-weight: 600">{{
+          selectedRowKeys.length
+        }}</a>椤�&nbsp;&nbsp;
+        <a style="margin-left: 24px" @click="onClearSelected">娓呯┖</a>
+      </div>
+
+      <a-table
+        ref="table"
+        bordered
+        size="middle"
+        rowKey="id"
+        :scroll="{y:465}"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+        <template slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">缂栬緫</a>
+
+          <a-divider type="vertical"/>
+
+          <a-popconfirm title="纭畾鍒犻櫎鍚�?" @confirm="() => handleDelete(record.id)">
+            <a>鍒犻櫎</a>
+          </a-popconfirm>
+        </template>
+      </a-table>
+    </div>
+    <!-- table鍖哄煙-end -->
+
+    <DeviceCustomTypeManagementModal ref="modalForm" :workshopTreeData="workshopTreeData" @ok="loadData"/>
+  </a-card>
+</template>
+
+<script>
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import dncApi from '@/api/dnc'
+import DeviceCustomTypeManagementModal
+  from '@views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue'
+
+export default {
+  name: 'DeviceCustomTypeManagement',
+  mixins: [JeecgListMixin],
+  components: {
+    DeviceCustomTypeManagementModal
+  },
+  data() {
+    return {
+      columns: [
+        {
+          title: '#',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        {
+          title: '杞﹂棿',
+          align: 'center',
+          width: 200,
+          dataIndex: 'productionId_dictText'
+        },
+        {
+          title: '璁惧绫�',
+          align: 'center',
+          width: 200,
+          dataIndex: 'deviceManagementCode'
+        },
+        {
+          title: '璁惧绫诲悕绉�',
+          align: 'center',
+          width: 200,
+          dataIndex: 'deviceManagementName'
+        },
+        {
+          title: '璁惧缁勭紪鍙�',
+          align: 'center',
+          dataIndex: 'equipmentIds',
+          width: 400,
+          ellipsis: true
+        },
+        {
+          title: '鎿嶄綔',
+          dataIndex: 'action',
+          scopedSlots: { customRender: 'action' },
+          align: 'center',
+          width: 80
+        }
+      ],
+      url: {
+        list: '/nc/deviceManagement/query',
+        delete: '/nc/deviceManagement/delete',
+        deleteBatch: '/nc/deviceManagement/deleteBatch'
+      },
+      workshopTreeData: []
+    }
+  },
+  created() {
+    this.getWorkshopListByApi()
+  },
+  methods: {
+    // 璋冪敤鎺ュ彛鑾峰彇鏌ヨ鍖哄煙杞﹂棿鏍戝垪琛�
+    getWorkshopListByApi() {
+      dncApi.getHasPermissionWorkshopTreeApi()
+        .then(res => {
+          if (res.success) {
+            this.workshopTreeData = res.result
+          }
+        })
+    },
+
+    handleAdd: function() {
+      this.$refs.modalForm.add()
+      this.$refs.modalForm.title = '鏂板'
+      this.$refs.modalForm.disabledEdit = false
+    },
+
+    handleEdit: function(record) {
+      this.$refs.modalForm.edit(record)
+      this.$refs.modalForm.title = '缂栬緫'
+      this.$refs.modalForm.disabledEdit = true
+    },
+
+    handleMenuClick(e) {
+      if (e.key == 1) {
+        this.batchDel()
+      }
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/ProductStructure.vue b/src/views/dnc/base/ProductStructure.vue
index 2095795..e679568 100644
--- a/src/views/dnc/base/ProductStructure.vue
+++ b/src/views/dnc/base/ProductStructure.vue
@@ -11,30 +11,35 @@
 
     <!--瀵煎叆鏂囦欢鍏叡寮圭獥-->
     <ImportFileModal/>
+
+    <!--鏂板鎴栫紪杈戣澶囩被鍏叡寮圭獥-->
+    <DeviceCustomTypeModal/>
   </a-card>
 </template>
 
 <script>
-  import ProductStructureTree from './modules/ProductStructure/ProductStructureTree'
-  import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
-  import ImportFileModal from '../common/ImportFileModal'
+import ProductStructureTree from './modules/ProductStructure/ProductStructureTree'
+import ProductStructureMain from './modules/ProductStructure/ProductStructureMain'
+import ImportFileModal from '../common/ImportFileModal'
+import DeviceCustomTypeModal from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
 
-  export default {
-    name: 'ProductStructure',
-    components: {
-      ProductStructureTree,
-      ProductStructureMain,
-      ImportFileModal
-    },
-    data() {
-      return {}
-    },
-    methods: {}
-  }
+export default {
+  name: 'ProductStructure',
+  components: {
+    DeviceCustomTypeModal,
+    ProductStructureTree,
+    ProductStructureMain,
+    ImportFileModal
+  },
+  data() {
+    return {}
+  },
+  methods: {}
+}
 </script>
 
 <style scoped lang="less">
-  /deep/ .ant-card-body {
-    padding: 8px;
-  }
+/deep/ .ant-card-body {
+  padding: 8px;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue b/src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue
new file mode 100644
index 0000000..04289e6
--- /dev/null
+++ b/src/views/dnc/base/modules/DeviceCustomTypeManagement/DeviceCustomTypeManagementModal.vue
@@ -0,0 +1,223 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="700"
+    @cancel="close"
+    :visible="visible"
+    :footer="null"
+    style="height: 100%;overflow: auto;padding-bottom: 53px;">
+
+    <a-spin :spinning="confirmLoading">
+      <a-form-model ref="form" :form="form" :model="model" :rules="validatorRules" :labelCol="labelCol"
+                    :wrapperCol="wrapperCol">
+        <a-row :gutter="24">
+          <a-col :span="12">
+            <a-form-model-item label="杞﹂棿鍒嗛厤" prop="productionId">
+              <a-select v-model="model.productionId" placeholder="璇烽�夋嫨杞﹂棿" @change="handleSelectChange"
+                        :disabled="disabledEdit">
+                <a-select-option v-for="item in workshopTreeData" :key="item.id">
+                  {{ item.productionName }}
+                </a-select-option>
+              </a-select>
+            </a-form-model-item>
+          </a-col>
+
+          <a-col :span="12">
+            <a-form-model-item label="璁惧绫�" prop="deviceManagementCode">
+              <a-input allow-clear placeholder="璇疯緭鍏ヨ澶囩被" :readOnly="disabledEdit"
+                       v-model="model.deviceManagementCode"/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+
+        <a-row :gutter="24">
+          <a-col :span="12">
+            <a-form-model-item label="璁惧绫诲悕绉�" prop="deviceManagementName">
+              <a-input allow-clear placeholder="璇疯緭鍏ヨ澶囩被鍚嶇О" :readOnly="disabledEdit"
+                       v-model="model.deviceManagementName"/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+
+        <a-row :gutter="24">
+          <a-col :span="24">
+            <a-form-model-item label="璁惧缁勭紪鍙�" :labelCol="labelColLong" :wrapperCol="wrapperColLong"
+                               prop="equipmentIds">
+              <a-input-search v-model="model.equipmentIds" :disabled="!model.productionId" @search="deviceSearch"
+                              enter-button :placeholder='!model.productionId?"璇烽�夋嫨杞﹂棿":"璇烽�夋嫨璁惧缁勭紪鍙�"'/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+      </a-form-model>
+    </a-spin>
+
+
+    <div class="drawer-bottom-button">
+      <a-space>
+        <a-button @click="close">鍙栨秷</a-button>
+        <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">鎻愪氦</a-button>
+      </a-space>
+    </div>
+
+    <workshop-device-list-modal :productionId="model.productionId" ref="deviceListModel"
+                                @sendSelectedRowKeys="getDeviceRowKeys"/>
+  </a-modal>
+</template>
+
+<script>
+import { httpAction } from '@/api/manage'
+import WorkshopDeviceListModal from '@views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue'
+
+export default {
+  name: 'DeviceCustomTypeManagementModal',
+  components: { WorkshopDeviceListModal },
+  props: {
+    workshopTreeData: {
+      type: Array
+    }
+  },
+  data() {
+    return {
+      title: '',
+      form: this.$form.createForm(this),
+      validatorRules: {
+        productionId: [
+          {
+            required: true, message: '璇烽�夋嫨杞﹂棿!'
+          }
+        ],
+        deviceManagementCode: [
+          {
+            required: true, message: '璇疯緭鍏ヨ澶囩被!'
+          }
+        ],
+        deviceManagementName: [
+          {
+            required: true, message: '璇疯緭鍏ヨ澶囩被鍚嶇О!'
+          }
+        ],
+        equipmentIds: [
+          {
+            required: true, message: '璇烽�夋嫨璁惧缂栧彿!'
+          }
+        ]
+      },
+      visible: false,
+      disabledEdit: false,
+      model: {},
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 14 }
+      },
+      labelColLong: {
+        xs: { span: 24 },
+        sm: { span: 4 }
+      },
+      wrapperColLong: {
+        xs: { span: 24 },
+        sm: { span: 19 }
+      },
+      confirmLoading: false,
+      url: {
+        add: '/nc/deviceManagement/add',
+        edit: '/nc/deviceManagement/edit'
+      }
+    }
+  },
+  methods: {
+    // 杞﹂棿閫夋嫨鍣ㄥ�煎彂鐢熸敼鍙樻椂瑙﹀彂娓呯┖宸查�夋嫨鐨勮澶囩紪鍙风粍
+    handleSelectChange() {
+      if (this.model.equipmentIds) delete this.model.equipmentIds
+    },
+
+    /**
+     * 褰撹澶囬�夋嫨瀹屾垚鍚庢彁浜ゅ皢宸查�夋嫨鐨勮澶囩紪鍙峰垪琛ㄤ互閫楀彿闅斿紑鎷嗗垎鍒板弬鏁颁腑
+     * @param selectedRowKeys
+     */
+    getDeviceRowKeys(selectedRowKeys) {
+      if (selectedRowKeys.length === 0) return
+      this.$set(this.model, 'equipmentIds', selectedRowKeys.join(','))
+      this.$refs.form.clearValidate()
+    },
+
+    deviceSearch() {
+      this.$refs.deviceListModel.openPage()
+      this.$refs.deviceListModel.title = '閫夋嫨璁惧'
+      this.$refs.deviceListModel.disableSubmit = false
+    },
+
+    add() {
+      this.edit({})
+    },
+
+    edit(record) {
+      this.visible = true
+      this.model = Object.assign({}, record)
+    },
+
+    handleSubmit() {
+      const that = this
+      // 瑙﹀彂琛ㄥ崟楠岃瘉
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          that.confirmLoading = true
+          let apiUrl, method
+          if (!this.model.id) {
+            apiUrl = this.url.add
+            method = 'post'
+          } else {
+            apiUrl = this.url.edit
+            method = 'put'
+          }
+          httpAction(apiUrl, this.model, method)
+            .then((res) => {
+              if (res.success) {
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+                that.$emit('ok')
+                that.close()
+              } else {
+                that.$notification.warning({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              }
+            })
+            .finally(() => {
+              that.confirmLoading = false
+            })
+        } else {
+          return false
+        }
+      })
+    },
+
+    close() {
+      this.$emit('close')
+      this.visible = false
+      this.$refs.form.clearValidate()
+    }
+  }
+
+}
+</script>
+
+<style scoped>
+.drawer-bottom-button {
+  position: absolute;
+  bottom: -40px;
+  width: 100%;
+  border-top: 1px solid #e8e8e8;
+  padding: 10px 16px;
+  text-align: right;
+  left: 0;
+  background: #fff;
+  border-radius: 0 0 2px 2px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue b/src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue
new file mode 100644
index 0000000..eae46ff
--- /dev/null
+++ b/src/views/dnc/base/modules/DeviceCustomTypeManagement/WorkshopDeviceListModal.vue
@@ -0,0 +1,125 @@
+<template>
+  <a-modal :title="title" :width="1000" :visible="visible" :maskClosable="false" @ok="handleOk" @cancel="close"
+           cancelText="鍏抽棴">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :md="8" :sm="8">
+            <a-form-item label="璁惧缂栧彿">
+              <a-input placeholder="璇疯緭鍏ヨ澶囩紪鍙�" v-model="queryParam.equipmentId"/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="8" :sm="8">
+            <a-form-item label="璁惧鍚嶇О">
+              <a-input placeholder="璇疯緭鍏ヨ澶囧悕绉�" v-model="queryParam.equipmentName"/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="3" :sm="3">
+            <a-space>
+              <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload">閲嶇疆</a-button>
+            </a-space>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- table鍖哄煙-begin -->
+    <a-table ref="table" size="middle" bordered rowKey="equipmentId" :scroll="{y: 300}" :columns="columns"
+             :dataSource="dataSource" :pagination="ipagination" :loading="loading"
+             :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type:'checkbox'}"
+             @change="handleTableChange">
+    </a-table>
+    <!-- table鍖哄煙-end -->
+  </a-modal>
+</template>
+
+<script>
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+
+export default {
+  name: 'WorkshopDeviceListModal',
+  mixins: [JeecgListMixin],
+  components: {},
+  props: {
+    productionId: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      title: '',
+      visible: false,
+      disableMixinCreated: true,
+      columns: [
+        {
+          title: '璁惧缂栧彿',
+          align: 'center',
+          dataIndex: 'equipmentId'
+        },
+        {
+          title: '璁惧鍚嶇О',
+          align: 'center',
+          dataIndex: 'equipmentName'
+        },
+        {
+          title: '璁惧鍨嬪彿',
+          align: 'center',
+          dataIndex: 'equipmentModel'
+        },
+        {
+          title: '鏈哄簥IP',
+          align: 'center',
+          dataIndex: 'equipmentIp'
+        },
+        {
+          title: '椹卞姩绫诲瀷',
+          align: 'center',
+          dataIndex: 'driveType'
+        },
+        {
+          title: '绔彛',
+          align: 'center',
+          dataIndex: 'dataPort'
+        },
+        {
+          title: '鏁版帶绯荤粺',
+          align: 'center',
+          dataIndex: 'controlSystem'
+        }
+      ],
+      url: {
+        list: '/nc/deviceManagement/getEquipmentListByProductionId'
+      }
+    }
+  },
+  methods: {
+    openPage() {
+      this.visible = true
+      this.onClearSelected()
+      this.dataSource = []
+      this.queryParam = Object.assign({}, { productionId: this.productionId })
+      this.loadData()
+    },
+    searchQuery() {
+      this.loadData()
+      this.onClearSelected()
+    },
+    searchReset() {
+      this.queryParam = Object.assign({}, { productionId: this.productionId })
+      this.loadData()
+      this.onClearSelected()
+    },
+    close() {
+      this.$emit('close')
+      this.visible = false
+    },
+    handleOk() {
+      this.$emit('sendSelectedRowKeys', this.selectedRowKeys)
+      this.close()
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue b/src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
index 9bfa203..fa67d6c 100644
--- a/src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
+++ b/src/views/dnc/base/modules/DeviceStructure/DeviceStructureMainBottom.vue
@@ -1,6 +1,6 @@
 <template>
-  <div>
-    <a-tabs v-model="activeTabKey" @change="handleTabChange">
+  <div style="height: 100%">
+    <a-tabs style="height: 100%" v-model="activeTabKey" @change="handleTabChange">
       <a-tab-pane :key="1" tab="璁惧灞炴��" v-if="currentTreeNodeInfo.type===2&&!currentDocumentInfo.docId">
         <DeviceInfo :currentLevelDetails="currentTreeNodeInfo.entity" :size="containerSize"/>
       </a-tab-pane>
diff --git a/src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue b/src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue
index a930ddd..fef8b3d 100644
--- a/src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue
+++ b/src/views/dnc/base/modules/DeviceStructure/DeviceStructureTree.vue
@@ -82,6 +82,7 @@
       getTreeDataByApi() {
         this.loading = true
         this.cardLoading = true
+        this.treeDataSource = []
         dncApi.getDeviceTreeDataApi()
           .then(res => {
             if (res.success) {
diff --git a/src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue b/src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue
index b9c1cf1..a886650 100644
--- a/src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Component/ComponentInfo.vue
@@ -1,6 +1,6 @@
 <template>
-  <a-descriptions bordered :size="size">
-    <a-descriptions-item label="鍚嶇О">{{currentLevelDetails.componentName}}</a-descriptions-item>
+  <a-descriptions bordered :size="size" :column="4">
+    <a-descriptions-item label="鍚嶇О" :span="2">{{currentLevelDetails.componentName}}</a-descriptions-item>
     <a-descriptions-item label="浠e彿">{{currentLevelDetails.componentCode}}</a-descriptions-item>
     <a-descriptions-item label="鍨嬪彿	">{{currentLevelDetails.componentModel}}</a-descriptions-item>
     <a-descriptions-item label="鐗╂枡缂栫爜">{{currentLevelDetails.materielCode}}</a-descriptions-item>
@@ -10,12 +10,12 @@
     <a-descriptions-item label="鐢熶骇绫诲瀷">{{currentLevelDetails.produceType}}</a-descriptions-item>
     <a-descriptions-item label="澶勭悊绫诲瀷	">{{currentLevelDetails.processType}}</a-descriptions-item>
     <a-descriptions-item label="缁撴瀯绫诲瀷	">{{currentLevelDetails.structureType}}</a-descriptions-item>
-    <a-descriptions-item label="閲嶉噺" :span="2">{{currentLevelDetails.componentWeight}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateName}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼鏃堕棿" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
-    <a-descriptions-item label="鎻忚堪" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
+    <a-descriptions-item label="閲嶉噺" >{{currentLevelDetails.componentWeight}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓鏃堕棿">{{currentLevelDetails.createTime}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼鏃堕棿">{{currentLevelDetails.updateTime}}</a-descriptions-item>
+    <a-descriptions-item label="鎻忚堪" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
   </a-descriptions>
 </template>
 
diff --git a/src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue
deleted file mode 100644
index 62a3182..0000000
--- a/src/views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-<template>
-  <a-descriptions bordered :size="size">
-    <a-descriptions-item label="鍒�鍏峰悕绉�">{{currentLevelDetails.cutterName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒�鍏风紪鍙�">{{currentLevelDetails.cutterCode}}</a-descriptions-item>
-    <a-descriptions-item label="鍒�鍏风被鍨�">{{currentLevelDetails.cutterType}}</a-descriptions-item>
-    <a-descriptions-item label="棰濆畾瀵垮懡">{{currentLevelDetails.lifetime}}</a-descriptions-item>
-    <a-descriptions-item label="鍒�浣�">{{currentLevelDetails.cutterSpacing}}</a-descriptions-item>
-    <a-descriptions-item label="鏁伴噺">{{currentLevelDetails.quantity}}</a-descriptions-item>
-    <a-descriptions-item label="鎻忚堪" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
-  </a-descriptions>
-</template>
-
-<script>
-export default {
-  name: 'CutterInfo',
-  components: {},
-  props: {
-    currentLevelDetails: {
-      type: Object
-    },
-    size: {
-      type: String
-    }
-  },
-  data() {
-    return {}
-  },
-  methods: {}
-}
-</script>
-
-<style scoped>
-
-</style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue
new file mode 100644
index 0000000..2503b1c
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue
@@ -0,0 +1,77 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    :maskClosable="false"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    cancelText="鍏抽棴">
+    <CutterModalForm ref="realForm" @ok="submitCallback" :disableSubmit="disableSubmit"/>
+  </j-modal>
+</template>
+
+<script>
+import CutterModalForm from './CutterModalForm.vue'
+
+export default {
+  name: 'CutterModal',
+  components: {
+    CutterModalForm
+  },
+  props: {
+    currentTreeNodeInfo: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      title: '',
+      width: 700,
+      visible: false,
+      disableSubmit: false
+    }
+  },
+  methods: {
+    // 娣诲姞鎵�鐢ㄥ垁鍏�
+    handleCutterAdd() {
+      const { id, type } = this.currentTreeNodeInfo
+      this.visible = true
+      this.$nextTick(() => {
+        if (this.$refs.realForm) {
+          this.$refs.realForm.add({
+            attributionId: id,
+            attributionType: type
+          })
+        }
+      })
+    },
+
+    // 缂栬緫鍒�鍏蜂俊鎭�
+    handleCutterEdit(record) {
+      this.visible = true
+      this.$nextTick(() => {
+        if (this.$refs.realForm) {
+          this.$refs.realForm.edit({ ...record })
+        }
+      })
+    },
+
+    handleOk() {
+      this.$refs.realForm.submitForm()
+    },
+
+    submitCallback() {
+      this.$emit('submitSuccess')
+      this.visible = false
+    },
+
+    handleCancel() {
+      this.$emit('close')
+      this.visible = false
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue
new file mode 100644
index 0000000..3c5c2c9
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterModalForm.vue
@@ -0,0 +1,152 @@
+<template>
+  <a-spin :spinning="confirmLoading">
+    <a-form-model ref="form" :model="model" :rules="validatorRules" :labelCol="labelCol" :wrapperCol="wrapperCol">
+      <a-row>
+        <a-col :span="12">
+          <a-form-model-item label="鍒�鍏风紪鍙�" prop="cutterCode">
+            <a-input v-model="model.cutterCode" placeholder="璇疯緭鍏ュ垁鍏风紪鍙�" :readOnly="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+        <a-col :span="12">
+          <a-form-model-item label="鍒�鍏峰悕绉�" prop="cutterName">
+            <a-input v-model="model.cutterName" placeholder="璇疯緭鍏ュ垁鍏峰悕绉�" :readOnly="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+
+      <a-row>
+        <a-col :span="12">
+          <a-form-model-item label="鍒�鍏风被鍨�">
+            <j-dict-select-tag v-model="model.cutterType" placeholder="璇烽�夋嫨鍒�鍏风被鍨�" dictCode="cutter_type"
+                               :disabled="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+        <a-col :span="12">
+          <a-form-model-item label="棰濆畾瀵垮懡">
+            <a-input-number v-model="model.lifetime" :min="0" placeholder="璇疯緭鍏ラ瀹氬鍛�" style="width: 100%"
+                            :disabled="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+
+      <a-row>
+        <a-col :span="12">
+          <a-form-model-item label="鍒�浣�">
+            <a-input v-model="model.cutterSpacing" placeholder="璇疯緭鍏ュ垁浣�" :readOnly="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+        <a-col :span="12">
+          <a-form-model-item label="鍒�鍏锋暟閲�">
+            <a-input-number v-model="model.quantity" placeholder="璇疯緭鍏ュ垁鍏锋暟閲�" :min="1" style="width: 100%"
+                            :disabled="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+
+      <a-row>
+        <a-col :span="24">
+          <a-form-model-item label="鎻忚堪" :labelCol="labelColLong" :wrapperCol="wrapperColLong">
+            <a-textarea v-model="model.description" placeholder="璇疯緭鍏ユ弿杩�" :readOnly="disableSubmit"/>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+    </a-form-model>
+  </a-spin>
+</template>
+
+<script>
+import { httpAction } from '@/api/manage'
+
+export default {
+  name: 'CutterModalForm',
+  components: {},
+  props: {
+    disableSubmit: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      model: {
+        quantity: 1
+      },
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 14 }
+      },
+      labelColLong: {
+        xs: { span: 24 },
+        sm: { span: 4 }
+      },
+      wrapperColLong: {
+        xs: { span: 24 },
+        sm: { span: 19 }
+      },
+      confirmLoading: false,
+      validatorRules: {
+        cutterCode: [
+          { required: true, message: '璇疯緭鍏ュ垁鍏风紪鍙�!' }
+        ],
+        cutterName: [
+          { required: true, message: '璇疯緭鍏ュ垁鍏峰悕绉�!' }
+        ]
+      },
+      url: {
+        add: '/nc/cutter/add',
+        edit: '/nc/cutter/edit'
+      }
+    }
+  },
+  created() {
+    //澶囦唤model鍘熷鍊�
+    this.modelDefault = JSON.parse(JSON.stringify(this.model))
+  },
+  methods: {
+    add(params) {
+      this.edit({ ...this.modelDefault, ...params })
+    },
+    edit(record) {
+      this.model = Object.assign({}, record)
+      console.log('model', this.model)
+    },
+    submitForm() {
+      const that = this
+      // 瑙﹀彂琛ㄥ崟楠岃瘉
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          that.confirmLoading = true
+          let httpUrl, method
+          if (!this.model.id) {
+            httpUrl = this.url.add
+            method = 'post'
+          } else {
+            httpUrl = this.url.edit
+            method = 'put'
+          }
+          httpAction(httpUrl, this.model, method).then((res) => {
+            if (res.success) {
+              that.$notification.success({
+                message: '娑堟伅',
+                description: res.message
+              })
+              that.$emit('ok')
+            } else {
+              that.$notification.warning({
+                message: '娑堟伅',
+                description: res.message
+              })
+            }
+          }).finally(() => {
+            that.confirmLoading = false
+          })
+        }
+
+      })
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue
new file mode 100644
index 0000000..09270d2
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/Cutter/CutterTableList.vue
@@ -0,0 +1,153 @@
+<template>
+  <div>
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :md="5" :sm="5">
+            <a-form-item label="鍒�鍏风紪鍙�">
+              <a-input placeholder="璇疯緭鍏ュ垁鍏风紪鍙�" v-model="queryParam.cutterCode" allow-clear/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="5" :sm="5">
+            <a-form-item label="鍒�鍏峰悕绉�">
+              <a-input placeholder="璇疯緭鍏ュ垁鍏峰悕绉�" v-model="queryParam.cutterName" allow-clear/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="4" :sm="4">
+            <a-space>
+              <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
+              <a-button type="primary" @click="handleAdd" icon="plus" v-has="'cutter_add'">鏂板</a-button>
+              <a-button type="primary" @click="handleExportXls('鍒�鍏峰垪琛�')" icon="export">瀵煎嚭</a-button>
+              <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader"
+                        :action="importExcelUrl" @change="handleImportExcel">
+                <a-button type="primary" icon="import">瀵煎叆</a-button>
+              </a-upload>
+            </a-space>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+
+    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination" :size="size" rowKey="id"
+             @change="handleTableChange" :scroll="{y:189}">
+      <template slot="action" slot-scope="text, record">
+        <a @click="handleEdit(record)">缂栬緫</a>
+
+        <a-divider type="vertical"/>
+
+        <a-dropdown>
+          <a class="ant-dropdown-link">
+            鏇村
+            <a-icon type="down"/>
+          </a>
+          <a-menu slot="overlay">
+            <a-menu-item>
+              <a href="javascript:;" @click="handleDetail(record)">璇︽儏</a>
+            </a-menu-item>
+
+            <a-menu-item>
+              <a-popconfirm title="纭畾鍒犻櫎鍚�?" @confirm="() => handleDelete(record.id)">
+                <a>鍒犻櫎</a>
+              </a-popconfirm>
+            </a-menu-item>
+          </a-menu>
+        </a-dropdown>
+      </template>
+    </a-table>
+
+    <CutterModal ref="cutterModalRef" :currentTreeNodeInfo="currentLevelInfo" @submitSuccess="loadData"/>
+  </div>
+</template>
+
+<script>
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import CutterModal from '@views/dnc/base/modules/ProductStructure/Cutter/CutterModal.vue'
+
+export default {
+  name: 'CutterTableList',
+  components: { CutterModal },
+  mixins: [JeecgListMixin],
+  props: {
+    currentLevelInfo: {
+      type: Object
+    },
+    size: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      disableMixinCreated: true,
+      columns: [
+        {
+          title: '搴忓彿',
+          dataIndex: 'rowIndex',
+          key: 'rowIndex',
+          width: 65,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        { title: '鍒�鍏风紪鍙�', dataIndex: 'cutterCode', align: 'center' },
+        { title: '鍒�鍏峰悕绉�', dataIndex: 'cutterName', align: 'center' },
+        { title: '鍒�鍏风被鍨�', dataIndex: 'cutterType_dictText', align: 'center' },
+        { title: '棰濆畾瀵垮懡', dataIndex: 'lifetime', width: 150, align: 'center' },
+        { title: '鍒�浣�', dataIndex: 'cutterSpacing', width: 150, align: 'center' },
+        { title: '鍒�鍏锋暟閲�', dataIndex: 'quantity', width: 150, align: 'center' },
+        { title: '鎿嶄綔', dataIndex: 'action', scopedSlots: { customRender: 'action' }, align: 'center', width: 150 }
+      ],
+      url: {
+        list: '/nc/cutter/getByBusinessId',
+        delete: '/nc/cutter/delete',
+        exportXlsUrl: '/nc/cutter/exportXls',
+        importExcelUrl: '/nc/cutter/importExcel'
+      }
+    }
+  },
+  computed: {
+    importExcelUrl: function() {
+      return `${window._CONFIG['domianURL']}${this.url.importExcelUrl}`
+    }
+  },
+  methods: {
+    setQueryParamAndLoadData(pageNo = 1) {
+      const { id, type } = this.currentLevelInfo
+      this.queryParam = Object.assign({}, { attributionId: id, attributionType: type })
+      this.loadData(pageNo)
+    },
+
+    handleAdd() {
+      if (!this.$refs.cutterModalRef) return
+      this.$refs.cutterModalRef.title = '娣诲姞鍒�鍏�'
+      this.$refs.cutterModalRef.disableSubmit = false
+      this.$refs.cutterModalRef.handleCutterAdd()
+    },
+
+    /**
+     * 缂栬緫琛ㄦ牸琛屼俊鎭�
+     * @param record 琛ㄦ牸琛屼俊鎭�
+     */
+    handleEdit(record) {
+      if (!this.$refs.cutterModalRef) return
+      this.$refs.cutterModalRef.title = '缂栬緫鍒�鍏蜂俊鎭�'
+      this.$refs.cutterModalRef.disableSubmit = false
+      this.$refs.cutterModalRef.handleCutterEdit(record)
+    },
+
+    /**
+     * 鏌ョ湅琛ㄦ牸瀹屾暣琛屼俊鎭�
+     * @param record 琛ㄦ牸琛屼俊鎭�
+     */
+    handleDetail: function(record) {
+      if (!this.$refs.cutterModalRef) return
+      this.$refs.cutterModalRef.title = '鍒�鍏疯鎯�'
+      this.$refs.cutterModalRef.disableSubmit = true
+      this.$refs.cutterModalRef.handleCutterEdit(record)
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue
new file mode 100644
index 0000000..82753ab
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue
@@ -0,0 +1,80 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    :maskClosable="false"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    cancelText="鍏抽棴">
+    <DeviceCustomTypeModalForm ref="realForm" @ok="handleCancel"/>
+  </j-modal>
+</template>
+
+<script>
+import DeviceCustomTypeModalForm from './DeviceCustomTypeModalForm'
+
+export default {
+  name: 'DeviceCustomTypeModal',
+  components: {
+    DeviceCustomTypeModalForm
+  },
+  data() {
+    return {
+      title: '',
+      width: 700,
+      visible: false
+    }
+  },
+  created() {
+    this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+  },
+  methods: {
+    // 鐐瑰嚮娣诲姞璁惧绫绘柊澧炲伐搴忔垨宸ユ涓嬭澶囩被
+    handleAddType(treeNodeInfo) {
+      this.visible = true
+      const { treeKey, type } = treeNodeInfo
+      console.log('treeNodeInfo', treeNodeInfo)
+      this.$nextTick(() => {
+        if (this.$refs.realForm) {
+          this.$refs.realForm.add({
+            attributionId: treeKey,
+            attributionType: type
+          })
+          this.$refs.realForm.getWorkshopListByApi()
+        }
+      })
+    },
+
+    // 缂栬緫璁惧绫讳俊鎭�
+    handleTypeEdit(_, tableRowInfo) {
+      this.visible = true
+      this.$nextTick(() => {
+        if (this.$refs.realForm) {
+          this.$refs.realForm.getWorkshopListByApi()
+          this.$refs.realForm.handleProductionChange()
+          this.$refs.realForm.edit({ ...tableRowInfo })
+        }
+      })
+    },
+
+    handleCancel() {
+      this.visible = false
+    },
+
+    handleOk() {
+      this.$refs.realForm.submitForm()
+    },
+
+    triggerCorrespondingMethod({ methodName, modalTitle, treeNodeInfo, tableRowInfo }) {
+      console.log('瑙﹀彂鍙抽敭鑿滃崟')
+      if (this[methodName]) {
+        this.title = modalTitle
+        this[methodName](treeNodeInfo, tableRowInfo)
+      }
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue
new file mode 100644
index 0000000..b587cd7
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModalForm.vue
@@ -0,0 +1,150 @@
+<template>
+  <a-spin :spinning="confirmLoading">
+    <a-form-model ref="form" :model="model" :rules="validatorRules" :labelCol="labelCol" :wrapperCol="wrapperCol">
+      <a-row>
+        <a-col :span="12">
+          <a-form-model-item label="杞﹂棿" prop="productionId">
+            <a-select v-model="model.productionId" placeholder="璇烽�夋嫨杞﹂棿" @change="handleProductionChange">
+              <a-select-option v-for="item in workshopTreeData" :key="item.id">
+                {{ item.productionName }}
+              </a-select-option>
+            </a-select>
+          </a-form-model-item>
+        </a-col>
+
+        <a-col :span="12">
+          <a-form-model-item label="璁惧绫�" prop="deviceManagementId">
+            <a-select v-model="model.deviceManagementId" placeholder="璇烽�夋嫨璁惧绫�" :disabled="!model.productionId"
+                      @change="handleCodeSelectChange">
+              <a-select-option v-for="item in deviceCustomTypeList" :key="item.id">
+                {{ item.deviceManagementCode }}
+              </a-select-option>
+            </a-select>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+
+      <a-row>
+        <a-col :span="12">
+          <a-form-model-item label="璁惧绫诲悕绉�">
+            <a-input v-model="model.deviceManagementId_dictText" placeholder="璇烽�夋嫨璁惧绫�" readOnly/>
+          </a-form-model-item>
+        </a-col>
+      </a-row>
+    </a-form-model>
+  </a-spin>
+</template>
+
+<script>
+import { httpAction } from '@/api/manage'
+import dncApi from '@/api/dnc'
+
+export default {
+  name: 'DeviceCustomTypeModalForm',
+  components: {},
+  data() {
+    return {
+      model: {},
+      workshopTreeData: [],
+      deviceCustomTypeList: [],
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 17 }
+      },
+      confirmLoading: false,
+      validatorRules: {
+        productionId: [
+          { required: true, message: '璇烽�夋嫨杞﹂棿!' }
+        ],
+        deviceManagementId: [
+          { required: true, message: '璇烽�夋嫨璁惧绫�!' }
+        ]
+      },
+      url: {
+        add: '/nc/deviceType/add',
+        edit: '/nc/deviceType/edit'
+      }
+    }
+  },
+  created() {
+    //澶囦唤model鍘熷鍊�
+    this.modelDefault = JSON.parse(JSON.stringify(this.model))
+  },
+  methods: {
+    // 璋冪敤鎺ュ彛鑾峰彇鏌ヨ鍖哄煙杞﹂棿鏍戝垪琛�
+    getWorkshopListByApi() {
+      dncApi.getHasPermissionWorkshopTreeApi()
+        .then(res => {
+          if (res.success) this.workshopTreeData = res.result
+        })
+    },
+
+    // 杞﹂棿閫夋嫨鏀瑰彉鍚庢竻绌鸿澶囩被閫夋嫨骞堕噸鏂拌幏鍙栬澶囩被鍒楄〃
+    handleProductionChange() {
+      if (this.model.deviceManagementId) delete this.model.deviceManagementId
+      if (this.model.deviceManagementId_dictText) delete this.model.deviceManagementId_dictText
+      dncApi.getDeviceCustomTypeListByProductionIdApi(this.model.productionId)
+        .then(res => {
+          if (res.success) this.deviceCustomTypeList = res.result
+        })
+    },
+
+    /**
+     * 璁惧绫婚�夋嫨鏀瑰彉鍚庤Е鍙戝~鍏呰澶囩被瀵瑰簲璁惧绫诲悕绉�
+     * @param value
+     */
+    handleCodeSelectChange(value) {
+      this.$set(this.model, 'deviceManagementId_dictText', this.deviceCustomTypeList.find(item => item.id === value).deviceManagementName)
+    },
+
+    add(params) {
+      this.edit({ ...this.modelDefault, ...params })
+    },
+
+    edit(record) {
+      this.model = Object.assign({}, record)
+    },
+
+    submitForm() {
+      const that = this
+      // 瑙﹀彂琛ㄥ崟楠岃瘉
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          that.confirmLoading = true
+          let httpUrl, method
+          if (!this.model.id) {
+            httpUrl = that.url.add
+            method = 'post'
+          } else {
+            httpUrl = that.url.edit
+            method = 'put'
+          }
+          httpAction(httpUrl, that.model, method)
+            .then((res) => {
+              if (res.success) {
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+                that.$bus.$emit('deviceCustomTypeAddSubmitSuccess')
+                that.$emit('ok')
+              } else {
+                that.$notification.warning({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              }
+            })
+            .finally(() => {
+              that.confirmLoading = false
+            })
+        }
+      })
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue
new file mode 100644
index 0000000..ca58908
--- /dev/null
+++ b/src/views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue
@@ -0,0 +1,167 @@
+<template>
+  <div style="flex: 0.25;margin-right: 10px">
+    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false"
+             :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="id" @change="handleTableChange">
+
+    </a-table>
+  </div>
+</template>
+
+<script>
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import DeviceCustomTypeModal from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
+import { deleteAction } from '@api/manage'
+
+export default {
+  name: 'DeviceCustomTypeTableList',
+  components: { DeviceCustomTypeModal },
+  mixins: [JeecgListMixin],
+  props: {
+    currentTreeNodeInfo: {
+      type: Object
+    },
+    size: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      disableMixinCreated: true,
+      columns: [
+        // {
+        //   title: '杞﹂棿',
+        //   dataIndex: 'productionId_dictText',
+        //   align: 'center'
+        // },
+        {
+          title: '璁惧绫�',
+          dataIndex: 'deviceManagementCode_dictText',
+          align: 'center'
+        },
+        {
+          title: '璁惧绫诲悕绉�',
+          dataIndex: 'deviceManagementId_dictText',
+          align: 'center'
+        }
+      ],
+      dataSource: [],
+      currentRightClickedTypeInfo: {},
+      currentClickedTypeInfo: {},
+      url: {
+        list: '/nc/deviceType/getByBusinessId',
+        delete: '/nc/deviceType/delete'
+      }
+    }
+  },
+  watch: {
+    currentTreeNodeInfo: {
+      handler(value) {
+        this.currentClickedTypeInfo = {}
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+    this.$bus.$on('deviceCustomTypeAddSubmitSuccess', this.loadData)
+  },
+  methods: {
+    setQueryParamAndLoadData() {
+      console.log('currentLevelInfo', this.currentTreeNodeInfo)
+      const { id, type } = this.currentTreeNodeInfo
+      this.queryParam = Object.assign({}, { attributionId: id, attributionType: type })
+      this.loadData()
+    },
+
+    customRow(record) {
+      return {
+        on: {
+          contextmenu: event => {
+            event.preventDefault()
+            this.currentRightClickedTypeInfo = Object.assign({ param: 'deviceCustomType' }, record)
+            this.$emit('handleTableContextMenuOpen', this.currentRightClickedTypeInfo)
+          },
+          click: () => {
+            if (this.currentClickedTypeInfo.docId === record.docId) return
+            this.currentClickedTypeInfo = Object.assign({}, record)
+            // this.$bus.$emit('sendCurrentClickedDocumentInfo', record)
+          }
+        }
+      }
+    },
+
+    /**
+     * 琛ㄦ牸鍒嗛〉銆佹帓搴忔敼鍙樸�佺瓫閫夋椂瑙﹀彂
+     * @param pagination 鍒嗛〉鍣ㄩ�夐」
+     * @param filters 绛涢�夐�夐」
+     * @param sorter 鎺掑簭閫夐」
+     */
+    handleTableChange(pagination, filters, sorter) {
+      if (sorter.order) {
+        this.isorter.column = sorter.field
+        this.isorter.order = sorter.order === 'ascend' ? 'asc' : 'desc'
+      } else {
+        this.isorter.column = 'createTime'
+        this.isorter.order = 'desc'
+      }
+      for (let key in filters) {
+        this.filters[key] = filters[key].join(',')
+      }
+      this.ipagination = pagination
+      this.loadData()
+    },
+
+    /**
+     * 鍒犻櫎宸ュ簭鎴栧伐姝ュ眰绾ф坊鍔犵殑璁惧绫�
+     * @param tableRowInfo
+     */
+    handleTypeDelete(tableRowInfo) {
+      const { id } = tableRowInfo
+      const { $confirm, url, loadData, $notification, $destroyAll } = this
+      $confirm({
+        title: '鎻愮ず',
+        content: '纭鍒犻櫎姝ゆ潯璁板綍鍚楋紵',
+        okText: '纭',
+        okType: 'danger',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          if (!url.delete) {
+            this.$message.error('璇疯缃畊rl.delete灞炴��!')
+            return
+          }
+
+          deleteAction(url.delete, { id: id })
+            .then((res) => {
+              if (res.success) {
+                $notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+                loadData()
+              } else {
+                $notification.warning({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              }
+            })
+            .finally(() => {
+              $destroyAll()
+            })
+        },
+        onCancel: () => {
+          $destroyAll()
+        }
+      })
+    },
+
+    triggerCorrespondingMethod({ methodName, modalTitle, tableRowInfo }) {
+      if (this[methodName] && tableRowInfo.param === 'deviceCustomType') this[methodName](tableRowInfo, modalTitle)
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue b/src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
index 302e9a6..079bd14 100644
--- a/src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Document/NcDocumentTableList.vue
@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div style="flex: 1">
     <a-table :columns="columns" :data-source="dataSource" bordered :pagination="ipagination"
              :scroll="{y:189}" :customRow="customRow" :size="size" rowKey="docId" @change="handleTableChange">
 
diff --git a/src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue b/src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue
index b91d89a..048e7cf 100644
--- a/src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Part/PartInfo.vue
@@ -1,6 +1,6 @@
 <template>
-  <a-descriptions bordered :size="size">
-    <a-descriptions-item label="闆朵欢鍚嶇О">{{currentLevelDetails.partsName}}</a-descriptions-item>
+  <a-descriptions bordered :size="size" :column="4">
+    <a-descriptions-item label="闆朵欢鍚嶇О" :span="2">{{currentLevelDetails.partsName}}</a-descriptions-item>
     <a-descriptions-item label="闆朵欢浠e彿">{{currentLevelDetails.partsCode}}</a-descriptions-item>
     <a-descriptions-item label="闆朵欢鍨嬪彿	">{{currentLevelDetails.partsModel}}</a-descriptions-item>
     <a-descriptions-item label="鐗╂枡缂栫爜">{{currentLevelDetails.materielCode}}</a-descriptions-item>
@@ -10,12 +10,12 @@
     <a-descriptions-item label="鐢熶骇绫诲瀷">{{currentLevelDetails.produceType}}</a-descriptions-item>
     <a-descriptions-item label="澶勭悊绫诲瀷	">{{currentLevelDetails.processType}}</a-descriptions-item>
     <a-descriptions-item label="缁撴瀯绫诲瀷	">{{currentLevelDetails.structureType}}</a-descriptions-item>
-    <a-descriptions-item label="閲嶉噺" :span="2">{{currentLevelDetails.partsWeight}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateName}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼鏃堕棿" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
-    <a-descriptions-item label="鎻忚堪" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
+    <a-descriptions-item label="閲嶉噺">{{currentLevelDetails.partsWeight}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓鏃堕棿">{{currentLevelDetails.createTime}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼鏃堕棿">{{currentLevelDetails.updateTime}}</a-descriptions-item>
+    <a-descriptions-item label="鎻忚堪" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
   </a-descriptions>
 </template>
 
diff --git a/src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue b/src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
index 07b8f9e..6491b13 100644
--- a/src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
@@ -27,124 +27,123 @@
 </template>
 
 <script>
-  import dncApi from '@/api/dnc'
-  import DepartPermissionTransfer from './DepartPermissionTransfer'
-  import UserPermissionTransfer from './UserPermissionTransfer'
-  import { queryProductionTreeList } from '@/api/api'
+import dncApi from '@/api/dnc'
+import DepartPermissionTransfer from './DepartPermissionTransfer'
+import UserPermissionTransfer from './UserPermissionTransfer'
 
-  export default {
-    name: 'AssignPermissionModal',
-    components: { UserPermissionTransfer, DepartPermissionTransfer },
-    props: {
-      currentTreeNodeInfo: {
-        type: Object
-      }
-    },
-    data() {
-      return {
-        visible: false,
-        title: '',
-        isAssignSonNode: true,
-        activeTabKey: 1,
-        allDepartmentsList: [],
-        allUsersList: [],
-        allTreeKeys: [],
-        hasLoadedDataTabKeyArray: []
-      }
-    },
-    watch: {
-      visible: {
-        handler(value) {
-          if (value) {
-            this.activeTabKey = 1
-            this.isAssignSonNode = true
-            this.getAllDepartmentsListByApi()
-          }
-        }
-      },
-      activeTabKey: {
-        handler(value) {
-          if (this.hasLoadedDataTabKeyArray.includes(value)) return
-          if (value === 2) this.getAllUsersListByApi()
-          this.hasLoadedDataTabKeyArray.push(value)
+export default {
+  name: 'AssignPermissionModal',
+  components: { UserPermissionTransfer, DepartPermissionTransfer },
+  props: {
+    currentTreeNodeInfo: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      title: '',
+      isAssignSonNode: true,
+      activeTabKey: 1,
+      allDepartmentsList: [],
+      allUsersList: [],
+      allTreeKeys: [],
+      hasLoadedDataTabKeyArray: []
+    }
+  },
+  watch: {
+    visible: {
+      handler(value) {
+        if (value) {
+          this.activeTabKey = 1
+          this.isAssignSonNode = true
+          this.getAllDepartmentsListByApi()
         }
       }
     },
-    created() {
-      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+    activeTabKey: {
+      handler(value) {
+        if (this.hasLoadedDataTabKeyArray.includes(value)) return
+        if (value === 2) this.getAllUsersListByApi()
+        this.hasLoadedDataTabKeyArray.push(value)
+      }
+    }
+  },
+  created() {
+    this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+  },
+  methods: {
+    // 鐐瑰嚮鏍戣妭鐐瑰彸閿彍鍗曟潈闄愰厤缃寜閽悗瑙﹀彂
+    handleAssignPermission() {
+      this.visible = true
     },
-    methods: {
-      // 鐐瑰嚮鏍戣妭鐐瑰彸閿彍鍗曟潈闄愰厤缃寜閽悗瑙﹀彂
-      handleAssignPermission() {
-        this.visible = true
-      },
 
-      // 璋冪敤鎺ュ彛鑾峰彇鎵�鏈夎溅闂村垪琛�
-      getAllDepartmentsListByApi() {
-        this.allTreeKeys = []
-        queryProductionTreeList()
-          .then(res => {
-            if (res.success) {
-              this.allDepartmentsList = res.result
-              this.generateList(this.allDepartmentsList)
-              this.$nextTick(() => {
-                this.$refs.departPermissionTransferRef.getHasPermissionDepartByApi()
-                this.$refs.departPermissionTransferRef.expandedKeys = this.allTreeKeys
-                this.$refs.departPermissionTransferRef.flatten(JSON.parse(JSON.stringify(this.allDepartmentsList)))
-              })
-              // 鍙湁涓婃閫�鍑烘椂鍦ㄨ溅闂村垎閰峵ab鐣岄潰鎵嶄細杩涘叆姝ゅ垽鏂�
-              // 鑻ヤ笂娆¢��鍑烘椂鍦ㄧ敤鎴峰垎閰峵ab鐣岄潰鍒欏啀娆¤繘鍏ユ椂key鐢�2鍙樹负1鏃朵細瑙﹀彂watch鐩戞祴activeTabKey鍙樺寲鍒欎細灏唊ey:1鍔犲叆hasLoadedDataTabKeyArray锛屽洜姝ゆ棤闇�鍐嶆鍔犲叆key:1
-              if (!this.hasLoadedDataTabKeyArray.includes(this.activeTabKey)) this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
-            }
-          })
-      },
-
-      /**
-       * 閫掑綊鑾峰緱鎵�鏈夋爲鑺傜偣key
-       * @param data
-       */
-      generateList(data) {
-        for (let i = 0; i < data.length; i++) {
-          const node = data[i]
-          const key = node.key
-          this.allTreeKeys.push(key)
-          if (node.children) this.generateList(node.children)
-        }
-      },
-
-      // 璋冪敤鎺ュ彛鑾峰彇鎵�鏈夌敤鎴峰垪琛�
-      getAllUsersListByApi() {
-        dncApi.getAllUsersListApi()
-          .then(res => {
-            if (res.success) {
-              this.allUsersList = res.result.records
-              this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
-            }
-          })
-      },
-
-      setAdminDisabled() {
-        this.allUsersList = this.allUsersList.map(item => {
-          return {
-            ...item,
-            disabled: item.username === 'admin'
+    // 璋冪敤鎺ュ彛鑾峰彇鎵�鏈夎溅闂村垪琛�
+    getAllDepartmentsListByApi() {
+      this.allTreeKeys = []
+      dncApi.getAllDepartmentsListApi()
+        .then(res => {
+          if (res.success) {
+            this.allDepartmentsList = res.result
+            this.generateList(this.allDepartmentsList)
+            this.$nextTick(() => {
+              this.$refs.departPermissionTransferRef.getHasPermissionDepartByApi()
+              this.$refs.departPermissionTransferRef.expandedKeys = this.allTreeKeys
+              this.$refs.departPermissionTransferRef.flatten(JSON.parse(JSON.stringify(this.allDepartmentsList)))
+            })
+            // 鍙湁涓婃閫�鍑烘椂鍦ㄨ溅闂村垎閰峵ab鐣岄潰鎵嶄細杩涘叆姝ゅ垽鏂�
+            // 鑻ヤ笂娆¢��鍑烘椂鍦ㄧ敤鎴峰垎閰峵ab鐣岄潰鍒欏啀娆¤繘鍏ユ椂key鐢�2鍙樹负1鏃朵細瑙﹀彂watch鐩戞祴activeTabKey鍙樺寲鍒欎細灏唊ey:1鍔犲叆hasLoadedDataTabKeyArray锛屽洜姝ゆ棤闇�鍐嶆鍔犲叆key:1
+            if (!this.hasLoadedDataTabKeyArray.includes(this.activeTabKey)) this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
           }
         })
-      },
+    },
 
-      handleModalClose() {
-        this.visible = false
-        this.hasLoadedDataTabKeyArray = []
-      },
+    /**
+     * 閫掑綊鑾峰緱鎵�鏈夋爲鑺傜偣key
+     * @param data
+     */
+    generateList(data) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        const key = node.key
+        this.allTreeKeys.push(key)
+        if (node.children) this.generateList(node.children)
+      }
+    },
 
-      triggerCorrespondingMethod({ methodName, modalTitle }) {
-        if (this[methodName]) {
-          this[methodName]()
-          this.title = modalTitle
+    // 璋冪敤鎺ュ彛鑾峰彇鎵�鏈夌敤鎴峰垪琛�
+    getAllUsersListByApi() {
+      dncApi.getAllUsersListApi()
+        .then(res => {
+          if (res.success) {
+            this.allUsersList = res.result.records
+            this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
+          }
+        })
+    },
+
+    setAdminDisabled() {
+      this.allUsersList = this.allUsersList.map(item => {
+        return {
+          ...item,
+          disabled: item.username === 'admin'
         }
+      })
+    },
+
+    handleModalClose() {
+      this.visible = false
+      this.hasLoadedDataTabKeyArray = []
+    },
+
+    triggerCorrespondingMethod({ methodName, modalTitle }) {
+      if (this[methodName]) {
+        this[methodName]()
+        this.title = modalTitle
       }
     }
   }
+}
 </script>
 
 <style scoped>
diff --git a/src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue b/src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue
index 2595b24..264c31b 100644
--- a/src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Process/ProcessInfo.vue
@@ -1,19 +1,19 @@
 <template>
-  <a-descriptions bordered :size="size">
-    <a-descriptions-item label="宸ュ簭鍚嶇О">{{currentLevelDetails.processName}}</a-descriptions-item>
-    <a-descriptions-item label="宸ュ簭鍙�">{{currentLevelDetails.processCode}}</a-descriptions-item>
-    <a-descriptions-item label="宸ヨ壓缂栧彿	">{{currentLevelDetails.craftNo}}</a-descriptions-item>
+  <a-descriptions bordered :size="size" :column="4">
+    <a-descriptions-item label="宸ュ簭鍚嶇О" :span="2">{{currentLevelDetails.processName}}</a-descriptions-item>
+    <a-descriptions-item label="宸ュ簭鍙�" :span="2">{{currentLevelDetails.processCode}}</a-descriptions-item>
+    <a-descriptions-item label="宸ヨ壓缂栧彿" :span="2">{{currentLevelDetails.craftNo}}</a-descriptions-item>
     <a-descriptions-item label="宸ュ簭绫诲瀷">{{currentLevelDetails.processType}}</a-descriptions-item>
     <a-descriptions-item label="鍔犲伐璁惧鍨嬪彿">{{currentLevelDetails.processingEquipmentModel}}</a-descriptions-item>
     <a-descriptions-item label="鍔犲伐璁惧绫诲瀷">{{currentLevelDetails.processingEquipmentOs}}</a-descriptions-item>
     <a-descriptions-item label="鍔犲伐璁惧缂栧彿">{{currentLevelDetails.processingEquipmentCode}}</a-descriptions-item>
     <a-descriptions-item label="宸ヨ缂栧彿">{{currentLevelDetails.assembleStep}}</a-descriptions-item>
-    <a-descriptions-item label="宸ヨ鍚嶇О	">{{currentLevelDetails.assembleName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateName}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼鏃堕棿" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
-    <a-descriptions-item label="鎻忚堪" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
+    <a-descriptions-item label="宸ヨ鍚嶇О">{{currentLevelDetails.assembleName}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓鏃堕棿">{{currentLevelDetails.createTime}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼鏃堕棿">{{currentLevelDetails.updateTime}}</a-descriptions-item>
+    <a-descriptions-item label="鎻忚堪" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
   </a-descriptions>
 </template>
 
diff --git a/src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue b/src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
index 0823c70..25d939d 100644
--- a/src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Process/ProcessModalForm.vue
@@ -122,7 +122,6 @@
     created() {
       //澶囦唤model鍘熷鍊�
       this.modelDefault = JSON.parse(JSON.stringify(this.model))
-      this.$bus.$on('sendAllDeviceList', deviceList => this.deviceList = deviceList)
     },
     methods: {
       add(params) {
diff --git a/src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue b/src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue
index d4649d5..550a750 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProcessStep/ProcessStepInfo.vue
@@ -1,5 +1,5 @@
 <template>
-  <a-descriptions bordered :size="size">
+  <a-descriptions bordered :size="size" :column="4">
     <a-descriptions-item label="宸ユ鍚嶇О">{{currentLevelDetails.stepName}}</a-descriptions-item>
     <a-descriptions-item label="宸ユ鍙�">{{currentLevelDetails.stepCode}}</a-descriptions-item>
     <a-descriptions-item label="宸ユ绫诲瀷">{{currentLevelDetails.stepType}}</a-descriptions-item>
@@ -7,12 +7,12 @@
     <a-descriptions-item label="鍔犲伐璁惧绫诲瀷">{{currentLevelDetails.processingEquipmentOs}}</a-descriptions-item>
     <a-descriptions-item label="鍔犲伐璁惧缂栧彿">{{currentLevelDetails.deviceNo}}</a-descriptions-item>
     <a-descriptions-item label="宸ヨ缂栧彿">{{currentLevelDetails.assembleStep}}</a-descriptions-item>
-    <a-descriptions-item label="宸ヨ鍚嶇О	" :span="2">{{currentLevelDetails.assembleName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateName}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼鏃堕棿" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
-    <a-descriptions-item label="鎻忚堪" :span="3">{{currentLevelDetails.description}}</a-descriptions-item>
+    <a-descriptions-item label="宸ヨ鍚嶇О">{{currentLevelDetails.assembleName}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓鏃堕棿">{{currentLevelDetails.createTime}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼鏃堕棿">{{currentLevelDetails.updateTime}}</a-descriptions-item>
+    <a-descriptions-item label="鎻忚堪" :span="4">{{currentLevelDetails.description}}</a-descriptions-item>
   </a-descriptions>
 </template>
 
diff --git a/src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue b/src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
index d28dc8a..e20f3c8 100644
--- a/src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
+++ b/src/views/dnc/base/modules/ProductStructure/Product/ProductInfo.vue
@@ -1,12 +1,12 @@
 <template>
-  <a-descriptions bordered :size="size">
-    <a-descriptions-item label="鍚嶇О">{{currentLevelDetails.productName}}</a-descriptions-item>
+  <a-descriptions bordered :size="size" :column="4">
+    <a-descriptions-item label="鍚嶇О" :span="2">{{currentLevelDetails.productName}}</a-descriptions-item>
     <a-descriptions-item label="鍨嬪彿">{{currentLevelDetails.productModel}}</a-descriptions-item>
     <a-descriptions-item label="浠g爜	">{{currentLevelDetails.productNo}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createName}}</a-descriptions-item>
-    <a-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{currentLevelDetails.createTime}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateName}}</a-descriptions-item>
-    <a-descriptions-item label="淇敼鏃堕棿" :span="2">{{currentLevelDetails.updateTime}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓浜�">{{currentLevelDetails.createBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="鍒涘缓鏃堕棿">{{currentLevelDetails.createTime}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼浜�">{{currentLevelDetails.updateBy_dictText}}</a-descriptions-item>
+    <a-descriptions-item label="淇敼鏃堕棿">{{currentLevelDetails.updateTime}}</a-descriptions-item>
   </a-descriptions>
 </template>
 
diff --git a/src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue b/src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue
index 30e0928..4f9ae99 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProductStructureMain.vue
@@ -1,12 +1,12 @@
 <template>
   <div style="height: 100%;max-height: 748px">
     <!--浜у搧缁撴瀯鏍戝彸渚ч《閮ㄥ尯鍩�-->
-    <div style="height: 45%;overflow: hidden">
+    <div style="height: 55%;overflow: hidden">
       <ProductStructureMainTop :size="tabContainerSize"/>
     </div>
 
     <!--浜у搧缁撴瀯鏍戝彸渚у簳閮ㄥ尯鍩�-->
-    <div style="height: 55%;overflow: hidden">
+    <div style="height: 45%;overflow: hidden">
       <ProductStructureMainBottom :size="tabContainerSize"/>
     </div>
   </div>
diff --git a/src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue b/src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
index c00a390..ddaa77d 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProductStructureMainBottom.vue
@@ -1,6 +1,7 @@
 <template>
-  <div v-if="currentLevelInfo.type!==4">
-    <a-tabs v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0" @change="handleTabChange">
+  <div v-if="+currentLevelInfo.type!==4" style="height: 100%">
+    <a-tabs style="height: 100%" v-model="activeTabKey" v-if="Object.keys(currentLevelInfo).length>0"
+            @change="handleTabChange">
       <a-tab-pane :key="1" tab="灞炴�т俊鎭�" v-if="+currentLevelInfo.type===1">
         <ProductInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
       </a-tab-pane>
@@ -21,8 +22,10 @@
         <ProcessStepInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
       </a-tab-pane>
 
-      <a-tab-pane :key="2" tab="鍒�鍏蜂俊鎭�" v-if="+currentLevelInfo.type===5||+currentLevelInfo.type===6">
-        <CutterInfo :currentLevelDetails="currentLevelInfo.entity" :size="containerSize"/>
+      <!--绯荤粺鍙傛暟閰嶇疆涓嫢鍙傛暟涓�1鏃舵墠灞曠ず瀵瑰簲灞傜骇鐨勫垁鍏峰垪琛�-->
+      <a-tab-pane :key="2" tab="鍒�鍏峰垪琛�"
+                  v-if="+currentLevelInfo.type===5&&isProcessHasCutterList||+currentLevelInfo.type===6&&isProcessStepHasCutterList">
+        <CutterTableList ref="cutterTableListRef" :currentLevelInfo="currentLevelInfo" :size="containerSize"/>
       </a-tab-pane>
 
       <template v-if="currentLevelInfo.hasOwnProperty('attributionType')">
@@ -57,19 +60,19 @@
 import ComponentInfo from './Component/ComponentInfo'
 import PartInfo from './Part/PartInfo'
 import ProcessInfo from './Process/ProcessInfo'
+import ProcessStepInfo from './ProcessStep/ProcessStepInfo'
+import CutterTableList from './Cutter/CutterTableList'
 import DocumentInfo from '../../../common/DocumentInfo'
 import DocumentVersionTableList from '../../../common/DocumentVersionTableList'
 import UseDocumentEquipmentTableList from './Document/UseNcDocumentEquipmentTableList'
-import ProcessStepInfo from './ProcessStep/ProcessStepInfo'
 import FilePreview from '../../../common/FilePreview'
 import TableContextMenu from '../../../common/TableContextMenu'
-import CutterInfo from '@views/dnc/base/modules/ProductStructure/Cutter/CutterInfo.vue'
-import dncApi from '@/api/dnc'
+import { getAction } from '@/api/manage'
 
 export default {
   name: 'ProductStructureMainBottom',
   components: {
-    CutterInfo,
+    CutterTableList,
     TableContextMenu,
     FilePreview,
     ProcessStepInfo,
@@ -85,6 +88,8 @@
     return {
       activeTabKey: 1,
       containerSize: 'small',
+      isProcessHasCutterList: false,
+      isProcessStepHasCutterList: false,
       currentLevelInfo: {},
       currentRightClickedTableRowInfo: {},
       hasLoadedDataTabKeyArray: []
@@ -94,30 +99,47 @@
     this.$bus.$on('sendCurrentClickedDocumentInfo', this.receiveCurrentLevelInfo)
     this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentLevelInfo)
     this.$bus.$on('reloadMainBottomTableData', this.reloadMainBottomTableData)
+    this.getCutterListDisplayPermission('dnc_cutter_process', 'isProcessHasCutterList')
+    this.getCutterListDisplayPermission('dnc_cutter_step', 'isProcessStepHasCutterList')
   },
   methods: {
+    /**
+     * 鑾峰彇鍒�鍏峰垪琛ㄥ湪宸ュ簭鍜屽伐姝ュ眰绾х殑灞曠ず鏉冮檺
+     * @param settingKey 鍚勫眰绾у睍绀烘潈闄恔ey
+     * @param dataProperty 缁勪欢data涓殑灞炴�у�肩敤鏉ユ帶鍒舵槸鍚﹀睍绀�
+     */
+    getCutterListDisplayPermission(settingKey, dataProperty) {
+      getAction(`/system/sysParams/query/by/settingKey?settingKey=${settingKey}`).then(res => {
+        if (res.success) {
+          this[dataProperty] = res.result.settingValue === '1'
+        }
+      })
+    },
+
     /**
      * 鎺ユ敹鏍戠粍浠朵互鍙婅〃鏍间紶鏉ョ殑褰撳墠閫変腑鎴栫偣鍑荤殑椤逛俊鎭�
      * @param levelInfo 褰撳墠灞傜骇淇℃伅
      */
     receiveCurrentLevelInfo(levelInfo) {
-      const { id, type } = levelInfo
-      dncApi.getProductStructureTreeNodeEntityApi({ id, type })
-        .then(res => {
-          if (res.success) {
-            console.log('res-------------', res)
-            this.currentLevelInfo = Object.assign(levelInfo, { entity: res.result[0] })
-          }
-        })
+      this.currentLevelInfo = levelInfo
       this.activeTabKey = 1
       this.hasLoadedDataTabKeyArray = []
     },
 
+    /**
+     * tab鏍忓垏鎹㈡椂瑙﹀彂
+     * @param activeTabKey 褰撳墠婵�娲荤殑tabKey
+     */
     handleTabChange(activeTabKey) {
       if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
         switch (activeTabKey) {
           case 2:
-            this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
+            if (this.currentLevelInfo.hasOwnProperty('attributionType')) {
+              console.log('ref', this.$refs.filePreviewRef)
+              this.$nextTick(() => this.$refs.filePreviewRef.getFilePreviewByApi())
+            } else {
+              this.$nextTick(() => this.$refs.cutterTableListRef.setQueryParamAndLoadData(1))
+            }
             break
           case 3:
             this.$nextTick(() => this.$refs.documentVersionTableRef.loadData())
@@ -172,6 +194,6 @@
 }
 
 /deep/ .ant-tabs-tabpane {
-  overflow: auto;
+  overflow: hidden auto;
 }
 </style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue b/src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
index 4dcd066..e67db7c 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProductStructureMainTop.vue
@@ -1,10 +1,18 @@
 <template>
-  <div v-if="currentTreeNodeInfo.type!==4">
+  <div v-if="+currentTreeNodeInfo.type!==4">
     <a-tabs v-model="activeTabKey" @contextmenu.native="e=>e.preventDefault()" @change="handleTabChange"
             v-if="Object.keys(currentTreeNodeInfo).length!==0">
-      <a-tab-pane :key="1" tab="NC鏂囨。" v-if="currentTreeNodeInfo.type===5||currentTreeNodeInfo.type===6">
-        <NcDocumentTableList ref="ncDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
-                             @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
+      <a-tab-pane :key="1" tab="NC绠$悊" v-if="+currentTreeNodeInfo.type===5||+currentTreeNodeInfo.type===6">
+        <div style="display: flex;">
+          <!--绯荤粺鍙傛暟閰嶇疆涓嫢鍙傛暟涓�1鏃舵墠灞曠ず瀵瑰簲灞傜骇鐨勮澶囩被鍒楄〃-->
+          <DeviceCustomTypeTableList
+            v-if="+currentTreeNodeInfo.type===5&&isProcessHasDeviceTypeList||+currentTreeNodeInfo.type===6&&isProcessStepHasDeviceTypeList"
+            ref="deviceCustomTypeTableList" :currentTreeNodeInfo="currentTreeNodeInfo"
+            @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
+
+          <NcDocumentTableList ref="ncDocumentTableListRef" :currentTreeNodeInfo="currentTreeNodeInfo"
+                               @handleTableContextMenuOpen="handleTableContextMenuOpen" :size="tableContainerSize"/>
+        </div>
       </a-tab-pane>
 
       <a-tab-pane :key="2" tab="鍏朵粬鏂囨。">
@@ -21,398 +29,426 @@
 </template>
 
 <script>
-  import dncApi from '@/api/dnc'
-  import NcDocumentTableList from './Document/NcDocumentTableList'
-  import OtherDocumentTableList from './Document/OtherDocumentTableList'
-  import TableContextMenu from '../../../common/TableContextMenu'
-  import DocumentBatchDeleteModal from '../../../common/DocumentBatchDeleteModal'
+import dncApi from '@/api/dnc'
+import NcDocumentTableList from './Document/NcDocumentTableList'
+import OtherDocumentTableList from './Document/OtherDocumentTableList'
+import TableContextMenu from '../../../common/TableContextMenu'
+import DocumentBatchDeleteModal from '../../../common/DocumentBatchDeleteModal'
+import DeviceCustomTypeTableList
+  from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeTableList.vue'
+import { getAction } from '@api/manage'
 
-  export default {
-    name: 'ProductStructureMainTop',
-    components: { DocumentBatchDeleteModal, TableContextMenu, OtherDocumentTableList, NcDocumentTableList },
-    data() {
-      return {
-        activeTabKey: 2,
-        tableContainerSize: 'small',
-        currentRightClickedTableRowInfo: {},
-        currentTreeNodeInfo: {},
-        hasLoadedDataTabKeyArray: []
+export default {
+  name: 'ProductStructureMainTop',
+  components: {
+    DeviceCustomTypeTableList,
+    DocumentBatchDeleteModal,
+    TableContextMenu,
+    OtherDocumentTableList,
+    NcDocumentTableList
+  },
+  data() {
+    return {
+      activeTabKey: 2,
+      tableContainerSize: 'small',
+      isProcessHasDeviceTypeList: false,
+      isProcessStepHasDeviceTypeList: false,
+      currentRightClickedTableRowInfo: {},
+      currentTreeNodeInfo: {},
+      hasLoadedDataTabKeyArray: []
+    }
+  },
+  created() {
+    this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
+    this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
+    this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+    this.getDeviceTypeListDisplayPermission('dnc_device_type_process', 'isProcessHasDeviceTypeList')
+    this.getDeviceTypeListDisplayPermission('dnc_device_type_step', 'isProcessStepHasDeviceTypeList')
+  },
+  methods: {
+    /**
+     * 鑾峰彇璁惧绫诲瀷鍒楄〃鍦ㄥ伐搴忓拰宸ユ灞傜骇鐨勫睍绀烘潈闄�
+     * @param settingKey 鍚勫眰绾у睍绀烘潈闄恔ey
+     * @param dataProperty 缁勪欢data涓殑灞炴�у�肩敤鏉ユ帶鍒舵槸鍚﹀睍绀�
+     */
+    getDeviceTypeListDisplayPermission(settingKey, dataProperty) {
+      getAction(`/system/sysParams/query/by/settingKey?settingKey=${settingKey}`).then(res => {
+        if (res.success) {
+          this[dataProperty] = res.result.settingValue === '1'
+        }
+      })
+    },
+
+    /**
+     * 鎺ユ敹鏍戠粍浠朵紶鏉ョ殑褰撳墠閫変腑鐨勬爲鑺傜偣淇℃伅
+     * @param treeNodeInfo 鏍戣妭鐐逛俊鎭�
+     */
+    receiveCurrentTreeNodeInfo(treeNodeInfo) {
+      console.log('treeNodeInfo', treeNodeInfo)
+      // 浠庢爲缁勪欢鎺ュ彈鏍戣妭鐐逛俊鎭悗浠庣埗缁勪欢娴佸叆瀛愮粍浠�
+      this.currentTreeNodeInfo = treeNodeInfo
+      // 娓呯┖涓婁竴鑺傜偣宸茬粡鍔犺浇杩囧緱鏂囨。鍒楄〃tabKey
+      this.hasLoadedDataTabKeyArray = []
+      if (+treeNodeInfo.type === 5 || +treeNodeInfo.type === 6) {
+        this.activeTabKey = 1
+        this.$nextTick(() => {
+          if (this.$refs.deviceCustomTypeTableList) this.$refs.deviceCustomTypeTableList.setQueryParamAndLoadData()
+          else if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
+        })
+      } else {
+        this.activeTabKey = 2
+        this.$nextTick(() => {
+          if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
+        })
+      }
+      this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
+    },
+
+    /**
+     * 鎺у埗鍙抽敭鑿滃崟寮�鍚�
+     * @param record 褰撳墠琛ㄦ牸琛屼俊鎭�
+     */
+    handleTableContextMenuOpen(record) {
+      this.currentRightClickedTableRowInfo = Object.assign({}, record)
+      console.log('currentRightClickedTableRowInfo', this.currentRightClickedTableRowInfo)
+      this.$refs.tableContextMenuRef.currentMenuLevel = record.param
+      this.$refs.tableContextMenuRef.menuStyle.top = event.clientY + 'px'
+      this.$refs.tableContextMenuRef.menuStyle.left = event.clientX + 'px'
+      this.$refs.tableContextMenuRef.menuVisible = true
+      document.body.addEventListener('click', this.handleMenuClose)
+    },
+
+    /**
+     * tab鏍忓垏鎹㈡椂瑙﹀彂
+     * @param activeTabKey 鍒囨崲鍚庣殑tabKey
+     */
+    handleTabChange(activeTabKey) {
+      if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
+        this.$nextTick(() => {
+          if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
+        })
+        // 闃绘鎺ュ彛鍦ㄥ悓涓�鏂囨。涓�娆$偣鍑诲唴澶氭瑙﹀彂
+        this.hasLoadedDataTabKeyArray.push(activeTabKey)
       }
     },
-    created() {
-      this.$bus.$on('sendCurrentTreeNodeInfo', this.receiveCurrentTreeNodeInfo)
-      this.$bus.$on('reloadDocumentListData', this.reloadDocumentListData)
-      this.$bus.$on('tableMenuItemMethodTrigger', this.triggerCorrespondingMethod)
+    /**
+     * 鏂囨。浠ュ強NC绋嬪簭瀵煎叆/鍑哄簱/鍏ュ簱鎴愬姛鍚庤Е鍙戦噸鏂板姞杞芥枃妗e垪琛�
+     * @param docClassCode 鏂囨。绫诲埆
+     * @param attributionId 鑺傜偣Id
+     */
+    reloadDocumentListData({ docClassCode, attributionId }) {
+      // 濡傛灉涓婁紶鐨勬枃妗d笉鏄墍灞炰簬褰撳墠鎵�灞曠ず鑺傜偣鐨勬枃妗e垯涓嶉噸鏂拌幏鍙栨枃妗e垪琛�
+      if (this.currentTreeNodeInfo.id !== attributionId) return
+      if (docClassCode === 'NC') {
+        if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
+      } else {
+        if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
+      }
     },
-    methods: {
-      /**
-       * 鎺у埗鍙抽敭鑿滃崟寮�鍚�
-       * @param record 褰撳墠琛ㄦ牸琛屼俊鎭�
-       */
-      handleTableContextMenuOpen(record) {
-        this.currentRightClickedTableRowInfo = Object.assign({}, record)
-        console.log('currentRightClickedTableRowInfo', this.currentRightClickedTableRowInfo)
-        this.$refs.tableContextMenuRef.currentMenuLevel = record.param
-        this.$refs.tableContextMenuRef.menuStyle.top = event.clientY + 'px'
-        this.$refs.tableContextMenuRef.menuStyle.left = event.clientX + 'px'
-        this.$refs.tableContextMenuRef.menuVisible = true
-        document.body.addEventListener('click', this.handleMenuClose)
-      },
 
-      /**
-       * 鎺ユ敹鏍戠粍浠朵紶鏉ョ殑褰撳墠閫変腑鐨勬爲鑺傜偣淇℃伅
-       * @param treeNodeInfo 鏍戣妭鐐逛俊鎭�
-       */
-      receiveCurrentTreeNodeInfo(treeNodeInfo) {
-        // 浠庢爲缁勪欢鎺ュ彈鏍戣妭鐐逛俊鎭悗浠庣埗缁勪欢娴佸叆瀛愮粍浠�
-        this.currentTreeNodeInfo = treeNodeInfo
-        // 娓呯┖涓婁竴鑺傜偣宸茬粡鍔犺浇杩囧緱鏂囨。鍒楄〃tabKey
-        this.hasLoadedDataTabKeyArray = []
-        if (treeNodeInfo.type === 5 || treeNodeInfo.type === 6) {
-          this.activeTabKey = 1
-          this.$nextTick(() => {
-            if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
-          })
-        } else {
-          this.activeTabKey = 2
-          this.$nextTick(() => {
-            if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
-          })
-        }
-        this.hasLoadedDataTabKeyArray.push(this.activeTabKey)
-      },
-
-      /**
-       * tab鏍忓垏鎹㈡椂瑙﹀彂
-       * @param activeTabKey 鍒囨崲鍚庣殑tabKey
-       */
-      handleTabChange(activeTabKey) {
-        if (!this.hasLoadedDataTabKeyArray.includes(activeTabKey)) {
-          this.$nextTick(() => {
-            if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
-          })
-          // 闃绘鎺ュ彛鍦ㄥ悓涓�鏂囨。涓�娆$偣鍑诲唴澶氭瑙﹀彂
-          this.hasLoadedDataTabKeyArray.push(activeTabKey)
-        }
-      },
-      /**
-       * 鏂囨。浠ュ強NC绋嬪簭瀵煎叆/鍑哄簱/鍏ュ簱鎴愬姛鍚庤Е鍙戦噸鏂板姞杞芥枃妗e垪琛�
-       * @param docClassCode 鏂囨。绫诲埆
-       * @param attributionId 鑺傜偣Id
-       */
-      reloadDocumentListData({ docClassCode, attributionId }) {
-        // 濡傛灉涓婁紶鐨勬枃妗d笉鏄墍灞炰簬褰撳墠鎵�灞曠ず鑺傜偣鐨勬枃妗e垯涓嶉噸鏂拌幏鍙栨枃妗e垪琛�
-        if (this.currentTreeNodeInfo.id !== attributionId) return
-        if (docClassCode === 'NC') {
-          if (this.$refs.ncDocumentTableListRef) this.$refs.ncDocumentTableListRef.loadData(1)
-        } else {
-          if (this.$refs.otherDocumentTableListRef) this.$refs.otherDocumentTableListRef.loadData(1)
-        }
-      },
-
-      // 涓嬭浇褰撳墠鍙抽敭閫変腑鏂囨。
-      handleDownload() {
-        const that = this
-        const { docId, docName } = this.currentRightClickedTableRowInfo
-        dncApi.downloadDocumentApi({ docId, docName })
-          .then(res => {
-            if (res && !res.success) {
-              that.$notification.error({
-                message: '娑堟伅',
-                description: res.message
-              })
-            }
-          })
-          .catch(err => {
+    // 涓嬭浇褰撳墠鍙抽敭閫変腑鏂囨。
+    handleDownload() {
+      const that = this
+      const { docId, docName } = this.currentRightClickedTableRowInfo
+      dncApi.downloadDocumentApi({ docId, docName })
+        .then(res => {
+          if (res && !res.success) {
             that.$notification.error({
               message: '娑堟伅',
-              description: err.message
+              description: res.message
             })
+          }
+        })
+        .catch(err => {
+          that.$notification.error({
+            message: '娑堟伅',
+            description: err.message
           })
-      },
-
-      // 鍒犻櫎褰撳墠鍙抽敭閫変腑鏂囨。
-      handleDelete() {
-        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
-        const that = this
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `鍒犻櫎鍚庝笉鍙彇娑堬紝纭鍒犻櫎鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.deleteDocumentApi(docId)
-              .then((res) => {
-                if (res.success) {
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                  that.reloadDocumentListData({ docClassCode: param, attributionId })
-                } else {
-                  that.$notification.warning({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel: () => {
-            that.$destroyAll()
-          }
         })
-      },
+    },
 
-      /**
-       * 鐐瑰嚮鎵归噺鍒犻櫎鍚庡嚭鐜板脊绐�
-       * @param modalTitle 寮圭獥鏍囬
-       */
-      handleBatchRemove(modalTitle) {
-        if (!this.$refs.documentBatchDeleteModalRef) return
-        this.$refs.documentBatchDeleteModalRef.title = modalTitle
-        this.$refs.documentBatchDeleteModalRef.visible = true
-      },
+    // 鍒犻櫎褰撳墠鍙抽敭閫変腑鏂囨。
+    handleDelete() {
+      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
+      const that = this
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `鍒犻櫎鍚庝笉鍙彇娑堬紝纭鍒犻櫎鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.deleteDocumentApi(docId)
+            .then((res) => {
+              if (res.success) {
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+                that.reloadDocumentListData({ docClassCode: param, attributionId })
+              } else {
+                that.$notification.warning({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              }
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel: () => {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      /**
-       * 鍑哄簱褰撳墠鍙抽敭閫変腑鏂囨。
-       * @param menuLabel
-       */
-      handlePull(menuLabel) {
-        const that = this
-        const { docId, docName, param, attributionId } = this.currentRightClickedTableRowInfo
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `纭${menuLabel}鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.documentOutboundApi({ docId, docName })
-              .then(res => {
-                console.log('res------------------', res)
-                if (res.success) {
-                  that.reloadDocumentListData({ docClassCode: param, attributionId })
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: `${menuLabel}鎴愬姛`
-                  })
-                } else {
-                  that.$notification.error({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .catch(err => {
+    /**
+     * 鐐瑰嚮鎵归噺鍒犻櫎鍚庡嚭鐜板脊绐�
+     * @param modalTitle 寮圭獥鏍囬
+     */
+    handleBatchRemove(modalTitle) {
+      if (!this.$refs.documentBatchDeleteModalRef) return
+      this.$refs.documentBatchDeleteModalRef.title = modalTitle
+      this.$refs.documentBatchDeleteModalRef.visible = true
+    },
+
+    /**
+     * 鍑哄簱褰撳墠鍙抽敭閫変腑鏂囨。
+     * @param menuLabel
+     */
+    handlePull(menuLabel) {
+      const that = this
+      const { docId, docName, param, attributionId } = this.currentRightClickedTableRowInfo
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `纭${menuLabel}鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.documentOutboundApi({ docId, docName })
+            .then(res => {
+              console.log('res------------------', res)
+              if (res.success) {
+                that.reloadDocumentListData({ docClassCode: param, attributionId })
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: `${menuLabel}鎴愬姛`
+                })
+              } else {
                 that.$notification.error({
                   message: '娑堟伅',
-                  description: err.message
+                  description: res.message
                 })
+              }
+            })
+            .catch(err => {
+              that.$notification.error({
+                message: '娑堟伅',
+                description: err.message
               })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel: () => {
-            that.$destroyAll()
-          }
-        })
-      },
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel: () => {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      /**
-       * 鍙栨秷鍑哄簱褰撳墠鍙抽敭閫変腑鏂囨。
-       * @param menuLabel
-       */
-      handleCancelPull(menuLabel) {
-        const that = this
-        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `纭${menuLabel}鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.documentCancelOutboundApi(docId)
-              .then(res => {
-                if (res.success) {
-                  this.reloadDocumentListData({ docClassCode: param, attributionId })
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                } else {
-                  that.$notification.error({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .catch(err => {
+    /**
+     * 鍙栨秷鍑哄簱褰撳墠鍙抽敭閫変腑鏂囨。
+     * @param menuLabel
+     */
+    handleCancelPull(menuLabel) {
+      const that = this
+      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `纭${menuLabel}鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.documentCancelOutboundApi(docId)
+            .then(res => {
+              if (res.success) {
+                this.reloadDocumentListData({ docClassCode: param, attributionId })
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              } else {
                 that.$notification.error({
                   message: '娑堟伅',
-                  description: err.message
+                  description: res.message
                 })
+              }
+            })
+            .catch(err => {
+              that.$notification.error({
+                message: '娑堟伅',
+                description: err.message
               })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel() {
-            that.$destroyAll()
-          }
-        })
-      },
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel() {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      /**
-       * 鍙戝竷褰撳墠鍙抽敭閫変腑鏂囨。
-       * @param menuLabel
-       */
-      handlePublish(menuLabel) {
-        const that = this
-        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `纭${menuLabel}鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.documentPublishApi(docId)
-              .then(res => {
-                if (res.success) {
-                  this.reloadDocumentListData({ docClassCode: param, attributionId })
-                  this.$bus.$emit('reloadMainBottomTableData', 'documentVersion')
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                } else {
-                  that.$notification.error({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .catch(err => {
+    /**
+     * 鍙戝竷褰撳墠鍙抽敭閫変腑鏂囨。
+     * @param menuLabel
+     */
+    handlePublish(menuLabel) {
+      const that = this
+      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `纭${menuLabel}鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.documentPublishApi(docId)
+            .then(res => {
+              if (res.success) {
+                this.reloadDocumentListData({ docClassCode: param, attributionId })
+                this.$bus.$emit('reloadMainBottomTableData', 'documentVersion')
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              } else {
                 that.$notification.error({
                   message: '娑堟伅',
-                  description: err.message
+                  description: res.message
                 })
+              }
+            })
+            .catch(err => {
+              that.$notification.error({
+                message: '娑堟伅',
+                description: err.message
               })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel() {
-            that.$destroyAll()
-          }
-        })
-      },
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel() {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      /**
-       * 閲嶆柊鍙戝竷褰撳墠鍙抽敭閫変腑鏂囨。骞堕噸鏂板彂甯冮��鍥炰笂涓�鏂囨。鐗堟湰
-       * @param menuLabel
-       */
-      handleRepublish(menuLabel) {
-        const that = this
-        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `纭${menuLabel}鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.documentRepublishApi(docId)
-              .then(res => {
-                if (res.success) {
-                  this.reloadDocumentListData({ docClassCode: param, attributionId })
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                } else {
-                  that.$notification.error({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .catch(err => {
+    /**
+     * 閲嶆柊鍙戝竷褰撳墠鍙抽敭閫変腑鏂囨。骞堕噸鏂板彂甯冮��鍥炰笂涓�鏂囨。鐗堟湰
+     * @param menuLabel
+     */
+    handleRepublish(menuLabel) {
+      const that = this
+      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `纭${menuLabel}鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.documentRepublishApi(docId)
+            .then(res => {
+              if (res.success) {
+                this.reloadDocumentListData({ docClassCode: param, attributionId })
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              } else {
                 that.$notification.error({
                   message: '娑堟伅',
-                  description: err.message
+                  description: res.message
                 })
+              }
+            })
+            .catch(err => {
+              that.$notification.error({
+                message: '娑堟伅',
+                description: err.message
               })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel() {
-            that.$destroyAll()
-          }
-        })
-      },
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel() {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      /**
-       * 閲嶅綊妗e綋鍓嶅彸閿�変腑鏂囨。涓斿悗缁棤娉曠户缁彂甯冩垨褰掓。
-       * @param menuLabel
-       */
-      handlePigeonhole(menuLabel) {
-        const that = this
-        const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
-        that.$confirm({
-          title: '鎻愮ず',
-          content: `${menuLabel}鍚庝笉鍙彇娑堬紝纭${menuLabel}鍚楋紵`,
-          okText: '纭',
-          cancelText: '鍙栨秷',
-          onOk: () => {
-            dncApi.documentPigeonholeApi(docId)
-              .then(res => {
-                if (res.success) {
-                  this.reloadDocumentListData({ docClassCode: param, attributionId })
-                  that.$notification.success({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                } else {
-                  that.$notification.error({
-                    message: '娑堟伅',
-                    description: res.message
-                  })
-                }
-              })
-              .catch(err => {
+    /**
+     * 閲嶅綊妗e綋鍓嶅彸閿�変腑鏂囨。涓斿悗缁棤娉曠户缁彂甯冩垨褰掓。
+     * @param menuLabel
+     */
+    handlePigeonhole(menuLabel) {
+      const that = this
+      const { docId, param, attributionId } = this.currentRightClickedTableRowInfo
+      that.$confirm({
+        title: '鎻愮ず',
+        content: `${menuLabel}鍚庝笉鍙彇娑堬紝纭${menuLabel}鍚楋紵`,
+        okText: '纭',
+        cancelText: '鍙栨秷',
+        onOk: () => {
+          dncApi.documentPigeonholeApi(docId)
+            .then(res => {
+              if (res.success) {
+                this.reloadDocumentListData({ docClassCode: param, attributionId })
+                that.$notification.success({
+                  message: '娑堟伅',
+                  description: res.message
+                })
+              } else {
                 that.$notification.error({
                   message: '娑堟伅',
-                  description: err.message
+                  description: res.message
                 })
+              }
+            })
+            .catch(err => {
+              that.$notification.error({
+                message: '娑堟伅',
+                description: err.message
               })
-              .finally(() => {
-                that.$destroyAll()
-              })
-          },
-          onCancel() {
-            that.$destroyAll()
-          }
-        })
-      },
+            })
+            .finally(() => {
+              that.$destroyAll()
+            })
+        },
+        onCancel() {
+          that.$destroyAll()
+        }
+      })
+    },
 
-      // 鎺у埗鍙抽敭鑿滃崟鍏抽棴
-      handleMenuClose() {
-        this.$refs.tableContextMenuRef.menuVisible = false
-        document.body.removeEventListener('click', this.handleMenuClose)
-      },
+    // 鎺у埗鍙抽敭鑿滃崟鍏抽棴
+    handleMenuClose() {
+      this.$refs.tableContextMenuRef.menuVisible = false
+      document.body.removeEventListener('click', this.handleMenuClose)
+    },
 
-      triggerCorrespondingMethod({ methodName, modalTitle }) {
-        if (this[methodName]) this[methodName](modalTitle)
-      }
+    triggerCorrespondingMethod({ methodName, modalTitle }) {
+      if (this[methodName]) this[methodName](modalTitle)
     }
   }
+}
 </script>
 
 <style scoped>
-  /deep/ .ant-table-tbody .ant-table-row {
-    cursor: pointer;
-  }
+/deep/ .ant-table-tbody .ant-table-row {
+  cursor: pointer;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue b/src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue
index 97b73a0..37a06d1 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProductStructureTree.vue
@@ -2,24 +2,26 @@
   <a-card class="tree_con" :loading="cardLoading" :bordered="false" @contextmenu.native="e=>e.preventDefault()">
     <a-spin :spinning="loading">
       <div style="display: flex;flex-direction: column;height: 100%">
-        <div style="display: flex">
+        <div style="display: flex;justify-content: space-between">
           <a-input placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�" allowClear v-model="searchInput"
                    @change="handleSearchInputChange"/>
-          <a-dropdown :trigger="['click']" placement="bottomCenter" style="margin: 0 8px">
-            <a-menu slot="overlay">
-              <a-menu-item key="1" @click="expandedKeys = allTreeKeys">灞曞紑鎵�鏈�</a-menu-item>
-              <a-menu-item key="2" @click="expandedKeys = ['-1']">鍚堝苟鎵�鏈�</a-menu-item>
-              <a-menu-item key="3" @click="getTreeDataByApi">鍒锋柊</a-menu-item>
-            </a-menu>
-            <a-button>
-              <a-icon type="bars"/>
-            </a-button>
-          </a-dropdown>
-          <a-button type="primary" v-has="'product_add'"
+          <a-tooltip title="鍒锋柊">
+            <a-button icon="reload" @click="getTreeDataByApi" style="width: 18%;margin-left: 8px"></a-button>
+          </a-tooltip>
+          <a-button type="primary" v-has="'product_add'" icon="plus" style="margin-left: 8px"
                     @click="$refs.productModalFormRef.triggerCorrespondingMethod({modalTitle:'娣诲姞浜у搧',methodName:'handleProductAdd'})">
-            <a-icon type="plus"></a-icon>
-            浜у搧
+            娣诲姞浜у搧
           </a-button>
+          <!--          <a-dropdown :trigger="['click']" placement="bottomCenter" style="margin: 0 8px">-->
+          <!--            <a-menu slot="overlay">-->
+          <!--              <a-menu-item key="1" @click="expandedKeys = allTreeKeys">灞曞紑鎵�鏈�</a-menu-item>-->
+          <!--              <a-menu-item key="2" @click="expandedKeys = ['-1']">鍚堝苟鎵�鏈�</a-menu-item>-->
+          <!--              <a-menu-item key="3" @click="getTreeDataByApi">鍒锋柊</a-menu-item>-->
+          <!--            </a-menu>-->
+          <!--            <a-button>-->
+          <!--              <a-icon type="bars"/>-->
+          <!--            </a-button>-->
+          <!--          </a-dropdown>-->
         </div>
 
         <!--浜у搧缁撴瀯鏍�-->
@@ -27,9 +29,9 @@
           <a-tree blockNode show-icon :expandedKeys.sync="expandedKeys"
                   :selectedKeys="selectedKeys" :treeData="treeDataSource" :autoExpandParent="autoExpandParent"
                   @select="handleTreeSelect" @expand="handleTreeExpand" @rightClick="handleTreeRightClick">
-            <template slot="title" slot-scope="{ label, parentId, entity, key:treeKey,type}">
+            <template slot="title" slot-scope="{ label, parentId, key:treeKey,type}">
               <ProductStructureTreeContextMenu ref="contextMenuRef"
-                                               :treeParams="{label,treeKey,searchValue,type,entity}"/>
+                                               :treeParams="{label,treeKey,searchValue,type}"/>
             </template>
 
             <a-icon slot="switcherIcon" type="down"/>
@@ -73,10 +75,12 @@
 import ProcessModal from './Process/ProcessModal'
 import ProcessStepModal from './ProcessStep/ProcessStepModal'
 import AssignPermissionModal from './Permission/AssignPermissionModal'
+import DeviceCustomTypeModal from '@views/dnc/base/modules/ProductStructure/DeviceCustomType/DeviceCustomTypeModal.vue'
 
 export default {
   name: 'ProductStructureTree',
   components: {
+    DeviceCustomTypeModal,
     AssignPermissionModal,
     ProcessStepModal,
     ProcessModal,
@@ -100,7 +104,6 @@
       autoExpandParent: true,
       checkStrictly: true,
       allTreeKeys: [],
-      currentSelected: {},
       rightClickSelected: {},
       url: {
         delete: '/nc/product/delete'
@@ -115,10 +118,10 @@
     getTreeDataByApi() {
       this.loading = true
       this.cardLoading = true
+      this.treeDataSource = []
       dncApi.getProductStructureTreeApi()
         .then(res => {
           if (res.success) {
-            console.log('res=================', res)
             this.dataList = []
             this.allTreeKeys = []
             this.treeDataSource = res.result
@@ -140,22 +143,62 @@
      * @param {node} node 鑺傜偣瀵硅薄
      */
     handleTreeSelect(selectedKeys, { node }) {
+      const that = this
       let record = node.dataRef
-      this.currentSelected = Object.assign({}, record)
-      // 鍚戝彸渚х埗绾х粍浠跺彂閫佸綋鍓嶉�変腑鏍戣妭鐐逛俊鎭�
-      this.$bus.$emit('sendCurrentTreeNodeInfo', this.currentSelected)
+      const { id, type } = record
+      dncApi.getProductStructureTreeNodeEntityApi({ id, type })
+        .then(res => {
+          if (res.success) {
+            let currentSelectedNodeInfo
+            if (res.result.length > 0) {
+              currentSelectedNodeInfo = Object.assign({}, record, { entity: res.result[0] })
+            } else {
+              currentSelectedNodeInfo = {}
+              that.$notification.warning({
+                message: '娑堟伅',
+                description: '鏆傛棤璇ヨ妭鐐硅缁嗕俊鎭�'
+              })
+            }
+            // 鍚戝彸渚х埗绾х粍浠跺彂閫佸綋鍓嶉�変腑鏍戣妭鐐逛俊鎭�
+            this.$bus.$emit('sendCurrentTreeNodeInfo', currentSelectedNodeInfo)
+          } else {
+            that.$notification.error({
+              message: '娑堟伅',
+              description: res.message
+            })
+          }
+        })
       if (selectedKeys.length === 0) return
       this.selectedKeys = selectedKeys
     },
 
     /**
      * 鏍戣妭鐐瑰彸閿崟鍑昏妭鐐规椂瑙﹀彂
-     * @param event 浜嬩欢瀵硅薄
      * @param node 鑺傜偣瀵硅薄
      */
-    handleTreeRightClick({ event, node }) {
+    handleTreeRightClick({ node }) {
+      const that = this
       const record = node.dataRef
-      this.rightClickSelected = Object.assign({}, record)
+      const { id, type } = record
+      dncApi.getProductStructureTreeNodeEntityApi({ id, type })
+        .then(res => {
+          if (res.success) {
+            if (res.result.length > 0) {
+              that.rightClickSelected = Object.assign({}, record, { entity: res.result[0] })
+            } else {
+              that.rightClickSelected = {}
+              that.$notification.warning({
+                message: '娑堟伅',
+                description: '鏆傛棤璇ヨ妭鐐硅缁嗕俊鎭�'
+              })
+            }
+          } else {
+            that.$notification.error({
+              message: '娑堟伅',
+              description: res.message
+            })
+          }
+        })
     },
 
     // 鏍戣妭鐐瑰彸閿崟鍑昏彍鍗曚腑鍒犻櫎鎸夐挳鏃惰Е鍙�
@@ -216,8 +259,18 @@
       this.autoExpandParent = false
     },
 
-    /* 杈撳叆鏌ヨ鍐呭鍙樺寲鏃惰Е鍙� */
+    // 杈撳叆鏌ヨ鍐呭鍙樺寲鏃惰Е鍙戯紙澧炲姞闃叉姈鏈哄埗锛�
     handleSearchInputChange() {
+      const that = this
+      let timer
+      if (timer) clearTimeout(timer)
+      timer = setTimeout(function() {
+        that.searchAndExpandTreeNode() // 鍔犲皬鎷彿璋冪敤鍑芥暟
+      }, 1000)
+    },
+
+    // 闃叉姈鍑芥暟涓Е鍙戞悳绱㈠苟灞曞紑鏍戣妭鐐�
+    searchAndExpandTreeNode() {
       let search = this.searchInput
       let expandedKeys
       let autoExpandParent
@@ -237,7 +290,6 @@
         expandedKeys = this.beforeSearchExpandedKeys
         autoExpandParent = false
       }
-
       Object.assign(this, {
         expandedKeys,
         searchValue: search,
@@ -292,7 +344,7 @@
      * @param treeNode
      */
     setTreeNodeIcon(treeNode) {
-      switch (treeNode.type) {
+      switch (+treeNode.type) {
         case 1:
           treeNode.slots = { icon: 'product' }
           break
diff --git a/src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue b/src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue
index fc878a6..338a3a0 100644
--- a/src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue
+++ b/src/views/dnc/base/modules/ProductStructure/ProductStructureTreeContextMenu.vue
@@ -1,14 +1,20 @@
 <template>
   <a-dropdown :trigger="['contextmenu']">
-    <span v-if="treeParams.label.indexOf(treeParams.searchValue) > -1">{{ treeParams.label.substr(0, treeParams.label.indexOf(treeParams.searchValue)) }}<span
-      class="replaceSearch">{{ treeParams.searchValue }}</span>{{ treeParams.label.substr(treeParams.label.indexOf(treeParams.searchValue) + treeParams.searchValue.length) }}</span>
+    <span v-if="treeParams.label.indexOf(treeParams.searchValue) > -1">{{
+        treeParams.label.substr(0, treeParams.label.indexOf(treeParams.searchValue))
+      }}<span
+        class="replaceSearch">{{
+          treeParams.searchValue
+        }}</span>{{
+        treeParams.label.substr(treeParams.label.indexOf(treeParams.searchValue) + treeParams.searchValue.length)
+      }}</span>
     <span v-else>{{ treeParams.label }}</span>
     <template #overlay>
       <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeParams.treeKey, menuKey)"
               @contextmenu="event=>event.preventDefault()">
         <a-menu-item v-for="item in defaultContextMenuList[getCurrentMenuLevel]" :key="item.code" v-has="item.code">
           <a-icon :type="item.icon"/>
-          {{item.label}}
+          {{ item.label }}
         </a-menu-item>
       </a-menu>
     </template>
@@ -16,141 +22,144 @@
 </template>
 
 <script>
-  export default {
-    name: 'ProductStructureTreeContextMenu',
-    components: {},
-    props: {
-      treeParams: {
-        type: Object
-      }
-    },
-    data() {
-      return {
-        defaultContextMenuList: {
-          //浜у搧
-          product: [
-            { label: '娣诲姞浜у搧', code: 'product_add', icon: 'plus', isCommonMethod: false },
-            { label: '娣诲姞閮ㄤ欢', code: 'product_add_child', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫浜у搧淇℃伅', code: 'product_edit', icon: 'edit', isCommonMethod: false },
-            // {  label: '瀵煎嚭鏂囨。', code: 'product_export', icon: 'export', isCommonMethod: true },
-            { label: '瀵煎叆鍏朵粬鏂囨。', code: 'product_import', icon: 'import', isCommonMethod: true },
-            { label: '鍒犻櫎', code: 'product_delete', icon: 'delete', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ],
-          //閮ㄤ欢
-          component: [
-            { label: '娣诲姞瀛愰儴浠�', code: 'component_add', icon: 'plus', isCommonMethod: false },
-            { label: '娣诲姞闆朵欢', code: 'component_add_child', icon: 'plus', isCommonMethod: false },
-            { label: '鍒涘缓宸ュ簭', code: 'component_add_relative', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫閮ㄤ欢淇℃伅', code: 'component_edit', icon: 'edit', isCommonMethod: false },
-            // {  label: '瀵煎嚭鏂囨。', code: 'component_export', icon: 'export', isCommonMethod: true },
-            { label: '瀵煎叆鍏朵粬鏂囨。', code: 'component_import', icon: 'import', isCommonMethod: true },
-            { label: '鍒犻櫎', code: 'component_delete', icon: 'delete', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ],
-          //闆朵欢
-          part: [
-            { label: '娣诲姞闆朵欢', code: 'parts_add', icon: 'plus', isCommonMethod: false },
-            { label: '鍒涘缓宸ヨ壓瑙勭▼鐗堟湰', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
-            // { label: '鍒涘缓宸ュ簭', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫闆朵欢淇℃伅', code: 'parts_edit', icon: 'edit', isCommonMethod: false },
-            // {  label: '瀵煎嚭鏂囨。', code: 'parts_export', icon: 'export', isCommonMethod: true },
-            { label: '瀵煎叆鍏朵粬鏂囨。', code: 'parts_import', icon: 'import', isCommonMethod: true },
-            { label: '鍒犻櫎', code: 'parts_delete', icon: 'delete', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ],
-          //宸ヨ壓瑙勭▼鐗堟湰
-          processSpecVersion: [
-            { label: '鍒涘缓宸ヨ壓瑙勭▼鐗堟湰', code: 'version_add', icon: 'plus', isCommonMethod: false },
-            { label: '鍒涘缓宸ュ簭', code: 'version_add_child', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫宸ヨ壓瑙勭▼鐗堟湰淇℃伅', code: 'version_edit', icon: 'edit', isCommonMethod: false },
-            { label: '鍒犻櫎', code: 'version_delete', icon: 'delete', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ],
-          //宸ュ簭
-          process: [
-            { label: '鍒涘缓宸ュ簭', code: 'process_add', icon: 'plus', isCommonMethod: false },
-            { label: '鍒涘缓宸ユ', code: 'process_add_child', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫宸ュ簭淇℃伅', code: 'process_edit', icon: 'edit', isCommonMethod: false },
-            { label: '鍒犻櫎', code: 'process_delete', icon: 'delete', isCommonMethod: true },
-            // {  label: '瀵煎嚭NC绋嬪簭', code: 'process_export', icon: 'export', isCommonMethod: true },
-            { label: '瀵煎叆NC绋嬪簭', code: 'process_import', icon: 'import', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ],
-          //宸ユ
-          processStep: [
-            { label: '鍒涘缓宸ユ', code: 'processStep_add', icon: 'plus', isCommonMethod: false },
-            { label: '缂栬緫宸ユ淇℃伅', code: 'processStep_edit', icon: 'edit', isCommonMethod: false },
-            { label: '鍒犻櫎', code: 'processStep_delete', icon: 'delete', isCommonMethod: true },
-            // {  label: '瀵煎嚭NC绋嬪簭', code: 'processStep_export', icon: 'import', isCommonMethod: true },
-            { label: '瀵煎叆NC绋嬪簭', code: 'processStep_import', icon: 'import', isCommonMethod: true },
-            { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
-          ]
-        }
-      }
-    },
-    computed: {
-      getCurrentMenuLevel() {
-        switch (this.treeParams.type) {
-          case 1:
-            return 'product'
-          case 2:
-            return 'component'
-          case 3:
-            return 'part'
-          case 4:
-            return 'processSpecVersion'
-          case 5:
-            return 'process'
-          case 6:
-            return 'processStep'
-        }
-      },
-      getCurrentDocClassCode() {
-        switch (this.treeParams.type) {
-          case 1:
-            return 'OTHER'
-          case 2:
-            return 'OTHER'
-          case 3:
-            return 'OTHER'
-          case 5:
-            return 'NC'
-          case 6:
-            return 'NC'
-        }
-      }
-    },
-    methods: {
-      onContextMenuClick(treeKey, menuKey) {
-        const level = this.getCurrentMenuLevel
-        const param = this.getCurrentDocClassCode
-        console.log('level---------------------', level)
-        console.log('param---------------------', param)
-        const treeNodeInfo = Object.assign({}, this.treeParams, { param })
-        console.log('treeNodeInfo******************', treeNodeInfo)
-        const menuKeyArray = menuKey.split('_')
-        const isCommonMethod = this.defaultContextMenuList[level].find(item => item.code === menuKey).isCommonMethod
-        // product_add => handleAdd 瑙﹀彂瀵瑰簲缁勪欢浜嬩欢
-        let methodName
-        // 鍒ゆ柇鏄惁涓哄叕鍏辨柟娉曪紝濡傛灉涓哄叕鍏辨柟娉曞垯鎴彇涓撴湁灞炴�roduct/component/part/process绛夊瓧娈�
-        if (isCommonMethod) {
-          methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).slice(1).join('')
-        } else {
-          methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).join('')
-        }
-        const modalTitle = this.defaultContextMenuList[level].find(item => item.code === menuKey).label
-        this.$bus.$emit('treeMenuItemMethodTrigger', { methodName, modalTitle, treeNodeInfo })
+export default {
+  name: 'ProductStructureTreeContextMenu',
+  components: {},
+  props: {
+    treeParams: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      defaultContextMenuList: {
+        //浜у搧
+        product: [
+          { label: '娣诲姞浜у搧', code: 'product_add', icon: 'plus', isCommonMethod: false },
+          { label: '娣诲姞閮ㄤ欢', code: 'product_add_child', icon: 'plus', isCommonMethod: false },
+          { label: '缂栬緫浜у搧淇℃伅', code: 'product_edit', icon: 'edit', isCommonMethod: false },
+          // {  label: '瀵煎嚭鏂囨。', code: 'product_export', icon: 'export', isCommonMethod: true },
+          { label: '瀵煎叆鍏朵粬鏂囨。', code: 'product_import', icon: 'import', isCommonMethod: true },
+          { label: '鍒犻櫎', code: 'product_delete', icon: 'delete', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ],
+        //閮ㄤ欢
+        component: [
+          { label: '娣诲姞瀛愰儴浠�', code: 'component_add', icon: 'plus', isCommonMethod: false },
+          { label: '娣诲姞闆朵欢', code: 'component_add_child', icon: 'plus', isCommonMethod: false },
+          { label: '鍒涘缓宸ュ簭', code: 'component_add_relative', icon: 'plus', isCommonMethod: false },
+          { label: '缂栬緫閮ㄤ欢淇℃伅', code: 'component_edit', icon: 'edit', isCommonMethod: false },
+          // {  label: '瀵煎嚭鏂囨。', code: 'component_export', icon: 'export', isCommonMethod: true },
+          { label: '瀵煎叆鍏朵粬鏂囨。', code: 'component_import', icon: 'import', isCommonMethod: true },
+          { label: '鍒犻櫎', code: 'component_delete', icon: 'delete', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ],
+        //闆朵欢
+        part: [
+          { label: '娣诲姞闆朵欢', code: 'parts_add', icon: 'plus', isCommonMethod: false },
+          { label: '鍒涘缓宸ヨ壓瑙勭▼鐗堟湰', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
+          // { label: '鍒涘缓宸ュ簭', code: 'parts_add_relative', icon: 'plus', isCommonMethod: false },
+          { label: '缂栬緫闆朵欢淇℃伅', code: 'parts_edit', icon: 'edit', isCommonMethod: false },
+          // {  label: '瀵煎嚭鏂囨。', code: 'parts_export', icon: 'export', isCommonMethod: true },
+          { label: '瀵煎叆鍏朵粬鏂囨。', code: 'parts_import', icon: 'import', isCommonMethod: true },
+          { label: '鍒犻櫎', code: 'parts_delete', icon: 'delete', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ],
+        //宸ヨ壓瑙勭▼鐗堟湰
+        processSpecVersion: [
+          { label: '鍒涘缓宸ヨ壓瑙勭▼鐗堟湰', code: 'version_add', icon: 'plus', isCommonMethod: false },
+          { label: '鍒涘缓宸ュ簭', code: 'version_add_child', icon: 'plus', isCommonMethod: false },
+          { label: '缂栬緫宸ヨ壓瑙勭▼鐗堟湰淇℃伅', code: 'version_edit', icon: 'edit', isCommonMethod: false },
+          { label: '鍒犻櫎', code: 'version_delete', icon: 'delete', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ],
+        //宸ュ簭
+        process: [
+          { label: '鍒涘缓宸ュ簭', code: 'process_add', icon: 'plus', isCommonMethod: false },
+          { label: '鍒涘缓宸ユ', code: 'process_add_child', icon: 'plus', isCommonMethod: false },
+          { label: '娣诲姞璁惧绫�', code: 'process_add_type', icon: 'plus', isCommonMethod: true },
+          { label: '缂栬緫宸ュ簭淇℃伅', code: 'process_edit', icon: 'edit', isCommonMethod: false },
+          { label: '鍒犻櫎', code: 'process_delete', icon: 'delete', isCommonMethod: true },
+          // {  label: '瀵煎嚭NC绋嬪簭', code: 'process_export', icon: 'export', isCommonMethod: true },
+          { label: '瀵煎叆NC绋嬪簭', code: 'process_import', icon: 'import', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ],
+        //宸ユ
+        processStep: [
+          { label: '鍒涘缓宸ユ', code: 'processStep_add', icon: 'plus', isCommonMethod: false },
+          { label: '缂栬緫宸ユ淇℃伅', code: 'processStep_edit', icon: 'edit', isCommonMethod: false },
+          { label: '娣诲姞璁惧绫�', code: 'processStep_add_type', icon: 'plus', isCommonMethod: true },
+          { label: '鍒犻櫎', code: 'processStep_delete', icon: 'delete', isCommonMethod: true },
+          // {  label: '瀵煎嚭NC绋嬪簭', code: 'processStep_export', icon: 'import', isCommonMethod: true },
+          { label: '瀵煎叆NC绋嬪簭', code: 'processStep_import', icon: 'import', isCommonMethod: true },
+          { label: '鏉冮檺閰嶇疆', code: 'public_assign_permission', icon: 'idcard', isCommonMethod: true }
+        ]
       }
     }
+  },
+  computed: {
+    getCurrentMenuLevel() {
+      switch (+this.treeParams.type) {
+        case 1:
+          return 'product'
+        case 2:
+          return 'component'
+        case 3:
+          return 'part'
+        case 4:
+          return 'processSpecVersion'
+        case 5:
+          return 'process'
+        case 6:
+          return 'processStep'
+      }
+    },
+    getCurrentDocClassCode() {
+      switch (+this.treeParams.type) {
+        case 1:
+          return 'OTHER'
+        case 2:
+          return 'OTHER'
+        case 3:
+          return 'OTHER'
+        case 5:
+          return 'NC'
+        case 6:
+          return 'NC'
+      }
+    }
+  },
+  methods: {
+    onContextMenuClick(treeKey, menuKey) {
+      const level = this.getCurrentMenuLevel
+      const param = this.getCurrentDocClassCode
+      console.log('level---------------------', level)
+      console.log('param---------------------', param)
+      const treeNodeInfo = Object.assign({}, this.treeParams, { param })
+      console.log('treeNodeInfo******************', treeNodeInfo)
+      const menuKeyArray = menuKey.split('_')
+      const isCommonMethod = this.defaultContextMenuList[level].find(item => item.code === menuKey).isCommonMethod
+      // product_add => handleAdd 瑙﹀彂瀵瑰簲缁勪欢浜嬩欢
+      let methodName
+      // 鍒ゆ柇鏄惁涓哄叕鍏辨柟娉曪紝濡傛灉涓哄叕鍏辨柟娉曞垯鎴彇涓撴湁灞炴�roduct/component/part/process绛夊瓧娈�
+      if (isCommonMethod) {
+        methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).slice(1).join('')
+      } else {
+        methodName = 'handle' + menuKeyArray.map(item => item[0].toUpperCase() + item.slice(1)).join('')
+      }
+      console.log('methodName', methodName)
+      const modalTitle = this.defaultContextMenuList[level].find(item => item.code === menuKey).label
+      this.$bus.$emit('treeMenuItemMethodTrigger', { methodName, modalTitle, treeNodeInfo })
+    }
   }
+}
 </script>
 
 <style scoped>
-  .replaceSearch {
-    color: #40a9ff;
-    font-weight: bold;
-    background-color: rgb(204, 204, 204);
-  }
+.replaceSearch {
+  color: #40a9ff;
+  font-weight: bold;
+  background-color: rgb(204, 204, 204);
+}
 
 </style>
\ No newline at end of file
diff --git a/src/views/dnc/common/TableContextMenu.vue b/src/views/dnc/common/TableContextMenu.vue
index 7635a07..1d62177 100644
--- a/src/views/dnc/common/TableContextMenu.vue
+++ b/src/views/dnc/common/TableContextMenu.vue
@@ -41,6 +41,12 @@
         },
         currentMenuLevel: '',
         defaultContextMenuList: {
+          //璁惧绫�
+          deviceCustomType:[
+            { label: '缂栬緫璁惧绫讳俊鎭�', code: 'type_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
+            { label: '鍒犻櫎', code: 'type_delete', subMenu: [], icon: 'delete', isCommonMethod: false },
+            { label: '瀵煎叆NC绋嬪簭', code: 'type_document_import', subMenu: [], icon: 'import', isCommonMethod: true },
+          ],
           //NC鏂囨。
           NC: [
             { label: '缂栬緫鏂囨。淇℃伅', code: 'document_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
diff --git a/src/views/system/modules/UserModal.vue b/src/views/system/modules/UserModal.vue
index a497293..58dc87c 100644
--- a/src/views/system/modules/UserModal.vue
+++ b/src/views/system/modules/UserModal.vue
@@ -376,11 +376,12 @@
         validatorRules: {
           username: [{ required: true, message: '璇疯緭鍏ョ敤鎴疯处鍙�!' },
             { validator: this.validateUsername }],
-          password: [{
-            required: true,
-            pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
-            message: '瀵嗙爜鐢�8浣嶆暟瀛椼�佸ぇ灏忓啓瀛楁瘝鍜岀壒娈婄鍙风粍鎴�!'
-          },
+          password: [
+          //   {
+          //   required: true,
+          //   pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
+          //   message: '瀵嗙爜鐢�8浣嶆暟瀛椼�佸ぇ灏忓啓瀛楁瘝鍜岀壒娈婄鍙风粍鎴�!'
+          // },
             { validator: this.validateToNextPassword, trigger: 'change' }],
           confirmpassword: [{ required: true, message: '璇烽噸鏂拌緭鍏ョ櫥褰曞瘑鐮�!' },
             { validator: this.compareToFirstPassword }],

--
Gitblit v1.9.3