merge合并数据结构、el-autocomplete搜索、objectSpanMethod合并单元格

<template>
  <div :class="['table-panel-group','table-min-space','conllect-tables','partInfoBox',typeName+'Box']"> 
    <!-- cap-table-style -->
    <div class="cap-table-style">
    <div class="table-panel-title">
      <span class="table-panel-tit">{{tablesData.tableTitle}}</span>
    </div>
    <div class="table-panel-tbar cap-button" >
          <el-button 
            type="text"
            class="table-top-button" 
            v-if="!wfprocessid"
            @click="downloadTemplate">下载模板</el-button>
          <el-button 
            type="text"
            class="table-top-button importBtn" 
            v-if="wfprocessid"
            @click="exportTemplate">导出EXCEL</el-button>
          <vivo-file-upload 
            :on-success="importEXCEL" 
            class="importFilesBtn"
            :multi="false" 
            :before-upload="beforeUpload" 
            :action="fileUploadUrl" 
            v-if="edit&&(!wfprocessid||isSupplier)"
            >
            <el-button 
              type="text"
              class="table-top-button importBtn" 
              >导入EXCEL</el-button>
          </vivo-file-upload>
        </div>
    <div class="table-panel-containner">
      <el-table
        ref="singleTable"
        :data="infoData['partInfoData']"
        border
        fit 
        width="100%"
        class="notHoverBg InfoCollectionPartDoc"
        :header-row-class-name="singleTable"
        :span-method="objectSpanMethod"
              >
        <el-table-column :width="col.width" v-for="(col,ix) in tablesData.columns" :key='ix'
                :show-overflow-tooltip="true">
           <template slot="header" slot-scope="scope">
            <span class="table-header-required" v-if="(col.required&&isSupplier)||col.vivoRequired">*</span>{{col.name}}
          </template>
          <template slot-scope="scope">
            <el-autocomplete v-if="col.xtype=='select'" 
                v-model="scope.row[col.id]" 
                class="material-code specification selectOpenIcon is-required"
                style="width:100%;" 
                :trigger-on-focus="false" 
                :disabled="true"
                :placeholder="col.placeholder||'请选择'" 
                :readonly="!edit">
                <div class="specification-containner" slot="prefix" v-if="scope.row[col.id]">
                    <div class="dist-common-phrase" > 
                        <a class="doc-url" :href="isSupplier?'javascript:;':scope.row.partUrl" target="_blank" :title="scope.row[col.id]">
                          {{scope.row[col.id]}}
                        </a>
                        <i class="el-icon-close" 
                            v-show="!wfprocessid" 
                            @click="deleteMaterial(scope.row,scope.$index,scope.row.partNumber)"></i>
                    </div>
                </div>
                <i class="dialog-visible el-input__icon" 
                    slot="suffix" 
                    v-else-if="!wfprocessid"  @click="dialogVisible(scope.$index)" 
                   ></i>
            </el-autocomplete>
            <template v-else-if="col.xtype=='input'">
              <span v-if="(scope.row[col.id]||edit)" :class="[{'is-required':col.required&&isSupplier},'changeVal']">
                <span>
                  <el-input v-if="edit&&(isSupplier||isAdminFlag||!col.required)&&(!(!isSupplier&&!isAdminFlag)&&col.vivoNotWrite)" v-model="scope.row[col.id]" class="pl0" placeholder="请输入"></el-input>
                  <span v-else>
                    <template v-if="scope.row[col.id]">{{scope.row[col.id]}}</template>
                    <span v-else class="gray-bar">-</span>
                  </span>
                </span>
                <span class="beforeVal" v-if="scope.row[col.before]">{{scope.row[col.before]}}</span>
              </span>
              <span v-else class="gray-bar">-</span>
            </template>
            <template v-else-if="col.xtype=='date'">
              <span v-if="(scope.row[col.id]||edit)" :class="[{'is-required':col.required&&isSupplier},'changeVal']">
                <span>
                  <vivo-date-picker  v-if="edit&&(isSupplier||isAdminFlag)" class="pl0" v-model="scope.row[col.id]"> 
                  </vivo-date-picker>
                  <span v-else>
                    <template v-if="scope.row[col.id]">{{scope.row[col.id]}}</template>
                    <span v-else class="gray-bar">-</span>
                  </span>
                </span>

                <span class="beforeVal" v-if="scope.row[col.before]">{{scope.row[col.before]}}</span>
              </span>
              <span v-else class="gray-bar">-</span> 
            </template>
            <template v-else-if="col.xtype=='selectOption'">
              <span v-if="(scope.row[col.id]||edit)"  class="changeVal">
                <span>
                  <el-select v-if="edit&&(isSupplier||isAdminFlag)" :class="[{'is-required':col.required&&isSupplier},'pl0']" v-model="scope.row[col.id]" placeholder="请选择">
                    <el-option
                      v-for="item in col.selectDetail"
                      :key="'option'+item"
                      :label="item"
                      :disable="!edit"
                      :value="item">
                    </el-option>
                  </el-select>
                  <span v-else>
                    <template v-if="scope.row[col.id]">{{scope.row[col.id]}}</template>
                    <span v-else class="gray-bar">-</span>
                  </span>
                </span>

                <span class="beforeVal" v-if="scope.row[col.before]">{{scope.row[col.before]}}</span>
              </span>

              <span v-else class="gray-bar">-</span>
            </template>
            <template v-else-if="col.xtype==''">
              <span v-if="scope.row[col.id]">{{scope.row[col.id]}}</span>
              <span v-else class="gray-bar">-</span>
            </template>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="90" v-if="edit&&!wfprocessid" :fixed="toFixed">
          <template slot-scope="scope">
            <el-button
              @click="addMaterial(scope.$index,scope.row.partNumber)"
              icon="el-icon-plus"
              type="text"
              :disabled="!edit"
              class="part-icon-button inline"
            ></el-button>
            <el-button
              :disabled="!edit"
              @click.native.prevent="deleteMaterial(scope.row,scope.$index,scope.row.partNumber)"
              icon="el-icon-minus"
              type="text"
              class="part-icon-button inline"
            ></el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    </div>
    <el-dialog
      :title="tablesData.popUpTitle"
      :visible.sync="dialogTableVisible"
      width="960px"
      top="20px"
      class="collectionDialog"
      :close-on-click-modal="false"
     >
      <div>
        <el-row class="componentSelection">
          <el-col :span="24"  v-if="!tablesData.getOidPath">
            
            <div class="el-autocomplete specification specification-search">
              <el-input
                v-model="searchPartCode"
                :style="{'width':tablesData.thConfig.width}"
                placeholder="请输入查找内容"
                @input="searchFn"
              ></el-input>
            </div><span class="ml20">已选择</span>
          </el-col>
          <el-col :span="24"  v-else>
            <el-autocomplete
              v-model="searchPartCode"
              class="specification specification-search"
                            :style="{'width':tablesData.thConfig.width}"
              :trigger-on-focus="false"
              placeholder="请输入查询内容"
              :hide-loading="true"
              popper-class="partSearch-dropdown"
              :fetch-suggestions="materialCodeFn"
              @select="manufacturerSelect"
            >
              <template slot-scope="{ item }">
                <div class="manufacturer-name">{{ item.fullName }}</div>
              </template>
            </el-autocomplete><span class="ml20">已选择</span>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <transfer :transferData="transferData" :thConfig="tablesData.thConfig" ref="transferData"></transfer>
          </el-col>
        </el-row>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="confirmAddpartFn">确 定</el-button>
        <el-button @click="clearAdd">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import transfer from "@/components/info-collection/moudel/transfer-panel";
