线联ERP数据权限配置操作手册

ERP 系统中,成本、卖价、金额是典型的敏感数据:业务不能看成本、采购不能看卖价、工程部不能看卖价和成本,HR/车间/仓库则要求屏蔽所有单价金额。传统的"每个窗体写死 if"做法维护成本极高。本文基于 CSFrameworkV6 快速开发框架(.NET 8 + WinForms + SQL Server)实现一套集中配置、字段字典驱动的数据权限方案,并交付数据权限配置窗体,管理员勾选即可即刻生效。
目录
一、方案概览:三重生效判定
整套方案只有一条核心判定规则,三个条件缺一不可:
某项权限对当前用户生效 = 总开关启用(UseDataPermission=启用)
AND 该权限项勾选(Enabled=启用)
AND 当前用户命中该权限项的适用范围
配套三条约定:
1、适用范围为空 = 对所有用户生效(含管理员自己,不做豁免);
2、读取配置失败视为"无命中",宁可放开也不阻塞界面;
3、隐藏方式为整列隐藏(列 Visible=false),不采用打码/掩码方式。
配置存储在系统库三张表:sys_DataPermissionItem(权限项)、sys_DataPermissionItemScope(适用范围)、sys_DataRangePermission(行级预留),总开关存 sys_SystemSettings(ParamCode=UseDataPermission,默认"不启用")。
二、配置窗体布局
配置窗体(frmDataPermissionConfig)挂在"系统管理"菜单下,仅管理员可见:
| 区域 | 组件 | 说明 |
|---|---|---|
| 顶部 | 【总开关】CheckBox | 数据权限总开关(UseDataPermission) |
| 左栏 | 8 个权限项 CheckBox | 数据驱动,动态生成自 sys_DataPermissionItem,按【行级权限】【列级权限】分组 |
| 右栏 | 适用范围编辑区 | 生效部门(多选)/ 生效角色(多选)/ 指定用户(逗号分隔文本框) |
| 底部 | 【保存】【关闭】 | 保存 = 即时写库 + 失效缓存,即刻生效 |

