vue3使用虚拟化表格自定义表格并动态生成表头

发布时间 2023-12-05 18:19:56作者: 幻影之舞

element Plus的虚拟化表格用的是lang=tsx,先安装

cnpm i @vitejs/plugin-vue-jsx

然后去vite.config.ts里加配置

import vueJsx from '@vitejs/plugin-vue-jsx'


 plugins: [
            vue(),
            vueJsx(),
]

再去tsconfig.json中加东西

// 不要把compilerOptions里的删掉,往里塞就行
"compilerOptions": {
     "jsx": "preserve",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
}

然后去要使用的的页面

把lang=ts改成lang=tsx

<script setup lang="tsx">
   .....
</script >

然后开始改造你的代码

 上图是el-table的数据格式,先改造表头数据tableOps

虚拟化表格的columns键是固定的,不能修改

 {
        title: '员工姓名',
        key: 'userName',
        align: 'center', // 是否居中
        dataKey: 'userName', 
        width: 120,
        fixed: 'left' // 是否固定在左边
},
// title就是表头名   dataKey就是对应返回数据的字段, key不知道干嘛用的,最好带着

然后表格的html代码就变成这样。  load是滚动条滑到底部时的事件

<el-auto-resizer>
     <template #default="{ height, width }">
            <el-table-v2
                        :columns="headOps"
                        :data="tableData"
                        :width="width"
                        :height="height"
                        fixed
                        @end-reached="load"
                    >
           </el-table-v2>
    </template>
</el-auto-resizer>

 定义表头字段

// 全部的表头
const headOps = ref<any>([])
// 固定的几个表头字段 const tableOps = ref
<any>([ { title: '序号', key: 'index', align: 'center', dataKey: 'index', width: 120, fixed: 'left', cellRenderer: (cellData: any) => ( <div>{cellData.rowIndex +1 }</div> ) }, { title: '员工姓名', key: 'userName', align: 'center', dataKey: 'userName', width: 120, fixed: 'left' }, { title: '岗位', fixed: 'left', align: 'center', width: 120, key: 'positionName', dataKey: 'positionName', }, ])

官方文档是在这自定义的

 先添加操作项

el-table样式

 虚拟化改造:

先建立操作项表头数据

list = {
       title: '操作',
           key: 'ops',
           align: 'center',
           dataKey: 'ops',
           width: 150,
           fixed: 'right',
           cellRenderer: (cellData: any) => (
              <div style="display:flex">
                   { !cellData.rowData.isEdit  && authorization('attendanceTable_edit') ? <el-button type="primary" plain onClick={() => updateRow(cellData.rowData)} > 修改</el-button> : ''}
                   { cellData.rowData.isEdit && authorization('attendanceTable_edit') ? <el-button type="success" plain onClick={() => submit(cellData.rowData)} > 提交</el-button> : ''}
                   { cellData.rowData.isEdit && authorization('attendanceTable_edit') ? <el-button plain onClick={() => cancelSubmit(cellData.rowData)} > 取消</el-button> : ''}
              </div>
           )
}

tsx中没有v-if.所以要用三元表达式来操作v-if的展示内容

cellData返回几个对象

cellData,  // 要展示的数据
rowData, // 相当于scope.row, 这一行的数据
rowIndex, // 行序号,从0开始, 

tsx中没有{{}} , 只有单括号, 不能在div直接写变量的,要用{}包起来

v-model的话就是把等号后边的“”换成{}就可以了,例如

 @click换成onClick,然后用{}包住定义的方法,有参数的话要写成

onClick={() => updateRow(cellData.rowData)}
// 点击修改
const updateRow = (row: any) => {
    row.isEdit = true
    for (let valueKey in editParams.value) {
        editParams.value[valueKey] = row[valueKey]
    }
}

方法还是正常定义

页面全部代码

