用 .NET MAUI 10 + VS Copilot 从 0 开发一个签到 App
登录 / 签到历史报表查询 + 按日期筛选 + 导出 Excel
在前面的章节中,我们已经完成了:
- ✅ 用户登录
- ✅ 签到记录入库
- ✅ 多租户数据隔离
- ✅ 基于 FreeSql 的数据访问封装
本章作为最终章节,我们将实现一个管理端功能:
📊 签到 / 登录历史报表
- 按日期区间查询
- 列表展示签到明细
- 一键导出 Excel
- 使用系统分享(微信 / 邮件 / AirDrop 等)
一、功能效果概览
页面包含以下几个核心功能点:
-
日期筛选
- 起始日期
- 结束日期
-
查询按钮
- 根据时间范围查询所有签到记录
-
报表列表
- 用户名
- 租户名称
- 签到时间
-
导出 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 进行三表关联:
SignInRecordUserTenant
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 就已经完整闭环 🎉
