1、设备结构树页面接收NC文件列表新增指派到产品NC文件功能
2、设备TEEP页面故障率数据展示格式调整
已添加1个文件
已修改5个文件
569 ■■■■■ 文件已修改
src/api/dnc.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Document/HasReceivedDocumentAssignModal.vue 543 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Document/HasReceivedDocumentTableList.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentAssignModal.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/common/TableContextMenu.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/efficiencyReport/EfficiencyList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/dnc.js
@@ -85,6 +85,10 @@
  //-------------------------设备结构树------------------------------------------------
  // èŽ·å–è®¾å¤‡æ ‘
  getDeviceTreeDataApi: () => getAction('/nc/device/queryTreeListByProduction'),
  // èŽ·å–äº§å“ç»“æž„æ ‘å®Œæ•´å±‚çº§åˆ°NC文件
  getAllProductTreeDataApi: () => getAction('/nc/product/getAllTree'),
  // æŒ‡æ´¾åˆ°äº§å“
  assignNcToProductApi: params => postAction('/dncFlow/assignEquipmentFileStream/savaFlow', params),
  // åˆ é™¤æ–‡æ¡£
  deleteDeviceRelativeDocumentApi: ({ docId, attributionId }) => deleteAction(`doc/relative/delete/device/${docId}/${attributionId}`),
  // èŽ·å–æœ‰æƒé™çš„ç”¨æˆ·åˆ—è¡¨
src/views/dnc/base/modules/DeviceStructure/Document/HasReceivedDocumentAssignModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,543 @@
<template>
  <j-modal width="85%" :title="title" :visible="visible" @cancel="handleCancel" :maskClosable="false" centered
           @ok="handleAssignDocumentToDevice" :confirmLoading="confirmLoading">
    <div class="tabs-container">
      <div style="width: 72%">
        <a-tabs>
          <a-tab-pane tab="文档列表">
            <div class="table-page-search-wrapper">
              <a-form layout="inline" @keyup.enter.native="searchQuery">
                <a-row :gutter="24">
                  <a-col :md="7" :sm="7">
                    <a-form-item label="文件名称">
                      <a-input placeholder="请输入文件名称" v-model="queryParam.docName" allow-clear></a-input>
                    </a-form-item>
                  </a-col>
                  <a-col :md="9" :sm="9">
                    <a-form-item label="上传时间">
                      <a-range-picker v-model="date" value-format="YYYY-MM-DD"
                                      @change="handleDateChange" allow-clear></a-range-picker>
                    </a-form-item>
                  </a-col>
                  <a-col :md="4" :sm="4">
                    <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
                  </a-col>
                </a-row>
              </a-form>
            </div>
            <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false" :loading="loading"
                     :rowSelection="{selectedRowKeys: selectedRowKeys,selectedRows:selectionRows, onChange: onSelectChange,type:'radio'}"
                     @change="handleTableChange" :customRow="customRow"
                     :scroll="{y:456}" :size="size" rowKey="docId">
              <!-- å­—符串超长截取省略号显示-->
              <span slot="docName" slot-scope="text">
                <j-ellipsis :value="text"/>
              </span>
            </a-table>
          </a-tab-pane>
        </a-tabs>
      </div>
      <div style="width: 26%">
        <a-tabs>
          <a-tab-pane tab="设备列表">
            <a-spin :spinning="spinning">
              <div style="display: flex;flex-direction: column;">
                <div style="display: flex">
                  <a-input placeholder="输入关键字进行搜索" allowClear v-model="searchInput"
                           @change="handleSearchInputChange"/>
                  <a-button type="primary" @click="isExpandAllTreeNode=!isExpandAllTreeNode" style="margin: 0 8px">
                    å±•å¼€/折叠
                  </a-button>
                </div>
                <!--产品结构树-->
                <div style="overflow:auto;margin-top: 10px;height: 400px">
                  <a-tree blockNode checkable :checkedKeys="checkedKeys" :expandedKeys.sync="expandedKeys"
                          :autoExpandParent="autoExpandParent" @select="handleTreeNodeSelect" checkStrictly
                          :treeData="treeDataSource" @check="handleTreeNodeCheck" @expand="handleTreeNodeExpand">
                    <template slot="title" slot-scope="{ label, parentId, entity, key:treeKey,type}">
                      <a-tooltip :title="label" v-if="type==99">
                          <span v-if="label.indexOf(searchValue) > -1">
                      {{ label.substr(0, label.indexOf(searchValue)) }}
                      <span class="replaceSearch">{{searchValue}}</span>
                      {{ label.substr(label.indexOf(searchValue) + searchValue.length) }}
                    </span>
                        <span v-else>{{ label }}</span>
                      </a-tooltip>
                      <template v-else>
                         <span v-if="label.indexOf(searchValue) > -1">
                      {{ label.substr(0, label.indexOf(searchValue)) }}
                      <span class="replaceSearch">{{searchValue}}</span>
                      {{ label.substr(label.indexOf(searchValue) + searchValue.length) }}
                    </span>
                        <span v-else>{{ label }}</span>
                      </template>
                    </template>
                  </a-tree>
                </div>
                <a-form-model ref="form" :rules="validateRules" :model="queryParam">
                  <a-form-model-item label="指派原因" prop="applyReason">
                    <a-textarea placeholder="请输入指派原因" v-model="queryParam.applyReason" rows="3" style="resize: none"/>
                  </a-form-model-item>
                </a-form-model>
              </div>
            </a-spin>
          </a-tab-pane>
        </a-tabs>
      </div>
    </div>
  </j-modal>
