Files
lserp_cs_6.0/插件库/Lskj.ProductSched/FrmProductSched.cs
T
wyf 1c650d159b SVN r388
SVN-Revision: r388
2025-03-25 07:33:10 +00:00

2127 lines
98 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;
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 ProductDataModel DataModel;
public FrmProductSched()
{
InitializeComponent();
}
/// <summary>
/// 界面加载时
/// </summary>
public void OnLoad(DynamicProductSchedModel mainModel)
{
GetControlData(mainModel);
InitSpiltLocation();
InitControlView();
InitControlEvents();
SetControlData();
}
/// <summary>
/// 获取数据
/// </summary>
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);
if (detailsTab != null)
{
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);
}
}
}
/// <summary>
/// 设置数据
/// </summary>
public void SetControlData()
{
}
/// <summary>
/// 初始化控件
/// </summary>
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<System.Windows.Forms.Control>().Max(n => n.Location.X + n.Width) + 5;
}
//构建树表格
if (TreeMultiHeader)//若为多表头树表格模式
{
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);
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);
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 (DataModel.BottomSysModel != null && !string.IsNullOrEmpty(DataModel.BottomSysModel.ModuleCode))
{
bandGcBottom.Model = DataModel.BottomSysModel;
bandGcBottom.SetEditColumns(DataModel.BottomGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.BottomModuleModel.FormKey);
bandGcBottom.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.BottomModuleModel.ModeCode), DataModel.BottomSysModel);
bandGcBottom.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.BottomModuleModel.ModeCode));
AddDataColumns(bandGcBottom);
foreach (GridBand gridBand in bandGcBottom.BandedView.Bands)
{
gridBand.OptionsBand.AllowSize = false;
foreach (BandedGridColumn bandedGridColumn in gridBand.Columns)
{
bandedGridColumn.OptionsColumn.AllowSize = false;
}
}
bandGcBottom.BandedView.OptionsBehavior.Editable = false;
if (TreeMultiHeader)
{
OnBandedViewColumnWidthChanged(treebandGcTop.TreeListObj, null);
}
else
{
OnBandedViewColumnWidthChanged(bandGcTop.BandedView, null);
}
}
else
{
splitLeftControl.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1;
}
//右侧表格
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.ModeCode), DataModel.RightSysModel);
gcRight.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.RightModuleModel.ModeCode));
}
}
/// <summary>
/// 绑定控件事件
/// </summary>
public void InitControlEvents()
{
splitLeftControl.SplitterPositionChanged += OnBandedViewColumnWidthChanged;
splitMainControl.SplitterPositionChanged += OnSplitContainerPositionChanged;
DataModel.TopSearchObj.OnDataSourceBindCallBack += OnDataSourceBindCallBack;
DataModel.TopSearchObj.OnSearchAfterCallBack += OnSearchAfterCallBack;
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;
}
/// <summary>
/// 判断单元格是否可以编辑
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnShowingEditor(object sender, CancelEventArgs e)
{
BandedGridView view = sender as BandedGridView;
if (view == null) return;
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<string> showDays = DataModel.nonEditableCells[billDocumentId];
// 如果列名(日期)在 showday_list 里,则禁用编辑
if (showDays.Contains(columnName))
{
e.Cancel = true; // 取消编辑,单元格变灰
}
}
}
}
/// <summary>
/// 判断TreeList单元格是否可以编辑(精准适配原BandedGridView逻辑)
/// </summary>
private void OnTreeListShowingEditor(object sender, CancelEventArgs e)
{
TreeList treeList = sender as TreeList;
if (treeList == null || treeList.FocusedNode == null) return;
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<string> showDays = DataModel.nonEditableCells[billDocumentId];
// 如果列名(日期)在 showday_list 里,则禁用编辑
if (showDays.Contains(columnName))
{
e.Cancel = true; // 取消编辑,单元格变灰
}
}
}
}
/// <summary>
/// 保存按钮点击时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBtnSaveClick(object sender, EventArgs e)
{
if (SaveGridRecord())
{
if (SaveDatePlanRecord())
{
DataModel.TopSearchObj.ButtonObj.PerformClick();
}
}
}
/// <summary>
/// 保存主表数据
/// </summary>
/// <param name="isErrorTips"></param>
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<BaseSaveModel> mList = new List<BaseSaveModel>();
DataTable dataTable = TreeMultiHeader ? treebandGcTop.GetGridViewDataSource() : bandGcTop.BandedView.GridControl.DataSource as DataTable;
DataRow[] modifiedRows = dataTable
.Rows
.Cast<DataRow>()
.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<DataRow>().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;
}
}
}
/// <summary>
/// 保存日期数据
/// </summary>
private bool SaveDatePlanRecord()
{
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().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;
}
}
/// <summary>
/// 保存日计划变更数据(批量保存)。
/// 调用存储过程 usp_MergeDayPlanChanges,将所有变更记录一次性提交到数据库。
/// 通过 TVP 参数传递数据,同时捕获输出参数 @msg 和返回值。
/// </summary>
/// <param name="tvp">包含所有变更记录的 DataTable,必须与 dbo.DayPlanChangeType 定义一致</param>
/// <param name="message">输出提示信息,存储过程执行后的返回消息</param>
/// <returns>存储过程返回值,成功返回 1,失败返回 0</returns>
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;
}
/// <summary>
/// 单元格点击刷新当前行数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().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.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql));
if (e != null)
{
if (labelDateEdit != null)
{
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
DataRow focusedRow = bandGcTop.BandedView.GetFocusedDataRow();
DataTable dataDayPlan = gcRight.GridControl.DataSourceTable().Copy();
UpdateRowWithDayPlan(focusedRow, dataDayPlan, dateTime);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// TreeList聚焦节点改变刷新当前行数据(精确移植原点击事件逻辑)
/// </summary>
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<BaseUserControl>()
.FirstOrDefault(n => n is LabelDateEdit);
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls
.Cast<System.Windows.Forms.Control>()
.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.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql));
// 更新行数据逻辑
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
DataTable dataDayPlan = gcRight.GridControl.DataSourceTable().Copy();
UpdateRowWithDayPlan(rowItem, dataDayPlan, dateTime);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 获取查询sql
/// </summary>
/// <param name="model"></param>
/// <param name="rowItem"></param>
/// <param name="isLeft"></param>
/// <returns></returns>
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 = 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;
}
/// <summary>
/// 宽度改变事件处理,兼容BandedGridView和TreeList
/// </summary>
private void OnBandedViewColumnWidthChanged(object sender, EventArgs e)
{
if (bandGcBottom.Visible)
{
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)
{
allWidth += treeListColumn.Width;
}
}
}
}
else
{
return; // 非预期sender类型时直接退出
}
// 调整底部bandGcBottom的列宽(始终为BandedGridView类型)
List<BandedGridColumn> bottomColumnList = new List<BandedGridColumn>();
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<BandedGridColumn>());
}
}
// 按计算好的宽度均分调整
if (bottomColumnList.Count > 0)
{
int perWidth = allWidth / bottomColumnList.Count;
foreach (BandedGridColumn bandedGridColumn in bottomColumnList)
{
bandedGridColumn.Width = perWidth;
}
}
}
}
/// <summary>
/// 水平滚动条改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBandedViewLeftCoordChanged(object sender, EventArgs e)
{
if (!bandGcBottom.Visible) 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;
}
}
}
/// <summary>
/// 搜索条件绑定完成后
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDataSourceBindCallBack(object sender, EventArgs e)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().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;
UpdateDynamicColumns(bandGcBottom, dateTime, typeDate);
if (TreeMultiHeader)
{
UpdateDynamicColumns(treebandGcTop, dateTime, typeDate);
}
else
{
UpdateDynamicColumns(bandGcTop, dateTime, typeDate);
}
}
}
/// <summary>
/// 搜索后事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSearchAfterCallBack(object sender, EventArgs e)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().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);
}
UpdateDynamicColumns(bandGcBottom, dateTime, typeDate);
DataTable dataMain = null;
DataTable dataDetail = null;
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 (bandGcBottom.Visible)
{
DataTable bottomTab = BuildCTable(dataDetail, dataDayPlan, dateTime, 93);
bandGcBottom.BandedView.GridControl.DataSource = bottomTab;
}
if (!TreeMultiHeader)
{
MergeMainDataWithDayPlan(dataMain, dataDayPlan, dateTime, typeDate);
bandGcTop.SetGridViewDataSource(dataMain);
OnBandedViewRowCellClick(bandGcTop.BandedView, null);
}
else
{
treebandGcTop.SetGridViewDataSource(dataMain);
}
}
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<string> daysSet = new HashSet<string>(showDayList.Split(','));
DataModel.nonEditableCells[billDocumentId] = daysSet;
}
}
}
/// <summary>
/// 获取数据源缓存
/// </summary>
/// <param name="cachesDic"></param>
/// <param name="dynamicModel"></param>
public void GetDataCaches(Dictionary<object, Hashtable> cachesDic)
{
//获取通用数据
Task<ModuleModel> sysModelTask = cachesDic.GetTask<ModuleModel>(this, "SysModel");
Task<DynamicModel> dynamicModelTask = cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
Task<List<GridDetailModel>> detailsTask = cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
Task<bool> getDataCachesTask = cachesDic.AddTask(this, "DataCaches", new Task<bool>(() =>
{
ModuleModel sysModel = sysModelTask.Result;
DynamicModel dynamicModel = dynamicModelTask.Result;
//创建数据
if (sysModel != null && dynamicModel != null)
{
Task<DataRow> menuConfigTabTask = cachesDic.AddTask(this, "MenuConfigTab", new Task<DataRow>(() =>
{
return BaseImpl.GetMenuConfigTab(dynamicModel.ModuleId); //获取菜单其他配置
}));
if (dynamicModel is DynamicExcelModel)//isExcel
{
Task<string> basePrimaryKeyTask = cachesDic.AddTask(this, "BasePrimaryKey", new Task<string>(() =>
{
return BaseImpl.GetBasePrimaryKey(dynamicModel.ModuleCode);
}));
Task<DataTable> gridColumnsTask = cachesDic.AddTask(this, "GridColumns", new Task<DataTable>(() =>
{
return BaseModuleImpl.GetBaseGridColumns(dynamicModel.ModuleCode);
}));
}
else
{
//构建主表数据
}
}
return true;
}));
}
/// <summary>
/// 添加虚拟日期列
/// </summary>
private void AddDataColumns(BandedGridControlEx bandedGridControlEx)
{
if (bandedGridControlEx == bandGcTop)
{
bandedGridControlEx.BandedView.OptionsView.ShowFooter = true;
}
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;
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;
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 = 140;
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);
}
}
/// <summary>
/// 添加多表头树结构模式的虚拟日期列(基于TreeList)
/// </summary>
/// <summary>
/// 添加虚拟日期列(树的多表头模式)
/// </summary>
/// <summary>
/// 添加虚拟日期列(树的多表头模式)
/// </summary>
private void AddDataColumns(TreeBandedGridControlEx bandedGridControlEx)
{
// 核心优化代码:暂停数据源绑定和界面刷新
bandedGridControlEx.TreeListObj.BeginUpdate();
bandedGridControlEx.TreeListObj.LockReloadNodes(); // 阻止节点数据重载(关键优化)
try
{
if (bandedGridControlEx == treebandGcTop)
{
bandedGridControlEx.TreeListObj.OptionsView.ShowSummaryFooter = true;
}
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.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 = 140,
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.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(); // 一次性完成所有刷新
}
}
/// <summary>
/// 创建TreeList统一的列
/// </summary>
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;
}
/// <summary>
/// 配置列的汇总项
/// </summary>
private void SetupColumnSummary(TreeListColumn column)
{
column.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum;
column.SummaryFooterStrFormat = "{0:#,##0.####}";
}
#region 类型切换日期展示方法
/// <summary>
/// 构建带日期或周期
/// </summary>
/// <param name="bandedGridControlEx"></param>
/// <param name="currentDate"></param>
/// <param name="typeDate"></param>
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();
}
}
/// <summary>
/// 更新TreeList控件的动态列
/// </summary>
private void UpdateDynamicColumns(TreeBandedGridControlEx bandedGridControlEx, DateTime currentDate, string typeDate = "0")
{
try
{
if (typeDate == "1")
{
UpdateWeeklyColumns(bandedGridControlEx, currentDate);
}
else
{
UpdateDailyColumns(bandedGridControlEx, currentDate);
}
}
finally
{
}
}
/// <summary>
/// 按照周结构生成列
/// </summary>
/// <param name="grid"></param>
/// <param name="currentDate"></param>
private void UpdateWeeklyColumns(BandedGridControlEx grid, DateTime currentDate)
{
DateTime endDate = currentDate.AddMonths(3).AddDays(-1); // 计算结束日期
int weekIndex = 0;
DateTime weekStart = GetStartOfWeek(currentDate); // 获取本周的周一日期
// 查找并更新15个虚拟的周列
while (weekStart <= endDate && weekIndex < 15)
{
DateTime weekEnd = weekStart.AddDays(6); // 周日的日期是周一 + 6 天
// 查找现有的虚拟周列(Week_0, Week_1, ..., Week_14
string bandTitle = $"Week_{weekIndex}";
GridBand weekBand = grid.BandedView.Bands.Cast<GridBand>()
.FirstOrDefault(b => b.Name == bandTitle);
if (weekBand != null && weekBand.Columns.Count > 0)
{
BandedGridColumn weekColumn = weekBand.Columns[0];
weekBand.Visible = true;
// 设置周列表头:例如 "03-01至03-07"
weekBand.Caption = $"{weekStart:MM-dd}至{weekEnd:MM-dd}";
weekColumn.FieldName = weekStart.ToString("yyyy-MM-dd");
// 设置列的内容为“第几周”
weekColumn.Caption = $"第{GetWeekOfYear(weekStart)}周";
// 设置列的宽度
weekColumn.Width = 140;
// 设置该列的Tag为周的开始日期(便于后续操作)
DataModel.columnDateMapping[weekColumn] = weekStart;
// 设置是否允许编辑
if (weekEnd >= DateTime.Today)
{
weekColumn.OptionsColumn.AllowEdit = true;
}
else
{
weekColumn.OptionsColumn.AllowEdit = false;
}
weekColumn.Visible = true; // 显示该列
}
// 更新到下一周
weekStart = weekEnd.AddDays(1); // 下一周的周一
weekIndex++;
}
// 隐藏多余的周列(超过15周的列)
foreach (int i in Enumerable.Range(weekIndex, 15 - weekIndex))
{
GridBand band = grid.BandedView.Bands.Cast<GridBand>()
.FirstOrDefault(b => b.Name == $"Week_{i}");
if (band != null) band.Visible = false;
}
// 隐藏所有包含 Day_ 的列
foreach (var band in grid.BandedView.Bands.Cast<GridBand>())
{
if (band.Name.StartsWith("Day_"))
{
band.Visible = false;
foreach (BandedGridColumn column in band.Columns)
{
column.Visible = false;
}
}
}
}
/// <summary>
/// 更新TreeList控件的周列
/// </summary>
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<TreeListBand>()
.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");
weekColumn.Caption = $"第{GetWeekOfYear(weekStart)}周";
weekColumn.Width = 140;
// 新优化方式(使用字典存储)
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<TreeListBand>()
.FirstOrDefault(b => b.Name == $"Week_{i}");
if (band != null) band.Visible = false;
}
foreach (var band in grid.TreeListObj.Bands.Cast<TreeListBand>())
{
if (band.Name.StartsWith("Day_"))
{
band.Visible = false;
foreach (TreeListColumn column in band.Columns)
{
column.Visible = false;
}
}
}
grid.TreeListObj.EndInit();
}
/// <summary>
/// 获取给定日期所在周的开始日期(周一)。
/// </summary>
private DateTime GetStartOfWeek(DateTime date)
{
// 这里假设一周是从周一开始的
int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7;
DateTime startOfWeek = date.AddDays(-diff);
return startOfWeek.Date; // 返回周一的日期
}
/// <summary>
/// 计算某个日期属于这一年的第几周
/// </summary>
/// <param name="date">日期</param>
/// <returns>周数</returns>
private int GetWeekOfYear(DateTime date)
{
var cultureInfo = new CultureInfo("zh-CN");
var calendar = cultureInfo.Calendar;
return calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
private void UpdateDailyColumns(BandedGridControlEx grid, DateTime currentDate)
{
// 原有的日处理逻辑(保持原代码不变)
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<GridBand>().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<GridBand>())
{
if (band.Name.StartsWith("Week_"))
{
band.Visible = false;
foreach (BandedGridColumn column in band.Columns)
{
column.Visible = false;
}
}
}
grid.BandedView.EndUpdate();
}
/// <summary>
/// 更新TreeList控件的日列
/// </summary>
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<TreeListBand>().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<TreeListBand>())
{
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
/// <summary>
/// 构建带日期的数据源
/// </summary>
/// <param name="dataMain"></param>
/// <param name="dataDayPlan"></param>
/// <param name="startDate"></param>
/// <returns></returns>
private DataTable MergeMainDataWithDayPlan(DataTable dataMain, DataTable dataDayPlan, DateTime startDate, string typeDate = "0")
{
string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey;
string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey;
DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期
// **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)**
Dictionary<string, List<DataRow>> dayPlanMap = new Dictionary<string, List<DataRow>>();
foreach (DataRow row in dataDayPlan.Rows)
{
string billId = row[rightPrimaryKey].ToString();
if (!dayPlanMap.ContainsKey(billId))
{
dayPlanMap[billId] = new List<DataRow>();
}
dayPlanMap[billId].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. 预构建数据填充映射表**
Dictionary<string, Dictionary<string, decimal>> dataMap = new Dictionary<string, Dictionary<string, decimal>>();
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (!dataMap.ContainsKey(key))
{
dataMap[key] = new Dictionary<string, decimal>();
}
// **查找 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 && dataMain.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. 如果有报告(HasReport 为 true)且 typeDate 为 "1",合并同一周的数据**
if (DataModel.TopModuleModel.HasReport && typeDate == "1")
{
int weekIndex = 0;
DateTime tempStartDate = startDate;
while (tempStartDate <= endDate && weekIndex < 15)
{
DateTime weekEnd = tempStartDate.AddDays(6); // 计算本周的周日
// 为每个 key 存储合并的数据
Dictionary<string, decimal> weekSumMap = new Dictionary<string, decimal>();
// 查找当前周的所有列(如 03-01, 03-02, ...
string weekColumnPrefix = $"{tempStartDate:yyyy-MM-dd}";
// 对每一天的列进行累加,合并到这一周的第一天
for (DateTime dt = tempStartDate; dt <= weekEnd && dt <= endDate; dt = dt.AddDays(1))
{
string colName = dt.ToString("yyyy-MM-dd"); // 使用 yyyy-MM-dd 格式
if (dataMain.Columns.Contains(colName))
{
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (dataMap.ContainsKey(key) && dataMap[key].ContainsKey(colName))
{
// 累加数据并更新 weekSumMap
if (!weekSumMap.ContainsKey(key))
{
weekSumMap[key] = 0;
}
weekSumMap[key] += dataMap[key][colName]; // 累加当前列的数据
}
}
}
}
// 将合并的数据写入到周一(即第一天)的列
string firstDayCol = tempStartDate.ToString("yyyy-MM-dd"); // 使用 yyyy-MM-dd 格式
// 为每个 key 更新其对应的合并数据
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (weekSumMap.ContainsKey(key))
{
row[firstDayCol] = weekSumMap[key]; // 设置周一的值为合并后的总和
}
}
// 隐藏其他非周一的列
for (DateTime dt = tempStartDate.AddDays(1); dt <= weekEnd && dt <= endDate; dt = dt.AddDays(1))
{
string colName = dt.ToString("yyyy-MM-dd"); // 使用 yyyy-MM-dd 格式
if (dataMain.Columns.Contains(colName))
{
dataMain.Columns[colName].ColumnMapping = MappingType.Hidden; // 将非周一列隐藏
}
}
// 更新到下一周
tempStartDate = weekEnd.AddDays(1); // 下一周的周一
weekIndex++;
}
}
// **5. 一次性填充 DataTable(避免逐行赋值带来的性能问题)**
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (dataMap.ContainsKey(key))
{
foreach (var col in dataMap[key])
{
row[col.Key] = col.Value;
}
}
}
return dataMain;
}
/// <summary>
/// 构建带日期的数据源
/// </summary>
/// <param name="focusedRow"></param>
/// <param name="dataDayPlan"></param>
/// <param name="startDate"></param>
/// <returns></returns>
private void UpdateRowWithDayPlan(DataRow focusedRow, DataTable dataDayPlan, DateTime startDate)
{
string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey;
string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey;
DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期
// **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)**
Dictionary<string, List<DataRow>> dayPlanMap = new Dictionary<string, List<DataRow>>();
foreach (DataRow row in dataDayPlan.Rows)
{
string billId = row[rightPrimaryKey].ToString();
if (!dayPlanMap.ContainsKey(billId))
{
dayPlanMap[billId] = new List<DataRow>();
}
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<string, Dictionary<string, decimal>> dataMap = new Dictionary<string, Dictionary<string, decimal>>();
string key = focusedRow[topPrimaryKey].ToString();
if (!dataMap.ContainsKey(key))
{
dataMap[key] = new Dictionary<string, decimal>();
}
// **查找 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;
}
}
}
/// <summary>
/// 日期对照
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
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 "";
}
}
/// <summary>
/// 初始化位置
/// </summary>
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);
}
}
/// <summary>
/// 分隔条位置改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 + "");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 合计显示居中设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCustomDrawFooterCell(object sender, FooterCellCustomDrawEventArgs e)
{
e.Appearance.TextOptions.HAlignment = HorzAlignment.Center;
}
/// <summary>
/// TreeList合计行单元格居中显示
/// </summary>
private void OnTreeListCustomDrawFooterCell(object sender, DevExpress.XtraTreeList.CustomDrawFooterCellEventArgs e)
{
e.Appearance.TextOptions.HAlignment = HorzAlignment.Center;
}
/// <summary>
/// 表头颜色设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
}
}
}
/// <summary>
/// TreeList表头颜色自定义绘制(精准适配原BandedGridView逻辑)
/// </summary>
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;
}
}
}
}
/// <summary>
/// 按键点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBandedViewKeyDown(object sender, KeyEventArgs e)
{
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 > 0)
{
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 (dateTime.Date >= DateTime.Now.Date)
{
bandedGridView.SetRowCellValue(gridCell.RowHandle, gridCell.Column, obj);
}
}
}
}
bandedGridView.PostEditor();
e.Handled = true;
}
WaitForm.HideForm();
}
}
}
}
}
/// <summary>
/// TreeList按键事件处理,精准移植原BandedGridView的F7快速填充逻辑
/// </summary>
private void OnTreeListKeyDown(object sender, KeyEventArgs e)
{
TreeList treeList = sender as TreeList;
if (treeList == null || !treeList.OptionsBehavior.Editable) return;
if (e.KeyCode == Keys.F7)
{
TreeListColumn column = treeList.FocusedColumn;
if (column != null && column.OptionsColumn.AllowEdit && treeList.AllNodesCount > 0)
{
// 获取当前聚焦单元格的值
object focusedValue = treeList.FocusedNode?.GetValue(column);
if (focusedValue != null && MessageUtil.Show("是否替换所选单元格值?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
WaitForm.ShowForm("数据填充中");
foreach (TreeListNode node in treeList.Selection)
{
DateTime dateTime;
if (DataModel.columnDateMapping.TryGetValue(column, out dateTime))
{
if (dateTime.Date >= DateTime.Now.Date)
{
node.SetValue(column, focusedValue);
}
}
}
treeList.PostEditor();
e.Handled = true;
WaitForm.HideForm();
}
}
}
}
/// <summary>
/// 构建下方数据
/// </summary>
/// <param name="dtA"></param>
/// <param name="dtPlan"></param>
/// <param name="startDate"></param>
/// <param name="daysCount"></param>
/// <returns></returns>
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<string>("产地"))
.ToDictionary(
g => g.Key,
g => new
{
TotalCapacity = g.First().Field<decimal>("总产能"),
Coefficient = g.First().Field<decimal>("系数"),
KeyValues = g.Select(r => r.Field<string>("keyvalue")).Distinct().ToList()
}
);
// 2. 构建 C 表结构:固定字段“产地”、“产能”,以及动态日期列(格式 "yyyy-MM-dd"
DataTable dtC = new DataTable();
dtC.Columns.Add("产地", typeof(string));
dtC.Columns.Add("总产能", typeof(decimal));
List<string> dateColumns = new List<string>();
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<string>("billdocument_id"),
ShowDay = r.Field<DateTime>("day").ToString("yyyy-MM-dd", CultureInfo.InvariantCulture),
Amount = r.Field<decimal>("amount")
})
.ToList();
// 4. 遍历每个分组,构造 C 表行数据
foreach (var kvp in groupDict)
{
string origin = kvp.Key;
decimal totalCapacity = kvp.Value.TotalCapacity;
decimal coefficient = kvp.Value.Coefficient;
List<string> keyValues = kvp.Value.KeyValues;
DataRow newRow = dtC.NewRow();
newRow["产地"] = origin;
newRow["总产能"] = totalCapacity;
// 对每个动态日期列,从 dtPlan 中查找 billdocument_id 在 keyValues 内,
// 且 ShowDay 等于当前列名的记录,将 amount 累加后再乘以系数
foreach (stri