meNotClearCode

161 阅读5分钟

下载日志

const downLoading = ref(false)
const downFile = (row:any)=>{
 downLoading.value = true
 const url = `/gics/algrun?appId=${row.appId}`
 utils.http.post(url).then((res:any)=>{
     if(typeof res !== 'object'){
     const form = document.createElement('form')
     form.methods = 'post'
     form.action = `/gics/algrun/getApplactionLogs?appId=${row.appId}`
     form.target = '_blank'
     const btn = document.createElement('input')
     btn.type='submit'
     form.append(btn)
     document.getElementByTagName('body')[0].appendChild(form)
     form.submit()
     document.getElementByTagName('body')[0].removeChild(form)
      } else {
      alert('有错误')
      }
   downLoading.value = false
  })
}

vue3别人的设参与用参

  • list/index.tsx
import { defineComponent, defineAsyncComponet, ref, onMounted, watch} from 'vue'
import {useRoute} from 'vue-router'
export default defineComponent({
name:'List'
components:{
 logicModel:defineAsyncComponent(()=>import('./components/logicModel')),
 searchForm:defineAsyncComponent(()=>import('./components/searchForm')),
 instanceModel:defineAsyncComponent(()=>import('./componnents/instanceModel'))
 },
 setup() {
 const route = useRoute()
 const activeTab = ref('列表1') //公共组件用与切换页面使用
 const logicModelRef: any = ref(null)
 const instanceModelRef: any = ref(null)
 }
 watch(
 () => route.query
 () => {}
 )
 onMounted(()=>{})
 return ()=>{
  //引用封装的公共组件
  return(
  <box title=['列表1', '列表2'] 
  isTab 
  onTabClick={(type:string)=>{activeTab.value = type}}
  v-slots ={{
   body:()=>{
    return(
          <div class="">
           <searchForm type={activeTab.value} BtnHandle={(form:any)=>{
               if(activeTab.value === '列表1'){
                //拿到组件实例的方法
                logicModel.value.getList(form)
               }else{
                instanceModel.value.getList(form)
               }
           }}/>
           {activeTab.value === 
           '列表1'?(<logicModel ref={logicModelRef}>):(<instanceModel 
           ref={instanceModelRef}>)}
          </div>
     )
    }
   }}
  /> 
  )
 }
 }
})
  • list/components/intanceModel.tsx
