封装qms三级物料多选组件

qms项目中的物料数据有很多,若是直接通过select下拉展示,首先是数据太多,会卡住,然后展示的内容也不全,目前物料有三个层级,分别一级物料、二级物料、三级物料,若是多加几个筛选条件,那最后获取到的数据就不是很多,然后就想到重新写个组件展示,
实现效果:
目前有两个框,一个展示选中的物料类别,一个是选中的物料名称,希望通过,点击一级物料列表项,获取到二级物料列表,点击二级物料列表项,获取三级物料列表,点击三级物料列表项,获取到物料清单,点击待选择物料列表项,选中物料列表新增一个物料,可以多选,点击选中的物料列表项,物料列表删除该物料,同时取消该物料的选中状态;若是点击一级物料列表项,则重新获取二级物料列表,同时把三级物料列表、待选择物料列表、已选择物料列表清空;点击二级物料列表时,则重新获取三级物料列表,同时把待选择物料列表、已选择物料列表清空;点击三级物料列表时,则重新获取待选择物料列表,同时把已选择物料列表清空;
在这里插入图片描述
在这里插入图片描述

20240126_190247

代码如下

materialType.vue

<template>
  <div>
    <div @click="inputClick()" style="cursor: pointer;">
      <!--通过css样式 pointer-events:none; 控制设为disabled的input可以点击 -->
      <a-input v-model:value="selectName"  disabled style="pointer-events:none;width:100%;" placeholder="请选择" ref="searchInput" autocomplete="off">%
      </a-input>
    </div>
    <a-modal v-model:visible="visible" @ok="handleOk" @cancel="handleCancel" width="850px" height="400px">
      <template #title>
        <div style="font-weight: 600; font-size: 16px">物料</div>
      </template>
      <div class="warp flex_between">
        <div class="flex_7">
          <div class="line30">未选择</div>
          <div class="flex_between">
            <div class="borderRight borderBottom table_title table_width150">一级物料</div>
            <div class="borderRight borderBottom table_title table_width150">二级物料</div>
            <div class="borderRight borderBottom table_title table_width150">三级物料</div>
            <div class="borderBottom table_title table_width200">物料名称</div>
          </div>
          <div class="flex_between">
            <div class="borderRight max_height table_width150">
              <div v-for="(item,index) in firstData" :key="index" :title="item.label" @click="firstClick(item)" :class="{'list_style':item.value!=firstTier,'list_active':item.value==firstTier}">{{item.label}}</div>
            </div>
            <div class="borderRight max_height table_width150">
              <div v-for="(item,index) in secondData" :key="index" :title="item.label" @click="secondClick(item)" :class="{'list_style':item.value!=secondTier,'list_active':item.value==secondTier}">{{item.label}}</div>
            </div>
            <div class="borderRight max_height table_width150">
              <div v-for="(item,index) in thirdData" :key="index" :title="item.label" @click="thirdClick(item)" :class="{'list_style':item.value!=thirdTier,'list_active':item.value==thirdTier}">{{item.label}}</div>
            </div>
            <div class="max_height table_width200">
              <div v-for="(item,index) in waitData" :key="index" :title="item.label" @click="waitClick(item)" :class="{'list_style':selectedMaterialName.includes(item.value),'list_active':selectedMaterialName.includes(item.value)}">{{item.label}}</div>
            </div>
          </div>
        </div>
        <div class="flex_3" >
          <div class="line30">选中</div>
          <div class="borderBottom table_title">物料名称</div>
          <div style="height:calc(100% - 30px);">
            <div style="width:100%;height:100%;" class="max_height">
              <div v-for="(item,index) in selectedData" :title="item.label" :key="index" @click="selectedClick(item)" class="list_style">{{item.label}}</div>
            </div>
          </div>
        </div>
      </div>
    </a-modal>
  </div>
