using DevExpress.Data;
|
using DevExpress.XtraTreeList;
|
using DevExpress.XtraTreeList.Nodes;
|
using Gs.DevApp.Entity;
|
using Gs.DevApp.ToolBox;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Data;
|
using System.Drawing;
|
using System.Windows.Forms;
|
|
namespace Gs.DevApp.DevFrm.Sys
|
{
|
/// <summary>
|
/// 看板目录管理 - 树形结构维护界面(用户控件)
|
/// </summary>
|
public partial class SimpleKanBan : DevExpress.XtraEditors.XtraUserControl
|
{
|
private string _webServiceName = "MesSimpleManager/";
|
|
public SimpleKanBan()
|
{
|
InitializeComponent();
|
|
// 工具栏事件绑定
|
toolBarMenu1.btnLoadClick += ToolBarMenu1_btnLoadClick;
|
toolBarMenu1.btnQueryClick += ToolBarMenu1_btnQueryClick;
|
// TreeList 行号显示
|
tlMenu.IndicatorWidth = 50;
|
tlMenu.CustomDrawNodeIndicator += (s, ee) =>
|
{
|
if (ee.IsNodeIndicator)
|
{
|
var index = ee.Node.TreeList.GetVisibleIndexByNode(ee.Node);
|
ee.Info.DisplayText = (index + 1).ToString();
|
}
|
};
|
|
// 初始化加载数据
|
getPageList();
|
|
// 右键菜单事件
|
tlMenu.MouseDown += TlMenu_MouseDown;
|
|
// 增加子项
|
toolStripMenuItemAdd.Click += (s, ee) =>
|
{
|
string strGuid = "";
|
string strUpGuid = "";
|
if (tlMenu.FocusedNode != null)
|
{
|
strUpGuid = tlMenu.FocusedNode.GetValue("id").ToString();
|
}
|
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
|
frm.UpdateParent += (s2, ee2) =>
|
{
|
getPageList();
|
TreeListNode node = tlMenu.FindNodeByKeyID(long.Parse(strUpGuid));
|
if (node != null)
|
{
|
node.Expanded = true;
|
tlMenu.MakeNodeVisible(node);
|
}
|
};
|
frm.ShowDialog();
|
};
|
|
// 增加主项(根节点)
|
toolStripMenuItemRoot.Click += (s, ee) =>
|
{
|
string strGuid = "";
|
string strUpGuid = "";
|
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
|
frm.UpdateParent += (s2, ee2) =>
|
{
|
getPageList();
|
};
|
frm.ShowDialog();
|
};
|
|
// 删除节点
|
toolStripMenuItemDel.Click += (s, ee) =>
|
{
|
if (tlMenu.FocusedNode != null)
|
{
|
string rowGuid = "";
|
string rowName = "";
|
rowGuid = tlMenu.FocusedNode.GetValue("id").ToString();
|
rowName = tlMenu.FocusedNode.GetValue("title").ToString();
|
if (string.IsNullOrEmpty(rowGuid))
|
{
|
MsgHelper.Warning("请先选择你要操作的行!");
|
return;
|
}
|
if (!MsgHelper.AskQuestion("你选择了【" + rowName + "】,确定删除吗?"))
|
return;
|
List<dynamic> lst = new List<dynamic>();
|
lst.Add(rowGuid);
|
try
|
{
|
string strJson = UtilityHelper.HttpPost("", _webServiceName + "DeleteModel", JsonConvert.SerializeObject(lst));
|
ReturnModel<dynamic> _rtn = UtilityHelper.ReturnToDynamic(strJson);
|
if (_rtn.rtnCode > 0)
|
{
|
tlMenu.DeleteNode(tlMenu.FocusedNode);
|
}
|
else
|
MsgHelper.ShowError("提示:" + _rtn.rtnMsg);
|
}
|
catch (Exception ex)
|
{
|
MsgHelper.ShowError("提示:" + ex.Message);
|
}
|
}
|
};
|
// 创建刷新菜单项
|
ToolStripMenuItem toolStripMenuItemRefresh = new ToolStripMenuItem();
|
toolStripMenuItemRefresh.Text = "刷新";
|
toolStripMenuItemRefresh.Click += ToolBarMenu1_btnLoadClick; // 直接调用已有刷新事件
|
|
// 添加到右键菜单,不清空原有 Items
|
cms1.Items.Add(toolStripMenuItemRefresh);
|
|
// 编辑节点
|
toolStripMenuItemEdt.Click += (s, ee) =>
|
{
|
string strGuid = "";
|
string strUpGuid = "";
|
if (tlMenu.FocusedNode != null)
|
{
|
strGuid = tlMenu.FocusedNode.GetValue("id").ToString();
|
var fidValue = tlMenu.FocusedNode.GetValue("parentId");
|
strUpGuid = fidValue != null ? fidValue.ToString() : "";
|
}
|
SimpleKanBanEdit frm = new SimpleKanBanEdit(strGuid, strUpGuid);
|
frm.UpdateParent += (s2, ee2) =>
|
{
|
getPageList();
|
TreeListNode node = tlMenu.FindNodeByKeyID(long.Parse(strGuid));
|
if (node != null)
|
{
|
node.Expanded = true;
|
tlMenu.MakeNodeVisible(node);
|
}
|
};
|
frm.ShowDialog();
|
};
|
}
|
|
/// <summary>
|
/// 查询事件
|
/// </summary>
|
private void ToolBarMenu1_btnQueryClick(object sender, EventArgs e)
|
{
|
MsgHelper.ShowInformation("该窗体不支持查询,若想更新页面,请点击 刷新");
|
}
|
|
/// <summary>
|
/// 刷新事件
|
/// </summary>
|
private void ToolBarMenu1_btnLoadClick(object sender, EventArgs e)
|
{
|
getPageList();
|
MsgHelper.ShowInformation("刷新成功!");
|
}
|
/// <summary>
|
/// 右键弹出菜单
|
/// </summary>
|
private void TlMenu_MouseDown(object sender, MouseEventArgs e)
|
{
|
if (e.Button == MouseButtons.Right)
|
{
|
TreeListHitInfo hInfo = tlMenu.CalcHitInfo(new Point(e.X, e.Y));
|
TreeListNode node = hInfo.Node;
|
tlMenu.FocusedNode = node;
|
if (hInfo.HitInfoType == HitInfoType.Cell ||
|
hInfo.HitInfoType == HitInfoType.Row ||
|
hInfo.HitInfoType == HitInfoType.RowIndent ||
|
hInfo.HitInfoType == HitInfoType.RowIndicator)
|
{
|
if (node != null)
|
{
|
toolStripMenuItemAdd.Visible = true;
|
toolStripMenuItemEdt.Visible = true;
|
toolStripMenuItemDel.Visible = true;
|
toolStripMenuItemRoot.Visible = false;
|
cms1.Show(tlMenu, e.Location);
|
}
|
}
|
else
|
{
|
toolStripMenuItemAdd.Visible = false;
|
toolStripMenuItemEdt.Visible = false;
|
toolStripMenuItemDel.Visible = false;
|
toolStripMenuItemRoot.Visible = true;
|
cms1.Show(tlMenu, e.Location);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 加载数据列表 - 树形结构显示
|
/// </summary>
|
private void getPageList()
|
{
|
var pgq = new PageQueryModel(1, 999999, "a.node_level", "asc", "", "");//sort_order
|
var json = JsonConvert.SerializeObject(pgq);
|
|
try
|
{
|
var strReturn = UtilityHelper.HttpPost("", _webServiceName + "GetListPage", json);
|
var dd = UtilityHelper.ReturnToTablePage(strReturn);
|
var dt = dd.rtnData.list; // 获取原始 DataTable
|
|
|
// 检测 parentId 是否存在且类型不对
|
if (dt.Columns.Contains("parentId") && dt.Columns["parentId"].DataType != typeof(long))
|
{
|
// 1. 创建一个新的 Int64 类型的临时列
|
DataColumn newCol = new DataColumn("parentId_Fixed", typeof(long));
|
dt.Columns.Add(newCol);
|
|
// 2. 遍历所有行,把 String 转成 Long
|
foreach (DataRow row in dt.Rows)
|
{
|
object oldVal = row["parentId"];
|
// 只有非空值才转换,空值保持 DBNull (即根节点)
|
if (oldVal != null && oldVal != DBNull.Value && !string.IsNullOrEmpty(oldVal.ToString()))
|
{
|
if (long.TryParse(oldVal.ToString(), out long val))
|
{
|
row["parentId_Fixed"] = val;
|
}
|
}
|
}
|
|
// 3. 移除旧的 String 列
|
dt.Columns.Remove("parentId");
|
|
// 4. 把新列改名为 parentId
|
newCol.ColumnName = "parentId";
|
}
|
|
|
tlMenu.BeginUpdate();
|
|
// 1. 绑定处理过的数据
|
tlMenu.DataSource = dt;
|
|
// 2. 绑定字段 (现在类型完全一致了)
|
tlMenu.KeyFieldName = "id";
|
tlMenu.ParentFieldName = "parentId";
|
// 设置根节点 (Int64 类型的列,空值就是 DBNull)
|
tlMenu.RootValue = DBNull.Value;
|
|
|
string sortColName = "sortOrder";
|
|
if (tlMenu.Columns[sortColName] != null)
|
{
|
|
tlMenu.ClearSorting();
|
|
tlMenu.Columns[sortColName].SortOrder = System.Windows.Forms.SortOrder.Ascending;
|
|
tlMenu.Columns[sortColName].SortIndex = 0;
|
}
|
tlMenu.ForceInitialize();
|
|
// 4. 调用展开逻辑
|
ApplyExpandState();
|
|
tlMenu.EndUpdate();
|
tlMenu.BestFitColumns();
|
|
|
|
}
|
catch (Exception ex)
|
{
|
tlMenu.EndUpdate();
|
MsgHelper.Warning("加载失败:" + ex.Message);
|
}
|
}
|
|
/// <summary>
|
/// 根据 isExpanded (bool) 字段设置节点展开
|
/// </summary>
|
private void ApplyExpandState()
|
{
|
// 1. 先全部折叠
|
tlMenu.CollapseAll();
|
|
// 2. 使用 DevExpress 高效迭代器遍历
|
tlMenu.NodesIterator.DoOperation(node =>
|
{
|
// 获取值 (注意:列名必须与 DataTable 中一致,通常是 "isExpanded")
|
object val = node.GetValue("isExpanded");
|
|
// 3. 判断并展开
|
if (val != null && val != DBNull.Value)
|
{
|
if ((bool)val)
|
{
|
node.Expanded = true;
|
}
|
}
|
});
|
}
|
/// <summary>
|
/// 将动态数据转换为DataTable
|
/// </summary>
|
private DataTable ConvertToDataTable(dynamic sourceData)
|
{
|
DataTable dt = new DataTable();
|
|
if (sourceData == null) return dt;
|
|
// 如果已经是DataTable,直接返回
|
if (sourceData is DataTable)
|
return sourceData as DataTable;
|
|
// 尝试从JSON数组转换
|
string jsonStr = JsonConvert.SerializeObject(sourceData);
|
dt = JsonConvert.DeserializeObject<DataTable>(jsonStr);
|
|
return dt;
|
}
|
|
/// <summary>
|
/// 处理parentId字段,确保树形结构正确构建
|
/// 根节点(node_level=0 或 parentId为null/0)的parentId设为DBNull
|
/// </summary>
|
private void ProcessParentIdForTreeStructure(DataTable dt)
|
{
|
if (dt == null || dt.Rows.Count == 0) return;
|
|
foreach (DataRow row in dt.Rows)
|
{
|
// 获取nodeLevel
|
int nodeLevel = 0;
|
if (dt.Columns.Contains("nodeLevel") && row["nodeLevel"] != DBNull.Value)
|
{
|
nodeLevel = Convert.ToInt32(row["nodeLevel"]);
|
}
|
|
// 获取parentId
|
object parentIdValue = null;
|
if (dt.Columns.Contains("parentId"))
|
{
|
parentIdValue = row["parentId"];
|
}
|
|
// 如果是根节点(nodeLevel=0 或 parentId为null/0/空),将parentId设为DBNull
|
bool isRootNode = nodeLevel == 0;
|
bool hasNoParent = parentIdValue == null ||
|
parentIdValue == DBNull.Value ||
|
string.IsNullOrEmpty(parentIdValue.ToString()) ||
|
parentIdValue.ToString() == "0";
|
|
if (isRootNode || hasNoParent)
|
{
|
row["parentId"] = DBNull.Value;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 展开第一级节点(根节点)
|
/// </summary>
|
private void ExpandFirstLevelNodes()
|
{
|
foreach (TreeListNode node in tlMenu.Nodes)
|
{
|
node.Expanded = true;
|
}
|
}
|
|
}
|
}
|