You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.5人力资源应用:请假天数计算与更新问题求助

解决Laravel HR应用中请假天数扣除与更新的问题

嘿,我来帮你捋捋这个请假天数计算的核心问题!咱们从数据库结构、后端逻辑到前端交互一步步拆解,确保你能顺利打通这个环节:

一、先理清楚数据库表的核心结构

假设你的两张表可以这样设计(可根据公司规则调整字段):

1. 员工请假额度分配表 (employee_leave_allocations)

这张表存每个员工每年的各类假期分配额度:

Schema::create('employee_leave_allocations', function (Blueprint $table) {
    $table->id();
    $table->foreignId('employee_id')->constrained()->onDelete('cascade');
    $table->foreignId('leave_type_id')->constrained(); -- 关联年假、病假等类型表
    $table->decimal('allocated_days', 5, 2); -- 总分配天数
    $table->decimal('used_days', 5, 2)->default(0); -- 已用天数
    $table->decimal('remaining_days', 5, 2); -- 剩余天数
    $table->year('allocation_year'); -- 按年度区分,避免跨年度混乱
    $table->timestamps();
});

2. 请假申请表 (leave_applications)

这张表存员工提交的请假申请记录:

Schema::create('leave_applications', function (Blueprint $table) {
    $table->id();
    $table->foreignId('employee_id')->constrained()->onDelete('cascade');
    $table->foreignId('leave_type_id')->constrained();
    $table->date('start_date');
    $table->date('end_date');
    $table->decimal('total_days', 5, 2); -- 申请的实际天数(已计算好工作日/自然日)
    $table->enum('status', ['pending', 'approved', 'rejected'])->default('pending');
    $table->text('reason')->nullable();
    $table->timestamps();
});

二、后端Laravel的核心逻辑实现

当请假申请被批准时,要自动扣除对应额度,这里的关键是确保数据一致性,建议用事务包裹操作:

1. 先写个工具方法计算请假天数

根据公司规则区分工作日/自然日,用Carbon处理更方便:

use Carbon\Carbon;

function calculateLeaveDays($startDate, $endDate, $countWorkingDays = true)
{
    $start = Carbon::parse($startDate);
    $end = Carbon::parse($endDate);
    
    if ($countWorkingDays) {
        // 计算工作日(排除周六周日,可额外加节假日排除逻辑)
        return $start->diffInWeekdays($end) + 1; // +1是包含开始当天
    } else {
        // 计算自然日
        return $start->diffInDays($end) + 1;
    }
}

2. 批准申请时更新额度的逻辑

在控制器的批准方法里加这段逻辑:

public function approve(Request $request, $id)
{
    DB::beginTransaction();
    try {
        $application = LeaveApplication::findOrFail($id);
        $application->status = 'approved';
        $application->save();

        // 获取该员工当前年度对应假期类型的额度记录
        $allocation = EmployeeLeaveAllocation::where('employee_id', $application->employee_id)
            ->where('leave_type_id', $application->leave_type_id)
            ->where('allocation_year', date('Y'))
            ->firstOrFail();

        // 更新已用和剩余天数
        $allocation->used_days += $application->total_days;
        $allocation->remaining_days = $allocation->allocated_days - $allocation->used_days;
        $allocation->save();

        DB::commit();
        return redirect()->back()->with('success', '申请已批准,假期额度已更新');
    } catch (\Exception $e) {
        DB::rollBack();
        return redirect()->back()->with('error', '批准失败:'.$e->getMessage());
    }
}

三、前端JS交互优化(结合你给出的代码片段)

你的JS开头应该是要实现「选择员工/假期类型后加载当前额度,实时校验申请天数」的功能,完善后的代码示例:

var baseUrl = $("#base_url").val(); 
var currentRemaining = 0; 
var currentUsed = 0; 

$(document).ready(function() {
    // 选择员工后加载其可用假期类型
    $('#employee_id').on('change', function() {
        const empId = $(this).val();
        if (!empId) return;

        $.ajax({
            url: `${baseUrl}/employee-leaves/${empId}`,
            type: 'GET',
            success: function(res) {
                $('#leave_type_id').empty();
                res.forEach(leave => {
                    $('#leave_type_id').append(`
                        <option value="${leave.id}" 
                            data-remaining="${leave.remaining_days}" 
                            data-used="${leave.used_days}">
                            ${leave.type_name}(剩余${leave.remaining_days}天)
                        </option>
                    `);
                });
                // 默认加载第一个选项的额度信息
                updateLeaveInfo();
            }
        });
    });

    // 切换假期类型时更新额度显示
    $('#leave_type_id').on('change', updateLeaveInfo);

    // 选择起止日期后计算申请天数并校验额度
    $('#start_date, #end_date').on('change', function() {
        const start = $('#start_date').val();
        const end = $('#end_date').val();
        if (!start || !end) return;

        $.ajax({
            url: `${baseUrl}/calculate-leave-days`,
            type: 'POST',
            data: {
                start_date: start,
                end_date: end,
                _token: $('meta[name="csrf-token"]').attr('content')
            },
            success: function(res) {
                const requestedDays = res.total_days;
                $('#total_days').val(requestedDays);

                // 校验是否超过剩余额度
                if (requestedDays > currentRemaining) {
                    $('#error-tip').text(`申请天数超过剩余额度,最多可申请${currentRemaining}天`).show();
                } else {
                    $('#error-tip').hide();
                }
            }
        });
    });

    // 更新当前选中假期的额度信息
    function updateLeaveInfo() {
        const selected = $('#leave_type_id option:selected');
        currentRemaining = parseFloat(selected.data('remaining'));
        currentUsed = parseFloat(selected.data('used'));
        
        $('#leave-info').text(`已使用${currentUsed}天,剩余${currentRemaining}天`);
    }
});

对应的Laravel路由和控制器方法:

// 路由
Route::get('/employee-leaves/{empId}', [LeaveController::class, 'getEmployeeLeaves']);
Route::post('/calculate-leave-days', [LeaveController::class, 'calculateLeaveDays']);

// 控制器方法
public function getEmployeeLeaves($empId)
{
    $leaves = EmployeeLeaveAllocation::where('employee_id', $empId)
        ->where('allocation_year', date('Y'))
        ->with('leaveType')
        ->get()
        ->map(function($item) {
            return [
                'id' => $item->leave_type_id,
                'type_name' => $item->leaveType->name,
                'remaining_days' => $item->remaining_days,
                'used_days' => $item->used_days
            ];
        });
    return response()->json($leaves);
}

public function calculateLeaveDays(Request $request)
{
    $days = calculateLeaveDays($request->start_date, $request->end_date);
    return response()->json(['total_days' => $days]);
}

几个关键注意点

  • 数据安全:后端一定要再做一次额度校验,不能只依赖前端,防止恶意提交
  • 假期规则:可以根据需求调整天数计算逻辑(比如半天假、节假日排除)
  • 权限控制:给批准申请的接口加权限验证,确保只有管理员能操作

内容的提问来源于stack exchange,提问作者Devzoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:27:08