DataForm.vue 7.82 KB
<template>
    <template v-if="dataRows && dataTables">    
        <el-table 
            ref="tableRef"
            show-header="true" 
            border 
            highlight-current-row 
            :max-height="maxHeight?maxHeight:'-'"
            :height="tableHeight" 
            virtual-scroll 
            style="border-color: #97d5fd;"
            :header-cell-class-name="setHeaderClass"  
            @sort-change="subSort"
            :cell-style="setCellStyle" 
            :data="visibleData" 
            :header-cell-style="setHeaderCellStyle"
            v-loading="isLoading"
            element-loading-text="数据加载中......"
            row-class-name="fixed-row-height"
            element-loading-background="rgba(0, 0, 0, 0.8)">
            
            <template v-for="(item) in dataRows" :key="item.name">
                <el-table-column v-if="item.isVisible" :class-name="[item.fixed ? classObject : '']" :fixed="item.fixed" :prop="item.name"
                    :label="item.showName" :width="item.width" :sortable="sortabletype" :color="item.color">
                    <el-table-column v-if="item.haveFilter" :prop="item.name" :width="item.width" >
                        <template #header>
                            <el-input v-if="item.filterType == 1" v-model="item.filterValue" placeholder=""  @keyup.enter="callParentMethod"/>
                            <el-select v-else-if="item.filterType == 2" v-model="item.filterValue"
                                placeholder="" @change="callParentMethod">
                                <el-option v-for="obj in item.filterText" :key="obj.text" :label="obj.text" :value="obj.value" />
                            </el-select>
                        </template>
                        <template #default="{row, column}">
                            <div v-if="shouldBlink(row,column)" class="blink-animation">{{ getCellValue(row, column)}}</div>
                            <div v-else>{{ row[column.property] }}</div>
                        </template>
                    </el-table-column>
                </el-table-column>
            </template>
        </el-table>
       
    </template>
</template>

<style scoped>
::v-deep .el-table__body tr:hover > td {
     background: linear-gradient(to top, rgb(0,198,255), rgb(255,255,255)) !important;
 }
 ::v-deep .el-table__body tr.current-row>td{
    background-color: #92cbf1!important;
  }
  @keyframes blink {
  0% {
    opacity: 1.0;
  }
  50% {
    opacity: 0.0;
  }
  100% {
    opacity: 1.0;
  }
}
 
.blink-animation {
  animation: blink 1s infinite;
}

</style>

<script setup>

//import { fa } from 'element-plus/es/locale';
import { reactive, ref, watch, onMounted, onUnmounted } from 'vue'

const props = defineProps(['dataRows',
 'dataTables', 
 'maxHeight', 
 'sortMap', 
 'sortabletype',
 'width', 
 'tableHeight', 
 'alarm',
 'isLoading', 
 'parentMethod',
 'offlineTime'
]);
const emit = defineEmits(['sort','child-event']);
const classObject = 'fixedColumn'
const tableRef = ref(null);

const itemHeight = 20; // 每个表格行的高度
const visibleItemCount = ref(30); // 可见区域内的行数
const visibleData = ref([]); //可视区数据
const totalCount = ref(1); //总记录数
const startIndex = ref(0);//可视区起始标

// 监听滚动事件来更新显示的数据
const handleScroll = (event) => {
    if(totalCount.value <= visibleItemCount.value){
        return;
    }
    //console.log('Table scrolled:', event);
    //console.log('deltaY:', event.deltaY);
    if(tableRef){
        var start = startIndex.value;
        if(event.deltaY > 0){
            start+=4;
        }else{
            start-=4;
        }
        if(start < 0){
            start = 0;
        }
        if((start+visibleItemCount.value) > totalCount.value){
            start =  totalCount.value - visibleItemCount.value;
        }
        if(start == startIndex.value){
            return;
        }
        startIndex.value = start;
        //console.log(startIndex.value + " " + (startIndex.value + visibleItemCount.value) + " " +  totalCount.value);
        reload();
    }
}

function reload(){
    if(props.dataTables.length){
        if(props.dataTables.length < visibleItemCount.value){
            visibleData.value = props.dataTables.slice(0, props.dataTables.length);
        }else{
            visibleData.value = props.dataTables.slice(startIndex.value, startIndex.value + visibleItemCount.value);
        }
    }
}

function subSort(data) {
    emit('sort', data);
}

function setCellStyle({ row, column, rowIndex, columnIndex }) {
    let css_color={};
    css_color['padding'] = '0px';
    css_color['borderColor'] = '#97d5fd';
    css_color['height'] = '15px';

    props.dataRows.forEach(element => {
        if (element.name === column.property) {
            css_color['background-color']='#'+ element.color;

            if(!element.fixed){
                 if(props.alarm){
                      props.alarm.forEach(alarmItem =>{
                         if(alarmItem.id.toUpperCase() === row.id.toUpperCase()){
                            if(alarmItem.enName.toUpperCase() == element.name.toUpperCase()){
                                if(alarmItem.topMost || alarmItem.downMost){
                                    css_color['color'] = '#ff0000';
                                }else{
                                    css_color['color'] = '#ff8040';
                                }
                            }
                         }
                      })
                 }
            }
        }
    })
    return css_color;
}

function setHeaderCellStyle({ row, column, rowIndex, columnIndex }) {
    let css_color;
    props.dataRows.forEach(element => {
        if (element.name === column.property) {
            var backcolor = (element.color=='FFFFFF') ? 'd9f1ff':element.color;
            css_color= {'background-color': '#'+backcolor, 'padding-left':'0px', 'padding-right':'0px', 'borderColor':'#97d5fd', 'color':'#000','text-align':'center','vertical-align':'top'};
        }
    })
    
     return css_color;
}

function setHeaderClass(params) {
    if (props.sortMap && params.column.property) {
        if (props.sortMap.get(params.column.property)) {
            params.column.order = props.sortMap.get(params.column.property).order
        }
    }
}

//监听修改loading状态
watch([() =>props.isLoading, ()=> props.dataTables], (oldValue, newValue) => {
   // console.log(`watch changed from ${oldValue} to ${newValue}`);
    totalCount.value = props.dataTables.length;
    reload();
},{deep:true});

onMounted(()=>{
    if(props.tableHeight){
        visibleItemCount.value = Math.ceil((props.tableHeight-100) / itemHeight);
    }
    totalCount.value = props.dataTables.length;
    //console.log("count : "+visibleItemCount.value +" totalCount:" + totalCount.value);

   // 挂载
   tableRef.value &&
   tableRef.value.$refs.bodyWrapper.addEventListener(
      "mousewheel",
      handleScroll
    );
    reload();
});
onUnmounted(() => {
  // 卸载
  tableRef.value &&
  tableRef.value.$refs.bodyWrapper.removeEventListener(
      "mousewheel",
      handleScroll
    );
});


const callParentMethod = () => {
  props.parentMethod();
  emit('child-event');
};

function shouldBlink(row, column){

    if(column.fixed){
        return false;
    }

    //console.log(row.name + " row:" + row.id+ " column.property:"+column.property);
    var check = false;
    if(props.alarm){
        props.alarm.forEach(alarmItem =>{
            if(alarmItem.id.toUpperCase() === row.id.toUpperCase()){
                if(alarmItem.enName.toUpperCase() == column.property.toUpperCase()){
                    //console.log("alarmItem.enName:" + alarmItem.enName );
                    check= true;
                }
            }
        })
    }
    //console.log("check:" + check);
    return check;
}

function getCellValue(row, column){
    return row[column.property];
}

</script>