import {
  getCollectMaterialInfo,
  getPartInfoList,
  getImportExcelModel,
  downExcelModel,
  exportExcelModel
  // getApproveRecord
} from "@/api/api";
export default {
  data() {
    return {
      searchPartCode: "", //搜索框值
      dialogTableVisible: false,
      loadingTable: false,
      partSelect:[], 
      pboid:this.$route.query.pboid,
      columns:[],
      editConfirm:true,
      typeName:this.$route.query.typeName,
      fileUploadUrl: "/Windchill/cmprest/uploadController/pluploadUpload",
      uploadFiles:"",
                checkFile:true,
      // hasSelect: [],
      tablesData:{},
      toFixed:null,
      transferData: {
        notSelectData: { // 左边未选中
          type: "left",
          data: []
        },
        SelectData: { // 右边选中
          type: "right",
          data: []
        }
      }
    }; 
  },
  props: {
    infoData: [Object, Array],
    wfprocessid:{
      type: String,
      default:''
    },
    headerEditPermission:Boolean,
    isSupplier:Boolean,
    isAdminFlag:Boolean,
  },
  components: {
    transfer
  },
  computed: {
    sortTables() {
      // addZeroDisable
      if (this.infoData['partInfoData'] && this.infoData['partInfoData'].length) {
        let _tableData = this.infoData['partInfoData'];
        //当前表单
        return _tableData.sort(this.compare("partNumber")); //partNumberIndex
      } else {
        return null;
      }
    },
    edit(){
        return this.$store.state.edit
    }
  },
  created() {    
    if (!this.pboid||!this.$route.query.tempValue) {
          this.addMaterial(0);
    }
    // this.infoData.partInfoData['SupplierMoldNum']='123456'
    var tableDefault = require('@/scene/'+this.$route.query.typeName+'/config/tablePartInfo.js');
    this.tablesData = tableDefault[0];
    
    if(this.typeName=='InfoCollection') this.tablesData.thConfig['width'] = "480px";
    this.toFixed = tableDefault[0].toFixed || null;
    
    setTimeout(()=>{
      if(this.infoData && this.infoData.state == "已发布" && !isAdminFlag){
        this.editConfirm = false;
      }
    })
    
  },
  watch:{
    'infoData.partInfoData'(val){
      if(!val || !val.length) {
        this.addMaterial(0);
      }

    },
  },
  methods: {
    singleTable(row,rowIndex){
      var headerClassName = "part-tableHeader";
      return headerClassName
    },
    //判断导入的文件格式
    checkFileExt(fileName){
      var arr = ["xlsx","xls"];
      var index = fileName.lastIndexOf(".");
      if(index == -1){return false;}
      var strMsg = fileName.slice(index+1);
      return arr.some(item=>item==strMsg);
    },
    //导入EXCEL  before
    beforeUpload(vivoupload,upload,file){
      var fileName = file.name;
      if(!this.checkFileExt(fileName)){
        this.checkFile = false;
      }else {
        this.checkFile = true;
      }
    },
    importEXCEL(data){
      var scope = this,checkFile=true;
      if(!this.checkFile){
        this.$message.error("当前导入文件格式不是xlsx");
        return;
      }
      if(!data.files.length){
        this.$message.error("请上传导入文件");
        return;
      }
      var param = {};
      param.filePath = data.files[0].filepath;
      var loadMask = this.$loading({
          lock: false,
          spinner:"vo-mask",
          background:"rgba(204,204,204,.5)"
      });
      getImportExcelModel(param).then(res => {
        if(res.data.retCode == '000000'){
          loadMask.close();
          var data = scope.parseData(res);
          if(data.errorPart&&data.errorPart.length){
            this.$message.warning(`导入模具编码:${JSON.stringify(data.errorPart)} 没有数据!`);
          }
          
          if(data.moldInfo.length > 0){
            var isChange = this.reduces(data.moldInfo,this.infoData['partInfoData'],'excels');
            if(this.wfprocessid){
              if(isChange&&isChange.length) return this.$message.error("导入的数据与模板不符合,请重新上传!");
            }
          }
          if(!this.isSupplier&&!this.isAdminFlag){//vivo用户非管理员不写入必填字段 
            this.vivoImportData(data.moldInfo);
          }
          this.$set(this.infoData,'partInfoData',data.moldInfo);
          if(!(data.errorPart&&data.errorPart.length))
            this.$message.success("导入成功");
        // loadMask.close();
        }else{
          this.$message({
            dangerouslyUseHTMLString:true,
            message: res.data.retMsg,
            type: 'error'
          });
          loadMask.close();
        }
      });
    },
    vivoImportData(data){
      var getRowsId=[],getRows =this.tablesData['columns'].filter(item=>item.vivoNotWrite);
      getRows.forEach(item =>getRowsId.push(item.id));
      return data.forEach(item=>{
        getRowsId.forEach(id=>{
          item[id]='';
        })
      })
    },
    exportTemplate(){
      var scope = this;
      var param = JSON.stringify(this.infoData['partInfoData']);
            //导出
      var url = "/Windchill/cmprest/uploadController/moldpart/export";
      var forms = "<form method='post' action='" + url + "'><input name='params' value='" + param +"' ></form>";
      $(forms).appendTo("body").submit().remove();
    },
    downloadTemplate(){
      // window.open("/Windchill/exporttemplate/模具信息收集上传模板.xlsx");
      var scope = this;
      var param = "";
      var loadMask = this.$loading({
        spinner:"vo-mask",
        background:"rgba(204,204,204,.5)"
      });
      downExcelModel(param).then(res => {
        if(res.data.retCode == '000000'){
          loadMask.close();
          debugger
          var data = res.data.element;
          window.open(data);
        }else{
          loadMask.close();
          this.$message({
            dangerouslyUseHTMLString:true,
            message: res.data.retMsg,
            type: 'error'
          });
        }
      });
    },
    //json排序
    compare(property) {
      return function(a, b) {
        if (a[property] && b[property]) {
          var value1 = a[property];
          var value2 = b[property];
          return value1 - value2;
        }
      };
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      //合并单元格
      let tableData = this.sortTables;
      //  let tableData  = this.objectValue[this.object.id]
      var num = 0;
      if (columnIndex == 0 || columnIndex == 1 || columnIndex == 5) {
        for (var i = 0; i < tableData.length; i++) {
          if (row.partNumber == tableData[i].partNumber) {
            //partNumberIndex
            num++;
          }
        }
        if (num == 1) {
          return {
            rowspan: num,
            colspan: 1
          };
        } else if (num > 1 && tableData && tableData[rowIndex].partNumber) {
          //partNumberIndex
          if (
            tableData[rowIndex - 1] &&
            tableData[rowIndex].partNumber == tableData[rowIndex - 1].partNumber //partNumberIndex
          ) {
            return {
              rowspan: 0,
              colspan: 0
            };
          } else {
            return {
              rowspan: num,
              colspan: 1
            };
          }
        }
      }
    },
    addMaterial(index) {
      //物料编码 添加空行
      if(!this.infoData['partInfoData']) this.$set( this.infoData,'partInfoData',[]);
      this.infoData['partInfoData'].push({});
    },
    //删除受影响对象行
    deleteMaterial(row, index, partNumber) {
      //partNumberIndex
      var tableData = this.infoData['partInfoData'];
            var scope = this;
      // this.$confirm("确认移除物料及相关联供应商部件?", "提示", {
      //   confirmButtonText: "确定",
      //   cancelButtonText: "取消",
      //   type: "warning"
      // }).then(() => {
          var result = [];
          if (partNumber) {
            //partNumberIndex
            result = tableData.filter(item => item.partNumber != partNumber); //partNumberIndex
          }else{
                        result = tableData.filter((item,num) => num != index);
                    }
          this.infoData['partInfoData'] =result;
          var addResult = result.filter(item => item.partNumber);
          // if (addResult &&addResult.length){
          //   this.merge(addResult);
          // }
          // else {
          //   this.geDocListFn("")
          // }
          
        // })
        // .catch(() => {});
    },
    //弹窗 搜索物料编码
    dialogVisible(index, type) {
      this.mfnRadio = index;
      if(!this.tablesData.getOidPath) 
      this.transferData.SelectData.data = this.infoData['partInfoData'].filter(
        item => item.number
      );
      else this.transferData.SelectData.data = this.infoData['partInfoData'].filter(
        item => item.partNumber
      );

      this.dialogTableVisible = true;
      this.searchPartCode = "";
      this.transferData.notSelectData.data = [];
    },
    searchFn(){
      if (this.searchPartCode.length >= 4) {
        var param = { params: this.searchPartCode };
        var loadMask = this.$loading({
          spinner: "vo-mask",
          background: "rgba(204,204,204,.5)"
        });
        getCollectMaterialInfo(param,this.tablesData.getDataPath).then(res => {
          if (res.data.retCode == "000000") {
              var SelectData = this.transferData.SelectData['data'];
              var mfnArr = this.parseData(res);

              if(!mfnArr) mfnArr=[];
              mfnArr = this.reduces(mfnArr,SelectData);
              this.transferData.notSelectData['data'] = mfnArr;

              console.log(this.transferData.notSelectData, "搜索物料结果");
              loadMask.close();
            } else {
              loadMask.close();
              this.$message.error(res.data.retMsg);
            }

          // if (res.data.retCode == "000000") {
          //   var mfnArr = this.parseData(res);
          //   if (mfnArr && mfnArr.length > 0) {
          //     for (var i = 0; i < mfnArr.length; i++) {
          //       this.$set(
          //         mfnArr[i],
          //         "fullName",
          //         mfnArr[i].name + " (" + mfnArr[i].number + ")"
          //       );
          //     }
          //     cb(mfnArr);
          //   } else {
          //   }
          //   loadMask.close();
          // } else {
          //   loadMask.close();
          //   this.$message.error(res.data.retMsg);
          // }
        });
      }
    },
    //受影响对象直接搜索物料编码
    materialCodeFn(queryString, cb) {
      if (queryString.length >= 5) {
        var param = { params: queryString };
        var loadMask = this.$loading({
          // lock: true,
          spinner: "vo-mask",
          background: "rgba(204,204,204,.5)"
        });
        getCollectMaterialInfo(param,this.tablesData.getDataPath).then(res => {
          if (res.data.retCode == "000000") {
            var mfnArr = this.parseData(res);
            if (mfnArr && mfnArr.length > 0) {
              for (var i = 0; i < mfnArr.length; i++) {
                this.$set(
                  mfnArr[i],
                  "fullName",
                  mfnArr[i].name + " (" + mfnArr[i].number + ")"
                );
              }
              cb(mfnArr);
            } else {
            }
            loadMask.close();
          } else {
            loadMask.close();
            this.$message.error(res.data.retMsg);
          }
        });
      }
    },
    //受影响对象搜索物料编码 选中下拉值
    manufacturerSelect(item) {
      this.partNumber = item.number;
      this.mpnNumber = item.mpnNumber||null;
      this.poid = item.oid||null;
      this.confirmAddMaterialFn();
    },
    //受影响对象 确认添加
    confirmAddMaterialFn() {
      //物料搜索
      this.searchPartCode = this.partNumber; //
      if (this.poid) {
        var param = {params:this.poid};//{params:this.poid}
        var loadMask = this.$loading({
          // lock: true,
          spinner: "vo-mask",
          background: "rgba(204,204,204,.5)"
        });
          getPartInfoList(param).then(res => {
            //confirmAddMaterial
            if (res.data.retCode == "000000") {
              var SelectData = this.transferData.SelectData['data'];
              var mfnArr = this.parseData(res);

              if(!mfnArr) mfnArr=[];
              mfnArr = this.reduces(mfnArr,SelectData);
              this.transferData.notSelectData['data'] = mfnArr;

              console.log(this.transferData.notSelectData, "搜索物料结果");
              loadMask.close();
            } else {
              loadMask.close();
              this.$message.error(res.data.retMsg);
            }
          });
      }else {
        this.$message.warning("请选择一个物料!");
      }
    },
    reduces(arr,select,type){//去除已选择的项
      if(!arr) return;
      let data = arr.reduce((pre,cur)=>{
          if(type=='excels'){
            if(select.every(item=>item.number!==cur.number)) pre.push(cur);
          }else{
            if(!this.tablesData.getOidPath){
              if(select.every(item=>item.number!==cur.number)) pre.push(cur);
            }
            else{
              if(select.every(item=>item.mpnNumber!==cur.mpnNumber)) pre.push(cur);
            }
          }
          return pre;
      },[]);
      // console.log(arr,select,data);
      return data;
    },
    //确定添加行
    confirmAddpartFn() {
      var selectData = this.$refs.transferData.initialData;
      var partInfoData = this.infoData['partInfoData'];
            if(selectData && selectData.length){
                if(!this.tablesData.getOidPath) selectData = selectData.filter(item=>item.number);
        else selectData = selectData.filter(item=>item.partNumber);
            }
            if(partInfoData && partInfoData.length){
        if(!this.tablesData.getOidPath) partInfoData = partInfoData.filter(item=>item.number);
        else partInfoData = partInfoData.filter(item=>item.partNumber);
            }
            if(selectData&&selectData.length&&selectData!=partInfoData){
                var addResult = this.$refs.transferData.initialData;
                this.infoData['partInfoData'] =addResult;
                // if (addResult &&addResult.length) this.merge(addResult);
      }
      
      // this.$set(this.busData,'poid',this.poid);
            console.log(addResult, this.mfnRadio, "确定添加-物料信息结果");
            this.clearAdd();
    },
    
    //解析合并
    merge(arr) {
      const map = {};
      for (const o of arr) {
        const partNumber = o.partNumber;
        if (!map.hasOwnProperty(partNumber)) {
          map[partNumber] = [o.mpnNumber];
        } else {
          map[partNumber].push(o.mpnNumber);
        }
      }
      return map;
    },
    //取消添加
    clearAdd() {
      this.$refs.transferData.initialData = null; //清除选中项
      this.dialogTableVisible = false;
    }
  }
};
</script>

转载于:https://my.oschina.net/u/4099729/blog/3024190

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值