hrm前端一版
This commit is contained in:
226
klp-ui/src/views/hrm/attendance/index.vue
Normal file
226
klp-ui/src/views/hrm/attendance/index.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="hrm-page">
|
||||
<section class="panel-grid triple">
|
||||
<el-card class="metal-panel" shadow="hover">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>班次</span>
|
||||
<el-button size="mini" icon="el-icon-refresh" @click="loadShift">刷新</el-button>
|
||||
</div>
|
||||
<el-table :data="shiftList" v-loading="shiftLoading" height="320" stripe>
|
||||
<el-table-column label="名称" prop="shiftName" min-width="140" />
|
||||
<el-table-column label="时间段" min-width="180">
|
||||
<template slot-scope="scope">{{ scope.row.startTime }} - {{ scope.row.endTime }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="夜班" prop="nightShift" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="mini" :type="scope.row.nightShift ? 'warning' : 'info'">
|
||||
{{ scope.row.nightShift ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="休息" prop="restMinutes" min-width="100" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card class="metal-panel" shadow="hover">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>排班</span>
|
||||
<div class="actions-inline">
|
||||
<el-date-picker
|
||||
v-model="scheduleQuery.date"
|
||||
type="date"
|
||||
placeholder="日期"
|
||||
size="mini"
|
||||
value-format="yyyy-MM-dd"
|
||||
@change="loadSchedule"
|
||||
/>
|
||||
<el-button size="mini" type="primary" @click="loadSchedule">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="scheduleList" v-loading="scheduleLoading" height="320" stripe>
|
||||
<el-table-column label="员工" prop="empId" min-width="100" />
|
||||
<el-table-column label="日期" prop="workDate" min-width="120" />
|
||||
<el-table-column label="班次" prop="shiftId" min-width="120" />
|
||||
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card class="metal-panel" shadow="hover">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>打卡与考勤结果</span>
|
||||
<div class="actions-inline">
|
||||
<el-date-picker
|
||||
v-model="punchQuery.range"
|
||||
type="daterange"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
size="mini"
|
||||
value-format="yyyy-MM-dd"
|
||||
@change="loadPunchAndAttend"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dual-tables">
|
||||
<div class="table-half">
|
||||
<div class="table-title">打卡记录</div>
|
||||
<el-table :data="punchList" v-loading="punchLoading" height="230" stripe>
|
||||
<el-table-column label="时间" prop="punchTime" min-width="150">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.punchTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="来源" prop="source" min-width="100" />
|
||||
<el-table-column label="定位/设备" prop="location" min-width="140" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="table-half">
|
||||
<div class="table-title">考勤结果</div>
|
||||
<el-table :data="attendList" v-loading="attendLoading" height="230" stripe>
|
||||
<el-table-column label="日期" prop="workDate" min-width="120" />
|
||||
<el-table-column label="出勤分钟" prop="attendMinutes" min-width="110" />
|
||||
<el-table-column label="加班分钟" prop="overtimeMinutes" min-width="110" />
|
||||
<el-table-column label="请假分钟" prop="leaveMinutes" min-width="110" />
|
||||
<el-table-column label="异常" prop="exceptionMsg" min-width="140" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<span :class="['exception-tag', scope.row.exceptionMsg ? 'is-error' : '']">
|
||||
{{ scope.row.exceptionMsg || '正常' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listShift, listSchedule, listPunch, listAttendCalc } from '@/api/hrm'
|
||||
|
||||
export default {
|
||||
name: 'HrmAttendance',
|
||||
data() {
|
||||
return {
|
||||
shiftList: [],
|
||||
shiftLoading: false,
|
||||
scheduleList: [],
|
||||
scheduleLoading: false,
|
||||
scheduleQuery: { date: '' },
|
||||
punchList: [],
|
||||
punchLoading: false,
|
||||
punchQuery: { range: [] },
|
||||
attendList: [],
|
||||
attendLoading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadShift()
|
||||
this.loadSchedule()
|
||||
this.loadPunchAndAttend()
|
||||
},
|
||||
methods: {
|
||||
formatDate(val) {
|
||||
if (!val) return ''
|
||||
const date = new Date(val)
|
||||
const pad = n => (n < 10 ? `0${n}` : n)
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||||
},
|
||||
loadShift() {
|
||||
this.shiftLoading = true
|
||||
listShift({ pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.shiftList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.shiftLoading = false
|
||||
})
|
||||
},
|
||||
loadSchedule() {
|
||||
this.scheduleLoading = true
|
||||
listSchedule({ ...this.scheduleQuery, pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.scheduleList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.scheduleLoading = false
|
||||
})
|
||||
},
|
||||
loadPunchAndAttend() {
|
||||
this.punchLoading = true
|
||||
this.attendLoading = true
|
||||
const [startTime, endTime] = this.punchQuery.range || []
|
||||
listPunch({ pageNum: 1, pageSize: 200, startTime, endTime })
|
||||
.then(res => {
|
||||
this.punchList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.punchLoading = false
|
||||
})
|
||||
listAttendCalc({ pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.attendList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.attendLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.hrm-page {
|
||||
padding: 16px 20px 32px;
|
||||
background: #f8f9fb;
|
||||
}
|
||||
.panel-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 14px;
|
||||
}
|
||||
.metal-panel {
|
||||
border: 1px solid #d7d9df;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
}
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
.actions-inline {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.dual-tables {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
.table-half {
|
||||
border: 1px dashed #e6e8ed;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
.table-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.exception-tag {
|
||||
color: #409eff;
|
||||
&.is-error {
|
||||
color: #e76f51;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.panel-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.dual-tables {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user