using DevExpress.Data; using DevExpress.Utils; using DevExpress.XtraEditors.Controls; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Columns; using DevExpress.XtraGrid.Views.BandedGrid; using DevExpress.XtraGrid.Views.BandedGrid.ViewInfo; using DevExpress.XtraGrid.Views.Base; using DevExpress.XtraGrid.Views.Grid; using DevExpress.XtraGrid.Views.Grid.ViewInfo; using DevExpress.XtraTab; using DevExpress.XtraTreeList; using DevExpress.XtraTreeList.Columns; using DevExpress.XtraTreeList.Nodes; using Lskj.Business; using Lskj.Business.Impl; using Lskj.Control; using Lskj.Control.Model; using Lskj.Data; using Lskj.Model; using Lskj.ProductSched; using Lskj.Util; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Drawing; using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; namespace Lskj.ProductiSched { public partial class FrmProductSched : UserControl { public bool TreeMultiHeader; public bool isAddBottom; public Control.BandedGridControlEx bandGcBottom; public ProductDataModel DataModel; public FrmProductSched() { InitializeComponent(); } /// /// 界面加载时 /// public void OnLoad(DynamicProductSchedModel mainModel) { GetControlData(mainModel); InitSpiltLocation(); InitControlView(); InitControlEvents(); SetControlData(); } /// /// 获取数据 /// public void GetControlData(DynamicProductSchedModel mainModel) { DataModel = new ProductDataModel(); DataModel.TopSysModel = mainModel; DataRow topSysRow = MainImpl.GetSystemdllTab(DataModel.TopSysModel.ModuleCode); DataModel.TopModuleModel = new ModuleModel(topSysRow); DataModel.TopModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.TopSysModel.ModuleCode); DataModel.TopGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.TopSysModel.ModuleCode); DataModel.TopRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.TopRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); DataModel.TopSearchTab = BaseModuleImpl.GetCustomQueryFields(DataModel.TopModuleModel.CondKey); DataModel.TopSchemesTable = BaseModuleImpl.GetSchemesList(DataModel.TopSysModel.ModuleId); if (DataModel.TopModuleModel.TreeAutoMultiHeader == 1) { DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, treebandGcTop); } else { DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, bandGcTop); } DataModel.TopSearchObj.Model = DataModel.TopSysModel; DataTable detailsTab = BaseModuleImpl.GetBaseDetailPages(DataModel.TopSysModel.ModuleCode);//明细数据 List detailsTablist = new List(); if (detailsTab != null) { foreach (DataRow item in detailsTab.Rows) { GridDetailModel detailModel = new GridDetailModel(item, null, GridCustomColumnStruct.BaseDetailGridView); DataTable gridColumns = ReportImpl.GetReportDetailColumns(DataModel.TopSysModel.ModuleCode, item["id"] + "");//获取报表明细列 detailModel.GridColumns = gridColumns; if (detailModel.Orderid == -1)//序号为-1固定配置右键 { string moduleCode = detailModel.UnionModule; DataModel.RightDetailModel = detailModel; DataModel.RightSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); DataModel.RightModuleModel = new ModuleModel(sysRow); DataModel.RightModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.RightSysModel.ModuleCode); DataModel.RightGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.RightSysModel.ModuleCode); DataModel.RightRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.RightRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); } else { detailsTablist.Add(detailModel); } } tabBottom.Model = DataModel.TopSysModel; tabBottom.InitTabPages(detailsTablist); this.isAddBottom = detailsTablist.Where(o => o.displayMode != 1 && o.rightVisible != 1 && o.Orderid == -2).ToList().Count > 0; //if (detailsTab.Rows.Count > 1) //{ // string moduleCode = detailsTab.Rows[0]["unionModule"] + ""; // DataModel.BottomDetailModel = new GridDetailModel(detailsTab.Rows[0], null, GridCustomColumnStruct.BaseDetailGridView); // DataModel.BottomSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); // DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.BottomSysModel.ModuleCode); // DataModel.BottomModuleModel = new ModuleModel(sysRow); // DataModel.BottomModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.BottomSysModel.ModuleCode); // DataModel.BottomGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.BottomSysModel.ModuleCode); // DataModel.BottomRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); // DataModel.BottomRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); //} //if (detailsTab.Rows.Count > 1) //{ // string moduleCode = detailsTab.Rows[1]["unionModule"] + ""; // DataModel.RightDetailModel = new GridDetailModel(detailsTab.Rows[1], null, GridCustomColumnStruct.BaseDetailGridView); // DataModel.RightSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); // DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); // DataModel.RightModuleModel = new ModuleModel(sysRow); // DataModel.RightModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.RightSysModel.ModuleCode); // DataModel.RightGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.RightSysModel.ModuleCode); // DataModel.RightRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); // DataModel.RightRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); //} //else //{ // string moduleCode = detailsTab.Rows[0]["unionModule"] + ""; // DataModel.RightDetailModel = new GridDetailModel(detailsTab.Rows[0], null, GridCustomColumnStruct.BaseDetailGridView); // DataModel.RightSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); // DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); // DataModel.RightModuleModel = new ModuleModel(sysRow); // DataModel.RightModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.RightSysModel.ModuleCode); // DataModel.RightGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.RightSysModel.ModuleCode); // DataModel.RightRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); // DataModel.RightRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); //} } } /// /// 设置数据 /// public void SetControlData() { } /// /// 初始化控件 /// public void InitControlView() { //搜索控件 bool fixedQuery = DataModel.TopSearchTab == null || DataModel.TopSearchTab.Rows.Count == 0; TreeMultiHeader = DataModel.TopModuleModel.TreeAutoMultiHeader == 1; if (!fixedQuery) { this.pl_mainSearch.Height = DataModel.TopSearchObj.InitSearchControl(DataModel.TopSearchTab, this.pl_search, true, DataModel.TopSchemesTable, DataModel.TopSysModel); this.pl_search.Width = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Max(n => n.Location.X + n.Width) + 5; } //构建树表格 if (TreeMultiHeader)//若为多表头树表格模式 { treebandGcTop.Expansion = "3"; treebandGcTop.Model = DataModel.TopSysModel; treebandGcTop.moduleModel = DataModel.TopModuleModel; treebandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey); treebandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.ModeCode), DataModel.TopSysModel, this.OnGridViewRightCallBack); treebandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode)); bandGcTop.Visible = false; } else { //上方表格 bandGcTop.Model = DataModel.TopSysModel; bandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey); bandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.ModeCode), DataModel.TopSysModel, this.OnGridViewRightCallBack); bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode)); bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode)); treebandGcTop.Visible = false; } if (TreeMultiHeader) { AddDataColumns(treebandGcTop); } else { AddDataColumns(bandGcTop); } if (DataModel.TopModuleModel.HasReport) { flowLayoutPanel.Visible = false; } if (isAddBottom) { GridControlEx gridControl = tabBottom.TabControlObj.TabPages[0].Tag as GridControlEx; bandGcBottom = gridControl as BandedGridControlEx; AddDataColumns(bandGcBottom); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { gridBand.OptionsBand.AllowSize = false; foreach (BandedGridColumn bandedGridColumn in gridBand.Columns) { bandedGridColumn.OptionsColumn.AllowSize = false; } } if (TreeMultiHeader) { OnBandedViewColumnWidthChanged(treebandGcTop.TreeListObj, null); } else { OnBandedViewColumnWidthChanged(bandGcTop.BandedView, null); } } if (tabBottom.TabControlObj.TabPages.Count == 0) { splitLeftControl.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1; } //右侧表格 if (!string.IsNullOrEmpty(DataModel.RightSysModel.ModuleCode)) { DataRow moduleInformation = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); if (moduleInformation == null) { MessageUtil.Show("没有找到编号为" + DataModel.RightSysModel.ModuleCode + "的模块信息"); return; } DataModel.RightDetailModel.SystemModel = new ModuleModel(moduleInformation); gcRight.OnSaveGridCallBack += OnDetailSaveGridCallBack; gcRight.Name = "gridEx"; gcRight.IsDetail = true; gcRight.Dock = DockStyle.Fill; gcRight.OperShortMode = false; // 不显示简短模式 gcRight.VisibleSearchPanel = false; DataTable rightDt = BaseModuleImpl.GetBaseGridRightMenus(DataModel.RightSysModel.ModuleCode, ModuleType.MrpClickBtn); gcRight.VisibleOperPanel = !DataModel.RightDetailModel.IsReadOnly; gcRight.InitializeControl(DataModel.RightDetailModel.SystemModel, DataModel.RightSysModel); gcRight.GridControlObj.Tag = DataModel.RightDetailModel; if (DataModel.RightDetailModel.IsCheck == 1)//加载复选框 { GridDragGrid.GridAddCheckBox(gcRight.GridControlObj.GridView); } } } /// /// 右侧表格保存回调 /// /// /// private void OnDetailSaveGridCallBack(object sender, EventArgs e) { DataModel.TopSearchObj.ButtonObj.PerformClick(); } /// /// 绑定控件事件 /// public void InitControlEvents() { splitLeftControl.SplitterPositionChanged += OnSplitContainerPositionChanged; splitMainControl.SplitterPositionChanged += OnSplitContainerPositionChanged; DataModel.TopSearchObj.OnDataSourceBindCallBack += OnDataSourceBindCallBack; DataModel.TopSearchObj.OnSearchBeforeCallBack += OnSearchBeforeCallBack; ; DataModel.TopSearchObj.OnSearchAfterCallBack += OnSearchAfterCallBack; if (bandGcBottom != null) { bandGcBottom.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcBottom.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader; } if (TreeMultiHeader) { // 改为TreeList的事件绑定 treebandGcTop.TreeListObj.BandWidthChanged += OnBandedViewColumnWidthChanged; treebandGcTop.TreeListObj.ColumnWidthChanged += OnBandedViewColumnWidthChanged; // 宽度改变事件 treebandGcTop.TreeListObj.LeftCoordChanged += OnBandedViewLeftCoordChanged; // 水平滚动事件 treebandGcTop.TreeListObj.FocusedNodeChanged += OnFocusedNodeChanged; // 单元格点击事件 treebandGcTop.TreeListObj.KeyDown += OnTreeListKeyDown; // 键盘事件 treebandGcTop.TreeListObj.CustomDrawFooterCell += OnTreeListCustomDrawFooterCell; // 自定义绘制Footer事件 treebandGcTop.TreeListObj.CustomDrawColumnHeader += OnTreeListCustomDrawColumnHeader; // 自定义绘制列头事件 treebandGcTop.TreeListObj.ShowingEditor += OnTreeListShowingEditor; // 编辑器显示前事件 treebandGcTop.TreeListObj.InvalidValueException += OnInvalidValueException; ; } else { bandGcTop.BandedView.BandWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.ColumnWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcTop.BandedView.RowCellClick += OnBandedViewRowCellClick; bandGcTop.BandedView.KeyDown += OnBandedViewKeyDown; bandGcTop.BandedView.CustomDrawFooterCell += OnCustomDrawFooterCell; bandGcTop.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader; bandGcTop.BandedView.ShowingEditor += OnShowingEditor; bandGcTop.BandedView.InvalidValueException += OnInvalidValueException; } btnSave.Click += OnBtnSaveClick; } /// /// 判断单元格是否可以编辑 /// /// /// private void OnRightShowingEditor(object sender, CancelEventArgs e) { var view = sender as GridView; if (view == null) return; DataRow row = gcRight.GridControlObj.GetViewFocusedDataRow(); if (row == null) { e.Cancel = true; return; } // 没有行也不让编辑 // —— 1. 解析 day 字段 —— if (!DateTime.TryParse(row["day"]?.ToString(), out DateTime dayDate)) { e.Cancel = true; // 无法解析日期 → 禁止编辑 return; } // —— 2. 超过 7 天的行不可编辑 —— if (dayDate.AddDays(7) <= DateTime.Today) { e.Cancel = true; return; } } /// /// 判断单元格是否可以编辑 /// /// /// private void OnShowingEditor(object sender, CancelEventArgs e) { BandedGridView view = sender as BandedGridView; if (view == null) return; if (DataModel.TopModuleModel.HasReport)//报表所有的都不能编辑 { e.Cancel = true; // 取消编辑,单元格变灰 } DataRow dataRow = view.GetFocusedDataRow(); if (dataRow == null) return; string bj_tig = dataRow["bj_tig"]?.ToString() ?? ""; if (bj_tig == "0") { e.Cancel = true; // 取消编辑,单元格变灰 } else { string billDocumentId = view.GetRowCellValue(view.FocusedRowHandle, DataModel.TopModuleModel.ParmaryKey) + ""; // 新方式 (精准替代原有取值方式) DateTime date; if (DataModel.columnDateMapping.TryGetValue(view.FocusedColumn, out date)) { string columnName = date.ToString("yyyy-MM-dd"); // 检查该行的 billdocument_id 是否在字典中 if (DataModel.nonEditableCells.ContainsKey(billDocumentId)) { HashSet showDays = DataModel.nonEditableCells[billDocumentId]; // 如果列名(日期)在 showday_list 里,则禁用编辑 if (showDays.Contains(columnName)) { e.Cancel = true; // 取消编辑,单元格变灰 } } } } } /// /// 判断TreeList单元格是否可以编辑(精准适配原BandedGridView逻辑) /// private void OnTreeListShowingEditor(object sender, CancelEventArgs e) { if (DataModel.TopModuleModel.HasReport)//报表所有的都不能编辑 { e.Cancel = true; // 取消编辑,单元格变灰 } TreeList treeList = sender as TreeList; string bj_tig = treeList.FocusedNode.GetValue("bj_tig")?.ToString() ?? ""; if (treeList == null || treeList.FocusedNode == null) return; if (bj_tig == "0") { e.Cancel = true; // 取消编辑,单元格变灰 } else { string billDocumentId = treeList.FocusedNode.GetValue(DataModel.TopModuleModel.ParmaryKey)?.ToString() ?? ""; DateTime date; if (DataModel.columnDateMapping.TryGetValue(treeList.FocusedColumn, out date)) { string columnName = date.ToString("yyyy-MM-dd"); // 检查该行的 billdocument_id 是否在字典中 if (DataModel.nonEditableCells.ContainsKey(billDocumentId)) { HashSet showDays = DataModel.nonEditableCells[billDocumentId]; // 如果列名(日期)在 showday_list 里,则禁用编辑 if (showDays.Contains(columnName)) { e.Cancel = true; // 取消编辑,单元格变灰 } } } } } /// /// 保存按钮点击时 /// /// /// private void OnBtnSaveClick(object sender, EventArgs e) { if (TreeMultiHeader) { treebandGcTop.GridView.PostEditor(); } else { bandGcTop.BandedView.PostEditor(); } if (!string.IsNullOrEmpty(DataModel.TopModuleModel.MenuTable)) { SaveGridRecord(); } if (SaveDatePlanRecord()) { DataModel.TopSearchObj.ButtonObj.PerformClick(); } } /// /// 保存主表数据 /// /// public bool SaveGridRecord() { string tableName = DataModel.TopModuleModel.MenuTable; string Autogrowcolumn = BaseImpl.GetResult(string.Format("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME='{0}' AND COLUMNPROPERTY(OBJECT_ID('{0}'),COLUMN_NAME,'IsIdentity')=1", tableName)) + ""; DataTable DatabasePropertySheet = BaseImpl.GetDataTableResult(string.Format("select COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH from information_schema.columns where table_name = '{0}'", tableName));//数据库属性表 string SaveErrorMessage = "失败列表:\r\n"; if (string.IsNullOrEmpty(tableName)) { MessageUtil.Show(ResourceKeys.MenuTableNameIsNull); return false; } List mList = new List(); DataTable dataTable = TreeMultiHeader ? treebandGcTop.GetGridViewDataSource() : bandGcTop.BandedView.GridControl.DataSource as DataTable; DataRow[] modifiedRows = dataTable .Rows .Cast() .Where(x => x.RowState == DataRowState.Modified || x.RowState == DataRowState.Added) .ToArray(); if (modifiedRows == null || modifiedRows.Length == 0) { MessageUtil.Show(ResourceKeys.UnUpdateData); return false; } else { DataColumnCollection columns = BaseImpl.GetTableColumns(tableName).Columns; foreach (DataRow row in modifiedRows) { string updateSql = "update {0} set {1} where {2}='{3}';"; string insertSql = "insert into {0}({1}) values({2});"; string updateFields = string.Empty; string insertFields = string.Empty; string insertValues = string.Empty; BaseSaveModel model = new BaseSaveModel() { MenuCode = DataModel.TopSysModel.ModuleCode, TableName = tableName, KeyField = DataModel.TopModuleModel.ParmaryKey, NewVer = DataModel.TopModuleModel.NewVer }; foreach (DataColumn col in columns) { // 区分大小写匹配列 DataRow hasContainRow = DataModel.TopGridColumns.Rows.Cast().FirstOrDefault(x => (x["fieldname"] + "").ToLower() == col.ColumnName.ToLower()); if (hasContainRow != null && col.ColumnName != DataModel.TopModuleModel.ParmaryKey && !col.ColumnName.Equals("id") && Autogrowcolumn.ToLower() != col.ColumnName.ToLower()) { if (row.RowState == DataRowState.Modified && string.IsNullOrEmpty(DataModel.TopModuleModel.CustomColumnSQL)) { string newValue = row[col.ColumnName, DataRowVersion.Current] + ""; string oldValue = row[col.ColumnName, DataRowVersion.Original] + ""; //如果是修改状态,没有改变的值就不拼接,以免造成多人同时修改同一行不同列的值混乱情况 if (oldValue != newValue) { if ((col.DataType == typeof(DateTime)) && (row[col.ColumnName] + "" == "")) { updateFields += string.Format("[{0}]=null,", col.ColumnName); } else { if (col.DataType == typeof(Decimal) && string.IsNullOrWhiteSpace((row[col.ColumnName] + "").Replace("'", "''"))) { updateFields += string.Format("[{0}]='{1}',", col.ColumnName, 0); } else { updateFields += string.Format("[{0}]=N'{1}',", col.ColumnName, (row[col.ColumnName] + "").Replace("'", "''")); } } } } else if (row.RowState == DataRowState.Added || (row.RowState == DataRowState.Modified && !string.IsNullOrEmpty(DataModel.TopModuleModel.CustomColumnSQL))) { // 动态生成列,保存时默认全部为新增 string fieldValue = (row[col.ColumnName] + "").Replace("'", "''"); insertFields += "[" + col.ColumnName + "],"; if (!string.IsNullOrWhiteSpace(fieldValue)) { insertValues += col.DataType == typeof(DateTime) ? "'" + Convert.ToDateTime(fieldValue).ToString("yyyy-MM-dd HH:mm:ss") + "'," : "N'" + fieldValue + "',"; } else { if (col.DataType == typeof(Decimal) || col.DataType == typeof(Int32)) insertValues += "0,"; else if (col.DataType == typeof(DateTime)) insertValues += "NULL,"; else insertValues += "'',"; } } SaveErrorMessage = SaveErrorMessage + DatabaseFormatJudgment.SaveOrModifyBalidation(DataModel.TopGridColumns, DatabasePropertySheet, row, col, (row[col.ColumnName] + "").Replace("'", "''")); } } // 检查是否保存主键字段 if (row.RowState == DataRowState.Added && !insertFields.Contains(DataModel.TopModuleModel.ParmaryKey) && !"ID".Equals(DataModel.TopModuleModel.ParmaryKey, StringComparison.OrdinalIgnoreCase)) { // 跳过自动增长列处理 if (Autogrowcolumn.ToLower() != DataModel.TopModuleModel.ParmaryKey.ToLower()) { insertFields += DataModel.TopModuleModel.ParmaryKey + ","; insertValues += "N'" + row[DataModel.TopModuleModel.ParmaryKey] + "',"; } } updateFields = updateFields.TrimEnd(','); insertFields = insertFields.TrimEnd(','); insertValues = insertValues.TrimEnd(','); if (!string.IsNullOrEmpty(updateFields)) { model.FieldValue = row[DataModel.TopModuleModel.ParmaryKey] + ""; model.BaseSaveType = SaveType.Update; model.BaseSql = string.Format(updateSql, tableName, updateFields, DataModel.TopModuleModel.ParmaryKey, row[DataModel.TopModuleModel.ParmaryKey]); } if (!string.IsNullOrEmpty(insertFields)) { model.BaseSaveType = SaveType.Add; model.FieldValue = row[DataModel.TopModuleModel.ParmaryKey] + ""; model.BaseSql = string.Format(insertSql, tableName, insertFields, insertValues); } if (!string.IsNullOrWhiteSpace(model.BaseSql)) mList.Add(model); } try { if (mList.Count == 0) { return true; } string retuenMsg = ""; string apiRetMsg = ""; // 批量保存数据 if (BaseModuleImpl.SaveBaseGridData(mList, out retuenMsg, out apiRetMsg)) { return true; } else { StringBuilder builder = new StringBuilder(); builder.Append("失败列表\r\n"); foreach (BaseSaveModel item in mList) { if (!string.IsNullOrEmpty(item.FaultMsg)) SaveErrorMessage += item.FaultMsg + "\r\n"; } LogHelper.Instance.WriteLog(builder.ToString()); MessageUtil.Show(SaveErrorMessage); return false; } } catch (Exception ex) { string Message = ErrorMessage.PromptErrorMessage(ex); MessageUtil.Show(Message, ex.Message); return false; } } } /// /// 保存日期数据 /// private bool SaveDatePlanRecord() { BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelComboxEdit).Cast().FirstOrDefault(); // 获取第一个符合条件的控件 string typeDate = "0"; if (dataTypeControl != null) { LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit; typeDate = labelAutoTextEdit.EditValue; } // 获取主数据源,假设已绑定到 gridControl1 DataTable mainDataSource = TreeMultiHeader ? treebandGcTop.GetGridViewDataSource() : bandGcTop.BandedView.GridControl.DataSourceTable(); if (mainDataSource == null) { return true; } // 当前操作用户(例如从全局获取) string currentUser = ERPInfo.Instance.UserName; DataTable tvp = new DataTable(); tvp.Columns.Add("billdocument_id", typeof(string)); tvp.Columns.Add("showday", typeof(string)); tvp.Columns.Add("amount", typeof(decimal)); tvp.Columns.Add("operatorname", typeof(string)); // 遍历主数据源所有行,仅处理已修改行 foreach (DataRow row in mainDataSource.Rows) { if (row.RowState == DataRowState.Modified) { // 获取关联的 keyvalue(用于匹配 mps_dayplantab.billdocument_id) string key = row["keyvalue"].ToString(); // 遍历每个列,处理虚拟列(列名格式必须为 "yyyy-MM-dd") foreach (DataColumn col in mainDataSource.Columns) { // 忽略固定字段 if (col.ColumnName == "ID" || col.ColumnName == "keyvalue" || col.ColumnName == "Name") continue; // 仅处理列名符合完整日期格式的虚拟列 if (!Regex.IsMatch(col.ColumnName, @"^\d{4}-\d{2}-\d{2}$")) continue; // 比较原始值和当前值 object originalValue = row[col, DataRowVersion.Original]; object currentValue = row[col, DataRowVersion.Current]; if (!object.Equals(originalValue, currentValue)) { decimal newAmount = 0m; if (row[col] != DBNull.Value && !string.IsNullOrWhiteSpace(row[col].ToString())) { decimal.TryParse(row[col].ToString(), out newAmount); } DataRow dr = tvp.NewRow(); dr["billdocument_id"] = key; dr["showday"] = col.ColumnName; // 列名如 "2025-03-06" dr["amount"] = newAmount; dr["operatorname"] = currentUser; tvp.Rows.Add(dr); } } } } if (tvp.Rows.Count == 0) { return true; } // 调用存储过程保存变更数据 string msg; int ret = SaveDayPlanChanges(tvp, typeDate, out msg); if (ret == 1) { MessageUtil.Show("保存成功:" + msg); return true; } else { MessageUtil.Show("保存失败:" + msg); return false; } } /// /// 保存日计划变更数据(批量保存)。 /// 调用存储过程 usp_MergeDayPlanChanges,将所有变更记录一次性提交到数据库。 /// 通过 TVP 参数传递数据,同时捕获输出参数 @msg 和返回值。 /// /// 包含所有变更记录的 DataTable,必须与 dbo.DayPlanChangeType 定义一致 /// 输出提示信息,存储过程执行后的返回消息 /// 存储过程返回值,成功返回 1,失败返回 0 public int SaveDayPlanChanges(DataTable tvp, string typeDate, out string message) { // 创建输出参数 @msg SqlParameter pMsg = new SqlParameter("@msg", SqlDbType.VarChar, 2000) { Direction = ParameterDirection.Output }; // 创建返回值参数 @return SqlParameter returnValue = new SqlParameter("@return", SqlDbType.Int) { Direction = ParameterDirection.ReturnValue }; // 创建 TVP 参数,名称必须与存储过程参数一致 SqlParameter tvpParam = new SqlParameter("@DayPlanChanges", SqlDbType.Structured) { TypeName = "dbo.DayPlanChangeType", Value = tvp }; // 创建 typeDate 参数并传入存储过程 SqlParameter typeDateParam = new SqlParameter("@TypeDate", SqlDbType.VarChar, 10) { Value = typeDate }; // 构造参数数组 SqlParameter[] parameters = new SqlParameter[] { tvpParam, typeDateParam, pMsg, returnValue }; // 执行存储过程,此处调用 ExecuteNonQuery 即可,不需要返回数据集 // 请确保 BaseImpl.ExecProcedure 方法能够传递参数并执行存储过程 BaseImpl.ExecProcedure("usp_MergeDayPlanChanges", parameters); // 获取输出参数 @msg 中的提示信息 message = pMsg.Value.ToString(); // 获取存储过程的返回值 int result = Convert.ToInt32(returnValue.Value); return result; } /// /// 单元格点击刷新当前行数据 /// /// /// private void OnBandedViewRowCellClick(object sender, RowCellClickEventArgs e) { try { GridDetailModel model = DataModel.RightDetailModel; DataRow rowItem = bandGcTop.BandedView.GetFocusedDataRow(); if (rowItem != null) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelComboxEdit).Cast().FirstOrDefault(); // 获取第一个符合条件的控件 string typeDate = "0"; LabelDateEdit labelDateEdit = null; if (baseUserControl != null) { labelDateEdit = baseUserControl as LabelDateEdit; } if (dataTypeControl != null) { LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit; typeDate = labelAutoTextEdit.EditValue; } string searchSql = this.GetSearchSql(model, rowItem, false); string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'"; searchSql = $"{ReplaceHelper.ReplaceWhereCond(searchSql)} and day >= '{labelDateEdit.TextEdit.DateTime.ToString("yyyy-MM-dd")}' {isweekcond}"; gcRight.GridControlObj.LastSearchSql = searchSql; // 4) 让 Grid 用这张表,并把 adapter 存起来 gcRight.GridControlObj.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql)); if (e != null) { if (labelDateEdit != null) { DateTime dateTime = labelDateEdit.TextEdit.DateTime; DataRow focusedRow = bandGcTop.BandedView.GetFocusedDataRow(); DataTable dataDayPlan = gcRight.GridControlObj.GridControl.DataSourceTable().Copy(); if (DataModel.TopModuleModel.HasReport) UpdateRowWithDayPlan(focusedRow, dataDayPlan, dateTime); } } this.SetDetailGridDataSource(rowItem); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// TreeList聚焦节点改变刷新当前行数据(精确移植原点击事件逻辑) /// private void OnFocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e) { try { GridDetailModel model = DataModel.RightDetailModel; if (e.Node != null) { DataRow rowItem = (treebandGcTop.TreeListObj.GetDataRecordByNode(e.Node) as DataRowView)?.Row; if (rowItem != null) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls .Cast() .FirstOrDefault(n => n is LabelDateEdit); BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls .Cast() .FirstOrDefault(n => n is LabelComboxEdit) as BaseUserControl; string typeDate = "0"; LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; if (dataTypeControl != null && dataTypeControl is LabelComboxEdit labelAutoTextEdit) { typeDate = labelAutoTextEdit.EditValue; } if (labelDateEdit == null) return; string searchSql = this.GetSearchSql(model, rowItem, false); string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'"; searchSql = $"{ReplaceHelper.ReplaceWhereCond(searchSql)} and day >= '{labelDateEdit.TextEdit.DateTime:yyyy-MM-dd}' {isweekcond}"; gcRight.GridControlObj.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql)); // 更新行数据逻辑 DateTime dateTime = labelDateEdit.TextEdit.DateTime; DataTable dataDayPlan = gcRight.GridControlObj.GridControl.DataSourceTable().Copy(); if (DataModel.TopModuleModel.HasReport) UpdateRowWithDayPlan(rowItem, dataDayPlan, dateTime); this.SetDetailGridDataSource(rowItem); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 说明:下面多数据源刷新 /// 创建人:王一帆 /// 创建日期:2017-12-19 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void SetDetailGridDataSource(DataRow rowItem, XtraTabPage tabPage = null) { if (tabPage != null) { this.SetTabPageDataSource(tabPage, rowItem); } else { foreach (XtraTabPage page in this.tabBottom.TabControlObj.TabPages) { if (rowItem != null && page != null) { this.SetTabPageDataSource(page, rowItem); } } } } protected void SetTabPageDataSource(XtraTabPage tabPage, DataRow rowItem) { GridDetailModel model = this.tabBottom.GetGridDetailModel(tabPage); if (model.Orderid == -2) return; Object moduleObject = tabPage.Controls.Cast().FirstOrDefault(); ModuleGridEx moduleGridEx = null; if (moduleObject is ModuleGridEx) { moduleGridEx = moduleObject as ModuleGridEx; } if (rowItem != null && model != null) { if (!string.IsNullOrEmpty(model.UnionModule) && (string.IsNullOrEmpty(model.UnionValue) && string.IsNullOrEmpty(model.UnionCond))) return; if (tabPage.Tag is FrmWebBrowser) { // 加载网页 FrmWebBrowser webView = tabPage.Tag as FrmWebBrowser; string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql)); url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url; //webView.FrmLoad(url); webView.LoadUrl(url); webView.Dock = DockStyle.Fill; webView.Tag = model; } else if (tabPage.Tag is FrmWebBrowser2) { // 加载网页 FrmWebBrowser2 webView = tabPage.Tag as FrmWebBrowser2; string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql)); url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url; webView.LoadUrl(url); webView.Dock = DockStyle.Fill; webView.Tag = model; } else if (tabPage.Tag is FrmMiniBlink) { // 加载网页 FrmMiniBlink webView = tabPage.Tag as FrmMiniBlink; string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql)); url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url; webView.LoadUrl(url); webView.Dock = DockStyle.Fill; webView.Tag = model; } else if (tabPage.Tag is TabMultipledetails) { TabMultipledetails tabMultipledetails = tabPage.Tag as TabMultipledetails; tabMultipledetails.SetConditionValues(rowItem); GridControlEx grdExMain = (tabMultipledetails.SplitMain.Panel1.Tag as GridControlEx); GridDetailModel MainModel = grdExMain.Tag as GridDetailModel; string searchMainSql = this.GetSearchSql(MainModel, rowItem); DataTable firstTable = MainImpl.GetDataTableResult(searchMainSql); grdExMain.LastSearchSql = searchMainSql; grdExMain.SetGridViewDataSource(firstTable); if (tabMultipledetails.SplitMain.Panel2.Tag is GridControlEx) { GridControlEx grdExAdditional = (tabMultipledetails.SplitMain.Panel2.Tag as GridControlEx); GridDetailModel AdditionalModel = grdExAdditional.Tag as GridDetailModel; string searchAddSql = this.GetSearchSql(AdditionalModel, rowItem); if (!MainModel.IsUnioDetail) { grdExAdditional.LastSearchSql = searchAddSql; grdExAdditional.SetGridViewDataSource(MainImpl.GetDataTableResult(searchAddSql)); } //右侧是左侧的明细,左侧没有数据时。右侧赋空值(因为无法触发左侧行改变事件) if (MainModel.IsUnioDetail && firstTable.Rows.Count == 0) { grdExAdditional.LastSearchSql = ""; grdExAdditional.SetGridViewDataSource(new DataTable()); } } else if (tabMultipledetails.SplitMain.Panel2.Tag is ChartControlEx) { ChartControlEx grdExAdditional = (tabMultipledetails.SplitMain.Panel2.Tag as ChartControlEx); GridDetailModel AdditionalModel = grdExAdditional.Tag as GridDetailModel; string searchAddSql = this.GetSearchSql(AdditionalModel, rowItem); DataTable table = MainImpl.GetDataTableResult(searchAddSql); grdExAdditional.CreateChart(table); } tabPage.Text = MainModel.DetailName + "(" + firstTable.Rows.Count + "条)"; tabPage.Appearance.Header.ForeColor = firstTable.Rows.Count > 0 ? Color.Red : Color.FromArgb(0, 0, 0); } else { if (model.IsDrag) { return; } string searchSql = this.GetSearchSql(model, rowItem); if (tabPage.Tag is GridControlEx) { (tabPage.Tag as GridControlEx).LastSearchSql = searchSql; } //DataTable dataTable = MainImpl.GetDataTableResult(searchSql);//明细数据源 if (model.DynamicDetails && rowItem.Table.Columns.Contains("DisplayColumns")) // { this.tabBottom.SetGridDisplayColumns(tabPage, rowItem["DisplayColumns"] + ""); } this.tabBottom.SetGridDataSource(tabPage, MainImpl.GetDataTableResult(searchSql)); if (tabPage.Tag is GridControlEx && (tabPage.Tag as GridControlEx).ParentControl != null) (tabPage.Tag as GridControlEx).ParentControl.SetAllControlValue(rowItem); //配置明细直接根据条件加载 if (model.SystemModel != null && 1 == model.SystemModel.isFirstLoad) { (tabPage.Tag as GridControlEx).ParentControl.SearchGrid(); tabPage.Text = model.DetailName + "(" + (tabPage.Tag as GridControlEx).ParentControl.GridRowCount + "条)"; } } if (moduleGridEx != null) moduleGridEx.ParentButtonState(rowItem); } } /// /// 获取查询sql /// /// /// /// /// private string GetSearchSql(GridDetailModel model, DataRow rowItem, bool isLeft = false) { string fieldName = !string.IsNullOrEmpty(model.UnionParentField) && rowItem.Table.Columns.Contains(model.UnionParentField) ? model.UnionParentField : DataModel.TopModuleModel.ParmaryKey; string sqlValue = model.Orderid == -1 ? DataModel.RightModuleModel.MenuSql : model.IsReadOnly || model.IsChart ? model.DetailSql : model.SystemModel.MenuSql; sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue); DataRow row = TreeMultiHeader ? treebandGcTop.GetViewFocusedDataRow() : bandGcTop.GetViewFocusedDataRow(); if (row != null && isLeft) { //先替换左侧选中行,在替换主表 sqlValue = ReplaceHelper.ReplaceRowParam(row, sqlValue); } if (ReplaceHelper.IsSelect(sqlValue) && !string.IsNullOrEmpty(model.UnionValue)) { string Conditions = string.Empty; //是左侧选中行,并且没有替换字段,则使用主表选中行 Conditions = isLeft ? rowItem.Table.Columns.Contains(fieldName) ? rowItem[fieldName] + "" : row[fieldName] + "" : rowItem[fieldName] + ""; sqlValue = ReplaceHelper.ReplaceWhereCond(sqlValue) + string.Format(" and {0}='{1}'", model.UnionValue, Conditions); } if (!string.IsNullOrEmpty(model.UnionCond)) { string UnionCond = ReplaceHelper.ReplaceRowParam(rowItem, model.UnionCond); sqlValue += UnionCond; } return sqlValue; } /// /// 宽度改变事件处理,兼容BandedGridView和TreeList /// private void OnBandedViewColumnWidthChanged(object sender, EventArgs e) { if (bandGcBottom != null) { int allWidth = 0; // 如果sender为原有的BandedView类型 if (sender == bandGcTop.BandedView) { foreach (GridBand gridBand in bandGcTop.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { allWidth += gridBand.Width; } } } // 如果sender为TreeList类型 else if (sender is TreeList treeListSender) { foreach (TreeListBand band in treeListSender.Bands) { if (band.Columns.Count == 1 && band.Columns[0].Name.Contains("DDay_")) { break; } else { foreach (TreeListColumn treeListColumn in band.Columns) { if (treeListColumn.Visible) allWidth += treeListColumn.Width; } } } } else { return; // 非预期sender类型时直接退出 } // 调整底部bandGcBottom的列宽(始终为BandedGridView类型) List bottomColumnList = new List(); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { bottomColumnList.AddRange(gridBand.Columns.Cast()); } } // 按计算好的宽度均分调整 if (bottomColumnList.Count > 0) { int perWidth = allWidth / bottomColumnList.Count; foreach (BandedGridColumn bandedGridColumn in bottomColumnList) { bandedGridColumn.Width = perWidth; } } } } /// /// 水平滚动条改变时 /// /// /// private void OnBandedViewLeftCoordChanged(object sender, EventArgs e) { if (!isAddBottom) return; if (sender == bandGcTop.BandedView) { bandGcBottom.BandedView.LeftCoord = bandGcTop.BandedView.LeftCoord; } else if (sender is TreeList treeListSender) { // 使用TreeList的LeftCoord属性同步BandedView的LeftCoord bandGcBottom.BandedView.LeftCoord = treeListSender.LeftCoord; } else if (sender == bandGcBottom.BandedView) { if (TreeMultiHeader) { treebandGcTop.TreeListObj.LeftCoord = bandGcBottom.BandedView.LeftCoord; } else { bandGcTop.BandedView.LeftCoord = bandGcBottom.BandedView.LeftCoord; } } } /// /// 记录展开的节点 /// public void GetTreeExpanded() { DataModel.treeListNodes.Clear(); foreach (TreeListNode n in this.treebandGcTop.TreeListObj.Nodes) { setRecursive(n); } } /// /// 递归进行遍历节点 /// /// public void setRecursive(TreeListNode treeNode) { if (treeNode.Expanded) DataModel.treeListNodes.Add(treeNode); // Visit each node recursively. foreach (TreeListNode tn in treeNode.Nodes) { setRecursive(tn); } } /// /// 搜索条件绑定完成后 /// /// /// private void OnDataSourceBindCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelComboxEdit).Cast().FirstOrDefault(); // 获取第一个符合条件的控件 string typeDate = "0"; if (dataTypeControl != null) { LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit; typeDate = labelAutoTextEdit.EditValue; } if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; if (isAddBottom) UpdateDynamicColumns(bandGcBottom, dateTime, typeDate); if (TreeMultiHeader) { UpdateDynamicColumns(treebandGcTop, dateTime, typeDate); } else { UpdateDynamicColumns(bandGcTop, dateTime, typeDate); } } } /// /// 搜索前事件 /// /// /// private void OnSearchBeforeCallBack(object sender, SearchArgs e) { if (TreeMultiHeader) { DataModel.MainLeftCoord = treebandGcTop.TreeListObj.LeftCoord; } else { DataModel.MainLeftCoord = bandGcTop.BandedView.LeftCoord; } } /// /// 搜索后事件 /// /// /// private void OnSearchAfterCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelComboxEdit).Cast().FirstOrDefault(); // 获取第一个符合条件的控件 string typeDate = "0"; if (dataTypeControl != null) { LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit; typeDate = labelAutoTextEdit.EditValue; } if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; if (typeDate == "1") { DateTime endDate = labelDateEdit.TextEdit.DateTime.AddMonths(3).AddDays(-1); // 计算结束日期 int weekIndex = 0; DateTime weekStart = GetStartOfWeek(labelDateEdit.TextEdit.DateTime); // 获取本周的周一日期 labelDateEdit.TextEdit.DateTime = weekStart; } DateTime dateTime = labelDateEdit.TextEdit.DateTime; if (TreeMultiHeader) { UpdateDynamicColumns(treebandGcTop, dateTime, typeDate); } else { UpdateDynamicColumns(bandGcTop, dateTime, typeDate); } if (isAddBottom) UpdateDynamicColumns(bandGcBottom, dateTime, typeDate); DataTable dataMain = null; DataTable dataDetail = null; int hander = bandGcTop.BandedView.FocusedRowHandle; if (TreeMultiHeader) { dataMain = treebandGcTop.GetGridViewDataSource().Copy(); dataDetail = treebandGcTop.GetGridViewDataSource().Copy(); //treebandGcTop.TreeListObj.DataSource = null; } else { dataMain = bandGcTop.GridControl.DataSourceTable().Copy(); dataDetail = bandGcTop.GridControl.DataSourceTable().Copy(); bandGcTop.GridControl.DataSource = null; } string sqlValue = DataModel.RightModuleModel.MenuSql; string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'"; sqlValue = $"{ReplaceHelper.ReplaceWhereCond(sqlValue)} and day >= '{dateTime.ToString("yyyy-MM-dd")}' {isweekcond}"; DataTable dataDayPlan = BaseImpl.GetDataTableResult(sqlValue); if (isAddBottom) { DataTable bottomTab = BuildCTable(dataDetail, dataDayPlan, dateTime, 93); bandGcBottom.BandedView.GridControl.DataSource = bottomTab; } MergeMainDataWithDayPlan(dataMain, dataDayPlan, dateTime, typeDate); if (!TreeMultiHeader) { bandGcTop.BandedView.GridControl.DataSource = dataMain; bandGcTop.BandedView.FocusedRowHandle = hander; OnBandedViewRowCellClick(bandGcTop.BandedView, null); bandGcTop.BandedView.LeftCoord = DataModel.MainLeftCoord; } else { treebandGcTop.SetGridViewDataSource(dataMain); treebandGcTop.TreeListObj.LeftCoord = DataModel.MainLeftCoord; } } string query = @" SELECT billdocument_id, STUFF((SELECT ',' + CAST(showday AS VARCHAR(MAX)) FROM mps_dayplantab AS sub WITH(NOLOCK) WHERE sub.billdocument_id = main.billdocument_id AND sub.update_tig = 1 FOR XML PATH('')), 1, 1, '') AS showday_list FROM mps_dayplantab AS main WITH(NOLOCK) GROUP BY billdocument_id;"; DataTable dt = BaseImpl.GetDataTableResult(query); foreach (DataRow row in dt.Rows) { string billDocumentId = row["billdocument_id"] + ""; string showDayList = row["showday_list"].ToString(); if (!string.IsNullOrEmpty(showDayList)) { HashSet daysSet = new HashSet(showDayList.Split(',')); DataModel.nonEditableCells[billDocumentId] = daysSet; } } } /// /// 获取数据源缓存 /// /// /// public void GetDataCaches(Dictionary cachesDic) { //获取通用数据 Task sysModelTask = cachesDic.GetTask(this, "SysModel"); Task dynamicModelTask = cachesDic.GetTask(this, "DynamicModel"); Task> detailsTask = cachesDic.GetTask>(this, "Details"); Task getDataCachesTask = cachesDic.AddTask(this, "DataCaches", new Task(() => { ModuleModel sysModel = sysModelTask.Result; DynamicModel dynamicModel = dynamicModelTask.Result; //创建数据 if (sysModel != null && dynamicModel != null) { Task menuConfigTabTask = cachesDic.AddTask(this, "MenuConfigTab", new Task(() => { return BaseImpl.GetMenuConfigTab(dynamicModel.ModuleId); //获取菜单其他配置 })); if (dynamicModel is DynamicExcelModel)//isExcel { Task basePrimaryKeyTask = cachesDic.AddTask(this, "BasePrimaryKey", new Task(() => { return BaseImpl.GetBasePrimaryKey(dynamicModel.ModuleCode); })); Task gridColumnsTask = cachesDic.AddTask(this, "GridColumns", new Task(() => { return BaseModuleImpl.GetBaseGridColumns(dynamicModel.ModuleCode); })); } else { //构建主表数据 } } return true; })); } /// /// 添加虚拟日期列 /// private void AddDataColumns(BandedGridControlEx bandedGridControlEx) { if (bandedGridControlEx == bandGcTop) { bandedGridControlEx.BandedView.OptionsView.ShowFooter = false; } foreach (GridBand gridBand in bandedGridControlEx.BandedView.Bands) { gridBand.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left; } for (int i = 0; i < 93; i++) { GridBand gridBand = new GridBand(); gridBand.Name = $"Day_{i}"; gridBand.Caption = ""; gridBand.OptionsBand.AllowMove = false; gridBand.OptionsBand.AllowSize = false; gridBand.AppearanceHeader.Options.UseFont = true; gridBand.AppearanceHeader.Font = new Font("宋体", 9, FontStyle.Bold); gridBand.AppearanceHeader.Options.UseTextOptions = true; gridBand.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; gridBand.AppearanceHeader.TextOptions.WordWrap = WordWrap.Wrap; bandedGridControlEx.BandedView.Bands.Add(gridBand); BandedGridColumn gridColumn = new BandedGridColumn(); gridColumn.AppearanceCell.Options.UseTextOptions = true; gridColumn.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.AppearanceHeader.Options.UseTextOptions = true; gridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.OptionsColumn.AllowMove = false; gridColumn.OptionsColumn.AllowSize = false; gridColumn.OptionsFilter.AllowFilter = false; gridColumn.OptionsColumn.AllowMerge = DefaultBoolean.False; gridColumn.OptionsColumn.AllowSort = DefaultBoolean.False; gridColumn.FieldName = $"DDay_{i}"; gridColumn.Width = 70; gridColumn.DisplayFormat.FormatType = FormatType.Numeric; gridColumn.DisplayFormat.FormatString = "{0:#,##0.####}"; gridColumn.Visible = false; if (bandedGridControlEx == bandGcTop) { gridColumn.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum; gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}"; } gridBand.Columns.Add(gridColumn); } // 现在添加15个周列 for (int i = 93; i < 108; i++) // 新增15个周列 { GridBand gridBand = new GridBand(); gridBand.Name = $"Week_{i - 93}"; gridBand.Caption = ""; gridBand.OptionsBand.AllowMove = false; gridBand.OptionsBand.AllowSize = false; gridBand.AppearanceHeader.Options.UseFont = true; gridBand.AppearanceHeader.Font = new Font("宋体", 9, FontStyle.Bold); gridBand.AppearanceHeader.Options.UseTextOptions = true; gridBand.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; gridBand.AppearanceHeader.TextOptions.WordWrap = WordWrap.Wrap; bandedGridControlEx.BandedView.Bands.Add(gridBand); BandedGridColumn gridColumn = new BandedGridColumn(); gridColumn.AppearanceCell.Options.UseTextOptions = true; gridColumn.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.AppearanceHeader.Options.UseTextOptions = true; gridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.OptionsColumn.AllowMove = false; gridColumn.OptionsColumn.AllowSize = false; gridColumn.OptionsFilter.AllowFilter = false; gridColumn.OptionsColumn.AllowMerge = DefaultBoolean.False; gridColumn.OptionsColumn.AllowSort = DefaultBoolean.False; gridColumn.FieldName = $"WWeek_{i - 93}"; gridColumn.Width = 105; gridColumn.DisplayFormat.FormatType = FormatType.Numeric; gridColumn.DisplayFormat.FormatString = "{0:#,##0.####}"; gridColumn.Visible = false; if (bandedGridControlEx == bandGcTop) { gridColumn.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum; gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}"; } gridBand.Columns.Add(gridColumn); } } /// /// 添加多表头树结构模式的虚拟日期列(基于TreeList) /// /// /// 添加虚拟日期列(树的多表头模式) /// /// /// 添加虚拟日期列(树的多表头模式) /// private void AddDataColumns(TreeBandedGridControlEx bandedGridControlEx) { // 核心优化代码:暂停数据源绑定和界面刷新 bandedGridControlEx.TreeListObj.BeginUpdate(); bandedGridControlEx.TreeListObj.LockReloadNodes(); // 阻止节点数据重载(关键优化) try { if (bandedGridControlEx == treebandGcTop) { bandedGridControlEx.TreeListObj.OptionsView.ShowSummaryFooter = false; } foreach (TreeListBand fixedBand in bandedGridControlEx.TreeListObj.Bands) { fixedBand.Fixed = DevExpress.XtraTreeList.Columns.FixedStyle.Left; } // 添加93个日列 for (int i = 0; i < 93; i++) { TreeListBand dayBand = new TreeListBand { Name = $"Day_{i}", Caption = "", OptionsBand = { AllowMove = false, AllowSize = false }, AppearanceHeader = { Options = { UseFont = true, UseTextOptions = true }, Font = new Font("宋体", 9, FontStyle.Bold), TextOptions = { HAlignment = HorzAlignment.Center } } }; bandedGridControlEx.TreeListObj.Bands.Add(dayBand); TreeListColumn dayColumn = new TreeListColumn { FieldName = $"DDay_{i}", Width = 70, Visible = false, OptionsColumn = { AllowMove = false, AllowSize = false, AllowSort = false, AllowEdit = false }, AppearanceCell = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } }, AppearanceHeader = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } }, Format = { FormatType = FormatType.Numeric, FormatString = "{0:#,##0.####}" } }; if (bandedGridControlEx == treebandGcTop) { dayColumn.AllNodesSummary = true; dayColumn.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum; dayColumn.SummaryFooterStrFormat = "{0:#,##0.####}"; } dayBand.Columns.Add(dayColumn); bandedGridControlEx.TreeListObj.Columns.Add(dayColumn); } // 添加15个周列 for (int i = 93; i < 108; i++) { TreeListBand weekBand = new TreeListBand { Name = $"Week_{i - 93}", Caption = "", OptionsBand = { AllowMove = false, AllowSize = false }, AppearanceHeader = { Options = { UseFont = true, UseTextOptions = true }, Font = new Font("宋体", 9, FontStyle.Bold), TextOptions = { HAlignment = HorzAlignment.Center } } }; bandedGridControlEx.TreeListObj.Bands.Add(weekBand); TreeListColumn weekColumn = new TreeListColumn { FieldName = $"WWeek_{i - 93}", Width = 105, Visible = false, OptionsColumn = { AllowMove = false, AllowSize = false, AllowSort = false, AllowEdit = false }, AppearanceCell = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } }, AppearanceHeader = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } }, Format = { FormatType = FormatType.Numeric, FormatString = "{0:#,##0.####}" } }; if (bandedGridControlEx == treebandGcTop) { weekColumn.AllNodesSummary = true; weekColumn.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum; weekColumn.SummaryFooterStrFormat = "{0:#,##0.####}"; } weekBand.Columns.Add(weekColumn); //bandedGridControlEx.TreeListObj.Columns.Add(weekColumn); } } finally { bandedGridControlEx.TreeListObj.UnlockReloadNodes(); // 重新允许节点加载数据 bandedGridControlEx.TreeListObj.EndUpdate(); // 一次性完成所有刷新 } } /// /// 创建TreeList统一的列 /// private TreeListColumn CreateTreeListColumn(string fieldName, int width) { var column = new TreeListColumn { Name = $"col_{fieldName}", FieldName = fieldName, Caption = fieldName, Width = width, Visible = true, OptionsColumn = { AllowMove = false, AllowSize = false, AllowSort = false, AllowEdit = false }, AppearanceHeader = { TextOptions = { HAlignment = HorzAlignment.Center }, Font = new Font("宋体", 9, FontStyle.Bold) }, AppearanceCell = { TextOptions = { HAlignment = HorzAlignment.Center } }, Format = { FormatType = FormatType.Numeric, FormatString = "{0:#,##0.####}" } }; return column; } /// /// 配置列的汇总项 /// private void SetupColumnSummary(TreeListColumn column) { column.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum; column.SummaryFooterStrFormat = "{0:#,##0.####}"; } #region 类型切换日期展示方法 /// /// 构建带日期或周期 /// /// /// /// private void UpdateDynamicColumns(BandedGridControlEx bandedGridControlEx, DateTime currentDate, string typeDate = "0") { bandedGridControlEx.BandedView.BeginUpdate(); try { if (typeDate == "1") { UpdateWeeklyColumns(bandedGridControlEx, currentDate); } else { UpdateDailyColumns(bandedGridControlEx, currentDate); } } finally { bandedGridControlEx.BandedView.EndUpdate(); } } /// /// 更新TreeList控件的动态列 /// private void UpdateDynamicColumns(TreeBandedGridControlEx bandedGridControlEx, DateTime currentDate, string typeDate = "0") { try { if (typeDate == "1") { UpdateWeeklyColumns(bandedGridControlEx, currentDate); } else { UpdateDailyColumns(bandedGridControlEx, currentDate); } } finally { } } /// /// 按周结构生成列(跨月后从第 1 周重新计) /// private void UpdateWeeklyColumns(BandedGridControlEx grid, DateTime currentDate) { grid.BandedView.BandPanelRowHeight = 45; DateTime endDate = currentDate.AddMonths(3).AddDays(-1); // 3 个月窗口 DateTime weekStart = GetStartOfWeek(currentDate); // 本周周一 int weekIndex = 0; // Week_0 ~ Week_14 while (weekStart <= endDate && weekIndex < 15) { DateTime weekEnd = weekStart.AddDays(6); // 本周周日 DateTime pivotDate = weekStart.AddDays(3); // —— 周四 —— 归属月份基准 int monthKey = pivotDate.Month; // 本周归属的「月份」 /* ---------- 计算“几月第几周” ---------- */ DateTime monthFirstDay = new DateTime(pivotDate.Year, pivotDate.Month, 1); // 当月1号 DateTime firstWeekStart = GetStartOfWeek(monthFirstDay); // 先找周一 // 若周四不在同月,则循环向后推 1 周,直到周四落在目标月 while (firstWeekStart.AddDays(3).Month != monthKey) firstWeekStart = firstWeekStart.AddDays(7); int weekOfMonth = ((weekStart - firstWeekStart).Days / 7) + 1; // 1 起算 /* ---------- 设置 Week_i Band ---------- */ string bandName = $"Week_{weekIndex}"; GridBand weekBand = grid.BandedView.Bands .Cast() .FirstOrDefault(b => b.Name == bandName); if (weekBand != null && weekBand.Columns.Count > 0) { BandedGridColumn weekColumn = weekBand.Columns[0]; weekBand.Visible = true; weekBand.Caption = $"{weekStart:MM.dd}\r\n|\r\n{weekEnd:MM.dd}"; // 父 Band:日期范围 weekColumn.FieldName = weekStart.ToString("yyyy-MM-dd"); // 字段名:周一 weekColumn.Caption = $"{pivotDate.Month}月第{weekOfMonth}周"; // 列标题:几月第几周 weekColumn.Width = 65; DataModel.columnDateMapping[weekColumn] = weekStart; weekColumn.OptionsColumn.AllowEdit = weekEnd >= DateTime.Today; // 仅未来可编辑 weekColumn.Visible = true; } /* ---------- 移到下一周 ---------- */ weekStart = weekEnd.AddDays(1); // 下周周一 weekIndex++; } /* ---------- 隐藏多余 Week_i Band(weekIndex ~ 14) ---------- */ for (int i = weekIndex; i < 15; i++) { GridBand band = grid.BandedView.Bands .Cast() .FirstOrDefault(b => b.Name == $"Week_{i}"); if (band != null) band.Visible = false; } /* ---------- 隐藏所有 Day_* 列 ---------- */ foreach (GridBand band in grid.BandedView.Bands.Cast()) { if (!band.Name.StartsWith("Day_")) continue; band.Visible = false; foreach (BandedGridColumn col in band.Columns) col.Visible = false; } } /// /// 更新TreeList控件的周列 /// private void UpdateWeeklyColumns(TreeBandedGridControlEx grid, DateTime currentDate) { grid.TreeListObj.BeginInit(); DateTime endDate = currentDate.AddMonths(3).AddDays(-1); int weekIndex = 0; DateTime weekStart = GetStartOfWeek(currentDate); while (weekStart <= endDate && weekIndex < 15) { DateTime weekEnd = weekStart.AddDays(6); string bandTitle = $"Week_{weekIndex}"; TreeListBand weekBand = grid.TreeListObj.Bands.Cast() .FirstOrDefault(b => b.Name == bandTitle); if (weekBand != null && weekBand.Columns.Count > 0) { TreeListColumn weekColumn = weekBand.Columns[0]; weekBand.Visible = true; weekBand.Caption = $"{weekStart:MM-dd}至{weekEnd:MM-dd}"; weekColumn.FieldName = weekStart.ToString("yyyy-MM-dd"); // 使用修改后的方法设置 Caption weekColumn.Caption = $"{weekEnd.Month}月第{GetWeekOfMonth(weekEnd)}周"; weekColumn.Width = 105; // 新优化方式(使用字典存储) DataModel.columnDateMapping[weekColumn] = weekStart; weekColumn.OptionsColumn.AllowEdit = weekEnd >= DateTime.Today; weekColumn.Visible = true; } weekStart = weekEnd.AddDays(1); weekIndex++; } foreach (int i in Enumerable.Range(weekIndex, 15 - weekIndex)) { TreeListBand band = grid.TreeListObj.Bands.Cast() .FirstOrDefault(b => b.Name == $"Week_{i}"); if (band != null) band.Visible = false; } foreach (var band in grid.TreeListObj.Bands.Cast()) { if (band.Name.StartsWith("Day_")) { band.Visible = false; foreach (TreeListColumn column in band.Columns) { column.Visible = false; } } } grid.TreeListObj.EndInit(); } /// /// 获取给定日期所在周的开始日期(周一)。 /// private DateTime GetStartOfWeek(DateTime date) { // 这里假设一周是从周一开始的 int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7; DateTime startOfWeek = date.AddDays(-diff); return startOfWeek.Date; // 返回周一的日期 } /// /// 计算某个日期在该月的第几周 /// /// 日期 /// 该月的周数 private int GetWeekOfMonth(DateTime date) { var cultureInfo = new CultureInfo("zh-CN"); var calendar = cultureInfo.Calendar; // 月份的第一天 DateTime firstDayOfMonth = new DateTime(date.Year, date.Month, 1); // 月份第一天是一年中的第几周 int firstWeekOfYear = calendar.GetWeekOfYear(firstDayOfMonth, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); // 当前日期是一年中的第几周 int currentWeekOfYear = calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); // 计算结果为当前周减去当月第一周,再加1(第一周为第1周) return currentWeekOfYear - firstWeekOfYear + 1; } private void UpdateDailyColumns(BandedGridControlEx grid, DateTime currentDate) { grid.BandedView.BandPanelRowHeight = -1; // 原有的日处理逻辑(保持原代码不变) DateTime endDate = currentDate.AddMonths(3).AddDays(-1); grid.BandedView.BeginUpdate(); // 处理每天的列(现有逻辑) for (int i = 0; i < 93; i++) { // 以构建列时的命名规则 "Day_{i}" 查找对应的 GridBand string bandTitle = $"Day_{i}"; GridBand gridBand = grid.BandedView.Bands.Cast().FirstOrDefault(x => x.Name == bandTitle); if (gridBand == null) { continue; } // 假定每个 GridBand 下只有一个子列 BandedGridColumn gridColumn = gridBand.Columns.Count > 0 ? gridBand.Columns[0] : null; if (gridColumn == null) { continue; } // 当前列对应的日期 = 起始日期加 i 天 DateTime dateForColumn = currentDate.AddDays(i); if (dateForColumn <= endDate) { gridBand.Caption = dateForColumn.ToString("MM-dd"); gridBand.Visible = true; gridColumn.FieldName = dateForColumn.ToString("yyyy-MM-dd"); gridColumn.Caption = GetChineseWeekDayNumber(dateForColumn); gridColumn.Width = 70; // 新优化方式(使用字典存储) DataModel.columnDateMapping[gridColumn] = dateForColumn; if (grid == bandGcTop) { if (dateForColumn.Date < DateTime.Now.Date) { gridColumn.OptionsColumn.AllowEdit = false; } else { gridColumn.OptionsColumn.AllowEdit = true; } } gridColumn.Visible = true; } else { gridBand.Visible = false; gridColumn.Visible = false; } } //隐藏所有包含 week_ 的列 foreach (var band in grid.BandedView.Bands.Cast()) { if (band.Name.StartsWith("Week_")) { band.Visible = false; foreach (BandedGridColumn column in band.Columns) { column.Visible = false; } } } grid.BandedView.EndUpdate(); } /// /// 更新TreeList控件的日列 /// private void UpdateDailyColumns(TreeBandedGridControlEx grid, DateTime currentDate) { DateTime endDate = currentDate.AddMonths(3).AddDays(-1); // 核心优化代码:暂停数据源绑定和界面刷新 grid.TreeListObj.BeginInit(); grid.TreeListObj.BeginUpdate(); grid.TreeListObj.LockReloadNodes(); // 阻止节点数据重载(关键优化) try { for (int i = 0; i < 93; i++) { string bandTitle = $"Day_{i}"; TreeListBand treeListBand = grid.TreeListObj.Bands.Cast().FirstOrDefault(x => x.Name == bandTitle); if (treeListBand == null) continue; TreeListColumn treeListColumn = treeListBand.Columns.Count > 0 ? treeListBand.Columns[0] : null; if (treeListColumn == null) continue; DateTime dateForColumn = currentDate.AddDays(i); if (dateForColumn <= endDate) { treeListBand.Caption = dateForColumn.ToString("MM-dd"); treeListBand.Visible = true; treeListColumn.FieldName = dateForColumn.ToString("yyyy-MM-dd"); // 保留原逻辑不变 treeListColumn.Caption = GetChineseWeekDayNumber(dateForColumn); treeListColumn.Width = 70; // 关键优化:改为外部字典缓存 DataModel.columnDateMapping[treeListColumn] = dateForColumn; //treeListColumn.Tag = dateForColumn; if (grid == treebandGcTop) { treeListColumn.OptionsColumn.AllowEdit = dateForColumn.Date >= DateTime.Now.Date; } treeListColumn.Visible = true; } else { treeListBand.Visible = false; treeListColumn.Visible = false; } } foreach (var band in grid.TreeListObj.Bands.Cast()) { if (band.Name.StartsWith("Week_")) { band.Visible = false; foreach (TreeListColumn column in band.Columns) { column.Visible = false; } } } } finally { grid.TreeListObj.UnlockReloadNodes(); // 重新允许节点加载数据 grid.TreeListObj.EndUpdate(); // 一次性完成所有刷新 grid.TreeListObj.EndInit(); } } #endregion /// /// 构建带日期的数据源 /// /// /// /// /// private DataTable MergeMainDataWithDayPlan( DataTable dataMain, DataTable dataDayPlan, DateTime startDate, string typeDate = "0") { string rightPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionValue) ? DataModel.RightDetailModel.UnionValue : "billdocument_id"; string topPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionParentField) ? DataModel.RightDetailModel.UnionParentField : "keyvalue"; // 结束日期 = 开始日期 + 3 个月(不包含该日) DateTime endDate = startDate.AddMonths(3); /* ---------- 1. 预索引 dataDayPlan ---------- */ var dayPlanMap = new Dictionary>(); foreach (DataRow row in dataDayPlan.Rows) { string billId = row[rightPrimaryKey].ToString(); if (!dayPlanMap.TryGetValue(billId, out var list)) { list = new List(); dayPlanMap[billId] = list; } list.Add(row); } /* ---------- 2. 预构建主数据列 ---------- */ for (DateTime dt = startDate; dt < endDate; dt = dt.AddDays(1)) { string colName = dt.ToString("yyyy-MM-dd"); if (!dataMain.Columns.Contains(colName)) dataMain.Columns.Add(colName, typeof(decimal)); } /* ---------- 3. 填充映射表 ---------- */ var dataMap = new Dictionary>(); foreach (DataRow row in dataMain.Rows) { string key = row[topPrimaryKey].ToString(); if (!dataMap.ContainsKey(key)) dataMap[key] = new Dictionary(); if (!dayPlanMap.TryGetValue(key, out var plans)) continue; foreach (var dayRow in plans) { if (dayRow["day"] == DBNull.Value) continue; var dayValue = Convert.ToDateTime(dayRow["day"]); if (dayValue < startDate || dayValue >= endDate) continue; // 改成 < endDate string colName = dayValue.ToString("yyyy-MM-dd"); decimal.TryParse(dayRow["amount"] + "", out var amount); if (dataMap[key].ContainsKey(colName)) dataMap[key][colName] += amount; else dataMap[key][colName] = amount; } } /* ---------- 4. 周报合并(仅当 HasReport && typeDate == "1") ---------- */ if (DataModel.TopModuleModel.HasReport && typeDate == "1") { int weekIndex = 0; DateTime weekStart = startDate; while (weekStart < endDate && weekIndex < 15) { DateTime weekEnd = weekStart.AddDays(6); var weekSumMap = new Dictionary(); for (DateTime dt = weekStart; dt <= weekEnd && dt < endDate; dt = dt.AddDays(1)) { string col = dt.ToString("yyyy-MM-dd"); if (!dataMain.Columns.Contains(col)) continue; foreach (DataRow row in dataMain.Rows) { string key = row[topPrimaryKey].ToString(); if (dataMap.TryGetValue(key, out var map) && map.TryGetValue(col, out var v)) weekSumMap[key] = weekSumMap.TryGetValue(key, out var x) ? x + v : v; } } string firstDayCol = weekStart.ToString("yyyy-MM-dd"); foreach (DataRow row in dataMain.Rows) { string key = row[topPrimaryKey].ToString(); if (weekSumMap.TryGetValue(key, out var sum)) row[firstDayCol] = sum; } for (DateTime dt = weekStart.AddDays(1); dt <= weekEnd && dt < endDate; dt = dt.AddDays(1)) { string col = dt.ToString("yyyy-MM-dd"); if (dataMain.Columns.Contains(col)) dataMain.Columns[col].ColumnMapping = MappingType.Hidden; } weekStart = weekEnd.AddDays(1); weekIndex++; } } /* ---------- 5. 一次性写入 DataTable ---------- */ bandGcTop.rowDateValues.Clear(); if (!dataMain.Columns.Contains("PrecomputedMaxDate")) dataMain.Columns.Add("PrecomputedMaxDate", typeof(string)); for (int i = 0; i < dataMain.Rows.Count; i++) { var row = dataMain.Rows[i]; bandGcTop.rowDateValues[i] = new List(); string key = row[topPrimaryKey].ToString(); if (!dataMap.TryGetValue(key, out var map)) continue; foreach (var kvp in map) { row[kvp.Key] = kvp.Value; if (DateTime.TryParse(kvp.Key, out var d)) bandGcTop.rowDateValues[i].Add(d); } row["PrecomputedMaxDate"] = bandGcTop.rowDateValues[i].Any() ? bandGcTop.rowDateValues[i].Max().ToString("yyyy-MM-dd") : ""; } dataMain.ColumnChanged += OnDataMainColumnChanged; dataMain.AcceptChanges(); return dataMain; } /// /// 数据值改变时 /// /// /// private void OnDataMainColumnChanged(object sender, DataColumnChangeEventArgs e) { DataTable dataMain = (DataTable)sender; if (e.Column.ColumnName.Equals("PrecomputedMaxDate")) { return; } if (dataMain != null && dataMain.Columns.Contains("PrecomputedMaxDate")) { var value = e.Row[e.Column]; int rowHandle = dataMain.Rows.IndexOf(e.Row); DateTime? maxDate = null; // 初始化为 null,表示尚未找到有效日期 bool isdatefile = DateTime.TryParse(e.Column.ColumnName, out DateTime tempDate);//获取改变当前列日期 bool isMaxDatefile = bandGcTop.rowDateValues.TryGetValue(rowHandle, out List currentRowDateColumns);//获取记录日期 if (isdatefile) { if (isMaxDatefile && currentRowDateColumns.Count > 0) { List mvalidDateColumns = bandGcTop.rowDateValues[rowHandle]; if (tempDate > currentRowDateColumns.Max()) // 只有在找到更大的日期时才更新 { if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0) { mvalidDateColumns.Add(tempDate); e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd"); } } else if (tempDate == currentRowDateColumns.Max() && string.IsNullOrEmpty(value + "")) { bandGcTop.rowDateValues[rowHandle].Remove(tempDate); e.Row["PrecomputedMaxDate"] = currentRowDateColumns.Count > 0 ? currentRowDateColumns.Max().ToString("yyyy-MM-dd") : ""; } else { if (!mvalidDateColumns.Contains(tempDate)) { if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0) { mvalidDateColumns.Add(tempDate); e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd"); } } } } else if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0) { bandGcTop.rowDateValues[rowHandle].Add(tempDate); e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd"); } } } } /// /// 构建带日期的数据源 /// /// /// /// /// private void UpdateRowWithDayPlan(DataRow focusedRow, DataTable dataDayPlan, DateTime startDate) { string rightPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionValue) ? DataModel.RightDetailModel.UnionValue : "billdocument_id"; string topPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionParentField) ? DataModel.RightDetailModel.UnionParentField : "keyvalue"; //string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey; //string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey; DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期 // **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)** Dictionary> dayPlanMap = new Dictionary>(); foreach (DataRow row in dataDayPlan.Rows) { string billId = row[rightPrimaryKey].ToString(); if (!dayPlanMap.ContainsKey(billId)) { dayPlanMap[billId] = new List(); } dayPlanMap[billId].Add(row); } // **2. 预构建主数据的列** for (DateTime dt = startDate; dt <= endDate; dt = dt.AddDays(1)) { string colName = dt.ToString("yyyy-MM-dd"); if (!focusedRow.Table.Columns.Contains(colName)) { focusedRow.Table.Columns.Add(colName, typeof(decimal)); // 确保列存在 } } // **3. 预构建数据填充映射表** Dictionary> dataMap = new Dictionary>(); string key = focusedRow[topPrimaryKey].ToString(); if (!dataMap.ContainsKey(key)) { dataMap[key] = new Dictionary(); } // **查找 key 关联的时间数据** if (dayPlanMap.ContainsKey(key)) { foreach (DataRow dayRow in dayPlanMap[key]) { if (dayRow["day"] != DBNull.Value) { DateTime dayValue = Convert.ToDateTime(dayRow["day"]); string colName = dayValue.ToString("yyyy-MM-dd"); // 检查日期是否在范围内,并且列存在 if (dayValue >= startDate && dayValue <= endDate && focusedRow.Table.Columns.Contains(colName)) { decimal.TryParse(dayRow["amount"] + "", out decimal amountValue); // 如果日期已存在,则累加金额;否则直接赋值 if (dataMap[key].ContainsKey(colName)) { dataMap[key][colName] += amountValue; // 累加金额 } else { dataMap[key][colName] = amountValue; // 直接赋值 } } } } } // **4. 一次性填充 DataTable(避免逐行赋值带来的性能问题)** if (dataMap.ContainsKey(key)) { foreach (var col in dataMap[key]) { focusedRow[col.Key] = col.Value; } } } /// /// 日期对照 /// /// /// private string GetChineseWeekDayNumber(DateTime date) { switch (date.DayOfWeek) { case DayOfWeek.Monday: return "一"; case DayOfWeek.Tuesday: return "二"; case DayOfWeek.Wednesday: return "三"; case DayOfWeek.Thursday: return "四"; case DayOfWeek.Friday: return "五"; case DayOfWeek.Saturday: return "六"; case DayOfWeek.Sunday: return "日"; default: return ""; } } /// /// 初始化位置 /// private void InitSpiltLocation() { try { string splitLeftWidth = IniHelper.Read(string.Format("ProductSched_SplitLeft_{0}", DataModel.TopSysModel.ModuleCode)); if (!string.IsNullOrEmpty(splitLeftWidth)) { splitLeftControl.SplitterPosition = Convert.ToInt32(splitLeftWidth); } string splitMainWidth = IniHelper.Read(string.Format("ProductSched_SplitMain_{0}", DataModel.TopSysModel.ModuleCode)); if (!string.IsNullOrEmpty(splitMainWidth)) { splitMainControl.SplitterPosition = Convert.ToInt32(splitMainWidth); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 分隔条位置改变时 /// /// /// private void OnSplitContainerPositionChanged(object sender, EventArgs e) { try { if (DataModel.TopSysModel != null) { IniHelper.Write(string.Format("ProductSched_SplitLeft_{0}", DataModel.TopSysModel.ModuleCode), splitLeftControl.SplitterPosition + ""); IniHelper.Write(string.Format("ProductSched_SplitMain_{0}", DataModel.TopSysModel.ModuleCode), splitMainControl.SplitterPosition + ""); } bandGcTop.gridControl.Refresh(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 合计显示居中设置 /// /// /// private void OnCustomDrawFooterCell(object sender, FooterCellCustomDrawEventArgs e) { e.Appearance.TextOptions.HAlignment = HorzAlignment.Center; } /// /// TreeList合计行单元格居中显示 /// private void OnTreeListCustomDrawFooterCell(object sender, DevExpress.XtraTreeList.CustomDrawFooterCellEventArgs e) { e.Appearance.TextOptions.HAlignment = HorzAlignment.Center; } /// /// 表头颜色设置 /// /// /// private void OnCustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e) { // 判断列的Tag是否为 DateTime if (e.Column != null) { if (e.Column.Caption.StartsWith("第")) { return; // 跳过周列 } DateTime dateTime; if (DataModel.columnDateMapping.TryGetValue(e.Column, out dateTime)) { // 判断日期是否为周末(星期六或星期日) if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday) { // 设置表头文字颜色为红色 e.Appearance.ForeColor = Color.Red; } } } } /// /// TreeList表头颜色自定义绘制(精准适配原BandedGridView逻辑) /// private void OnTreeListCustomDrawColumnHeader(object sender, DevExpress.XtraTreeList.CustomDrawColumnHeaderEventArgs e) { // 判断列的Tag是否为 DateTime if (e.Column != null) { if (e.Column.Caption.StartsWith("第")) { return; // 跳过周列 } DateTime dateTime; if (DataModel.columnDateMapping.TryGetValue(e.Column, out dateTime)) { // 判断日期是否为周末(星期六或星期日) if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday) { // 设置表头文字颜色为红色 e.Appearance.ForeColor = Color.Red; } } } } /// /// 按键点击事件 /// /// /// private void OnBandedViewKeyDown(object sender, KeyEventArgs e) { BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelComboxEdit).Cast().FirstOrDefault(); // 获取第一个符合条件的控件 string typeDate = "0"; if (dataTypeControl != null) { LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit; typeDate = labelAutoTextEdit.EditValue; } BandedGridView bandedGridView = (BandedGridView)sender; if (e.KeyCode == Keys.F7) { GridColumn column = bandedGridView.FocusedColumn; GridColumnModel model = column.Tag as GridColumnModel; if (column != null && column.OptionsColumn.AllowEdit && bandedGridView.RowCount > 0 && bandedGridView.OptionsBehavior.Editable) { // 允许操作 GridCell[] SelectCells = bandedGridView.GetSelectedCells(); if (SelectCells.Length > 1) { object obj = bandedGridView.GetRowCellValue(SelectCells[0].RowHandle, SelectCells[0].Column); if (MessageUtil.Show("是否替换所选单元格值?", MessageBoxButtons.YesNo) == DialogResult.Yes) { WaitForm.ShowForm("数据填充中"); if (obj != null) { foreach (GridCell gridCell in SelectCells) { // 判断列的Tag是否为 DateTime if (gridCell.Column != null) { DateTime dateTime; if (DataModel.columnDateMapping.TryGetValue(gridCell.Column, out dateTime)) { if (typeDate.Equals("1")) { dateTime = dateTime.AddDays(7); } string bj_tig = bandedGridView.GetRowCellValue(gridCell.RowHandle, "bj_tig")?.ToString() ?? ""; if (!DataModel.TopModuleModel.HasReport && bj_tig != "0" && dateTime.Date >= DateTime.Now.Date) { bandedGridView.SetRowCellValue(gridCell.RowHandle, gridCell.Column, obj); } } } } bandedGridView.PostEditor(); e.Handled = true; } WaitForm.HideForm(); } } } } } /// /// TreeList按键事件处理,精准移植原BandedGridView的F7快速填充逻辑 /// private void OnTreeListKeyDown(object sender, KeyEventArgs e) { TreeList treeList = sender as TreeList; if (treeList == null || !treeList.OptionsBehavior.Editable) return; if (e.KeyCode == Keys.F7) { // 使用你框架中定义的精准方法来获取选中的单元格集合 List selectedCells = treeList.GetSelectedCells(); if (selectedCells != null && selectedCells.Count > 0) { // 以第一个选中单元格作为赋值基准值 TreeListCell firstCell = selectedCells[0]; object valueToSet = firstCell.Node.GetValue(firstCell.Column); if (valueToSet != null && MessageUtil.Show("是否替换所选单元格值?", MessageBoxButtons.YesNo) == DialogResult.Yes) { WaitForm.ShowForm("数据填充中"); foreach (TreeListCell cell in selectedCells) { if (cell.Column.OptionsColumn.AllowEdit) { if (DataModel.columnDateMapping.TryGetValue(cell.Column, out DateTime dateTime)) { // 日期必须大于等于今天才允许赋值 string bj_tig = cell.Node.GetValue("bj_tig")?.ToString() ?? ""; if (!DataModel.TopModuleModel.HasReport && bj_tig != "0" && dateTime.Date >= DateTime.Now.Date) { treeList.SetFocusedNode(treebandGcTop.TreeListObj.Nodes[0]); cell.Node.SetValue(cell.Column, valueToSet); } } } } e.Handled = true; WaitForm.HideForm(); } } } } /// /// 构建下方数据 /// /// /// /// /// /// public DataTable BuildCTable(DataTable dtA, DataTable dtPlan, DateTime startDate, int daysCount) { try { // 1. 按“产地”分组 // key: 产地; value: Tuple(总产能, 系数, keyvalue集合) var groupDict = dtA.AsEnumerable() .GroupBy(r => r.Field("产地")) .ToDictionary( g => g.Key, g => new { TotalCapacity = g.First().Field("总产能"), Coefficient = g.First().Field("系数"), KeyValues = g.Select(r => r.Field("keyvalue")).Distinct().ToList() } ); // 2. 构建 C 表结构:固定字段“产地”、“产能”,以及动态日期列(格式 "yyyy-MM-dd") DataTable dtC = new DataTable(); dtC.Columns.Add("产地", typeof(string)); dtC.Columns.Add("总产能", typeof(decimal)); List dateColumns = new List(); for (int i = 0; i < daysCount; i++) { DateTime d = startDate.AddDays(i); string colName = d.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); dtC.Columns.Add(colName, typeof(decimal)); dateColumns.Add(colName); } // 3. 预处理 dtPlan:转换 day 字段为 "yyyy-MM-dd" 字符串,方便后续匹配 var planRows = dtPlan.AsEnumerable() .Select(r => new { BillId = r.Field("billdocument_id"), ShowDay = r.Field("day").ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), Amount = r.Field("amount") }) .ToList(); // 4. 遍历每个分组,构造 C 表行数据 foreach (var kvp in groupDict) { string origin = kvp.Key; decimal totalCapacity = kvp.Value.TotalCapacity; decimal coefficient = kvp.Value.Coefficient; List keyValues = kvp.Value.KeyValues; DataRow newRow = dtC.NewRow(); newRow["产地"] = origin; newRow["总产能"] = totalCapacity; // 对每个动态日期列,从 dtPlan 中查找 billdocument_id 在 keyValues 内, // 且 ShowDay 等于当前列名的记录,将 amount 累加后再乘以系数 foreach (string dateCol in dateColumns) { decimal sumAmount = planRows .Where(pr => keyValues.Contains(pr.BillId) && pr.ShowDay == dateCol) .Sum(pr => pr.Amount); // 乘以系数得到实际值 newRow[dateCol] = sumAmount * coefficient; } dtC.Rows.Add(newRow); } return dtC; } catch (Exception) { return default; } } /// /// 纠正输入异常 /// /// /// private void OnInvalidValueException(object sender, InvalidValueExceptionEventArgs e) { if (e.Value.Equals("")) { e.ExceptionMode = ExceptionMode.Ignore; } } /// /// 说明:右键菜单执行后刷新数据,刷新规则按照上一次查询条件刷新 /// 创建人:龚宇超 /// 创建日期:2017-11-02 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The sender. /// The instance containing the event data. protected void OnGridViewRightCallBack(object sender, EventArgs e) { try { if (TreeMultiHeader) { DataTable dt = this.treebandGcTop.GetGridViewDataSource(); if (dt == null || dt.Rows.Count == 0) return; DataRow SelectTheLine = this.treebandGcTop.GetViewFocusedDataRow(); this.DataModel.TopSearchObj.RememberRow = (this.DataModel.TopModuleModel.AccordingNameSelected == 0); this.DataModel.TopSearchObj.ButtonObj.PerformClick(); if (this.DataModel.TopModuleModel.AccordingNameSelected != 0)//根据主键刷新目标选中行 { DataRow items = dt.Rows.Cast().FirstOrDefault(x => x[this.DataModel.TopModuleModel.ParmaryKey].Equals(SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey])); dt = this.treebandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable(); BindingSource bindingSource = new BindingSource(); bindingSource.DataSource = dt; int numberOfRows = bindingSource.Find(this.DataModel.TopModuleModel.ParmaryKey, SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey].ToString()); this.treebandGcTop.GridView.ClearSelection(); this.treebandGcTop.GridView.FocusedRowHandle = numberOfRows; this.treebandGcTop.GridView.SelectRow(numberOfRows); } //this.OnSearchAfterCallBack(null,null); } else { int oldRowHandle = bandGcTop.GridView.FocusedRowHandle; DataTable dt = this.bandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable(); if (dt == null || dt.Rows.Count == 0) return; DataRow SelectTheLine = dt.Rows[oldRowHandle]; this.DataModel.TopSearchObj.RememberRow = (this.DataModel.TopModuleModel.AccordingNameSelected == 0); this.DataModel.TopSearchObj.ButtonObj.PerformClick(); bandGcTop.GridView.SelectRowHandler(oldRowHandle); if (this.DataModel.TopModuleModel.AccordingNameSelected != 0)//根据主键刷新目标选中行 { DataRow items = dt.Rows.Cast().FirstOrDefault(x => x[this.DataModel.TopModuleModel.ParmaryKey].Equals(SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey])); dt = this.bandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable(); BindingSource bindingSource = new BindingSource(); bindingSource.DataSource = dt; int numb