vue3项目 使用 element-plus 中 el-collapse 折叠面板

时间:2024-04-23 07:13:54

最近接触拉了一个项目,使用到 element-plus 中 el-collapse 折叠面板,发现在使用中利用高官网多多少少的会出现问题。
(1.直接默认一个展开值,发现时显时不显
2 . 数据渲染问题,接口请求了,页面数据不更新
3 样式问题,自定义表头title等等)
我们的数据结构是双数组,如果你和我一样直接copy, 如果是一个对象数组或者数组吧,只需把外层的数组转化即可
在这里插入图片描述

效果图 : 当点击 了查看按钮时,弹框出现,且默认展开第一个数据,且每次的展开或者收起都有对应的样式,可见下图左侧的图样,
我这里还用到了 el-steps ,最外层的 是自己写的样式,因为我一个页面中使用了两次el-steps ,发现样式会有干扰。所以我在最外层的el-steps是自己写的div标签。

注意 的是我们使用 官网说明的 const activeName = ref([]) 数组类型 ,且里面的值使用字符串类型。
当 弹框出现时,调用接口进行处理赋值 activeName,并转成 toString() 字符串,然后默认展开第一项
	activeName.value.push(index.toString())
    activeName.value = ['0']
    在进行处理每个item之间的高和选中样式。
    最后在处理点击@change 的事件
    
    // 处理在展开折叠状态
	const handleCollapseChange = (val: any) => {
	  // console.log(val, 'val');
	  PurchaseInfo.forEach((item:any, index:any)=>{
	    if(val){
	      if(val === index.toString()){
	        item.flagActive = true
	        item.height = myCollapseRef.value.$el.clientHeight + 20
	      } else{
	        item.flagActive = false
	        item.height = 38
	      }
	    }else{
	      item.flagActive = false
	      item.height = 38
	    }
	  })
	  // console.log(PurchaseInfo, 'PurchaseInfo')
	}

在这里插入图片描述
上代码了。

<ProcessViewDialog
  v-model:value="dialogFormVisible"
  :projectDeviceId="projectDeviceId"
/>

自己 引入组件

