using Model; using Newtonsoft.Json; using Permission; using PlcUiForm; using Sunny.UI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace YangjieTester.用户管理 { [FormDescriptionAttribute("权限管理")] public partial class PermissionConfigForm : PlcBaseForm { private string ROOT_NAMESPACE = "YangjieTester"; // ← 你要扫描的根命名空间 private PermissionLevel currentRoleLevel = PermissionLevel.操作工; // 默认操作工 private Dictionary roleProfiles = new Dictionary(); List permissionLevels=new List() { PermissionLevel.操作工, PermissionLevel.工程师, PermissionLevel.技术员, PermissionLevel.管理员, }; private readonly string[] roleNames; public PermissionConfigForm() { ROOT_NAMESPACE = this.GetType().Namespace.Split('.')[0]; InitializeComponent(); treeView1.CheckBoxes = true; // 启用复选框 treeView1.AfterCheck += treeView1_AfterCheck; // ← 添加这一行 roleNames= permissionLevels.Select(level => Enum.GetName(typeof(PermissionLevel), level)).ToArray(); // 👇 添加这一行 InitializeRoleComboBox(); LoadAllProfiles(); // 加载4个角色的权限 LoadPermissionControlsIntoTreeView(); // 构建树结构(不带勾选) RefreshTreeViewCheckState(currentRoleLevel); // 应用当前角色的勾选状态 } private void InitializeRoleComboBox() { //comboBoxRole.Items.Clear(); //for (int i = 0; i < roleNames.Length; i++) //{ // comboBoxRole.Items.Add($"{roleNames[i]} ({i})"); //} comboBoxRole.DataSource = permissionLevels; comboBoxRole.SelectedItem = comboBoxRole.Items[0]; comboBoxRole.SelectedIndexChanged += (s, e) => { SaveCurrentProfile(); // 先保存当前角色的勾选 currentRoleLevel = (PermissionLevel)comboBoxRole.SelectedItem; RefreshTreeViewCheckState(currentRoleLevel); // 根据新权限重设 CheckBox }; } private void LoadAllProfiles() { foreach (var item in permissionLevels) { roleProfiles[item] = PermissionManager.GetRoleProfile(item); } } private void SaveCurrentProfile() { var profile = new PermissionProfile(); // 遍历 TreeView 所有叶子节点(控件节点) CollectCheckedControls(treeView1.Nodes, profile.AuthorizedControls); roleProfiles[currentRoleLevel] = profile; } private void CollectCheckedControls(TreeNodeCollection nodes, List list) { foreach (TreeNode node in nodes) { if (node.Tag is ControlInfo info && node.Checked) { list.Add(new AuthorizedControl { Namespace = info.NameSpace, FormType = info.FormType, ControlName = info.ControlName }); } CollectCheckedControls(node.Nodes, list); } } private bool isRestoringCheckState = false; private void RefreshTreeViewCheckState(PermissionLevel roleLevel) { var currentProfile = roleProfiles.TryGetValue(roleLevel, out var profile) ? profile : new PermissionProfile(); // 构建快速查找字典:(FormType + "." + ControlName) -> bool var authorizedSet = new HashSet( currentProfile.AuthorizedControls.Select(c => $"{c.Namespace}.{c.FormType}.{c.ControlName}") ); //isRestoringCheckState = true; foreach (TreeNode node in treeView1.Nodes) { node.Checked = false; } SetCheckStateRecursive(treeView1.Nodes, authorizedSet); //isRestoringCheckState = false; } private void SetCheckStateRecursive(TreeNodeCollection nodes, HashSet authorizedSet) { foreach (TreeNode node in nodes) { if (node.Tag is ControlInfo info) { bool isChecked = authorizedSet.Contains($"{info.NameSpace}.{info.FormType}.{info.ControlName}"); node.Checked = isChecked; } SetCheckStateRecursive(node.Nodes, authorizedSet); } // 注意:此时不要触发 AfterCheck(避免级联),所以暂时关闭事件? // 或者我们重构:AfterCheck 只处理用户点击,程序设置不触发逻辑 } private void LoadPermissionControlsIntoTreeView() { treeView1.Nodes.Clear(); var assembly = Assembly.GetExecutingAssembly(); var currentType = typeof(PermissionConfigForm); // 1. 获取所有在 ROOT_NAMESPACE 及其子命名空间下的非抽象 Form 类型(排除自己) var formTypes = assembly.GetTypes() .Where(t => t.IsSubclassOf(typeof(Form)) && !t.IsAbstract && t != currentType && !string.IsNullOrEmpty(t.Namespace) && (t.Namespace == ROOT_NAMESPACE || t.Namespace.StartsWith(ROOT_NAMESPACE + "."))) .ToList(); // 2. 按命名空间分组 var formsByNamespace = formTypes .GroupBy(f => f.Namespace) .OrderBy(g => g.Key) .ToList(); foreach (var nsGroup in formsByNamespace) { TreeNode nsNode = new TreeNode(nsGroup.Key); treeView1.Nodes.Add(nsNode); foreach (var formType in nsGroup.OrderBy(f => f.Name)) { // TreeNode formNode = new TreeNode(formType.Name); TreeNode formNode = new TreeNode(FormEx.GetFormDescription(formType)); nsNode.Nodes.Add(formNode); // 3. 扫描该窗体中所有实现了 IPermissionControl 的控件 try { var permissionControls = GetPermissionControlFields(formType); //using (Form instance = (Form)Activator.CreateInstance(formType)) { //var permissionControls = FindPermissionControls(instance.Controls, ""); foreach (var item in permissionControls.OrderBy(x => x.ControlName)) { TreeNode ctrlNode = new TreeNode($"{item.ControlName}"); ctrlNode.Tag = new ControlInfo { NameSpace = nsGroup.Key, FormType = formType.Name, ControlName= item.ControlName, ControlType = item.ControlType }; formNode.Nodes.Add(ctrlNode); } } } catch (Exception ex) { TreeNode errorNode = new TreeNode($"[加载失败: {ex.Message}]") { ForeColor = Color.Red }; formNode.Nodes.Add(errorNode); } } } } private List GetPermissionControlFields(Type formType) { var list = new List(); // 遍历窗体类中所有字段(包括私有、继承的) var fields = formType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (var field in fields) { Type fieldType = field.FieldType; // 1. 必须是 Control 或其子类 if (!typeof(Control).IsAssignableFrom(fieldType)) continue; // 2. 必须实现 IPermissionControl 接口 if (!typeof(IPermissionControl).IsAssignableFrom(fieldType)) continue; //// 3. 必须具有名为 "WriteNode" 的公共实例属性(可读或可写均可) //var writeNodeProperty = fieldType.GetProperty( // "WriteNode", // BindingFlags.Public | BindingFlags.Instance); //if (writeNodeProperty == null) // continue; // 没有 WriteNode 属性,跳过 if (typeof(MyUiButton).IsAssignableFrom(fieldType) || typeof(MyUiInput).IsAssignableFrom(fieldType) || typeof(MyUIComboBox).IsAssignableFrom(fieldType)) { // ✅ 全部条件满足,加入列表 list.Add(new ControlInfo { ControlName = field.Name, ControlType = fieldType.Name, }); } } return list; } private bool isUpdating = false; // 防止 AfterCheck 递归调用 private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) { // 防止递归触发 if (isUpdating || isRestoringCheckState) return; isUpdating = true; try { // 1. 子节点跟随父节点 SetChildNodesChecked(e.Node, e.Node.Checked); // 👇 关键修复:如果当前节点被设为 Checked(全选),立即恢复其默认颜色 if (e.Node.Checked) { e.Node.ForeColor = treeView1.ForeColor; // 恢复默认文字颜色 } // 2. 更新所有祖先节点的状态(部分选中 or 全选/全不选) UpdateParentCheckState(e.Node.Parent); } finally { isUpdating = false; } } // 递归设置所有子节点状态 private void SetChildNodesChecked(TreeNode node, bool isChecked) { foreach (TreeNode child in node.Nodes) { child.Checked = isChecked; SetChildNodesChecked(child, isChecked); } } // 递归更新父节点状态 private void UpdateParentCheckState(TreeNode parentNode) { if (parentNode == null) return; bool allChecked = true; bool allUnchecked = true; foreach (TreeNode child in parentNode.Nodes) { if (child.Checked) allUnchecked = false; else allChecked = false; } if (allChecked) parentNode.Checked = true; else if (allUnchecked) parentNode.Checked = false; else parentNode.Checked = false; // 逻辑上是“部分选中”,但 CheckBox 只能显示 false // 👇 修复:明确根据状态设置颜色 if (allChecked || allUnchecked) { parentNode.ForeColor = treeView1.ForeColor; // 全选或全不选 → 正常颜色 } else { parentNode.ForeColor = Color.LightGray; // 部分选中 → 灰色 } // 继续向上更新祖父节点 UpdateParentCheckState(parentNode.Parent); } private void btnSave_Click(object sender, EventArgs e) { SaveCurrentProfile(); foreach (var item in roleProfiles) { PermissionManager.SaveRoleProfile(item.Key, item.Value); } PermissionManager.ResetPermissions(); MessageBox.Show("保存完成"); } } public class ControlInfo { public string NameSpace { get; set; } = ""; public string FormType { get; set; } = ""; public string ControlName { get; set; } = ""; public string ControlType { get; set; } = ""; } }