|
<template>
<div class="page-main1">
<div class="page-content">
<t-tabs v-model="activePanel" :animated="false">
<!-- 日报 -->
<t-tab-panel label="日报" panel-id="tab-1">
<div class="track-container">
<div class="search-container">
<div class="search-ctn">
<div>
<div style="display: flex;">
<t-date-picker v-model="dailyForm.workDay" style="width:200px" placeholder="请选择日期"></t-date-picker>
<template>
<t-button style="margin-left:10px" color="primary" icon="search-outline" @click="handSearchDay">查询</t-button>
</template>
<t-button icon="filter-outline" style="margin: 0 10px;" @click="slideVisible0 = !slideVisible0"></t-button>
</div>
</div>
<div class="btns">
<t-button>
<t-icon size="14" icon="upload-outline"></t-icon> 导出至Excel
</t-button>
<t-dropdown :visibled="customVisibled0" trigger-mode="custom">
<t-button slot="trigger" color="secondary" icon="tile-four-outline" class="trigger-button" @click="onTriggerClick"></t-button>
<div slot="popper">
<div style="border-radius: 5px;padding: 20px 20px 20px 20px;background-color: white;">
<t-checkbox-group v-model="social0" vertical @change="checkAllGroupChange">
<t-checkbox v-for="(item) in columns0" :key="item.label" :value="item.label" :label="item.label">
<span>{{ item.label }}</span>
</t-checkbox>
</t-checkbox-group>
<div style="padding-bottom: 10px">
<t-checkbox :indeterminate0="indeterminate0" :checked.sync="checkAll0" @click.prevent.native="handleCheckAll">全选
</t-checkbox>
</div>
<t-button color="primary" size="sm" @click="onCloseClick">确认</t-button>
</div>
</div>
</t-dropdown>
<t-button color="secondary" icon="loading" class="reset-btn" @click="resetDailyData"></t-button>
</div>
</div>
<div class="animate-demo-wrapper">
<transition name="slide-up">
<div v-show="slideVisible0" class="transition-box allCondition">
<div class="input-rule">
<span>部门/员工:</span>
<dept-staff-cascader v-model="dailyForm" @inited="handleDailyInited" @getOrgId="getDailyOrgId" @getDepId="getDailyDepId" @getStaffId="getDailyStaffId" />
</div>
</div>
</transition>
</div>
</div>
</div>
<t-table :data="dailyTableData" :loading="loadDailyTable" size="sm" line class="table-detail">
<t-table-column size="sm" type="selection"></t-table-column>
<t-table-column v-if="columns0[0].show" size="sm" prop="name" label="姓名"></t-table-column>
<t-table-column v-if="columns0[1].show" size="sm" prop="userid" label="员工编号"></t-table-column>
<t-table-column v-if="columns0[2].show" size="sm" prop="duty" label="职务"></t-table-column>
<t-table-column v-if="columns0[3].show" size="sm" prop="status" label="考勤状态">
<template slot-scope="scope">
<span :class="getStatusClass(scope.row.goToWorkStatus)">{{ scope.row.goToWorkStatus }}</span>
<span :class="getStatusClass(scope.row.goOffWorkStatus)">{{ scope.row.goOffWorkStatus }}</span>
</template>
</t-table-column>
</t-table>
<t-pager :page-size="dailyForm.pageSize" :current="dailyForm.current" :total="dailyTotal" :sizer-range="[ 5, 10, 20, 30 ]" class="pager" show-elevator @on-change="onChangeDay"></t-pager>
</t-tab-panel>
<!-- 月报 -->
<t-tab-panel label="月报" panel-id="tab-2">
<div class="track-container">
<div class="search-container">
<div class="search-ctn">
<div>
<div style="display: flex;">
<t-date-picker v-model="monthlyForm.month" style="width:200px" type="month" placeholder="请选择月份"></t-date-picker>
<template>
<t-button style="margin-left:10px" color="primary" icon="search-outline" @click="handSearchMonth">查询</t-button>
</template>
<t-button icon="filter-outline" style="margin: 0 10px;" @click="slideVisible1 = !slideVisible1"></t-button>
</div>
</div>
<div class="btns">
<t-button>
<t-icon size="14" icon="upload-outline"></t-icon> 导出至Excel
</t-button>
<t-dropdown :visibled="customVisibled1" trigger-mode="custom">
<t-button slot="trigger" color="secondary" icon="tile-four-outline" class="trigger-button" @click="onTriggerClick"></t-button>
<div slot="popper">
<div style="border-radius: 5px;padding: 20px 20px 20px 20px;background-color: white;">
<t-checkbox-group v-model="social1" vertical @change="checkAllGroupChange">
<t-checkbox v-for="(item) in columns1" :key="item.label" :value="item.label" :label="item.label">
<span>{{ item.label }}</span>
</t-checkbox>
</t-checkbox-group>
<div style="padding-bottom: 10px">
<t-checkbox :indeterminate0="indeterminate1" :checked.sync="checkAll1" @click.prevent.native="handleCheckAll">全选
</t-checkbox>
</div>
<t-button color="primary" size="sm" @click="onCloseClick">确认</t-button>
</div>
</div>
</t-dropdown>
<t-button color="secondary" icon="loading" class="reset-btn" @click="resetMonthData"></t-button>
</div>
</div>
<div class="animate-demo-wrapper">
<transition name="slide-up">
<div v-show="slideVisible1" class="transition-box allCondition">
<div class="input-rule">
<span>部门/员工:</span>
<dept-staff-cascader v-model="monthlyForm" @getOrgId="getMonthOrgId" @getDepId="getMonthDepId" @getStaffId="getMonthStaffId" />
<div class="search-btn">
</div>
</div>
</div>
</transition>
</div>
</div>
</div>
<t-table :data="monthTableData" :loading="loadMonthTable" size="sm" line class="table-detail">
<t-table-column type="selection"></t-table-column>
<t-table-column v-if="columns1[0].show" width="75" prop="name" label="姓名"></t-table-column>
<t-table-column v-if="columns1[1].show" width="90" prop="userid" label="员工编号"></t-table-column>
<t-table-column v-if="columns1[2].show" width="90" prop="duty" label="职务"></t-table-column>
<t-table-column v-if="columns1[3].show" width="120" prop="daysAttendance" label="出勤天数(天)"></t-table-column>
<t-table-column v-if="columns1[4].show" width="120" prop="timesLate" label="迟到次数(次)">
<template slot-scope="scope">
<span v-if="scope.row.timesLate===0" size="sm">{{ scope.row.timesLate }}</span>
<span v-else class="abnormalState">{{ scope.row.timesLate }}</span>
</template>
</t-table-column>
<t-table-column v-if="columns1[5].show" width="110" prop="hoursLate" label="迟到时长(h)">
<template slot-scope="scope">
<span v-if="scope.row.hoursLate===0" size="sm">{{ scope.row.hoursLate }}</span>
<span v-else class="abnormalState">{{ scope.row.hoursLate }}</span>
</template>
</t-table-column>
<t-table-column v-if="columns1[6].show" width="120" prop="timesLeftearly" label="早退次数(次)">
<template slot-scope="scope">
<span v-if="scope.row.timesLeftearly===0" size="sm">{{ scope.row.timesLeftearly }}</span>
<span v-else class="abnormalState">{{ scope.row.timesLeftearly }}</span>
</template>
</t-table-column>
<t-table-column v-if="columns1[7].show" width="120" prop="hoursLeftearly" label="早退时长(h)">
<template slot-scope="scope">
<span v-if="scope.row.hoursLeftearly===0" size="sm">{{ scope.row.hoursLeftearly }}</span>
<span v-else class="abnormalState">{{ scope.row.hoursLeftearly }}</span>
</template>
</t-table-column>
<t-table-column v-if="columns1[8].show" width="120" prop="timesAbsence" label="旷工次数(次)">
<template slot-scope="scope">
<span v-if="scope.row.timesAbsence===0" size="sm">{{ scope.row.timesAbsence }}</span>
<span v-else class="abnormalState">{{ scope.row.timesAbsence }}</span>
</template>
</t-table-column>
<t-table-column v-if="columns1[9].show" width="120" prop="daysAbsence" label="旷工时长(天)">
<template slot-scope="scope">
<span v-if="scope.row.daysAbsence===0" size="sm">{{ scope.row.daysAbsence }}</span>
<span v-else class="abnormalState">{{ scope.row.daysAbsence }}</span>
</template>
</t-table-column>
<t-table-column width="120" prop="operation" label="操作" fixed="right">
<template slot-scope="scope">
<a class="link" size="sm" @click="handleClick(scope.row)">详情</a>
</template>
</t-table-column>
</t-table>
<t-pager :page-size="monthlyForm.pageSize" :current="monthlyForm.current" :total="monthlyTotal" :sizer-range="[ 5, 10, 20, 30 ]" class="pager" show-elevator @on-change="onChangeMonth"></t-pager>
</t-tab-panel>
</t-tabs>
</div>
<attendance-dialog :visibled.sync="attendanceModal" :data="modalData" :loading="loadDetail" />
</div>
</template>
<script>
import atdapi from '@/api/attendance'
import formatDateTime from '@/utils/formatDateTime.js'
import AttendanceDialog from '../components/AttendanceDialog'
import DeptStaffCascader from '../components/DeptStaffCascader'
export default {
components: { AttendanceDialog, DeptStaffCascader },
data () {
const now = new Date()
return {
slideVisible0: false,
slideVisible1: false,
indeterminate0: true,
indeterminate1: true,
checkAll0: true,
checkAll1: true,
social0: ['姓名', '员工编号', '职务', '考勤状态'],
social1: ['姓名', '员工编号', '职务', '出勤天数(天)', '迟到次数(次)', '迟到时长(h)', '早退次数(次)', '早退时长(h)', '旷工次数(次)', '旷工时长(天)'],
columns0: [
{
label: '姓名',
show: true
}, {
label: '员工编号',
show: true
}, {
label: '职务',
show: true
}, {
label: '考勤状态',
show: true
}
],
columns1: [
{
label: '姓名',
show: true
}, {
label: '员工编号',
show: true
}, {
label: '职务',
show: true
}, {
label: '出勤天数(天)',
show: true
}, {
label: '迟到次数(次)',
show: true
}, {
label: '迟到时长(h)',
show: true
}, {
label: '早退次数(次)',
show: true
}, {
label: '早退时长(h)',
show: true
}, {
label: '旷工次数(次)',
show: true
}, {
label: '旷工时长(天)',
show: true
}
],
customVisibled0: false,
customVisibled1: false,
attendanceModal: false,
modalData: {},
tabName: 'tab-1',
dailyTableData: [],
monthTableData: [],
data: '',
loadDetail: false,
loadDailyTable: false,
loadMonthTable: false,
// 公司、部门、员工、列表
companyTypesList: [],
departmentTypesList: [],
getStaffTypesList: [],
monthlyTotal: 0,
dailyTotal: 0,
monthlyForm: {
month: formatDateTime(new Date().setMonth(now.getMonth() - 1), 'yyyy-MM'),
userid: null,
depId: '',
orgId: '',
current: 1,
pageSize: 10
},
dailyForm: {
workDay: formatDateTime(now, 'yyyy-MM-dd'),
userid: null,
depId: '',
orgId: '',
current: 1,
pageSize: 10
},
isFirstCreatedMonth: true,
isFirstCreatedDaily: true,
// 当前tab
activePanel: 'tab-1'
}
},
watch: {
activePanel () {
this.customVisibled0 = false
this.customVisibled1 = false
}
},
methods: {
checkAllGroupChange () {
if (this.activePanel === 'tab-1') {
if (this.social0.length === 4) {
this.indeterminate0 = false
this.checkAll0 = true
} else if (this.social0.length > 0) {
this.indeterminate0 = true
this.checkAll0 = false
} else {
this.indeterminate0 = false
this.checkAll0 = false
}
} else {
if (this.social1.length === 10) {
this.indeterminate1 = false
this.checkAll1 = true
} else if (this.social1.length > 0) {
this.indeterminate1 = true
this.checkAll1 = false
} else {
this.indeterminate1 = false
this.checkAll1 = false
}
}
},
handleCheckAll () {
if (this.activePanel === 'tab-1') {
if (this.indeterminate0) {
this.checkAll0 = false
} else {
this.checkAll0 = !this.checkAll0
}
this.indeterminate0 = false
if (this.checkAll0) {
this.social0 = ['姓名', '员工编号', '职务', '考勤状态']
} else {
this.social0 = []
}
} else {
if (this.indeterminate1) {
this.checkAll1 = false
} else {
this.checkAll1 = !this.checkAll1
}
this.indeterminate1 = false
if (this.checkAll1) {
this.social1 = ['姓名', '员工编号', '职务', '出勤天数(天)', '迟到次数(次)', '迟到时长(h)', '早退次数(次)', '早退时长(h)', '旷工次数(次)', '旷工时长(天)']
} else {
this.social1 = []
}
}
},
onTriggerClick () {
if (this.activePanel === 'tab-1') {
this.customVisibled0 = true
} else {
this.customVisibled1 = true
// 我加了一个这个事件 避免点击事件时对话框不显示
window.scrollTo(0, 1)
}
},
onCloseClick () {
if (this.activePanel === 'tab-1') {
this.columns0.forEach(e => {
e.show = this.social0.indexOf(e.label) >= 0
})
this.customVisibled0 = false
} else {
this.columns1.forEach(e => {
e.show = this.social1.indexOf(e.label) >= 0
})
this.customVisibled1 = false
}
},
getDailyOrgId (id) {
this.dailyForm.orgId = id
},
getDailyDepId (id) {
this.dailyForm.depId = id
// 第一次创建获取日报表格数据
if (this.isFirstCreatedDaily) {
this.isFirstCreatedDaily = false
this.getDailyTable()
}
},
getDailyStaffId (id) {
this.dailyForm.userid = id
},
getMonthOrgId (id) {
this.monthlyForm.orgId = id
},
getMonthDepId (id) {
this.monthlyForm.depId = id
// 第一次创建获取月报表格数据
if (this.isFirstCreatedMonth) {
this.isFirstCreatedMonth = false
this.getMonthTable()
}
},
getMonthStaffId (id) {
this.monthlyForm.userid = id
},
handleDailyInited () {
// this.getDailyTable()
},
// 搜索
handSearchDay () {
if (this.dailyForm.workDay && this.dailyForm.orgId) {
this.dailyForm.current = 1
this.getDailyTable()
} else { return this.$Message.warning('请选择时间和部门') }
},
handSearchMonth () {
if (this.monthlyForm.month && this.monthlyForm.orgId) {
this.monthlyForm.current = 1
this.getMonthTable()
} else { return this.$Message.warning('请选择时间和部门') }
},
// 分页
onChangeDay (val) {
this.dailyForm.current = val
this.getDailyTable()
},
onChangeMonth (val) {
this.monthlyForm.current = val
this.getMonthTable()
},
// // 向服务器发送请求获取公司类型列表数据
// async getCompanyTypesList () {
// const res = await commonApi.getCompanyTypesList()
// if (res.status === 200) {
// this.companyTypesList = res.data.data
// } else {
// this.$Message.danger('公司类型列表数据获取失败!')
// }
// },
// // 获取部门列表
// async queryCycleChildOrg (id) {
// const res = await commonApi.queryCycleChildOrg(id)
// if (res.status === 200) {
// const data = []
// // 递归 实现tree组件所需部门数据结构
// this.nextDepartment(res.data, data)
// // 深拷贝data
// const data1 = JSON.parse(JSON.stringify(data))
// // 用部门id映射关系代替code与parentCode父子映射关系
// data.forEach(item => {
// // 删除pid为"-1"的的pid属性,否则tree渲染的时候没有根节点渲染不出来
// if (item.pid === '-1') {
// delete item.pid
// }
// item.id = item.orgId
// data1.some((item1) => {
// if (item.pid === item1.id) {
// item.pid = item1.orgId
// } else {
// return false
// }
// })
// })
// // eslint-disable-next-line no-return-assign
// this.departmentTypesList = data.filter(item => item.data = item.id)
// } else {
// this.$Message.danger('部门类型列表数据获取失败!')
// }
// },
// // 向服务器发送请求获取用户类型列表数据
// async getStaffTypesList (id) {
// const res = await commonApi.getStaffTypesList(id)
// if (res.status === 200) {
// this.staffTypesList = res.data.data
// } else {
// this.$Message.danger('用户类型列表数据获取失败!')
// }
// },
// // 如果部门还有下级 递归
// nextDepartment (data, arr) {
// if (data.length > 0) {
// data.forEach(item => {
// arr.push({
// orgId: item.id + '',
// id: item.code,
// label: item.name,
// pid: item.parentCode
// })
// this.nextDepartment(item.departments, arr)
// })
// }
// },
// 重置日报数据
resetDailyData () {
this.$nextTick(() => {
this.dailyForm = {
workDay: '',
userid: null,
depId: '',
orgId: '',
current: 1,
pageSize: 10
}
})
},
// 重置月报数据
resetMonthData () {
this.monthlyForm = {
month: '',
userid: null,
depId: '',
orgId: '',
current: 1,
pageSize: 10
}
},
// 获得月报表格数据
getMonthTable () {
this.loadMonthTable = true
atdapi.getMonthAttendance({ params: this.monthlyForm }).then(res => {
let tableData = res.data.data
this.monthTableData = []
tableData.forEach(element => {
this.monthTableData.push(element)
})
this.monthlyTotal = res.data.total
}).finally(() => {
this.loadMonthTable = false
})
},
// 获得日报表格数据
getDailyTable () {
this.loadDailyTable = true
atdapi.getDayAttendance({ params: this.dailyForm }).then(res => {
let tableData = res.data.data
this.dailyTableData = []
tableData.forEach(element => {
this.dailyTableData.push(element)
})
this.dailyTotal = res.data.total
}).finally(() => {
this.loadDailyTable = false
})
},
// 弹窗打开
handleClick (data) {
const { userid, beginDay, endDay } = data
if (beginDay == null) {
this.$Message.danger('未识别到有效的起止日期')
return
}
this.loadDetail = true
this.modalData = Object.assign({}, data)
this.attendanceModal = true
this.modalData.range = [beginDay, endDay]
atdapi.getAttendanceDetail({
params: { userid, beginDay, endDay }
}).then(res => {
const { detail } = res.data
this.modalData.detail = detail
}).finally(() => {
this.loadDetail = false
})
},
getStatusClass (status) {
if (status === '未打卡') {
return 'abnormalState'
}
return ''
}
}
}
</script>
<style lang="scss" scoped>
.page-main1 {
margin: 20px 20px 16px 20px;
.abnormalState {
color: #eda30f;
font-size: 14px;
}
.track-container {
width: 100%;
margin: 24px 0;
// padding: 20px;
box-sizing: border-box;
.search-container {
width: 100%;
.search-ctn {
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
display: flex;
position: relative;
> div {
// margin: 0 20px 16px 0;
line-height: 2;
}
.btns {
margin-left: auto;
display: block;
button {
margin: 0 2px;
}
}
}
}
.table-pager {
margin: 20px auto;
}
.allCondition {
display: flex;
justify-content: space-between;
border: 1px solid rgba(0, 0, 0, 0.09);
background-color: #f8f9fa;
flex-wrap: wrap;
padding: 20px;
margin: 5px auto;
.input-rule {
display: flex;
flex: 1;
width: 80%;
min-width: 80%;
max-width: 80%;
padding: 10px 0 10px 20px;
> span {
line-height: 32px;
}
}
}
}
.table-detail {
margin-top: 20px;
}
.pager {
margin-right: auto;
margin: 21px 21px 0 0;
float: right;
}
}
</style>
|