</template>
<script>
  import { getAction } from '@/api/manage'
  import dncApi from '@/api/dnc'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  export default {
    name: 'HasReceivedDocumentAssignModal',
    components: {},
    mixins: [JeecgListMixin],
    props: {
      currentDocumentInfo: {
        type: Object
      },
      currentTreeNodeInfo: {
        type: Object
      },
      size: {
        type: String
      }
    },
    data() {
      return {
        disableMixinCreated: true,
        visible: false,
        title: '',
        columns: [
          {
            title: '序号',
            dataIndex: 'rowIndex',
            key: 'rowIndex',
            width: 65,
            align: 'center',
            customRender: function(t, r, index) {
              return parseInt(index) + 1
            }
          },
          {
            title: '文件名称',
            dataIndex: 'docName',
            key: 'docName',
            align: 'center',
            scopedSlots: { customRender: 'docName' },
            sorter: true
          },
          { title: '设备编号', dataIndex: 'docCode', align: 'center' },
          {
            title: '出库状态',
            dataIndex: 'pullStatus_dictText',
            key: 'pullStatus',
            align: 'center',
            filters: [
              { text: '未出库', value: 1 },
              { text: '已出库', value: 2 }
            ]
          },
          {
            title: '状  æ€',
            dataIndex: 'docDispatchStatus_dictText',
            key: 'docDispatchStatus',
            align: 'center',
            filters: [
              { text: '编制', value: 1 },
              { text: '校对', value: 2 },
              { text: '批准', value: 3 },
              { text: '试切', value: 4 },
              { text: '定型', value: 5 }
            ]
          },
          {
            title: '创建时间',
            dataIndex: 'createTime',
            align: 'center',
            width: 200,
            sorter: true
          }
        ],
        validateRules: {
          applyReason: [
            { required: true, message: '请输入指派原因' }
          ]
        },
        searchValue: '',
        searchInput: '',
        spinning: false,
        treeDataSource: [],
        allTreeKeys: [],
        checkedKeys: [],
        expandedKeys: [],
        autoExpandParent: true,
        isExpandAllTreeNode: false,
        confirmLoading: false,
        date: [],
        url: {
          list: '/nc/doc/find/list'
        }
      }
    },
    watch: {
      visible: {
        handler(value) {
          if (value) {
            this.resetData()
            this.loadData()
            this.getDocumentAssignDeviceTreeByApi()
          }
        }
      },
      isExpandAllTreeNode: {
        handler(value) {
          if (value) this.expandedKeys = this.allTreeKeys
          else this.expandedKeys = []
        }
      }
    },
    created() {
      this.$bus.$on('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    beforeDestroy() {
      this.$bus.$off('treeMenuItemMethodTrigger', this.triggerCorrespondingMethod)
    },
    methods: {
      // è®¾å¤‡æ ‘右键菜单指派到产品弹窗
      handleDeviceRecAssign() {
        this.visible = true
      },
      // èŽ·å–å½“å‰å·¥åºæˆ–å·¥æ­¥å¯¹åº”æ–‡æ¡£åˆ—è¡¨
      loadData() {
        this.dataSource = []
        if (!this.url.list) {
          this.$message.error('请设置url.list属性!')
          return
        }
        var params = this.getQueryParams()//查询条件
        if (!params) return false
        let paramType, paramId
        if (this.currentTreeNodeInfo) {
          const { key, type } = this.currentTreeNodeInfo
          paramType = type
          paramId = key
        } else if (this.currentDocumentInfo) {
          const { attributionType, attributionId } = this.currentDocumentInfo
          paramType = attributionType
          paramId = attributionId
        }
        params.attributionType = paramType
        params.attributionId = paramId
        params.docClassCode = 'REC'
        this.loading = true
        getAction(this.url.list, params)
          .then((res) => {
            if (res.success) this.dataSource = res.result
            else this.$message.warning(res.message)
          }).finally(() => {
          this.loading = false
        })
      },
      /**
       * è‡ªå®šä¹‰è¡¨æ ¼è¡Œ
       * @param record è¡¨æ ¼è¡Œè®°å½•
       */
      customRow(record) {
        return {
          style: {
            cursor: 'pointer'
          },
          on: {
            click: () => {
              this.onSelectChange([record.docId], [record])
            }
          }
        }
      },
      // èŽ·å–DNC产品树
      getDocumentAssignDeviceTreeByApi() {
        this.spinning = true
        this.treeDataSource = []
        dncApi.getAllProductTreeDataApi()
          .then(res => {
            if (res.success) {
              this.dataList = []
              this.allTreeKeys = []
              this.treeDataSource = res.result
              console.log('treeDataSource', res.result)
              this.generateList(this.treeDataSource)
              this.expandedKeys = [this.treeDataSource[0].id]
            } else {
              this.$message.warn(res.message)
            }
          })
          .finally(() => {
            this.spinning = false
          })
      },
      // æ—¶é—´é€‰æ‹©å™¨é€‰æ‹©å®ŒæˆåŽè§¦å‘
      handleDateChange(value) {
        this.queryParam.startTime = value[0]
        this.queryParam.endTime = value[1]
      },
      /**
       * è¡¨æ ¼åˆ†é¡µã€æŽ’序改变、筛选时触发
       * @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.loadData()
      },
      // æŒ‡æ´¾åˆ°äº§å“çª—口点击确定指派设备后触发
      handleAssignDocumentToDevice() {
        const { checkedKeys, selectionRows, selectedRowKeys, $confirm, $notification, queryParam: { applyReason }, $destroyAll, handleCancel } = this
        if (checkedKeys.length === 0 || selectedRowKeys.length === 0) {
          $notification.warning({
            message: '消息',
            description: '请选择设备或文档'
          })
          return
        }
        const that = this
        this.$refs.form.validate(valid => {
          if (valid) {
            const { docId, attributionId, publishFileId } = selectionRows[0]
            const params = {
              docId: checkedKeys[0],
              equipmentDocId: docId,
              equipmentId: attributionId,
              equipmentFileId: publishFileId,
              applyReason
            }
            $confirm({
              title: '提示',
              content: `确认提交吗?`,
              okText: '确认',
              cancelText: '取消',
              onOk: () => {
                that.confirmLoading = true
                dncApi.assignNcToProductApi(params)
                  .then(res => {
                    if (res.success) {
                      handleCancel()
                      $notification.success({
                        message: '消息',
                        description: res.message
                      })
                    } else {
                      $notification.error({
                        message: '消息',
                        description: res.message
                      })
                    }
                  })
                  .finally(() => {
                    $destroyAll()
                    that.confirmLoading = false
                  })
              },
              onCancel: () => {
                $destroyAll()
              }
            })
          } else {
            return false
          }
        })
      },
      /* è¾“入查询内容变化时触发 */
      handleSearchInputChange() {
        let search = this.searchInput
        let expandedKeys = this.dataList
          .map(item => {
            if (item.title != null) {
              if (item.title.indexOf(search) > -1) {
                return this.getParentKey(item.key, this.treeDataSource)
              }
              return null
            }
          })
          .filter((item, i, self) => item && self.indexOf(item) === i)
        Object.assign(this, {
          expandedKeys,
          searchValue: search,
          autoExpandParent: true
        })
      },
      /**
       * æ ‘节点展开合并时触发
       * @param expandedKeys å±•开项key
       */
      handleTreeNodeExpand(expandedKeys) {
        this.expandedKeys = expandedKeys
        this.autoExpandParent = false
      },
      /**
       * æ ‘节点复选框选中时触发
       * @param selectedKeys é€‰ä¸­èŠ‚ç‚¹key
       * @param {node} node èŠ‚ç‚¹å¯¹è±¡
       */
      handleTreeNodeCheck(checkedObj, { node }) {
        console.log('checkedObj', checkedObj)
        console.log('node', node.dataRef)
        let record = node.dataRef
        if (record.type !== 99) return
        this.checkedKeys = checkedObj.checked.slice(-1)
      },
      /**
       * æ ‘节点选中时触发(模拟树节点复选框选中时的效果)
       * @param selectedKeys é€‰ä¸­èŠ‚ç‚¹key
       * @param {node} node èŠ‚ç‚¹å¯¹è±¡
       */
      handleTreeNodeSelect(selectedKeys, { node }) {
        node.$el.childNodes[1].click()
      },
      /**
       * é€’归获得输入项的父级key
       * @param key å­é¡¹key
       * @param tree å­é¡¹
       */
      getParentKey(key, tree) {
        let parentKey
        for (let i = 0; i < tree.length; i++) {
          const node = tree[i]
          if (node.children) {
            if (node.children.some(item => item.key === key)) {
              parentKey = node.key
            } else if (
              this.getParentKey(key, node.children)) {
              parentKey = this.getParentKey(key, node.children)
            }
          }
        }
        return parentKey
      },
      /**
       * é€’归获得所有树节点key
       * @param data è®¾å¤‡æ ‘数据
       */
      generateList(data) {
        for (let i = 0; i < data.length; i++) {
          data[i].key = data[i].id
          const node = data[i]
          const key = node.id
          const title = node.label
          this.dataList.push({ key, title })
          this.allTreeKeys.push(key)
          this.setTreeNodeIcon(node)
          if (node.children) this.generateList(node.children)
        }
      },
      /**
       * è®¾ç½®æ ‘节点图标
       * @param treeNode
       */
      setTreeNodeIcon(treeNode) {
        switch (+treeNode.type) {
          case 1:
            treeNode.slots = { icon: 'product' }
            break
          case 2:
            treeNode.slots = { icon: 'component' }
            break
          case 3:
            treeNode.slots = { icon: 'part' }
            break
          case 4:
            treeNode.slots = { icon: 'processSpecVersion' }
            break
          case 5:
            treeNode.slots = { icon: 'process' }
            break
          case 6:
            treeNode.slots = { icon: 'processStep' }
            break
          default:
        }
      },
      resetData() {
        this.searchInput = this.searchValue = ''
        this.expandedKeys = []
        this.selectedRowKeys = []
        this.selectionRows = {}
        this.checkedKeys = []
        this.filters = {}
        this.isorter = Object.assign({}, this.defaultSorter)
      },
      handleCancel() {
        this.visible = false
      },
      triggerCorrespondingMethod({ methodName, modalTitle }) {
        if (this[methodName]) {
          this[methodName]()
          this.title = modalTitle
        }
      }
    }
  }
</script>
<style scoped lang="less">
  /deep/ .ant-modal {
    .tabs-container {
      display: flex;
      justify-content: space-between;
      .replaceSearch {
        color: #40a9ff;
        font-weight: bold;
        background-color: rgb(204, 204, 204);
      }
    }
  }
  ::-webkit-scrollbar {
    width: 8px;
  }
</style>
src/views/dnc/base/modules/DeviceStructure/Document/HasReceivedDocumentTableList.vue
@@ -9,6 +9,9 @@
    </a-table>
    <DocumentModal ref="modalForm" @ok="modalFormOk"/>
    <has-received-document-assign-modal :size="size" ref="documentAssignModalRef"
                                        :currentDocumentInfo="currentRightClickedDocumentInfo"/>
  </div>
</template>
@@ -16,10 +19,11 @@
  import { getAction } from '@/api/manage'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import DocumentModal from '../../../../common/DocumentModal.vue'
  import HasReceivedDocumentAssignModal from './HasReceivedDocumentAssignModal'
  export default {
    name: 'HasReceivedDocumentTableList',
    components: { DocumentModal },
    components: { HasReceivedDocumentAssignModal, DocumentModal },
    mixins: [JeecgListMixin],
    props: {
      currentTreeNodeInfo: {
@@ -185,7 +189,12 @@
        this.$refs.modalForm.title = modalTitle
      },
      handleDocumentAssign(record, modalTitle) {
      /**
       * æŽ§åˆ¶æŒ‡æ´¾åˆ°äº§å“å¼¹çª—
       * @param record è¡¨æ ¼è¡Œä¿¡æ¯
       * @param modalTitle å¼¹çª—标题
       */
      handleDocumentRecAssign(record, modalTitle) {
        this.$refs.documentAssignModalRef.title = modalTitle
        this.$refs.documentAssignModalRef.visible = true
      },
src/views/dnc/base/modules/ProductStructure/Document/NcDocumentAssignModal.vue
@@ -56,7 +56,7 @@
                  </a-button>
                </div>
                <!--产品结构树-->
                <!--设备结构树-->
                <div style="overflow:auto;margin-top: 10px;height: 400px">
                  <a-tree blockNode checkable :checkedKeys="checkedKeys" :expandedKeys.sync="expandedKeys"
                          :autoExpandParent="autoExpandParent" @select="handleTreeNodeSelect"
@@ -436,7 +436,7 @@
    },
    resetData() {
      this.searchInput = ''
      this.searchInput = this.searchValue = ''
      this.expandedKeys = []
      this.selectedRowKeys = []
      this.selectionRows = {}
src/views/dnc/common/TableContextMenu.vue
@@ -45,7 +45,7 @@
          deviceCustomType:[
            { label: '编辑设备类信息', code: 'type_edit', subMenu: [], icon: 'edit', isCommonMethod: false },
            { label: '删除', code: 'type_delete', subMenu: [], icon: 'delete', isCommonMethod: false },
            { label: '导入NC程序', code: 'type_nc_import', subMenu: [], icon: 'import', isCommonMethod: true },
            { label: '导入NC程序', code: 'type_nc_import', subMenu: [], icon: 'import', isCommonMethod: true }
          ],
          //NC文档
          NC: [
@@ -117,6 +117,7 @@
            { label: '下载', code: 'document_download', subMenu: [], icon: 'download', isCommonMethod: true },
            { label: '删除', code: 'document_delete', subMenu: [], icon: 'delete', isCommonMethod: true },
            { label: '批量删除', code: 'document_batch_remove', subMenu: [], icon: 'delete', isCommonMethod: true },
            { label: '指派到产品', code: 'document_rec_assign', subMenu: [], icon: 'cluster', isCommonMethod: false },
            {
              label: '生命周期',
              subMenu: [
src/views/mdc/base/modules/efficiencyReport/EfficiencyList.vue
@@ -189,7 +189,7 @@
                    {{tableHead.openRate | numFilter}}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('gzl') > -1">
                    {{tableHead.faultRate | numFilter}}
                    {{tableHead.faultRate }}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('kjsj') > -1">
                    {{tableHead.openLong | getFormattedTime}}