<template>
    <div class="attendanceTableList" v-loading="loading">
        <div class="left" ref="left1">
            <left-company-menu
                ref="leftTree"
                @getCompanyDeptInfo="getCompanyDeptInfo"
                :permissionTag="permissionTag"
                @hasNoPrivilege="hasNoPrivilege"
            />
        </div>
        <div class="right">
            <div class="topSearch">
                <el-form inline :model="searchVal">
                    <el-form-item label="查询月份"  prop="date">
                        <el-date-picker
                            style="width: 100%;"
                            :editable="false"
                            :clearable="false"
                            v-model="selectedDate"
                            type="month"
                            placeholder="选择月份"
                            @change="changeDate"
                        />
                    </el-form-item>
                    <el-form-item label="员工姓名" prop="userName">
                        <el-input @keyup.enter="getListData()" clearable v-model.trim="searchVal.userNames" placeholder="搜索多个请用逗号分隔"  />
                    </el-form-item>
                    <el-form-item>
                        <div class="f">
                            <el-button class="btn" type="primary" @click="getListData" :icon="Search">查询</el-button>
                            <el-button v-if="authorization('attendance_exportBtn')" class="btn" @click="exportTableData" :icon="Upload">导出</el-button>
                            <el-button v-if="authorization('pushQiXinBtn')" class="btn" @click="pushQX" :icon="Position">推送企信</el-button>
                        </div>
                    </el-form-item>
                </el-form>
            </div>
            <el-auto-resizer>
                <template #default="{ height, width }">
                    <el-table-v2
                        border
                        :columns="headOps"
                        :data="tableData"
                        :width="width"
                        :height="height"
                        fixed
                        @end-reached="load"
                    >
                    </el-table-v2>
                </template>
            </el-auto-resizer>

<!--            <el-table-->
<!--                :header-cell-style="{ 'text-align': 'center' }"-->
<!--                :cell-style="{ 'text-align': 'center' }"-->
<!--                tooltip-effect="dark"-->
<!--                border-->
<!--                style="height:100%;max-height:100%"-->
<!--                 v-el-table-infinite-scroll="load"-->
<!--                scrollbar-always-on-->
<!--                :data="tableData"-->
<!--                @cell-click="cellClick"-->
<!--            >-->
<!--                <el-table-column type="index" fixed="left" label="序号" width="55"/>-->
<!--                <el-table-column show-overflow-tooltip v-for="item in tableOps" :label="item.title" :prop="item.key" :fixed="item.fixed" :width="item.width" align="center" :min-width="item.minWidth">-->
<!--                    <template #default="{row}">-->
<!--                        <div v-if="item.key === 'checkStatus'">{{ row.checkStatus ? '已核对' : '未核对' }}</div>-->
<!--                        <div v-else>-->
<!--                            <div v-if="!canEditCloumn.some((i: any) => i.key === item.key)">{{ row[item.key]  ===0 ? 0 : row[item.key] }}</div>-->
<!--                            <div v-else>-->
<!--                                <div v-if="row.isEdit">-->
<!--                                    <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model="editParams[item.key]" placeholder="请输入" clearable />-->
<!--                                </div>-->
<!--                                <div v-else>-->
<!--                                    {{ row[item.key]  === 0 ? 0 : row[item.key] || '&#45;&#45;&#45;&#45;' }}-->
<!--                                </div>-->
<!--                            </div>-->
<!--                        </div>-->
<!--                    </template>-->
<!--                </el-table-column>-->
<!--                <el-table-column show-overflow-tooltip v-for="item in headWeek" :label="item.label" :prop="item.prop" :fixed="item.fixed" :width="item.width" align="center" :min-width="item.minWidth">-->
<!--                    <template #default="{row}">-->
<!--                        <div>-->
<!--                            {{ row[item.prop] }}-->
<!--                            <span class="xiang" v-if="row.positionName=== '客户经理' && row[item.prop]" @click="goToDetail(item, row)">详</span>-->
<!--                        </div>-->
<!--                    </template>-->
<!--                </el-table-column>-->
<!--                <el-table-column fixed="right" label="操作" width="160" v-if="dayjs().isAfter(selectedDate, 'month')">-->
<!--                    <template #default="{row}">-->
<!--                        <el-button v-if="!row.isEdit  && authorization('attendanceTable_edit')" type="primary" plain @click="updateRow(row)" > 修改</el-button>-->
<!--                        <el-button v-if="row.isEdit && authorization('attendanceTable_edit')" type="success" plain @click="submit(row)" > 提交</el-button>-->
<!--                        <el-button v-if="row.isEdit && authorization('attendanceTable_edit')" type="" plain @click="cancelSubmit(row)" > 取消</el-button>-->
<!--                    </template>-->
<!--                </el-table-column>-->
<!--            </el-table>-->
            <div class="dfcr mt10">
                <el-text>当前页:<el-text type="danger">{{ searchVal.pageIndex }}</el-text>/总共<el-text type="danger">{{ total
                    }}</el-text></el-text>
            </div>
        </div>
    </div>
    <attendance-list-dialog :dialogVisible="isShowDialog" @beforeClose="beforeClose" :mapData="mapData" :itemInfo="itemInfo"/>
    <push-q-x-dialog :is-show-dialog="isShowPushDialog" @closePushDialog="closePushDialog"/>
