Maui Blazor 中文社区 QQ群:645660665

用 .NET MAUI 10 + VS Copilot 从 0 开发一个签到 App(九)签到历史报表 + Excel 导出

用 .NET MAUI 10 + VS Copilot 从 0 开发一个签到 App

登录 / 签到历史报表查询 + 按日期筛选 + 导出 Excel

在前面的章节中,我们已经完成了:

  • ✅ 用户登录
  • ✅ 签到记录入库
  • ✅ 多租户数据隔离
  • ✅ 基于 FreeSql 的数据访问封装

本章作为最终章节,我们将实现一个管理端功能

📊 签到 / 登录历史报表

  • 按日期区间查询
  • 列表展示签到明细
  • 一键导出 Excel
  • 使用系统分享(微信 / 邮件 / AirDrop 等)

一、功能效果概览

页面包含以下几个核心功能点:

  1. 日期筛选

    • 起始日期
    • 结束日期
  2. 查询按钮

    • 根据时间范围查询所有签到记录
  3. 报表列表

    • 用户名
    • 租户名称
    • 签到时间
  4. 导出 Excel

    • 生成 .xlsx
    • 调用系统分享能力

二、报表页面 XAML 布局

我们先定义一个 SignInReportPage.xaml,整体采用 VerticalStackLayout,结构简单直观:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SignInMauiApp.SignInReportPage">

    <VerticalStackLayout Padding="20,30" Spacing="10">

        <Label Text="签到历史报表"
               FontSize="22"
               HorizontalOptions="Center" />

        <!-- 日期筛选 -->
        <HorizontalStackLayout Spacing="10">
            <DatePicker x:Name="StartDatePicker" />
            <Label Text="至" VerticalOptions="Center" />
            <DatePicker x:Name="EndDatePicker" />
            <Button Text="查询" Clicked="OnQueryClicked" />
        </HorizontalStackLayout>

        <!-- 导出 -->
        <Button Text="导出Excel" Clicked="OnExportClicked" />

        <!-- 报表列表 -->
        <CollectionView x:Name="ReportCollectionView">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Frame Margin="0,5" Padding="10" BorderColor="#ccc">
                        <VerticalStackLayout>
                            <Label Text="{Binding Username}" />
                            <Label Text="{Binding TenantName}" />
                            <Label Text="{Binding SignInTime,
                                StringFormat='签到时间:{0:yyyy-MM-dd HH:mm:ss}'}" />
                        </VerticalStackLayout>
                    </Frame>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

    </VerticalStackLayout>
</ContentPage>

三、页面后台逻辑(FreeSql + MiniExcel)

1️⃣ 构造函数 & 默认时间范围

  • 默认查询最近 7 天
  • 通过 DI 获取 FreeSql 实例
public partial class SignInReportPage : ContentPage
{
    private readonly IFreeSql? _fsql;
    private List<SignInReportItem> _report = new();

    public SignInReportPage()
    {
        InitializeComponent();

        _fsql = IPlatformApplication.Current?
            .Services.GetService<IFreeSql>();

        StartDatePicker.Date = DateTime.Today.AddDays(-7);
        EndDatePicker.Date = DateTime.Today;

        LoadReport();
    }
}

2️⃣ 查询签到历史(多表 Join)

通过 FreeSql 进行三表关联:

  • SignInRecord
  • User
  • Tenant
private void LoadReport()
{
    var start = StartDatePicker.Date;
    var end = EndDatePicker.Date!.Value.AddDays(1);

    _report = _fsql!
        .Select<SignInRecord, User, Tenant>()
        .LeftJoin((r, u, t) => r.UserId == u.Id)
        .LeftJoin((r, u, t) => r.TenantId == t.Id)
        .Where((r, u, t) =>
            r.SignInTime >= start &&
            r.SignInTime < end)
        .ToList((r, u, t) => new SignInReportItem
        {
            Username = u.Username,
            TenantName = t.Name,
            SignInTime = r.SignInTime
        });

    ReportCollectionView.ItemsSource = _report;
}

点击 查询按钮 即可重新加载:

private void OnQueryClicked(object sender, EventArgs e)
{
    LoadReport();
}

四、导出 Excel(MiniExcel + MAUI Share)

1️⃣ 使用 MiniExcel 生成报表

private async void OnExportClicked(object sender, EventArgs e)
{
    if (_report.Count == 0)
    {
        await DisplayAlertAsync("提示", "无数据可导出", "确定");
        return;
    }

    var fileName = $"签到报表_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
    var filePath = Path.Combine(FileSystem.CacheDirectory, fileName);

    await MiniExcel.SaveAsAsync(filePath, _report);

2️⃣ 调用系统分享能力

MAUI 内置 Share.RequestAsync,跨平台通用:

    if (!File.Exists(filePath))
    {
        await DisplayAlertAsync("错误", "文件未生成,无法分享", "确定");
        return;
    }

    try
    {
        await Share.RequestAsync(new ShareFileRequest
        {
            Title = "导出签到报表",
            File = new ShareFile(filePath),
        });
    }
    catch (Exception ex)
    {
        await DisplayAlertAsync("错误", ex.Message, "确定");
    }
}

📱 Android / iOS / Windows / macOS 都可以正常弹出分享面板。


五、报表 DTO 模型

public class SignInReportItem
{
    public string? Username { get; set; }
    public string? TenantName { get; set; }
    public DateTime SignInTime { get; set; }
}

六、技术点总结(系列收官)

本系列完整覆盖了一个 真实可落地的 MAUI 应用

  • ✅ .NET MAUI 10 跨平台 UI
  • ✅ FreeSql 多表查询
  • ✅ VS Copilot 辅助开发
  • ✅ 日期筛选 + 报表展示
  • ✅ MiniExcel 导出 Excel
  • ✅ MAUI Share 跨平台分享

到这里,一个 可用于内部管理 / 考勤 / 登录审计 的签到 App 就已经完整闭环 🎉

posted @ 2025-12-21 22:30  AlexChow  阅读(390)  评论(0)    收藏  举报