<template>
  <div>
    <zmjDialog
      v-model="show"
      width="460"
      @opened="init"
      title="查看所有设备"
      center
    > 
      <div style="display:flex; width: 460px">
        <div class="el-dialog-div">
          <div class="el-dialog_divleft">
            <div class=divleftlast v-for="(el, index) in PurchaseInfo" :key="index">
              <p :class="el.flagActive ? 'arrdata1Active' : 'arrdata1'"></p>
              <p :style="{width: 2 + 'px', height: el.height + 'px', background: '#E8F0FF', borderRadius: '0px 0px 0px 0px', marginLeft: '8px'}"></p>
            </div>
          </div>
          <el-collapse
            class="el-collapse-parent"
            v-model="activeName"
            accordion
            @change="handleCollapseChange"
            ref="myCollapseRef"
          >
            <el-collapse-item
              v-for="(item, index) in PurchaseInfo"
              :key="index"
              :name="index.toString()"
              style="margin-bottom: 10px;"
              ref="itemHeight"
            >
              <template #title>
                <div :class="item.flagActive ? 'headerRightTrue' : 'headerRightFlase'">
                  <span class="spanFalse"></span>
                  <div class="itemApproveTimeFalse">
                    {{ item.approveTime }}
                  </div>
                  <div class="top-right">
                    <div> {{item.operatorName}} <span v-if="item?.nodeId"> ({{item?.nodeId == 120 ? '方案' : ( item?.nodeId == 130 ? '商务活动' : (item?.nodeId == 140 ? '配套' : '' ))}}) </span> </div>
                    <span :class="item.flagActive ? 'headerRightspan1' : 'headerRightspan2'">{{ activeName.includes(index.toString()) ? '收起' : '展开' }}</span>
                  </div>
                </div>
              </template>
              <div class="contntDiv">
                <div class="contntDiv-1">
                  <div class="contntDiv-1">
                    <span class="contntDiv-1-span"> {{item.model}} </span>
                    <span class="contntDiv-2-span"> {{ item?.supportLabel === 1 ? '标准架型' : (item?.supportLabel === 3 ? '模块架型' : '非标架型')}} </span>
                  </div>
                  <div class="contntDiv-1-d"> {{ item?.deviceCount}}架 </div>
                </div>
                <div class="line"></div>
                <div>
                  <div class="contntDiv-item-left"> 片区 </div>
                  <div class="contntDiv-item-right"> {{ item?.areaName }} </div>
                </div>
                <div>
                  <div class="contntDiv-item-left"> 支架类型 </div>
                  <div class="contntDiv-item-right"> {{ GET_SUPPORT_TYPE(item?.firstDeviceType) }} - {{ GET_SUPPORT_SECOND_TYPE_NAME(item?.secondDeviceType) }}</div>
                </div>
                <div>
                  <div class="contntDiv-item-left"> 图号 </div>
                  <div class="contntDiv-item-right"> {{item?.standardGroupNo }} </div>
                </div>
                <div>
                  <div class="contntDiv-item-left"> 单架重量 </div>
                  <div class="contntDiv-item-right"> {{ item?.singleWeight}}吨 </div>
                </div> 
                <div>
                  <div class="contntDiv-item-left"> 支架特征代号 </div>
                  <div class="contntDiv-item-right"> {{ joinSupportFeatureModel }} </div>
                </div>
                <div class="contntDiv-item-right-bottom" v-if="item?.supportFeatureModel && item?.supportFeatureModel?.length > 0">
                  *支架产品型号{{ item?.supportProductModel}}
                </div>
              </div>
              <div class="box-approve" v-if="item?.flowApproveDtoList?.length>0">
                <el-steps direction="vertical" :active="1" align-center>
                  <el-step v-for="(v, i) in item?.flowApproveDtoList" class="my-text" :key="i">
                    <template #icon>
                      <div class="titleDiv">
                        <div class="time">{{ v.updateTime }}</div>
                      </div>
                    </template>
                    <template #title>
                      <div class="step-icon"></div>
                    </template>
                    <template #description>
                      <div class="descriptionDiv">
                        <div style="color: #707070; font-size: 14px">
                        <span class="" style="color: #3076fe">{{ v.approveUserName }}</span>
                        <!-- approveType  1 提交 2 审批 status 1 未审批 2  审批通过 3 驳回 -->
                        <span v-if="v.approveType == 1 && v.status == 2 && isLastElement(item?.flowApproveDtoList, i)" style="color: rgba(0, 0, 0, 0.56)"><span style="color: #262626">提交审批</span></span>
                        <span v-else>
                          <span v-if="v.approveType == 1 && v.status == 2" style="color: rgba(0, 0, 0, 0.56)"><span style="color: #262626">再次提交审批</span></span>
                          <span v-if="v.approveType == 1 && v.status == 3" style="color: rgba(0, 0, 0, 0.56)"><span style="color: #ffb236">审批驳回</span></span>
                          <span v-if="v.approveType == 2 && v.status == 2">
                            <span style="color: #63af17">审批通过</span>
                          </span>
                          <span v-if="v.approveType == 2 && v.status == 3">
                            将<span style="color: #ffb236">审批驳回</span>
                          </span>
                        </span>
                        </div>
                        <div v-if="(v.approveType == 1 || v.approveType == 2) && v.status == 3" class="reject-box">
                          <div class="reject-item-1">
                            <div>驳回原因</div>
                            <div>{{ v.rejectReason }}</div>
                          </div>
                        </div>
                      </div>
                      
                    </template>
                  </el-step>
                </el-steps>
              </div>
            </el-collapse-item>
          </el-collapse>
        </div>
      </div>
      
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="show = false">返回</el-button>
        </div>
      </template>
    </zmjDialog>
  </div>
</template>


<script setup lang="ts">
import { recordLog } from '@/api/project/device' // 接口替换为完成
import { GET_SUPPORT_TYPE, GET_SUPPORT_SECOND_TYPE_NAME } from './config'
const props = defineProps({
  dialogFormVisible: Boolean,
  value: Boolean,
  projectDeviceId: { type: Number, default: null }, // 业务id
})
// const activeName = ref()
const activeName = ref([])
const emit = defineEmits(['update:value', 'exit'])
// 添加页面弹出标识
let show = computed({
  get() {
    return props.value
  },
  set(val: any) {
    emit('update:value', val)
  }
})
let PurchaseInfo:any = reactive([])
let joinSupportFeatureModel:any = ref('')