</template>

<script setup lang="tsx">
import {
    Search,
    Refresh,
    Position,
    Upload
} from '@element-plus/icons-vue'
import {authorization} from "../../../utils/auth";
import {nextTick, onMounted, ref, h} from "vue";
import LeftCompanyMenu from "./leftCompanyMenu.vue";
import Stable from "../../../components/table/Stable.vue";
import {
    getAttendanceTableList, getDetailById,
    updateAttendance,
} from "../../../api/humanResources/attendanceTableList";
import {ElMessage, ElMessageBox} from "element-plus";
import dayjs from "dayjs";
import AttendanceListDialog from "./attendanceListDialog.vue";
import PushQXDialog from "./pushQXDialog.vue";
import axios from "axios";
import {exportData} from "../../../utils/export";

const leftTree = ref()
const total = ref(0)
const loading = ref(false)
const isShowDialog = ref(false)
const isShowPushDialog = ref(false)
// 要查询的月份
const selectedDate = ref()
const permissionTag = ref()
const itemInfo = ref<any>()
// 点击详情返回的经纬度信息
const mapData = ref<any>([])
const tableData = ref<any>([])
const canEditCloumn = ref<any>([
    {
        label: '应出勤天数',
        type: '',
        data: null,
        key: 'shouldBeAttendedOnDays'
    },
    {
        label: '实际出勤',
        type: '',
        width: 100,
        key: 'actualAttendance'
    },
    {
        label: '值班小时',
        type: '',
        width: 100,
        key: 'dutyHours'
    },
    {
        label: '出差',
        type: '',
        key: 'businessTrip'
    },
    {
        label: '外出登记',
        type: '',
        width: 100,
        key: 'goOutAndRegister'
    },
    {
        label: '探亲假',
        type: '',
        key: 'familyLeave'
    },
    {
        label: '年假',
        type: '',
        key: 'annualLeave'
    },
    {
        label: '调休',
        type: '',
        key: 'rest'
    },
    {
        label: '事假',
        type: '',
        key: 'leave'
    },
    {
        label: '高管带薪事假',
        type: '',
        width: 110,
        key: 'executivePaidPersonalLeave'
    },
    {
        label: '病假',
        type: '',
        key: 'sickLeave'
    },
    {
        label: '丧假',
        type: '',
        key: 'bereavementLeave'
    },
    {
        label: '婚假',
        type: '',
        key: 'marriageLeave'
    },
    {
        label: '产假',
        type: '',
        key: 'maternityLeave'
    },
    {
        label: '陪产假',
        type: '',
        key: 'paternityLeave'
    },
    {
        label: '产检假',
        type: '',
        key: 'maternityExamineLeave'
    },
    {
        label: '育儿假',
        type: '',
        key: 'parentalLeave'
    },
    {
        label: '哺乳假',
        type: '',
        key: 'breastfeedingLeave'
    },
    {
        label: '工伤假',
        type: '',
        key: 'injuryLeave'
    },
    {
        label: '未打卡',
        type: '',
        key: 'notClockedOut'
    },
    {
        label: '迟到',
        type: '',
        key: 'late'
    },
    {
        label: '早退',
        type: '',
        key: 'early'
    },
    {
        label: '旷工',
        type: '',
        key: 'absenteeism'
    },

])
const headOps = ref<any>([])
const tableOps = ref<any>([
    {
        title: '序号',
        key: 'index',
        align: 'center',
        dataKey: 'index',
        width: 120,
        fixed: 'left',
        cellRenderer: (cellData: any) => {
            console.log(cellData)}
        //     (
        //     <div>{cellData.rowIndex +1 }</div>
        // )
    },
    {
        title: '员工姓名',
        key: 'userName',
        align: 'center',
        dataKey: 'userName',
        width: 120,
        fixed: 'left'
    },
    {
        title: '岗位',
        fixed: 'left',
        align: 'center',
        width: 120,
        key: 'positionName',
        dataKey: 'positionName',
    },
    {
        title: '公司',
        align: 'center',
        key: 'companyName',
        dataKey: 'companyName',
        width: 160,
    },
    {
        title: '部门',
        width: 120,
        align: 'center',
        key: 'deptName',
        dataKey: 'deptName',
    },
    {
        title: '是否全勤',
        width: 120,
        align: 'center',
        key: 'fullAttendance',
        dataKey: 'fullAttendance',
        cellRenderer: (cellData: any) => (
            <div>
                { cellData.cellData ? '全勤' : '缺勤'}
            </div>
        )
    },
    {
        title: '核对状态',
        width: 100,
        align: 'center',
        key: 'checkStatus',
        dataKey: 'checkStatus',
        cellRenderer: (cellData: any) => (
            <div>
                { cellData.rowData.checkStatus ? <div style="color: #67c23a">已核对</div> : '未核对'}
            </div>
        )
    },
    {
        title: '推送次数',
        width: 100,
        align: 'center',
        key: 'theNumberOfPushes',
        dataKey: 'theNumberOfPushes',
    },
    {
        title: '应出勤天数',
        width: 100,
        align: 'center',
        key: 'shouldBeAttendedOnDays',
        dataKey: 'shouldBeAttendedOnDays',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.shouldBeAttendedOnDays} placeholder="请输入" clearable /> : <div>{cellData.rowData.shouldBeAttendedOnDays}</div>
                }
            </div>
        )
    },
    {
        title: '实际出勤',
        width: 100,
        align: 'center',
        key: 'actualAttendance',
        dataKey: 'actualAttendance',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.actualAttendance} placeholder="请输入" clearable /> : <div>{cellData.rowData.actualAttendance}</div>
                }
            </div>
        )
    },
    {
        title: '值班小时',
        width: 100,
        align: 'center',
        key: 'dutyHours',
        dataKey: 'dutyHours',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.dutyHours} placeholder="请输入" clearable /> : <div>{cellData.rowData.dutyHours}</div>
                }
            </div>
        )
    },
    {
        title: '出差',
        width: 120,
        align: 'center',
        key: 'businessTrip',
        dataKey: 'businessTrip',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.businessTrip} placeholder="请输入" clearable /> : <div>{cellData.rowData.businessTrip}</div>
                }
            </div>
        )
    },
    {
        title: '外出登记',
        width: 100,
        align: 'center',
        key: 'goOutAndRegister',
        dataKey: 'goOutAndRegister',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.goOutAndRegister} placeholder="请输入" clearable /> : <div>{cellData.rowData.goOutAndRegister}</div>
                }
            </div>
        )
    },
    {
        title: '探亲假',
        width: 120,
        align: 'center',
        key: 'familyLeave',
        dataKey: 'familyLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.familyLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.familyLeave}</div>
                }
            </div>
        )
    },
    {
        title: '年假',
        width: 120,
        align: 'center',
        key: 'annualLeave',
        dataKey: 'annualLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.annualLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.annualLeave}</div>
                }
            </div>
        )
    },
    {
        title: '调休',
        key: 'rest',
        align: 'center',
        width: 120,
        dataKey: 'rest',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.rest} placeholder="请输入" clearable /> : <div>{cellData.rowData.rest}</div>
                }
            </div>
        )
    },
    {
        title: '事假',
        key: 'leave',
        align: 'center',
        width: 120,
        dataKey: 'leave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.leave} placeholder="请输入" clearable /> : <div>{cellData.rowData.leave}</div>
                }
            </div>
        )
    },
    {
        title: '高管带薪事假',
        width: 110,
        align: 'center',
        key: 'executivePaidPersonalLeave',
        dataKey: 'executivePaidPersonalLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.executivePaidPersonalLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.executivePaidPersonalLeave}</div>
                }
            </div>
        )
    },
    {
        title: '病假',
        width: 100,
        align: 'center',
        key: 'sickLeave',
        dataKey: 'sickLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.sickLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.sickLeave}</div>
                }
            </div>
        )
    },
    {
        title: '丧假',
        width: 80,
        align: 'center',
        key: 'bereavementLeave',
        dataKey: 'bereavementLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.bereavementLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.bereavementLeave}</div>
                }
            </div>
        )
    },
    {
        title: '婚假',
        width: 80,
        align: 'center',
        key: 'marriageLeave',
        dataKey: 'marriageLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.marriageLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.marriageLeave}</div>
                }
            </div>
        )
    },
    {
        title: '产假',
        width: 80,
        align: 'center',
        key: 'maternityLeave',
        dataKey: 'maternityLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.maternityLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.maternityLeave}</div>
                }
            </div>
        )
    },
    {
        title: '陪产假',
        width: 80,
        align: 'center',
        key: 'paternityLeave',
        dataKey: 'paternityLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.paternityLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.paternityLeave}</div>
                }
            </div>
        )
    },
    {
        title: '产检假',
        width: 80,
        align: 'center',
        key: 'maternityExamineLeave',
        dataKey: 'maternityExamineLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.maternityExamineLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.maternityExamineLeave}</div>
                }
            </div>
        )
    },
    {
        title: '育儿假',
        width: 80,
        align: 'center',
        key: 'parentalLeave',
        dataKey: 'parentalLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.parentalLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.parentalLeave}</div>
                }
            </div>
        )
    },
    {
        title: '哺乳假',
        width: 80,
        align: 'center',
        key: 'breastfeedingLeave',
        dataKey: 'breastfeedingLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.breastfeedingLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.breastfeedingLeave}</div>
                }
            </div>
        )
    },
    {
        title: '工伤假',
        width: 80,
        align: 'center',
        key: 'injuryLeave',
        dataKey: 'injuryLeave',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.injuryLeave} placeholder="请输入" clearable /> : <div>{cellData.rowData.injuryLeave}</div>
                }
            </div>
        )
    },
    {
        title: '未打卡',
        width: 80,
        align: 'center',
        key: 'notClockedOut',
        dataKey: 'notClockedOut',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.notClockedOut} placeholder="请输入" clearable /> : <div>{cellData.rowData.notClockedOut}</div>
                }
            </div>
        )
    },
    {
        title: '迟到',
        width: 80,
        align: 'center',
        key: 'late',
        dataKey: 'late',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.late} placeholder="请输入" clearable /> : <div>{cellData.rowData.late}</div>
                }
            </div>
        )
    },
    {
        title: '早退',
        width: 80,
        align: 'center',
        key: 'early',
        dataKey: 'early',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.early} placeholder="请输入" clearable /> : <div>{cellData.rowData.early}</div>
                }
            </div>
        )
    },
    {
        title: '旷工',
        width: 80,
        align: 'center',
        key: 'absenteeism',
        dataKey: 'absenteeism',
        cellRenderer: (cellData: any) => (
            <div>
                {
                    cellData.rowData.isEdit ? <el-input onkeyup="value=value.replace(/[^\d]/g,'')" v-model={editParams.value.absenteeism} placeholder="请输入" clearable /> : <div>{cellData.rowData.absenteeism}</div>
                }
            </div>
        )
    },
])
const weekData = ref([
    {
        weekName: '周一',
        index: 1,
    },
    {
        weekName: '周二',
        index: 2,
    },
    {
        weekName: '周三',
        index: 3,
    },
    {
        weekName: '周四',
        index: 4,
    },
    {
        weekName: '周五',
        index: 5,
    },
    {
        weekName: '周六',
        index: 6,
    },
    {
        weekName: '周日',
        index: 0,
    }
])
const canSearch = ref(false)
const isCanEdit = ref(false)
const hasRes = ref(true)
const weekList: any = ref([])
const headWeek: any = ref([])
const searchVal: any = ref({
    startTime: '',
    workCode: null,
    userNames: null,
    endTime: '',
    type: null,
    queryId: null,
    pageIndex: 1,
    pageSize: 500,
})
const editParams: any = ref({
    shouldBeAttendedOnDays: null,
    actualAttendance: null,
    dutyHours: null,
    businessTrip: null,
    goOutAndRegister: null,
    familyLeave: null,
    annualLeave: null,
    rest: null,
    leave: null,
    executivePaidPersonalLeave: null,
    sickLeave: null,
    bereavementLeave: null,
    marriageLeave: null,
    maternityLeave: null,
    paternityLeave: null,
    maternityExamineLeave: null,
    parentalLeave: null,
    breastfeedingLeave : null,
    injuryLeave: null,
    notClockedOut: null,
    late: null,
    early: null,
    absenteeism: null
})
const haOps = ref<boolean>(true)
// 是否含有权限
const hasNoPrivilege = (val: boolean) => {
    canSearch.value = val
}