左栏点击任一权限项,右栏加载该项的适用范围;范围下拉显示格式为 ID - Name(如 0003 - 采购部),但保存的是编码(GroupCode/RoleID),部门/角色改名不影响已存配置。
三、8 个权限项的配置逻辑
1、行级权限(4 项,预留)
行级权限控制"能看到哪些行"。4 个配置项已建好(可勾选、可保存),查询过滤逻辑预留待实施:
| 配置项 | 编码 | 计划过滤逻辑 |
|---|---|---|
| 业务员只能看自己的客户 | CustomerSelf | dt_Customer.SalesUserId == 自己的 SalesCode(经 dt_SalesPerson.UserId 关联)OR SalesUserId 为空(无主客户人人可见) |
| 部门经理可以看该部门的所有客户 | CustomerDept | 部门经理判定:tb_MyGroup.Owner1/Owner2 含当前账号;范围 = 管辖部门(含子部门)用户的 SalesCode 集合 |
| 制单人只能看自己的订单 | DocSelf | 制单人字段(CreatedBy/CreationBy/DocUser,按单据映射)== 当前账号 |
| 部门经理可以看该部门的订单 | DocDept | 制单人 ∈ 管辖部门(含子部门)用户集合 |
2、列级权限(4 项,已实施)
列级权限控制"能看到哪些列",同一用户命中多个项时敏感分类取并集:
| 配置项 | 编码 | 隐藏的敏感分类 |
|---|---|---|
| 业务不能看成本 | SalesHideCost | Cost(成本类) |
| 采购不能看卖价 | PurchaseHidePrice | SalesPrice(卖价类) |
| 工程部不能看卖价、成本 | EngineerHideCostPrice | Cost + SalesPrice |
| 屏蔽所有单价、金额 | AllHideAmount | Cost + SalesPrice + Amount(全部) |
四、敏感字段映射:35 条字段字典
1、三类敏感分类
方案 B 的核心思想是:不逐窗体配置,而是建一张 FieldName → 敏感分类的集中映射字典。业务窗体打开时遍历 GridView 全部列,按列 FieldName 查字典得到分类,命中即整列隐藏。与数据源模型无关(res_tb_PO / tb_PO 通用),不受代码生成器再生成影响。
2、字段清单
| 分类 | 字段(FieldName,忽略大小写) |
|---|---|
| Cost 成本类(7 个) | CostPrice、CostAmount、ManufactCostPrice、ManufactCostAmount、ProcessPrice、ProcessAmount、StandardCost |
| SalesPrice 卖价类(2 个) | PriceSO(成品入库订单卖价)、PriceNewly(价格表最新价格) |
| Amount 通用金额类(26 个) | Price、Amount、LocalPrice、LocalAmount、ForeignPrice、ForeignAmount、PriceExclTax、AmountExclTax、TaxAmount、AmountSO、TotalAmount、TotalLocalAmount、TotalForeignAmount、TotalTaxAmount、TotalAmountExclTax、TotalAmountExclRate、SettleAmount、SettleAmountBal、TotalSettleAmount、TotalSettleAmountBal、TotalSettleLocalAmount、TotalSettleLocalAmountBal、InvoiceAmount、InvoiceAmountBal、TotalInvoiceAmount、TotalInvoiceAmountBal |
新增/调整映射只需改字典文件;个别窗体的同名特例可用 sys_DataPermissionOverride(窗体×FieldName)覆盖,优先级高于全局字典。
五、核心实现
1、生效判定:DataPermissionContext
Business 层静态类,读系统库计算当前用户命中的敏感分类集合,带静态缓存:
//项编码 → 敏感分类集合(列级 4 项在此映射)
private static readonly Dictionary<string, string[]> _itemCategories
= new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
{
{ "SalesHideCost", new[] { nameof(SensitiveType.Cost) } },
{ "PurchaseHidePrice", new[] { nameof(SensitiveType.SalesPrice) } },
{ "EngineerHideCostPrice", new[] { nameof(SensitiveType.Cost), nameof(SensitiveType.SalesPrice) } },
{ "AllHideAmount", new[] { nameof(SensitiveType.Cost), nameof(SensitiveType.SalesPrice), nameof(SensitiveType.Amount) } },
};
public static HashSet<string> GetHitCategories()
{
//... 缓存加载
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (SystemSettings.Current.UseDataPermission) //条件①:总开关
{
var items = db.GetQueryable<sys_DataPermissionItem>()
.Where(w => w.Enabled == "启用" && w.ItemType == "Field").ToList(); //条件②:项勾选
var scopes = db.GetQueryable<sys_DataPermissionItemScope>().ToList();
foreach (var item in items)
{
var itemScopes = scopes.Where(w => w.ItemCode == item.ItemCode).ToList();
//条件③:适用范围为空 = 对所有用户生效;否则部门/用户/角色任一命中
var hit = itemScopes.Count == 0 || itemScopes.Any(s =>
(s.ScopeType == "Dept" && s.ScopeCode == org)
|| (s.ScopeType == "User" && s.ScopeCode == account)
|| (s.ScopeType == "Role" && roles.Contains(s.ScopeCode)));
if (hit) set.UnionWith(_itemCategories[item.ItemCode]); //多项目录取并集
}
}
return set;
}
2、列隐藏:SensitiveFieldApplier
Library 层统一入口,遍历窗体内全部 GridControl 的所有 GridView 列,命中即隐藏(幂等):
private static void ApplyToView(GridView view, HashSet<string> hitTypes)
{
foreach (DevExpress.XtraGrid.Columns.GridColumn col in view.Columns)
{
if (string.IsNullOrEmpty(col.FieldName)) continue;
if (SensitiveFieldMap.TryGetCategory(col.FieldName, out var type)
&& hitTypes.Contains(type.ToString()))
{
col.Visible = false; //整列隐藏,不打码
}
}
}
//调用点:业务窗体基类 DoViewContent,每次加载数据后重应用,覆盖布局恢复
SensitiveFieldApplier.ApplyAll(this);
3、缓存失效:保存即生效
配置窗体保存成功后调用 DataPermissionContext.ResetCache() 清空静态缓存,下一次任何业务窗体加载数据时按新配置重新应用。已打开的窗体不会自动刷新,重新打开或刷新数据即可。
六、适用范围与保存机制
| 范围类型 | 存储值 | 判定逻辑 |
|---|---|---|
| 生效部门 | ScopeType='Dept',ScopeCode=GroupCode | 当前用户所属组织(Loginer.CurrentUser.Org2)== GroupCode |
| 生效角色 | ScopeType='Role',ScopeCode=RoleID | 当前用户角色串(Loginer.CurrentUser.Roles)包含 RoleID |
| 指定用户 | ScopeType='User',ScopeCode=账号 | 当前登录账号 == ScopeCode |
三种范围类型是"或"的关系,命中任意一条即生效。保存时依次写:总开关 → 各项开关变更 → 当前选中项的适用范围(先清后存,全量覆盖)。
七、常见问题
Q1:勾选了"业务不能看成本",某用户还能看到成本列?
按三条件排查:总开关是否启用 → 该项是否勾选 → 用户是否命中适用范围。另注意列必须能被字段字典识别(按 FieldName 精确匹配)。
Q2:保存后当前窗体没变化?
缓存已失效但已打开的窗体不会重应用,重新打开窗体或刷新数据即可。
Q3:管理员自己也会被隐藏列吗?
会。数据权限不做管理员豁免,只要命中"启用项 + 适用范围"同样隐藏。不希望管理员受控时,把相关项的适用范围配置为不含管理员。
Q4:为什么不逐窗体配置要隐藏哪些列?
逐窗体配置工作量大且受代码生成器再生成影响;字段字典方案只在字典文件维护 35 条映射,一个字典覆盖全部窗体。
了解更多 CSFrameworkV6 快速开发框架,请访问 C/S框架网。
CSFramework成功案例-电子线束行业ERP-线联ERP|C/S开发框架
喜鹊软件线联ERP四大系统:ERP、MES、SRM、OMS
线联ERP - 电子线材线束行业ERP销售模块介绍
电子线束ERP - HR人事考勤模块详细功能介绍|C/S开发框架
CSFrameworkV6开发框架打造塑木地板新材料行业ERP系统
C/S快速开发框架|旗舰版V5.1客户案例 | 染厂ERP系统|C/S开发框架
CSFrameworkV6旗舰版|成功案例|塑料板材行业ERP系统|C/S开发框架
CSFrameworkV6旗舰版|成功案例|纸箱行业ERP系统|C/S开发框架
喜鹊ERP | DevExpress 表格常用操作指南|表格组件自动分组|C/S开发框架
喜鹊ERP | FastReport.NET报表实施与开发操作指引|C/S开发框架
喜鹊ERP | 局域网服务器固定IP操作指南|C/S开发框架
喜鹊ERP用户操作手册|表格样式设置、表格常用操作|C/S开发框架
生产制造企业的业务流程(适用软件ERP/OMS/MES)|C/S开发框架
喜鹊软件 | ERP安装与部署|C/S开发框架
软件开发团队使用ERP系统快速开发框架的优势
塑胶板材行业ERP系统软件开发平台(VS2022+C#+Winform)
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 |
在线客服
