编辑 | blame | 历史 | 原始文档

HRM 考勤管理补充功能 - 前端修改文档

概述

本次补充了考勤管理的核心功能:考勤规则管理、节假日配置、员工打卡、考勤统计汇总。


一、考勤规则管理

涉及页面

  • 考勤规则列表页面(新增)
  • 考勤规则新增/编辑弹窗(新增)

API

方法 路径 说明
POST /hrm/attendance/rule/create 新增考勤规则
PUT /hrm/attendance/rule/update 更新考勤规则
DELETE /hrm/attendance/rule/delete 删除考勤规则
GET /hrm/attendance/rule/get 获得考勤规则详情
GET /hrm/attendance/rule/page 获得考勤规则分页列表
GET /hrm/attendance/rule/list 获得考勤规则列表(启用状态)
GET /hrm/attendance/rule/export-excel 导出考勤规则 Excel

请求参数(create/update):

参数 类型 必填 说明
id Long 规则ID(修改时必填)
name String 规则名称
deptId Long 适用部门ID(空表示全局)
workStartTime String 上班时间,格式:HH:mm:ss
workEndTime String 下班时间,格式:HH:mm:ss
lateAllowMinutes Integer 迟到允许分钟数,默认 0
earlyAllowMinutes Integer 早退允许分钟数,默认 0
overtimeThreshold BigDecimal 加班起算时长(小时),默认 1
status Integer 状态:0-启用,1-禁用
remark String 备注

响应: { "code": 200, "data": 1, "msg": "操作成功" }

前端修改点

1. 路由配置

// src/router/modules/hrm.js
{
  path: 'rule',
  name: 'HrmAttendanceRule',
  component: () => import('@/views/hrm/attendance/rule/index'),
  meta: { title: '考勤规则', icon: 'setting' }
}

2. 列表页面表格

<el-table :data="list">
  <el-table-column label="规则名称" prop="name" />
  <el-table-column label="适用部门" prop="deptName">
    <template #default="{ row }">
      {{ row.deptName || '全局' }}
    </template>
  </el-table-column>
  <el-table-column label="上班时间" prop="workStartTime" />
  <el-table-column label="下班时间" prop="workEndTime" />
  <el-table-column label="迟到允许(分钟)" prop="lateAllowMinutes" />
  <el-table-column label="早退允许(分钟)" prop="earlyAllowMinutes" />
  <el-table-column label="加班起算(小时)" prop="overtimeThreshold" />
  <el-table-column label="状态" prop="status">
    <template #default="{ row }">
      <el-tag :type="row.status === 0 ? 'success' : 'danger'">
        {{ row.status === 0 ? '启用' : '禁用' }}
      </el-tag>
    </template>
  </el-table-column>
  <el-table-column label="操作" width="180">
    <template #default="{ row }">
      <el-button type="primary" link @click="handleUpdate(row)">编辑</el-button>
      <el-button type="danger" link @click="handleDelete(row.id)">删除</el-button>
    </template>
  </el-table-column>
</el-table>

3. 新增/编辑表单

<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
  <el-form-item label="规则名称" prop="name">
    <el-input v-model="form.name" placeholder="请输入规则名称" />
  </el-form-item>
  <el-form-item label="适用部门" prop="deptId">
    <el-tree-select
      v-model="form.deptId"
      :data="deptList"
      :props="{ label: 'name', value: 'id' }"
      placeholder="请选择部门(不选表示全局)"
      clearable
      check-strictly
    />
  </el-form-item>
  <el-form-item label="上班时间" prop="workStartTime">
    <el-time-picker v-model="form.workStartTime" value-format="HH:mm:ss" placeholder="选择上班时间" />
  </el-form-item>
  <el-form-item label="下班时间" prop="workEndTime">
    <el-time-picker v-model="form.workEndTime" value-format="HH:mm:ss" placeholder="选择下班时间" />
  </el-form-item>
  <el-form-item label="迟到允许" prop="lateAllowMinutes">
    <el-input-number v-model="form.lateAllowMinutes" :min="0" :max="60" placeholder="分钟" />
  </el-form-item>
  <el-form-item label="早退允许" prop="earlyAllowMinutes">
    <el-input-number v-model="form.earlyAllowMinutes" :min="0" :max="60" placeholder="分钟" />
  </el-form-item>
  <el-form-item label="加班起算" prop="overtimeThreshold">
    <el-input-number v-model="form.overtimeThreshold" :min="0" :precision="1" placeholder="小时" />
  </el-form-item>
  <el-form-item label="状态" prop="status">
    <el-radio-group v-model="form.status">
      <el-radio :value="0">启用</el-radio>
      <el-radio :value="1">禁用</el-radio>
    </el-radio-group>
  </el-form-item>
  <el-form-item label="备注" prop="remark">
    <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
  </el-form-item>