// 点击左侧公司
const getCompanyDeptInfo = async (val: any) => {
    const { id } = val
    searchVal.value.queryId = id
    searchVal.value.pageIndex = 1
    searchVal.value.pageSize = 500
    await getListData()
}

// 选择完时间
const changeDate = (val: any) => {
    searchVal.value.startTime = dayjs(val).startOf('M').format('YYYY-MM-DD')
    searchVal.value.endTime = dayjs(val).endOf('M').format('YYYY-MM-DD')
    getListData()

}
// 设置当月第一天和最后一天
const setSearchValDate = (val: any) =>{
    searchVal.value.startTime = dayjs(val).startOf('M').format('YYYY-MM-DD')
    searchVal.value.endTime = dayjs(val).endOf('M').format('YYYY-MM-DD')
}

// 动态生成表头
const creatHead = (monthData: any) => {
    headOps.value = [...tableOps.value, ...monthData]
    // 选择当月之前的时间可以编辑数据
    haOps.value = headOps.value.some((item:any) => item.key === 'ops')
    if ( dayjs().isAfter(selectedDate.value, 'month')){
        if (!haOps.value){
            headOps.value.push({
                title: '操作',
                key: 'ops',
                align: 'center',
                dataKey: 'ops',
                width: 150,
                fixed: 'right',
                cellRenderer: (cellData: any) => (
                    <div style="display:flex">
                        { !cellData.rowData.isEdit  && authorization('attendanceTable_edit') ? <el-button type="primary" plain onClick={() => updateRow(cellData.rowData)} > 修改</el-button> : ''}
                        { cellData.rowData.isEdit && authorization('attendanceTable_edit') ? <el-button type="success" plain onClick={() => submit(cellData.rowData)} > 提交</el-button> : ''}
                        { cellData.rowData.isEdit && authorization('attendanceTable_edit') ? <el-button plain onClick={() => cancelSubmit(cellData.rowData)} > 取消</el-button> : ''}
                    </div>
                )
            })
        }
    }else {
        // 删除操作项
        if (haOps.value){
            headOps.value.pop()
        }
    }
}