// 判断数组的最后一个
const isLastElement = (array:any, index:any) => {
  return index === array.length - 1
}

const init = async () => {
  try {
    const res: any = await recordLog({ deviceId: props.projectDeviceId })
    PurchaseInfo = res.data
    let arr:any = []
    activeName.value = []
    PurchaseInfo.forEach((item:any, index:any)=>{
      activeName.value.push(index.toString())
      activeName.value = ['0']
      if(index.toString() === activeName.value[0]){
        item.height = myCollapseRef.value.$el.clientHeight + 20
        item.flagActive = true
      }else{
        item.height = 38
        item.flagActive = false
      }
      item?.supportFeatureModel?.map((v:any)=>{
        if(v==='A1'){
          arr.push('A类支架')
        } else if(v ==='Q'){
          arr.push('大倾角')
        }else if(v ==='D'){
          arr.push('电液控')
        }else if(v ==='A'){
          arr.push('大侧帮支架左架')
        }else if(v ==='B'){
          arr.push('大侧帮支架右架')
        }else{
          arr = []
        }
      })
    })
    // console.log(PurchaseInfo, 'PurchaseInfo-loading---',)
    joinSupportFeatureModel.value = arr.join('、')
  } catch (err) {
    console.log(err.message)
  }
}

let myCollapseRef = ref()
const itemHeight = ref(null)
// 监听折叠状态
const handleCollapseChange = (val: any) => {
  // console.log(val, 'val');
  PurchaseInfo.forEach((item:any, index:any)=>{
    if(val){
      if(val === index.toString()){
        item.flagActive = true
        item.height = myCollapseRef.value.$el.clientHeight + 20
      } else{
        item.flagActive = false
        item.height = 38
      }
    }else{
      item.flagActive = false
      item.height = 38
    }
  })
  // console.log(PurchaseInfo, 'PurchaseInfo')
}
</script>

<style lang="scss" scoped>
.el-dialog_divleft{
  width: 10px;
  // margin-left: 10px;
  margin-top:28px;
  display: flex;
  flex-wrap: wrap;
  height: 38px;
}
/* 选择最后一个div中的第二个p标签,并应用样式 */
.divleftlast:last-child p:last-child {
  display: none;
}
.arrdata1{
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid #3076fe;
  // margin-top: 15px;
  margin-left: 5px;
}
.arrdata1Active{
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid #3076fe;
  // margin-top: 15px;
  margin-left: 5px;
  background: #3076fe;
}
.el-dialog-div {
  // width: 395px;
  width: 100%;
  margin-left: 20px; // 20px
  height: 50vh;
  overflow-x: hidden;
  display: flex;
}

.page-content {
  padding: 24px 44px;
  .device-group {
    &:not(:first-child) {
      margin-top: 12px;
    }
  }
  :deep(.el-descriptions.zmj-descriptions) {
    .el-descriptions__header {
      margin-top: 12px;
      margin-bottom: 8px;
      .el-descriptions__title {
        font-weight: 400;
      }
    }

    .el-descriptions__cell {
      padding: 10px 12px;
      color: #262626;
    }
    .el-descriptions__label {
      padding: 10px 12px;
      background-color: #fafafa;
      color: #707070;
    }
  }
}
.page-empty {
  height: 100%;
}
.color-centent {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #3076fe;
}
/* 如果您想要在展开的el-collapse-item上添加特殊样式,可以使用深度选择器 */
.el-collapse {
  :deep(.el-collapse-item__content) {
    border: 1px solid #3076FE;
    padding-bottom: 0px; /* 根据需要调整padding值 */
    width: 384px;
  }
}