</el-form>

4. API 方法

// src/api/hrm/attendance.js
export function getAttendanceRulePage(params) {
  return request({ url: '/hrm/attendance/rule/page', method: 'get', params })
}

export function getAttendanceRuleList() {
  return request({ url: '/hrm/attendance/rule/list', method: 'get' })
}

export function createAttendanceRule(data) {
  return request({ url: '/hrm/attendance/rule/create', method: 'post', data })
}

export function updateAttendanceRule(data) {
  return request({ url: '/hrm/attendance/rule/update', method: 'put', data })
}

export function deleteAttendanceRule(id) {
  return request({ url: '/hrm/attendance/rule/delete', method: 'delete', params: { id } })
}

二、节假日配置

涉及页面

  • 节假日配置列表页面(新增)
  • 节假日新增/编辑弹窗(新增)

API

方法 路径 说明
POST /hrm/attendance/holiday/create 新增节假日
PUT /hrm/attendance/holiday/update 更新节假日
DELETE /hrm/attendance/holiday/delete 删除节假日
GET /hrm/attendance/holiday/get 获得节假日详情
GET /hrm/attendance/holiday/page 获得节假日分页列表
GET /hrm/attendance/holiday/export-excel 导出节假日 Excel

请求参数(create/update):

参数 类型 必填 说明
id Long 节假日ID(修改时必填)
name String 节假日名称
date String 日期,格式:yyyy-MM-dd
type Integer 类型:1-休息日,2-工作日
isLegal Integer 是否法定节假日:0-否,1-是
remark String 备注

前端修改点

1. 列表页面

<el-table :data="list">
  <el-table-column label="节假日名称" prop="name" />
  <el-table-column label="日期" prop="date" />
  <el-table-column label="类型" prop="type">
    <template #default="{ row }">
      <el-tag :type="row.type === 1 ? 'warning' : 'success'">
        {{ row.type === 1 ? '休息日' : '工作日' }}
      </el-tag>
    </template>
  </el-table-column>
  <el-table-column label="法定节假日" prop="isLegal">
    <template #default="{ row }">
      <el-tag v-if="row.isLegal === 1" type="danger">法定</el-tag>
      <span v-else>-</span>
    </template>
  </el-table-column>
  <el-table-column label="备注" prop="remark" />
  <el-table-column label="操作" width="180">
    <template #default="{ row }">
      <el-button type="primary" link @click="handleUpdate(row)">编辑</el-button>
      <el-button type="danger" link @click="handleDelete(row.id)">删除</el-button>
    </template>
  </el-table-column>
</el-table>

2. 表单

<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
  <el-form-item label="节假日名称" prop="name">
    <el-input v-model="form.name" placeholder="如:春节、国庆节" />
  </el-form-item>
  <el-form-item label="日期" prop="date">
    <el-date-picker v-model="form.date" value-format="YYYY-MM-DD" placeholder="选择日期" />
  </el-form-item>
  <el-form-item label="类型" prop="type">
    <el-radio-group v-model="form.type">
      <el-radio :value="1">休息日</el-radio>
      <el-radio :value="2">工作日(调休)</el-radio>
    </el-radio-group>
  </el-form-item>
  <el-form-item label="法定节假日" prop="isLegal">
    <el-checkbox v-model="form.isLegal" :true-value="1" :false-value="0">是法定节假日</el-checkbox>
  </el-form-item>
  <el-form-item label="备注" prop="remark">
    <el-input v-model="form.remark" type="textarea" />
  </el-form-item>
</el-form>

3. API 方法

export function getAttendanceHolidayPage(params) {
  return request({ url: '/hrm/attendance/holiday/page', method: 'get', params })
}

export function createAttendanceHoliday(data) {
  return request({ url: '/hrm/attendance/holiday/create', method: 'post', data })
}

export function updateAttendanceHoliday(data) {
  return request({ url: '/hrm/attendance/holiday/update', method: 'put', data })
}

export function deleteAttendanceHoliday(id) {
  return request({ url: '/hrm/attendance/holiday/delete', method: 'delete', params: { id } })
}

三、员工打卡

涉及页面

  • 考勤记录列表页面(已有,扩展功能)
  • 打卡按钮/组件(新增)

API

方法 路径 说明
POST /hrm/attendance/record/clock-in 上班打卡
POST /hrm/attendance/record/clock-out 下班打卡

