using DevExpress.Data; using DevExpress.Utils; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Columns; using DevExpress.XtraGrid.Views.BandedGrid; using Lskj.Business.Impl; using Lskj.Control; using Lskj.Control.Model; 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.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Lskj.ProductiSched { public partial class FrmProductSched : UserControl { 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.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); DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, bandGcTop); DataModel.TopSearchObj.Model = DataModel.TopSysModel; DataTable detailsTab = BaseModuleImpl.GetBaseDetailPages(DataModel.TopSysModel.ModuleCode); if (detailsTab != null) { if (detailsTab.Rows.Count > 0) { 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.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.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; 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; } //上方表格 bandGcTop.Model = DataModel.TopSysModel; bandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey); bandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey), DataModel.TopSysModel); bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey)); AddDataColumns(bandGcTop); //下方表格 if (!string.IsNullOrEmpty(DataModel.BottomSysModel.ModuleCode)) { bandGcBottom.Model = DataModel.BottomSysModel; bandGcBottom.SetEditColumns(DataModel.BottomGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.BottomModuleModel.FormKey); bandGcBottom.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.BottomModuleModel.FormKey), DataModel.BottomSysModel); bandGcBottom.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.BottomModuleModel.FormKey)); AddDataColumns(bandGcBottom); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { gridBand.OptionsBand.AllowSize = false; foreach (BandedGridColumn bandedGridColumn in gridBand.Columns) { bandedGridColumn.OptionsColumn.AllowSize = false; } } OnBandedViewColumnWidthChanged(bandGcTop.BandedView, null); } //右侧表格 if (!string.IsNullOrEmpty(DataModel.RightSysModel.ModuleCode)) { gcRight.Model = DataModel.RightSysModel; gcRight.SetEditColumns(DataModel.RightGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.RightModuleModel.FormKey); gcRight.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.RightModuleModel.FormKey), DataModel.RightSysModel); gcRight.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.RightModuleModel.FormKey)); } } /// /// 绑定控件事件 /// public void InitControlEvents() { splitLeftControl.SplitterPositionChanged += OnSplitContainerPositionChanged; splitMainControl.SplitterPositionChanged += OnSplitContainerPositionChanged; DataModel.TopSearchObj.OnDataSourceBindCallBack += OnDataSourceBindCallBack; DataModel.TopSearchObj.OnSearchAfterCallBack += OnSearchAfterCallBack; bandGcTop.BandedView.BandWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.ColumnWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcBottom.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcTop.BandedView.FocusedRowObjectChanged += OnBandedTopFocusedRowObjectChanged; } /// /// 选中行改变时 /// /// /// private void OnBandedTopFocusedRowObjectChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs e) { GridDetailModel model = DataModel.RightDetailModel; DataRow rowItem = bandGcTop.BandedView.GetFocusedDataRow(); string searchSql = this.GetSearchSql(model, rowItem, false); gcRight.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql)); } /// /// 获取查询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.IsReadOnly || model.IsChart ? model.DetailSql : DataModel.RightModuleModel.MenuSql; sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue); DataRow row = 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; } /// /// 宽度改变时 /// /// /// private void OnBandedViewColumnWidthChanged(object sender, EventArgs e) { if (sender == bandGcTop.BandedView) { int allWidth = 0; foreach (GridBand gridBand in bandGcTop.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { allWidth += gridBand.Width; } } List bandedColumnList = new List(); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { bandedColumnList.AddRange(gridBand.Columns.Cast()); } } int perWidth = allWidth / bandedColumnList.Count; foreach (BandedGridColumn bandedGridColumn in bandedColumnList) { bandedGridColumn.Width = perWidth; } } } /// /// 水平滚动条改变时 /// /// /// private void OnBandedViewLeftCoordChanged(object sender, EventArgs e) { if (sender == bandGcTop.BandedView) { bandGcBottom.BandedView.LeftCoord = bandGcTop.BandedView.LeftCoord; } else if (sender == bandGcBottom.BandedView) { bandGcTop.BandedView.LeftCoord = bandGcBottom.BandedView.LeftCoord; } } /// /// 搜索条件绑定完成后 /// /// /// private void OnDataSourceBindCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; UpdateDynamicColumns(bandGcTop, dateTime); UpdateDynamicColumns(bandGcBottom, dateTime); } } /// /// 搜索后事件 /// /// /// private void OnSearchAfterCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; UpdateDynamicColumns(bandGcTop, dateTime); UpdateDynamicColumns(bandGcBottom, dateTime); DataTable dataMain = bandGcTop.GridControl.DataSourceTable(); string sqlValue = DataModel.RightModuleModel.MenuSql; sqlValue = $"{ReplaceHelper.ReplaceWhereCond(sqlValue)} and day >= '{dateTime.ToString("yyyy-MM-dd")}'"; DataTable dataDayPlan = BaseImpl.GetDataTableResult(sqlValue); MergeMainDataWithDayPlan(dataMain, dataDayPlan, dateTime); } } /// /// 获取数据源缓存 /// /// /// 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 = true; } foreach (GridBand gridBand in bandedGridControlEx.BandedView.Bands) { gridBand.Fixed = 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; bandedGridControlEx.BandedView.Bands.Add(gridBand); BandedGridColumn gridColumn = new BandedGridColumn(); gridColumn.AppearanceCell.Options.UseTextOptions = true; gridColumn.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.OptionsColumn.AllowMove = false; gridColumn.OptionsColumn.AllowSize = false; gridColumn.FieldName = $"DDay_{i}"; gridColumn.Width = 70; gridColumn.DisplayFormat.FormatType = FormatType.Numeric; gridColumn.DisplayFormat.FormatString = "{0:#,##0.####}"; gridColumn.Visible = false; if (bandedGridControlEx == bandGcTop) { GridColumnSummaryItem gridColumnSummaryItem = gridColumn.Summary.Add(); gridColumnSummaryItem.FieldName = gridColumn.FieldName; gridColumnSummaryItem.DisplayFormat = "{0:#,##0.####}"; gridColumnSummaryItem.SummaryType = SummaryItemType.Sum; } gridBand.Columns.Add(gridColumn); } } /// /// 根据日期修改列状态 /// /// private void UpdateDynamicColumns(BandedGridControlEx bandedGridControlEx, DateTime currentDate) { // 定义三个月的结束日期:起始日期加3个月减1天 DateTime endDate = currentDate.AddMonths(3).AddDays(-1); bandedGridControlEx.BandedView.BeginUpdate(); try { for (int i = 0; i < 93; i++) { // 以构建列时的命名规则 "Day_{i}" 查找对应的 GridBand string bandTitle = $"Day_{i}"; GridBand gridBand = bandedGridControlEx.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.Visible = true; gridColumn.Visible = true; // 父列标题:上行为日期(MM-dd),下行为中文星期(完整格式) string bandCaption = dateForColumn.ToString("MM-dd"); gridBand.Caption = bandCaption; // 子列标题只显示中文星期数字,例如:如果是周三,则显示“3”对应的“三” gridColumn.Caption = GetChineseWeekDayNumber(dateForColumn); gridColumn.FieldName = bandCaption; } else { gridBand.Visible = false; gridColumn.Visible = false; } } } finally { bandedGridControlEx.BandedView.EndUpdate(); } } /// /// 构建带日期的数据源 /// /// /// /// /// private DataTable MergeMainDataWithDayPlan(DataTable dataMain, DataTable dataDayPlan, DateTime startDate) { 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["billdocument_id"].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("MM-dd"); if (!dataMain.Columns.Contains(colName)) { dataMain.Columns.Add(colName, typeof(decimal)); // 确保列存在 } } // **3. 预构建数据填充映射表** Dictionary> dataMap = new Dictionary>(); foreach (DataRow row in dataMain.Rows) { string key = row["keyvalue"].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("MM-dd"); if (dayValue >= startDate && dayValue <= endDate && dataMain.Columns.Contains(colName)) { dataMap[key][colName] = Convert.ToDecimal(dayRow["amount"]); } } } } } // **4. 一次性填充 DataTable(避免逐行赋值带来的性能问题)** foreach (DataRow row in dataMain.Rows) { string key = row["keyvalue"].ToString(); if (dataMap.ContainsKey(key)) { foreach (var col in dataMap[key]) { row[col.Key] = col.Value; } } } return dataMain; } /// /// 日期对照 /// /// /// 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.To