用 .NET MAUI 10 + VS Copilot 从 0 开发一个签到 App(七)初始化数据与租户管理(全程 Copilot 生成)
用 .NET MAUI 10 + VS Copilot 从 0 开发一个签到 App
第 7 篇:初始化数据与租户管理(全程 Copilot 生成)
本篇为独立完整页面,不与前文步骤混写。
在前几篇中,我们已经完成了:
- 多租户登录 / 注册
- 签到与签到历史
- 基于 FreeSql 的本地数据存储
但一个真实可用的系统,还缺最后一块“地基”:
系统如何完成第一次初始化?租户如何被长期维护?
这一篇,我们只做一件事:
- 用一个最简单、最真实的方式
- 完成 初始化数据 + 租户管理能力
并且必须强调:
本篇涉及的页面和逻辑,全部由 Copilot 生成,仅做排版与注释整理。
一、为什么要单独做「租户管理」?
在多租户系统中:
- 租户不是配置文件
- 也不是一次性初始化脚本
而是会被真实用户长期维护的数据。
在这个 MAUI 签到 App 中,租户至少需要支持:
- 新建公司
- 修改公司名称
- 删除公司(测试 / 演示环境)
与其写复杂初始化逻辑,不如:
直接给管理员一个可视化管理页面
二、TenantManagementPage 页面职责
这一页只做三件事:
- 展示现有公司列表
- 新增公司
- 编辑 / 删除公司
不涉及:
- 权限系统
- 用户关联
- 数据级联
这是一个阶段性基础设施页面。
三、页面 UI(XAML,全 AI 生成)
Copilot 生成的 XAML 如下:
<?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.TenantManagementPage">
<VerticalStackLayout Padding="20,30" Spacing="10">
<Label Text="公司管理" FontSize="22" HorizontalOptions="Center" />
<Entry x:Name="NewTenantEntry" Placeholder="新公司名称" />
<Button Text="添加公司" Clicked="OnAddTenantClicked" />
<CollectionView x:Name="TenantCollectionView" SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<Border Margin="0,5" Padding="10">
<HorizontalStackLayout>
<Label Text="{Binding Name}" Padding="10" />
<Button Text="编辑" Clicked="OnEditTenantClicked" CommandParameter="{Binding .}" />
<Button Text="删除" Clicked="OnDeleteTenantClicked" CommandParameter="{Binding .}" />
</HorizontalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
UI 特点非常明显:
- 垂直布局
- CRUD 标准结构
- 所有事件直连 Code-behind
这是 Copilot 在「管理型页面」场景下最典型、也最实用的输出。
四、页面逻辑(Code-behind)
对应的业务代码同样由 Copilot 生成:
public partial class TenantManagementPage : ContentPage
{
private readonly IFreeSql? _fsql;
private List<Tenant> _tenants = new();
public TenantManagementPage()
{
InitializeComponent();
_fsql = IPlatformApplication.Current?.Services.GetService<IFreeSql>();
LoadTenants();
}
private void LoadTenants()
{
_tenants = _fsql!.Select<Tenant>().ToList();
TenantCollectionView.ItemsSource = _tenants;
}
private async void OnAddTenantClicked(object sender, EventArgs e)
{
var name = NewTenantEntry.Text?.Trim();
if (string.IsNullOrEmpty(name)) return;
if (_fsql!.Select<Tenant>().Any(t => t.Name == name))
{
await DisplayAlertAsync("提示", "公司已存在", "确定");
return;
}
await _fsql!.Insert(new Tenant { Name = name }).ExecuteAffrowsAsync();
NewTenantEntry.Text = string.Empty;
LoadTenants();
}
private async void OnEditTenantClicked(object sender, EventArgs e)
{
if (sender is Button btn && btn.CommandParameter is Tenant tenant)
{
string result = await DisplayPromptAsync("编辑公司", "请输入新名称", initialValue: tenant.Name);
if (!string.IsNullOrEmpty(result) && result != tenant.Name)
{
tenant.Name = result;
await _fsql!.Update<Tenant>().SetSource(tenant).ExecuteAffrowsAsync();
LoadTenants();
}
}
}
private async void OnDeleteTenantClicked(object sender, EventArgs e)
{
if (sender is Button btn && btn.CommandParameter is Tenant tenant)
{
if (await DisplayAlertAsync("确认", $"确定删除公司:{tenant.Name}?", "删除", "取消"))
{
await _fsql!.Delete<Tenant>().Where(t => t.Id == tenant.Id).ExecuteAffrowsAsync();
LoadTenants();
}
}
}
}
这段代码的特点非常“工程真实”:
- 逻辑清晰
- CRUD 直观
- 没有过度设计
对于一个客户端本地管理页来说,这已经是非常合适的复杂度。
五、初始化数据是如何自然完成的?
你会发现:
- 没有 InitData
- 没有 Seed 脚本
因为初始化能力已经被拆解到了:
- 注册页:创建新租户
- 租户管理页:维护租户
这是一种非常 MAUI / 客户端化的设计思路:
用 UI 行为,完成数据初始化。
六、管理员入口的接入方式
在签到页面中,通过一行逻辑接入:
if (_user.Username == "admin")
{
ToolbarItems.Add(new ToolbarItem("公司管理", null, async () =>
{
await Navigation.PushAsync(new TenantManagementPage());
}));
}
这是 Copilot 给出的最低成本方案:
- 不引入角色表
- 不提前设计权限系统
在当前阶段,这是完全合理的工程决策。
七、本篇 Copilot 的价值总结
在「初始化 + 管理型页面」这种场景中:
- 结构固定
- 逻辑重复
- 人工写性价比极低
Copilot 的表现可以总结为一句话:
它生成的不是“完美代码”,而是“马上可用的工程代码”。
八、下一篇预告
功能已经全部完成,下一篇将不再新增页面,而是回头复盘:
第 8 篇:Copilot 在 MAUI 项目中的真实边界与最佳用法
我们会从这 7 篇的真实代码出发,总结:
- 哪些地方可以 100% 交给 AI
- 哪些地方必须人工兜底
- 如果重来一次,我会如何更高效地用 Copilot
关联项目
FreeSql QQ群:4336577
BA & Blazor QQ群:795206915
Maui Blazor 中文社区 QQ群:645660665
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
转载声明
本文来自博客园,作者:周创琳 AlexChow,转载请注明原文链接:https://www.cnblogs.com/densen2014/p/19380040
AlexChow
今日头条 | 博客园 | 知乎 | Gitee | GitHub


浙公网安备 33010602011771号