</template>
<script setup>
import {onMounted, ref,defineEmits,defineProps, onBeforeUnmount, watch, nextTick} from 'vue';
import {defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import qs from 'qs'
const { createMessage } = useMessage();
const visible = ref(false);
const emits = defineEmits(['check']);
const props = defineProps({
  //选中的物料级别
  checkLevel: {
    type: Object,
    default:{},
  }, //字段
  //选中的物料
  checkedMaterial: {
    type: Array,
    default:[],
  }, //字段
});

const selectedMaterialName=ref([]);//选中的物料名称数组,进行选中状态判断

const selectName=ref('');//选中返回值
const levels=[];//接收传过来的物料级别
levels.value=props.checkLevel;

const materials=[];//接收传过来的物料编号
materials.value=props.checkedMaterial;

const firstTier=ref('');//选中的第一列物料code
const firstTierName=ref('');//选中的第一列物料名称
const secondTier=ref('');//选中的第二列物料code
const secondTierName=ref('');//选中的第二列物料名称
const thirdTier=ref('');//选中的第三列物料code
const thirdTierName=ref('');//选中的第三列物料名称

//第一级物料列表
const firstData=ref([]);
//第二级物料列表
const secondData=ref([]);
//第三级物料列表
const thirdData=ref([]);

//待选择物料清单列表
const waitData=ref([]);

//选中的物料清单列表
const selectedData=ref([]);

onMounted(() => {
  // console.log(levels.value,'物料级别回显值');
  // console.log(materials.value,'选中物料回显值');

  //一级物料级别、二级物料级别、三级物料级别同时存在才会回显数据
  if(levels.value.firstTier&&levels.value.secondTier&&levels.value.thirdTier){
    firstTier.value=levels.value.firstTier;
    secondTier.value=levels.value.secondTier;
    thirdTier.value=levels.value.thirdTier;
    getFirstList();
    getOtherList(2,levels.value.firstTier);
    getOtherList(3,levels.value.secondTier);
    getMaterialList();
  }else{
    //传过来的数据为空时,则只显示一级物料
    getFirstList();
  }
});
//获取一级物料列表
async function getFirstList(){
  let url = '/materiel/tierLlist/'+1;
  await defHttp.get({ url}, { isTransformResponse: false }).then((res) => {
    if (res.success) {
      firstData.value=res.result;
      //对一级物料列表进行遍历,根据传过来的物料编号,查找对应的物料名称
      for(let i=0;i<firstData.value.length;i++){
        if(firstTier.value==firstData.value[i].value){
          firstTierName.value=firstData.value[i].label
        }
      }

    } else {
      createMessage.error(res.message);
    }
  });
}
//获取其他级别的物料列表
async function getOtherList(level,code){
  let url = '/materiel/tierLlist/'+level;
  let params={
    code:code,
  }
  await defHttp.get({ url,params}, { isTransformResponse: false }).then((res) => {
    if (res.success) {
      if(level==2){
        secondData.value=res.result;
        //对二级物料列表进行遍历,根据传过来的物料编号,查找对应的物料名称
        for(let i=0;i<secondData.value.length;i++){
          if(secondTier.value==secondData.value[i].value){
            secondTierName.value=secondData.value[i].label
          }
        }
      }else if(level==3){
        thirdData.value=res.result;
        //对三级物料列表进行遍历,根据传过来的物料编号,查找对应的物料名称
        for(let i=0;i<thirdData.value.length;i++){
          if(thirdTier.value==thirdData.value[i].value){
            thirdTierName.value=thirdData.value[i].label
          }
        }
      }
      //将一级物料名称、二级物料名称、三级物料名称进行组合,如 一级物料名称/二级物料名称/三级物料名称
      selectName.value=firstTierName.value+'/'+secondTierName.value+'/'+thirdTierName.value;
    } else {
      createMessage.error(res.message);
    }
  });
}

//获取待选中物料
async function getMaterialList(){
  let url = '/materiel/tierLlist/';
  let params={
    firstTier:firstTier.value,
    secondTier:secondTier.value,
    thirdTier:thirdTier.value,
  }
  await defHttp.get({ url,params}, { isTransformResponse: false }).then((res) => {
    if (res.success) {
      waitData.value=res.result;
      //若是传过来的物料编号数组存在,与查到的待选择物料列表进行遍历,获取选中的物料列表,
      if(materials.value){
        for(let i=0;i<waitData.value.length;i++){
          for(let j=0;j<materials.value.length;j++){
            if(materials.value[j]==waitData.value[i].value){
              selectedData.value.push(waitData.value[i])
            }
          }
        }
        // 对获取到的选中物料列表进行遍历,获取选中物料编号列表,用于待选则物料的选中状态判断
        selectedMaterialName.value=selectedData.value.map(item=>{
          return item.value
        })
        let levels={
          firstTier:{value:firstTier.value,label:firstTierName.value},
          secondTier:{value:secondTier.value,label:secondTierName.value},
          thirdTier:{value:thirdTier.value,label:thirdTierName.value},
        }
        console.log(selectedData.value,'selectedData')
        emits('check', selectedData.value,levels); //把选中的物料列表、选中的物料级别传过去
      }
    } else {
      createMessage.error(res.message);
    }
  });
}

//一级物料点击事件
function firstClick(val){
  //一级物料级别存在时,点击一级物料列表项,把二级物料列表、三级物料列表、待选择物料列表、已选择物料列表清空
  if(firstTier.value!=val.value){
    secondData.value=[];
    thirdData.value=[];
    waitData.value=[];
    selectedData.value=[];
    firstTier.value=val.value;//获取此时点击的一级物料名称、一级物料编号
    firstTierName.value=val.label;
    getOtherList(2,val.value);//重新获取此时点击的一级物料编号对应的二级物料列表
  }
}
//二级物料点击事件
function secondClick(val){
  //二级物料级别存在时,点击二级物料列表项,把三级物料列表、待选择物料列表、已选择物料列表清空
  if(secondTier.value!=val.value){
    thirdData.value=[];
    waitData.value=[];
    selectedData.value=[];
    secondTier.value=val.value;//获取此时点击的二级物料名称、二级物料编号
    secondTierName.value=val.label;
    getOtherList(3,val.value)//重新获取此时点击的二级物料编号对应的三级物料列表
  }
}
//三级物料点击事件
function thirdClick(val){
  //三级物料级别存在时,点击三级物料列表项,把待选择物料列表、已选择物料列表清空
  if(thirdTier.value!=val.value){
    selectedData.value=[];
    thirdTier.value=val.value;//获取此时点击的三级物料名称、三级物料编号
    thirdTierName.value=val.label;
    getMaterialList();//重新获取此时点击的一级二级三级物料编号对应的物料清单列表
  }
}

//物料点击
function waitClick(val){
  //对此时点击的待选择物料列表项进行判断,若是不存在已选中物料列表里面,则添加到已选中物料列表中,同时更新已选中物料编号数组
  if(selectedMaterialName.value.includes(val.value)==false){
    waitData.value.map(item=>{
      if(item.value==val.value){
        selectedData.value.push(item);
      }
    })
    selectedMaterialName.value=selectedData.value.map(item=>{
      return item.value
    })
  }else{
  //对此时点击的待选择物料列表项进行判断,若是存在已选中物料列表里面,则遍历查到点击的物料编号在已选中物料列表中的索引,进行删除,同时更新已选中物料编号数组
    selectedData.value.map((item,index)=>{
      if(item.value==val.value){
        selectedData.value.splice(index,1);
      }
    })
    selectedMaterialName.value=selectedData.value.map(item=>{
      return item.value
    })
  }
}
//已选中物料点击
function selectedClick(val){
  //点击已选中物料列表项,遍历查到点击的物料编号在已选中物料列表中的索引,进行删除,同时更新已选中物料编号数组
  selectedData.value.map((item,i)=>{
    if(item.value==val.value){
      selectedData.value.splice(i,1)
    }
  })
  selectedMaterialName.value=selectedData.value.map(item=>{
    return item.value
  })
}
//点击显示弹窗
function inputClick(){
  visible.value=true;
}

const handleCancel = (e) => {
  visible.value = false;
}

const handleOk = (e) => {
  // 点击确定时,把此时选中的物料列表、一级、二级、三级物料传过去
  if(selectedData.value.length>0){
    visible.value = false;
    selectName.value=firstTierName.value+'/'+secondTierName.value+'/'+thirdTierName.value;//返回物料类别
    let levels={
      firstTier:{value:firstTier.value,label:firstTierName.value},
      secondTier:{value:secondTier.value,label:secondTierName.value},
      thirdTier:{value:thirdTier.value,label:thirdTierName.value},
    }
    emits('check', selectedData.value,levels); //把列表选中的值传过去
  }else{
    createMessage.warning('至少选中一个物料~');
  }
};


</script>
<style lang="less" scoped>
.flex_between{
  display:flex;
  justify-content:center;
  text-align: center;
}
.warp{
  margin:10px;
  border:1px solid #ddd;
  height:auto;
  border-top:none;
  border-left:none;
  box-sizing: border-box;
  .flex_7{
    // flex:7;
    width:650px;
    border:1px solid #ddd;
    height:100%;
    border-bottom:none;
  }
  .line30{
    border-bottom:1px solid #ddd;
    height:30px;
    line-height:30px;
  }
  .borderRight{
    border-right:1px solid #ddd;
    width:100%;
  }
  .table_title{
    font-size: 16px;
    color: #333;
  }
  .borderBottom{
    width:100%;
    border-bottom:1px solid #ddd;
  }
  .max_height{
    max-height: 500px;
    overflow-y: scroll;
  }
  .table_width200{
    width:200px;
  }
  .table_width150{
    width:150px;
  }
  .flex_3{
    // flex:3;
    width:200px;
    border-top:1px solid #ddd;
    height:100%;
  }
}
.list_style{
  cursor: pointer;
}
.list_active{
  color: rgb(24, 144, 255);
}
.list_style:hover{
  color: #409eff;
}
</style>

引用组件

<template>
 
    <a-card :bordered="false">
      <a-tabs defaultActiveKey="4">
        <a-tab-pane tab="物料名称组件" key="4">
          <a-form :label-col="{style:{width:'150px'} }">
            <a-row :gutter="24">
              <a-col :span="8">
                <a-form-item label="供货工艺类别:">
                  <material-type :checkedMaterial='selectedMaterial' :checkLevel='levels' @check='getMaterialLevel'></material-type>
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="供货产品名称:">
                  <a-input v-model:value="selectedMaterialNames" disabled></a-input>
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>
        </a-tab-pane>
      </a-tabs>
    </a-card>
</template>

<script setup>
import {onMounted, ref,defineEmits,defineProps, onBeforeUnmount, watch, nextTick} from 'vue';
import materialType from '/@/components/materialType.vue';

onMounted(()=>{
  getMaterialLevel();
})

//物料选择调用
const levels=ref(
  {
    firstTier:'A',
    secondTier:'A.2',
    thirdTier:'A.2.1',
  }
)

const selectedMaterial=ref(
  [
    '02.10.MSP120H-11-01',
    '02.10.MSP120H-30-01',
  ]
)

const selectedMaterialNames=ref('');//选中的产品名称
const checkedMaterial=ref([]);//回显的数据
let materielData=[];
function getMaterialLevel(materials,levels){
  if(materials){
    materielData=materials.map(item=>{
      return item.label
    });
    selectedMaterialNames.value=materielData.toString();
  }
  // console.log(selectedMaterialNames.value,'选中物料名称')
}
//物料选择调用
</script>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderdwy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值