// 获取月表头
const getMonthHeader = (date: any) => {
    weekList.value = []
    headWeek.value = []
    // 获取第一天是周几
    const firstDay = dayjs(date).startOf('M')
    // 获取当月总天数
    const sum = dayjs(date).daysInMonth()
    for (let i = 0; i < sum; i++) {
        const itemDate = firstDay.add(i, "day")
        const week =   dayjs(itemDate).day()
        const weekName = weekData.value.filter(item => item.index === week)
        weekList.value.push({
            date: dayjs(itemDate).format('YYYY-MM-DD'),
            weekName: weekName[0].weekName,
            dateNum: dayjs(itemDate).format('DD')
        })
    }
    for (let i = 0; i < weekList.value.length; i++) {
        headWeek.value.push({
            title: weekList.value[i].weekName + '  /  ' + weekList.value[i].dateNum,
            dataKey: weekList.value[i].date,
            key: weekList.value[i].date,
            align: 'center',
            width: 200,
            cellRenderer: (cellData: any) => (
                <div>
                    { cellData.cellData }
                    { cellData.rowData.positionName=== '客户经理' ? <span style="margin-left: 10px; color: #1890FF; font-weight: 550; cursor: pointer;" onClick={() =>goToDetail(cellData.column, cellData.rowData)}></span> : ''}
                </div>

            )
        })
    }
    // positionName
    creatHead(headWeek.value)
}