请求参数:

参数 类型 必填 说明
location String 打卡地点

响应(打卡成功):

{
  "code": 200,
  "data": {
    "id": 1,
    "userId": 100,
    "userName": "张三",
    "deptId": 1,
    "deptName": "研发部",
    "date": "2024-01-15",
    "clockInTime": "2024-01-15T09:05:00",
    "clockInType": 1,
    "clockOutTime": null,
    "clockOutType": null,
    "workHours": null,
    "location": "公司前台"
  }
}

前端修改点

1. 打卡按钮组件

<template>
  <div class="clock-container">
    <el-button type="primary" size="large" @click="handleClockIn">
      <el-icon><Clock /></el-icon>
      上班打卡
    </el-button>
    <el-button type="success" size="large" @click="handleClockOut">
      <el-icon><Clock /></el-icon>
      下班打卡
    </el-button>
    <div v-if="clockStatus" class="clock-status">
      <p>今日打卡状态:</p>
      <p>上班:{{ clockStatus.clockInTime || '未打卡' }}
        <el-tag v-if="clockStatus.clockInType === 2" type="warning">迟到</el-tag>
      </p>
      <p>下班:{{ clockStatus.clockOutTime || '未打卡' }}
        <el-tag v-if="clockStatus.clockOutType === 3" type="warning">早退</el-tag>
      </p>
    </div>
  </div>
</template>

<script setup>
import { clockIn, clockOut } from '@/api/hrm/attendance'
import { ElMessage } from 'element-plus'

const location = ref('公司前台')

const handleClockIn = async () => {
  try {
    const res = await clockIn({ location: location.value })
    ElMessage.success('上班打卡成功')
    // 更新打卡状态显示
  } catch (e) {
    ElMessage.error(e.message || '打卡失败')
  }
}

const handleClockOut = async () => {
  try {
    const res = await clockOut({ location: location.value })
    ElMessage.success('下班打卡成功')
  } catch (e) {
    ElMessage.error(e.message || '打卡失败')
  }
}
</script>

2. API 方法

export function clockIn(params) {
  return request({ url: '/hrm/attendance/record/clock-in', method: 'post', params })
}

export function clockOut(params) {
  return request({ url: '/hrm/attendance/record/clock-out', method: 'post', params })
}

四、考勤统计汇总

涉及页面

  • 考勤统计列表页面(新增)
  • 统计生成弹窗(新增)

API

方法 路径 说明
GET /hrm/attendance/summary/page 获得考勤统计分页列表
GET /hrm/attendance/summary/get 获得员工月度汇总
POST /hrm/attendance/summary/generate 生成月度考勤汇总
GET /hrm/attendance/summary/export-excel 导出考勤统计 Excel

请求参数(generate):

参数 类型 必填 说明
yearMonth String 年月,格式:yyyy-MM
deptId Long 部门ID(指定部门时填写)
userId Long 员工ID(指定员工时填写)

前端修改点

1. 列表页面

<el-form :inline="true">
  <el-form-item label="年月">
    <el-date-picker v-model="queryParams.yearMonth" type="month" value-format="YYYY-MM" placeholder="选择年月" />
  </el-form-item>
  <el-form-item label="部门">
    <el-tree-select v-model="queryParams.deptId" :data="deptList" clearable check-strictly placeholder="选择部门" />
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="handleQuery">搜索</el-button>
    <el-button type="success" @click="handleGenerate">生成统计</el-button>
    <el-button type="warning" @click="handleExport">导出</el-button>
  </el-form-item>
</el-form>

<el-table :data="list">
  <el-table-column label="员工姓名" prop="userName" />
  <el-table-column label="部门" prop="deptName" />
  <el-table-column label="年月" prop="yearMonth" />
  <el-table-column label="应出勤天数" prop="workDays" />
  <el-table-column label="实际出勤天数" prop="actualDays" />
  <el-table-column label="迟到次数" prop="lateCount">
    <template #default="{ row }">
      <el-tag v-if="row.lateCount > 0" type="warning">{{ row.lateCount }}</el-tag>
      <span v-else>{{ row.lateCount }}</span>
    </template>
  </el-table-column>
  <el-table-column label="早退次数" prop="earlyCount">
    <template #default="{ row }">
      <el-tag v-if="row.earlyCount > 0" type="warning">{{ row.earlyCount }}</el-tag>
      <span v-else>{{ row.earlyCount }}</span>
    </template>
  </el-table-column>
  <el-table-column label="缺卡次数" prop="absentCount">
    <template #default="{ row }">
      <el-tag v-if="row.absentCount > 0" type="danger">{{ row.absentCount }}</el-tag>
      <span v-else>{{ row.absentCount }}</span>
    </template>
  </el-table-column>
  <el-table-column label="加班时长(h)" prop="overtimeHours" />
  <el-table-column label="请假时长(h)" prop="leaveHours" />