.el-collapse-parent{
  margin-top: 10px;
  border: none;
  width:395px;
  margin-left: 10px;
  :deep(.el-collapse-item__header){
    background: #3076FE;
    border-radius: 4px 4px 0px 0px;
    width: 384px;
    height: 39px
  }
}
:deep(.el-collapse-item__arrow){
  display:none;
}
.headerRightTrue{
  width: 395px;
  height: 38px;
  background: #3076FE;
  border-radius: 4px 4px 0px 0px;
  display: flex;
  justify-content: space-between;
  padding: 10px;
  color:#fff;
  font-size: 14px;
  line-height: 20px;
  top: -20px;
  .top-right{
    width: 160px;
    display: flex;
    // justify-content: space-around;
    justify-content: space-between;
    font-size: 12px;
    .headerRightspan1{
      color:#fff;
    }
  }
}
.spanFalse{
    width: 4px;
    height: 12px;
    background: #3076FE;
    border-radius: 0px 0px 0px 0px;
    margin-top: 4px;
  }
  .itemApproveTimeFalse{
    margin-left: -55px;
  }
.headerRightFlase{
  background: #F3F8FF;
  width: 395px;
  height: 38px;
  border-radius: 4px 4px 0px 0px;
  display: flex;
  justify-content: space-between;
  padding: 10px;
  color: #666666;
  font-size: 14px;
  line-height: 20px;
  top: -20px;
  border: 1px solid #3076FE;
  .top-right{
    width: 160px;
    display: flex;
    // justify-content: space-around;
    justify-content: space-between;
    font-size: 12px;
    .headerRightspan2{
      color: #3076FE
    }
  }
}
.contntDiv{
  width: 355px;
  height: 200px;
  background: #F3F8FF;
  border-radius: 4px 4px 4px 4px;
  border: 1px solid #EEEEEE;
  padding: 10px;
  // margin: 14px;
  margin: 8px 14px;
  >div{
    display: flex;
    justify-content: space-between;
    margin-top: 5px;
  }
  .contntDiv-1-span{
    width: 116px;
    height: 20px;
    font-size: 14px;
    color: #262626;
    line-height: 0px;
    text-align: left;
  }
  .contntDiv-2-span{
    font-size: 10px;
    color: #1890FF;
    text-align: center;
    height: 16px;
    background: #E3F2FF;
    border-radius: 2px 2px 2px 2px;
    margin-left: 14px;
  }
  .contntDiv-1-d{
    height: 17px;
    font-size: 12px;
    color: #A3A3A3;
  }
  .line{
    background: #F3F8FF;
    border: 1px dotted #A3A3A3;
  }
  .contntDiv-item-left{
    // width: 100px;
    height: 18px;
    font-size: 13px;
    color: #A3A3A3;
  }
  .contntDiv-item-right{
    // width: 112px;
    height: 18px;
    font-size: 13px;
    color: #262626;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .contntDiv-item-right-bottom{
    height: 18px; 
    font-size: 13px;
    color: #262626;
    text-align: left;
    display: flex;
    justify-content: flex-end;
  }
}

.box-approve {
  min-height: 130px;
  max-height: calc(100% - 82px);
  overflow: auto;
  margin-top: -5px;
}
.step-icon {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #A3A3A3;
  border: 1px solid #A3A3A3;
  margin-left: 50px;
  // margin-top: 0px;
}
.titleDiv{
  display: flex;
  width: 155px;
  .time {
    color: #c2c2c2;
    font-size: 12px;
    margin-left: 90px;
    width: 100px;
  }
}

:deep(.el-steps) {
  height: 100%;
}
:deep(.el-step__line){
  background: #E8F0FF;
  border: 1px dotted #A3A3A3;
  margin-left: 87px;
  margin-top: 20px;
  height: calc(100% - 20px);
}
:deep(.el-step__main) {
  padding: 8px 8px 9px;
  // background-color: #f1f6ff;
  min-height: 58px;
  box-sizing: border-box;
  margin-bottom: 12px;
  .el-step__description {
    font-size: 14px;
  }
}
:deep(.el-step__title){
  margin-left: 11px;
  color: #e0e0e0;
}
// :deep(.el-step__head){
//   // margin-left:110px;
// }
.reject-box {
  font-size: 12px;
  color: #a3a3a3;
  .reject-item-1 {
    display: flex;
    & > div:nth-child(1) {
      flex-shrink: 0;
    }
    & > div:nth-child(2) {
      word-break: break-word;
      width: 100%;
    }
  }
}
.descriptionDiv{
  height: 100%;
  width: 264px;
  margin-left: 76px;
  margin-top: -20px;
}
</style>

完成,请指教
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述