// 导出
const exportTableData = () => {
    axios({
        method: 'get',
        url: 'api/attendance-server/attendance/user/statistics/check/history/export', // 请求地址
        responseType: 'blob', // 表明返回服务器返回的数据类型
        params: {dateTime: dayjs(searchVal.value.startTime).format('YYYY-MM-DD'), queryId: searchVal.value.queryId},
        headers: {
            "Content-Type": "application/json, text/plain, */*",
            Authorization: localStorage.getItem('token') as string,
        }
    }).then( (res: any) => {
        if (res.code) {
            ElMessage.warning(res.message);
            return
        }
        exportData('考勤统计.xlsx', res.data)
    })
}

// 获取列表
const getListData = () => {
    if (searchVal.value.queryId){
        searchVal.value.type = searchVal.value.queryId === '1' ? null : 1
        if (canSearch.value){
            searchVal.value.pageIndex = 1
            tableData.value = [];
            loading.value = true;
            getMonthHeader(selectedDate.value)
            getAttendanceTableList(searchVal.value).then(res => {
                if (res && res.data) {
                    const { count, results } = res.data;
                    total.value = count;
                    tableData.value = [...results];
                    for (let i = 0; i < results.length; i++) {
                        let MonthList = results[i].attendanceInfoDtos;
                        if (MonthList && MonthList.length > 0) {
                            for (let j = 0; j < MonthList.length; j++) {
                                // const infoList = MonthList[j].punchInInformation.split(' ');
                                tableData.value[i][MonthList[j].attendanceDate] = MonthList[j].punchInInformation;
                            }
                        }
                    }
                }
                loading.value = false;
            })
        }else {
            ElMessage.error('暂无权限查询')
        }
    }else {
        ElMessage.error('请选择左侧公司')
    }
};

