CNCEC_SUBQHSE_WUHUAN/SGGL/FineUIPro.Web/JDGL/SGManPower/ManPowerWorkGrid.aspx.cs

741 lines
26 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 BLL;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace FineUIPro.Web.JDGL.SGManPower
{
public partial class ManPowerWorkGrid : PageBase
{
#region Page_Init
// 注意动态创建的代码需要放置于Page_Init不是Page_Load这样每次构造页面时都会执行
protected void Page_Init(object sender, EventArgs e)
{
InitGrid();
}
public DataTable GridTable = new DataTable();
private void InitGrid()
{
FineUIPro.BoundField bf;
FineUIPro.RenderField rf;
FineUIPro.TextBox txTextBox;
// 设置Grid的编辑属性
Grid1.AllowCellEditing = true;
Grid1.ClicksToEdit = 1;
Grid1.EnableAfterEditEvent = true;
UnitId = Request.Params["UnitId"];
StartTime = Request.Params["StartTime"];
EndTime = Request.Params["EndTime"];
GridTable.Columns.Add("Id");
// 添加隐藏列来存储额外的ID信息
GridTable.Columns.Add("UnitId");
GridTable.Columns.Add("WorkPostId");
ListItem[] list = new ListItem[4];
list[0] = new ListItem("序号", "SerialNumber");
list[1] = new ListItem("单位", "UnitName");
list[2] = new ListItem("岗位", "WorkPostName");
list[3] = new ListItem("累计", "TotalCount");
foreach (var item in list)
{
bf = new FineUIPro.BoundField();
bf.ColumnID = item.Value;
bf.DataField = item.Value;
bf.HeaderText = item.Text;
bf.HeaderTextAlign = TextAlign.Center;
bf.TextAlign = TextAlign.Center;
bf.Locked = true;
Grid1.Columns.Add(bf);
GridTable.Columns.Add(item.Value);
}
// 动态获取日期范围
DateTime startDate = Convert.ToDateTime(StartTime);
DateTime endDate = Convert.ToDateTime(EndTime);
var dateRange = Enumerable.Range(0, (endDate - startDate).Days + 1)
.Select(i => startDate.AddDays(i))
.ToList();
// 按年分组日期
var groupedByYear = dateRange.GroupBy(d => d.Year)
.OrderBy(g => g.Key)
.ToList();
foreach (var yearGroup in groupedByYear)
{
GroupField yearGroupField = new GroupField();
yearGroupField.HeaderText = $"{yearGroup.Key}年";
yearGroupField.TextAlign = TextAlign.Center;
// 按月分组
var groupedByMonth = yearGroup.GroupBy(d => d.Month)
.OrderBy(g => g.Key)
.ToList();
foreach (var monthGroup in groupedByMonth)
{
GroupField monthGroupField = new GroupField();
monthGroupField.HeaderText = $"{monthGroup.Key}月";
monthGroupField.TextAlign = TextAlign.Center;
// 添加具体日期的列
foreach (var date in monthGroup.OrderBy(d => d))
{
bf = new FineUIPro.BoundField();
bf.ColumnID = date.ToString("yyyy-MM-dd");
bf.DataField = date.ToString("yyyy-MM-dd");
bf.HeaderText = date.ToString("dd");
bf.HeaderTextAlign = TextAlign.Center;
bf.TextAlign = TextAlign.Center;
monthGroupField.Columns.Add(bf);
GridTable.Columns.Add(date.ToString("yyyy-MM-dd"));
}
yearGroupField.Columns.Add(monthGroupField);
}
Grid1.Columns.Add(yearGroupField);
}
}
#endregion
public string UnitId
{
get => (string)ViewState["UnitId"];
set => ViewState["UnitId"] = value;
}
public string StartTime
{
get => (string)ViewState["StartTime"];
set => ViewState["StartTime"] = value;
}
public string EndTime
{
get => (string)ViewState["EndTime"];
set => ViewState["EndTime"] = value;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Funs.DropDownPageSize(this.ddlPageSize);
// 设置Grid的PageSize与下拉框默认值一致
Grid1.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
WorkPostService.InitWorkPostDropDownList(this.drpWorkPost, true); //岗位
// 绑定表格
this.BindGrid();
}
}
#region
/// <summary>
/// 绑定数据
/// </summary>
private void BindGrid()
{
// 清空现有数据
GridTable.Clear();
// 重新添加列定义(保持列结构)
if (GridTable.Columns.Count == 0)
{
GridTable.Columns.Add("Id");
GridTable.Columns.Add("UnitId");
GridTable.Columns.Add("WorkPostId");
// 添加动态日期列这部分已经在InitGrid中定义了
ListItem[] list = new ListItem[4];
list[0] = new ListItem("序号", "SerialNumber");
list[1] = new ListItem("单位", "UnitName");
list[2] = new ListItem("岗位", "WorkPostName");
list[3] = new ListItem("累计", "TotalCount");
foreach (var item in list)
{
GridTable.Columns.Add(item.Value);
}
// 日期列会在InitGrid中添加这里不需要重复添加
}
else
{
// 清空行数据但保持列结构
GridTable.Rows.Clear();
}
// 使用原生SQL查询来提高性能直接在数据库层面进行分组统计
string strSql = @"
SELECT UnitId, PostId, RecordDate, COUNT(1) as RecordCount
FROM T_d_EmployInOutRecord
WHERE ProjectId = @ProjectId
AND RecordDate >= @StartDate
AND RecordDate <= @EndDate";
var parameters = new List<System.Data.SqlClient.SqlParameter>
{
new System.Data.SqlClient.SqlParameter("@ProjectId", this.CurrUser.LoginProjectId),
new System.Data.SqlClient.SqlParameter("@StartDate", Convert.ToDateTime(StartTime)),
new System.Data.SqlClient.SqlParameter("@EndDate", Convert.ToDateTime(EndTime))
};
if (UnitId != Const._Null)
{
strSql += " AND UnitId = @UnitId";
parameters.Add(new System.Data.SqlClient.SqlParameter("@UnitId", UnitId));
}
if (drpWorkPost.SelectedValue != Const._Null)
{
strSql += " AND PostId = @PostId";
parameters.Add(new System.Data.SqlClient.SqlParameter("@PostId", drpWorkPost.SelectedValue));
}
strSql += " GROUP BY UnitId, PostId, RecordDate";
// 执行查询获取分组数据
var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray());
// 将数据转换为更易处理的格式
var groupedData = new List<dynamic>();
var groupedDict = new Dictionary<string, dynamic>();
foreach (System.Data.DataRow row in dt.Rows)
{
string key = $"{row["UnitId"]}_{row["PostId"]}";
DateTime recordDate = Convert.ToDateTime(row["RecordDate"]);
int count = Convert.ToInt32(row["RecordCount"]);
if (!groupedDict.ContainsKey(key))
{
dynamic group = new System.Dynamic.ExpandoObject();
group.UnitId = row["UnitId"];
group.PostId = row["PostId"];
group.DailyCounts = new Dictionary<DateTime, int>();
group.TotalCount = 0;
groupedDict[key] = group;
groupedData.Add(group);
}
groupedDict[key].DailyCounts[recordDate] = count;
groupedDict[key].TotalCount += count;
}
Grid1.RecordCount = groupedData.Count();
// 分页处理
var pagedData = groupedData.Skip(Grid1.PageSize * Grid1.PageIndex).Take(Grid1.PageSize).ToList();
// 只获取当前页需要的单位和岗位信息,避免加载全部数据
var unitIds = pagedData.Where(x => x.UnitId != null).Select(x => x.UnitId.ToString()).Distinct().ToList();
var postIds = pagedData.Where(x => x.PostId != null).Select(x => x.PostId.ToString()).Distinct().ToList();
var units = new Dictionary<string, string>();
var workPosts = new Dictionary<string, string>();
if (unitIds.Any())
{
var unitQuery = from u in Funs.DB.Base_Unit
where unitIds.Contains(u.UnitId)
select new { u.UnitId, u.UnitName };
foreach (var u in unitQuery)
{
units[u.UnitId] = u.UnitName;
}
}
if (postIds.Any())
{
var postQuery = from p in Funs.DB.Base_WorkPost
where postIds.Contains(p.WorkPostId)
select new { p.WorkPostId, p.WorkPostName };
foreach (var p in postQuery)
{
workPosts[p.WorkPostId] = p.WorkPostName;
}
}
foreach (var group in pagedData)
{
DataRow row = GridTable.NewRow();
// 基本信息
row["Id"] = Guid.NewGuid().ToString(); // 生成唯一ID用于行标识
row["SerialNumber"] = GridTable.Rows.Count + 1; // 序号
// 单位信息
string unitName = "";
if (group.UnitId != null && units.ContainsKey(group.UnitId.ToString()))
{
unitName = units[group.UnitId.ToString()];
}
row["UnitName"] = unitName;
row["UnitId"] = group.UnitId ?? (object)DBNull.Value;
// 岗位信息
string workPostName = "";
if (group.PostId != null && workPosts.ContainsKey(group.PostId.ToString()))
{
workPostName = workPosts[group.PostId.ToString()];
}
row["WorkPostName"] = workPostName;
row["WorkPostId"] = group.PostId ?? (object)DBNull.Value;
// 每日数量填充
foreach (var kvp in group.DailyCounts)
{
string dateColumnId = kvp.Key.ToString("yyyy-MM-dd");
// 确保列存在
if (GridTable.Columns.Contains(dateColumnId))
{
row[dateColumnId] = kvp.Value;
}
}
// 设置累计数量
row["TotalCount"] = group.TotalCount;
GridTable.Rows.Add(row);
}
Grid1.DataSource = GridTable;
Grid1.DataBind();
// 计算汇总数据
OutputSummaryData();
}
#region
/// <summary>
/// 计算合计
/// </summary>
private void OutputSummaryData()
{
// 创建用于存储合计值的对象
JObject summary = new JObject();
// 设置固定列的合计值
summary.Add("UnitName", "合计");
// 计算TotalCount列的合计值
int totalCountSum = 0;
foreach (DataRow row in GridTable.Rows)
{
if (row["TotalCount"] != DBNull.Value && row["TotalCount"] != null)
{
int value;
if (int.TryParse(row["TotalCount"].ToString(), out value))
{
totalCountSum += value;
}
}
}
summary.Add("TotalCount", totalCountSum.ToString());
// 计算日期列的合计值
foreach (DataColumn column in GridTable.Columns)
{
// 检查是否为日期列(格式为 yyyy-MM-dd
DateTime date;
if (DateTime.TryParseExact(column.ColumnName, "yyyy-MM-dd", null,
System.Globalization.DateTimeStyles.None, out date))
{
// 计算该列的合计值
int columnSum = 0;
foreach (DataRow row in GridTable.Rows)
{
if (row[column.ColumnName] != DBNull.Value && row[column.ColumnName] != null)
{
int value;
if (int.TryParse(row[column.ColumnName].ToString(), out value))
{
columnSum += value;
}
}
}
summary.Add(column.ColumnName, columnSum.ToString());
}
}
// 设置汇总数据
Grid1.SummaryData = summary;
}
#endregion
#endregion
#region GV
/// <summary>
/// 分页
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Grid1_PageIndexChange(object sender, GridPageEventArgs e)
{
this.Grid1.PageIndex = e.NewPageIndex;
this.BindGrid();
}
/// <summary>
/// 排序
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Grid1_Sort(object sender, GridSortEventArgs e)
{
this.Grid1.SortDirection = e.SortDirection;
this.Grid1.SortField = e.SortField;
this.BindGrid();
}
/// <summary>
/// 分页显示条数下拉框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e)
{
Grid1.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
this.BindGrid();
}
#endregion
#region
/// <summary>
/// 查询
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
protected void btnQuery_OnClick(object sender, EventArgs e)
{
BindGrid();
}
/// <summary>
/// 统计图表
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
protected void btnGetChart_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(UnitId) && !string.IsNullOrEmpty(StartTime) && !string.IsNullOrEmpty(EndTime))
{
// 构建基础URL参数
string urlParams = string.Format("UnitId={0}&StartTime={1}&EndTime={2}", UnitId, StartTime, EndTime);
// 添加岗位参数(如果已选择)
if (drpWorkPost.SelectedValue != Const._Null && !string.IsNullOrEmpty(drpWorkPost.SelectedValue))
{
urlParams += "&WorkPostId=" + drpWorkPost.SelectedValue;
}
PageContext.RegisterStartupScript(
Window2.GetShowReference(string.Format("ManPowerWorkChart.aspx?{0}", urlParams), "人力计划图表"));
}
else
{
ShowNotify("请先选确保时间范围已设置", MessageBoxIcon.Warning);
}
}
#endregion
#region
/// <summary>
/// 关闭弹出窗
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Window1_Close(object sender, WindowCloseEventArgs e)
{
BindGrid();
}
#endregion
#region
/// 导出按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnOut_Click(object sender, EventArgs e)
{
Response.ClearContent();
string filename = Funs.GetNewFileName();
Response.AddHeader("content-disposition",
"attachment; filename=" +
System.Web.HttpUtility.UrlEncode("现场考勤人力表" + filename, System.Text.Encoding.UTF8) + ".xls");
Response.ContentType = "application/excel";
Response.ContentEncoding = System.Text.Encoding.UTF8;
this.BindGrid();
// 生成并写入Excel表格
Response.Write(GetGridTableHtml(Grid1));
Response.End();
}
/// <summary>
/// 导出方法 - 支持多级表头
/// </summary>
/// <param name="grid"></param>
/// <returns></returns>
/// <summary>
private string GetGridTableHtml(Grid grid)
{
StringBuilder sb = new StringBuilder();
MultiHeaderTable mht = new MultiHeaderTable();
mht.ResolveMultiHeaderTable(grid.Columns);
sb.Append("<meta http-equiv=\"Content-Type\" content=\"application/vnd.ms-excel;charset=utf-8\"/>");
sb.Append("<table cellspacing=\"0\" rules=\"all\" border=\"1\" style=\"border-collapse:collapse;\">");
// 生成多级表头
foreach (List<object[]> rows in mht.MultiTable)
{
sb.Append("<tr>");
foreach (object[] cell in rows)
{
int rowspan = 1;
int colspan = Convert.ToInt32(cell[1]);
GridColumn column = cell[2] as GridColumn;
// 对于锁定列固定列确保rowspan为3
if (column.Locked)
{
rowspan = 3;
}
sb.AppendFormat("<th{0}{1}{2}>{3}</th>",
" rowspan=\"" + rowspan + "\"",
colspan != 1 ? " colspan=\"" + colspan + "\"" : "",
colspan != 1 ? " style=\"text-align:center;\"" : "",
column.HeaderText);
}
sb.Append("</tr>");
}
// 生成数据行
foreach (GridRow row in grid.Rows)
{
sb.Append("<tr>");
foreach (GridColumn column in mht.Columns)
{
string html = row.Values[column.ColumnIndex].ToString();
// 特殊处理固定列
if (column.ColumnID == "UnitName")
{
html = row.Values[column.ColumnIndex].ToString();
}
else if (column.ColumnID == "WorkPostName")
{
html = row.Values[column.ColumnIndex].ToString();
}
else if (column.ColumnID == "TotalCount")
{
html = row.Values[column.ColumnIndex].ToString();
}
// 处理日期列(格式为 yyyy-MM-dd
else if (DateTime.TryParseExact(column.ColumnID, "yyyy-MM-dd", null,
System.Globalization.DateTimeStyles.None, out _))
{
html = row.Values[column.ColumnIndex].ToString();
}
sb.AppendFormat("<td>{0}</td>", html);
}
sb.Append("</tr>");
}
// 添加合计行
if (grid.SummaryData != null)
{
sb.Append("<tr style=\"font-weight:bold;\">");
foreach (GridColumn column in mht.Columns)
{
string summaryValue = "";
// 检查SummaryData中是否有该列的合计值
if (grid.SummaryData.Properties().Any(p => p.Name == column.ColumnID))
{
var property = grid.SummaryData.Properties().FirstOrDefault(p => p.Name == column.ColumnID);
if (property != null)
{
summaryValue = property.Value.ToString();
}
}
else if (column.ColumnID == "UnitName")
{
summaryValue = "合计";
}
sb.AppendFormat("<td>{0}</td>", summaryValue);
}
sb.Append("</tr>");
}
sb.Append("</table>");
return sb.ToString();
}
#region
/// <summary>
/// 处理多表头的类
/// </summary>
public class MultiHeaderTable
{
// 包含 rowspancolspan 的多表头,方便生成 HTML 的 table 标签
public List<List<object[]>> MultiTable = new List<List<object[]>>();
// 最终渲染的列数组
public List<GridColumn> Columns = new List<GridColumn>();
public void ResolveMultiHeaderTable(GridColumnCollection columns)
{
List<object[]> row = new List<object[]>();
foreach (GridColumn column in columns)
{
object[] cell = new object[4];
cell[0] = 1; // rowspan
cell[1] = 1; // colspan
cell[2] = column;
cell[3] = null;
row.Add(cell);
}
ResolveMultiTable(row, 0);
ResolveColumns(row);
}
private void ResolveColumns(List<object[]> row)
{
foreach (object[] cell in row)
{
GroupField groupField = cell[2] as GroupField;
if (groupField != null && groupField.Columns.Count > 0)
{
List<object[]> subrow = new List<object[]>();
foreach (GridColumn column in groupField.Columns)
{
subrow.Add(new object[]
{
1,
1,
column,
groupField
});
}
ResolveColumns(subrow);
}
else
{
Columns.Add(cell[2] as GridColumn);
}
}
}
private void ResolveMultiTable(List<object[]> row, int level)
{
List<object[]> nextrow = new List<object[]>();
foreach (object[] cell in row)
{
GroupField groupField = cell[2] as GroupField;
if (groupField != null && groupField.Columns.Count > 0)
{
// 如果当前列包含子列,则更改当前列的 colspan以及增加父列向上递归的colspan
cell[1] = Convert.ToInt32(groupField.Columns.Count);
PlusColspan(level - 1, cell[3] as GridColumn, groupField.Columns.Count - 1);
foreach (GridColumn column in groupField.Columns)
{
nextrow.Add(new object[]
{
1,
1,
column,
groupField
});
}
}
else
{
// 如果当前列不包含子列但不是最末级列不是叶子节点则增加rowspan
if (level > 0)
{
cell[0] = level + 1;
}
}
}
MultiTable.Add(row);
if (nextrow.Count > 0)
{
ResolveMultiTable(nextrow, level + 1);
}
}
private void PlusColspan(int level, GridColumn column, int colspan)
{
if (level < 0)
{
return;
}
foreach (List<object[]> rows in MultiTable)
{
foreach (object[] cells in rows)
{
if (cells[2] == column)
{
cells[1] = Convert.ToInt32(cells[1]) + colspan;
PlusColspan(level - 1, cells[3] as GridColumn, colspan);
break;
}
}
}
}
}
#endregion
#endregion
}
}