修复相关漏洞
This commit is contained in:
@@ -10,6 +10,7 @@ namespace SimpleAdmin.Application;
|
||||
/// </summary>
|
||||
public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
{
|
||||
private const string EmployeeExportTemplateFileName = "员工导出模版.xlsx";
|
||||
private readonly SqlSugarScope _db;
|
||||
private readonly IOnboardingDataPermissionService _dataPermission;
|
||||
|
||||
@@ -110,12 +111,17 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
using var package = new ExcelPackage();
|
||||
var templatePath = ResolveEmployeeExportTemplatePath();
|
||||
using var package = new ExcelPackage(new FileInfo(templatePath));
|
||||
package.Workbook.Properties.Title = "员工明细";
|
||||
package.Workbook.Properties.Subject = "员工基本、人事状态及主要合同信息";
|
||||
package.Workbook.Properties.Created = DateTime.Now;
|
||||
|
||||
WriteEmployeeSheet(package.Workbook.Worksheets.Add("员工明细"), employeeRows);
|
||||
var worksheet = package.Workbook.Worksheets.FirstOrDefault(item =>
|
||||
item.Dimension != null
|
||||
&& string.Equals(item.Cells[1, 1].Text.Trim(), "姓名", StringComparison.OrdinalIgnoreCase))
|
||||
?? throw Oops.Bah("员工导出模板未找到以“姓名”开头的表头行,请检查模板内容");
|
||||
WriteEmployeeSheet(worksheet, employeeRows);
|
||||
|
||||
return new OnboardingEmployeeExportFile
|
||||
{
|
||||
@@ -192,6 +198,11 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task UpdateHrInfo(OnboardingEmployeeHrUpdateInput input)
|
||||
{
|
||||
await OnboardingConcurrency.RunEmployee(_db, input.Id, () => UpdateHrInfoCore(input));
|
||||
}
|
||||
|
||||
private async Task UpdateHrInfoCore(OnboardingEmployeeHrUpdateInput input)
|
||||
{
|
||||
ValidateEmploymentType(input.EmploymentType);
|
||||
ValidateSocialInsuranceStatus(input.SocialInsuranceStatus);
|
||||
@@ -275,6 +286,11 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Regularize(OnboardingEmployeeRegularizeInput input)
|
||||
{
|
||||
await OnboardingConcurrency.RunEmployee(_db, input.Id, () => RegularizeCore(input));
|
||||
}
|
||||
|
||||
private async Task RegularizeCore(OnboardingEmployeeRegularizeInput input)
|
||||
{
|
||||
if (!input.RegularizationDate.HasValue)
|
||||
throw Oops.Bah("请选择转正日期");
|
||||
@@ -370,6 +386,11 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RevokeRegularization(OnboardingEmployeeRegularizationRevokeInput input)
|
||||
{
|
||||
await OnboardingConcurrency.RunEmployee(_db, input.Id, () => RevokeRegularizationCore(input));
|
||||
}
|
||||
|
||||
private async Task RevokeRegularizationCore(OnboardingEmployeeRegularizationRevokeInput input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input.Remark))
|
||||
throw Oops.Bah("请填写撤销原因");
|
||||
@@ -775,7 +796,100 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
||||
TextColumn("工资卡开户行", row => row.Employee.BankName, 22)
|
||||
};
|
||||
|
||||
WriteWorksheet(worksheet, columns, rows);
|
||||
WriteEmployeeTemplateWorksheet(worksheet, columns, rows);
|
||||
}
|
||||
|
||||
private static void WriteEmployeeTemplateWorksheet(
|
||||
ExcelWorksheet worksheet,
|
||||
IReadOnlyList<ExportColumn<EmployeeExportContext>> columns,
|
||||
IReadOnlyList<EmployeeExportContext> rows)
|
||||
{
|
||||
var templateColumnCount = worksheet.Dimension?.End.Column ?? 0;
|
||||
if (templateColumnCount == 0)
|
||||
throw Oops.Bah("员工导出模板没有配置表头");
|
||||
|
||||
var columnsByHeader = columns.ToDictionary(
|
||||
item => item.Header,
|
||||
item => item,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
var headerAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["户口所在地"] = "户籍所在地"
|
||||
};
|
||||
var templateColumns = new List<(int Index, ExportColumn<EmployeeExportContext> Column)>();
|
||||
var mappedHeaders = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
for (var columnIndex = 1; columnIndex <= templateColumnCount; columnIndex++)
|
||||
{
|
||||
var templateHeader = worksheet.Cells[1, columnIndex].Text?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(templateHeader))
|
||||
throw Oops.Bah($"员工导出模板第 {columnIndex} 列表头为空,请补充后重新导出");
|
||||
|
||||
var exportHeader = headerAliases.GetValueOrDefault(templateHeader, templateHeader);
|
||||
if (!columnsByHeader.TryGetValue(exportHeader, out var exportColumn))
|
||||
throw Oops.Bah($"员工导出模板包含无法识别的表头“{templateHeader}”,请检查模板");
|
||||
if (!mappedHeaders.Add(exportHeader))
|
||||
throw Oops.Bah($"员工导出模板表头“{templateHeader}”重复,请检查模板");
|
||||
|
||||
templateColumns.Add((columnIndex, exportColumn));
|
||||
}
|
||||
|
||||
var missingHeaders = columns
|
||||
.Where(item => !mappedHeaders.Contains(item.Header))
|
||||
.Select(item => item.Header)
|
||||
.ToList();
|
||||
if (missingHeaders.Count > 0)
|
||||
throw Oops.Bah($"员工导出模板缺少表头:{string.Join("、", missingHeaders)}");
|
||||
|
||||
var existingLastRow = worksheet.Dimension?.End.Row ?? 1;
|
||||
for (var rowIndex = 2; rowIndex <= existingLastRow; rowIndex++)
|
||||
{
|
||||
for (var columnIndex = 1; columnIndex <= templateColumnCount; columnIndex++)
|
||||
worksheet.Cells[rowIndex, columnIndex].Value = null;
|
||||
}
|
||||
|
||||
for (var rowIndex = 0; rowIndex < rows.Count; rowIndex++)
|
||||
{
|
||||
var excelRow = rowIndex + 2;
|
||||
foreach (var templateColumn in templateColumns)
|
||||
{
|
||||
var cell = worksheet.Cells[excelRow, templateColumn.Index];
|
||||
var value = templateColumn.Column.Value(rows[rowIndex]);
|
||||
if (value != null)
|
||||
cell.Value = value;
|
||||
|
||||
var templateNumberFormat = worksheet.Cells[1, templateColumn.Index]
|
||||
.Style.Numberformat.Format;
|
||||
cell.Style.Numberformat.Format = string.IsNullOrWhiteSpace(templateNumberFormat)
|
||||
|| string.Equals(
|
||||
templateNumberFormat,
|
||||
"General",
|
||||
StringComparison.OrdinalIgnoreCase)
|
||||
? templateColumn.Column.NumberFormat
|
||||
: templateNumberFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResolveEmployeeExportTemplatePath()
|
||||
{
|
||||
var currentDirectory = Directory.GetCurrentDirectory();
|
||||
var candidates = new[]
|
||||
{
|
||||
Path.Combine(AppContext.BaseDirectory, "Upload", EmployeeExportTemplateFileName),
|
||||
Path.Combine(currentDirectory, "Upload", EmployeeExportTemplateFileName),
|
||||
Path.Combine(currentDirectory, "SimpleAdmin.Web.Core", "Upload", EmployeeExportTemplateFileName),
|
||||
Path.GetFullPath(Path.Combine(
|
||||
currentDirectory,
|
||||
"..",
|
||||
"SimpleAdmin.Web.Core",
|
||||
"Upload",
|
||||
EmployeeExportTemplateFileName))
|
||||
};
|
||||
|
||||
var templatePath = candidates.FirstOrDefault(File.Exists);
|
||||
return templatePath
|
||||
?? throw Oops.Bah("员工导出模板文件不存在,请检查部署目录中的 Upload/员工导出模版.xlsx");
|
||||
}
|
||||
|
||||
private static void WriteContractSheet(
|
||||
|
||||
Reference in New Issue
Block a user