// 点击查看详情
const goToDetail = (val: any, row: any) => {
    itemInfo.value = row
    getDetailById({date: val.key, userId: row.userId}).then(res => {
        if (res && res.data.length > 0) {
            isShowDialog.value = true
            mapData.value = res.data
        }else {
            isShowDialog.value = false
            ElMessage.error('暂无打卡数据')
        }
    })
}

// 弹窗关闭回调
const beforeClose = () => {
    isShowDialog.value = false
}

// 上滑滚动
const onSearchInfinite = () => {
    loading.value = true
    getAttendanceTableList(searchVal.value).then(res => {
        if (res?.code == 0) {
            const { results } = res.data;
            for (let i = 0; i < results.length; i++) {
                let MonthList = results[i].attendanceInfoDtos;
                if (MonthList && MonthList.length > 0) {
                    for (let j = 0; j < MonthList.length; j++) {
                        const infoList = MonthList[j].punchInInformation.split(' ');
                        results[i][MonthList[j].attendanceDate] = MonthList[j].punchInInformation;
                    }
                }
            }
            tableData.value = tableData.value.concat(res.data.results)
            loading.value = false;
        }
    })
}
const load = async () => {
    if (tableData.value.length > 0){
        if (total.value > tableData.value.length) {
            searchVal.value.pageIndex++
            await onSearchInfinite()
        }
    }

}
// 分页
const handleCurrentChange = (val: number) => {
    searchVal.value.pageIndex = val
    getListData()
}
const handleSizeChange = (val: number) => {
    searchVal.value.pageSize = val
    searchVal.value.pageIndex = 1
    getListData()
}

// 点击修改
const updateRow = (row: any) => {
    row.isEdit = true
    for (let valueKey in editParams.value) {
        editParams.value[valueKey] = row[valueKey]
    }
}

// 点击提交
const submit = (row: any) => {
    row.month = dayjs(selectedDate.value).format('YYYY-MM')
    row = {...row, ...editParams.value}
    updateAttendance(row).then((res: any) => {
        if (res && res.code === 0){
            ElMessage.success('提交成功')
            getListData()
        }
    })
}

// 取消
const cancelSubmit = (row: any) => {
    row.isEdit = false
}

// 重置
const reset = () => {
    const nowDay = dayjs().format('YYYY-MM-DD')
    selectedDate.value = nowDay
    searchVal.value = {
        startTime: '',
        endTime: '',
        queryId: '1',
        pageIndex: 1,
        pageSize: 500,
    }
    setSearchValDate(nowDay)
    getMonthHeader(new Date())
    leftTree.value.getCompanyDepartmentTree()
    getListData()
}


// 推送企信
const pushQX = () => {
    isShowPushDialog.value = true
}

const closePushDialog = () => {
    isShowPushDialog.value = false
}

onMounted(() => {
    const nowDay = dayjs().format('YYYY-MM-DD')
    selectedDate.value = nowDay
    permissionTag.value = 'attendance_statistics'
    setSearchValDate(nowDay)
    getMonthHeader(nowDay)
})
</script>

<style scoped lang="scss">
::v-deep(.el-table-v2__row.is-hovered){
    background-color: #FFFFFF;
}
::v-deep(.el-empty__image){
    display: none;
}
.attendanceTableList{
    display: flex;
    height: 100%;
    min-height: 0;
    .left {
        min-width: 256px;
        padding: 5px;
        height: 100%;
        box-sizing: border-box;
        box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
    }
    .right {
        display: flex;
        flex-direction: column;
        margin-left: 20px;
        width: calc(100% - 276px);
        height: 100%;
        min-height: 0;
    }
}

.xiang{
    margin-left: 10px;
    color: #1890FF;
    font-weight: 550;
    cursor: pointer;
}
</style>