本系统基于 WPF、.NET6 WebAPI 和 SqlSugar ORM 构建,专注于权限管理模块。支持互联网与局域网部署,适用于智能制造及工控系统研发场景。

工控系统开发圈近期存在一种现象:使用 WPF 开发上位机的团队常需自行实现权限管理系统。虽然看似基础,但涉及权限树形结构拖拽、动态菜单生成及多级审批流程,实施难度较大。以下拆解一套实战级的 WPF+.NET6+SqlSugar 权限系统方案。
整体架构分为三个核心模块:
- WPF 客户端采用 DevExpress 全家桶,MVVM 模式分离界面逻辑
- .NET6 WebApi 服务端使用 JWT 鉴权,自带流量控制
- 数据层使用 SqlSugar ORM,简化查询编写

用户管理模块的 Service 层代码示例如下:
public UserPagedList GetUserList(QueryUserDto dto) { return _userRepository.AsQueryable() .WhereIF(!string.IsNullOrEmpty(dto.Account), u => u.Account.Contains(dto.Account)) .WhereIF(!string.IsNullOrEmpty(dto.RealName), u => u.RealName.Contains(dto.RealName)) .WhereIF(dto.Status != null, u => u.Status == dto.Status) .OrderBy(u => u.CreateTime, OrderByType.Desc) .ToPagedList(dto.Page, dto.PageSize); }
这段代码展示了 SqlSugar 的链式查询用法,WhereIF 方法根据条件动态拼接查询,比直接写 if 判断更简洁。ToPagedList 扩展方法封装了分页逻辑,语义更符合业务需求。

前端 WPF 绑定用户数据时,MVVM 模式的优势体现明显:
<dxg:GridControl ItemsSource="{Binding Users}" AutoGenerateColumns="None">
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="Account" Header="账号"/>
<dxg:GridColumn FieldName="RealName" Header="姓名"/>
<dxg:GridColumn FieldName="Status" Header="状态">
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Status, Converter={StaticResource StatusConverter}}"/>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
</dxg:GridControl.Columns>
</dxg:GridControl>
DevExpress 的 GridControl 绑定 ObservableCollection 集合时,增删改查能自动刷新界面。状态转换器将枚举值转为'启用/禁用'文字,实现了视图与逻辑的解耦。

权限校验的核心位于 WebApi 的鉴权过滤器:
public override void OnAuthorization(AuthorizationFilterContext context) {
var endpoint = context.HttpContext.GetEndpoint();
if (endpoint?.Metadata.GetMetadata<AllowAnonymousAttribute>() != null) return;
var token = context.HttpContext.Request.Headers["Authorization"].ToString();
if (string.IsNullOrEmpty(token) || !_jwtService.ValidateToken(token)) {
context.Result = new ObjectResult(new { code = 401 }) { StatusCode = 401 };
return;
}
// 权限码校验
var permissionCode = endpoint?.Metadata.GetMetadata<PermissionAttribute>()?.Code;
if (!_permissionService.CheckPermission(token, permissionCode)) {
context.Result = new ObjectResult(new { code = 403 }) { StatusCode = 403 };
}
}
该过滤器执行三项操作:放行匿名访问、校验 JWT 有效性、检查接口权限码。权限码通过自定义的 PermissionAttribute 获取,相比硬编码方式更灵活。

系统支持混合部署模式:
- 局域网部署时直连数据库,响应速度<100ms
- 互联网部署切换至 WebApi 模式,通过 Nginx 反向代理处理 HTTPS
- 权限数据同步采用 SignalR,修改权限后所有在线客户端实时生效
该系统的核心亮点在于异常处理机制。例如删除用户时遇到外键约束:
public async Task DeleteUser(Guid userId) {
try {
await _db.TransactionAsync(async () => {
await _db.Deleteable<User>().Where(u => u.Id == userId).ExecuteCommandAsync();
await _db.Deleteable<UserRole>().Where(ur => ur.UserId == userId).ExecuteCommandAsync();
});
} catch (SqlSugarException ex) {
if (ex.Message.Contains("FK_")) {
throw new BusinessException("该用户存在关联数据,请先解除关联");
}
throw;
}
}
使用 SqlSugar 的事务包裹删除操作,捕获外键异常后转换为业务提示,提升了用户体验。这种细节处理在工控系统中尤为重要。

建议开发者重点研究权限树形结构的实现:
public List<PermissionTree> BuildPermissionTree(List<Permission> permissions) {
var rootNodes = permissions.Where(p => p.ParentId == Guid.Empty).ToList();
var tree = new List<PermissionTree>();
foreach (var node in rootNodes) {
tree.Add(new PermissionTree { Id = node.Id, Label = node.Name, Children = GetChildren(node.Id, permissions) });
}
return tree;
}
private List<PermissionTree> GetChildren(Guid parentId, List<Permission> permissions) {
return permissions.Where(p => p.ParentId == parentId)
.Select(p => new PermissionTree { Id = p.Id, Label = p.Name, Children = GetChildren(p.Id, permissions) }).ToList();
}
递归构建权限树结构,配合前端 DevExpress 的 TreeListControl,可实现可视化拖拽权限层级。实际项目中建议增加缓存,避免每次请求都递归查询。

该系统曾在 MES 系统中验证过 200+ 并发,使用 MemoryCache 做权限缓存,Redis 做 Session 共享,稳定性可靠。代码中还包含性能优化技巧,如批处理操作提升效率。

对工控开发者来说,设备权限绑定模块较为实用——将 PLC 操作权限和设备管理账号打通,现场工程师扫码登录时自动匹配权限,比传统密码登录更适合制造业场景。
建议开发者先跑通基础权限模块,再尝试扩展:
- 增加 AD 域认证集成
- 实现权限变更审批流
- 接入 OPC UA 服务端权限控制
这些扩展方向是制造企业真实需要的功能,也是系统从'能用'到'好用'的关键跃迁。