</el-table>

2. 生成统计弹窗

<el-dialog title="生成考勤统计" v-model="generateVisible">
  <el-form :model="generateForm" label-width="100px">
    <el-form-item label="年月">
      <el-date-picker v-model="generateForm.yearMonth" type="month" value-format="YYYY-MM" placeholder="选择年月" />
    </el-form-item>
    <el-form-item label="生成范围">
      <el-radio-group v-model="generateForm.rangeType">
        <el-radio value="all">全公司</el-radio>
        <el-radio value="dept">指定部门</el-radio>
        <el-radio value="user">指定员工</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item v-if="generateForm.rangeType === 'dept'" label="部门">
      <el-tree-select v-model="generateForm.deptId" :data="deptList" check-strictly placeholder="选择部门" />
    </el-form-item>
    <el-form-item v-if="generateForm.rangeType === 'user'" label="员工">
      <el-select v-model="generateForm.userId" filterable placeholder="选择员工">
        <el-option v-for="item in employeeList" :key="item.id" :label="item.name" :value="item.id" />
      </el-select>
    </el-form-item>
  </el-form>
  <template #footer>
    <el-button @click="generateVisible = false">取消</el-button>
    <el-button type="primary" @click="handleGenerateSubmit">生成</el-button>
  </template>
</el-dialog>

3. API 方法

export function getAttendanceSummaryPage(params) {
  return request({ url: '/hrm/attendance/summary/page', method: 'get', params })
}

export function getMonthlySummary(params) {
  return request({ url: '/hrm/attendance/summary/get', method: 'get', params })
}

export function generateSummary(params) {
  return request({ url: '/hrm/attendance/summary/generate', method: 'post', params })
}

五、考勤异常申请提交

修改点

原提交接口 /hrm/attendance/exception/submit 需增加 processDefinitionKey 参数。

原接口:
js POST /hrm/attendance/exception/submit?id=xxx

新接口:
js POST /hrm/attendance/exception/submit?id=xxx&processDefinitionKey=xxx

前端修改

<!-- 提交弹窗增加流程选择 -->
<el-dialog title="提交补卡申请" v-model="submitVisible">
  <el-form :model="submitForm" label-width="100px">
    <el-form-item label="审批流程">
      <el-select v-model="submitForm.processDefinitionKey" placeholder="选择审批流程">
        <el-option v-for="item in processList" :key="item.key" :label="item.name" :value="item.key" />
      </el-select>
    </el-form-item>
  </el-form>
  <template #footer>
    <el-button @click="submitVisible = false">取消</el-button>
    <el-button type="primary" @click="handleSubmit">提交</el-button>
  </template>
</el-dialog>
// 提交方法
const handleSubmit = async () => {
  await submitException({
    id: currentId,
    processDefinitionKey: submitForm.processDefinitionKey
  })
  ElMessage.success('提交成功')
  submitVisible = false
  getList()
}

六、字典数据配置

在系统字典管理中添加以下字典:

1. hrm_clock_type - 打卡类型

字典值 字典标签
1 正常
2 迟到
3 早退
4 缺卡

2. hrm_holiday_type - 节假日类型

字典值 字典标签
1 休息日
2 工作日

3. hrm_is_legal_holiday - 是否法定节假日

字典值 字典标签
0
1

4. hrm_data_source - 数据来源

字典值 字典标签
1 打卡
2 导入
3 补卡审批

七、菜单配置

在系统菜单中确认以下菜单已配置:

菜单ID 菜单名称 路由路径 组件路径
6013 考勤规则 rule hrm/attendance/rule/index
6014 节假日配置 holiday hrm/attendance/holiday/index
6015 考勤统计 summary hrm/attendance/summary/index

注意事项

  1. 打卡逻辑:打卡会自动判断是否工作日、迟到、早退,前端只需传入打卡地点即可
  2. 考勤规则优先级:部门专属规则优先,其次查找全局规则(不选部门)
  3. 节假日判断:有配置则按配置,无配置则按周末判断(周六周日为休息日)
  4. 补卡审批:审批通过后会自动更新考勤记录,无需手动操作
  5. 统计生成:建议每月结束后手动触发生成统计,或配置定时任务自动生成