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

Laravel开发求助:实现带日期选择的链接展示模态框

嘿,这需求完全可行!Carbon绝对能帮你搞定日期处理,而且结合jQuery的加载功能也不难上手,咱们一步步拆解来做~

一、后端用Carbon处理日期与分页逻辑

(假设你用的是Laravel,Carbon是Laravel默认的日期工具,新手友好度拉满)

首先处理日期范围:

  • 默认显示过去10天的数据,用Carbon一行就能拿到起始日期:$startDate = Carbon::now()->subDays(10)->toDateString();
  • 如果用户通过日期选择器自定义范围,就接收前端传的start和end参数,替换默认值即可。

接着是分页查询,比如你有个Link模型,控制器代码可以这么写:

public function getLinks(Request $request)
{
    // 默认取过去10天,也支持接收前端筛选的日期
    $startDate = $request->get('start_date', Carbon::now()->subDays(10)->toDateString());
    $endDate = $request->get('end_date', Carbon::now()->toDateString());

    // 按日期范围分页查询,每页10条(可自行调整)
    $links = Link::whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59'])
        ->orderBy('created_at', 'desc')
        ->paginate(10);

    // 返回JSON给前端,包含数据和分页关键信息
    return response()->json([
        'data' => $links->items(),
        'current_page' => $links->currentPage(),
        'last_page' => $links->lastPage(),
    ]);
}
二、前端实现模态框+日期选择器

咱们用Bootstrap模态框(新手易上手)搭配flatpickr日期选择器(轻量简洁)来做:

  1. 先引入必要的资源:
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<!-- flatpickr CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- flatpickr JS -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
  1. 模态框和列表容器的HTML:
<!-- 触发筛选的按钮 -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#filterModal">
  筛选链接
</button>

<!-- 筛选模态框 -->
<div class="modal fade" id="filterModal" tabindex="-1" aria-labelledby="filterModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="filterModalLabel">选择日期范围</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <div class="mb-3">
          <label for="startDate" class="form-label">开始日期</label>
          <input type="text" class="form-control" id="startDate" placeholder="点击选择">
        </div>
        <div class="mb-3">
          <label for="endDate" class="form-label">结束日期</label>
          <input type="text" class="form-control" id="endDate" placeholder="点击选择">
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
        <button type="button" class="btn btn-primary" id="applyFilter">应用筛选</button>
      </div>
    </div>
  </div>
</div>

<!-- 链接列表展示容器 -->
<div id="linksContainer" class="mt-3"></div>
<!-- 加载更多按钮 -->
<button id="loadMoreBtn" class="btn btn-outline-primary mt-3 d-none">加载更多</button>
  1. 初始化日期选择器和核心逻辑:
$(document).ready(function() {
    // 初始化日期选择器,默认选中过去10天到今天
    const defaultStartDate = new Date();
    defaultStartDate.setDate(defaultStartDate.getDate() - 10);
    
    flatpickr('#startDate', {
        defaultDate: defaultStartDate,
        dateFormat: 'Y-m-d'
    });
    
    flatpickr('#endDate', {
        defaultDate: new Date(),
        dateFormat: 'Y-m-d'
    });

    // 全局维护分页和筛选状态
    let currentPage = 1;
    let currentFilters = {
        start_date: flatpickr('#startDate').selectedDates[0].toISOString().split('T')[0],
        end_date: flatpickr('#endDate').selectedDates[0].toISOString().split('T')[0]
    };

    // 页面加载时先加载第一页数据
    loadLinks(currentPage, currentFilters);

    // 应用筛选按钮点击事件
    $('#applyFilter').click(function() {
        // 更新筛选条件
        currentFilters.start_date = flatpickr('#startDate').selectedDates[0].toISOString().split('T')[0];
        currentFilters.end_date = flatpickr('#endDate').selectedDates[0].toISOString().split('T')[0];
        // 重置页码,清空现有列表重新加载
        currentPage = 1;
        $('#linksContainer').empty();
        loadLinks(currentPage, currentFilters);
        // 关闭模态框
        $('#filterModal').modal('hide');
    });

    // 加载更多按钮点击事件
    $('#loadMoreBtn').click(function() {
        currentPage++;
        loadLinks(currentPage, currentFilters);
    });

    // 可选:滚动到页面底部自动加载更多
    $(window).scroll(function() {
        // 距离底部100px时触发加载
        if($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
            if($('#loadMoreBtn').is(':visible')) {
                $('#loadMoreBtn').click();
            }
        }
    });

    // 封装加载数据的函数
    function loadLinks(page, filters) {
        // 加载中禁用按钮,防止重复请求
        $('#loadMoreBtn').text('加载中...').prop('disabled', true);

        $.ajax({
            url: '/get-links', // 替换成你的后端路由
            method: 'GET',
            data: {
                page: page,
                start_date: filters.start_date,
                end_date: filters.end_date
            },
            success: function(response) {
                // 渲染每条链接
                response.data.forEach(link => {
                    $('#linksContainer').append(`
                        <div class="card mb-2">
                            <div class="card-body">
                                <a href="${link.url}" target="_blank">${link.title}</a>
                                <p class="text-muted small">创建时间: ${link.created_at}</p>
                            </div>
                        </div>
                    `);
                });

                // 更新加载按钮状态:如果是最后一页就隐藏按钮
                if(response.current_page >= response.last_page) {
                    $('#loadMoreBtn').hide();
                } else {
                    $('#loadMoreBtn').show().text('加载更多').prop('disabled', false);
                }
            },
            error: function() {
                alert('加载失败,请稍后重试~');
                $('#loadMoreBtn').text('加载更多').prop('disabled', false);
            }
        });
    }
});
三、新手必看的关键注意事项
  • Carbon兼容性:如果不是Laravel项目,也可以单独安装Carbon包(composer require nesbot/carbon),用法完全一致。
  • 日期格式匹配:确保数据库的created_at字段是日期时间类型,Carbon生成的Y-m-d格式能和数据库完美匹配。
  • 重复请求拦截:加载数据时一定要禁用按钮,请求完成后再恢复,避免用户多次点击导致重复加载。
  • 滚动加载阈值:代码里的-100是距离底部100px触发加载,你可以根据自己的页面布局调整这个数值。

这样一套下来,就能实现你想要的所有功能啦!

内容的提问来源于stack exchange,提问作者Valter Sousa Cardoso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:15:56