import { defineComponent, onMounted, reactive, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
let getList = {} as any
export default defineComponent({
 name:'intanceModel',
 setup(){
  const router = useRouter()
  const route = useRoute()
  //用于表格操作的多个图标点击跳转
  const button = reactive([
  {title:'',type:'',class:''},{title:'',type:'',class:''}
  ] as any)
  const modelList = reactive({loading:false,list:[]})
   //用于分页器的初始参数
 const page=reactive({totalCount:0,pageNum:1,pageSize} as any)
 watch(
 () => route.query,
 () => { getList() }
 )
 onMounted(()=>{
  getList()
 }
 //获取列表数据
 getList=(form={} as any)=>{
  const formData = new FormData
  Object.keys(form).forEach((item:any)=>{
  if(form[item] && form[item].trim()){
   formData.append(item, form[item].trim())
  }
  })
  forData.append(pageNum,page.pageNum.toString())
  forData.append(pageSize,page.pageSize.toString())
  utils.htttp.post('/search', formData).then((res:any)=>{
   if(res.code){
    model.list = res.data
    page.totalCount = res.data.totalCount
   }
  })
  .catch(()=>{})
 }
 //当分页器发生变化时的回调
 const pageChange = (pageNum:number, pageSize:number):void=>{
   page.pageNum = pageNum
   page.pageSize = pageSize
   getList()
  }
  //列表按钮点击
  const btnHandle =(index:number, data:any, type:string):void=>{
   const {dataId,dataName} = data
   const {deviceName, topicName} = data
   localStroage.setItem('deviceLogicPath', data.logicPath)
   router.push({
   path:type,
   query:{
    deviceName:deviceName,
    topicName:topicName,
    dataId:dataId,
    dataName:dataName
   }
   })
  }
  return()=>{
   return(
    <>
     <el-table></el-table>
     <el-pageination></el-pageination>
    </>
   )
  }
 },
   created(){
   const ts:any = this
   ts.getList = getList
   }
 })
  • list/components/searchForm.tsx
import {defineComponent, ref, onMounted, reactive, watch, computed } from 'vue'
import { ElNotification } from 'element-plus'
export default defineComponent({
name:'ModelList',
components:{},
props:{
 type:{
  type:String,
  default:''
 }
},
emits:['btnHandle'],
setup(props, {emit}){
 const siteList = ref([] as any)
 const form = reactive({
  modelName:'',
  directionId:'',
  topicName:'',
  deviceType:'',
  deviceManufactor:'',
  siteId:'',
  physicPath:'',
  logicPath:''
  }as any)
  const researchTopic = computed(()=>{
   const name = directionList.value.find((item:any)=>item.id === form.directionId)?.name || ''
   return name === '全部'?"":name
  })
  watch(
  () => props.type,
  () => { clearForm() }
  )
  onMounted({
   getModelAttrList()
   getDirectionList()
   getSiteList()
  })
  //查询
  const search = () => {
   const params = {} any
   Object.keys(form).forEach((key:any)=>{
    if(form[key].trim() && key != 'directionId'){
     params[key] = from[key].trim()
    }
   })
   if(props.type === '逻辑模型列表' && researchTopic.value){
    params.researchTopic = researchTopic.value
   }
   }
   //清除form
   const clearForm = () =>{
    Object.keys(form).forEach(()=>{
     form[item] = ''
    })
    }
   //获取列表
   const getSiteList = () =>{
     const userName = utils.cookies.get('userName') || 'avatar'
     const url = `/deviceObject/service/site/getSiteByUsername?username=${userName}`
     utils.http.get(url,'',{ needBaseUrl:false }).then((d:any)=>{
      if(d.code === 200 && d.data.length){
       siteList.value = [{
        siteName:'全部',
        id:''
       }, ...d.data]
      }
     })
    }
   const modelAttrList = ref([] as any)
   //获取列表
   const getModelAttrList = () =>{
    const url = '/analysis/getAllAnalModelAttr'
    utils.http.post(url).then((res:any)=>{
     if(!res.code){
      modelAttrList.value = [
      {modelAttrName: '全部',modelAttrId:''},
      ...res.data.map((item:any)=>{
       return{
        modelAttrName: item.modelAttrName
        modelAttrId: item.modelAttrName
       }
      })
      ]
     }
    })
   }
   const formRef:any = ref(null)
   const showDeviceList = ref(false)
   //获取列表
   const getDeviceList = () =>{
    const url = '/service/publish/logicDevice?page=1&limit=1'
    utils.http.get(url,null,{needBaseUrl:false}).then((d:any)=>{
     if(d.code === 200){
      if(d.data.length){
       getTreeNode(d.data[0].id)
      }
     }
    })
   }
   const tree = ref(null)
   const loading = ref(false)
   const treeList = reactive({ value: []} as any)
   const getTreeNode = (templatedId: string) =>{
    const url = `/service?templateId=${templateId}`
    utils.http.get(url, null,{needBaseUrl:false}).then((d:any)=>{
     if(d.code === 200){
      tree.list = d.data
      loading.value = false
     }
    })
   }
   let deviceNode = reactive({} as any)
   const getNodeValue = (node: any)=>{
    deviceNode = node
   }
   const confirmSelectDevice = () =>{
    if(!deviceNode){
     ElNotification({
      type:'error',
      message:'请选择'
     })
     return
    }
    form.logicPath = deviceNode.name
    getDeviceTypeList()
    showDeviceList.value = false
   }
   //获取类别
   const deviceTypeList  = ref([] as any)
   const getDeviceTypeList = () => {
    const url = `service/device?logicDevice=${encodeURLComponent(form.logicPath)}`
    utils.http.get(url,null,{needBaseUrl: false}).then((d:any)=>{
     if(d.code === 200){
      const dataList = d.data
      deviceTypeList.value = dataList
     }
    })
   }
   const input = ref('')
   const manufactorList = ref([] as any)
   const getDeviceManufactor = () =>{
    const url = '/deviceObj/service=${encodeURLComponent(form.logicPath)}&deviceType=${form.devicType}'
    utils.http.get(url, null,{needBaseUrl:false})
    .then((d:any)=.{if(d.code === 200){ const resList = d.data manufactorList.value = resList}})
   }
   watch(()=>{}
   ()=>{
    if(form.deviceType){
     getDeviceManufactor()
     }
   }
   )
   const directionList = ref([] as any)
   const topicAllList = ref([] as any)
   const topicList = ref([] as any)
   const getDirectionList = () => {
    const url='/analysis?id=0003'
    utils.http.post(url).then((res:any)=>{
     if(!res.statusCode && res.data.length){
      const dataList = res.data
      directionList.value = [{ name:'全部', id:''}, ...dataList] as any
      const nextList = [] as any
      const preList = [] as any
      for(let i=0; i<dataList.length; i++){
       for(let j=0; j<dataList[i].child.length; j++){
         if(j<2){
           preList.push(dataList[i].child[j])
        }else{
           nextList.push(dataList[i].child[j])
        }
       }
      }
      topicAllList.value = [...preList, ...nextList].map((item:any)=>{
       return {
        name:item.name,
        id:item.name,
        parent:item.parent
       }
      })
      getTopicList()
     }
    })
   }
   const getTopicList = () => {
    let list = topicAllList.value as any
    if(form.directionId) {
     list = topicAllList.value.filter((item:any)=>
      item.parent === form.directionId
     )
     const isCurrent = list.some((item:any)=>item.id === form.topicName)
     if(!isCurrent){
      form.topicName = ''
     }
    }
    topicList.value = [{name:'全部',id:''}, ...list] as any
   }
   const unitList = ref([] as any)
   const changeSite = () => {
    if(!form.siteId){
        const changeSite = () => {
      if (!form.siteId) {
        unitList.value = []
        form.physicPath = ''
        return
      }
      const url = `/deviceObject/service/device/getSubDevice?siteId=${form.siteId}&id=`
      utils.http.get(url, '', { needBaseUrl: false }).then((d: any) => {
        if (d.code == 200 && d.data.length) {
          unitList.value = [
            {
              name: '全部',
              id: ''
            },
            ...d.data.map((item: any) => {
              return {
                name: item.name,
                id: item.name
              }
            })
          ]
        }
      })
    }
    return () => {
      return (
        <>
          <el-form ref={formRef} inline={true}>
            <el-form-item label="模型名称">
              <el-input
                clearable
                placeholder="请输入模型名称"
                vModel={form.modelName}
              />
            </el-form-item>
            <el-form-item label="电站" v-show={props.type != '逻辑模型列表'}>
              <el-select
                v-model={form.siteId}
                placeholder="全部"
                clearable
                onChange={changeSite}
              >
                {siteList.value.map((item: any) => {
                  return (
                    <el-option
                      label={item.siteName}
                      value={item.id}
                    ></el-option>
                  )
                })}
              </el-select>
            </el-form-item>
            <el-form-item label="机组号" v-show={props.type != '逻辑模型列表'}>
              <el-select v-model={form.physicPath} placeholder="全部" clearable>
                {unitList.value.map((item: any) => {
                  return (
                    <el-option label={item.name} value={item.name}></el-option>
                  )
                })}
              </el-select>
            </el-form-item>
            <el-form-item
              label="应用方向"
              v-show={props.type == '逻辑模型列表'}
            >

              <el-select
                v-model={form.directionId}
                placeholder="全部"
                onChange={getTopicList}
                clearable
              >
                {directionList.value.map((item: any) => {
                  return (
                    <el-option label={item.name} value={item.id}></el-option>
                  )
                })}
              </el-select>
            </el-form-item>
            <el-form-item
              label="研究专题"
              v-show={props.type == '逻辑模型列表'}
            >
              <el-select v-model={form.topicName} placeholder="全部" clearable>
                {topicList.value.map((item: any) => {
                  return (
                    <el-option label={item.name} value={item.id}></el-option>
                  )
                })}
              </el-select>
            </el-form-item>
            <el-form-item label="逻辑设备">
              {/* <el-input
                clearable
                placeholder="请输入模型名称"
                vModel={form.logicPath}
              /> */}
              <el-input
                clearable
                ref={input}
                placeholder="请选择逻辑设备"
                onFocus={() => {
                  deviceNode = null
                  showDeviceList.value = true
                  formRef.value.$el[5].blur()
                }}
                vModel={form.logicPath}
              />
            </el-form-item>
            {/* <el-form-item label="分析类别" clearable>
              <el-select
                v-model={form.modelAttr}
                clearable
                placeholder="请选择分析类别"
              >
                {modelAttrList.value.map((item: any) => {
                  return (
                    <el-option
                      label={item.modelAttrName}
                      value={item.modelAttrId}
                    />
                  )
                })}
              </el-select>
            </el-form-item> */}
            {/* <el-form-item
              label="机组类别"
              v-show={props.type == '逻辑模型列表'}
            >
              <el-select
                clearable
                v-model={form.deviceType}
                placeholder="请选择机组类别"
              >
                {deviceTypeList.value.map((item: any) => {
                  return <el-option label={item} value={item} />
                })}
              </el-select>
            </el-form-item> */}
            {/* <el-form-item
              label="制造厂商"
              v-show={props.type == '逻辑模型列表'}
            >
              <el-input
                clearable
                placeholder="请输入模型名称"
                vModel={form.deviceManufactor}
              />
              <el-select
                v-model={form.deviceManufactor}
                placeholder="请选择制造厂商"
                clearable
              >
                {manufactorList.value.map((item: any) => {
                  return <el-option label={item} value={item} />
                })}
              </el-select>
            </el-form-item> */}
            <el-form-item>
              <el-button
                type="primary"
                onClick={() => {
                  search()
                }}
              >
                查询
              </el-button>
            </el-form-item>
          </el-form>
          <el-dialog
            title="查看逻辑设备"
            v-model={showDeviceList.value}
            width="30%"
            // destroy-on-close
            close-on-click-modal={false}
            close-on-press-escape={false}
            open={getDeviceList()}
          >

            <div
              style={{ marginTop: '20px', height: '300px', overflow: 'auto' }}
              v-loading={loading.value}
              element-loading-text="数据加载中"
            >
              <xtree
                ref={tree}
                data={treeList.value}
                isFormatIcon={true}
                defaultProp={{
                  id: 'id',
                  label: 'name',
                  children: 'dopTemplateDetailList'
                }}
                showFilter={true}
                onNodeClick={getNodeValue}
              ></xtree>
            </div>
            <span class="dialog-footer">
              <el-button
                type="primary"
                onClick={() => {
                  confirmSelectDevice()
                }}
              >
                确 定
              </el-button>
              <el-button
                onClick={() => {
                  showDeviceList.value = false
                }}
              >
                取 消
              </el-button>
            </span>
          </el-dialog>
        </>
      )
    }
    }
   }
   
  }
})

封装混入函数可以将数组对象转化为对象的方法或将2个参数连接成对象的参数的方法

const runModelList = [
 {
  label:'持续',
  value:'run_continue'
 },{
  label:'固定',
  value:'run'
 },{
 label:'执行',
 value:'run_plan'
 }
]
cosnt arrToObj = (arr:Array<any>)=>{
 const obj = {} any
 arr.forEach((item:any)=>{
  obj[item.value] = item.label
 })
 return obj  //输出为{run:固定...}
}
const runModelObj = arrToObj(runModelList)
export{runModelObj,runModelList}
 let sortField = reactive({} as any)
 const sortChange = ({prop,order}:any) =>{
  sortField[prop] = order //可以拿到sortField.prop的值用作判断条件并且改变值
}

VUE3结合tsx写echarts

//折线图
import { defineComponent,ref,watch} from 'vue'
import * as echarts from 'echarts'
export default defineComponent({
 name:'Line',
 props:{
   data:{
     type:Array,
     default:()=>{return []}
   },
   station:{
     type:Object,
     default:()=>{return {}}
   }
 },
 setup(props){
   const chartRef=ref(null)    //个人理解获取dom元素
   const myEchart = ref(null as any) //初始化及调用echarts
   watch(
    () => props.data,
    () => {
       initEchart()
       setEchartOption()
    }
   )
   //echart初始化
   const initEchart = () => {
     if(!myEchart.value) {
       const dom:any = chartRef.value
       myEchart.value = echarts.init(dom)
       myEchart.value.on('click',(params:any)=>{
        emit('chartClick',params)
       })
     }
   }
   const setEchartOption = () => {
      const dataList = props.data
      const station = props.station
      const timeList = dataList.map((item:any) => new Date(item.time).format())
      const prvData = dataList.map((item:any) => item.prv)
      const targetData = dataList.map((item:any) => item.target)
      const option = {
        tooltip:{}, //配置没有作用
        grid:{}, //整体布局
        legend:{}, //图例设置
        xAxis:{
         data:timeList,
         axisLabel:{
           color:'#555',
           fontSize:14,
           formatter: function(time:string){
            return new Date(time).formatter('YYYY/MM/DD')
           }
         }
        },
        yAxis:[{
         type:'value',
         scale:true
        }],
        series:[
        {
         name:`${station['xxx']}xx`,
         data:prvData
        },
        {
         name:station['xxx'],
         data:targetData
        }
        ]
      }
      myEchart.value.clear() //点击需要传入参数需要清除前一个表格
      myEchart.value.setOption(option)
      myEchart.value.on('click',(params:any)=>{
        emit('chartClick',params)
      })
   }
   return () => {
    return(
      <div id="myEchart" ref={chartRef} style="width:100%;height:100%"></div>
    )
   }
 }
})

选取某个片段

body:()=>{
 return (
  <div style="100%">
   //引入的组件
   <viewSectionGraph ref={viewSectoinGraphRef} onChartBrush={(range:any)=>                {selectedSectionList.value = range}}/>
  </div>
 )
}
//封装组件
import {defineComponent,ref,ComponentPublicInstance,nextTick,reactive} from 'vue'
import * as echarts from 'echarts'
let init:any = {}
export default defineComponent({
  name:'ViewSectionGraph',
  props:{},
  emits:['getSectionTime','chartBrush'],
  setup(props:any, {emit}){
   const loading = ref(false)
   const stationDataList = ref([])
   let sectionData = reactive({} as any)
   init = (data:any):void => {
    sectionData = data
    if(data.stationList.length){
     getStationDataList()
    }else{
     initEcharts()
     }
    }
    const chartRef = ref(<ComponentPublicInstance<HTMLCanvasElement>>)()
    const getStationDataList = ():void =>{
     const url = '/xxxxxxxxxx/xxxxxxx'
     const formData - new FormData()
     const codes = sectionData.stationList.map((item:any)=>item.stationId).join(',')
     formData.append('codes',codes)
     formData.append('startTime',new Date(sectionData.startTime).getTime().toString())
     formData.append('endTime',new Date(sectionData.endTime).getTime().toString())
     formData.append('sampled', '-1000')
     formData.append('fillPoint', '-1')
     loading.value = true
     utils.http.post(url,formData).then((res:any)=>{
      loading.value = false
      stationDataList.value = res.RTDataSets
      initEcharts()
      }).catch(()=>{
       loading.value = false
      })
     }
     const initEcharts = ():void =>{
      const stationList:any = sectonData.stationList
      const sectionList = sectionData.setctoin.map((item:any)=>{
       return [
       {xAxis: new Date(item.startDate).format('YYYY-MM-DD hh:mm:ss')},
       {xAxis: new Dateitem.endDate).format('YYYY-MM-DD hh:mm:ss')}
       ]
      })
      const chart:any = echart.init(chartRef.value as HTMLCanvasElement)
      const legendList = []
      const seriesList = []
      let isNullData = true
      for(let i=0; i<stationList.length;i++){
       const station = stationList[i]
       legendList.push(station.stationName)
       const dataValues: any = stationDataList.value.find((item:any)=>item.code === station.stationId)
       let dataList = [] as any
       if(dataValues){
        dataList = dataValues.RTDataValues.mao((item:any)=>[
        item.Time,
        item.Value
        ])
       }
       if(dataList.length) {
        isNullData = false
       }
       const data = {
        name:station.stationName,
        type:'line',
        data:dataList,
        showSymbol: false,
        lineStyle:{
         normal:{
           width:2
         }
        }
       }
       seriesList.push(data)
      }
      const option = {
       title:{
        text: isNullData ? '暂无数据' : '',
        x: 'center',
        y: '50%',
        textStyle: {
         color: 'rgb(204, 204, 204)',
         fontWeight: 500
        }
       },
       tooltip: {
        trigger: 'axis',
        axisPointer: {
         type:'cross',
         label: {
          backgroundColor: '#6a7985'
         }
        }
       },
       toolbox: {
         show: true,
         itemSize: 18,
         itemGap: 10,
         right: '20px',
         top: 15,
         feature:{
          brush:{
           type:['lineX','clear','keep']
          }
         },
         emphasis:{
           iconStyle:{
             color:'#3189cb',
             borderColor:'#3189cb',
             textPosition: 'top',
             textFill:'#f00'
           },
           label:{
             position: 'top'
           }
         }
       },
       brush:{
        model:'multiple',
        xAxisIndex: 'all',
        brushLink: 'all',
        throttleType: 'debounce',
        throttleDelay: 200,
        outOfBrush:{
         colorAlpha: 0.1
        }
       },
       legend: {
        top: '35px',
        right: 'center',
        data: legendList
       },
       grid:{
        left:'20px',
        right:'20px',
        bottom:'50px',
        containLabel:true
       },
       xAxis:{
        type:'time',
        boundaryGap:false,
        axisTick:{
         show: false
        },
        axisLable:{
         showMinLabel:true,
         showMaxLable:true,
         fontSize: '12',
         interval:0,
         formatter:function(value:string, index:number){
          if(index % 2 === 0){
           return `${new Date(value).format('hh:mm')}\n${new Date(value).format('MM-DD')}`
          } else {
           return ''
          }
         }
        }
       },
       yAxis:{
        type:'value',
        scale:true
       },
       dataZoom:[
       {
        show:true,
        height:15,
        start: 0,
        end: 100,
        bottom: 15,
        handleIcon:'path://M306.1,413c0',
        handleSize: '110%',
        handleStyle:{
         color:'#d3dee5'
        },
        textStyle:{
         color:'#fff'
        },
        borderColor:'#90979c'
       },
       {
        type:'inside',
        show:true,
        height:15,
        start:1,
        end:30,
        bottom:15
       }
       ],
       hoverAnimation: false,
       animation:false,
       animationDurationUpdate:0,
       series:[
       {
        name: '',
        type:'line',
        markArea:{
         itemStyle:{
           color:'rgba(255,172,177,0.4)'
          },
          data: sectionList
        }
       },
        ...seriesList
       ]
      }
      chart.off('brushSelected')
      chart.on('brushSelected',(params:any)=>{
       const timeList = params.batch[0].areas.map((area:any)=>{
       return area.coordRange.map((item:any)=>item.toString().split('.')[0])
       }).sort((a:any, b:any) => a[0]-b[0])
       emit('chartBrush', timeList)
      })
      chart.clear()
      chart.setOption(option)
      nextTick(()=>{})
     }
     
     return () => {
      return (
       <div
        v-eleResize
        v-loading = {loading.value}
        element-loading-text="数据加载中"
        ref={chartRef}
        style={{width: '100%', height: '100%'}}
        ></div>
      )
     }
  },
  created(){
   const t:any = this
   t.init = init
   }
})

tree封装

import { defineComponet } from 'vue'
export default defineComponent({
 name:'Xtree',
 props:{
  data:{
   type:Array,
   required:true,
   default:() => {
    return [{}]
   }
  },
  showFilter:{
   type:Boolean,
   default:true
  },
  isLoad:{
   type:Boolean,
   default:false
  },
  showIcon:{
   type:Boolean,
   default:false
  },
  nodeKey:{
   type:String,
   default:'id'
  },
  showCheckbox:{
   type:Boolean,
   default: false
  },
  iconObj:{
   type:Array,
   default:() => {
    return [{}]
   }
  },
  defaultProp:{
   type:Object,
   default:() => {
    return {
     id: 'id',
     label: 'name',
     children: 'children'
    }
   }
  },
  defaultExpandedKeys:{
   type:Array,
   default:() => {
    return []
   }
  },
  formatClass:{
   type:String,
   default:() =>{
    return ''
   }
  },
  isFormatIcon:{
   type:Boolean,
   default:() => {
    return false
   }
  },
  filterChildNode: {
   type:Boolean,
   default:() =>{
    return false
   }
  },
  formatFn:{
   type:Function,
   default:() => {
    return ''
   }
  },
  isFormatLabel: {
   type:Boolean,
   default:() => {
    return false
   }
  },
  formatLableFn:{
   type:Function,
   default:() => {
    return ''
   }
  },
  islogicTree: {
   type: Boolean,
   default: () => {
    return false
   }
  },
  isDrag: {
   type: Boolean,
   default: () => {
    return false
   }
  }
 },
 emits:[
  'nodeClick',
  'loadData',
  'iconClick',
  'check',
  'checkChange',
  'dragstart'
 ],
 data() {
  return {
   filterText: ''
  }
 },
 watch: {
  filterText: function (v:string){
   const t:any = this
   utils.debounce(():void => {
    t.$refs.jtree.filter(v)
   },500)
  }
 },
 methods:{
  filterNode(value:any, data:any, node:any):any{
   const t: any = this
   if(!value) return true
   if(t.filterChildNode) {
    const one = data.name.indexOf(value) !== -1
    const two = node.parent &&
                node.parent.data &&
                node.parent.data.name &&
                node.parent.data.name.indexOf(value) !== -1
   const three = node.parent &&
                 node.parnet.parent &&
                 node.parent.parent.data &&
                 node.parent.parent.data.name &&
                 node.parent.parent.parent.data.name.indexOf(value) !== -1
                 let result_one = false
                 let result_two = false
                 let result_three = false
                 if(node.level === 1) {
                  result_one = one
                 } else if(node.level === 2){
                  result_two = one || two
                 } else if(node.level === 3){
                  result_three = one || two || three
                 }
                 return result_one || result_two || result_three
   } else {
    return data[t.defaultProp.labe].indexOf(value) !== -1
   }
  },
  nodeClick(data:any, node:any):void {
   this.$emit('nodeClick', data, node)
  },
  loadNode(node:any, resolve:any):void {
   this.$emit('laodData',node,resolve)
  },
  iconClick(item:any):void {
   this.$emit('iconClick',item)
  },
  formatIcon(row:any):any{
   return this.formatFn(row.node, row.data)
  },
  formatLabel(row:any):any{
   return this.formatLabelFn(row)
  },
  check(data:any,node:any):void{
   this.$emit('check',data,node)
  },
  checkChange(data:any,checked:boolean,indeterminate:boolean):void{
  this.$emit('checkChange',data,checked,indeterminate)
  },
  dragstart(ev:any,data:any,node:Any,chekNodes:any):boolean{
   this.$emit('dragstart',ev,data,node,checkNodes)
   return false
  }
 },
 render(){
  return(
   <div class="tree-box">
    <div class="shrink0">
     <div style="margin-right:3px;marign-left:3px" v-show={this.showFilter}>
      <el-input placeholder="快速检索" v-model={this.filterText} size="mini" prefix-icon="el-icon-search" />
     </div>
     <div v-show={this.showIcon} style="text-align:right">
      {this.iconObj.map((item:any)=>{
       return(
        <a style="margin-left: 3px">
         <i class={'el-icon-'+ item.icon}
            style={{color:item.color?item.color:''}}
            title={item.title}
            onClick={()=>this.iconClick(item)}
         />
        </a>
       )
      })
      }
     </div>
    </div>
    <el-scrollbar class="h-full">
     <el-tree
      disabled={false}
      default-expand-all
      data={tis.data}
      show-checkbox={this.showCheckbox ? true : false}
      accordion={true}
      props={this.defaultProp}
      ref="xTree"
      node-key="id"
      laod={this.loadNode}
      lazy={this.isLoad}
      highlight-current
      filterNodeMethod={this.filterNode}
      onNodeClick={this.nodeClick}
      onCheck={this.check}
      onCheckChange={this.checkChange}
      v-slots={{
       default:(sdata:any):any =>{
        return (
         <span class="custom-tree-node">
          <span v-show={!this.isFormatIcon} class="el-tree-node__label">
          {this.islogicTree?sdata.data.label:sdata.data[this.defaultProp.label]
          }
         </span>
         <span v-show={this.isFormatIcon} class={['el-tree-node__label',this.formatClass]}>
         <span class={this.formatIcon(sdata)}></span>
         <span draggable={this.isDrag}
          onDragstart={(e:DragEvent):void=>{
           const checkNodes = (this.$refs as any).jtree.getCheckedNodes() this.dragstart(e, sdata.data, sdata.node, checkNodes)
          }}
         >
         {this.islogicTree?sdata.data.label:this.isFormatLabel?this.formatLabel(sdata):sdata.data.name}
         </span>
         </span>
        )
       }
      }}
     >
     </el-tree>
    </el-scrollbar>
   </div>
  )
 }
})

使用element-plus中的table表格并附带展开行 在vue3中tsx写法的代码

会出现row不一样导致展开行表格有数据但是不显示

//事件名 expand-change 当用户对表格某一行展开或者关闭的时候会触发该事件
//      onSortChange  当表格的排序条件发生变化的时候会触发该事件
//属性   row-key 行数据的 Key,用来优化 Table 的渲染
//       expand-row-key  当前行的 key,只写属性
//获取外层表格数据

<el-table 
    data={model.list} 
    height="100%" 
    v-loading={model.loading}
    element-loading-text="正在加载中"
    onExpandChange={getHistory}
    row-key="modelName"
    onSortChange={sortChange}
    expand-row-keys={expand.value}
    >
    <el-table-column
    type="expand"
    v-slots={{
        default:(parentScope:any) => {
            return(
               <div style={{padding}}>
                 <el-table
                  border
                  highlight-current-row
                  element-loading-text="正在加载中"
                  data={parentScope.row.historyList}
                 >
                     <el-tbale-column
                      prop="aglModelName"
                      label="模型名称"
                      v-slots={{
                       default:(sdata: any):any => {
                        return sdata.row.aglModelName.split('~')[2]
                       }
                      }}
                     ></el-table-column>
                 </el-table>
               </div>
            )
        }
    }}
    >
    </el-table-column>
</el-table>
//在export default defineComponent 外,和import 这样可以拿到组件的实例
let init = {} as any
//在setup外defineComponent内
 created(){
  const t:any = this
      t.init = init
 }
 setup(){
  init = (params={}) {
   form = params
   getModleList()
  }
  const getModelList = ():void => {
   model.List = []
   const params={...form}
   delete params.status
   //此处用到了另一个回调函数sortChange
   if(sortFiled.siteId){
    params.sortBySite = sortField.siteId == 'descending' ? 'desc' : 'asc'
   }
   const url = `/analysis/xxx`
   utils.http.post(url, params)
   .then((d:any) =>{
    if(!d.state){
     model.list = d.data.map((item:any)=>{
      if(item.logicPath){
       item.logicPath = item.logicPath.split('~')[item.logicPath.split('~').lenght - 1]
      }
      return item
     })
     getHistory()
    }
   })
   .catch((error)=>{
      console.log(error)
   })
  }
  const historyRow = ref({} as any)
  const expands = reactive({value:[]} as any)
  const getHistory = (row = {} as any, expandendRows = {} as any) => {
    //每次只展开一个
    if(expandendRows.length){
      expands.value = []
      if(row && row.modleName) {
       expands.value.push(row.modelName)
      } else {
       expands.value = []
      }
    }
    if(!Object.keys(row).length){
     row = historyRow.value
    }else {
     historyRow.value = row
    }
    //如果没有row
    if(!Object.keys(row).length){
      return
    }
    const url = '/xxx/x/x'
    utils.http.post(url,params).then((d:any)=>{
     if(!d.statue){
      if(Object.keys(historyRow.value).length){
       const index = model.list.findIndex((item:any)=>{
        return item.InstanceId ===historyRow.InstanceId
       })
       model.list[index].historyList =  d.data.map((item:any)=>{
        item._status = getAppState(item) 
        return item
       })
      }
     }
    })
  }
 }