SVN-Revision: r960
This commit is contained in:
tdx
2025-09-03 03:09:09 +00:00
parent dc5c6cdef4
commit 3c6dff2ec5
+329 -180
View File
@@ -1211,172 +1211,398 @@ namespace Lskj.PubBill
}
}
}
#region -
// 只固定“最初存在的静态列”(一般是左侧来源等);动态日期/合计列永不固定
private HashSet<string> _baselineFixedFields;
// 防重入/去抖(避免短时间内重复重绑与布局抖动)
private volatile bool _mainRebindBusy = false;
private int _mainRebindScheduled = 0;
private DateTime _lastRebindAt = DateTime.MinValue;
private readonly TimeSpan _rebindDebounce = TimeSpan.FromMilliseconds(25);
#endregion
#region + OnDataFileRefrshFile
private void OnDataFileRefrshFile(object sender, EventArgs e)
{
var gv = gcMain.GridView;
gv.BeginUpdate();
try
{
AddDataColumns(); // 只固定“基线静态列”,动态日期/合计列不固定
UpdateDynamicColumns(); // 日期列 FieldName/Caption/Tag
UpdateSummaryData(); // 你的汇总渲染逻辑
}
finally
{
gv.EndUpdate();
}
// 不要在回调栈里直接改数据源;改为“请求重绑”,异步排队执行
RequestRebindPivot();
}
#endregion
#region 线 AddDataColumns()
private void AddDataColumns()
{
foreach (GridColumn gridColumn in gcMain.GridView.Columns)
var gv = gcMain.GridView;
gv.BeginUpdate();
try
{
gridColumn.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left;
}
int dayCount = 0;
BaseUserControl baseUserControl = ControlObj.FindControl("bom_rdm_tianshu");
if (baseUserControl != null)
{
int.TryParse(baseUserControl.EditText, out dayCount);
}
if (dayCount <= 0)
{
dayCount = 7;
}
if (DateColumnList.Count != dayCount)
{
foreach (GridColumn item in DateColumnList)
// 首次运行:记录“当下已有的列”为基线静态列(只固定这些列)
if (_baselineFixedFields == null)
{
gcMain.GridView.Columns.Remove(item);
_baselineFixedFields = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (DevExpress.XtraGrid.Columns.GridColumn c in gv.Columns)
{
if (!string.IsNullOrEmpty(c.FieldName))
_baselineFixedFields.Add(c.FieldName);
}
}
gcMain.GridView.Columns.Remove(SumGridColumn);
DateColumnList.Clear();
for (int i = 0; i < dayCount; i++)
// 先统一恢复:基线列固定到左侧,其他全部取消固定(含日期列/合计列)
foreach (DevExpress.XtraGrid.Columns.GridColumn c in gv.Columns)
{
GridColumn gridColumn = new GridColumn();
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 = true;
gridColumn.SummaryItem.SummaryType = SummaryItemType.Sum;
gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}";
gcMain.GridView.Columns.Add(gridColumn);
DateColumnList.Add(gridColumn);
if (!string.IsNullOrEmpty(c.FieldName) && _baselineFixedFields.Contains(c.FieldName))
c.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left; // 静态列固定
else
c.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.None; // 动态列不固定
}
GridColumn sumGridColumn = new GridColumn();
sumGridColumn.AppearanceCell.Options.UseTextOptions = true;
sumGridColumn.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center;
sumGridColumn.AppearanceHeader.Options.UseTextOptions = true;
sumGridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center;
sumGridColumn.OptionsColumn.AllowEdit = false;
sumGridColumn.OptionsColumn.AllowMove = false;
sumGridColumn.OptionsColumn.AllowSize = false;
sumGridColumn.OptionsFilter.AllowFilter = false;
sumGridColumn.OptionsColumn.AllowMerge = DefaultBoolean.False;
sumGridColumn.OptionsColumn.AllowSort = DefaultBoolean.False;
sumGridColumn.FieldName = $"workingsum";
sumGridColumn.Caption = $"工时合计";
sumGridColumn.Width = 70;
sumGridColumn.DisplayFormat.FormatType = FormatType.Numeric;
sumGridColumn.DisplayFormat.FormatString = "{0:#,##0.####}";
sumGridColumn.Visible = true;
sumGridColumn.SummaryItem.SummaryType = SummaryItemType.Sum;
sumGridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}";
SumGridColumn = sumGridColumn;
gcMain.GridView.Columns.Add(sumGridColumn);
// 读取天数
int dayCount = 0;
BaseUserControl baseUserControl = ControlObj.FindControl("bom_rdm_tianshu");
if (baseUserControl != null) int.TryParse(baseUserControl.EditText, out dayCount);
if (dayCount <= 0) dayCount = 7;
// 当天数变化:移除旧日期列与旧合计列,重建
if (DateColumnList.Count != dayCount)
{
// 删除旧日期列
foreach (var item in DateColumnList)
{
if (item != null && gv.Columns.Contains(item))
gv.Columns.Remove(item);
}
DateColumnList.Clear();
// 删除旧合计列
if (SumGridColumn != null && gv.Columns.Contains(SumGridColumn))
gv.Columns.Remove(SumGridColumn);
SumGridColumn = null;
// 新建日期列(默认不固定)
for (int i = 0; i < dayCount; i++)
{
var col = new DevExpress.XtraGrid.Columns.GridColumn();
col.AppearanceCell.Options.UseTextOptions = true;
col.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
col.AppearanceHeader.Options.UseTextOptions = true;
col.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
col.OptionsColumn.AllowMove = false;
col.OptionsColumn.AllowSize = true;
col.OptionsFilter.AllowFilter = false;
col.OptionsColumn.AllowMerge = DevExpress.Utils.DefaultBoolean.False;
col.OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.False;
col.FieldName = $"DDay_{i}"; // 先占位;稍后 UpdateDynamicColumns 改成 yyyy-MM-dd
col.Width = 70;
col.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
col.DisplayFormat.FormatString = "{0:#,##0.####}";
col.Visible = true;
col.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
col.SummaryItem.DisplayFormat = "{0:#,##0.####}";
col.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.None; // 关键:不固定
gv.Columns.Add(col);
DateColumnList.Add(col);
}
// 合计列(也不固定)
var sum = new DevExpress.XtraGrid.Columns.GridColumn();
sum.AppearanceCell.Options.UseTextOptions = true;
sum.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
sum.AppearanceHeader.Options.UseTextOptions = true;
sum.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
sum.OptionsColumn.AllowEdit = false;
sum.OptionsColumn.AllowMove = false;
sum.OptionsColumn.AllowSize = true;
sum.OptionsFilter.AllowFilter = false;
sum.OptionsColumn.AllowMerge = DevExpress.Utils.DefaultBoolean.False;
sum.OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.False;
sum.FieldName = "workingsum";
sum.Caption = "工时合计";
sum.Width = 70;
sum.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
sum.DisplayFormat.FormatString = "{0:#,##0.####}";
sum.Visible = true;
sum.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
sum.SummaryItem.DisplayFormat = "{0:#,##0.####}";
sum.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.None; // 关键:不固定
SumGridColumn = sum;
gv.Columns.Add(sum);
}
// 横向滚动策略:固定为非自适应宽度 + 始终显示水平滚动条,减少布局震荡
var gridView = gv as DevExpress.XtraGrid.Views.Grid.GridView;
if (gridView != null)
{
gridView.OptionsView.ColumnAutoWidth = false;
gridView.HorzScrollVisibility = DevExpress.XtraGrid.Views.Base.ScrollVisibility.Always;
}
}
finally
{
gv.EndUpdate();
}
}
#endregion
/// <summary>
/// 根据日期修改列状态
/// </summary>
/// <param name="currentDate"></param>
#region UpdateDynamicColumns()
private void UpdateDynamicColumns()
{
DateTime currentDate = DateTime.Now;
BaseUserControl dateUserControl = ControlObj.FindControl("bom_rdm_ksdt");
if (dateUserControl is LabelDateEdit labelDateEdit)
{
currentDate = labelDateEdit.TextEdit.DateTime;
}
int dayCount = 0;
BaseUserControl baseUserControl = ControlObj.FindControl("bom_rdm_tianshu");
if (baseUserControl != null)
{
int.TryParse(baseUserControl.EditText, out dayCount);
}
if (dayCount <= 0)
{
dayCount = 7;
}
if (baseUserControl != null) int.TryParse(baseUserControl.EditText, out dayCount);
if (dayCount <= 0) dayCount = 7;
DateTime endDate = currentDate.AddDays(dayCount);
gcMain.GridView.BeginUpdate();
var gv = gcMain.GridView;
gv.BeginUpdate();
try
{
for (int i = 0; i < DateColumnList.Count; i++)
{
GridColumn gridColumn = DateColumnList[i];
// 当前列对应的日期 = 起始日期加 i 天
DateTime dateForColumn = currentDate.AddDays(i);
var gridColumn = DateColumnList[i];
var dateForColumn = currentDate.AddDays(i);
if (dateForColumn <= endDate)
{
gridColumn.FieldName = dateForColumn.ToString("yyyy-MM-dd");
gridColumn.Caption = dateForColumn.ToString("MM-dd");
gridColumn.Visible = true;
gridColumn.Tag = dateForColumn;
gridColumn.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.None; // 保证不固定
}
else
{
gridColumn.Visible = false;
}
}
if (SumGridColumn != null) SumGridColumn.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.None;
}
finally
{
gcMain.GridView.EndUpdate();
gv.EndUpdate();
}
}
#endregion
/// <summary>
/// 新增汇总数据(日期修改后)
/// </summary>
#region UpdateSummaryData()
private void UpdateSummaryData(DataTable table = null)
{
DataTable dataTable = new DataTable();
if (table != null)
{
dataTable = table;
}
else
DataTable dataTable = table;
if (dataTable == null)
{
XtraTabPage tabPage = this.xtc_left_container.SelectedTabPage;
BillSourceUnionModel model = tabPage.Tag as BillSourceUnionModel;
if (model.GridControlObj != null)
BillSourceUnionModel model = tabPage?.Tag as BillSourceUnionModel;
if (model != null)
{
if (model.ModelObj.sourceDetailType.Equals("1"))
{
dataTable = model.TreeGridDetailControlObj.TreeListObj.DataSource as DataTable;
}
dataTable = model.TreeGridDetailControlObj?.TreeListObj?.DataSource as DataTable;
else
{
dataTable = model.GridDetailControlObj.GridControl.DataSource as DataTable;
}
dataTable = model.GridDetailControlObj?.GridControl?.DataSource as DataTable;
}
}
if (dataTable != null && dataTable.Columns.Contains("num"))
{
MultiLineSummary = true;
gcMain.GridView.OptionsView.ShowFooter = true;
DataRow[] dataRows = dataTable.Select("num='999'");
DataRow dataRow = dataRows != null && dataRows.Length > 0 ? dataRows[0] : null;
DataRow dataRow = (dataRows != null && dataRows.Length > 0) ? dataRows[0] : null;
gcMain.AddHeadquarters(dataRow);
}
else if (MultiLineSummary)
{
MultiLineSummary = false;
//清空新加的汇总列
// 清空新加的汇总列
gcMain.AddHeadquarters();
}
}
#endregion
#region OnGcMainDataSourceChanged
private void OnGcMainDataSourceChanged(object sender, EventArgs e)
{
var grid = this.gcMain?.GridControl;
var view = grid?.MainView as DevExpress.XtraGrid.Views.Base.ColumnView;
var src = grid?.DataSource as DataTable;
if (grid == null || view == null) return;
if (src == null) return; // DataSource == null 的那次变化不处理(避免抖动)
if (DateColumnList == null || DateColumnList.Count == 0) return;
var tag = DateColumnList[0].Tag as DateTime?;
if (tag == null) return;
DateTime dateTime = tag.Value;
// 去抖:合并短时间内多次触发
if (DateTime.UtcNow - _lastRebindAt < _rebindDebounce)
{
System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 1);
this.BeginInvoke((Action)(() => SafeRebindPivot(grid, view, src, dateTime)));
return;
}
System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 1);
this.BeginInvoke((Action)(() => SafeRebindPivot(grid, view, src, dateTime)));
}
#endregion
#region 使
private void RequestRebindPivot()
{
var grid = this.gcMain?.GridControl;
var view = grid?.MainView as DevExpress.XtraGrid.Views.Base.ColumnView;
var src = grid?.DataSource as DataTable;
if (grid == null || view == null || src == null) return;
if (DateColumnList == null || DateColumnList.Count == 0) return;
var tag = DateColumnList[0].Tag as DateTime?;
if (tag == null) return;
DateTime dateTime = tag.Value;
if (DateTime.UtcNow - _lastRebindAt < _rebindDebounce)
{
System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 1);
this.BeginInvoke((Action)(() => SafeRebindPivot(grid, view, src, dateTime)));
return;
}
System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 1);
this.BeginInvoke((Action)(() => SafeRebindPivot(grid, view, src, dateTime)));
}
#endregion
#region + + / SafeRebindPivot
private void SafeRebindPivot(DevExpress.XtraGrid.GridControl grid,
DevExpress.XtraGrid.Views.Base.ColumnView view,
DataTable currentSource,
DateTime dateTime)
{
if (System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 0) == 0) return;
if (_mainRebindBusy) return;
_mainRebindBusy = true;
_lastRebindAt = DateTime.UtcNow;
try
{
grid.DataSourceChanged -= OnGcMainDataSourceChanged;
grid.BeginUpdate();
view.BeginDataUpdate();
this.SuspendLayout();
var src = currentSource;
if (src == null || src.Rows.Count == 0)
{
// 没数据直接收尾;不要 DataSource = null
return;
}
string billNo = (this.lblOrderNo?.Text ?? string.Empty).Replace("'", "''");
// 查询 ①:排除“计划文件”
string sqlExcludePlan = "SELECT * FROM RD_worktimetab WHERE 1=1"
+ $" AND lblOrderNo = '{billNo}'"
+ $" AND showday >= '{dateTime:yyyy-MM-dd}'"
+ " AND billdocument_id NOT LIKE N'计划文件%'";
DataTable dataNoPlanFile = BaseImpl.GetDataTableResult(sqlExcludePlan) ?? new DataTable();
// 查询 ②:只包含“计划文件”
string sqlIncludePlan = "SELECT billdocument_id FROM RD_worktimetab WHERE 1=1"
+ $" AND lblOrderNo = '{billNo}'"
+ $" AND showday >= '{dateTime:yyyy-MM-dd}'"
+ " AND billdocument_id LIKE N'计划文件%'";
DataTable dataOnlyPlanFile = BaseImpl.GetDataTableResult(sqlIncludePlan) ?? new DataTable();
// 复制成新表再加工(不要在当前绑定表上原地改)
DataTable result = src.Copy();
MergeMainDataWithDayPlan(result, dataNoPlanFile, dateTime); // 你自有实现
// 绑定“新表”(严禁 DataSource=null 再赋值)
grid.DataSource = result;
grid.ForceInitialize();
// 稳定水平滚动条(不自适应宽度,始终显示)
var gv = view as DevExpress.XtraGrid.Views.Grid.GridView;
if (gv != null)
{
gv.OptionsView.ColumnAutoWidth = false;
gv.HorzScrollVisibility = DevExpress.XtraGrid.Views.Base.ScrollVisibility.Always;
}
// 渲染“计划合计”(绑定之后)
if (dataOnlyPlanFile.Rows.Count > 0)
{
string jhrowtiemjson = (dataOnlyPlanFile.Rows[0]["billdocument_id"] + "").Replace("计划文件", "");
try
{
var rowObject = Newtonsoft.Json.Linq.JObject.Parse(jhrowtiemjson);
var arr = new Newtonsoft.Json.Linq.JArray(rowObject);
DataRow jhrowitem = Newtonsoft.Json.JsonConvert
.DeserializeObject<DataTable>(arr.ToString()).Rows[0];
gcMain.AddHeadquarters(jhrowitem);
}
catch { /* JSON 容错 */ }
}
// 如需无计划时清空:gcMain.AddHeadquarters(null);
gcMain.RefreshHeaderColor();
// 强制重建滚动信息 + 刷新 + 回到顶部
grid.ForceInitialize();
view.RefreshData();
if (gv != null) gv.TopRowIndex = 0;
}
finally
{
try { this.ResumeLayout(false); } catch { }
try { view.EndDataUpdate(); } catch { }
try { grid.EndUpdate(); } catch { }
try { grid.DataSourceChanged += OnGcMainDataSourceChanged; } catch { }
_mainRebindBusy = false;
// 若执行期间有新请求,合并再跑一次
if (System.Threading.Interlocked.Exchange(ref _mainRebindScheduled, 0) == 1)
{
this.BeginInvoke((Action)(() =>
{
var g = this.gcMain?.GridControl;
var v = g?.MainView as DevExpress.XtraGrid.Views.Base.ColumnView;
var s = g?.DataSource as DataTable;
if (g != null && v != null && s != null)
{
// 取当前起始日期
if (DateColumnList != null && DateColumnList.Count > 0)
{
var t = DateColumnList[0].Tag as DateTime?;
if (t != null) SafeRebindPivot(g, v, s, t.Value);
}
}
}));
}
}
}
#endregion
/// <summary>
@@ -3499,24 +3725,7 @@ namespace Lskj.PubBill
}
}
}
/// <summary>
/// <para>说明:刷新表格列(时间)</para>
/// <para>创建人:王一帆</para>
/// <para>创建日期:2018-08-16 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDataFileRefrshFile(object sender, EventArgs e)
{
AddDataColumns();
UpdateDynamicColumns();
UpdateSummaryData();
OnGcMainDataSourceChanged(gcMain.GridView, null);//手动刷新日期合计数据源
}
/// <summary>
/// <para>说明:刷新单据来源明细</para>
/// <para>创建人:龚宇超</para>
@@ -5841,68 +6050,8 @@ namespace Lskj.PubBill
SetDetailGridDataSource();
}
}
/// <summary>
/// 主表数据源改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnGcMainDataSourceChanged(object sender, EventArgs e)
{
if (DateColumnList.Count > 0 && DateColumnList[0].Tag is DateTime dateTime)
{
string billNo = this.lblOrderNo.Text;
this.gcMain.GridControl.DataSourceChanged -= OnGcMainDataSourceChanged;
DataTable dataTable = gcMain.GridControl.DataSource as DataTable;
if (dataTable != null)
{
//DataTable dataMain = dataTable.Copy();
//string sqlValue = "select * from RD_worktimetab where 1 = 1";
//sqlValue = $"{sqlValue} and lblOrderNo = '{billNo}' and showday >= '{dateTime.ToString("yyyy-MM-dd")}'";
//DataTable dataDayPlan = BaseImpl.GetDataTableResult(sqlValue);
//---------- 查询①:渲染表格排程” ----------
string sqlExcludePlan = "SELECT * FROM RD_worktimetab WHERE 1 = 1";
sqlExcludePlan += $" AND lblOrderNo = '{billNo}'";
sqlExcludePlan += $" AND showday >= '{dateTime:yyyy-MM-dd}'";
sqlExcludePlan += " AND billdocument_id NOT LIKE N'计划文件%'";
// 获取结果
DataTable dataNoPlanFile = BaseImpl.GetDataTableResult(sqlExcludePlan);
// ---------- 查询②:只包含“计划文件” ----------
string sqlIncludePlan = "SELECT billdocument_id FROM RD_worktimetab WHERE 1 = 1";
sqlIncludePlan += $" AND lblOrderNo = '{billNo}'";
sqlIncludePlan += $" AND showday >= '{dateTime:yyyy-MM-dd}'";
sqlIncludePlan += " AND billdocument_id LIKE N'计划文件%'";
// 获取结果
DataTable dataOnlyPlanFile = BaseImpl.GetDataTableResult(sqlIncludePlan);
MergeMainDataWithDayPlan(dataTable, dataNoPlanFile, dateTime);
//若存在缓存计划数据则渲染合计
if (dataOnlyPlanFile.Rows.Count > 0)
{
string jhrowtiemjson = (dataOnlyPlanFile.Rows[0]["billdocument_id"] + "").Replace("计划文件", "");
try
{
JObject rowObject = JsonConvert.DeserializeObject<JObject>(jhrowtiemjson);
JArray jArray = new JArray();
jArray.Add(rowObject);
DataRow jhrowitem = JsonConvert.DeserializeObject<DataTable>(JsonConvert.SerializeObject(jArray)).Rows[0];
//渲染计划合计
gcMain.AddHeadquarters(jhrowitem);
}
catch (Exception)
{
}
}
//else
//{
// gcMain.AddHeadquarters(null);
//}
gcMain.RefreshHeaderColor();
this.gcMain.GridControl.DataSource = null;
this.gcMain.GridControl.DataSource = dataTable;
}
this.gcMain.GridControl.DataSourceChanged += OnGcMainDataSourceChanged;
}
}
/// <summary>
/// 保存日计划变更数据(批量保存)。